widl [2/4]: Generate dlldata files. [take 4]
Dan Hipschman
dsh at linux.ucla.edu
Wed Oct 17 20:03:57 CDT 2007
This gets widl to act like midl by default: It incrementally adds to the
dlldata file. I've also changed the --dlldata-file option to just --dlldata
since midl uses /dlldata to specify the name and it seemed less confusing to
use the same thing. However, this time I've added a --dlldata-only option
that takes a list of names and will generate the dlldata file from them.
For example: "widl --dlldata-only foo bar baz" will generate the dlldata
file with foo, bar, and baz in the list. This should fit into the Makefile
(something like "widl --dlldata-only $(IDL_P_SRCS:.idl=)".
---
tools/widl/parser.y | 1 +
tools/widl/utils.c | 29 ++++++++
tools/widl/utils.h | 1 +
tools/widl/widl.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++----
tools/widl/widl.h | 3 +
5 files changed, 202 insertions(+), 13 deletions(-)
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index afab0d2..96e9891 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);
}
;
diff --git a/tools/widl/utils.c b/tools/widl/utils.c
index 007d1cb..68b74b4 100644
--- a/tools/widl/utils.c
+++ b/tools/widl/utils.c
@@ -153,6 +153,35 @@ char *dup_basename(const char *name, const char *ext)
return base;
}
+size_t widl_getline(char **linep, size_t *lenp, FILE *fp)
+{
+ char *line = *linep;
+ size_t len = *lenp;
+ size_t n = 0;
+
+ if (!line)
+ {
+ len = 64;
+ line = xmalloc(len);
+ }
+
+ while (fgets(&line[n], len - n, fp))
+ {
+ n += strlen(&line[n]);
+ if (line[n - 1] == '\n')
+ break;
+ else if (n == len - 1)
+ {
+ len *= 2;
+ line = xrealloc(line, len);
+ }
+ }
+
+ *linep = line;
+ *lenp = len;
+ return n;
+}
+
void *xmalloc(size_t size)
{
void *res;
diff --git a/tools/widl/utils.h b/tools/widl/utils.h
index aa1d6b4..c4dbb31 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);
+size_t widl_getline(char **linep, size_t *lenp, FILE *fp);
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 094195a..53c9e29 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>
@@ -51,10 +52,12 @@
static const char usage[] =
"Usage: widl [options...] infile.idl\n"
+" or: widl [options...] --dlldata-only name1 [name2...]\n"
" -c Generate client stub\n"
" -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=file Name of the 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_ONLY_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", required_argument, 0, DLLDATA_OPTION },
+ { "dlldata-only", no_argument, 0, DLLDATA_ONLY_OPTION },
{ "oldnames", no_argument, 0, OLDNAMES_OPTION },
{ "prefix-all", required_argument, 0, PREFIX_ALL_OPTION },
{ "prefix-client", required_argument, 0, PREFIX_CLIENT_OPTION },
@@ -185,6 +194,135 @@ static void set_everything(int x)
do_client = x;
do_server = x;
do_idfile = x;
+ do_dlldata = x;
+}
+
+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 void write_dlldata_list(struct list *filenames)
+{
+ FILE *dlldata;
+ filename_node_t *node;
+
+ 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 <objbase.h>\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);
+}
+
+static char *eat_space(char *s)
+{
+ while (isspace((unsigned char) *s))
+ ++s;
+ return s;
+}
+
+void write_dlldata(ifref_list_t *ifaces)
+{
+ struct list filenames = LIST_INIT(filenames);
+ filename_node_t *node;
+ FILE *dlldata;
+
+ if (!do_dlldata || !need_proxy_file(ifaces))
+ return;
+
+ dlldata = fopen(dlldata_name, "r");
+ if (dlldata) {
+ static char marker[] = "REFERENCE_PROXY_FILE";
+ char *line = NULL;
+ size_t len = 0;
+
+ while (widl_getline(&line, &len, dlldata)) {
+ char *start, *end;
+ 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)
+ add_filename_node(&filenames, start);
+ }
+ }
+
+ if (ferror(dlldata))
+ error("couldn't read from %s: %s\n", dlldata_name, strerror(errno));
+
+ free(line);
+ fclose(dlldata);
+ }
+
+ LIST_FOR_EACH_ENTRY(node, &filenames, filename_node_t, link)
+ if (strcmp(proxy_token, node->filename) == 0) {
+ /* We're already in the list, no need to regenerate this file. */
+ free_filename_nodes(&filenames);
+ return;
+ }
+
+ add_filename_node(&filenames, proxy_token);
+ write_dlldata_list(&filenames);
+ free_filename_nodes(&filenames);
}
int main(int argc,char *argv[])
@@ -205,6 +343,13 @@ int main(int argc,char *argv[])
while((optc = getopt_long(argc, argv, short_options, long_options, &opti)) != EOF) {
switch(optc) {
+ case DLLDATA_OPTION:
+ dlldata_name = xstrdup(optarg);
+ break;
+ case DLLDATA_ONLY_OPTION:
+ do_everything = 0;
+ do_dlldata = 1;
+ break;
case OLDNAMES_OPTION:
old_names = 1;
break;
@@ -291,8 +436,26 @@ int main(int argc,char *argv[])
if(do_everything) {
set_everything(TRUE);
}
+
+ if (!dlldata_name && do_dlldata)
+ dlldata_name = xstrdup("dlldata.c");
+
if(optind < argc) {
- input_name = xstrdup(argv[optind]);
+ if (do_dlldata && !do_everything) {
+ struct list filenames = LIST_INIT(filenames);
+ for ( ; optind < argc; ++optind)
+ add_filename_node(&filenames, argv[optind]);
+
+ write_dlldata_list(&filenames);
+ free_filename_nodes(&filenames);
+ return 0;
+ }
+ else if (optind != argc - 1) {
+ fprintf(stderr, "%s", usage);
+ return 1;
+ }
+ else
+ input_name = xstrdup(argv[optind]);
}
else {
fprintf(stderr, usage);
@@ -388,9 +551,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) {
@@ -407,9 +568,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();
@@ -423,18 +582,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