widl: Add a --local-stubs option. [take 2]

Dan Hipschman dsh at linux.ucla.edu
Tue Oct 30 21:07:36 CDT 2007


This is the same as the patch sent yesterday:
http://www.winehq.org/pipermail/wine-patches/2007-October/045937.html
except it makes the generated stubs with HRESULT type return E_NOTIMPL
by default instead of E_FAIL (suggested by Rob).

---
 tools/widl/header.c    |   75 ++++++++++++++++++++++++++++++++++++-----------
 tools/widl/header.h    |    1 +
 tools/widl/parser.y    |    2 +
 tools/widl/widl.c      |   28 ++++++++++++++++++
 tools/widl/widl.h      |    2 +
 tools/widl/widl.man.in |    7 ++++-
 6 files changed, 96 insertions(+), 19 deletions(-)

diff --git a/tools/widl/header.c b/tools/widl/header.c
index 40fda80..7d224fe 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -702,7 +702,6 @@ static void write_method_proto(const type_t *iface)
   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
   {
     const var_t *def = cur->def;
-    const var_t *cas = is_callas(def->attrs);
 
     if (!is_local(def->attrs)) {
       /* proxy prototype */
@@ -721,30 +720,69 @@ static void write_method_proto(const type_t *iface)
       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
       fprintf(header, "    DWORD* pdwStubPhase);\n");
     }
+  }
+}
+
+void write_locals(FILE *fp, const type_t *iface, int body)
+{
+  static const char comment[]
+    = "/* WIDL-generated stub.  You must provide an implementation for this.  */";
+  const func_list_t *funcs = iface->funcs;
+  const func_t *cur;
+
+  if (!is_object(iface->attrs) || !funcs)
+    return;
+
+  LIST_FOR_EACH_ENTRY(cur, funcs, const func_t, entry) {
+    const var_t *def = cur->def;
+    const var_t *cas = is_callas(def->attrs);
+
     if (cas) {
       const func_t *m;
-      LIST_FOR_EACH_ENTRY( m, iface->funcs, const func_t, entry )
-          if (!strcmp(m->def->name, cas->name)) break;
+      LIST_FOR_EACH_ENTRY(m, iface->funcs, const func_t, entry)
+        if (!strcmp(m->def->name, cas->name))
+          break;
       if (&m->entry != iface->funcs) {
         const var_t *mdef = m->def;
         /* proxy prototype - use local prototype */
-        write_type_decl_left(header, mdef->type);
-        fprintf(header, " CALLBACK %s_", iface->name);
-        write_name(header, mdef);
-        fprintf(header, "_Proxy(\n");
-        write_args(header, m->args, iface->name, 1, TRUE);
-        fprintf(header, ");\n");
+        write_type_decl_left(fp, mdef->type);
+        fprintf(fp, " CALLBACK %s_", iface->name);
+        write_name(fp, mdef);
+        fprintf(fp, "_Proxy(\n");
+        write_args(fp, m->args, iface->name, 1, TRUE);
+        fprintf(fp, ")");
+        if (body) {
+          type_t *rt = mdef->type;
+          fprintf(fp, "\n{\n");
+          fprintf(fp, "    %s\n", comment);
+          if (rt->name && strcmp(rt->name, "HRESULT") == 0)
+            fprintf(fp, "    return E_NOTIMPL;\n");
+          else if (rt->type) {
+            fprintf(fp, "    ");
+            write_type_decl(fp, rt, "rv");
+            fprintf(fp, ";\n");
+            fprintf(fp, "    memset(&rv, 0, sizeof rv);\n");
+            fprintf(fp, "    return rv;\n");
+          }
+          fprintf(fp, "}\n\n");
+        }
+        else
+          fprintf(fp, ";\n");
         /* stub prototype - use remotable prototype */
-        write_type_decl_left(header, def->type);
-        fprintf(header, " __RPC_STUB %s_", iface->name);
-        write_name(header, mdef);
-        fprintf(header, "_Stub(\n");
-        write_args(header, cur->args, iface->name, 1, TRUE);
-        fprintf(header, ");\n");
-      }
-      else {
-        parser_warning("invalid call_as attribute (%s -> %s)\n", def->name, cas->name);
+        write_type_decl_left(fp, def->type);
+        fprintf(fp, " __RPC_STUB %s_", iface->name);
+        write_name(fp, mdef);
+        fprintf(fp, "_Stub(\n");
+        write_args(fp, cur->args, iface->name, 1, TRUE);
+        fprintf(fp, ")");
+        if (body)
+          /* Remotable methods must all return HRESULTs.  */
+          fprintf(fp, "\n{\n    %s\n    return E_NOTIMPL;\n}\n\n", comment);
+        else
+          fprintf(fp, ";\n");
       }
+      else
+        error_loc("invalid call_as attribute (%s -> %s)\n", def->name, cas->name);
     }
   }
 }
@@ -894,6 +932,7 @@ static void write_com_interface(type_t *iface)
   fprintf(header, "#endif\n");
   fprintf(header, "\n");
   write_method_proto(iface);
+  write_locals(header, iface, FALSE);
   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
 }
 
diff --git a/tools/widl/header.h b/tools/widl/header.h
index 312b757..47564de 100644
--- a/tools/widl/header.h
+++ b/tools/widl/header.h
@@ -50,6 +50,7 @@ extern void write_array(FILE *h, array_dims_t *v, int field);
 extern void write_forward(type_t *iface);
 extern void write_interface(type_t *iface);
 extern void write_dispinterface(type_t *iface);
+extern void write_locals(FILE *fp, const type_t *iface, int body);
 extern void write_coclass(type_t *cocl);
 extern void write_coclass_forward(type_t *cocl);
 extern void write_typedef(type_t *type);
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 11ddd45..3d643c1 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -816,6 +816,7 @@ interfacedef: interfacehdr inherit
 						  $$->funcs = $4;
 						  compute_method_indexes($$);
 						  if (!parse_only && do_header) write_interface($$);
+						  if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
 						  if (!parse_only && do_idfile) write_iid($$);
 						  pointer_default = $1.old_pointer_default;
 						}
@@ -828,6 +829,7 @@ interfacedef: interfacehdr inherit
 						  $$->funcs = $6;
 						  compute_method_indexes($$);
 						  if (!parse_only && do_header) write_interface($$);
+						  if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
 						  if (!parse_only && do_idfile) write_iid($$);
 						  pointer_default = $1.old_pointer_default;
 						}
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index 37f1a5e..0dcc069 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -62,6 +62,7 @@ static const char usage[] =
 "   -h          Generate headers\n"
 "   -H file     Name of header file (default is infile.h)\n"
 "   -I path     Set include search dir to path (multiple -I allowed)\n"
+"   --local-stubs=file  Write empty stubs for call_as/local methods to file\n"
 "   -N          Do not preprocess input\n"
 "   --oldnames  Use old naming conventions\n"
 "   -p          Generate proxy\n"
@@ -108,6 +109,7 @@ int old_names = 0;
 
 char *input_name;
 char *header_name;
+char *local_stubs_name;
 char *header_token;
 char *typelib_name;
 char *dlldata_name;
@@ -126,6 +128,7 @@ const char *prefix_server = "";
 int line_number = 1;
 
 FILE *header;
+FILE *local_stubs;
 FILE *proxy;
 FILE *idfile;
 
@@ -135,6 +138,7 @@ enum {
     OLDNAMES_OPTION = CHAR_MAX + 1,
     DLLDATA_OPTION,
     DLLDATA_ONLY_OPTION,
+    LOCAL_STUBS_OPTION,
     PREFIX_ALL_OPTION,
     PREFIX_CLIENT_OPTION,
     PREFIX_SERVER_OPTION
@@ -145,6 +149,7 @@ static const char short_options[] =
 static const struct option long_options[] = {
     { "dlldata", required_argument, 0, DLLDATA_OPTION },
     { "dlldata-only", no_argument, 0, DLLDATA_ONLY_OPTION },
+    { "local-stubs", required_argument, 0, LOCAL_STUBS_OPTION },
     { "oldnames", no_argument, 0, OLDNAMES_OPTION },
     { "prefix-all", required_argument, 0, PREFIX_ALL_OPTION },
     { "prefix-client", required_argument, 0, PREFIX_CLIENT_OPTION },
@@ -350,6 +355,10 @@ int main(int argc,char *argv[])
       do_everything = 0;
       do_dlldata = 1;
       break;
+    case LOCAL_STUBS_OPTION:
+      do_everything = 0;
+      local_stubs_name = xstrdup(optarg);
+      break;
     case OLDNAMES_OPTION:
       old_names = 1;
       break;
@@ -554,6 +563,17 @@ int main(int argc,char *argv[])
     start_cplusplus_guard(header);
   }
 
+  if (local_stubs_name) {
+    local_stubs = fopen(local_stubs_name, "w");
+    if (!local_stubs) {
+      fprintf(stderr, "Could not open %s for output\n", local_stubs_name);
+      return 1;
+    }
+    fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name);
+    fprintf(local_stubs, "#include <objbase.h>\n");
+    fprintf(local_stubs, "#include \"%s\"\n\n", header_name);
+  }
+
   if (do_idfile) {
     idfile_token = make_token(idfile_name);
 
@@ -587,6 +607,10 @@ int main(int argc,char *argv[])
     fclose(header);
   }
 
+  if (local_stubs) {
+    fclose(local_stubs);
+  }
+
   if (do_idfile) {
     fprintf(idfile, "\n");
     end_cplusplus_guard(idfile);
@@ -602,6 +626,8 @@ int main(int argc,char *argv[])
 
   /* Everything has been done successfully, don't delete any files.  */
   set_everything(FALSE);
+  local_stubs_name = NULL;
+
   return 0;
 }
 
@@ -612,6 +638,8 @@ static void rm_tempfile(void)
     unlink(temp_name);
   if (do_header)
     unlink(header_name);
+  if (local_stubs_name)
+    unlink(local_stubs_name);
   if (do_client)
     unlink(client_name);
   if (do_server)
diff --git a/tools/widl/widl.h b/tools/widl/widl.h
index 4496a81..924b67a 100644
--- a/tools/widl/widl.h
+++ b/tools/widl/widl.h
@@ -48,6 +48,7 @@ extern int old_names;
 
 extern char *input_name;
 extern char *header_name;
+extern char *local_stubs_name;
 extern char *typelib_name;
 extern char *dlldata_name;
 extern char *proxy_name;
@@ -64,6 +65,7 @@ extern int line_number;
 extern int char_number;
 
 extern FILE* header;
+extern FILE* local_stubs;
 extern FILE* idfile;
 
 extern void write_proxies(ifref_list_t *ifaces);
diff --git a/tools/widl/widl.man.in b/tools/widl/widl.man.in
index 61749d8..81c6e40 100644
--- a/tools/widl/widl.man.in
+++ b/tools/widl/widl.man.in
@@ -12,7 +12,7 @@ widl \- Wine Interface Definition Language (IDL) compiler
 When no options are used the program will generate a header file, and possibly
 client and server stubs, proxy and dlldata files, a typelib, and a UUID file,
 depending on the contents of the IDL file.  If any of the options \fB-c\fR,
-\fB-h\fR, \fB-p\fR, \fB-s\fR, \fB-t\fR, or \fB-u\fR are given,
+\fB-h\fR, \fB-p\fR, \fB-s\fR, \fB-t\fR, \fB-u\fR, or \fB--local-stubs\fR are given,
 .B widl
 will only generate the requested files, and no others.  When run with
 \fB--dlldata-only\fR, widl will only generate a dlldata file, and it will
@@ -98,6 +98,11 @@ Set debug level to the nonnegative integer \fIn\fR.  If
 prefixed with \fB0x\fR, it will be interpretted as a hexidecimal
 number.  For the meaning of values, see the \fBDebug\fR section.
 .PP
+.B Miscellaneous options:
+.IP "\fB--local-stubs=\fIfile\fR"
+Generate empty stubs for call_as/local methods in an object interface and
+write them to \fIfile\fR.
+.PP
 .SH Debug
 Debug level \fIn\fR is a bitmask with the following meaning:
     * 0x01 Tell which resource is parsed (verbose mode)



More information about the wine-patches mailing list