From 6b955b514d45d9c953a418e8dcb756f22a2cbdf5 Mon Sep 17 00:00:00 2001
From: Rob Shearman <robertshearman@gmail.com>
Date: Mon, 29 Dec 2008 12:06:35 +0000
Subject: [PATCH] widl: Generate header files from the parse tree instead of
 using hooks in the parser.

---
 tools/widl/header.c    | 281 +++++++++++++++++++++++++++++++----------
 tools/widl/header.h    |  11 --
 tools/widl/parser.h    |   1 +
 tools/widl/parser.y    |  96 +++++---------
 tools/widl/typetree.c  |   7 +-
 tools/widl/typetree.h  |   2 +-
 tools/widl/widl.c      |  33 +----
 tools/widl/widl.h      |   8 +-
 tools/widl/widltypes.h |   3 +-
 9 files changed, 266 insertions(+), 176 deletions(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index d06ef4d2347..b7df77bb171 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -205,7 +205,7 @@ void write_type_left(FILE *h, type_t *t, int declonly)
     switch (t->type) {
       case RPC_FC_ENUM16:
       case RPC_FC_ENUM32:
-        if (!declonly && t->defined && !t->written && !t->ignore) {
+        if (!declonly && t->defined && !t->written) {
           if (t->name) fprintf(h, "enum %s {\n", t->name);
           else fprintf(h, "enum {\n");
           t->written = TRUE;
@@ -223,7 +223,7 @@ void write_type_left(FILE *h, type_t *t, int declonly)
       case RPC_FC_PSTRUCT:
       case RPC_FC_BOGUS_STRUCT:
       case RPC_FC_ENCAPSULATED_UNION:
-        if (!declonly && t->defined && !t->written && !t->ignore) {
+        if (!declonly && t->defined && !t->written) {
           if (t->name) fprintf(h, "struct %s {\n", t->name);
           else fprintf(h, "struct {\n");
           t->written = TRUE;
@@ -238,7 +238,7 @@ void write_type_left(FILE *h, type_t *t, int declonly)
         else fprintf(h, "struct %s", t->name ? t->name : "");
         break;
       case RPC_FC_NON_ENCAPSULATED_UNION:
-        if (!declonly && t->defined && !t->written && !t->ignore) {
+        if (!declonly && t->defined && !t->written) {
           if (t->name) fprintf(h, "union %s {\n", t->name);
           else fprintf(h, "union {\n");
           t->written = TRUE;
@@ -426,7 +426,7 @@ void check_for_additional_prototype_types(const var_list_t *list)
   }
 }
 
-void write_user_types(void)
+static void write_user_types(FILE *header)
 {
   user_type_t *ut;
   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
@@ -439,7 +439,7 @@ void write_user_types(void)
   }
 }
 
-void write_context_handle_rundowns(void)
+static void write_context_handle_rundowns(FILE *header)
 {
   context_handle_t *ch;
   LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
@@ -449,7 +449,7 @@ void write_context_handle_rundowns(void)
   }
 }
 
-void write_generic_handle_routines(void)
+static void write_generic_handle_routines(FILE *header)
 {
   generic_handle_t *gh;
   LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
@@ -460,7 +460,7 @@ void write_generic_handle_routines(void)
   }
 }
 
-void write_typedef(type_t *type)
+static void write_typedef(FILE *header, type_t *type)
 {
   fprintf(header, "typedef ");
   write_type_def_or_decl(header, type->orig, FALSE, "%s", type->name);
@@ -485,7 +485,7 @@ int is_const_decl(const var_t *var)
   return FALSE;
 }
 
-void write_declaration(const var_t *v, int is_in_interface)
+static void write_declaration(FILE *header, const var_t *v)
 {
   if (is_const_decl(v) && v->eval)
   {
@@ -493,7 +493,7 @@ void write_declaration(const var_t *v, int is_in_interface)
     write_expr(header, v->eval, 0, 1, NULL, NULL, "");
     fprintf(header, ")\n\n");
   }
-  else if (v->type->type != RPC_FC_FUNCTION || !is_in_interface)
+  else
   {
     switch (v->stgclass)
     {
@@ -512,7 +512,7 @@ void write_declaration(const var_t *v, int is_in_interface)
   }
 }
 
-void write_library(const typelib_t *typelib)
+static void write_library(FILE *header, const typelib_t *typelib)
 {
   const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID);
   fprintf(header, "\n");
@@ -846,55 +846,28 @@ void write_local_stubs(const statement_list_t *stmts)
   fclose(local_stubs);
 }
 
-static void write_function_proto(FILE *header, const type_t *iface, const func_t *fun, const char *prefix)
+static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix)
 {
-  var_t *def = fun->def;
-  const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
+  const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV);
 
   /* FIXME: do we need to handle call_as? */
-  write_type_decl_left(header, get_func_return_type(fun));
+  write_type_decl_left(header, fun->type->ref);
   fprintf(header, " ");
   if (callconv) fprintf(header, "%s ", callconv);
-  fprintf(header, "%s%s(\n", prefix, get_name(def));
-  if (fun->args)
-    write_args(header, fun->args, iface->name, 0, TRUE);
+  fprintf(header, "%s%s(\n", prefix, get_name(fun));
+  if (fun->type->details.function->args)
+    write_args(header, fun->type->details.function->args, iface->name, 0, TRUE);
   else
     fprintf(header, "    void");
   fprintf(header, ");\n\n");
 }
 
-static void write_function_protos(FILE *header, const type_t *iface)
+static void write_forward(FILE *header, type_t *iface)
 {
-  const func_t *cur;
-  int prefixes_differ = strcmp(prefix_client, prefix_server);
-
-  if (!iface->funcs) return;
-  LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
-  {
-    if (prefixes_differ) {
-      fprintf(header, "/* client prototype */\n");
-      write_function_proto(header, iface, cur, prefix_client);
-      fprintf(header, "/* server prototype */\n");
-    }
-    write_function_proto(header, iface, cur, prefix_server);
-  }
-}
-
-void write_forward(type_t *iface)
-{
-  /* C/C++ forwards should only be written for object interfaces, so if we
-   * have a full definition we only write one if we find [object] among the
-   * attributes - however, if we don't have a full definition at this point
-   * (i.e. this is an IDL forward), then we also assume that it is an object
-   * interface, since non-object interfaces shouldn't need forwards */
-  if ((!iface->defined || is_object(iface->attrs) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
-        && !iface->written) {
-    fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
-    fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
-    fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
-    fprintf(header, "#endif\n\n" );
-    iface->written = TRUE;
-  }
+  fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
+  fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
+  fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
+  fprintf(header, "#endif\n\n" );
 }
 
 static void write_iface_guid(FILE *header, const type_t *iface)
@@ -1031,22 +1004,7 @@ static void write_rpc_interface_end(FILE *header, const type_t *iface)
   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
 }
 
-void write_interface(type_t *iface)
-{
-  if (is_attr(iface->attrs, ATTR_DISPINTERFACE) || is_object(iface->attrs))
-  {
-    write_com_interface_start(header, iface);
-    write_com_interface_end(header, iface);
-  }
-  else
-  {
-    write_rpc_interface_start(header, iface);
-    write_function_protos(header, iface);
-    write_rpc_interface_end(header, iface);
-  }
-}
-
-void write_coclass(type_t *cocl)
+static void write_coclass(FILE *header, type_t *cocl)
 {
   fprintf(header, "/*****************************************************************************\n");
   fprintf(header, " * %s coclass\n", cocl->name);
@@ -1055,7 +1013,7 @@ void write_coclass(type_t *cocl)
   fprintf(header, "\n");
 }
 
-void write_coclass_forward(type_t *cocl)
+static void write_coclass_forward(FILE *header, type_t *cocl)
 {
   fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
   fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
@@ -1063,7 +1021,7 @@ void write_coclass_forward(type_t *cocl)
   fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
 }
 
-void write_import(const char *fname)
+static void write_import(FILE *header, const char *fname)
 {
   char *hname, *p;
 
@@ -1074,3 +1032,194 @@ void write_import(const char *fname)
   fprintf(header, "#include <%s>\n", hname);
   free(hname);
 }
+
+static void write_imports(FILE *header, const statement_list_t *stmts)
+{
+  const statement_t *stmt;
+  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+  {
+    switch (stmt->type)
+    {
+      case STMT_TYPE:
+        if (stmt->u.type->type == RPC_FC_IP)
+          write_imports(header, stmt->u.type->stmts);
+        break;
+      case STMT_TYPEREF:
+      case STMT_IMPORTLIB:
+        /* not included in header */
+        break;
+      case STMT_IMPORT:
+        write_import(header, stmt->u.str);
+        break;
+      case STMT_TYPEDEF:
+      case STMT_MODULE:
+      case STMT_CPPQUOTE:
+      case STMT_DECLARATION:
+        /* not processed here */
+        break;
+      case STMT_LIBRARY:
+        write_imports(header, stmt->u.lib->stmts);
+        break;
+    }
+  }
+}
+
+static void write_forward_decls(FILE *header, const statement_list_t *stmts)
+{
+  const statement_t *stmt;
+  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+  {
+    switch (stmt->type)
+    {
+      case STMT_TYPE:
+        if (stmt->u.type->type == RPC_FC_IP)
+        {
+          if (is_object(stmt->u.type->attrs) || is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE))
+            write_forward(header, stmt->u.type);
+        }
+        else if (stmt->u.type->type == RPC_FC_COCLASS)
+          write_coclass_forward(header, stmt->u.type);
+        break;
+      case STMT_TYPEREF:
+      case STMT_IMPORTLIB:
+        /* not included in header */
+        break;
+      case STMT_IMPORT:
+      case STMT_TYPEDEF:
+      case STMT_MODULE:
+      case STMT_CPPQUOTE:
+      case STMT_DECLARATION:
+        /* not processed here */
+        break;
+      case STMT_LIBRARY:
+        write_forward_decls(header, stmt->u.lib->stmts);
+        break;
+    }
+  }
+}
+
+static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs)
+{
+  const statement_t *stmt;
+  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+  {
+    switch (stmt->type)
+    {
+      case STMT_TYPE:
+        if (stmt->u.type->type == RPC_FC_IP)
+        {
+          type_t *iface = stmt->u.type;
+          if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type->attrs))
+          {
+            write_com_interface_start(header, iface);
+            write_header_stmts(header, iface->stmts, stmt->u.type, TRUE);
+            write_com_interface_end(header, iface);
+          }
+          else
+          {
+            write_rpc_interface_start(header, iface);
+            write_header_stmts(header, iface->stmts, iface, FALSE);
+            write_rpc_interface_end(header, iface);
+          }
+        }
+        else if (stmt->u.type->type == RPC_FC_COCLASS)
+          write_coclass(header, stmt->u.type);
+        else
+        {
+          write_type_def_or_decl(header, stmt->u.type, FALSE, NULL);
+          fprintf(header, ";\n\n");
+        }
+        break;
+      case STMT_TYPEREF:
+        /* FIXME: shouldn't write out forward declarations for undefined
+        * interfaces but a number of our IDL files depend on this */
+        if (stmt->u.type->type == RPC_FC_IP && !stmt->u.type->written)
+          write_forward(header, stmt->u.type);
+        break;
+      case STMT_IMPORTLIB:
+      case STMT_MODULE:
+        /* not included in header */
+        break;
+      case STMT_IMPORT:
+        /* not processed here */
+        break;
+      case STMT_TYPEDEF:
+      {
+        const type_list_t *type_entry = stmt->u.type_list;
+        for (; type_entry; type_entry = type_entry->next)
+	  write_typedef(header, type_entry->type);
+        break;
+      }
+      case STMT_LIBRARY:
+        write_library(header, stmt->u.lib);
+        write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE);
+        break;
+      case STMT_CPPQUOTE:
+        fprintf(header, "%s\n", stmt->u.str);
+        break;
+      case STMT_DECLARATION:
+        if (iface && stmt->u.var->type->type == RPC_FC_FUNCTION)
+        {
+          if (!ignore_funcs)
+          {
+            int prefixes_differ = strcmp(prefix_client, prefix_server);
+
+            if (prefixes_differ)
+            {
+              fprintf(header, "/* client prototype */\n");
+              write_function_proto(header, iface, stmt->u.var, prefix_client);
+              fprintf(header, "/* server prototype */\n");
+            }
+            write_function_proto(header, iface, stmt->u.var, prefix_server);
+          }
+        }
+        else
+          write_declaration(header, stmt->u.var);
+        break;
+    }
+  }
+}
+
+void write_header(const statement_list_t *stmts)
+{
+  FILE *header;
+
+  if (!do_header) return;
+
+  if(!(header = fopen(header_name, "w"))) {
+    error("Could not open %s for output\n", header_name);
+    return;
+  }
+  fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name);
+  fprintf(header, "#include <rpc.h>\n" );
+  fprintf(header, "#include <rpcndr.h>\n\n" );
+
+  fprintf(header, "#ifndef __WIDL_%s\n", header_token);
+  fprintf(header, "#define __WIDL_%s\n\n", header_token);
+  start_cplusplus_guard(header);
+
+  fprintf(header, "/* Headers for imported files */\n\n");
+  write_imports(header, stmts);
+  fprintf(header, "\n");
+
+  /* FIXME: should be before imported file includes */
+  fprintf(header, "/* Forward declarations */\n\n");
+  write_forward_decls(header, stmts);
+  fprintf(header, "\n");
+
+  write_header_stmts(header, stmts, NULL, FALSE);
+
+  fprintf(header, "/* Begin additional prototypes for all interfaces */\n");
+  fprintf(header, "\n");
+  write_user_types(header);
+  write_generic_handle_routines(header);
+  write_context_handle_rundowns(header);
+  fprintf(header, "\n");
+  fprintf(header, "/* End additional prototypes */\n");
+  fprintf(header, "\n");
+
+  end_cplusplus_guard(header);
+  fprintf(header, "#endif /* __WIDL_%s */\n", header_token);
+
+  fclose(header);
+}
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 84b652de951..23561ce37e6 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -47,17 +47,6 @@ extern int need_proxy_file(const statement_list_t *stmts);
 extern const var_t *is_callas(const attr_list_t *list);
 extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent);
 extern void write_array(FILE *h, array_dims_t *v, int field);
-extern void write_import(const char *fname);
-extern void write_forward(type_t *iface);
-extern void write_interface(type_t *iface);
-extern void write_coclass(type_t *cocl);
-extern void write_coclass_forward(type_t *cocl);
-extern void write_typedef(type_t *type);
-extern void write_declaration(const var_t *v, int is_in_interface);
-extern void write_library(const typelib_t *typelib);
-extern void write_user_types(void);
-extern void write_context_handle_rundowns(void);
-extern void write_generic_handle_routines(void);
 extern const var_t* get_explicit_handle_var(const func_t* func);
 extern const type_t* get_explicit_generic_handle_type(const var_t* var);
 extern const var_t* get_explicit_generic_handle_var(const func_t* func);
diff --git a/tools/widl/parser.h b/tools/widl/parser.h
index 72d551c5d3d..85171f74b9f 100644
--- a/tools/widl/parser.h
+++ b/tools/widl/parser.h
@@ -46,5 +46,6 @@ void pop_import(void);
 int is_type(const char *name);
 
 void check_functions(const type_t *iface);
+func_list_t *gen_function_list(const statement_list_t *stmts);
 
 #endif
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 1bcfd337339..d9b5c3cbfdf 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -69,7 +69,6 @@
 #define YYERROR_VERBOSE
 
 unsigned char pointer_default = RPC_FC_UP;
-static int is_in_interface = FALSE;
 static int is_object_interface = FALSE;
 /* are we inside a library block? */
 static int is_inside_library = FALSE;
@@ -140,7 +139,6 @@ static type_t *get_type(unsigned char type, char *name, int t);
 static var_t *reg_const(var_t *var);
 
 static char *gen_name(void);
-static statement_t *process_typedefs(var_list_t *names);
 static void check_arg(var_t *arg);
 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);
@@ -166,9 +164,10 @@ static statement_t *make_statement_library(typelib_t *typelib);
 static statement_t *make_statement_cppquote(const char *str);
 static statement_t *make_statement_importlib(const char *str);
 static statement_t *make_statement_module(type_t *type);
+static statement_t *make_statement_typedef(var_list_t *names);
 static statement_t *make_statement_import(const char *str);
+static statement_t *make_statement_typedef(var_list_t *names);
 static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt);
-static func_list_t *append_func_from_statement(func_list_t *list, statement_t *stmt);
 
 #define tsENUM   1
 #define tsSTRUCT 2
@@ -320,7 +319,6 @@ static func_list_t *append_func_from_statement(func_list_t *list, statement_t *s
 %type <declarator> declarator direct_declarator init_declarator
 %type <declarator_list> declarator_list
 %type <func> funcdef
-%type <func_list> int_statements dispint_meths
 %type <type> coclass coclasshdr coclassdef
 %type <num> pointer_type version
 %type <str> libraryhdr callconv cppquote importlib import t_ident
@@ -328,7 +326,7 @@ static func_list_t *append_func_from_statement(func_list_t *list, statement_t *s
 %type <import> import_start
 %type <typelib> library_start librarydef
 %type <statement> statement typedef
-%type <stmt_list> gbl_statements imp_statements
+%type <stmt_list> gbl_statements imp_statements int_statements dispint_meths
 
 %left ','
 %right '?' ':'
@@ -349,6 +347,7 @@ static func_list_t *append_func_from_statement(func_list_t *list, statement_t *s
 
 input:   gbl_statements				{ fix_incomplete();
 						  check_all_user_types($1);
+						  write_header($1);
 						  write_id_data($1);
 						  write_proxies($1);
 						  write_client($1);
@@ -359,15 +358,13 @@ input:   gbl_statements				{ fix_incomplete();
 	;
 
 gbl_statements:					{ $$ = NULL; }
-	| gbl_statements interfacedec		{ $$ = $1; }
+	| gbl_statements interfacedec		{ $$ = append_statement($1, make_statement_reference($2)); }
 	| gbl_statements interfacedef		{ $$ = append_statement($1, make_statement_type_decl($2)); }
 	| gbl_statements coclass ';'		{ $$ = $1;
 						  reg_type($2, $2->name, 0);
-						  if (!parse_only && do_header) write_coclass_forward($2);
 						}
 	| gbl_statements coclassdef		{ $$ = append_statement($1, make_statement_type_decl($2));
 						  reg_type($2, $2->name, 0);
-						  if (!parse_only && do_header) write_coclass_forward($2);
 						}
 	| gbl_statements moduledef		{ $$ = append_statement($1, make_statement_module($2)); }
 	| gbl_statements librarydef		{ $$ = append_statement($1, make_statement_library($2)); }
@@ -377,10 +374,9 @@ gbl_statements:					{ $$ = NULL; }
 imp_statements:					{ $$ = NULL; }
 	| imp_statements interfacedec		{ $$ = append_statement($1, make_statement_reference($2)); }
 	| imp_statements interfacedef		{ $$ = append_statement($1, make_statement_type_decl($2)); }
-	| imp_statements coclass ';'		{ $$ = $1; reg_type($2, $2->name, 0); if (!parse_only && do_header) write_coclass_forward($2); }
+	| imp_statements coclass ';'		{ $$ = $1; reg_type($2, $2->name, 0); }
 	| imp_statements coclassdef		{ $$ = append_statement($1, make_statement_type_decl($2));
 						  reg_type($2, $2->name, 0);
-						  if (!parse_only && do_header) write_coclass_forward($2);
 						}
 	| imp_statements moduledef		{ $$ = append_statement($1, make_statement_module($2)); }
 	| imp_statements statement		{ $$ = append_statement($1, $2); }
@@ -389,7 +385,7 @@ imp_statements:					{ $$ = NULL; }
 	;
 
 int_statements:					{ $$ = NULL; }
-	| int_statements statement		{ $$ = append_func_from_statement( $1, $2 ); }
+	| int_statements statement		{ $$ = append_statement($1, $2); }
 	;
 
 semicolon_opt:
@@ -398,15 +394,8 @@ semicolon_opt:
 
 statement:
 	  cppquote				{ $$ = make_statement_cppquote($1); }
-	| typedecl ';'				{ $$ = make_statement_type_decl($1);
-						  if (!parse_only && do_header) {
-						    write_type_def_or_decl(header, $1, FALSE, NULL);
-						    fprintf(header, ";\n\n");
-						  }
-						}
-	| declaration ';'			{ $$ = make_statement_declaration($1);
-						  if (!parse_only && do_header) write_declaration($1, is_in_interface);
-						}
+	| typedecl ';'				{ $$ = make_statement_type_decl($1); }
+	| declaration ';'			{ $$ = make_statement_declaration($1); }
 	| import				{ $$ = make_statement_import($1); }
 	| typedef ';'				{ $$ = $1; }
 	;
@@ -420,7 +409,7 @@ typedecl:
 	| attributes uniondef                   { $$ = $2; $$->attrs = check_union_attrs($1); }
 	;
 
-cppquote: tCPPQUOTE '(' aSTRING ')'		{ $$ = $3; if (!parse_only && do_header) fprintf(header, "%s\n", $3); }
+cppquote: tCPPQUOTE '(' aSTRING ')'		{ $$ = $3; }
 	;
 import_start: tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
 						  $$ = xmalloc(sizeof(struct _import_t));
@@ -433,7 +422,6 @@ import_start: tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
 import: import_start imp_statements aEOF	{ $$ = $1->name;
 						  if ($1->import_performed) pop_import();
 						  free($1);
-						  if (!parse_only && do_header) write_import($$);
 						}
 	;
 
@@ -445,7 +433,6 @@ libraryhdr: tLIBRARY aIDENTIFIER		{ $$ = $2; }
 	;
 library_start: attributes libraryhdr '{'	{ $$ = make_library($2, check_library_attrs($2, $1));
 						  if (!parse_only) start_typelib($$);
-						  if (!parse_only && do_header) write_library($$);
 						  is_inside_library = TRUE;
 						}
 	;
@@ -841,8 +828,6 @@ coclass:  tCOCLASS aIDENTIFIER			{ $$ = make_class($2); }
 coclasshdr: attributes coclass			{ $$ = $2;
 						  check_def($$);
 						  $$->attrs = check_coclass_attrs($2->name, $1);
-						  if (!parse_only && do_header)
-						    write_coclass($$);
 						}
 	;
 
@@ -866,14 +851,12 @@ dispinterface: tDISPINTERFACE aIDENTIFIER	{ $$ = get_type(RPC_FC_IP, $2, 0); $$-
 	;
 
 dispinterfacehdr: attributes dispinterface	{ attr_t *attrs;
-						  is_in_interface = TRUE;
 						  is_object_interface = TRUE;
 						  $$ = $2;
 						  check_def($$);
 						  attrs = make_attr(ATTR_DISPINTERFACE);
 						  $$->attrs = append_attr( check_dispiface_attrs($2->name, $1), attrs );
 						  $$->defined = TRUE;
-						  if (!parse_only && do_header) write_forward($$);
 						}
 	;
 
@@ -890,14 +873,10 @@ dispinterfacedef: dispinterfacehdr '{'
 	  dispint_meths
 	  '}'					{ $$ = $1;
 						  type_dispinterface_define($$, $3, $4);
-						  if (!parse_only && do_header) write_interface($$);
-						  is_in_interface = FALSE;
 						}
 	| dispinterfacehdr
 	 '{' interface ';' '}' 			{ $$ = $1;
 						  type_dispinterface_define_from_iface($$, $3);
-						  if (!parse_only && do_header) write_interface($$);
-						  is_in_interface = FALSE;
 						}
 	;
 
@@ -914,20 +893,16 @@ interfacehdr: attributes interface		{ $$.interface = $2;
 						  if (is_attr($1, ATTR_POINTERDEFAULT))
 						    pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
 						  is_object_interface = is_object($1);
-						  is_in_interface = TRUE;
 						  check_def($2);
 						  $2->attrs = check_iface_attrs($2->name, $1);
 						  $2->defined = TRUE;
-						  if (!parse_only && do_header) write_forward($2);
 						}
 	;
 
 interfacedef: interfacehdr inherit
 	  '{' int_statements '}' semicolon_opt	{ $$ = $1.interface;
 						  type_interface_define($$, $2, $4);
-						  if (!parse_only && do_header) write_interface($$);
 						  pointer_default = $1.old_pointer_default;
-						  is_in_interface = FALSE;
 						}
 /* MIDL is able to import the definition of a base class from inside the
  * definition of a derived class, I'll try to support it with this rule */
@@ -935,16 +910,14 @@ interfacedef: interfacehdr inherit
 	  '{' import int_statements '}'
 	   semicolon_opt			{ $$ = $1.interface;
 						  type_interface_define($$, find_type_or_error2($3, 0), $6);
-						  if (!parse_only && do_header) write_interface($$);
 						  pointer_default = $1.old_pointer_default;
-						  is_in_interface = FALSE;
 						}
 	| dispinterfacedef semicolon_opt	{ $$ = $1; }
 	;
 
 interfacedec:
-	  interface ';'				{ $$ = $1; if (!parse_only && do_header) write_forward($$); }
-	| dispinterface ';'			{ $$ = $1; if (!parse_only && do_header) write_forward($$); }
+	  interface ';'				{ $$ = $1; }
+	| dispinterface ';'			{ $$ = $1; }
 	;
 
 module:   tMODULE aIDENTIFIER			{ $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; }
@@ -958,8 +931,8 @@ modulehdr: attributes module			{ $$ = $2;
 
 moduledef: modulehdr '{' int_statements '}'
 	   semicolon_opt			{ $$ = $1;
-						  $$->funcs = $3;
-						  /* FIXME: if (!parse_only && do_header) write_module($$); */
+						  $$->stmts = $3;
+						  $$->funcs = gen_function_list($3);
 						}
 	;
 
@@ -1046,7 +1019,7 @@ type:	  tVOID					{ $$ = find_type_or_error("void", 0); }
 
 typedef: tTYPEDEF m_attributes decl_spec declarator_list
 						{ reg_typedefs($3, $4, check_typedef_attrs($2));
-						  $$ = process_typedefs($4);
+						  $$ = make_statement_typedef($4);
 						}
 	;
 
@@ -1735,7 +1708,6 @@ static func_t *make_func(var_t *def)
   func_t *f = xmalloc(sizeof(func_t));
   f->def = def;
   f->args = def->type->details.function->args;
-  f->ignore = parse_only;
   f->idx = -1;
   return f;
 }
@@ -2010,6 +1982,25 @@ var_t *find_const(const char *name, int f)
   return cur->var;
 }
 
+func_list_t *gen_function_list(const statement_list_t *stmts)
+{
+  func_list_t *func_list = NULL;
+  const statement_t *stmt;
+  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+  {
+    if (stmt->type == STMT_DECLARATION)
+    {
+      var_t *var = stmt->u.var;
+      if (var->stgclass == STG_NONE && var->type->type == RPC_FC_FUNCTION)
+      {
+        check_function_attrs(var->name, var->type->attrs);
+        func_list = append_func(func_list, make_func(var));
+      }
+    }
+  }
+  return func_list;
+}
+
 static char *gen_name(void)
 {
   static const char format[] = "__WIDL_%s_generated_name_%08lX";
@@ -2677,7 +2668,7 @@ static statement_t *make_statement_module(type_t *type)
     return stmt;
 }
 
-static statement_t *process_typedefs(declarator_list_t *decls)
+static statement_t *make_statement_typedef(declarator_list_t *decls)
 {
     declarator_t *decl, *next;
     statement_t *stmt;
@@ -2697,9 +2688,6 @@ static statement_t *process_typedefs(declarator_list_t *decls)
         (*type_list)->type = type;
         (*type_list)->next = NULL;
 
-        if (! parse_only && do_header)
-            write_typedef(type);
-
         type_list = &(*type_list)->next;
         free(decl);
         free(var);
@@ -2720,20 +2708,6 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
     return list;
 }
 
-static func_list_t *append_func_from_statement(func_list_t *list, statement_t *stmt)
-{
-    if (stmt->type == STMT_DECLARATION)
-    {
-        var_t *var = stmt->u.var;
-        if (var->stgclass == STG_NONE && var->type->type == RPC_FC_FUNCTION)
-        {
-            check_function_attrs(var->name, var->type->attrs);
-            return append_func(list, make_func(stmt->u.var));
-        }
-    }
-    return list;
-}
-
 void init_loc_info(loc_info_t *i)
 {
     i->input_name = input_name ? input_name : "stdin";
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c
index 7de91144a85..2b56bb8e6ff 100644
--- a/tools/widl/typetree.c
+++ b/tools/widl/typetree.c
@@ -64,13 +64,14 @@ static int compute_method_indexes(type_t *iface)
     return idx;
 }
 
-void type_interface_define(type_t *iface, type_t *inherit, func_list_t *funcs)
+void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts)
 {
     iface->ref = inherit;
     iface->details.iface = xmalloc(sizeof(*iface->details.iface));
-    iface->funcs = funcs;
+    iface->funcs = gen_function_list(stmts);
     iface->details.iface->disp_props = NULL;
     iface->details.iface->disp_methods = NULL;
+    iface->stmts = stmts;
     iface->defined = TRUE;
     check_functions(iface);
     compute_method_indexes(iface);
@@ -84,7 +85,7 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *me
     iface->funcs = NULL;
     iface->details.iface->disp_props = props;
     iface->details.iface->disp_methods = methods;
-    iface->funcs = methods;
+    iface->stmts = NULL;
     iface->defined = TRUE;
     check_functions(iface);
     compute_method_indexes(iface);
diff --git a/tools/widl/typetree.h b/tools/widl/typetree.h
index eafe0d52eba..99c0d2f911d 100644
--- a/tools/widl/typetree.h
+++ b/tools/widl/typetree.h
@@ -26,7 +26,7 @@
 
 type_t *type_new_function(var_list_t *args);
 type_t *type_new_pointer(type_t *ref, attr_list_t *attrs);
-void type_interface_define(type_t *iface, type_t *inherit, func_list_t *funcs);
+void type_interface_define(type_t *iface, type_t *inherit, statement_list_t *stmts);
 void type_dispinterface_define(type_t *iface, var_list_t *props, func_list_t *methods);
 void type_dispinterface_define_from_iface(type_t *dispiface, type_t *iface);
 
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index 4f076c3113b..ab1572611b3 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -213,14 +213,14 @@ static void set_everything(int x)
   do_dlldata = x;
 }
 
-static void start_cplusplus_guard(FILE *fp)
+void start_cplusplus_guard(FILE *fp)
 {
   fprintf(fp, "#ifdef __cplusplus\n");
   fprintf(fp, "extern \"C\" {\n");
   fprintf(fp, "#endif\n\n");
 }
 
-static void end_cplusplus_guard(FILE *fp)
+void end_cplusplus_guard(FILE *fp)
 {
   fprintf(fp, "#ifdef __cplusplus\n");
   fprintf(fp, "}\n");
@@ -626,38 +626,11 @@ int main(int argc,char *argv[])
     }
   }
 
-  if(do_header) {
-    header_token = make_token(header_name);
-
-    if(!(header = fopen(header_name, "w"))) {
-      fprintf(stderr, "Could not open %s for output\n", header_name);
-      return 1;
-    }
-    fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name);
-    fprintf(header, "#include <rpc.h>\n" );
-    fprintf(header, "#include <rpcndr.h>\n\n" );
-    fprintf(header, "#ifndef __WIDL_%s\n", header_token);
-    fprintf(header, "#define __WIDL_%s\n", header_token);
-    start_cplusplus_guard(header);
-  }
+  header_token = make_token(header_name);
 
   init_types();
   ret = parser_parse();
 
-  if(do_header) {
-    fprintf(header, "/* Begin additional prototypes for all interfaces */\n");
-    fprintf(header, "\n");
-    write_user_types();
-    write_generic_handle_routines();
-    write_context_handle_rundowns();
-    fprintf(header, "\n");
-    fprintf(header, "/* End additional prototypes */\n");
-    fprintf(header, "\n");
-    end_cplusplus_guard(header);
-    fprintf(header, "#endif /* __WIDL_%s */\n", header_token);
-    fclose(header);
-  }
-
   fclose(parser_in);
 
   if(ret) {
diff --git a/tools/widl/widl.h b/tools/widl/widl.h
index c36831794d7..d8c945ff524 100644
--- a/tools/widl/widl.h
+++ b/tools/widl/widl.h
@@ -50,6 +50,7 @@ extern int do_win64;
 
 extern char *input_name;
 extern char *header_name;
+extern char *header_token;
 extern char *local_stubs_name;
 extern char *typelib_name;
 extern char *dlldata_name;
@@ -67,9 +68,7 @@ extern time_t now;
 extern int line_number;
 extern int char_number;
 
-extern FILE* header;
-extern FILE* idfile;
-
+extern void write_header(const statement_list_t *stmts);
 extern void write_id_data(const statement_list_t *stmts);
 extern void write_proxies(const statement_list_t *stmts);
 extern void write_client(const statement_list_t *stmts);
@@ -77,4 +76,7 @@ extern void write_server(const statement_list_t *stmts);
 extern void write_local_stubs(const statement_list_t *stmts);
 extern void write_dlldata(const statement_list_t *stmts);
 
+extern void start_cplusplus_guard(FILE *fp);
+extern void end_cplusplus_guard(FILE *fp);
+
 #endif
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index cb670ebaa7e..2ae856c827e 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -295,6 +295,7 @@ struct _type_t {
     struct iface_details *iface;
   } details;
   func_list_t *funcs;             /* interfaces and modules */
+  statement_list_t *stmts;        /* interfaces and modules */
   ifref_list_t *ifaces;           /* coclasses */
   unsigned long dim;              /* array dimension */
   expr_t *size_is, *length_is;
@@ -339,7 +340,7 @@ struct _declarator_t {
 struct _func_t {
   var_t *def;
   var_list_t *args;
-  int ignore, idx;
+  int idx;
 
   /* parser-internal */
   struct list entry;
-- 
GitLab