widl [2/3]: Generate dlldata files. [take 2]

Dan Hipschman dsh at linux.ucla.edu
Mon Oct 15 20:07:04 CDT 2007


This patch is basically the same as the one I sent Saturday, but instead
of introducing a new global, have_object, it uses the need_proxy function
from the previous patch.

---
 tools/widl/parser.y |    7 +--
 tools/widl/utils.c  |    8 ++
 tools/widl/utils.h  |    1 +
 tools/widl/widl.c   |  189 +++++++++++++++++++++++++++++++++++++++++++++++----
 tools/widl/widl.h   |    3 +
 5 files changed, 190 insertions(+), 18 deletions(-)

diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index afab0d2..e61ac90 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -288,6 +288,7 @@ input:   gbl_statements				{ fix_incomplete();
 						  write_proxies($1);
 						  write_client($1);
 						  write_server($1);
+						  write_dlldata($1);
 						}
 	;
 
@@ -2020,11 +2021,7 @@ static char *gen_name(void)
   {
     char *dst = dup_basename(input_name, ".idl");
     file_id = dst;
-
-    for (; *dst; ++dst)
-      if (! isalnum((unsigned char) *dst))
-        *dst = '_';
-
+    make_filename_c_identifier(dst);
     size = sizeof format - 7 + strlen(file_id) + 8;
   }
 
diff --git a/tools/widl/utils.c b/tools/widl/utils.c
index 007d1cb..4cc4763 100644
--- a/tools/widl/utils.c
+++ b/tools/widl/utils.c
@@ -153,6 +153,14 @@ char *dup_basename(const char *name, const char *ext)
 	return base;
 }
 
+void make_filename_c_identifier(char *name)
+{
+    char *s = name;
+    for (; *s; ++s)
+        if (!isalnum((unsigned char) *s))
+            *s = '_';
+}
+
 void *xmalloc(size_t size)
 {
     void *res;
diff --git a/tools/widl/utils.h b/tools/widl/utils.h
index aa1d6b4..ed8ac1a 100644
--- a/tools/widl/utils.h
+++ b/tools/widl/utils.h
@@ -41,6 +41,7 @@ void warning(const char *s, ...) __attribute__((format (printf, 1, 2)));
 void chat(const char *s, ...) __attribute__((format (printf, 1, 2)));
 
 char *dup_basename(const char *name, const char *ext);
+void make_filename_c_identifier(char *name);
 
 UUID *parse_uuid(const char *u);
 int is_valid_uuid(const char *s);
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index c5e9d40..d4ecdb3 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -22,6 +22,7 @@
 #include "config.h"
 #include "wine/port.h"
 
+#include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -55,6 +56,8 @@ static const char usage[] =
 "   -C file     Name of client stub file (default is infile_c.c)\n"
 "   -d n        Set debug level to 'n'\n"
 "   -D id[=val] Define preprocessor identifier id=val\n"
+"   --dlldata   Generate dlldata file\n"
+"   --dlldata-file=file  Name of dlldata file (default is dlldata.c)\n"
 "   -E          Preprocess only\n"
 "   -h          Generate headers\n"
 "   -H file     Name of header file (default is infile.h)\n"
@@ -99,6 +102,7 @@ int do_proxies = 0;
 int do_client = 0;
 int do_server = 0;
 int do_idfile = 0;
+int do_dlldata = 0;
 int no_preprocess = 0;
 int old_names = 0;
 
@@ -106,6 +110,7 @@ char *input_name;
 char *header_name;
 char *header_token;
 char *typelib_name;
+char *dlldata_name;
 char *proxy_name;
 char *proxy_token;
 char *client_name;
@@ -128,6 +133,8 @@ time_t now;
 
 enum {
     OLDNAMES_OPTION = CHAR_MAX + 1,
+    DLLDATA_OPTION,
+    DLLDATA_FILE_OPTION,
     PREFIX_ALL_OPTION,
     PREFIX_CLIENT_OPTION,
     PREFIX_SERVER_OPTION
@@ -136,6 +143,8 @@ enum {
 static const char short_options[] =
     "cC:d:D:EhH:I:NpP:sS:tT:uU:VW";
 static const struct option long_options[] = {
+    { "dlldata", no_argument, 0, DLLDATA_OPTION },
+    { "dlldata-file", required_argument, 0, DLLDATA_FILE_OPTION },
     { "oldnames", no_argument, 0, OLDNAMES_OPTION },
     { "prefix-all", required_argument, 0, PREFIX_ALL_OPTION },
     { "prefix-client", required_argument, 0, PREFIX_CLIENT_OPTION },
@@ -177,6 +186,152 @@ static void exit_on_signal( int sig )
     exit(1);  /* this will call the atexit functions */
 }
 
+static 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)
+{
+  fprintf(fp, "#ifdef __cplusplus\n");
+  fprintf(fp, "}\n");
+  fprintf(fp, "#endif\n\n");
+}
+
+typedef struct
+{
+  char *filename;
+  struct list link;
+} filename_node_t;
+
+static void add_filename_node(struct list *list, const char *name)
+{
+  filename_node_t *node = xmalloc(sizeof *node);
+  node->filename = xstrdup(name);
+  list_add_tail(list, &node->link);
+}
+
+static void free_filename_nodes(struct list *list)
+{
+  filename_node_t *node, *next;
+  LIST_FOR_EACH_ENTRY_SAFE(node, next, list, filename_node_t, link) {
+    list_remove(&node->link);
+    free(node->filename);
+    free(node);
+  }
+}
+
+static char *eat_space(char *s)
+{
+  while (isspace((unsigned char) *s))
+    ++s;
+  return s;
+}
+
+static int is_c_ident(const char *s)
+{
+  if (!isalpha((unsigned char) *s) && *s != '_')
+    return FALSE;
+  while (*++s)
+    if (!isalnum((unsigned char) *s) && *s != '_')
+      return FALSE;
+  return TRUE;
+}
+
+void write_dlldata(ifref_list_t *ifaces)
+{
+  struct list filenames = LIST_INIT(filenames);
+  filename_node_t *node;
+  char *own_filename;
+  FILE *dlldata;
+
+  if (!do_dlldata)
+    return;
+  if (do_everything && !need_proxy_file(ifaces))
+    return;
+
+  dlldata = fopen(dlldata_name, "r");
+  if (dlldata) {
+    /* The longest possible line in this file should be the length of the
+       longest possible filename (not counting path components), plus some
+       small constant.  This should be plenty long, and we do check.  */
+    static char line[1024];
+    static char marker[] = "REFERENCE_PROXY_FILE";
+    int lineno = 0;
+
+    while (fgets(line, sizeof line - 1, dlldata)) {
+      char c, *start, *end;
+      ++lineno;
+      /* Sanity check, make sure we got the whole line.  */
+      c = line[sizeof line - 2];
+      if (c != '\0' && c != '\n')
+        error("couldn't parse %s (line %d): unexpectedly long line\n",
+              dlldata_name, lineno);
+
+      start = eat_space(line);
+      if (strncmp(start, marker, sizeof marker - 1) == 0) {
+        start = eat_space(start + sizeof marker - 1);
+        if (*start != '(')
+          continue;
+        end = start = eat_space(start + 1);
+        while (*end && *end != ')')
+          ++end;
+        if (*end != ')')
+          continue;
+        while (isspace((unsigned char) end[-1]))
+          --end;
+        *end = '\0';
+        if (start < end && is_c_ident(start))
+          add_filename_node(&filenames, start);
+      }
+    }
+
+    if (ferror(dlldata))
+      error("couldn't read from %s: %s\n", dlldata_name, strerror(errno));
+
+    fclose(dlldata);
+  }
+
+  own_filename = dup_basename(input_name, ".idl");
+  make_filename_c_identifier(own_filename);
+  LIST_FOR_EACH_ENTRY(node, &filenames, filename_node_t, link)
+    if (strcmp(own_filename, node->filename) == 0) {
+      /* We're already in the list, no need to regenerate this file.  */
+      free(own_filename);
+      free_filename_nodes(&filenames);
+      return;
+    }
+
+  add_filename_node(&filenames, own_filename);
+  free(own_filename);
+
+  dlldata = fopen(dlldata_name, "w");
+  if (!dlldata)
+    error("couldn't open %s: %s\n", dlldata_name, strerror(errno));
+
+  fprintf(dlldata, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
+  fprintf(dlldata, "- Do not edit ***/\n\n");
+  fprintf(dlldata, "#include <rpcproxy.h>\n\n");
+  start_cplusplus_guard(dlldata);
+
+  LIST_FOR_EACH_ENTRY(node, &filenames, filename_node_t, link)
+    fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", node->filename);
+
+  fprintf(dlldata, "\nPROXYFILE_LIST_START\n");
+  fprintf(dlldata, "/* Start of list */\n");
+  LIST_FOR_EACH_ENTRY(node, &filenames, filename_node_t, link)
+    fprintf(dlldata, "  REFERENCE_PROXY_FILE(%s),\n", node->filename);
+  fprintf(dlldata, "/* End of list */\n");
+  fprintf(dlldata, "PROXYFILE_LIST_END\n\n");
+
+  fprintf(dlldata, "DLLDATA_ROUTINES(aProxyFileList, GET_DLL_CLSID)\n\n");
+  end_cplusplus_guard(dlldata);
+  fclose(dlldata);
+  free_filename_nodes(&filenames);
+}
+
 int main(int argc,char *argv[])
 {
   extern char* optarg;
@@ -195,6 +350,13 @@ int main(int argc,char *argv[])
 
   while((optc = getopt_long(argc, argv, short_options, long_options, &opti)) != EOF) {
     switch(optc) {
+    case DLLDATA_OPTION:
+      do_everything = 0;
+      do_dlldata = 1;
+      break;
+    case DLLDATA_FILE_OPTION:
+      dlldata_name = xstrdup(optarg);
+      break;
     case OLDNAMES_OPTION:
       old_names = 1;
       break;
@@ -279,7 +441,13 @@ int main(int argc,char *argv[])
   }
 
   if(do_everything) {
-      do_header = do_typelib = do_proxies = do_client = do_server = do_idfile = 1;
+    do_header = 1;
+    do_typelib = 1;
+    do_proxies = 1;
+    do_client = 1;
+    do_server = 1;
+    do_idfile = 1;
+    do_dlldata = 1;
   }
   if(optind < argc) {
     input_name = xstrdup(argv[optind]);
@@ -332,6 +500,9 @@ int main(int argc,char *argv[])
     strcat(idfile_name, "_i.c");
   }
 
+  if (!dlldata_name && do_dlldata)
+    dlldata_name = xstrdup("dlldata.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");
@@ -378,9 +549,7 @@ int main(int argc,char *argv[])
     fprintf(header, "#include <rpcndr.h>\n\n" );
     fprintf(header, "#ifndef __WIDL_%s\n", header_token);
     fprintf(header, "#define __WIDL_%s\n", header_token);
-    fprintf(header, "#ifdef __cplusplus\n");
-    fprintf(header, "extern \"C\" {\n");
-    fprintf(header, "#endif\n");
+    start_cplusplus_guard(header);
   }
 
   if (do_idfile) {
@@ -397,9 +566,7 @@ int main(int argc,char *argv[])
     fprintf(idfile, "#include <rpc.h>\n");
     fprintf(idfile, "#include <rpcndr.h>\n\n");
     fprintf(idfile, "#include <initguid.h>\n\n");
-    fprintf(idfile, "#ifdef __cplusplus\n");
-    fprintf(idfile, "extern \"C\" {\n");
-    fprintf(idfile, "#endif\n\n");
+    start_cplusplus_guard(idfile);
   }
 
   init_types();
@@ -413,18 +580,14 @@ int main(int argc,char *argv[])
     fprintf(header, "\n");
     fprintf(header, "/* End additional prototypes */\n");
     fprintf(header, "\n");
-    fprintf(header, "#ifdef __cplusplus\n");
-    fprintf(header, "}\n");
-    fprintf(header, "#endif\n");
+    end_cplusplus_guard(header);
     fprintf(header, "#endif /* __WIDL_%s */\n", header_token);
     fclose(header);
   }
 
   if (do_idfile) {
     fprintf(idfile, "\n");
-    fprintf(idfile, "#ifdef __cplusplus\n");
-    fprintf(idfile, "}\n");
-    fprintf(idfile, "#endif\n");
+    end_cplusplus_guard(idfile);
 
     fclose(idfile);
   }
diff --git a/tools/widl/widl.h b/tools/widl/widl.h
index a2b905c..4496a81 100644
--- a/tools/widl/widl.h
+++ b/tools/widl/widl.h
@@ -43,11 +43,13 @@ extern int do_proxies;
 extern int do_client;
 extern int do_server;
 extern int do_idfile;
+extern int do_dlldata;
 extern int old_names;
 
 extern char *input_name;
 extern char *header_name;
 extern char *typelib_name;
+extern char *dlldata_name;
 extern char *proxy_name;
 extern char *proxy_token;
 extern char *client_name;
@@ -67,5 +69,6 @@ extern FILE* idfile;
 extern void write_proxies(ifref_list_t *ifaces);
 extern void write_client(ifref_list_t *ifaces);
 extern void write_server(ifref_list_t *ifaces);
+extern void write_dlldata(ifref_list_t *ifaces);
 
 #endif



More information about the wine-patches mailing list