widl: Add a --local-stubs option.
Dan Hipschman
dsh at linux.ucla.edu
Mon Oct 29 21:17:23 CDT 2007
This patch adds a --local-stubs=file option to WIDL. This is *extremely*
convenient when there are a lot of call_as/local methods in a proxy file
and you need to write implementations for them (empty or otherwise). As
you can see, my next ten or so patches would be *much* more tedious with-
out this. I've also updated the man page.
---
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..d148bad 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_FAIL;\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_FAIL;\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