%{ #include #include /* * (C) 2005 David A. Wheeler * Version 0.11.1 * Released under the GNU GPL (version 2 or greater) and AFL (1.1 or greater). * Implements an IDL as close to CORBA as plausible for D-BUS. * * specification = definition+ * definition = interface_spec * interface_spec = [ "deprecated" ] "interface" IDENTIFIER "{" * ( op_dcl | attr_dcl | signal_dcl )* "}" ";" * attr_dcl = [ "read" | "write" ] ( "property" | "attribute" ) * param_type_spec IDENTIFIER ( "," IDENTIFIER )* ";" * op_dcl: [ "oneway" ] op_type_spec IDENTIFIER '(' parameter_list ')' ";" * parameter_list = [ param_dcl ( "," param_dcl )* ] * param_dcl = [ "in" | "out" | "inout" ] param_type_spec IDENTIFIER * signal_dcl = "signal" IDENTIFIER "(" out_parameter_list ")" ";" * out_parameter_list = [ out_param_dcl ( "," out_parameter_dcl )* ] * out_param_dcl: param_type_spec IDENTIFIER * param_type_spec: IDENTIFIER // INT32, STRING, etc. * | ARRAY OF param_type_spec * * NOTE: "oneway" is an addition; it sets oneway="yes" in the method. * * This uses the low-level "glib" library to make development easier - * it's a portable library for linked lists, string handling, etc. * This does NOT depend on GTK+ or GNOME or KDE or any GUI like that. * * TODO: Better support of types. * It'd be easy to add support for structures, say * as "(" list ")", and separate type definitions would make sense too. */ #include #include void process(char *s); void yyerror(char *s); void pindent(void); void pproperties (gpointer data, gpointer user_data); void free_string_list(GList *list_to_dealloc); extern int linenum; int indent = 0; int yydebug=1; const char xmlheader[] = "\n"; %} %union { char *str; char *str_nofree; /* Do not free() this string. */ GList *list_str; /* list of strings */ } /* Free: */ %token IDENTIFIER /* Do not free: */ %token IN OUT INOUT %token INTERFACE %token ONEWAY DEPRECATED %token ARRAY OF /* VOID itself doesn't produce something that needs freeing */ %token VOID %token READONLY WRITEONLY ATTRIBUTE %token SIGNAL /* Free these (typically because they pass up IDENTIFIERs): */ %type param_type_spec op_type_spec /* Don't free these; these just pass up ptrs to constants */ %type readwrite param_attribute is_deprecated op_attribute %type attr_list %start specification %% param_type_spec: IDENTIFIER { $$ = $1; /* The default action. NOT VOID. */ } | ARRAY OF param_type_spec { /* returns an array of the parameter. */ $$ = g_strconcat("array[", $3, "]", NULL); g_free($3); } ; param_attribute: /* empty = IN */ { $$ = "i"; } | IN { $$ = "i"; } | OUT { $$ = "o"; } | INOUT { $$ = "b"; /* both in and out */ } ; param_dcl: param_attribute param_type_spec IDENTIFIER { /* FIXME: identifier is too broad */ if (*($1) != 'o') { pindent(); printf("\n", $3, $2); } if (*($1) != 'i') { pindent(); printf("\n", $3, $2); } free($2); free($3); } ; parameter_list_nonempty: param_dcl | parameter_list_nonempty ',' param_dcl ; parameter_list: /* empty */ | parameter_list_nonempty ; op_attribute: /* empty */ { $$ = ""; } | ONEWAY { $$ = " oneway=\"yes\""; } ; op_type_spec: param_type_spec { $$ = $1; } | VOID { $$ = g_strdup("void"); } ; op_dcl: op_attribute op_type_spec IDENTIFIER '(' { pindent(); printf("\n", $3, $1); indent++; if (strcmp($2,"void")) { /* FIXME: complain if oneway. */ /* "return" is usually a keyword, */ /* so this is unlikely to clash */ /* with any other param name. */ pindent(); printf("\n", $2); } } parameter_list ')' /* raises_context_expr */ { indent--; pindent(); printf("\n"); free($2); free($3); } ; attr_list: IDENTIFIER { $$ = g_list_append( (GList *) NULL, $1); } | attr_list "," IDENTIFIER { $$ = g_list_append( $1, $3); } ; readwrite: /* empty */ { $$ = "readwrite"; } | READONLY { $$ = "read"; } | WRITEONLY { $$ = "write"; /* CORBA lacks "writeonly". */} ; attr_dcl: readwrite ATTRIBUTE param_type_spec attr_list /* attr_raises_expr */ { GList *attribute_info; attribute_info = g_list_append(NULL, $1); attribute_info = g_list_append(attribute_info, $3); g_list_foreach($4, pproperties, attribute_info); free_string_list($4); g_list_free(attribute_info); /* frees g_list_last(attribute_info): */ free($3); } ; out_param_dcl: param_type_spec IDENTIFIER { /* FIXME: identifier is too broad */ pindent(); printf("\n", $2, $1); free($1); free($2); } ; out_parameter_list_nonempty: out_param_dcl | out_parameter_list_nonempty ',' out_param_dcl ; out_parameter_list: /* empty */ | out_parameter_list_nonempty ; signal_dcl: SIGNAL IDENTIFIER '(' { pindent(); printf("\n", $2); indent++; } out_parameter_list ')' /* raises_context_expr */ { indent--; pindent(); printf("\n"); free($2); } ; export: op_dcl ';' | attr_dcl ';' | signal_dcl ';' ; exports: /* empty */ | exports export ; interface_body: exports ; is_deprecated: /* empty */ {$$ = "";} | DEPRECATED {$$ = " deprecated=\"yes\"";} ; interface_spec: is_deprecated INTERFACE IDENTIFIER '{' { pindent(); printf("\n", $3, $1); indent++; free($3); } interface_body '}' { indent--; pindent(); printf("\n"); } ';' ; definition: interface_spec /* | type_dcl | except_dcl | event */ ; definitions: /* empty */ | definitions definition ; specification: { printf(xmlheader); } definitions ; %% void process(char *s) { fprintf(stdout, "%s\n", s); } void free_string_list(GList *list_to_dealloc) { /* FIXME: Deallocate. */ } void yyerror(char *s) { fprintf(stdout, "-:%d: %s\n", linenum, s); exit(1); } int main(void) { yyparse(); return 0; } void pindent(void) { /* print an indent, using the 'indent' value. */ int i; int realindent = indent * 2; /* # spaces per indent level */ for (i = 0; i < realindent; i++) putchar(' '); }; void pproperties (gpointer data, gpointer property_data) { pindent(); printf("\n", data, g_list_last(property_data)->data, g_list_first(property_data)->data); } #ifdef UNUSED #endif