Rob Shearman : widl: Add support for varargs functions.

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


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

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

widl: Add support for varargs functions.

---

 dlls/rpcrt4/tests/server.c   |    3 ++
 dlls/rpcrt4/tests/server.idl |    2 +
 tools/widl/header.c          |   68 ++++++++++++++++++++++-------------------
 tools/widl/parser.l          |    1 +
 tools/widl/parser.y          |   12 +++++--
 5 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index d9a9fcc..1205ea4 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -42,6 +42,9 @@ static NDR_SCONTEXT (WINAPI *pNDRSContextUnmarshall2)(RPC_BINDING_HANDLE, void*,
 static RPC_STATUS (WINAPI *pRpcServerRegisterIfEx)(RPC_IF_HANDLE,UUID*, RPC_MGR_EPV*, unsigned int,
                    unsigned int,RPC_IF_CALLBACK_FN*);
 
+/* type check statements generated in header file */
+fnprintf *p_printf = printf;
+
 static void InitFunctionPointers(void)
 {
     HMODULE hrpcrt4 = GetModuleHandleA("rpcrt4.dll");
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index fe2c075..d8e79bd 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -27,6 +27,8 @@ typedef struct tag_vector
   int z;
 } vector_t;
 
+typedef int fnprintf(const char *format, ...);
+
 [
   uuid(00000000-4114-0704-2301-000000000000),
 #ifndef __midl
diff --git a/tools/widl/header.c b/tools/widl/header.c
index a0582f2..e87a44e 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -348,42 +348,46 @@ void write_type_right(FILE *h, type_t *t, int is_field)
 
 static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name)
 {
-  type_t *pt;
+  type_t *pt = NULL;
   int ptr_level = 0;
 
   if (!h) return;
 
-  for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++)
-    ;
-
-  if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
-    int i;
-    const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
-    if (!callconv) callconv = "";
-    if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
-    write_type_left(h, type_function_get_rettype(pt), declonly);
-    fputc(' ', h);
-    if (ptr_level) fputc('(', h);
-    fprintf(h, "%s ", callconv);
-    for (i = 0; i < ptr_level; i++)
-      fputc('*', h);
-  } else
-    write_type_left(h, t, declonly);
-
-  if (name) fprintf(h, "%s%s", needs_space_after(t) ? " " : "", name );
-
-  if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
-    const var_list_t *args = type_function_get_args(pt);
-
-    if (ptr_level) fputc(')', h);
-    fputc('(', h);
-    if (args)
-        write_args(h, args, NULL, 0, FALSE);
-    else
-        fprintf(h, "void");
-    fputc(')', h);
-  } else
-    write_type_right(h, t, is_field);
+  if (t) {
+    for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++)
+      ;
+
+    if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
+      int i;
+      const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
+      if (!callconv) callconv = "";
+      if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
+      write_type_left(h, type_function_get_rettype(pt), declonly);
+      fputc(' ', h);
+      if (ptr_level) fputc('(', h);
+      fprintf(h, "%s ", callconv);
+      for (i = 0; i < ptr_level; i++)
+        fputc('*', h);
+    } else
+      write_type_left(h, t, declonly);
+  }
+
+  if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
+
+  if (t) {
+    if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
+      const var_list_t *args = type_function_get_args(pt);
+
+      if (ptr_level) fputc(')', h);
+      fputc('(', h);
+      if (args)
+          write_args(h, args, NULL, 0, FALSE);
+      else
+          fprintf(h, "void");
+      fputc(')', h);
+    } else
+      write_type_right(h, t, is_field);
+  }
 }
 
 void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name)
diff --git a/tools/widl/parser.l b/tools/widl/parser.l
index d3f355f..f509cb1 100644
--- a/tools/widl/parser.l
+++ b/tools/widl/parser.l
@@ -193,6 +193,7 @@ SAFEARRAY{ws}*/\(	return tSAFEARRAY;
 <INITIAL,ATTR>\<=	return LESSEQUAL;
 <INITIAL,ATTR>\|\|	return LOGICALOR;
 <INITIAL,ATTR>&&	return LOGICALAND;
+<INITIAL,ATTR>\.\.\.	return ELLIPSIS;
 <INITIAL,ATTR>.		return yytext[0];
 <<EOF>>			{
 				if (import_stack_ptr)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 9e1598e..0c216ec 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -194,6 +194,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
 %token EQUALITY INEQUALITY
 %token GREATEREQUAL LESSEQUAL
 %token LOGICALOR LOGICALAND
+%token ELLIPSIS
 %token tAGGREGATABLE tALLOCATE tANNOTATION tAPPOBJECT tASYNC tASYNCUUID
 %token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT
 %token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS
@@ -292,7 +293,8 @@ 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 args fields ne_union_fields cases enums enum_list dispint_props field
+%type <var_list> m_args arg_list args
+%type <var_list> fields ne_union_fields cases enums enum_list dispint_props field
 %type <var> m_ident ident
 %type <declarator> declarator direct_declarator init_declarator struct_declarator
 %type <declarator> m_any_declarator any_declarator any_declarator_no_ident any_direct_declarator
@@ -426,8 +428,12 @@ m_args:						{ $$ = NULL; }
 	| args
 	;
 
-args:	  arg					{ check_arg_attrs($1); $$ = append_var( NULL, $1 ); }
-	| args ',' arg				{ check_arg_attrs($3); $$ = append_var( $1, $3); }
+arg_list: arg					{ check_arg_attrs($1); $$ = append_var( NULL, $1 ); }
+	| arg_list ',' arg			{ check_arg_attrs($3); $$ = append_var( $1, $3 ); }
+	;
+
+args:	  arg_list
+	| arg_list ',' ELLIPSIS			{ $$ = append_var( $1, make_var(strdup("...")) ); }
 	;
 
 /* split into two rules to get bison to resolve a tVOID conflict */




More information about the wine-cvs mailing list