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