Rob Shearman : widl: Enhance the IDL grammar to support unnamed arguments to functions.

Alexandre Julliard julliard at winehq.org
Mon Nov 9 15:14:19 CST 2009


Module: wine
Branch: master
Commit: c3676245348b0222b1c2b61dc24b26ad35a23b07
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=c3676245348b0222b1c2b61dc24b26ad35a23b07

Author: Rob Shearman <robertshearman at gmail.com>
Date:   Sat Nov  7 15:54:24 2009 +0100

widl: Enhance the IDL grammar to support unnamed arguments to functions.

---

 tools/widl/parser.y   |   64 ++++++++++++++++++++++++++++++++++++------------
 tools/widl/typetree.c |   56 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 103 insertions(+), 17 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index b12741c..64f92b0 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -121,7 +121,7 @@ static type_t *find_type_or_error2(char *name, int t);
 static var_t *reg_const(var_t *var);
 
 static char *gen_name(void);
-static void check_arg(var_t *arg);
+static void check_arg_attrs(const var_t *arg);
 static void check_statements(const statement_list_t *stmts, int is_inside_library);
 static void check_all_user_types(const statement_list_t *stmts);
 static attr_list_t *check_iface_attrs(const char *name, attr_list_t *attrs);
@@ -292,9 +292,10 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
 %type <ifref> coclass_int
 %type <ifref_list> coclass_ints
 %type <var> arg ne_union_field union_field s_field case enum declaration
-%type <var_list> m_args no_args args fields ne_union_fields cases enums enum_list dispint_props field
+%type <var_list> m_args args fields ne_union_fields cases enums enum_list dispint_props field
 %type <var> m_ident ident
 %type <declarator> declarator direct_declarator init_declarator
+%type <declarator> m_any_declarator any_declarator any_declarator_no_ident any_direct_declarator
 %type <declarator_list> declarator_list
 %type <func> funcdef
 %type <type> coclass coclasshdr coclassdef
@@ -425,23 +426,19 @@ m_args:						{ $$ = NULL; }
 	| args
 	;
 
-no_args:  tVOID					{ $$ = NULL; }
-	;
-
-args:	  arg					{ check_arg($1); $$ = append_var( NULL, $1 ); }
-	| args ',' arg				{ check_arg($3); $$ = append_var( $1, $3); }
-	| no_args
+args:	  arg					{ check_arg_attrs($1); $$ = append_var( NULL, $1 ); }
+	| args ',' arg				{ check_arg_attrs($3); $$ = append_var( $1, $3); }
 	;
 
 /* split into two rules to get bison to resolve a tVOID conflict */
-arg:	  attributes decl_spec declarator	{ $$ = $3->var;
+arg:	  attributes decl_spec m_any_declarator	{ $$ = $3->var;
 						  $$->attrs = $1;
 						  if ($2->stgclass != STG_NONE && $2->stgclass != STG_REGISTER)
 						    error_loc("invalid storage class for function parameter\n");
 						  set_type($$, $2, $3, TRUE);
 						  free($3);
 						}
-	| decl_spec declarator			{ $$ = $2->var;
+	| decl_spec m_any_declarator		{ $$ = $2->var;
 						  if ($1->stgclass != STG_NONE && $1->stgclass != STG_REGISTER)
 						    error_loc("invalid storage class for function parameter\n");
 						  set_type($$, $1, $2, TRUE);
@@ -945,6 +942,45 @@ direct_declarator:
 						}
 	;
 
+/* abstract or non-abstract declarator */
+any_declarator:
+	  '*' m_type_qual_list m_any_declarator %prec PPTR
+						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+	| any_direct_declarator
+	;
+
+/* abstract or non-abstract declarator without accepting idents */
+any_declarator_no_ident:
+	  '*' m_type_qual_list m_any_declarator %prec PPTR
+						{ $$ = $3; $$->type = append_ptrchain_type($$->type, type_new_pointer(pointer_default, NULL, $2)); }
+	| callconv m_any_declarator		{ $$ = $2; $$->type->attrs = append_attr($$->type->attrs, make_attrp(ATTR_CALLCONV, $1)); }
+	;
+
+/* abstract or non-abstract declarator or empty */
+m_any_declarator: 				{ $$ = make_declarator(NULL); }
+	| any_declarator
+	;
+
+/* abstract or non-abstract direct declarator. note: idents aren't accepted
+ * inside brackets to avoid ambiguity with the rule for function arguments */
+any_direct_declarator:
+	  ident					{ $$ = make_declarator($1); }
+	| '(' any_declarator_no_ident ')'	{ $$ = $2; }
+	| any_direct_declarator array		{ $$ = $1; $$->array = append_array($$->array, $2); }
+	| array					{ $$ = make_declarator(NULL); $$->array = append_array($$->array, $1); }
+	| '(' m_args ')'
+						{ $$ = make_declarator(NULL);
+						  $$->func_type = append_ptrchain_type($$->type, type_new_function($2));
+						  $$->type = NULL;
+						}
+	| any_direct_declarator '(' m_args ')'
+						{ $$ = $1;
+						  $$->func_type = append_ptrchain_type($$->type, type_new_function($3));
+						  $$->type = NULL;
+						}
+	;
+
 declarator_list:
 	  declarator				{ $$ = append_declarator( NULL, $1 ); }
 	| declarator_list ',' declarator	{ $$ = append_declarator( $1, $3 ); }
@@ -1532,7 +1568,7 @@ static declarator_list_t *append_declarator(declarator_list_t *list, declarator_
 static declarator_t *make_declarator(var_t *var)
 {
   declarator_t *d = xmalloc(sizeof(*d));
-  d->var = var;
+  d->var = var ? var : make_var(NULL);
   d->type = NULL;
   d->func_type = NULL;
   d->array = NULL;
@@ -1979,14 +2015,10 @@ static attr_list_t *check_function_attrs(const char *name, attr_list_t *attrs)
   return attrs;
 }
 
-static void check_arg(var_t *arg)
+static void check_arg_attrs(const var_t *arg)
 {
-  const type_t *t = arg->type;
   const attr_t *attr;
 
-  if (type_get_type(t) == TYPE_VOID)
-    error_loc("argument '%s' has void type\n", arg->name);
-
   if (arg->attrs)
   {
     LIST_FOR_EACH_ENTRY(attr, arg->attrs, const attr_t, entry)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 4359d92..07393f4 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -63,9 +63,63 @@ type_t *make_type(enum type_type type)
     return t;
 }
 
+static const var_t *find_arg(const var_list_t *args, const char *name)
+{
+    const var_t *arg;
+
+    if (args) LIST_FOR_EACH_ENTRY(arg, args, const var_t, entry)
+    {
+        if (arg->name && !strcmp(name, arg->name))
+            return arg;
+    }
+
+    return NULL;
+}
+
 type_t *type_new_function(var_list_t *args)
 {
-    type_t *t = make_type(TYPE_FUNCTION);
+    var_t *arg;
+    type_t *t;
+    unsigned int i = 0;
+
+    if (args)
+    {
+        arg = LIST_ENTRY(list_head(args), var_t, entry);
+        if (list_count(args) == 1 && !arg->name && arg->type && type_get_type(arg->type) == TYPE_VOID)
+        {
+            list_remove(&arg->entry);
+            free(arg);
+            free(args);
+            args = NULL;
+        }
+    }
+    if (args) LIST_FOR_EACH_ENTRY(arg, args, var_t, entry)
+    {
+        if (arg->type && type_get_type(arg->type) == TYPE_VOID)
+            error_loc("argument '%s' has void type\n", arg->name);
+        if (!arg->name)
+        {
+            if (i > 26 * 26)
+                error_loc("too many unnamed arguments\n");
+            else
+            {
+                int unique;
+                do
+                {
+                    char name[3];
+                    name[0] = i > 26 ? 'a' + i / 26 : 'a' + i;
+                    name[1] = i > 26 ? 'a' + i % 26 : 0;
+                    name[2] = 0;
+                    unique = !find_arg(args, name);
+                    if (unique)
+                        arg->name = xstrdup(name);
+                    i++;
+                } while (!unique);
+            }
+        }
+    }
+
+    t = make_type(TYPE_FUNCTION);
     t->details.function = xmalloc(sizeof(*t->details.function));
     t->details.function->args = args;
     t->details.function->idx = -1;




More information about the wine-cvs mailing list