widl: Generate GUID (infile_i.c) files

Dan Hipschman dsh at linux.ucla.edu
Thu Aug 3 19:48:45 CDT 2006


This patch allows WIDL to output the files that contain GUID definitions.
These are output by MIDL with the infile_i.c naming convention, so that is
what I've done here, too.

ChangeLog:
* Get WIDL to output GUID files
---
 tools/widl/header.c |   12 ++++++-----
 tools/widl/header.h |    2 ++
 tools/widl/parser.y |   39 ++++++++++++++++++++++++++++++++++++-
 tools/widl/widl.c   |   54 +++++++++++++++++++++++++++++++++++++++++++++++----
 tools/widl/widl.h   |    2 ++
 5 files changed, 98 insertions(+), 11 deletions(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index c807691..6344fb3 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -80,10 +80,10 @@ int is_void(const type_t *t, const var_t
   return 0;
 }
 
-static void write_guid(const char *guid_prefix, const char *name, const UUID *uuid)
+void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
 {
   if (!uuid) return;
-  fprintf(header, "DEFINE_GUID(%s_%s, 0x%08lx, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
+  fprintf(f, "DEFINE_GUID(%s_%s, 0x%08lx, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
         guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
         uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
@@ -503,7 +503,7 @@ void write_externdef(const var_t *v)
 void write_library(const char *name, const attr_t *attr) {
   const UUID *uuid = get_attrp(attr, ATTR_UUID);
   fprintf(header, "\n");
-  write_guid("LIBID", name, uuid);
+  write_guid(header, "LIBID", name, uuid);
   fprintf(header, "\n");
 }
 
@@ -846,19 +846,19 @@ void write_forward(type_t *iface)
 static void write_iface_guid(const type_t *iface)
 {
   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
-  write_guid("IID", iface->name, uuid);
+  write_guid(header, "IID", iface->name, uuid);
 } 
 
 static void write_dispiface_guid(const type_t *iface)
 {
   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
-  write_guid("DIID", iface->name, uuid);
+  write_guid(header, "DIID", iface->name, uuid);
 }
 
 static void write_coclass_guid(type_t *cocl)
 {
   const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
-  write_guid("CLSID", cocl->name, uuid);
+  write_guid(header, "CLSID", cocl->name, uuid);
 }
 
 static void write_com_interface(type_t *iface)
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 5863f3b..6358d98 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -46,6 +46,8 @@ extern void write_library(const char *na
 extern void write_user_types(void);
 extern const var_t* get_explicit_handle_var(const func_t* func);
 extern int has_out_arg_or_return(const func_t *func);
+extern void write_guid(FILE *f, const char *guid_prefix, const char *name,
+                       const UUID *uuid);
 
 static inline int is_string_type(const attr_t *attrs, int ptr_level, const expr_t *array)
 {
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index b9f858e..ca5db5c 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -96,6 +96,11 @@ static int get_struct_type(var_t *fields
 static var_t *reg_const(var_t *var);
 static var_t *find_const(char *name, int f);
 
+static void write_libid(const char *name, const attr_t *attr);
+static void write_clsid(type_t *cls);
+static void write_diid(type_t *iface);
+static void write_iid(type_t *iface);
+
 #define tsENUM   1
 #define tsSTRUCT 2
 #define tsUNION  3
@@ -299,7 +304,9 @@ importlib: tIMPORTLIB '(' aSTRING ')'		{
 libraryhdr: tLIBRARY aIDENTIFIER		{ $$ = $2; }
 	;
 library_start: attributes libraryhdr '{'	{ start_typelib($2, $1);
-						  if (!parse_only && do_header) write_library($2, $1); }
+						  if (!parse_only && do_header) write_library($2, $1);
+						  if (!parse_only && do_idfile) write_libid($2, $1);
+						}
 	;
 librarydef: library_start imp_statements '}'	{ end_typelib(); }
 	;
@@ -649,6 +656,8 @@ coclasshdr: attributes coclass			{ $$ = 
 						  $$->attrs = $1;
 						  if (!parse_only && do_header)
 						    write_coclass($$);
+						  if (!parse_only && do_idfile)
+						    write_clsid($$);
 						}
 	;
 
@@ -698,10 +707,12 @@ dispinterfacedef: dispinterfacehdr '{'
 						  $$->fields = $3;
 						  $$->funcs = $4;
 						  if (!parse_only && do_header) write_dispinterface($$);
+						  if (!parse_only && do_idfile) write_diid($$);
 						}
 /* FIXME: not sure how to handle this yet
 	| dispinterfacehdr '{' interface '}'	{ $$ = $1;
 						  if (!parse_only && do_header) write_interface($$);
+						  if (!parse_only && do_idfile) write_iid($$);
 						}
 */
 	;
@@ -727,6 +738,7 @@ interfacedef: interfacehdr inherit
 						  $$->ref = $2;
 						  $$->funcs = $4;
 						  if (!parse_only && do_header) write_interface($$);
+						  if (!parse_only && do_idfile) write_iid($$);
 						}
 /* 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 */
@@ -736,6 +748,7 @@ interfacedef: interfacehdr inherit
 						  if (!$$->ref) yyerror("base class '%s' not found in import", $3);
 						  $$->funcs = $6;
 						  if (!parse_only && do_header) write_interface($$);
+						  if (!parse_only && do_idfile) write_iid($$);
 						}
 	| dispinterfacedef			{ $$ = $1; }
 	;
@@ -1505,3 +1518,27 @@ static var_t *find_const(char *name, int
   }
   return cur->var;
 }
+
+static void write_libid(const char *name, const attr_t *attr)
+{
+  const UUID *uuid = get_attrp(attr, ATTR_UUID);
+  write_guid(idfile, "LIBID", name, uuid);
+}
+
+static void write_clsid(type_t *cls)
+{
+  const UUID *uuid = get_attrp(cls->attrs, ATTR_UUID);
+  write_guid(idfile, "CLSID", cls->name, uuid);
+}
+
+static void write_diid(type_t *iface)
+{
+  const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
+  write_guid(idfile, "DIID", iface->name, uuid);
+}
+
+static void write_iid(type_t *iface)
+{
+  const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
+  write_guid(idfile, "IID", iface->name, uuid);
+}
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index c6c4a1c..152d35f 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -46,8 +46,6 @@ #include "header.h"
 /* A = ACF input filename */
 /* J = do not search standard include path */
 /* O = generate interpreted stubs */
-/* u = UUID file only? */
-/* U = UUID filename */
 /* w = select win16/win32 output (?) */
 
 static char usage[] =
@@ -68,6 +66,8 @@ static char usage[] =
 "   -S file     Name of server stub file (default is infile_s.c)\n"
 "   -t          Generate typelib\n"
 "   -T file     Name of typelib file (default is infile.tlb)\n"
+"   -u          Generate interface identifiers file\n"
+"   -U file     Name of interface identifiers file (default is infile_i.c)\n"
 "   -V          Print version and exit\n"
 "   -W          Enable pedantic warnings\n"
 "Debug level 'n' is a bitmask with following meaning:\n"
@@ -94,6 +94,7 @@ int do_typelib = 0;
 int do_proxies = 0;
 int do_client = 0;
 int do_server = 0;
+int do_idfile = 0;
 int no_preprocess = 0;
 int old_names = 0;
 
@@ -107,17 +108,20 @@ char *client_name;
 char *client_token;
 char *server_name;
 char *server_token;
+char *idfile_name;
+char *idfile_token;
 char *temp_name;
 
 int line_number = 1;
 
 FILE *header;
 FILE *proxy;
+FILE *idfile;
 
 time_t now;
 
 static const char *short_options =
-    "cC:d:D:EhH:I:NpP:sS:tT:VW";
+    "cC:d:D:EhH:I:NpP:sS:tT:uU:VW";
 static struct option long_options[] = {
     { "oldnames", 0, 0, 1 },
     { 0, 0, 0, 0 }
@@ -231,6 +235,13 @@ #endif
     case 'T':
       typelib_name = strdup(optarg);
       break;
+    case 'u':
+      do_everything = 0;
+      do_idfile = 1;
+      break;
+    case 'U':
+      idfile_name = strdup(optarg);
+      break;
     case 'V':
       printf(version_string);
       return 0;
@@ -244,7 +255,7 @@ #endif
   }
 
   if(do_everything) {
-      do_header = do_typelib = do_proxies = do_client = do_server = 1;
+      do_header = do_typelib = do_proxies = do_client = do_server = do_idfile = 1;
   }
   if(optind < argc) {
     input_name = xstrdup(argv[optind]);
@@ -292,6 +303,11 @@ #endif
     strcat(server_name, "_s.c");
   }
 
+  if (!idfile_name && do_idfile) {
+    idfile_name = dup_basename(input_name, ".idl");
+    strcat(idfile_name, "_i.c");
+  }
+
   if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
   if (do_client) client_token = dup_basename_token(client_name,"_c.c");
   if (do_server) server_token = dup_basename_token(server_name,"_s.c");
@@ -343,6 +359,26 @@ #endif
     fprintf(header, "#endif\n");
   }
 
+  if (do_idfile) {
+    idfile_token = make_token(idfile_name);
+
+    idfile = fopen(idfile_name, "w");
+    if (! idfile) {
+      fprintf(stderr, "Could not open %s for output\n", idfile_name);
+      return 1;
+    }
+
+    fprintf(idfile, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
+    fprintf(idfile, "from %s - Do not edit ***/\n\n", input_name);
+    fprintf(idfile, "#include <rpc.h>\n");
+    fprintf(idfile, "#include <rpcndr.h>\n\n");
+    fprintf(idfile, "#define INITGUID\n");
+    fprintf(idfile, "#include <guiddef.h>\n\n");
+    fprintf(idfile, "#ifdef __cplusplus\n");
+    fprintf(idfile, "extern \"C\" {\n");
+    fprintf(idfile, "#endif\n\n");
+  }
+
   ret = yyparse();
 
   if(do_header) {
@@ -359,6 +395,15 @@ #endif
     fclose(header);
   }
 
+  if (do_idfile) {
+    fprintf(idfile, "\n");
+    fprintf(idfile, "#ifdef __cplusplus\n");
+    fprintf(idfile, "}\n");
+    fprintf(idfile, "#endif\n");
+
+    fclose(idfile);
+  }
+
   fclose(yyin);
 
   if(ret) {
@@ -367,6 +412,7 @@ #endif
   header_name = NULL;
   client_name = NULL;
   server_name = NULL;
+  idfile_name = NULL;
   return 0;
 }
 
diff --git a/tools/widl/widl.h b/tools/widl/widl.h
index d41ca70..9357450 100644
--- a/tools/widl/widl.h
+++ b/tools/widl/widl.h
@@ -43,6 +43,7 @@ extern int do_typelib;
 extern int do_proxies;
 extern int do_client;
 extern int do_server;
+extern int do_idfile;
 extern int old_names;
 
 extern char *input_name;
@@ -60,6 +61,7 @@ extern int line_number;
 extern int char_number;
 
 extern FILE* header;
+extern FILE* idfile;
 
 extern void write_proxies(ifref_t *ifaces);
 extern void write_client(ifref_t *ifaces);



More information about the wine-patches mailing list