widl: Default to fully interpreted stubs mode.
[wine.git] / tools / widl / widl.c
blobef68259157b4976227b6fbb7be479c6f273c3bac
1 /*
2 * IDL Compiler
4 * Copyright 2002 Ove Kaaven
5 * based on WRC code by Bertho Stultiens
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #include <errno.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <ctype.h>
31 #include <limits.h>
32 #include <sys/types.h>
34 #include "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "wpp_private.h"
38 #include "header.h"
40 static const char usage[] =
41 "Usage: widl [options...] infile.idl\n"
42 " or: widl [options...] --dlldata-only name1 [name2...]\n"
43 " --acf=file Use ACF file\n"
44 " --align=n Set structure packing to 'n'\n"
45 " -app_config Ignored, present for midl compatibility\n"
46 " -b arch Set the target architecture\n"
47 " -c Generate client stub\n"
48 " -d n Set debug level to 'n'\n"
49 " -D id[=val] Define preprocessor identifier id=val\n"
50 " -E Preprocess only\n"
51 " --help Display this help and exit\n"
52 " -h Generate headers\n"
53 " -H file Name of header file (default is infile.h)\n"
54 " -I directory Add directory to the include search path (multiple -I allowed)\n"
55 " -L directory Add directory to the library search path (multiple -L allowed)\n"
56 " --local-stubs=file Write empty stubs for call_as/local methods to file\n"
57 " -m32, -m64 Set the target architecture (Win32 or Win64)\n"
58 " -N Do not preprocess input\n"
59 " --nostdinc Do not search the standard include path\n"
60 " --ns_prefix Prefix namespaces with ABI namespace\n"
61 " --oldnames Use old naming conventions\n"
62 " --oldtlb Generate typelib in the old format (SLTG)\n"
63 " -o, --output=NAME Set the output file name\n"
64 " -Otype Type of stubs to generate (-Os, -Oi, -Oif)\n"
65 " -p Generate proxy\n"
66 " --packing=n Set structure packing to 'n'\n"
67 " --prefix-all=p Prefix names of client stubs / server functions with 'p'\n"
68 " --prefix-client=p Prefix names of client stubs with 'p'\n"
69 " --prefix-server=p Prefix names of server functions with 'p'\n"
70 " -r Generate registration script\n"
71 " -robust Ignored, present for midl compatibility\n"
72 " --sysroot=DIR Prefix include paths with DIR\n"
73 " -s Generate server stub\n"
74 " -t Generate typelib\n"
75 " -u Generate interface identifiers file\n"
76 " -V Print version and exit\n"
77 " -W Enable pedantic warnings\n"
78 " --win32, --win64 Set the target architecture (Win32 or Win64)\n"
79 " --winrt Enable Windows Runtime mode\n"
80 "Debug level 'n' is a bitmask with following meaning:\n"
81 " * 0x01 Tell which resource is parsed (verbose mode)\n"
82 " * 0x02 Dump internal structures\n"
83 " * 0x04 Create a parser trace (yydebug=1)\n"
84 " * 0x08 Preprocessor messages\n"
85 " * 0x10 Preprocessor lex messages\n"
86 " * 0x20 Preprocessor yacc trace\n"
89 static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSION "\n"
90 "Copyright 2002 Ove Kaaven\n";
92 struct target target = { 0 };
94 int debuglevel = DEBUGLEVEL_NONE;
95 int parser_debug, yy_flex_debug;
97 int pedantic = 0;
98 int do_everything = 1;
99 static int preprocess_only = 0;
100 int do_header = 0;
101 int do_typelib = 0;
102 int do_proxies = 0;
103 int do_client = 0;
104 int do_server = 0;
105 int do_regscript = 0;
106 int do_idfile = 0;
107 int do_dlldata = 0;
108 static int no_preprocess = 0;
109 int old_names = 0;
110 int old_typelib = 0;
111 int winrt_mode = 0;
112 int interpreted_mode = 1;
113 int use_abi_namespace = 0;
114 static int stdinc = 1;
116 char *input_name;
117 char *idl_name;
118 char *acf_name;
119 char *header_name;
120 char *local_stubs_name;
121 char *header_token;
122 char *typelib_name;
123 char *dlldata_name;
124 char *proxy_name;
125 char *proxy_token;
126 char *client_name;
127 char *client_token;
128 char *server_name;
129 char *server_token;
130 char *regscript_name;
131 char *regscript_token;
132 static char *idfile_name;
133 struct strarray temp_files = { 0 };
134 const char *temp_dir = NULL;
135 const char *prefix_client = "";
136 const char *prefix_server = "";
137 static const char *includedir;
138 static const char *dlldir;
139 static struct strarray dlldirs;
140 static char *output_name;
141 static const char *sysroot = "";
143 static FILE *idfile;
145 unsigned int packing = 8;
146 unsigned int pointer_size = 0;
148 time_t now;
150 enum {
151 OLDNAMES_OPTION = CHAR_MAX + 1,
152 ACF_OPTION,
153 APP_CONFIG_OPTION,
154 DLLDATA_OPTION,
155 DLLDATA_ONLY_OPTION,
156 LOCAL_STUBS_OPTION,
157 NOSTDINC_OPTION,
158 OLD_TYPELIB_OPTION,
159 PACKING_OPTION,
160 PREFIX_ALL_OPTION,
161 PREFIX_CLIENT_OPTION,
162 PREFIX_SERVER_OPTION,
163 PRINT_HELP,
164 RT_NS_PREFIX,
165 RT_OPTION,
166 ROBUST_OPTION,
167 SYSROOT_OPTION,
168 WIN32_OPTION,
169 WIN64_OPTION,
172 static const char short_options[] =
173 "b:cC:d:D:EhH:I:L:m:No:O:pP:rsS:tT:uU:VW";
174 static const struct long_option long_options[] = {
175 { "acf", 1, ACF_OPTION },
176 { "align", 1, PACKING_OPTION },
177 { "app_config", 0, APP_CONFIG_OPTION },
178 { "dlldata", 1, DLLDATA_OPTION },
179 { "dlldata-only", 0, DLLDATA_ONLY_OPTION },
180 { "help", 0, PRINT_HELP },
181 { "local-stubs", 1, LOCAL_STUBS_OPTION },
182 { "nostdinc", 0, NOSTDINC_OPTION },
183 { "ns_prefix", 0, RT_NS_PREFIX },
184 { "oldnames", 0, OLDNAMES_OPTION },
185 { "oldtlb", 0, OLD_TYPELIB_OPTION },
186 { "output", 0, 'o' },
187 { "packing", 1, PACKING_OPTION },
188 { "prefix-all", 1, PREFIX_ALL_OPTION },
189 { "prefix-client", 1, PREFIX_CLIENT_OPTION },
190 { "prefix-server", 1, PREFIX_SERVER_OPTION },
191 { "robust", 0, ROBUST_OPTION },
192 { "sysroot", 1, SYSROOT_OPTION },
193 { "target", 0, 'b' },
194 { "winrt", 0, RT_OPTION },
195 { "win32", 0, WIN32_OPTION },
196 { "win64", 0, WIN64_OPTION },
197 { NULL }
200 static void rm_tempfile(void);
202 static char *make_token(const char *name)
204 char *token;
205 int i;
207 token = get_basename( name );
208 for (i=0; token[i]; i++) {
209 if (!isalnum(token[i])) token[i] = '_';
210 else token[i] = tolower(token[i]);
212 return token;
215 /* duplicate a basename into a valid C token */
216 static char *dup_basename_token(const char *name, const char *ext)
218 char *p, *ret = replace_extension( get_basename(name), ext, "" );
219 /* map invalid characters to '_' */
220 for (p = ret; *p; p++) if (!isalnum(*p)) *p = '_';
221 return ret;
224 static void add_widl_version_define(void)
226 char version_str[32];
227 unsigned int version;
228 const char *p = PACKAGE_VERSION;
230 /* major */
231 version = atoi(p) * 0x10000;
232 p = strchr(p, '.');
234 /* minor */
235 if (p)
237 version += atoi(p + 1) * 0x100;
238 p = strchr(p + 1, '.');
241 /* build */
242 if (p)
243 version += atoi(p + 1);
245 sprintf(version_str, "__WIDL__=0x%x", version);
246 wpp_add_cmdline_define(version_str);
249 /* clean things up when aborting on a signal */
250 static void exit_on_signal( int sig )
252 exit(1); /* this will call the atexit functions */
255 static void set_everything(int x)
257 do_header = x;
258 do_typelib = x;
259 do_proxies = x;
260 do_client = x;
261 do_server = x;
262 do_regscript = x;
263 do_idfile = x;
264 do_dlldata = x;
267 void start_cplusplus_guard(FILE *fp)
269 fprintf(fp, "#ifdef __cplusplus\n");
270 fprintf(fp, "extern \"C\" {\n");
271 fprintf(fp, "#endif\n\n");
274 void end_cplusplus_guard(FILE *fp)
276 fprintf(fp, "#ifdef __cplusplus\n");
277 fprintf(fp, "}\n");
278 fprintf(fp, "#endif\n\n");
281 static void write_dlldata_list( struct strarray filenames, int define_proxy_delegation)
283 FILE *dlldata;
284 unsigned int i;
286 dlldata = fopen(dlldata_name, "w");
287 if (!dlldata)
288 error("couldn't open %s: %s\n", dlldata_name, strerror(errno));
290 fprintf(dlldata, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
291 fprintf(dlldata, "- Do not edit ***/\n\n");
292 if (define_proxy_delegation)
293 fprintf(dlldata, "#define PROXY_DELEGATION\n");
294 fprintf(dlldata, "#include <objbase.h>\n");
295 fprintf(dlldata, "#include <rpcproxy.h>\n\n");
296 start_cplusplus_guard(dlldata);
298 for (i = 0; i < filenames.count; i++)
299 fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", filenames.str[i]);
301 fprintf(dlldata, "\nPROXYFILE_LIST_START\n");
302 fprintf(dlldata, "/* Start of list */\n");
303 for (i = 0; i < filenames.count; i++)
304 fprintf(dlldata, " REFERENCE_PROXY_FILE(%s),\n", filenames.str[i]);
305 fprintf(dlldata, "/* End of list */\n");
306 fprintf(dlldata, "PROXYFILE_LIST_END\n\n");
308 fprintf(dlldata, "DLLDATA_ROUTINES(aProxyFileList, GET_DLL_CLSID)\n\n");
309 end_cplusplus_guard(dlldata);
310 fclose(dlldata);
313 static char *eat_space(char *s)
315 while (isspace((unsigned char) *s))
316 ++s;
317 return s;
320 void write_dlldata(const statement_list_t *stmts)
322 struct strarray filenames = empty_strarray;
323 int define_proxy_delegation = 0;
324 FILE *dlldata;
326 if (!do_dlldata || !need_proxy_file(stmts))
327 return;
329 define_proxy_delegation = need_proxy_delegation(stmts);
331 dlldata = fopen(dlldata_name, "r");
332 if (dlldata) {
333 static const char marker[] = "REFERENCE_PROXY_FILE";
334 static const char delegation_define[] = "#define PROXY_DELEGATION";
335 char *line = NULL;
336 size_t len = 0;
338 while (widl_getline(&line, &len, dlldata)) {
339 char *start, *end;
340 start = eat_space(line);
341 if (strncmp(start, marker, sizeof marker - 1) == 0) {
342 start = eat_space(start + sizeof marker - 1);
343 if (*start != '(')
344 continue;
345 end = start = eat_space(start + 1);
346 while (*end && *end != ')')
347 ++end;
348 if (*end != ')')
349 continue;
350 while (isspace((unsigned char) end[-1]))
351 --end;
352 *end = '\0';
353 if (start < end)
354 strarray_add(&filenames, replace_extension( get_basename( start ), ".idl", "" ));
355 }else if (!define_proxy_delegation && strncmp(start, delegation_define, sizeof(delegation_define)-1)) {
356 define_proxy_delegation = 1;
360 if (ferror(dlldata))
361 error("couldn't read from %s: %s\n", dlldata_name, strerror(errno));
363 free(line);
364 fclose(dlldata);
367 if (strarray_exists( &filenames, proxy_token ))
368 /* We're already in the list, no need to regenerate this file. */
369 return;
371 strarray_add(&filenames, proxy_token);
372 write_dlldata_list(filenames, define_proxy_delegation);
375 static void write_id_guid(FILE *f, const char *type, const char *guid_prefix, const char *name, const struct uuid *uuid)
377 if (!uuid) return;
378 fprintf(f, "MIDL_DEFINE_GUID(%s, %s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
379 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
380 type, guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
381 uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
382 uuid->Data4[6], uuid->Data4[7]);
385 static void write_id_data_stmts(const statement_list_t *stmts)
387 const statement_t *stmt;
388 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
390 if (stmt->type == STMT_TYPE)
392 const type_t *type = stmt->u.type;
393 if (type_get_type(type) == TYPE_INTERFACE)
395 const struct uuid *uuid;
396 if (!is_object(type) && !is_attr(type->attrs, ATTR_DISPINTERFACE))
397 continue;
398 uuid = get_attrp(type->attrs, ATTR_UUID);
399 write_id_guid(idfile, "IID", is_attr(type->attrs, ATTR_DISPINTERFACE) ? "DIID" : "IID",
400 type->name, uuid);
401 if (type_iface_get_async_iface(type))
403 uuid = get_attrp(type_iface_get_async_iface(type)->attrs, ATTR_UUID);
404 write_id_guid(idfile, "IID", "IID", type_iface_get_async_iface(type)->name, uuid);
407 else if (type_get_type(type) == TYPE_COCLASS)
409 const struct uuid *uuid = get_attrp(type->attrs, ATTR_UUID);
410 write_id_guid(idfile, "CLSID", "CLSID", type->name, uuid);
413 else if (stmt->type == STMT_LIBRARY)
415 const struct uuid *uuid = get_attrp(stmt->u.lib->attrs, ATTR_UUID);
416 write_id_guid(idfile, "IID", "LIBID", stmt->u.lib->name, uuid);
417 write_id_data_stmts(stmt->u.lib->stmts);
422 void write_id_data(const statement_list_t *stmts)
424 if (!do_idfile) return;
426 idfile = fopen(idfile_name, "w");
427 if (! idfile) {
428 error("Could not open %s for output\n", idfile_name);
429 return;
432 fprintf(idfile, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
433 fprintf(idfile, "from %s - Do not edit ***/\n\n", idl_name);
434 fprintf(idfile, "#include <rpc.h>\n");
435 fprintf(idfile, "#include <rpcndr.h>\n\n");
437 fprintf(idfile, "#ifdef _MIDL_USE_GUIDDEF_\n\n");
439 fprintf(idfile, "#ifndef INITGUID\n");
440 fprintf(idfile, "#define INITGUID\n");
441 fprintf(idfile, "#include <guiddef.h>\n");
442 fprintf(idfile, "#undef INITGUID\n");
443 fprintf(idfile, "#else\n");
444 fprintf(idfile, "#include <guiddef.h>\n");
445 fprintf(idfile, "#endif\n\n");
447 fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
448 fprintf(idfile, " DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\n\n");
450 fprintf(idfile, "#elif defined(__cplusplus)\n\n");
452 fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
453 fprintf(idfile, " EXTERN_C const type DECLSPEC_SELECTANY name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n");
455 fprintf(idfile, "#else\n\n");
457 fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
458 fprintf(idfile, " const type DECLSPEC_SELECTANY name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n");
460 fprintf(idfile, "#endif\n\n");
461 start_cplusplus_guard(idfile);
463 write_id_data_stmts(stmts);
465 fprintf(idfile, "\n");
466 end_cplusplus_guard(idfile);
467 fprintf(idfile, "#undef MIDL_DEFINE_GUID\n" );
469 fclose(idfile);
472 static void init_argv0_dir( const char *argv0 )
474 char *dir = get_argv0_dir( argv0 );
476 if (!dir) return;
477 includedir = strmake( "%s/%s", dir, BIN_TO_INCLUDEDIR );
478 dlldir = strmake( "%s/%s", dir, BIN_TO_DLLDIR );
481 static void option_callback( int optc, char *optarg )
483 switch (optc)
485 case DLLDATA_OPTION:
486 dlldata_name = xstrdup(optarg);
487 break;
488 case DLLDATA_ONLY_OPTION:
489 do_everything = 0;
490 do_dlldata = 1;
491 break;
492 case LOCAL_STUBS_OPTION:
493 do_everything = 0;
494 local_stubs_name = xstrdup(optarg);
495 break;
496 case NOSTDINC_OPTION:
497 stdinc = 0;
498 break;
499 case OLDNAMES_OPTION:
500 old_names = 1;
501 break;
502 case PREFIX_ALL_OPTION:
503 prefix_client = xstrdup(optarg);
504 prefix_server = xstrdup(optarg);
505 break;
506 case PREFIX_CLIENT_OPTION:
507 prefix_client = xstrdup(optarg);
508 break;
509 case PREFIX_SERVER_OPTION:
510 prefix_server = xstrdup(optarg);
511 break;
512 case PRINT_HELP:
513 fprintf(stderr, "%s", usage);
514 exit(0);
515 case RT_OPTION:
516 winrt_mode = 1;
517 break;
518 case RT_NS_PREFIX:
519 use_abi_namespace = 1;
520 break;
521 case SYSROOT_OPTION:
522 sysroot = xstrdup(optarg);
523 break;
524 case WIN32_OPTION:
525 pointer_size = 4;
526 break;
527 case WIN64_OPTION:
528 pointer_size = 8;
529 break;
530 case PACKING_OPTION:
531 packing = strtol(optarg, NULL, 0);
532 if(packing != 2 && packing != 4 && packing != 8)
533 error("Structure packing must be one of 2, 4 or 8\n");
534 break;
535 case ACF_OPTION:
536 acf_name = xstrdup(optarg);
537 break;
538 case APP_CONFIG_OPTION:
539 /* widl does not distinguish between app_mode and default mode,
540 but we ignore this option for midl compatibility */
541 break;
542 case ROBUST_OPTION:
543 /* FIXME: Support robust option */
544 break;
545 case 'b':
546 if (!parse_target( optarg, &target ))
547 error( "Invalid target specification '%s'\n", optarg );
548 break;
549 case 'c':
550 do_everything = 0;
551 do_client = 1;
552 break;
553 case 'C':
554 client_name = xstrdup(optarg);
555 break;
556 case 'd':
557 debuglevel = strtol(optarg, NULL, 0);
558 break;
559 case 'D':
560 wpp_add_cmdline_define(optarg);
561 break;
562 case 'E':
563 do_everything = 0;
564 preprocess_only = 1;
565 break;
566 case 'h':
567 do_everything = 0;
568 do_header = 1;
569 break;
570 case 'H':
571 header_name = xstrdup(optarg);
572 break;
573 case 'I':
574 wpp_add_include_path(optarg);
575 break;
576 case 'L':
577 strarray_add( &dlldirs, optarg );
578 break;
579 case 'm':
580 if (!strcmp( optarg, "32" )) pointer_size = 4;
581 else if (!strcmp( optarg, "64" )) pointer_size = 8;
582 break;
583 case 'N':
584 no_preprocess = 1;
585 break;
586 case 'o':
587 output_name = xstrdup(optarg);
588 break;
589 case 'O':
590 if (!strcmp( optarg, "s" )) interpreted_mode = 0;
591 else if (!strcmp( optarg, "i" )) interpreted_mode = 1;
592 else if (!strcmp( optarg, "ic" )) interpreted_mode = 1;
593 else if (!strcmp( optarg, "if" )) interpreted_mode = 1;
594 else if (!strcmp( optarg, "icf" )) interpreted_mode = 1;
595 else error( "Invalid argument '-O%s'\n", optarg );
596 break;
597 case 'p':
598 do_everything = 0;
599 do_proxies = 1;
600 break;
601 case 'P':
602 proxy_name = xstrdup(optarg);
603 break;
604 case 'r':
605 do_everything = 0;
606 do_regscript = 1;
607 break;
608 case 's':
609 do_everything = 0;
610 do_server = 1;
611 break;
612 case 'S':
613 server_name = xstrdup(optarg);
614 break;
615 case 't':
616 do_everything = 0;
617 do_typelib = 1;
618 break;
619 case OLD_TYPELIB_OPTION:
620 old_typelib = 1;
621 break;
622 case 'T':
623 typelib_name = xstrdup(optarg);
624 break;
625 case 'u':
626 do_everything = 0;
627 do_idfile = 1;
628 break;
629 case 'U':
630 idfile_name = xstrdup(optarg);
631 break;
632 case 'V':
633 printf("%s", version_string);
634 exit(0);
635 case 'W':
636 pedantic = 1;
637 break;
638 case '?':
639 fprintf(stderr, "widl: %s\n\n%s", optarg, usage);
640 exit(1);
644 int open_typelib( const char *name )
646 static const char *default_dirs[] = { DLLDIR, "/usr/lib/wine", "/usr/local/lib/wine" };
647 struct target win_target = { target.cpu, PLATFORM_WINDOWS };
648 const char *pe_dir = get_arch_dir( win_target );
649 int fd;
650 unsigned int i;
652 #define TRYOPEN(str) do { \
653 char *file = str; \
654 if ((fd = open( file, O_RDONLY | O_BINARY )) != -1) return fd; \
655 free( file ); } while(0)
657 for (i = 0; i < dlldirs.count; i++)
659 if (strendswith( dlldirs.str[i], "/*" )) /* special case for wine build tree */
661 int namelen = strlen( name );
662 if (strendswith( name, ".dll" )) namelen -= 4;
663 TRYOPEN( strmake( "%.*s/%.*s%s/%s", (int)strlen(dlldirs.str[i]) - 2, dlldirs.str[i],
664 namelen, name, pe_dir, name ));
666 else
668 TRYOPEN( strmake( "%s%s/%s", dlldirs.str[i], pe_dir, name ));
669 TRYOPEN( strmake( "%s/%s", dlldirs.str[i], name ));
673 if (stdinc)
675 if (dlldir)
677 TRYOPEN( strmake( "%s%s/%s", dlldir, pe_dir, name ));
678 TRYOPEN( strmake( "%s/%s", dlldir, name ));
680 for (i = 0; i < ARRAY_SIZE(default_dirs); i++)
682 if (i && !strcmp( default_dirs[i], default_dirs[0] )) continue;
683 TRYOPEN( strmake( "%s%s/%s", default_dirs[i], pe_dir, name ));
686 error( "cannot find %s\n", name );
687 #undef TRYOPEN
690 int main(int argc,char *argv[])
692 int i;
693 int ret = 0;
694 struct strarray files;
696 init_signals( exit_on_signal );
697 init_argv0_dir( argv[0] );
698 target = init_argv0_target( argv[0] );
700 now = time(NULL);
702 files = parse_options( argc, argv, short_options, long_options, 1, option_callback );
704 if (stdinc)
706 static const char *incl_dirs[] = { INCLUDEDIR, "/usr/include", "/usr/local/include" };
708 if (includedir)
710 wpp_add_include_path( strmake( "%s/wine/msvcrt", includedir ));
711 wpp_add_include_path( strmake( "%s/wine/windows", includedir ));
713 for (i = 0; i < ARRAY_SIZE(incl_dirs); i++)
715 if (i && !strcmp( incl_dirs[i], incl_dirs[0] )) continue;
716 wpp_add_include_path( strmake( "%s%s/wine/msvcrt", sysroot, incl_dirs[i] ));
717 wpp_add_include_path( strmake( "%s%s/wine/windows", sysroot, incl_dirs[i] ));
721 if (pointer_size)
722 set_target_ptr_size( &target, pointer_size );
723 else
724 pointer_size = get_target_ptr_size( target );
726 /* if nothing specified, try to guess output type from the output file name */
727 if (output_name && do_everything && !do_header && !do_typelib && !do_proxies &&
728 !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata)
730 do_everything = 0;
731 if (strendswith( output_name, ".h" )) do_header = 1;
732 else if (strendswith( output_name, ".tlb" )) do_typelib = 1;
733 else if (strendswith( output_name, "_p.c" )) do_proxies = 1;
734 else if (strendswith( output_name, "_c.c" )) do_client = 1;
735 else if (strendswith( output_name, "_s.c" )) do_server = 1;
736 else if (strendswith( output_name, "_i.c" )) do_idfile = 1;
737 else if (strendswith( output_name, "_r.res" )) do_regscript = 1;
738 else if (strendswith( output_name, "_t.res" )) do_typelib = 1;
739 else if (strendswith( output_name, "_l.res" )) do_typelib = 1;
740 else if (strendswith( output_name, "dlldata.c" )) do_dlldata = 1;
741 else do_everything = 1;
744 if(do_everything) {
745 set_everything(TRUE);
748 if (do_header + do_typelib + do_proxies + do_client +
749 do_server + do_regscript + do_idfile + do_dlldata == 1 && output_name)
751 if (do_header && !header_name) header_name = output_name;
752 else if (do_typelib && !typelib_name) typelib_name = output_name;
753 else if (do_proxies && !proxy_name) proxy_name = output_name;
754 else if (do_client && !client_name) client_name = output_name;
755 else if (do_server && !server_name) server_name = output_name;
756 else if (do_regscript && !regscript_name) regscript_name = output_name;
757 else if (do_idfile && !idfile_name) idfile_name = output_name;
758 else if (do_dlldata && !dlldata_name) dlldata_name = output_name;
761 if (!dlldata_name && do_dlldata)
762 dlldata_name = xstrdup("dlldata.c");
764 if (files.count) {
765 if (do_dlldata && !do_everything) {
766 struct strarray filenames = empty_strarray;
767 for (i = 0; i < files.count; i++)
768 strarray_add(&filenames, replace_extension( get_basename( files.str[i] ), ".idl", "" ));
770 write_dlldata_list(filenames, 0 /* FIXME */ );
771 return 0;
773 else if (files.count > 1) {
774 fprintf(stderr, "%s", usage);
775 return 1;
777 else
779 input_name = xstrdup( files.str[0] );
780 idl_name = get_basename( input_name );
783 else {
784 fprintf(stderr, "%s", usage);
785 return 1;
788 if(debuglevel)
790 setbuf(stdout, NULL);
791 setbuf(stderr, NULL);
794 parser_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
795 yy_flex_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
797 wpp_set_debug( (debuglevel & DEBUGLEVEL_PPLEX) != 0,
798 (debuglevel & DEBUGLEVEL_PPTRACE) != 0,
799 (debuglevel & DEBUGLEVEL_PPMSG) != 0 );
801 if (!header_name)
802 header_name = replace_extension( get_basename(input_name), ".idl", ".h" );
804 if (!typelib_name && do_typelib)
805 typelib_name = replace_extension( get_basename(input_name), ".idl", ".tlb" );
807 if (!proxy_name && do_proxies)
808 proxy_name = replace_extension( get_basename(input_name), ".idl", "_p.c" );
810 if (!client_name && do_client)
811 client_name = replace_extension( get_basename(input_name), ".idl", "_c.c" );
813 if (!server_name && do_server)
814 server_name = replace_extension( get_basename(input_name), ".idl", "_s.c" );
816 if (!regscript_name && do_regscript)
817 regscript_name = replace_extension( get_basename(input_name), ".idl", "_r.rgs" );
819 if (!idfile_name && do_idfile)
820 idfile_name = replace_extension( get_basename(input_name), ".idl", "_i.c" );
822 if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
823 if (do_client) client_token = dup_basename_token(client_name,"_c.c");
824 if (do_server) server_token = dup_basename_token(server_name,"_s.c");
825 if (do_regscript) regscript_token = dup_basename_token(regscript_name,"_r.rgs");
827 add_widl_version_define();
828 wpp_add_cmdline_define("_WIN32=1");
830 atexit(rm_tempfile);
831 if (preprocess_only) exit( wpp_parse( input_name, stdout ) );
832 parser_in = open_input_file( input_name );
834 header_token = make_token(header_name);
836 init_types();
837 ret = parser_parse();
838 close_all_inputs();
839 if (ret) exit(1);
841 /* Everything has been done successfully, don't delete any files. */
842 set_everything(FALSE);
843 local_stubs_name = NULL;
845 return 0;
848 static void rm_tempfile(void)
850 if (do_header)
851 unlink(header_name);
852 if (local_stubs_name)
853 unlink(local_stubs_name);
854 if (do_client)
855 unlink(client_name);
856 if (do_server)
857 unlink(server_name);
858 if (do_regscript)
859 unlink(regscript_name);
860 if (do_idfile)
861 unlink(idfile_name);
862 if (do_proxies)
863 unlink(proxy_name);
864 if (do_typelib)
865 unlink(typelib_name);
866 remove_temp_files();
869 char *find_input_file( const char *name, const char *parent )
871 char *path;
873 /* don't search for a file name with a path in the include directories, for compatibility with MIDL */
874 if (strchr( name, '/' ) || strchr( name, '\\' )) path = xstrdup( name );
875 else if (!(path = wpp_find_include( name, parent ))) error_loc( "Unable to open include file %s\n", name );
877 return path;
880 FILE *open_input_file( const char *path )
882 FILE *file;
883 char *name;
884 int ret;
886 if (no_preprocess)
888 if (!(file = fopen( path, "r" ))) error_loc( "Unable to open %s\n", path );
889 return file;
892 name = make_temp_file( "widl", NULL );
893 if (!(file = fopen( name, "wt" ))) error_loc( "Could not open %s for writing\n", name );
894 ret = wpp_parse( path, file );
895 fclose( file );
896 if (ret) exit( 1 );
898 if (!(file = fopen( name, "r" ))) error_loc( "Unable to open %s\n", name );
899 return file;