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