Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/widl/header.c
4389 views
1
/*
2
* IDL Compiler
3
*
4
* Copyright 2002 Ove Kaaven
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include "config.h"
22
23
#include <stdarg.h>
24
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#include <ctype.h>
28
29
#include "widl.h"
30
#include "utils.h"
31
#include "parser.h"
32
#include "header.h"
33
#include "expr.h"
34
#include "typetree.h"
35
#include "typelib.h"
36
37
static int indentation = 0;
38
static int is_object_interface = 0;
39
user_type_list_t user_type_list = LIST_INIT(user_type_list);
40
context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
41
generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
42
43
static void write_apicontract( FILE *header, type_t *type );
44
static void write_apicontract_guard_start(FILE *header, const expr_t *expr);
45
static void write_apicontract_guard_end(FILE *header, const expr_t *expr);
46
47
static void write_widl_using_macros(FILE *header, type_t *iface);
48
49
static void indent(FILE *h, int delta)
50
{
51
int c;
52
if (delta < 0) indentation += delta;
53
for (c=0; c<indentation; c++) fprintf(h, " ");
54
if (delta > 0) indentation += delta;
55
}
56
57
static void write_line(FILE *f, int delta, const char *fmt, ...)
58
{
59
va_list ap;
60
indent(f, delta);
61
va_start(ap, fmt);
62
vfprintf(f, fmt, ap);
63
va_end(ap);
64
fprintf(f, "\n");
65
}
66
67
static void write_guid(FILE *f, const char *guid_prefix, const char *name, const struct uuid *uuid)
68
{
69
if (!uuid) return;
70
fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
71
"0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
72
guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
73
uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
74
uuid->Data4[6], uuid->Data4[7]);
75
}
76
77
static void write_uuid_decl(FILE *f, type_t *type, const struct uuid *uuid)
78
{
79
fprintf(f, "#ifdef __CRT_UUID_DECL\n");
80
fprintf(f, "__CRT_UUID_DECL(%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
81
"0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
82
type->c_name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
83
uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
84
uuid->Data4[7]);
85
fprintf(f, "#endif\n");
86
}
87
88
static const char *uuid_string(const struct uuid *uuid)
89
{
90
static char buf[37];
91
92
snprintf(buf, sizeof(buf), "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
93
uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2],
94
uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]);
95
96
return buf;
97
}
98
99
static void write_namespace_start(FILE *header, struct namespace *namespace)
100
{
101
if(is_global_namespace(namespace)) {
102
if(use_abi_namespace)
103
write_line(header, 1, "namespace ABI {");
104
return;
105
}
106
107
write_namespace_start(header, namespace->parent);
108
write_line(header, 1, "namespace %s {", namespace->name);
109
}
110
111
static void write_namespace_end(FILE *header, struct namespace *namespace)
112
{
113
if(is_global_namespace(namespace)) {
114
if(use_abi_namespace)
115
write_line(header, -1, "}");
116
return;
117
}
118
119
write_line(header, -1, "}");
120
write_namespace_end(header, namespace->parent);
121
}
122
123
const char *get_name(const var_t *v)
124
{
125
static char *buffer;
126
free( buffer );
127
if (is_attr( v->attrs, ATTR_EVENTADD ))
128
return buffer = strmake( "add_%s", v->name );
129
if (is_attr( v->attrs, ATTR_EVENTREMOVE ))
130
return buffer = strmake( "remove_%s", v->name );
131
if (is_attr( v->attrs, ATTR_PROPGET ))
132
return buffer = strmake( "get_%s", v->name );
133
if (is_attr( v->attrs, ATTR_PROPPUT ))
134
return buffer = strmake( "put_%s", v->name );
135
if (is_attr( v->attrs, ATTR_PROPPUTREF ))
136
return buffer = strmake( "putref_%s", v->name );
137
buffer = NULL;
138
return v->name;
139
}
140
141
static void write_type_definition_left( FILE *h, const decl_spec_t *ds, enum name_type name_type, bool write_callconv );
142
static void write_type_definition( FILE *h, const decl_spec_t *ds, bool is_field, const char *name, enum name_type name_type )
143
{
144
type_t *t = ds->type;
145
146
if (!h) return;
147
if (t) write_type_definition_left( h, ds, name_type, true );
148
if (name) fprintf( h, "%s%s", !t || needs_space_after( t ) ? " " : "", name );
149
if (t) write_type_right( h, t, is_field );
150
}
151
152
static void write_type_v( FILE *h, const decl_spec_t *ds, bool is_field, const char *name, enum name_type name_type )
153
{
154
struct strbuf str = {0};
155
156
if (!h) return;
157
append_declspec( &str, ds, name_type, is_object_interface ? "STDMETHODCALLTYPE" : "", is_field, name );
158
fwrite( str.buf, 1, str.pos, h );
159
}
160
161
static void write_fields(FILE *h, var_list_t *fields, enum name_type name_type)
162
{
163
unsigned nameless_struct_cnt = 0, nameless_struct_i = 0, nameless_union_cnt = 0, nameless_union_i = 0;
164
const char *name;
165
char buf[32];
166
var_t *v;
167
168
if (!fields) return;
169
170
LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
171
if (!v->declspec.type) continue;
172
173
switch(type_get_type_detect_alias(v->declspec.type)) {
174
case TYPE_STRUCT:
175
case TYPE_ENCAPSULATED_UNION:
176
nameless_struct_cnt++;
177
break;
178
case TYPE_UNION:
179
nameless_union_cnt++;
180
break;
181
default:
182
;
183
}
184
}
185
186
LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) {
187
expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT);
188
if (!v->declspec.type) continue;
189
if (contract) write_apicontract_guard_start(h, contract);
190
191
indent(h, 0);
192
name = v->name;
193
194
switch(type_get_type_detect_alias(v->declspec.type)) {
195
case TYPE_STRUCT:
196
case TYPE_ENCAPSULATED_UNION:
197
if(!v->name) {
198
fprintf(h, "__C89_NAMELESS ");
199
if(nameless_struct_cnt == 1) {
200
name = "__C89_NAMELESSSTRUCTNAME";
201
}else if(nameless_struct_i < 5 /* # of supporting macros */) {
202
snprintf(buf, sizeof(buf), "__C89_NAMELESSSTRUCTNAME%d", ++nameless_struct_i);
203
name = buf;
204
}
205
}
206
break;
207
case TYPE_UNION:
208
if(!v->name) {
209
fprintf(h, "__C89_NAMELESS ");
210
if(nameless_union_cnt == 1) {
211
name = "__C89_NAMELESSUNIONNAME";
212
}else if(nameless_union_i < 8 /* # of supporting macros */ ) {
213
snprintf(buf, sizeof(buf), "__C89_NAMELESSUNIONNAME%d", ++nameless_union_i);
214
name = buf;
215
}
216
}
217
break;
218
default:
219
;
220
}
221
if (v->is_defined) write_type_definition( h, &v->declspec, true, name, name_type );
222
else write_type_v( h, &v->declspec, true, name, name_type );
223
fprintf(h, ";\n");
224
if (contract) write_apicontract_guard_end(h, contract);
225
}
226
}
227
228
static void write_enums(FILE *h, var_list_t *enums, const char *enum_name)
229
{
230
var_t *v;
231
if (!enums) return;
232
LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
233
{
234
expr_t *contract = get_attrp(v->attrs, ATTR_CONTRACT);
235
if (contract) write_apicontract_guard_start(h, contract);
236
if (v->name) {
237
indent(h, 0);
238
if(!enum_name)
239
fprintf(h, "%s", get_name(v));
240
else
241
fprintf(h, "%s_%s", enum_name, get_name(v));
242
if (v->eval) {
243
fprintf(h, " = ");
244
write_expr(h, v->eval, 0, 1, NULL, NULL, "");
245
}
246
}
247
if (list_next( enums, &v->entry )) fprintf(h, ",\n");
248
else fprintf(h, "\n");
249
if (contract) write_apicontract_guard_end(h, contract);
250
}
251
}
252
253
static void write_pointer_left(FILE *h, type_t *ref)
254
{
255
struct strbuf str = {0};
256
append_pointer_left( &str, ref, is_object_interface ? "STDMETHODCALLTYPE" : "" );
257
fwrite( str.buf, 1, str.pos, h );
258
}
259
260
static void write_record_type_definition( FILE *header, type_t *type, const char *specifier, enum name_type name_type )
261
{
262
const char *decl_name;
263
264
assert( type->defined );
265
type->written = TRUE;
266
267
if (!(decl_name = type_get_decl_name( type, name_type ))) decl_name = "";
268
fprintf( header, "%s %s%s{\n", specifier, decl_name, *decl_name ? " " : "" );
269
indentation++;
270
271
switch (type_get_type_detect_alias( type ))
272
{
273
case TYPE_ENUM:
274
write_enums( header, type_enum_get_values( type ), is_global_namespace( type->namespace ) ? NULL : type->name );
275
break;
276
case TYPE_STRUCT:
277
write_fields( header, type_struct_get_fields( type ), name_type );
278
break;
279
case TYPE_ENCAPSULATED_UNION:
280
write_fields( header, type_encapsulated_union_get_fields( type ), name_type );
281
break;
282
case TYPE_UNION:
283
write_fields( header, type_union_get_cases( type ), name_type );
284
break;
285
default:
286
/* shouldn't be here */
287
assert( 0 );
288
break;
289
}
290
291
indent( header, -1 );
292
fprintf( header, "}" );
293
}
294
295
static void write_type_definition_left( FILE *h, const decl_spec_t *decl_spec, enum name_type name_type, bool write_callconv )
296
{
297
bool is_const = !!(decl_spec->qualifier & TYPE_QUALIFIER_CONST);
298
type_t *type = decl_spec->type;
299
const char *name;
300
struct strbuf str = {0};
301
302
if (!h) return;
303
304
if (decl_spec->func_specifier & FUNCTION_SPECIFIER_INLINE) fprintf( h, "inline " );
305
if (is_const && (type_is_alias( type ) || !is_ptr( type ))) fprintf( h, "const " );
306
307
if ((name = type_get_name( type, name_type, false ))) fprintf( h, "%s", name );
308
else switch (type_get_type_detect_alias( type ))
309
{
310
case TYPE_ENUM:
311
case TYPE_STRUCT:
312
case TYPE_ENCAPSULATED_UNION:
313
case TYPE_UNION:
314
{
315
const char *specifier = type_get_record_specifier( type );
316
if (!type->written) write_record_type_definition( h, type, specifier, name_type );
317
else if ((name = type_get_name( type, name_type, true )) && winrt_mode && name_type == NAME_DEFAULT) fprintf( h, "%s", name );
318
else fprintf( h, "%s %s", specifier, name ? name : "" );
319
break;
320
}
321
322
case TYPE_POINTER:
323
write_type_definition_left( h, type_pointer_get_ref( type ), name_type, false );
324
write_pointer_left( h, type_pointer_get_ref_type( type ) );
325
if (is_const) fprintf( h, "const " );
326
break;
327
328
case TYPE_ARRAY:
329
write_type_definition_left( h, type_array_get_element( type ), name_type, !type_array_is_decl_as_ptr( type ) );
330
if (type_array_is_decl_as_ptr( type )) write_pointer_left( h, type_array_get_element_type( type ) );
331
break;
332
333
case TYPE_FUNCTION:
334
write_type_definition_left( h, type_function_get_ret( type ), name_type, true );
335
336
/* A pointer to a function has to write the calling convention inside
337
* the parentheses. There's no way to handle that here, so we have to
338
* use an extra parameter to tell us whether to write the calling
339
* convention or not. */
340
if (write_callconv)
341
{
342
const char *callconv = get_attrp( type->attrs, ATTR_CALLCONV );
343
if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
344
if (callconv) fprintf( h, " %s ", callconv );
345
}
346
break;
347
348
case TYPE_BASIC:
349
append_basic_type( &str, type );
350
fwrite( str.buf, 1, str.pos, h );
351
break;
352
case TYPE_BITFIELD:
353
type = type_bitfield_get_field( type );
354
if (!type_is_alias( type )) append_basic_type( &str, type );
355
else strappend( &str, "%s", type_get_name( type, name_type, false ) );
356
fwrite( str.buf, 1, str.pos, h );
357
break;
358
359
case TYPE_INTERFACE:
360
case TYPE_MODULE:
361
case TYPE_COCLASS:
362
case TYPE_RUNTIMECLASS:
363
case TYPE_DELEGATE:
364
case TYPE_VOID:
365
case TYPE_ALIAS:
366
case TYPE_PARAMETERIZED_TYPE:
367
case TYPE_PARAMETER:
368
/* handled elsewhere */
369
assert( 0 );
370
break;
371
case TYPE_APICONTRACT:
372
/* shouldn't be here */
373
assert( 0 );
374
break;
375
}
376
}
377
378
void write_type_left( FILE *h, const decl_spec_t *ds, enum name_type name_type )
379
{
380
struct strbuf str = {0};
381
if (!h) return;
382
append_type_left( &str, ds, name_type, is_object_interface ? "STDMETHODCALLTYPE" : "" );
383
fwrite( str.buf, 1, str.pos, h );
384
}
385
386
void write_type_right( FILE *h, type_t *type, bool is_field )
387
{
388
struct strbuf str = {0};
389
if (!h) return;
390
append_type_right( &str, type, is_object_interface ? "STDMETHODCALLTYPE" : "", is_field );
391
fwrite( str.buf, 1, str.pos, h );
392
}
393
394
static void write_type( FILE *f, type_t *t, bool define )
395
{
396
int in_namespace = t->namespace && !is_global_namespace(t->namespace);
397
decl_spec_t ds = {.type = t};
398
expr_t *contract = get_attrp(t->attrs, ATTR_CONTRACT);
399
400
if (t->written) return;
401
402
if (contract) write_apicontract_guard_start(f, contract);
403
if (winrt_mode && define && type_get_type( t ) == TYPE_ENUM)
404
{
405
fprintf( f, "#ifndef __%s_ENUM_DEFINED__\n", t->c_name );
406
fprintf( f, "#define __%s_ENUM_DEFINED__\n", t->c_name );
407
}
408
if(in_namespace) {
409
fprintf(f, "#ifdef __cplusplus\n");
410
fprintf(f, "} /* extern \"C\" */\n");
411
write_namespace_start(f, t->namespace);
412
}
413
indent(f, 0);
414
if (define) write_type_definition_left( f, &ds, NAME_DEFAULT, true );
415
else write_type_left( f, &ds, NAME_DEFAULT );
416
fprintf(f, ";\n");
417
if(in_namespace) {
418
t->written = false;
419
write_namespace_end(f, t->namespace);
420
fprintf(f, "extern \"C\" {\n");
421
fprintf(f, "#else\n");
422
if (define) write_type_definition_left( f, &ds, NAME_C, true );
423
else write_type_left( f, &ds, NAME_C );
424
fprintf(f, ";\n");
425
if (winrt_mode) write_widl_using_macros(f, t);
426
fprintf(f, "#endif\n\n");
427
}
428
if (winrt_mode && define && type_get_type( t ) == TYPE_ENUM)
429
fprintf( f, "#endif /* __%s_ENUM_DEFINED__ */\n", t->c_name );
430
if (contract) write_apicontract_guard_end(f, contract);
431
}
432
433
void write_type_decl(FILE *f, const decl_spec_t *t, const char *name)
434
{
435
write_type_v( f, t, false, name, NAME_DEFAULT );
436
}
437
438
void write_type_decl_left(FILE *f, const decl_spec_t *ds)
439
{
440
write_type_left( f, ds, NAME_DEFAULT );
441
}
442
443
static int user_type_registered(const char *name)
444
{
445
user_type_t *ut;
446
LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
447
if (!strcmp(name, ut->name))
448
return 1;
449
return 0;
450
}
451
452
static int context_handle_registered(const char *name)
453
{
454
context_handle_t *ch;
455
LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
456
if (!strcmp(name, ch->name))
457
return 1;
458
return 0;
459
}
460
461
static int generic_handle_registered(const char *name)
462
{
463
generic_handle_t *gh;
464
LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
465
if (!strcmp(name, gh->name))
466
return 1;
467
return 0;
468
}
469
470
unsigned int get_context_handle_offset( const type_t *type )
471
{
472
context_handle_t *ch;
473
unsigned int index = 0;
474
475
while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE ))
476
{
477
if (type_is_alias( type )) type = type_alias_get_aliasee_type( type );
478
else if (is_ptr( type )) type = type_pointer_get_ref_type( type );
479
else error( "internal error: %s is not a context handle\n", type->name );
480
}
481
LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry )
482
{
483
if (!strcmp( type->name, ch->name )) return index;
484
index++;
485
}
486
error( "internal error: %s is not registered as a context handle\n", type->name );
487
return index;
488
}
489
490
unsigned int get_generic_handle_offset( const type_t *type )
491
{
492
generic_handle_t *gh;
493
unsigned int index = 0;
494
495
while (!is_attr( type->attrs, ATTR_HANDLE ))
496
{
497
if (type_is_alias( type )) type = type_alias_get_aliasee_type( type );
498
else if (is_ptr( type )) type = type_pointer_get_ref_type( type );
499
else error( "internal error: %s is not a generic handle\n", type->name );
500
}
501
LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry )
502
{
503
if (!strcmp( type->name, gh->name )) return index;
504
index++;
505
}
506
error( "internal error: %s is not registered as a generic handle\n", type->name );
507
return index;
508
}
509
510
/* check for types which require additional prototypes to be generated in the
511
* header */
512
void check_for_additional_prototype_types(type_t *type)
513
{
514
if (!type) return;
515
for (;;) {
516
const char *name = type->name;
517
if (type->user_types_registered) break;
518
type->user_types_registered = 1;
519
if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) {
520
if (!context_handle_registered(name))
521
{
522
context_handle_t *ch = xmalloc(sizeof(*ch));
523
ch->name = xstrdup(name);
524
list_add_tail(&context_handle_list, &ch->entry);
525
}
526
/* don't carry on parsing fields within this type */
527
break;
528
}
529
if ((type_get_type(type) != TYPE_BASIC ||
530
type_basic_get_type(type) != TYPE_BASIC_HANDLE) &&
531
is_attr(type->attrs, ATTR_HANDLE)) {
532
if (!generic_handle_registered(name))
533
{
534
generic_handle_t *gh = xmalloc(sizeof(*gh));
535
gh->name = xstrdup(name);
536
list_add_tail(&generic_handle_list, &gh->entry);
537
}
538
/* don't carry on parsing fields within this type */
539
break;
540
}
541
if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
542
if (!user_type_registered(name))
543
{
544
user_type_t *ut = xmalloc(sizeof *ut);
545
ut->name = xstrdup(name);
546
list_add_tail(&user_type_list, &ut->entry);
547
}
548
/* don't carry on parsing fields within this type as we are already
549
* using a wire marshaled type */
550
break;
551
}
552
else if (type_is_complete(type))
553
{
554
var_list_t *vars;
555
const var_t *v;
556
switch (type_get_type_detect_alias(type))
557
{
558
case TYPE_ENUM:
559
vars = type_enum_get_values(type);
560
break;
561
case TYPE_STRUCT:
562
vars = type_struct_get_fields(type);
563
break;
564
case TYPE_UNION:
565
vars = type_union_get_cases(type);
566
break;
567
default:
568
vars = NULL;
569
break;
570
}
571
if (vars) LIST_FOR_EACH_ENTRY( v, vars, const var_t, entry )
572
check_for_additional_prototype_types(v->declspec.type);
573
}
574
575
if (type_is_alias(type))
576
type = type_alias_get_aliasee_type(type);
577
else if (is_ptr(type))
578
type = type_pointer_get_ref_type(type);
579
else if (is_array(type))
580
type = type_array_get_element_type(type);
581
else
582
break;
583
}
584
}
585
586
static int write_serialize_function_decl(FILE *header, const type_t *type)
587
{
588
write_serialize_functions(header, type, NULL);
589
return 1;
590
}
591
592
static int serializable_exists(FILE *header, const type_t *type)
593
{
594
return 0;
595
}
596
597
static int for_each_serializable(const statement_list_t *stmts, FILE *header,
598
int (*proc)(FILE*, const type_t*))
599
{
600
statement_t *stmt, *iface_stmt;
601
statement_list_t *iface_stmts;
602
typeref_t *ref;
603
604
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry )
605
{
606
if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
607
continue;
608
609
iface_stmts = type_iface_get_stmts(stmt->u.type);
610
if (iface_stmts) LIST_FOR_EACH_ENTRY( iface_stmt, iface_stmts, statement_t, entry )
611
{
612
if (iface_stmt->type != STMT_TYPEDEF) continue;
613
if (iface_stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, iface_stmt->u.type_list, typeref_t, entry)
614
{
615
if (!is_attr(ref->type->attrs, ATTR_ENCODE)
616
&& !is_attr(ref->type->attrs, ATTR_DECODE))
617
continue;
618
if (!proc(header, ref->type))
619
return 0;
620
}
621
}
622
}
623
624
return 1;
625
}
626
627
static void write_user_types(FILE *header)
628
{
629
user_type_t *ut;
630
LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
631
{
632
const char *name = ut->name;
633
fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name);
634
fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name);
635
fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
636
fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name);
637
}
638
}
639
640
static void write_context_handle_rundowns(FILE *header)
641
{
642
context_handle_t *ch;
643
LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
644
{
645
const char *name = ch->name;
646
fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name);
647
}
648
}
649
650
static void write_generic_handle_routines(FILE *header)
651
{
652
generic_handle_t *gh;
653
LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
654
{
655
const char *name = gh->name;
656
fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name);
657
fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name);
658
}
659
}
660
661
static void write_typedef(FILE *header, type_t *type, bool define)
662
{
663
type_t *t = type_alias_get_aliasee_type(type), *root = type_pointer_get_root_type(t);
664
if (winrt_mode && !define && type_get_type( t ) == TYPE_ENUM) write_type( header, t, true );
665
if (winrt_mode && root->namespace && !is_global_namespace(root->namespace))
666
{
667
fprintf(header, "#ifndef __cplusplus\n");
668
fprintf(header, "typedef ");
669
if (define) write_type_definition( header, type_alias_get_aliasee( type ), false, type->c_name, NAME_C );
670
else write_type_v( header, type_alias_get_aliasee( type ), false, type->c_name, NAME_C );
671
fprintf(header, ";\n");
672
if (type_get_type_detect_alias(t) != TYPE_ENUM)
673
{
674
fprintf(header, "#else /* __cplusplus */\n");
675
if (t->namespace && !is_global_namespace(t->namespace)) write_namespace_start(header, t->namespace);
676
indent(header, 0);
677
fprintf(header, "typedef ");
678
write_type_v( header, type_alias_get_aliasee( type ), false, type->name, NAME_DEFAULT );
679
fprintf(header, ";\n");
680
if (t->namespace && !is_global_namespace(t->namespace)) write_namespace_end(header, t->namespace);
681
}
682
fprintf(header, "#endif /* __cplusplus */\n\n");
683
}
684
else
685
{
686
fprintf(header, "typedef ");
687
if (define) write_type_definition( header, type_alias_get_aliasee( type ), false, type->name, NAME_DEFAULT );
688
else write_type_v( header, type_alias_get_aliasee( type ), false, type->name, NAME_DEFAULT );
689
fprintf(header, ";\n");
690
}
691
}
692
693
int is_const_decl(const var_t *var)
694
{
695
const decl_spec_t *t;
696
/* strangely, MIDL accepts a const attribute on any pointer in the
697
* declaration to mean that data isn't being instantiated. this appears
698
* to be a bug, but there is no benefit to being incompatible with MIDL,
699
* so we'll do the same thing */
700
for (t = &var->declspec; ; )
701
{
702
if (t->qualifier & TYPE_QUALIFIER_CONST)
703
return TRUE;
704
else if (is_ptr(t->type))
705
t = type_pointer_get_ref(t->type);
706
else break;
707
}
708
return FALSE;
709
}
710
711
static void write_declaration(FILE *header, const var_t *v)
712
{
713
if (is_const_decl(v) && v->eval)
714
{
715
fprintf(header, "#define %s (", v->name);
716
write_expr(header, v->eval, 0, 1, NULL, NULL, "");
717
fprintf(header, ")\n\n");
718
}
719
else
720
{
721
switch (v->declspec.stgclass)
722
{
723
case STG_NONE:
724
case STG_REGISTER: /* ignored */
725
break;
726
case STG_STATIC:
727
fprintf(header, "static ");
728
break;
729
case STG_EXTERN:
730
fprintf(header, "extern ");
731
break;
732
}
733
if (v->is_defined) write_type_definition( header, &v->declspec, false, v->name, NAME_DEFAULT );
734
else write_type_v( header, &v->declspec, false, v->name, NAME_DEFAULT );
735
fprintf(header, ";\n\n");
736
}
737
}
738
739
static void write_library(FILE *header, const typelib_t *typelib)
740
{
741
const struct uuid *uuid = get_attrp(typelib->attrs, ATTR_UUID);
742
fprintf(header, "\n");
743
write_guid(header, "LIBID", typelib->name, uuid);
744
fprintf(header, "\n");
745
}
746
747
748
const type_t* get_explicit_generic_handle_type(const var_t* var)
749
{
750
const type_t *t;
751
for (t = var->declspec.type;
752
is_ptr(t) || type_is_alias(t);
753
t = type_is_alias(t) ? type_alias_get_aliasee_type(t) : type_pointer_get_ref_type(t))
754
if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) &&
755
is_attr(t->attrs, ATTR_HANDLE))
756
return t;
757
return NULL;
758
}
759
760
const var_t *get_func_handle_var( const type_t *iface, const var_t *func,
761
unsigned char *explicit_fc, unsigned char *implicit_fc )
762
{
763
const var_t *var;
764
const var_list_t *args = type_function_get_args( func->declspec.type );
765
766
*explicit_fc = *implicit_fc = 0;
767
if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
768
{
769
if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue;
770
if (type_get_type( var->declspec.type ) == TYPE_BASIC && type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE)
771
{
772
*explicit_fc = FC_BIND_PRIMITIVE;
773
return var;
774
}
775
if (get_explicit_generic_handle_type( var ))
776
{
777
*explicit_fc = FC_BIND_GENERIC;
778
return var;
779
}
780
if (is_context_handle( var->declspec.type ))
781
{
782
*explicit_fc = FC_BIND_CONTEXT;
783
return var;
784
}
785
}
786
787
if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE )))
788
{
789
if (type_get_type( var->declspec.type ) == TYPE_BASIC &&
790
type_basic_get_type( var->declspec.type ) == TYPE_BASIC_HANDLE)
791
*implicit_fc = FC_BIND_PRIMITIVE;
792
else
793
*implicit_fc = FC_BIND_GENERIC;
794
return var;
795
}
796
797
*implicit_fc = FC_AUTO_HANDLE;
798
return NULL;
799
}
800
801
int has_out_arg_or_return(const var_t *func)
802
{
803
const var_t *var;
804
805
if (!is_void(type_function_get_rettype(func->declspec.type)))
806
return 1;
807
808
if (!type_function_get_args(func->declspec.type))
809
return 0;
810
811
LIST_FOR_EACH_ENTRY( var, type_function_get_args(func->declspec.type), const var_t, entry )
812
if (is_attr(var->attrs, ATTR_OUT))
813
return 1;
814
815
return 0;
816
}
817
818
819
/********** INTERFACES **********/
820
821
int is_object(const type_t *iface)
822
{
823
const attr_t *attr;
824
if (type_is_defined(iface) && (type_get_type(iface) == TYPE_DELEGATE || type_iface_get_inherit(iface)))
825
return 1;
826
if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry )
827
if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
828
return 0;
829
}
830
831
int is_local(const attr_list_t *a)
832
{
833
return is_attr(a, ATTR_LOCAL);
834
}
835
836
const var_t *is_callas(const attr_list_t *a)
837
{
838
return get_attrp(a, ATTR_CALLAS);
839
}
840
841
static int is_inherited_method(const type_t *iface, const var_t *func)
842
{
843
while ((iface = type_iface_get_inherit(iface)))
844
{
845
const statement_t *stmt;
846
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
847
{
848
const var_t *funccmp = stmt->u.var;
849
850
if (!is_callas(func->attrs))
851
{
852
char inherit_name[256];
853
/* compare full name including property prefix */
854
strcpy(inherit_name, get_name(funccmp));
855
if (!strcmp(inherit_name, get_name(func))) return 1;
856
}
857
}
858
}
859
860
return 0;
861
}
862
863
static int is_override_method(const type_t *iface, const type_t *child, const var_t *func)
864
{
865
if (iface == child)
866
return 0;
867
868
do
869
{
870
const statement_t *stmt;
871
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(child))
872
{
873
const var_t *funccmp = stmt->u.var;
874
875
if (!is_callas(func->attrs))
876
{
877
char inherit_name[256];
878
/* compare full name including property prefix */
879
strcpy(inherit_name, get_name(funccmp));
880
if (!strcmp(inherit_name, get_name(func))) return 1;
881
}
882
}
883
}
884
while ((child = type_iface_get_inherit(child)) && child != iface);
885
886
return 0;
887
}
888
889
static int is_aggregate_return(const var_t *func)
890
{
891
enum type_type type = type_get_type(type_function_get_rettype(func->declspec.type));
892
return type == TYPE_STRUCT || type == TYPE_UNION ||
893
type == TYPE_COCLASS || type == TYPE_INTERFACE ||
894
type == TYPE_RUNTIMECLASS;
895
}
896
897
static char *get_vtbl_entry_name(const type_t *iface, const var_t *func)
898
{
899
static char buff[255];
900
if (is_inherited_method(iface, func))
901
snprintf(buff, sizeof(buff), "%s_%s", iface->name, get_name(func));
902
else
903
snprintf(buff, sizeof(buff), "%s", get_name(func));
904
return buff;
905
}
906
907
static void write_method_macro(FILE *header, const type_t *iface, const type_t *child, const char *name)
908
{
909
const statement_t *stmt;
910
int first_iface = 1;
911
912
if (type_iface_get_inherit(iface))
913
write_method_macro(header, type_iface_get_inherit(iface), child, name);
914
915
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
916
{
917
const var_t *func = stmt->u.var;
918
919
if (first_iface)
920
{
921
fprintf(header, "/*** %s methods ***/\n", iface->name);
922
first_iface = 0;
923
}
924
925
if (is_override_method(iface, child, func))
926
continue;
927
928
if (!is_callas(func->attrs)) {
929
const var_t *arg;
930
931
fprintf(header, "#define %s_%s(This", name, get_name(func));
932
if (type_function_get_args(func->declspec.type))
933
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
934
fprintf(header, ",%s", arg->name);
935
fprintf(header, ") ");
936
937
if (is_aggregate_return(func))
938
{
939
fprintf(header, "%s_%s_define_WIDL_C_INLINE_WRAPPERS_for_aggregate_return_support\n", name, get_name(func));
940
continue;
941
}
942
943
fprintf(header, "(This)->lpVtbl->%s(This", get_vtbl_entry_name(iface, func));
944
if (type_function_get_args(func->declspec.type))
945
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
946
fprintf(header, ",%s", arg->name);
947
fprintf(header, ")\n");
948
}
949
}
950
}
951
952
void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent, enum name_type name_type)
953
{
954
const var_t *arg;
955
int count = 0;
956
957
if (do_indent)
958
{
959
indentation++;
960
indent(h, 0);
961
}
962
if (method == 1) {
963
fprintf(h, "%s* This", name);
964
count++;
965
}
966
if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
967
if (count) {
968
if (do_indent)
969
{
970
fprintf(h, ",\n");
971
indent(h, 0);
972
}
973
else fprintf(h, ",");
974
}
975
/* In theory we should be writing the definition using write_type_v(..., arg->define),
976
* but that causes redefinition in e.g. proxy files. In fact MIDL disallows
977
* defining UDTs inside of an argument list. */
978
write_type_v( h, &arg->declspec, false, arg->name, name_type );
979
if (method == 2) {
980
const expr_t *expr = get_attrp(arg->attrs, ATTR_DEFAULTVALUE);
981
if (expr) {
982
const var_t *tail_arg;
983
984
/* Output default value only if all following arguments also have default value. */
985
LIST_FOR_EACH_ENTRY_REV( tail_arg, args, const var_t, entry ) {
986
if(tail_arg == arg) {
987
expr_t bstr;
988
989
/* Fixup the expression type for a BSTR like midl does. */
990
if (get_type_vt(arg->declspec.type) == VT_BSTR && expr->type == EXPR_STRLIT)
991
{
992
bstr = *expr;
993
bstr.type = EXPR_WSTRLIT;
994
expr = &bstr;
995
}
996
997
fprintf(h, " = ");
998
write_expr( h, expr, 0, 1, NULL, NULL, "" );
999
break;
1000
}
1001
if(!get_attrp(tail_arg->attrs, ATTR_DEFAULTVALUE))
1002
break;
1003
}
1004
}
1005
}
1006
count++;
1007
}
1008
if (do_indent) indentation--;
1009
}
1010
1011
static void write_cpp_method_def(FILE *header, const type_t *iface)
1012
{
1013
const statement_t *stmt;
1014
1015
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
1016
{
1017
const var_t *func = stmt->u.var;
1018
if (!is_callas(func->attrs)) {
1019
const decl_spec_t *ret = type_function_get_ret(func->declspec.type);
1020
const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
1021
const var_list_t *args = type_function_get_args(func->declspec.type);
1022
const var_t *arg;
1023
1024
if (!callconv) callconv = "STDMETHODCALLTYPE";
1025
1026
if (is_aggregate_return(func)) {
1027
fprintf(header, "#ifdef WIDL_EXPLICIT_AGGREGATE_RETURNS\n");
1028
1029
indent(header, 0);
1030
fprintf(header, "virtual ");
1031
write_type_decl_left(header, ret);
1032
fprintf(header, "* %s %s(\n", callconv, get_name(func));
1033
++indentation;
1034
indent(header, 0);
1035
write_type_decl_left(header, ret);
1036
fprintf(header, " *__ret");
1037
--indentation;
1038
if (args) {
1039
fprintf(header, ",\n");
1040
write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT);
1041
}
1042
fprintf(header, ") = 0;\n");
1043
1044
indent(header, 0);
1045
write_type_decl_left(header, ret);
1046
fprintf(header, " %s %s(\n", callconv, get_name(func));
1047
write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT);
1048
fprintf(header, ")\n");
1049
indent(header, 0);
1050
fprintf(header, "{\n");
1051
++indentation;
1052
indent(header, 0);
1053
write_type_decl_left(header, ret);
1054
fprintf(header, " __ret;\n");
1055
indent(header, 0);
1056
fprintf(header, "return *%s(&__ret", get_name(func));
1057
if (args)
1058
LIST_FOR_EACH_ENTRY(arg, args, const var_t, entry)
1059
fprintf(header, ", %s", arg->name);
1060
fprintf(header, ");\n");
1061
--indentation;
1062
indent(header, 0);
1063
fprintf(header, "}\n");
1064
1065
fprintf(header, "#else\n");
1066
}
1067
1068
indent(header, 0);
1069
fprintf(header, "virtual ");
1070
write_type_decl_left(header, ret);
1071
fprintf(header, " %s %s(\n", callconv, get_name(func));
1072
write_args(header, args, iface->name, 2, TRUE, NAME_DEFAULT);
1073
fprintf(header, ") = 0;\n");
1074
1075
if (is_aggregate_return(func))
1076
fprintf(header, "#endif\n");
1077
fprintf(header, "\n");
1078
}
1079
}
1080
}
1081
1082
static void write_inline_wrappers(FILE *header, const type_t *iface, const type_t *child, const char *name)
1083
{
1084
const statement_t *stmt;
1085
int first_iface = 1;
1086
1087
if (type_iface_get_inherit(iface))
1088
write_inline_wrappers(header, type_iface_get_inherit(iface), child, name);
1089
1090
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
1091
{
1092
const var_t *func = stmt->u.var;
1093
1094
if (first_iface)
1095
{
1096
fprintf(header, "/*** %s methods ***/\n", iface->name);
1097
first_iface = 0;
1098
}
1099
1100
if (is_override_method(iface, child, func))
1101
continue;
1102
1103
if (!is_callas(func->attrs)) {
1104
const var_t *arg;
1105
1106
fprintf(header, "static inline ");
1107
write_type_decl_left(header, type_function_get_ret(func->declspec.type));
1108
fprintf(header, " %s_%s(", name, get_name(func));
1109
write_args(header, type_function_get_args(func->declspec.type), name, 1, FALSE, NAME_C);
1110
fprintf(header, ") {\n");
1111
++indentation;
1112
if (!is_aggregate_return(func)) {
1113
indent(header, 0);
1114
fprintf(header, "%sThis->lpVtbl->%s(This",
1115
is_void(type_function_get_rettype(func->declspec.type)) ? "" : "return ",
1116
get_vtbl_entry_name(iface, func));
1117
} else {
1118
indent(header, 0);
1119
write_type_decl_left(header, type_function_get_ret(func->declspec.type));
1120
fprintf(header, " __ret;\n");
1121
indent(header, 0);
1122
fprintf(header, "return *This->lpVtbl->%s(This,&__ret", get_vtbl_entry_name(iface, func));
1123
}
1124
if (type_function_get_args(func->declspec.type))
1125
LIST_FOR_EACH_ENTRY( arg, type_function_get_args(func->declspec.type), const var_t, entry )
1126
fprintf(header, ",%s", arg->name);
1127
fprintf(header, ");\n");
1128
--indentation;
1129
fprintf(header, "}\n");
1130
}
1131
}
1132
}
1133
1134
static void do_write_c_method_def(FILE *header, const type_t *iface, const char *name)
1135
{
1136
const statement_t *stmt;
1137
int first_iface = 1;
1138
1139
if (type_iface_get_inherit(iface))
1140
do_write_c_method_def(header, type_iface_get_inherit(iface), name);
1141
1142
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
1143
{
1144
const var_t *func = stmt->u.var;
1145
if (first_iface) {
1146
indent(header, 0);
1147
fprintf(header, "/*** %s methods ***/\n", iface->name);
1148
first_iface = 0;
1149
}
1150
if (!is_callas(func->attrs)) {
1151
const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
1152
if (!callconv) callconv = "STDMETHODCALLTYPE";
1153
indent(header, 0);
1154
write_type_decl_left(header, type_function_get_ret(func->declspec.type));
1155
if (is_aggregate_return(func))
1156
fprintf(header, " *");
1157
if (is_inherited_method(iface, func))
1158
fprintf(header, " (%s *%s_%s)(\n", callconv, iface->name, func->name);
1159
else
1160
fprintf(header, " (%s *%s)(\n", callconv, get_name(func));
1161
++indentation;
1162
indent(header, 0);
1163
fprintf(header, "%s *This", name);
1164
if (is_aggregate_return(func)) {
1165
fprintf(header, ",\n");
1166
indent(header, 0);
1167
write_type_decl_left(header, type_function_get_ret(func->declspec.type));
1168
fprintf(header, " *__ret");
1169
}
1170
--indentation;
1171
if (type_function_get_args(func->declspec.type)) {
1172
fprintf(header, ",\n");
1173
write_args(header, type_function_get_args(func->declspec.type), name, 0, TRUE, NAME_C);
1174
}
1175
fprintf(header, ");\n");
1176
fprintf(header, "\n");
1177
}
1178
}
1179
}
1180
1181
static void write_c_method_def(FILE *header, const type_t *iface)
1182
{
1183
do_write_c_method_def(header, iface, iface->c_name);
1184
}
1185
1186
static void write_c_disp_method_def(FILE *header, const type_t *iface)
1187
{
1188
do_write_c_method_def(header, type_iface_get_inherit(iface), iface->c_name);
1189
}
1190
1191
static void write_method_proto(FILE *header, const type_t *iface)
1192
{
1193
const statement_t *stmt;
1194
1195
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
1196
{
1197
const var_t *func = stmt->u.var;
1198
1199
if (is_callas(func->attrs)) {
1200
const char *callconv = get_attrp(func->declspec.type->attrs, ATTR_CALLCONV);
1201
if (!callconv) callconv = "STDMETHODCALLTYPE";
1202
/* proxy prototype */
1203
write_type_decl_left(header, type_function_get_ret(func->declspec.type));
1204
fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
1205
write_args(header, type_function_get_args(func->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT);
1206
fprintf(header, ");\n");
1207
/* stub prototype */
1208
fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func));
1209
fprintf(header, " IRpcStubBuffer* This,\n");
1210
fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n");
1211
fprintf(header, " PRPC_MESSAGE pRpcMessage,\n");
1212
fprintf(header, " DWORD* pdwStubPhase);\n");
1213
}
1214
}
1215
}
1216
1217
static void write_locals(FILE *fp, const type_t *iface, int body)
1218
{
1219
static const char comment[]
1220
= "/* WIDL-generated stub. You must provide an implementation for this. */";
1221
const statement_t *stmt;
1222
1223
if (!is_object(iface))
1224
return;
1225
1226
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
1227
const var_t *func = stmt->u.var;
1228
const var_t *cas = is_callas(func->attrs);
1229
1230
if (cas) {
1231
const statement_t *stmt2 = NULL;
1232
STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface))
1233
if (!strcmp(get_name(stmt2->u.var), cas->name))
1234
break;
1235
if (&stmt2->entry != type_iface_get_stmts(iface)) {
1236
const var_t *m = stmt2->u.var;
1237
/* proxy prototype - use local prototype */
1238
write_type_decl_left(fp, type_function_get_ret(m->declspec.type));
1239
fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m));
1240
write_args(fp, type_function_get_args(m->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT);
1241
fprintf(fp, ")");
1242
if (body) {
1243
const decl_spec_t *rt = type_function_get_ret(m->declspec.type);
1244
fprintf(fp, "\n{\n");
1245
fprintf(fp, " %s\n", comment);
1246
if (rt->type->name && strcmp(rt->type->name, "HRESULT") == 0)
1247
fprintf(fp, " return E_NOTIMPL;\n");
1248
else if (type_get_type(rt->type) != TYPE_VOID) {
1249
fprintf(fp, " ");
1250
write_type_decl(fp, rt, "rv");
1251
fprintf(fp, ";\n");
1252
fprintf(fp, " memset(&rv, 0, sizeof rv);\n");
1253
fprintf(fp, " return rv;\n");
1254
}
1255
fprintf(fp, "}\n\n");
1256
}
1257
else
1258
fprintf(fp, ";\n");
1259
/* stub prototype - use remotable prototype */
1260
write_type_decl_left(fp, type_function_get_ret(func->declspec.type));
1261
fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m));
1262
write_args(fp, type_function_get_args(func->declspec.type), iface->name, 1, TRUE, NAME_DEFAULT);
1263
fprintf(fp, ")");
1264
if (body)
1265
/* Remotable methods must all return HRESULTs. */
1266
fprintf(fp, "\n{\n %s\n return E_NOTIMPL;\n}\n\n", comment);
1267
else
1268
fprintf(fp, ";\n");
1269
}
1270
else
1271
error_loc("invalid call_as attribute (%s -> %s)\n", func->name, cas->name);
1272
}
1273
}
1274
}
1275
1276
static void write_local_stubs_stmts(FILE *local_stubs, const statement_list_t *stmts)
1277
{
1278
const statement_t *stmt;
1279
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1280
{
1281
if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
1282
write_locals(local_stubs, stmt->u.type, TRUE);
1283
}
1284
}
1285
1286
void write_local_stubs(const statement_list_t *stmts)
1287
{
1288
FILE *local_stubs;
1289
1290
if (!local_stubs_name) return;
1291
1292
local_stubs = fopen(local_stubs_name, "w");
1293
if (!local_stubs) {
1294
error("Could not open %s for output\n", local_stubs_name);
1295
return;
1296
}
1297
fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name);
1298
fprintf(local_stubs, "#include <objbase.h>\n");
1299
fprintf(local_stubs, "#include \"%s\"\n\n", header_name);
1300
1301
write_local_stubs_stmts(local_stubs, stmts);
1302
1303
fclose(local_stubs);
1304
}
1305
1306
static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix)
1307
{
1308
const char *callconv = get_attrp(fun->declspec.type->attrs, ATTR_CALLCONV);
1309
1310
if (!callconv) callconv = "__cdecl";
1311
/* FIXME: do we need to handle call_as? */
1312
write_type_decl_left(header, type_function_get_ret(fun->declspec.type));
1313
fprintf(header, " %s ", callconv);
1314
fprintf(header, "%s%s(\n", prefix, get_name(fun));
1315
if (type_function_get_args(fun->declspec.type))
1316
write_args(header, type_function_get_args(fun->declspec.type), iface->name, 0, TRUE, NAME_DEFAULT);
1317
else
1318
fprintf(header, " void");
1319
fprintf(header, ");\n\n");
1320
}
1321
1322
static void write_parameterized_type_forward(FILE *header, type_t *type)
1323
{
1324
type_t *iface = type->details.parameterized.type;
1325
char *args;
1326
1327
if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
1328
1329
fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
1330
write_namespace_start(header, type->namespace);
1331
1332
args = format_parameterized_type_args(type, "class ", "");
1333
write_line(header, 0, "template <%s>", args);
1334
write_line(header, 0, "struct %s_impl;\n", iface->name);
1335
1336
write_line(header, 0, "template <%s>", args);
1337
free(args);
1338
args = format_parameterized_type_args(type, "", "");
1339
write_line(header, 0, "struct %s : %s_impl<%s> {};", iface->name, iface->name, args);
1340
free(args);
1341
1342
write_namespace_end(header, type->namespace);
1343
fprintf(header, "#endif\n\n" );
1344
}
1345
1346
static void write_parameterized_implementation(FILE *header, type_t *type, bool define)
1347
{
1348
const statement_t *stmt;
1349
typeref_list_t *params = type->details.parameterized.params;
1350
typeref_t *ref;
1351
type_t *iface = type->details.parameterized.type, *base;
1352
char *args = NULL;
1353
1354
fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
1355
write_line(header, 0, "} /* extern \"C\" */");
1356
write_namespace_start(header, type->namespace);
1357
1358
if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
1359
base = type_iface_get_inherit(iface);
1360
1361
args = format_parameterized_type_args(type, "class ", "");
1362
write_line(header, 0, "template <%s>", args);
1363
free(args);
1364
write_line(header, 0, "struct %s_impl%s", iface->name, base ? strmake(" : %s", base->name) : "");
1365
write_line(header, 0, "{");
1366
1367
write_line(header, 1, "private:");
1368
if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
1369
{
1370
write_line(header, 0, "typedef typename Windows::Foundation::Internal::GetAbiType<%s>::type %s_abi;", ref->type->name, ref->type->name);
1371
write_line(header, 0, "typedef typename Windows::Foundation::Internal::GetLogicalType<%s>::type %s_logical;", ref->type->name, ref->type->name);
1372
}
1373
indentation -= 1;
1374
1375
write_line(header, 1, "public:");
1376
if (params) LIST_FOR_EACH_ENTRY(ref, params, typeref_t, entry)
1377
write_line(header, 0, "typedef %s %s_complex;", ref->type->name, ref->type->name);
1378
1379
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
1380
{
1381
const var_t *func = stmt->u.var;
1382
if (is_callas(func->attrs)) continue;
1383
indent(header, 1);
1384
fprintf(header, "virtual ");
1385
write_type_decl_left(header, &func->declspec);
1386
fprintf(header, "%s(", get_name(func));
1387
write_args(header, type_function_get_args(func->declspec.type), NULL, 0, 0, NAME_DEFAULT);
1388
fprintf(header, ") = 0;\n");
1389
indentation -= 1;
1390
}
1391
write_line(header, -1, "};");
1392
1393
write_namespace_end(header, type->namespace);
1394
write_line(header, 0, "extern \"C\" {");
1395
write_line(header, 0, "#endif\n");
1396
}
1397
1398
static void write_forward(FILE *header, type_t *iface)
1399
{
1400
fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->c_name);
1401
fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->c_name);
1402
fprintf(header, "typedef interface %s %s;\n", iface->c_name, iface->c_name);
1403
fprintf(header, "#ifdef __cplusplus\n");
1404
if (iface->namespace && !is_global_namespace(iface->namespace))
1405
fprintf(header, "#define %s %s\n", iface->c_name, iface->qualified_name);
1406
if (!iface->impl_name)
1407
{
1408
write_namespace_start(header, iface->namespace);
1409
write_line(header, 0, "interface %s;", iface->name);
1410
write_namespace_end(header, iface->namespace);
1411
}
1412
fprintf(header, "#endif /* __cplusplus */\n");
1413
fprintf(header, "#endif\n\n" );
1414
}
1415
1416
static char *format_apicontract_macro(const type_t *type)
1417
{
1418
char *name = format_namespace(type->namespace, "", "_", type->name, NULL);
1419
int i;
1420
for (i = strlen(name); i > 0; --i) name[i - 1] = toupper(name[i - 1]);
1421
return name;
1422
}
1423
1424
static void write_apicontract_guard_start(FILE *header, const expr_t *expr)
1425
{
1426
type_t *type;
1427
char *name;
1428
int ver;
1429
if (!winrt_mode) return;
1430
type = expr->u.var->declspec.type;
1431
write_apicontract( header, type );
1432
ver = expr->ref->u.integer.value;
1433
name = format_apicontract_macro(type);
1434
fprintf(header, "#if %s_VERSION >= %#x\n", name, ver);
1435
free(name);
1436
}
1437
1438
static void write_apicontract_guard_end(FILE *header, const expr_t *expr)
1439
{
1440
const type_t *type;
1441
char *name;
1442
int ver;
1443
if (!winrt_mode) return;
1444
type = expr->u.var->declspec.type;
1445
ver = expr->ref->u.integer.value;
1446
name = format_apicontract_macro(type);
1447
fprintf(header, "#endif /* %s_VERSION >= %#x */\n", name, ver);
1448
free(name);
1449
}
1450
1451
static void write_com_interface_start(FILE *header, const type_t *iface)
1452
{
1453
int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
1454
expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
1455
fprintf(header, "/*****************************************************************************\n");
1456
fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : "");
1457
fprintf(header, " */\n");
1458
if (contract) write_apicontract_guard_start(header, contract);
1459
fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->c_name, dispinterface ? "DISP" : "");
1460
fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->c_name, dispinterface ? "DISP" : "");
1461
}
1462
1463
static void write_widl_using_method_macros(FILE *header, const type_t *iface, const type_t *top_iface)
1464
{
1465
const statement_t *stmt;
1466
const char *name = top_iface->short_name ? top_iface->short_name : top_iface->name;
1467
1468
if (type_iface_get_inherit(iface)) write_widl_using_method_macros(header, type_iface_get_inherit(iface), top_iface);
1469
1470
STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
1471
{
1472
const var_t *func = stmt->u.var;
1473
const char *func_name;
1474
1475
if (is_override_method(iface, top_iface, func)) continue;
1476
if (is_callas(func->attrs)) continue;
1477
1478
func_name = get_name(func);
1479
fprintf(header, "#define %s_%s %s_%s\n", name, func_name, top_iface->c_name, func_name);
1480
}
1481
}
1482
1483
static void write_widl_using_macros(FILE *header, type_t *iface)
1484
{
1485
const struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID);
1486
const char *name = iface->short_name ? iface->short_name : iface->name;
1487
char *macro;
1488
1489
if (!strcmp(iface->name, iface->c_name)) return;
1490
1491
macro = format_namespace(iface->namespace, "WIDL_using_", "_", NULL, NULL);
1492
fprintf(header, "#ifdef %s\n", macro);
1493
1494
if (uuid) fprintf(header, "#define IID_%s IID_%s\n", name, iface->c_name);
1495
if (iface->type_type == TYPE_INTERFACE) fprintf(header, "#define %sVtbl %sVtbl\n", name, iface->c_name);
1496
fprintf(header, "#define %s %s\n", name, iface->c_name);
1497
1498
if (iface->type_type == TYPE_INTERFACE) write_widl_using_method_macros(header, iface, iface);
1499
1500
fprintf(header, "#endif /* %s */\n", macro);
1501
free(macro);
1502
}
1503
1504
static void write_com_interface_end(FILE *header, type_t *iface)
1505
{
1506
int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
1507
const struct uuid *uuid = get_attrp(iface->attrs, ATTR_UUID);
1508
expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
1509
type_t *type;
1510
1511
if (uuid)
1512
write_guid(header, dispinterface ? "DIID" : "IID", iface->c_name, uuid);
1513
1514
/* C++ interface */
1515
fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
1516
if (!is_global_namespace(iface->namespace)) {
1517
write_line(header, 0, "} /* extern \"C\" */");
1518
write_namespace_start(header, iface->namespace);
1519
}
1520
if (uuid) {
1521
if (strchr(iface->name, '<')) write_line(header, 0, "template<>");
1522
write_line(header, 0, "MIDL_INTERFACE(\"%s\")", uuid_string(uuid));
1523
indent(header, 0);
1524
}else {
1525
indent(header, 0);
1526
if (strchr(iface->name, '<')) fprintf(header, "template<> struct ");
1527
else fprintf(header, "interface ");
1528
}
1529
if (iface->impl_name)
1530
{
1531
fprintf(header, "%s : %s\n", iface->name, iface->impl_name);
1532
write_line(header, 1, "{");
1533
}
1534
else if (type_iface_get_inherit(iface))
1535
{
1536
fprintf(header, "%s : public %s\n", iface->name,
1537
type_iface_get_inherit(iface)->name);
1538
write_line(header, 1, "{");
1539
}
1540
else
1541
{
1542
fprintf(header, "%s\n", iface->name);
1543
write_line(header, 1, "{\n");
1544
write_line(header, 0, "BEGIN_INTERFACE\n");
1545
}
1546
/* dispinterfaces don't have real functions, so don't write C++ functions for
1547
* them */
1548
if (!dispinterface && !iface->impl_name)
1549
write_cpp_method_def(header, iface);
1550
if (!type_iface_get_inherit(iface) && !iface->impl_name)
1551
write_line(header, 0, "END_INTERFACE\n");
1552
write_line(header, -1, "};");
1553
if (!is_global_namespace(iface->namespace)) {
1554
write_namespace_end(header, iface->namespace);
1555
write_line(header, 0, "extern \"C\" {");
1556
}
1557
if (uuid)
1558
write_uuid_decl(header, iface, uuid);
1559
fprintf(header, "#else\n");
1560
/* C interface */
1561
write_line(header, 1, "typedef struct %sVtbl {", iface->c_name);
1562
write_line(header, 0, "BEGIN_INTERFACE\n");
1563
if (dispinterface)
1564
write_c_disp_method_def(header, iface);
1565
else
1566
write_c_method_def(header, iface);
1567
write_line(header, 0, "END_INTERFACE");
1568
write_line(header, -1, "} %sVtbl;\n", iface->c_name);
1569
fprintf(header, "interface %s {\n", iface->c_name);
1570
fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->c_name);
1571
fprintf(header, "};\n\n");
1572
fprintf(header, "#ifdef COBJMACROS\n");
1573
/* dispinterfaces don't have real functions, so don't write macros for them,
1574
* only for the interface this interface inherits from, i.e. IDispatch */
1575
fprintf(header, "#ifndef WIDL_C_INLINE_WRAPPERS\n");
1576
type = dispinterface ? type_iface_get_inherit(iface) : iface;
1577
write_method_macro(header, type, type, iface->c_name);
1578
fprintf(header, "#else\n");
1579
write_inline_wrappers(header, type, type, iface->c_name);
1580
fprintf(header, "#endif\n");
1581
if (winrt_mode) write_widl_using_macros(header, iface);
1582
fprintf(header, "#endif\n");
1583
fprintf(header, "\n");
1584
fprintf(header, "#endif\n");
1585
fprintf(header, "\n");
1586
/* dispinterfaces don't have real functions, so don't write prototypes for
1587
* them */
1588
if (!dispinterface && !winrt_mode)
1589
{
1590
write_method_proto(header, iface);
1591
write_locals(header, iface, FALSE);
1592
fprintf(header, "\n");
1593
}
1594
fprintf(header, "#endif /* __%s_%sINTERFACE_DEFINED__ */\n", iface->c_name, dispinterface ? "DISP" : "");
1595
if (contract) write_apicontract_guard_end(header, contract);
1596
fprintf(header, "\n");
1597
}
1598
1599
static void write_rpc_interface_start(FILE *header, const type_t *iface)
1600
{
1601
const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
1602
expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
1603
unsigned short major, minor;
1604
1605
get_version( iface->attrs, &major, &minor );
1606
1607
fprintf(header, "/*****************************************************************************\n");
1608
fprintf(header, " * %s interface (v%d.%d)\n", iface->name, major, minor);
1609
fprintf(header, " */\n");
1610
if (contract) write_apicontract_guard_start(header, contract);
1611
fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
1612
fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
1613
if (var)
1614
{
1615
fprintf(header, "extern ");
1616
write_type_decl( header, &var->declspec, var->name );
1617
fprintf(header, ";\n");
1618
}
1619
if (old_names)
1620
{
1621
fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
1622
fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
1623
}
1624
else
1625
{
1626
fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
1627
prefix_client, iface->name, major, minor);
1628
fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
1629
prefix_server, iface->name, major, minor);
1630
}
1631
}
1632
1633
static void write_rpc_interface_end(FILE *header, const type_t *iface)
1634
{
1635
expr_t *contract = get_attrp(iface->attrs, ATTR_CONTRACT);
1636
fprintf(header, "\n#endif /* __%s_INTERFACE_DEFINED__ */\n", iface->name);
1637
if (contract) write_apicontract_guard_end(header, contract);
1638
fprintf(header, "\n");
1639
}
1640
1641
static void write_coclass(FILE *header, type_t *cocl)
1642
{
1643
const struct uuid *uuid = get_attrp(cocl->attrs, ATTR_UUID);
1644
1645
fprintf(header, "/*****************************************************************************\n");
1646
fprintf(header, " * %s coclass\n", cocl->name);
1647
fprintf(header, " */\n\n");
1648
if (uuid)
1649
write_guid(header, "CLSID", cocl->name, uuid);
1650
fprintf(header, "\n#ifdef __cplusplus\n");
1651
if (uuid)
1652
{
1653
fprintf(header, "class DECLSPEC_UUID(\"%s\") %s;\n", uuid_string(uuid), cocl->name);
1654
write_uuid_decl(header, cocl, uuid);
1655
}
1656
else
1657
{
1658
fprintf(header, "class %s;\n", cocl->name);
1659
}
1660
fprintf(header, "#endif\n");
1661
fprintf(header, "\n");
1662
}
1663
1664
static void write_coclass_forward(FILE *header, type_t *cocl)
1665
{
1666
fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
1667
fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
1668
fprintf(header, "#ifdef __cplusplus\n");
1669
fprintf(header, "typedef class %s %s;\n", cocl->name, cocl->name);
1670
fprintf(header, "#else\n");
1671
fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name);
1672
fprintf(header, "#endif /* defined __cplusplus */\n");
1673
fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
1674
}
1675
1676
static void write_apicontract( FILE *header, type_t *apicontract )
1677
{
1678
const version_t *version;
1679
char *name;
1680
if (apicontract->written) return;
1681
name = format_apicontract_macro( apicontract );
1682
version = get_attrp( apicontract->attrs, ATTR_CONTRACTVERSION );
1683
fprintf( header, "#if !defined(%s_VERSION)\n", name );
1684
fprintf( header, "#define %s_VERSION %#x\n", name, (version->major << 16 | version->minor) );
1685
fprintf( header, "#endif // defined(%s_VERSION)\n\n", name );
1686
free( name );
1687
apicontract->written = true;
1688
}
1689
1690
static void write_runtimeclass(FILE *header, type_t *runtimeclass)
1691
{
1692
expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT);
1693
char *name, *c_name;
1694
size_t i, len;
1695
name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL);
1696
c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL);
1697
fprintf(header, "/*\n");
1698
fprintf(header, " * Class %s\n", name);
1699
fprintf(header, " */\n");
1700
if (contract) write_apicontract_guard_start(header, contract);
1701
fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name);
1702
fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name);
1703
fprintf(header, "#if !defined(_MSC_VER) && !defined(__MINGW32__)\n");
1704
fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name);
1705
for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
1706
fprintf(header, "0};\n");
1707
fprintf(header, "#elif defined(__GNUC__) && !defined(__cplusplus)\n");
1708
/* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */
1709
fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L\"%s\";\n", c_name, name);
1710
fprintf(header, "#else\n");
1711
fprintf(header, "extern const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = {", c_name);
1712
for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
1713
fprintf(header, "0};\n");
1714
fprintf(header, "#endif\n");
1715
fprintf(header, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name);
1716
free(c_name);
1717
free(name);
1718
if (contract) write_apicontract_guard_end(header, contract);
1719
fprintf(header, "\n");
1720
}
1721
1722
static void write_runtimeclass_forward(FILE *header, type_t *runtimeclass)
1723
{
1724
fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", runtimeclass->c_name);
1725
fprintf(header, "#define __%s_FWD_DEFINED__\n", runtimeclass->c_name);
1726
fprintf(header, "#ifdef __cplusplus\n");
1727
write_namespace_start(header, runtimeclass->namespace);
1728
write_line(header, 0, "class %s;", runtimeclass->name);
1729
write_namespace_end(header, runtimeclass->namespace);
1730
fprintf(header, "#else\n");
1731
fprintf(header, "typedef struct %s %s;\n", runtimeclass->c_name, runtimeclass->c_name);
1732
fprintf(header, "#endif /* defined __cplusplus */\n");
1733
fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", runtimeclass->c_name);
1734
}
1735
1736
static void write_import(FILE *header, const char *fname)
1737
{
1738
char *hname = replace_extension( get_basename(fname), ".idl", "" );
1739
1740
if (!strendswith( hname, ".h" )) hname = strmake( "%s.h", hname );
1741
fprintf(header, "#include <%s>\n", hname);
1742
free(hname);
1743
}
1744
1745
static void write_imports(FILE *header, const statement_list_t *stmts)
1746
{
1747
const statement_t *stmt;
1748
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1749
{
1750
switch (stmt->type)
1751
{
1752
case STMT_TYPE:
1753
if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
1754
write_imports(header, type_iface_get_stmts(stmt->u.type));
1755
break;
1756
case STMT_TYPEREF:
1757
case STMT_IMPORTLIB:
1758
/* not included in header */
1759
break;
1760
case STMT_IMPORT:
1761
write_import(header, stmt->u.str);
1762
break;
1763
case STMT_TYPEDEF:
1764
case STMT_MODULE:
1765
case STMT_CPPQUOTE:
1766
case STMT_PRAGMA:
1767
case STMT_DECLARATION:
1768
/* not processed here */
1769
break;
1770
case STMT_LIBRARY:
1771
write_imports(header, stmt->u.lib->stmts);
1772
break;
1773
}
1774
}
1775
}
1776
1777
static void write_forward_decls(FILE *header, const statement_list_t *stmts)
1778
{
1779
const statement_t *stmt;
1780
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1781
{
1782
switch (stmt->type)
1783
{
1784
case STMT_TYPE:
1785
if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE)
1786
{
1787
type_t *iface = stmt->u.type;
1788
if (type_get_type(iface) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
1789
if (is_object(iface) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
1790
{
1791
write_forward(header, iface);
1792
if (type_iface_get_async_iface(iface))
1793
write_forward(header, type_iface_get_async_iface(iface));
1794
}
1795
}
1796
else if (type_get_type(stmt->u.type) == TYPE_COCLASS)
1797
write_coclass_forward(header, stmt->u.type);
1798
else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
1799
write_runtimeclass_forward(header, stmt->u.type);
1800
else if (type_get_type(stmt->u.type) == TYPE_PARAMETERIZED_TYPE)
1801
write_parameterized_type_forward(header, stmt->u.type);
1802
break;
1803
case STMT_TYPEREF:
1804
case STMT_IMPORTLIB:
1805
/* not included in header */
1806
break;
1807
case STMT_IMPORT:
1808
case STMT_TYPEDEF:
1809
case STMT_MODULE:
1810
case STMT_CPPQUOTE:
1811
case STMT_PRAGMA:
1812
case STMT_DECLARATION:
1813
/* not processed here */
1814
break;
1815
case STMT_LIBRARY:
1816
write_forward_decls(header, stmt->u.lib->stmts);
1817
break;
1818
}
1819
}
1820
}
1821
1822
static void write_header_stmts( FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs );
1823
1824
static void write_header_com_interface( FILE *header, type_t *iface, const type_t *ref_iface )
1825
{
1826
type_t *inherit_from;
1827
1828
if (iface->written) return;
1829
1830
/* ensure declaration of inherited interface exists before ours (C++ requires this) */
1831
inherit_from = type_iface_get_inherit( iface );
1832
if (inherit_from && !inherit_from->ignore)
1833
write_header_com_interface( header, inherit_from, inherit_from );
1834
1835
write_com_interface_start( header, iface );
1836
write_header_stmts( header, type_iface_get_stmts(iface), ref_iface, TRUE );
1837
write_com_interface_end( header, iface );
1838
1839
iface->written = true;
1840
}
1841
1842
static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs)
1843
{
1844
const statement_t *stmt;
1845
if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1846
{
1847
switch (stmt->type)
1848
{
1849
case STMT_TYPE:
1850
if (type_get_type(stmt->u.type) == TYPE_INTERFACE || type_get_type(stmt->u.type) == TYPE_DELEGATE)
1851
{
1852
type_t *iface = stmt->u.type, *async_iface;
1853
if (type_get_type(stmt->u.type) == TYPE_DELEGATE) iface = type_delegate_get_iface(iface);
1854
async_iface = type_iface_get_async_iface(iface);
1855
if (is_object(iface)) is_object_interface++;
1856
if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type))
1857
{
1858
write_header_com_interface(header, iface, stmt->u.type);
1859
if (async_iface)
1860
{
1861
write_com_interface_start(header, async_iface);
1862
write_com_interface_end(header, async_iface);
1863
}
1864
}
1865
else
1866
{
1867
write_rpc_interface_start(header, iface);
1868
write_header_stmts(header, type_iface_get_stmts(iface), iface, FALSE);
1869
write_rpc_interface_end(header, iface);
1870
}
1871
if (is_object(iface)) is_object_interface--;
1872
}
1873
else if (type_get_type(stmt->u.type) == TYPE_COCLASS)
1874
write_coclass(header, stmt->u.type);
1875
else if (type_get_type(stmt->u.type) == TYPE_APICONTRACT)
1876
write_apicontract(header, stmt->u.type);
1877
else if (type_get_type(stmt->u.type) == TYPE_RUNTIMECLASS)
1878
write_runtimeclass(header, stmt->u.type);
1879
else if (type_get_type( stmt->u.type ) != TYPE_PARAMETERIZED_TYPE)
1880
write_type( header, stmt->u.type, stmt->is_defined );
1881
else
1882
{
1883
is_object_interface++;
1884
write_parameterized_implementation(header, stmt->u.type, stmt->is_defined);
1885
is_object_interface--;
1886
}
1887
break;
1888
case STMT_TYPEREF:
1889
/* FIXME: shouldn't write out forward declarations for undefined
1890
* interfaces but a number of our IDL files depend on this */
1891
if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
1892
write_forward(header, stmt->u.type);
1893
break;
1894
case STMT_IMPORTLIB:
1895
/* not included in header */
1896
break;
1897
case STMT_IMPORT:
1898
/* not processed here */
1899
break;
1900
case STMT_TYPEDEF:
1901
{
1902
typeref_t *ref;
1903
if (stmt->u.type_list) LIST_FOR_EACH_ENTRY(ref, stmt->u.type_list, typeref_t, entry)
1904
write_typedef(header, ref->type, stmt->is_defined);
1905
break;
1906
}
1907
case STMT_LIBRARY:
1908
fprintf(header, "#ifndef __%s_LIBRARY_DEFINED__\n", stmt->u.lib->name);
1909
fprintf(header, "#define __%s_LIBRARY_DEFINED__\n", stmt->u.lib->name);
1910
write_library(header, stmt->u.lib);
1911
write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE);
1912
fprintf(header, "#endif /* __%s_LIBRARY_DEFINED__ */\n", stmt->u.lib->name);
1913
break;
1914
case STMT_MODULE:
1915
fprintf(header, "#ifndef __%s_MODULE_DEFINED__\n", stmt->u.type->name);
1916
fprintf(header, "#define __%s_MODULE_DEFINED__\n", stmt->u.type->name);
1917
write_header_stmts(header, stmt->u.type->details.module->stmts, stmt->u.type, FALSE);
1918
fprintf(header, "#endif /* __%s_MODULE_DEFINED__ */\n", stmt->u.type->name);
1919
break;
1920
case STMT_PRAGMA:
1921
if (!strncmp( stmt->u.str, "pack", 4 )) fprintf(header, "#pragma %s\n", stmt->u.str);
1922
break;
1923
case STMT_CPPQUOTE:
1924
fprintf(header, "%s\n", stmt->u.str);
1925
break;
1926
case STMT_DECLARATION:
1927
if (iface && type_get_type(stmt->u.var->declspec.type) == TYPE_FUNCTION)
1928
{
1929
if (!ignore_funcs)
1930
{
1931
int prefixes_differ = strcmp(prefix_client, prefix_server);
1932
1933
if (prefixes_differ)
1934
{
1935
fprintf(header, "/* client prototype */\n");
1936
write_function_proto(header, iface, stmt->u.var, prefix_client);
1937
fprintf(header, "/* server prototype */\n");
1938
}
1939
write_function_proto(header, iface, stmt->u.var, prefix_server);
1940
}
1941
}
1942
else
1943
write_declaration(header, stmt->u.var);
1944
break;
1945
}
1946
}
1947
}
1948
1949
void write_header(const statement_list_t *stmts)
1950
{
1951
FILE *header;
1952
1953
if (!do_header) return;
1954
1955
if(!(header = fopen(header_name, "w"))) {
1956
error("Could not open %s for output\n", header_name);
1957
return;
1958
}
1959
fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name);
1960
1961
fprintf(header, "#ifdef _WIN32\n");
1962
fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n");
1963
fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n");
1964
fprintf(header, "#endif\n");
1965
fprintf(header, "#include <rpc.h>\n" );
1966
fprintf(header, "#include <rpcndr.h>\n" );
1967
if (!for_each_serializable(stmts, NULL, serializable_exists))
1968
fprintf(header, "#include <midles.h>\n" );
1969
fprintf(header, "#endif\n\n");
1970
1971
fprintf(header, "#ifndef COM_NO_WINDOWS_H\n");
1972
fprintf(header, "#include <windows.h>\n");
1973
fprintf(header, "#include <ole2.h>\n");
1974
fprintf(header, "#endif\n\n");
1975
1976
fprintf(header, "#ifndef __%s__\n", header_token);
1977
fprintf(header, "#define __%s__\n\n", header_token);
1978
1979
fprintf(header, "/* Forward declarations */\n\n");
1980
write_forward_decls(header, stmts);
1981
1982
fprintf(header, "/* Headers for imported files */\n\n");
1983
write_imports(header, stmts);
1984
fprintf(header, "\n");
1985
start_cplusplus_guard(header);
1986
1987
write_header_stmts(header, stmts, NULL, FALSE);
1988
1989
fprintf(header, "/* Begin additional prototypes for all interfaces */\n");
1990
fprintf(header, "\n");
1991
for_each_serializable(stmts, header, write_serialize_function_decl);
1992
write_user_types(header);
1993
write_generic_handle_routines(header);
1994
write_context_handle_rundowns(header);
1995
fprintf(header, "\n");
1996
fprintf(header, "/* End additional prototypes */\n");
1997
fprintf(header, "\n");
1998
1999
end_cplusplus_guard(header);
2000
fprintf(header, "#endif /* __%s__ */\n", header_token);
2001
2002
fclose(header);
2003
}
2004
2005