widl.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  1. /*
  2. * IDL Compiler
  3. *
  4. * Copyright 2002 Ove Kaaven
  5. * based on WRC code by Bertho Stultiens
  6. *
  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.
  11. *
  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.
  16. *
  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
  20. */
  21. #include "config.h"
  22. #include <errno.h>
  23. #include <limits.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <ctype.h>
  29. #include <signal.h>
  30. #include <limits.h>
  31. #include <sys/types.h>
  32. #ifdef HAVE_SYS_SYSCTL_H
  33. # include <sys/sysctl.h>
  34. #endif
  35. #include "widl.h"
  36. #include "utils.h"
  37. #include "parser.h"
  38. #include "wpp_private.h"
  39. #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. " -app_config Ignored, present for midl compatibility\n"
  45. " -b arch Set the target architecture\n"
  46. " -c Generate client stub\n"
  47. " -d n Set debug level to 'n'\n"
  48. " -D id[=val] Define preprocessor identifier id=val\n"
  49. " -E Preprocess only\n"
  50. " --help Display this help and exit\n"
  51. " -h Generate headers\n"
  52. " -H file Name of header file (default is infile.h)\n"
  53. " -I directory Add directory to the include search path (multiple -I allowed)\n"
  54. " -L directory Add directory to the library search path (multiple -L allowed)\n"
  55. " --local-stubs=file Write empty stubs for call_as/local methods to file\n"
  56. " -m32, -m64 Set the target architecture (Win32 or Win64)\n"
  57. " -N Do not preprocess input\n"
  58. " --nostdinc Do not search the standard include path\n"
  59. " --ns_prefix Prefix namespaces with ABI namespace\n"
  60. " --oldnames Use old naming conventions\n"
  61. " -o, --output=NAME Set the output file name\n"
  62. " -Otype Type of stubs to generate (-Os, -Oi, -Oif)\n"
  63. " -p Generate proxy\n"
  64. " --prefix-all=p Prefix names of client stubs / server functions with 'p'\n"
  65. " --prefix-client=p Prefix names of client stubs with 'p'\n"
  66. " --prefix-server=p Prefix names of server functions with 'p'\n"
  67. " -r Generate registration script\n"
  68. " -robust Ignored, present for midl compatibility\n"
  69. " --sysroot=DIR Prefix include paths with DIR\n"
  70. " -s Generate server stub\n"
  71. " -t Generate typelib\n"
  72. " -u Generate interface identifiers file\n"
  73. " -V Print version and exit\n"
  74. " -W Enable pedantic warnings\n"
  75. " --win32, --win64 Set the target architecture (Win32 or Win64)\n"
  76. " --win32-align n Set win32 structure alignment to 'n'\n"
  77. " --win64-align n Set win64 structure alignment to 'n'\n"
  78. " --winrt Enable Windows Runtime mode\n"
  79. "Debug level 'n' is a bitmask with following meaning:\n"
  80. " * 0x01 Tell which resource is parsed (verbose mode)\n"
  81. " * 0x02 Dump internal structures\n"
  82. " * 0x04 Create a parser trace (yydebug=1)\n"
  83. " * 0x08 Preprocessor messages\n"
  84. " * 0x10 Preprocessor lex messages\n"
  85. " * 0x20 Preprocessor yacc trace\n"
  86. ;
  87. static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSION "\n"
  88. "Copyright 2002 Ove Kaaven\n";
  89. static struct target target;
  90. int debuglevel = DEBUGLEVEL_NONE;
  91. int parser_debug, yy_flex_debug;
  92. int pedantic = 0;
  93. int do_everything = 1;
  94. static int preprocess_only = 0;
  95. int do_header = 0;
  96. int do_typelib = 0;
  97. int do_proxies = 0;
  98. int do_client = 0;
  99. int do_server = 0;
  100. int do_regscript = 0;
  101. int do_idfile = 0;
  102. int do_dlldata = 0;
  103. static int no_preprocess = 0;
  104. int old_names = 0;
  105. int win32_packing = 8;
  106. int win64_packing = 8;
  107. int winrt_mode = 0;
  108. int use_abi_namespace = 0;
  109. static int stdinc = 1;
  110. static enum stub_mode stub_mode = MODE_Os;
  111. char *input_name;
  112. char *input_idl_name;
  113. char *acf_name;
  114. char *header_name;
  115. char *local_stubs_name;
  116. char *header_token;
  117. char *typelib_name;
  118. char *dlldata_name;
  119. char *proxy_name;
  120. char *proxy_token;
  121. char *client_name;
  122. char *client_token;
  123. char *server_name;
  124. char *server_token;
  125. char *regscript_name;
  126. char *regscript_token;
  127. static char *idfile_name;
  128. char *temp_name;
  129. const char *prefix_client = "";
  130. const char *prefix_server = "";
  131. static const char *includedir;
  132. static const char *dlldir;
  133. static struct strarray dlldirs;
  134. static char *output_name;
  135. static const char *sysroot = "";
  136. int line_number = 1;
  137. static FILE *idfile;
  138. unsigned int pointer_size = 0;
  139. time_t now;
  140. enum {
  141. OLDNAMES_OPTION = CHAR_MAX + 1,
  142. ACF_OPTION,
  143. APP_CONFIG_OPTION,
  144. DLLDATA_OPTION,
  145. DLLDATA_ONLY_OPTION,
  146. LOCAL_STUBS_OPTION,
  147. NOSTDINC_OPTION,
  148. PREFIX_ALL_OPTION,
  149. PREFIX_CLIENT_OPTION,
  150. PREFIX_SERVER_OPTION,
  151. PRINT_HELP,
  152. RT_NS_PREFIX,
  153. RT_OPTION,
  154. ROBUST_OPTION,
  155. SYSROOT_OPTION,
  156. WIN32_OPTION,
  157. WIN64_OPTION,
  158. WIN32_ALIGN_OPTION,
  159. WIN64_ALIGN_OPTION
  160. };
  161. static const char short_options[] =
  162. "b:cC:d:D:EhH:I:L:m:No:O:pP:rsS:tT:uU:VW";
  163. static const struct long_option long_options[] = {
  164. { "acf", 1, ACF_OPTION },
  165. { "app_config", 0, APP_CONFIG_OPTION },
  166. { "dlldata", 1, DLLDATA_OPTION },
  167. { "dlldata-only", 0, DLLDATA_ONLY_OPTION },
  168. { "help", 0, PRINT_HELP },
  169. { "local-stubs", 1, LOCAL_STUBS_OPTION },
  170. { "nostdinc", 0, NOSTDINC_OPTION },
  171. { "ns_prefix", 0, RT_NS_PREFIX },
  172. { "oldnames", 0, OLDNAMES_OPTION },
  173. { "output", 0, 'o' },
  174. { "prefix-all", 1, PREFIX_ALL_OPTION },
  175. { "prefix-client", 1, PREFIX_CLIENT_OPTION },
  176. { "prefix-server", 1, PREFIX_SERVER_OPTION },
  177. { "robust", 0, ROBUST_OPTION },
  178. { "sysroot", 1, SYSROOT_OPTION },
  179. { "target", 0, 'b' },
  180. { "winrt", 0, RT_OPTION },
  181. { "win32", 0, WIN32_OPTION },
  182. { "win64", 0, WIN64_OPTION },
  183. { "win32-align", 1, WIN32_ALIGN_OPTION },
  184. { "win64-align", 1, WIN64_ALIGN_OPTION },
  185. { NULL }
  186. };
  187. static void rm_tempfile(void);
  188. enum stub_mode get_stub_mode(void)
  189. {
  190. /* old-style interpreted stubs are not supported on 64-bit */
  191. if (stub_mode == MODE_Oi && pointer_size == 8) return MODE_Oif;
  192. return stub_mode;
  193. }
  194. static char *make_token(const char *name)
  195. {
  196. char *token;
  197. int i;
  198. token = get_basename( name );
  199. for (i=0; token[i]; i++) {
  200. if (!isalnum(token[i])) token[i] = '_';
  201. else token[i] = tolower(token[i]);
  202. }
  203. return token;
  204. }
  205. /* duplicate a basename into a valid C token */
  206. static char *dup_basename_token(const char *name, const char *ext)
  207. {
  208. char *p, *ret = replace_extension( get_basename(name), ext, "" );
  209. /* map invalid characters to '_' */
  210. for (p = ret; *p; p++) if (!isalnum(*p)) *p = '_';
  211. return ret;
  212. }
  213. static void add_widl_version_define(void)
  214. {
  215. char version_str[32];
  216. unsigned int version;
  217. const char *p = PACKAGE_VERSION;
  218. /* major */
  219. version = atoi(p) * 0x10000;
  220. p = strchr(p, '.');
  221. /* minor */
  222. if (p)
  223. {
  224. version += atoi(p + 1) * 0x100;
  225. p = strchr(p + 1, '.');
  226. }
  227. /* build */
  228. if (p)
  229. version += atoi(p + 1);
  230. sprintf(version_str, "__WIDL__=0x%x", version);
  231. wpp_add_cmdline_define(version_str);
  232. }
  233. /* clean things up when aborting on a signal */
  234. static void exit_on_signal( int sig )
  235. {
  236. exit(1); /* this will call the atexit functions */
  237. }
  238. static void set_everything(int x)
  239. {
  240. do_header = x;
  241. do_typelib = x;
  242. do_proxies = x;
  243. do_client = x;
  244. do_server = x;
  245. do_regscript = x;
  246. do_idfile = x;
  247. do_dlldata = x;
  248. }
  249. void start_cplusplus_guard(FILE *fp)
  250. {
  251. fprintf(fp, "#ifdef __cplusplus\n");
  252. fprintf(fp, "extern \"C\" {\n");
  253. fprintf(fp, "#endif\n\n");
  254. }
  255. void end_cplusplus_guard(FILE *fp)
  256. {
  257. fprintf(fp, "#ifdef __cplusplus\n");
  258. fprintf(fp, "}\n");
  259. fprintf(fp, "#endif\n\n");
  260. }
  261. static void write_dlldata_list( struct strarray filenames, int define_proxy_delegation)
  262. {
  263. FILE *dlldata;
  264. unsigned int i;
  265. dlldata = fopen(dlldata_name, "w");
  266. if (!dlldata)
  267. error("couldn't open %s: %s\n", dlldata_name, strerror(errno));
  268. fprintf(dlldata, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
  269. fprintf(dlldata, "- Do not edit ***/\n\n");
  270. if (define_proxy_delegation)
  271. fprintf(dlldata, "#define PROXY_DELEGATION\n");
  272. fprintf(dlldata, "#include <objbase.h>\n");
  273. fprintf(dlldata, "#include <rpcproxy.h>\n\n");
  274. start_cplusplus_guard(dlldata);
  275. for (i = 0; i < filenames.count; i++)
  276. fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", filenames.str[i]);
  277. fprintf(dlldata, "\nPROXYFILE_LIST_START\n");
  278. fprintf(dlldata, "/* Start of list */\n");
  279. for (i = 0; i < filenames.count; i++)
  280. fprintf(dlldata, " REFERENCE_PROXY_FILE(%s),\n", filenames.str[i]);
  281. fprintf(dlldata, "/* End of list */\n");
  282. fprintf(dlldata, "PROXYFILE_LIST_END\n\n");
  283. fprintf(dlldata, "DLLDATA_ROUTINES(aProxyFileList, GET_DLL_CLSID)\n\n");
  284. end_cplusplus_guard(dlldata);
  285. fclose(dlldata);
  286. }
  287. static char *eat_space(char *s)
  288. {
  289. while (isspace((unsigned char) *s))
  290. ++s;
  291. return s;
  292. }
  293. void write_dlldata(const statement_list_t *stmts)
  294. {
  295. struct strarray filenames = empty_strarray;
  296. int define_proxy_delegation = 0;
  297. FILE *dlldata;
  298. if (!do_dlldata || !need_proxy_file(stmts))
  299. return;
  300. define_proxy_delegation = need_proxy_delegation(stmts);
  301. dlldata = fopen(dlldata_name, "r");
  302. if (dlldata) {
  303. static const char marker[] = "REFERENCE_PROXY_FILE";
  304. static const char delegation_define[] = "#define PROXY_DELEGATION";
  305. char *line = NULL;
  306. size_t len = 0;
  307. while (widl_getline(&line, &len, dlldata)) {
  308. char *start, *end;
  309. start = eat_space(line);
  310. if (strncmp(start, marker, sizeof marker - 1) == 0) {
  311. start = eat_space(start + sizeof marker - 1);
  312. if (*start != '(')
  313. continue;
  314. end = start = eat_space(start + 1);
  315. while (*end && *end != ')')
  316. ++end;
  317. if (*end != ')')
  318. continue;
  319. while (isspace((unsigned char) end[-1]))
  320. --end;
  321. *end = '\0';
  322. if (start < end)
  323. strarray_add(&filenames, replace_extension( get_basename( start ), ".idl", "" ));
  324. }else if (!define_proxy_delegation && strncmp(start, delegation_define, sizeof(delegation_define)-1)) {
  325. define_proxy_delegation = 1;
  326. }
  327. }
  328. if (ferror(dlldata))
  329. error("couldn't read from %s: %s\n", dlldata_name, strerror(errno));
  330. free(line);
  331. fclose(dlldata);
  332. }
  333. if (strarray_exists( &filenames, proxy_token ))
  334. /* We're already in the list, no need to regenerate this file. */
  335. return;
  336. strarray_add(&filenames, proxy_token);
  337. write_dlldata_list(filenames, define_proxy_delegation);
  338. }
  339. static void write_id_guid(FILE *f, const char *type, const char *guid_prefix, const char *name, const UUID *uuid)
  340. {
  341. if (!uuid) return;
  342. fprintf(f, "MIDL_DEFINE_GUID(%s, %s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
  343. "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
  344. type, guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
  345. uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
  346. uuid->Data4[6], uuid->Data4[7]);
  347. }
  348. static void write_id_data_stmts(const statement_list_t *stmts)
  349. {
  350. const statement_t *stmt;
  351. if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
  352. {
  353. if (stmt->type == STMT_TYPE)
  354. {
  355. const type_t *type = stmt->u.type;
  356. if (type_get_type(type) == TYPE_INTERFACE)
  357. {
  358. const UUID *uuid;
  359. if (!is_object(type) && !is_attr(type->attrs, ATTR_DISPINTERFACE))
  360. continue;
  361. uuid = get_attrp(type->attrs, ATTR_UUID);
  362. write_id_guid(idfile, "IID", is_attr(type->attrs, ATTR_DISPINTERFACE) ? "DIID" : "IID",
  363. type->name, uuid);
  364. if (type_iface_get_async_iface(type))
  365. {
  366. uuid = get_attrp(type_iface_get_async_iface(type)->attrs, ATTR_UUID);
  367. write_id_guid(idfile, "IID", "IID", type_iface_get_async_iface(type)->name, uuid);
  368. }
  369. }
  370. else if (type_get_type(type) == TYPE_COCLASS)
  371. {
  372. const UUID *uuid = get_attrp(type->attrs, ATTR_UUID);
  373. write_id_guid(idfile, "CLSID", "CLSID", type->name, uuid);
  374. }
  375. }
  376. else if (stmt->type == STMT_LIBRARY)
  377. {
  378. const UUID *uuid = get_attrp(stmt->u.lib->attrs, ATTR_UUID);
  379. write_id_guid(idfile, "IID", "LIBID", stmt->u.lib->name, uuid);
  380. write_id_data_stmts(stmt->u.lib->stmts);
  381. }
  382. }
  383. }
  384. void write_id_data(const statement_list_t *stmts)
  385. {
  386. if (!do_idfile) return;
  387. idfile = fopen(idfile_name, "w");
  388. if (! idfile) {
  389. error("Could not open %s for output\n", idfile_name);
  390. return;
  391. }
  392. fprintf(idfile, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
  393. fprintf(idfile, "from %s - Do not edit ***/\n\n", input_idl_name);
  394. fprintf(idfile, "#include <rpc.h>\n");
  395. fprintf(idfile, "#include <rpcndr.h>\n\n");
  396. fprintf(idfile, "#ifdef _MIDL_USE_GUIDDEF_\n\n");
  397. fprintf(idfile, "#ifndef INITGUID\n");
  398. fprintf(idfile, "#define INITGUID\n");
  399. fprintf(idfile, "#include <guiddef.h>\n");
  400. fprintf(idfile, "#undef INITGUID\n");
  401. fprintf(idfile, "#else\n");
  402. fprintf(idfile, "#include <guiddef.h>\n");
  403. fprintf(idfile, "#endif\n\n");
  404. fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
  405. fprintf(idfile, " DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\n\n");
  406. fprintf(idfile, "#elif defined(__cplusplus)\n\n");
  407. fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
  408. fprintf(idfile, " EXTERN_C const type DECLSPEC_SELECTANY name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n");
  409. fprintf(idfile, "#else\n\n");
  410. fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
  411. fprintf(idfile, " const type DECLSPEC_SELECTANY name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n");
  412. fprintf(idfile, "#endif\n\n");
  413. start_cplusplus_guard(idfile);
  414. write_id_data_stmts(stmts);
  415. fprintf(idfile, "\n");
  416. end_cplusplus_guard(idfile);
  417. fprintf(idfile, "#undef MIDL_DEFINE_GUID\n" );
  418. fclose(idfile);
  419. }
  420. static void init_argv0_dir( const char *argv0 )
  421. {
  422. #ifndef _WIN32
  423. char *dir;
  424. #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
  425. dir = realpath( "/proc/self/exe", NULL );
  426. #elif defined (__FreeBSD__) || defined(__DragonFly__)
  427. static int pathname[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
  428. size_t path_size = PATH_MAX;
  429. char *path = malloc( path_size );
  430. if (path && !sysctl( pathname, sizeof(pathname)/sizeof(pathname[0]), path, &path_size, NULL, 0 ))
  431. dir = realpath( path, NULL );
  432. free( path );
  433. #else
  434. dir = realpath( argv0, NULL );
  435. #endif
  436. if (!dir) return;
  437. includedir = strmake( "%s/%s", get_dirname( dir ), BIN_TO_INCLUDEDIR );
  438. dlldir = strmake( "%s/%s", get_dirname( dir ), BIN_TO_DLLDIR );
  439. #endif
  440. }
  441. static void option_callback( int optc, char *optarg )
  442. {
  443. switch (optc)
  444. {
  445. case DLLDATA_OPTION:
  446. dlldata_name = xstrdup(optarg);
  447. break;
  448. case DLLDATA_ONLY_OPTION:
  449. do_everything = 0;
  450. do_dlldata = 1;
  451. break;
  452. case LOCAL_STUBS_OPTION:
  453. do_everything = 0;
  454. local_stubs_name = xstrdup(optarg);
  455. break;
  456. case NOSTDINC_OPTION:
  457. stdinc = 0;
  458. break;
  459. case OLDNAMES_OPTION:
  460. old_names = 1;
  461. break;
  462. case PREFIX_ALL_OPTION:
  463. prefix_client = xstrdup(optarg);
  464. prefix_server = xstrdup(optarg);
  465. break;
  466. case PREFIX_CLIENT_OPTION:
  467. prefix_client = xstrdup(optarg);
  468. break;
  469. case PREFIX_SERVER_OPTION:
  470. prefix_server = xstrdup(optarg);
  471. break;
  472. case PRINT_HELP:
  473. fprintf(stderr, "%s", usage);
  474. exit(0);
  475. case RT_OPTION:
  476. winrt_mode = 1;
  477. break;
  478. case RT_NS_PREFIX:
  479. use_abi_namespace = 1;
  480. break;
  481. case SYSROOT_OPTION:
  482. sysroot = xstrdup(optarg);
  483. break;
  484. case WIN32_OPTION:
  485. pointer_size = 4;
  486. break;
  487. case WIN64_OPTION:
  488. pointer_size = 8;
  489. break;
  490. case WIN32_ALIGN_OPTION:
  491. win32_packing = strtol(optarg, NULL, 0);
  492. if(win32_packing != 2 && win32_packing != 4 && win32_packing != 8)
  493. error("Packing must be one of 2, 4 or 8\n");
  494. break;
  495. case WIN64_ALIGN_OPTION:
  496. win64_packing = strtol(optarg, NULL, 0);
  497. if(win64_packing != 2 && win64_packing != 4 && win64_packing != 8)
  498. error("Packing must be one of 2, 4 or 8\n");
  499. break;
  500. case ACF_OPTION:
  501. acf_name = xstrdup(optarg);
  502. break;
  503. case APP_CONFIG_OPTION:
  504. /* widl does not distinguish between app_mode and default mode,
  505. but we ignore this option for midl compatibility */
  506. break;
  507. case ROBUST_OPTION:
  508. /* FIXME: Support robust option */
  509. break;
  510. case 'b':
  511. if (!parse_target( optarg, &target ))
  512. error( "Invalid target specification '%s'\n", optarg );
  513. break;
  514. case 'c':
  515. do_everything = 0;
  516. do_client = 1;
  517. break;
  518. case 'C':
  519. client_name = xstrdup(optarg);
  520. break;
  521. case 'd':
  522. debuglevel = strtol(optarg, NULL, 0);
  523. break;
  524. case 'D':
  525. wpp_add_cmdline_define(optarg);
  526. break;
  527. case 'E':
  528. do_everything = 0;
  529. preprocess_only = 1;
  530. break;
  531. case 'h':
  532. do_everything = 0;
  533. do_header = 1;
  534. break;
  535. case 'H':
  536. header_name = xstrdup(optarg);
  537. break;
  538. case 'I':
  539. wpp_add_include_path(optarg);
  540. break;
  541. case 'L':
  542. strarray_add( &dlldirs, optarg );
  543. break;
  544. case 'm':
  545. if (!strcmp( optarg, "32" )) pointer_size = 4;
  546. else if (!strcmp( optarg, "64" )) pointer_size = 8;
  547. break;
  548. case 'N':
  549. no_preprocess = 1;
  550. break;
  551. case 'o':
  552. output_name = xstrdup(optarg);
  553. break;
  554. case 'O':
  555. if (!strcmp( optarg, "s" )) stub_mode = MODE_Os;
  556. else if (!strcmp( optarg, "i" )) stub_mode = MODE_Oi;
  557. else if (!strcmp( optarg, "ic" )) stub_mode = MODE_Oif;
  558. else if (!strcmp( optarg, "if" )) stub_mode = MODE_Oif;
  559. else if (!strcmp( optarg, "icf" )) stub_mode = MODE_Oif;
  560. else error( "Invalid argument '-O%s'\n", optarg );
  561. break;
  562. case 'p':
  563. do_everything = 0;
  564. do_proxies = 1;
  565. break;
  566. case 'P':
  567. proxy_name = xstrdup(optarg);
  568. break;
  569. case 'r':
  570. do_everything = 0;
  571. do_regscript = 1;
  572. break;
  573. case 's':
  574. do_everything = 0;
  575. do_server = 1;
  576. break;
  577. case 'S':
  578. server_name = xstrdup(optarg);
  579. break;
  580. case 't':
  581. do_everything = 0;
  582. do_typelib = 1;
  583. break;
  584. case 'T':
  585. typelib_name = xstrdup(optarg);
  586. break;
  587. case 'u':
  588. do_everything = 0;
  589. do_idfile = 1;
  590. break;
  591. case 'U':
  592. idfile_name = xstrdup(optarg);
  593. break;
  594. case 'V':
  595. printf("%s", version_string);
  596. exit(0);
  597. case 'W':
  598. pedantic = 1;
  599. break;
  600. case '?':
  601. fprintf(stderr, "widl: %s\n\n%s", optarg, usage);
  602. exit(1);
  603. }
  604. }
  605. int open_typelib( const char *name )
  606. {
  607. static const char *default_dirs[] = { DLLDIR, "/usr/lib/wine", "/usr/local/lib/wine" };
  608. struct target win_target = { target.cpu, PLATFORM_WINDOWS };
  609. const char *pe_dir = get_arch_dir( win_target );
  610. int fd;
  611. unsigned int i;
  612. #define TRYOPEN(str) do { \
  613. char *file = str; \
  614. if ((fd = open( file, O_RDONLY | O_BINARY )) != -1) return fd; \
  615. free( file ); } while(0)
  616. for (i = 0; i < dlldirs.count; i++)
  617. {
  618. if (strendswith( dlldirs.str[i], "/*" )) /* special case for wine build tree */
  619. {
  620. int namelen = strlen( name );
  621. if (strendswith( name, ".dll" )) namelen -= 4;
  622. TRYOPEN( strmake( "%.*s/%.*s/%s", (int)strlen(dlldirs.str[i]) - 2, dlldirs.str[i],
  623. namelen, name, name ));
  624. }
  625. else
  626. {
  627. TRYOPEN( strmake( "%s%s/%s", dlldirs.str[i], pe_dir, name ));
  628. TRYOPEN( strmake( "%s/%s", dlldirs.str[i], name ));
  629. }
  630. }
  631. if (stdinc)
  632. {
  633. if (dlldir)
  634. {
  635. TRYOPEN( strmake( "%s%s/%s", dlldir, pe_dir, name ));
  636. TRYOPEN( strmake( "%s/%s", dlldir, name ));
  637. }
  638. for (i = 0; i < ARRAY_SIZE(default_dirs); i++)
  639. {
  640. if (i && !strcmp( default_dirs[i], default_dirs[0] )) continue;
  641. TRYOPEN( strmake( "%s%s/%s", default_dirs[i], pe_dir, name ));
  642. }
  643. }
  644. error( "cannot find %s\n", name );
  645. #undef TRYOPEN
  646. }
  647. int main(int argc,char *argv[])
  648. {
  649. int i;
  650. int ret = 0;
  651. struct strarray files;
  652. signal( SIGTERM, exit_on_signal );
  653. signal( SIGINT, exit_on_signal );
  654. #ifdef SIGHUP
  655. signal( SIGHUP, exit_on_signal );
  656. #endif
  657. init_argv0_dir( argv[0] );
  658. target = init_argv0_target( argv[0] );
  659. now = time(NULL);
  660. files = parse_options( argc, argv, short_options, long_options, 1, option_callback );
  661. if (stdinc)
  662. {
  663. static const char *incl_dirs[] = { INCLUDEDIR, "/usr/include", "/usr/local/include" };
  664. if (includedir)
  665. {
  666. wpp_add_include_path( strmake( "%s/wine/msvcrt", includedir ));
  667. wpp_add_include_path( strmake( "%s/wine/windows", includedir ));
  668. }
  669. for (i = 0; i < ARRAY_SIZE(incl_dirs); i++)
  670. {
  671. if (i && !strcmp( incl_dirs[i], incl_dirs[0] )) continue;
  672. wpp_add_include_path( strmake( "%s%s/wine/msvcrt", sysroot, incl_dirs[i] ));
  673. wpp_add_include_path( strmake( "%s%s/wine/windows", sysroot, incl_dirs[i] ));
  674. }
  675. }
  676. if (pointer_size)
  677. set_target_ptr_size( &target, pointer_size );
  678. else
  679. pointer_size = get_target_ptr_size( target );
  680. /* if nothing specified, try to guess output type from the output file name */
  681. if (output_name && do_everything && !do_header && !do_typelib && !do_proxies &&
  682. !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata)
  683. {
  684. do_everything = 0;
  685. if (strendswith( output_name, ".h" )) do_header = 1;
  686. else if (strendswith( output_name, ".tlb" )) do_typelib = 1;
  687. else if (strendswith( output_name, "_p.c" )) do_proxies = 1;
  688. else if (strendswith( output_name, "_c.c" )) do_client = 1;
  689. else if (strendswith( output_name, "_s.c" )) do_server = 1;
  690. else if (strendswith( output_name, "_i.c" )) do_idfile = 1;
  691. else if (strendswith( output_name, "_r.res" )) do_regscript = 1;
  692. else if (strendswith( output_name, "_t.res" )) do_typelib = 1;
  693. else if (strendswith( output_name, "_l.res" )) do_typelib = 1;
  694. else if (strendswith( output_name, "dlldata.c" )) do_dlldata = 1;
  695. else do_everything = 1;
  696. }
  697. if(do_everything) {
  698. set_everything(TRUE);
  699. }
  700. if (do_header + do_typelib + do_proxies + do_client +
  701. do_server + do_regscript + do_idfile + do_dlldata == 1 && output_name)
  702. {
  703. if (do_header && !header_name) header_name = output_name;
  704. else if (do_typelib && !typelib_name) typelib_name = output_name;
  705. else if (do_proxies && !proxy_name) proxy_name = output_name;
  706. else if (do_client && !client_name) client_name = output_name;
  707. else if (do_server && !server_name) server_name = output_name;
  708. else if (do_regscript && !regscript_name) regscript_name = output_name;
  709. else if (do_idfile && !idfile_name) idfile_name = output_name;
  710. else if (do_dlldata && !dlldata_name) dlldata_name = output_name;
  711. }
  712. if (!dlldata_name && do_dlldata)
  713. dlldata_name = xstrdup("dlldata.c");
  714. if (files.count) {
  715. if (do_dlldata && !do_everything) {
  716. struct strarray filenames = empty_strarray;
  717. for (i = 0; i < files.count; i++)
  718. strarray_add(&filenames, replace_extension( get_basename( files.str[i] ), ".idl", "" ));
  719. write_dlldata_list(filenames, 0 /* FIXME */ );
  720. return 0;
  721. }
  722. else if (files.count > 1) {
  723. fprintf(stderr, "%s", usage);
  724. return 1;
  725. }
  726. else
  727. input_idl_name = input_name = xstrdup(files.str[0]);
  728. }
  729. else {
  730. fprintf(stderr, "%s", usage);
  731. return 1;
  732. }
  733. if(debuglevel)
  734. {
  735. setbuf(stdout, NULL);
  736. setbuf(stderr, NULL);
  737. }
  738. parser_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
  739. yy_flex_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
  740. wpp_set_debug( (debuglevel & DEBUGLEVEL_PPLEX) != 0,
  741. (debuglevel & DEBUGLEVEL_PPTRACE) != 0,
  742. (debuglevel & DEBUGLEVEL_PPMSG) != 0 );
  743. if (!header_name)
  744. header_name = replace_extension( get_basename(input_name), ".idl", ".h" );
  745. if (!typelib_name && do_typelib)
  746. typelib_name = replace_extension( get_basename(input_name), ".idl", ".tlb" );
  747. if (!proxy_name && do_proxies)
  748. proxy_name = replace_extension( get_basename(input_name), ".idl", "_p.c" );
  749. if (!client_name && do_client)
  750. client_name = replace_extension( get_basename(input_name), ".idl", "_c.c" );
  751. if (!server_name && do_server)
  752. server_name = replace_extension( get_basename(input_name), ".idl", "_s.c" );
  753. if (!regscript_name && do_regscript)
  754. regscript_name = replace_extension( get_basename(input_name), ".idl", "_r.rgs" );
  755. if (!idfile_name && do_idfile)
  756. idfile_name = replace_extension( get_basename(input_name), ".idl", "_i.c" );
  757. if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
  758. if (do_client) client_token = dup_basename_token(client_name,"_c.c");
  759. if (do_server) server_token = dup_basename_token(server_name,"_s.c");
  760. if (do_regscript) regscript_token = dup_basename_token(regscript_name,"_r.rgs");
  761. add_widl_version_define();
  762. wpp_add_cmdline_define("_WIN32=1");
  763. atexit(rm_tempfile);
  764. if (!no_preprocess)
  765. {
  766. chat("Starting preprocess\n");
  767. if (!preprocess_only)
  768. {
  769. FILE *output;
  770. int fd;
  771. char *name;
  772. fd = make_temp_file( header_name, NULL, &name );
  773. temp_name = name;
  774. if (!(output = fdopen(fd, "wt")))
  775. error("Could not open fd %s for writing\n", name);
  776. ret = wpp_parse( input_name, output );
  777. fclose( output );
  778. }
  779. else
  780. {
  781. ret = wpp_parse( input_name, stdout );
  782. }
  783. if(ret) exit(1);
  784. if(preprocess_only) exit(0);
  785. if(!(parser_in = fopen(temp_name, "r"))) {
  786. fprintf(stderr, "Could not open %s for input\n", temp_name);
  787. return 1;
  788. }
  789. }
  790. else {
  791. if(!(parser_in = fopen(input_name, "r"))) {
  792. fprintf(stderr, "Could not open %s for input\n", input_name);
  793. return 1;
  794. }
  795. }
  796. header_token = make_token(header_name);
  797. init_types();
  798. ret = parser_parse();
  799. fclose(parser_in);
  800. if(ret) {
  801. exit(1);
  802. }
  803. /* Everything has been done successfully, don't delete any files. */
  804. set_everything(FALSE);
  805. local_stubs_name = NULL;
  806. return 0;
  807. }
  808. static void rm_tempfile(void)
  809. {
  810. abort_import();
  811. if(temp_name)
  812. unlink(temp_name);
  813. if (do_header)
  814. unlink(header_name);
  815. if (local_stubs_name)
  816. unlink(local_stubs_name);
  817. if (do_client)
  818. unlink(client_name);
  819. if (do_server)
  820. unlink(server_name);
  821. if (do_regscript)
  822. unlink(regscript_name);
  823. if (do_idfile)
  824. unlink(idfile_name);
  825. if (do_proxies)
  826. unlink(proxy_name);
  827. if (do_typelib)
  828. unlink(typelib_name);
  829. }