Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/widl.c
8650 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
292
dlldata = fopen(dlldata_name, "w");
293
if (!dlldata)
294
error("couldn't open %s: %s\n", dlldata_name, strerror(errno));
295
296
fprintf(dlldata, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
297
fprintf(dlldata, "- Do not edit ***/\n\n");
298
if (define_proxy_delegation)
299
fprintf(dlldata, "#define PROXY_DELEGATION\n");
300
fprintf(dlldata, "#include <objbase.h>\n");
301
fprintf(dlldata, "#include <rpcproxy.h>\n\n");
302
start_cplusplus_guard(dlldata);
303
304
STRARRAY_FOR_EACH( file, &filenames ) fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", file);
305
306
fprintf(dlldata, "\nPROXYFILE_LIST_START\n");
307
fprintf(dlldata, "/* Start of list */\n");
308
STRARRAY_FOR_EACH( file, &filenames ) fprintf(dlldata, " REFERENCE_PROXY_FILE(%s),\n", file);
309
fprintf(dlldata, "/* End of list */\n");
310
fprintf(dlldata, "PROXYFILE_LIST_END\n\n");
311
312
fprintf(dlldata, "DLLDATA_ROUTINES(aProxyFileList, GET_DLL_CLSID)\n\n");
313
end_cplusplus_guard(dlldata);
314
fclose(dlldata);
315
}
316
317
static char *eat_space(char *s)
318
{
319
while (isspace((unsigned char) *s))
320
++s;
321
return s;
322
}
323
324
void write_dlldata(const statement_list_t *stmts)
325
{
326
struct strarray filenames = empty_strarray;
327
int define_proxy_delegation = 0;
328
FILE *dlldata;
329
330
if (!do_dlldata || !need_proxy_file(stmts))
331
return;
332
333
define_proxy_delegation = need_proxy_delegation(stmts);
334
335
dlldata = fopen(dlldata_name, "r");
336
if (dlldata) {
337
static const char marker[] = "REFERENCE_PROXY_FILE";
338
static const char delegation_define[] = "#define PROXY_DELEGATION";
339
char *line = NULL;
340
size_t len = 0;
341
342
while (widl_getline(&line, &len, dlldata)) {
343
char *start, *end;
344
start = eat_space(line);
345
if (strncmp(start, marker, sizeof marker - 1) == 0) {
346
start = eat_space(start + sizeof marker - 1);
347
if (*start != '(')
348
continue;
349
end = start = eat_space(start + 1);
350
while (*end && *end != ')')
351
++end;
352
if (*end != ')')
353
continue;
354
while (isspace((unsigned char) end[-1]))
355
--end;
356
*end = '\0';
357
if (start < end)
358
strarray_add(&filenames, replace_extension( get_basename( start ), ".idl", "" ));
359
}else if (!define_proxy_delegation && strncmp(start, delegation_define, sizeof(delegation_define)-1)) {
360
define_proxy_delegation = 1;
361
}
362
}
363
364
if (ferror(dlldata))
365
error("couldn't read from %s: %s\n", dlldata_name, strerror(errno));
366
367
free(line);
368
fclose(dlldata);
369
}
370
371
if (strarray_exists( filenames, proxy_token ))
372
/* We're already in the list, no need to regenerate this file. */
373
return;
374
375
strarray_add(&filenames, proxy_token);
376
write_dlldata_list(filenames, define_proxy_delegation);
377
}
378
379
static void write_id_guid(FILE *f, const char *type, const char *guid_prefix, const char *name, const struct uuid *uuid)
380
{
381
if (!uuid) return;
382
fprintf(f, "MIDL_DEFINE_GUID(%s, %s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
383
"0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
384
type, guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
385
uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
386
uuid->Data4[6], uuid->Data4[7]);
387
}
388
389
static void write_id_data_stmts(const statement_list_t *stmts)
390
{
391
const statement_t *stmt;
392
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
393
{
394
if (stmt->type == STMT_TYPE)
395
{
396
const type_t *type = stmt->u.type;
397
if (type_get_type(type) == TYPE_INTERFACE)
398
{
399
const struct uuid *uuid;
400
if (!is_object(type) && !is_attr(type->attrs, ATTR_DISPINTERFACE))
401
continue;
402
uuid = get_attrp(type->attrs, ATTR_UUID);
403
write_id_guid(idfile, "IID", is_attr(type->attrs, ATTR_DISPINTERFACE) ? "DIID" : "IID",
404
type->name, uuid);
405
if (type_iface_get_async_iface(type))
406
{
407
uuid = get_attrp(type_iface_get_async_iface(type)->attrs, ATTR_UUID);
408
write_id_guid(idfile, "IID", "IID", type_iface_get_async_iface(type)->name, uuid);
409
}
410
}
411
else if (type_get_type(type) == TYPE_COCLASS)
412
{
413
const struct uuid *uuid = get_attrp(type->attrs, ATTR_UUID);
414
write_id_guid(idfile, "CLSID", "CLSID", type->name, uuid);
415
}
416
}
417
else if (stmt->type == STMT_LIBRARY)
418
{
419
const struct uuid *uuid = get_attrp(stmt->u.lib->attrs, ATTR_UUID);
420
write_id_guid(idfile, "IID", "LIBID", stmt->u.lib->name, uuid);
421
write_id_data_stmts(stmt->u.lib->stmts);
422
}
423
}
424
}
425
426
void write_id_data(const statement_list_t *stmts)
427
{
428
if (!do_idfile) return;
429
430
idfile = fopen(idfile_name, "w");
431
if (! idfile) {
432
error("Could not open %s for output\n", idfile_name);
433
return;
434
}
435
436
fprintf(idfile, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION);
437
fprintf(idfile, "from %s - Do not edit ***/\n\n", idl_name);
438
fprintf(idfile, "#include <rpc.h>\n");
439
fprintf(idfile, "#include <rpcndr.h>\n\n");
440
441
fprintf(idfile, "#ifdef _MIDL_USE_GUIDDEF_\n\n");
442
443
fprintf(idfile, "#ifndef INITGUID\n");
444
fprintf(idfile, "#define INITGUID\n");
445
fprintf(idfile, "#include <guiddef.h>\n");
446
fprintf(idfile, "#undef INITGUID\n");
447
fprintf(idfile, "#else\n");
448
fprintf(idfile, "#include <guiddef.h>\n");
449
fprintf(idfile, "#endif\n\n");
450
451
fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
452
fprintf(idfile, " DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\n\n");
453
454
fprintf(idfile, "#elif defined(__cplusplus)\n\n");
455
456
fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
457
fprintf(idfile, " EXTERN_C const type DECLSPEC_SELECTANY name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n");
458
459
fprintf(idfile, "#else\n\n");
460
461
fprintf(idfile, "#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n");
462
fprintf(idfile, " const type DECLSPEC_SELECTANY name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n");
463
464
fprintf(idfile, "#endif\n\n");
465
start_cplusplus_guard(idfile);
466
467
write_id_data_stmts(stmts);
468
469
fprintf(idfile, "\n");
470
end_cplusplus_guard(idfile);
471
fprintf(idfile, "#undef MIDL_DEFINE_GUID\n" );
472
473
fclose(idfile);
474
}
475
476
static void option_callback( int optc, char *optarg )
477
{
478
switch (optc)
479
{
480
case DLLDATA_OPTION:
481
dlldata_name = xstrdup(optarg);
482
break;
483
case DLLDATA_ONLY_OPTION:
484
do_everything = 0;
485
do_dlldata = 1;
486
break;
487
case LOCAL_STUBS_OPTION:
488
do_everything = 0;
489
local_stubs_name = xstrdup(optarg);
490
break;
491
case NOSTDINC_OPTION:
492
stdinc = 0;
493
break;
494
case OLDNAMES_OPTION:
495
old_names = 1;
496
break;
497
case PREFIX_ALL_OPTION:
498
prefix_client = xstrdup(optarg);
499
prefix_server = xstrdup(optarg);
500
break;
501
case PREFIX_CLIENT_OPTION:
502
prefix_client = xstrdup(optarg);
503
break;
504
case PREFIX_SERVER_OPTION:
505
prefix_server = xstrdup(optarg);
506
break;
507
case PRINT_HELP:
508
fprintf(stderr, "%s", usage);
509
exit(0);
510
case RT_OPTION:
511
winrt_mode = 1;
512
break;
513
case RT_NS_PREFIX:
514
use_abi_namespace = 1;
515
break;
516
case SYSROOT_OPTION:
517
sysroot = xstrdup(optarg);
518
break;
519
case WIN32_OPTION:
520
pointer_size = 4;
521
break;
522
case WIN64_OPTION:
523
pointer_size = 8;
524
break;
525
case WINMD_OPTION:
526
do_everything = 0;
527
winrt_mode = 1;
528
do_metadata = 1;
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);
641
}
642
}
643
644
int open_typelib( const char *name )
645
{
646
static const char *default_dirs[] = { LIBDIR "/wine", "/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;
651
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)
656
657
STRARRAY_FOR_EACH( dir, &dlldirs )
658
{
659
if (strendswith( dir, "/*" )) /* special case for wine build tree */
660
{
661
int namelen = strlen( name );
662
if (strendswith( name, ".dll" )) namelen -= 4;
663
TRYOPEN( strmake( "%.*s/%.*s%s/%s", (int)strlen(dir) - 2, dir,
664
namelen, name, pe_dir, name ));
665
}
666
else
667
{
668
TRYOPEN( strmake( "%s%s/%s", dir, pe_dir, name ));
669
TRYOPEN( strmake( "%s/%s", dir, name ));
670
}
671
}
672
673
if (stdinc)
674
{
675
if (libdir)
676
{
677
TRYOPEN( strmake( "%s/wine%s/%s", libdir, pe_dir, name ));
678
TRYOPEN( strmake( "%s/wine/%s", libdir, name ));
679
}
680
for (i = 0; i < ARRAY_SIZE(default_dirs); i++)
681
{
682
if (i && !strcmp( default_dirs[i], default_dirs[0] )) continue;
683
TRYOPEN( strmake( "%s%s/%s", default_dirs[i], pe_dir, name ));
684
}
685
}
686
error( "cannot find %s\n", name );
687
#undef TRYOPEN
688
}
689
690
int main(int argc,char *argv[])
691
{
692
int i;
693
int ret = 0;
694
struct strarray files;
695
696
init_signals( exit_on_signal );
697
bindir = get_bindir( argv[0] );
698
libdir = get_libdir( bindir );
699
includedir = get_includedir( bindir );
700
target = init_argv0_target( argv[0] );
701
702
now = time(NULL);
703
704
files = parse_options( argc, argv, short_options, long_options, 1, option_callback );
705
706
if (stdinc)
707
{
708
static const char *incl_dirs[] = { INCLUDEDIR, "/usr/include", "/usr/local/include" };
709
710
if (includedir)
711
{
712
wpp_add_include_path( strmake( "%s/wine/msvcrt", includedir ));
713
wpp_add_include_path( strmake( "%s/wine/windows", includedir ));
714
}
715
for (i = 0; i < ARRAY_SIZE(incl_dirs); i++)
716
{
717
if (i && !strcmp( incl_dirs[i], incl_dirs[0] )) continue;
718
wpp_add_include_path( strmake( "%s%s/wine/msvcrt", sysroot, incl_dirs[i] ));
719
wpp_add_include_path( strmake( "%s%s/wine/windows", sysroot, incl_dirs[i] ));
720
}
721
}
722
723
if (pointer_size)
724
set_target_ptr_size( &target, pointer_size );
725
else
726
pointer_size = get_target_ptr_size( target );
727
728
/* if nothing specified, try to guess output type from the output file name */
729
if (output_name && do_everything && !do_header && !do_typelib && !do_proxies &&
730
!do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata && !do_metadata)
731
{
732
do_everything = 0;
733
if (strendswith( output_name, ".h" )) do_header = 1;
734
else if (strendswith( output_name, ".tlb" )) do_typelib = 1;
735
else if (strendswith( output_name, ".winmd" ))
736
{
737
winrt_mode = 1;
738
do_metadata = 1;
739
}
740
else if (strendswith( output_name, "_p.c" )) do_proxies = 1;
741
else if (strendswith( output_name, "_c.c" )) do_client = 1;
742
else if (strendswith( output_name, "_s.c" )) do_server = 1;
743
else if (strendswith( output_name, "_i.c" )) do_idfile = 1;
744
else if (strendswith( output_name, "_r.res" )) do_regscript = 1;
745
else if (strendswith( output_name, "_t.res" )) do_typelib = 1;
746
else if (strendswith( output_name, "_l.res" )) do_typelib = 1;
747
else if (strendswith( output_name, "dlldata.c" )) do_dlldata = 1;
748
else do_everything = 1;
749
}
750
751
if(do_everything) {
752
set_everything(TRUE);
753
}
754
755
if (do_header + do_typelib + do_proxies + do_client +
756
do_server + do_regscript + do_idfile + do_dlldata + do_metadata == 1 && output_name)
757
{
758
if (do_header && !header_name) header_name = output_name;
759
else if (do_typelib && !typelib_name) typelib_name = output_name;
760
else if (do_metadata && !metadata_name) metadata_name = output_name;
761
else if (do_proxies && !proxy_name) proxy_name = output_name;
762
else if (do_client && !client_name) client_name = output_name;
763
else if (do_server && !server_name) server_name = output_name;
764
else if (do_regscript && !regscript_name) regscript_name = output_name;
765
else if (do_idfile && !idfile_name) idfile_name = output_name;
766
else if (do_dlldata && !dlldata_name) dlldata_name = output_name;
767
}
768
769
if (!dlldata_name && do_dlldata)
770
dlldata_name = xstrdup("dlldata.c");
771
772
if (files.count) {
773
if (do_dlldata && !do_everything) {
774
struct strarray filenames = empty_strarray;
775
STRARRAY_FOR_EACH( file, &files )
776
strarray_add(&filenames, replace_extension( get_basename( file ), ".idl", "" ));
777
778
write_dlldata_list(filenames, 0 /* FIXME */ );
779
return 0;
780
}
781
else if (files.count > 1) {
782
fprintf(stderr, "%s", usage);
783
return 1;
784
}
785
else
786
{
787
input_name = xstrdup( files.str[0] );
788
idl_name = get_basename( input_name );
789
}
790
}
791
else {
792
fprintf(stderr, "%s", usage);
793
return 1;
794
}
795
796
if(debuglevel)
797
{
798
setbuf(stdout, NULL);
799
setbuf(stderr, NULL);
800
}
801
802
parser_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
803
yy_flex_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0;
804
805
wpp_set_debug( (debuglevel & DEBUGLEVEL_PPLEX) != 0,
806
(debuglevel & DEBUGLEVEL_PPTRACE) != 0,
807
(debuglevel & DEBUGLEVEL_PPMSG) != 0 );
808
809
if (!header_name)
810
header_name = replace_extension( get_basename(input_name), ".idl", ".h" );
811
812
if (!typelib_name && do_typelib)
813
typelib_name = replace_extension( get_basename(input_name), ".idl", ".tlb" );
814
815
if (!proxy_name && do_proxies)
816
proxy_name = replace_extension( get_basename(input_name), ".idl", "_p.c" );
817
818
if (!client_name && do_client)
819
client_name = replace_extension( get_basename(input_name), ".idl", "_c.c" );
820
821
if (!server_name && do_server)
822
server_name = replace_extension( get_basename(input_name), ".idl", "_s.c" );
823
824
if (!regscript_name && do_regscript)
825
regscript_name = replace_extension( get_basename(input_name), ".idl", "_r.rgs" );
826
827
if (!idfile_name && do_idfile)
828
idfile_name = replace_extension( get_basename(input_name), ".idl", "_i.c" );
829
830
if (!metadata_name && do_metadata)
831
metadata_name = replace_extension( get_basename(input_name), ".idl", ".winmd" );
832
833
if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
834
if (do_client) client_token = dup_basename_token(client_name,"_c.c");
835
if (do_server) server_token = dup_basename_token(server_name,"_s.c");
836
if (do_regscript) regscript_token = dup_basename_token(regscript_name,"_r.rgs");
837
838
add_widl_version_define();
839
wpp_add_cmdline_define("_WIN32=1");
840
841
atexit(rm_tempfile);
842
if (preprocess_only) exit( wpp_parse( input_name, stdout ) );
843
parser_in = open_input_file( input_name );
844
845
header_token = make_token(header_name);
846
847
init_types();
848
ret = parser_parse();
849
close_all_inputs();
850
if (ret) exit(1);
851
852
/* Everything has been done successfully, don't delete any files. */
853
set_everything(FALSE);
854
local_stubs_name = NULL;
855
856
return 0;
857
}
858
859
static void rm_tempfile(void)
860
{
861
if (do_header)
862
unlink(header_name);
863
if (local_stubs_name)
864
unlink(local_stubs_name);
865
if (do_client)
866
unlink(client_name);
867
if (do_server)
868
unlink(server_name);
869
if (do_regscript)
870
unlink(regscript_name);
871
if (do_idfile)
872
unlink(idfile_name);
873
if (do_proxies)
874
unlink(proxy_name);
875
if (do_typelib)
876
unlink(typelib_name);
877
if (do_metadata)
878
unlink(metadata_name);
879
remove_temp_files();
880
}
881
882
char *find_input_file( const char *name, const char *parent )
883
{
884
char *path;
885
886
/* don't search for a file name with a path in the include directories, for compatibility with MIDL */
887
if (strchr( name, '/' ) || strchr( name, '\\' )) path = xstrdup( name );
888
else if (!(path = wpp_find_include( name, parent ))) error_loc( "Unable to open include file %s\n", name );
889
890
return path;
891
}
892
893
FILE *open_input_file( const char *path )
894
{
895
FILE *file;
896
char *name;
897
int ret;
898
899
if (no_preprocess)
900
{
901
if (!(file = fopen( path, "r" ))) error_loc( "Unable to open %s\n", path );
902
return file;
903
}
904
905
name = make_temp_file( "widl", NULL );
906
if (!(file = fopen( name, "wt" ))) error_loc( "Could not open %s for writing\n", name );
907
ret = wpp_parse( path, file );
908
fclose( file );
909
if (ret) exit( 1 );
910
911
if (!(file = fopen( name, "r" ))) error_loc( "Unable to open %s\n", name );
912
return file;
913
}
914
915