Update WIDL to rev 20070519.
[reactos.git] / reactos / tools / widl / header.c
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 <stdio.h>
24 #include <stdlib.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <string.h>
29 #include <assert.h>
30 #include <ctype.h>
31 #include <signal.h>
32
33 #include "windef.h"
34 #include "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "header.h"
38
39 static int indentation = 0;
40
41 static void indent(FILE *h, int delta)
42 {
43 int c;
44 if (delta < 0) indentation += delta;
45 for (c=0; c<indentation; c++) fprintf(h, " ");
46 if (delta > 0) indentation += delta;
47 }
48
49 int is_ptrchain_attr(const var_t *var, enum attr_type t)
50 {
51 if (is_attr(var->attrs, t))
52 return 1;
53 else
54 {
55 type_t *type = var->type;
56 for (;;)
57 {
58 if (is_attr(type->attrs, t))
59 return 1;
60 else if (type->kind == TKIND_ALIAS)
61 type = type->orig;
62 else if (is_ptr(type))
63 type = type->ref;
64 else return 0;
65 }
66 }
67 }
68
69 int is_attr(const attr_list_t *list, enum attr_type t)
70 {
71 const attr_t *attr;
72 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
73 if (attr->type == t) return 1;
74 return 0;
75 }
76
77 void *get_attrp(const attr_list_t *list, enum attr_type t)
78 {
79 const attr_t *attr;
80 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
81 if (attr->type == t) return attr->u.pval;
82 return NULL;
83 }
84
85 unsigned long get_attrv(const attr_list_t *list, enum attr_type t)
86 {
87 const attr_t *attr;
88 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
89 if (attr->type == t) return attr->u.ival;
90 return 0;
91 }
92
93 int is_void(const type_t *t)
94 {
95 if (!t->type && !t->ref) return 1;
96 return 0;
97 }
98
99 int is_conformant_array( const array_dims_t *array )
100 {
101 expr_t *dim;
102 if (!array) return 0;
103 dim = LIST_ENTRY( list_head( array ), expr_t, entry );
104 return !dim->is_const;
105 }
106
107 int is_non_void(const expr_list_t *list)
108 {
109 const expr_t *expr;
110
111 if (list)
112 LIST_FOR_EACH_ENTRY( expr, list, const expr_t, entry )
113 if (expr->type != EXPR_VOID) return 1;
114 return 0;
115 }
116
117 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
118 {
119 if (!uuid) return;
120 fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
121 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
122 guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
123 uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
124 uuid->Data4[6], uuid->Data4[7]);
125 }
126
127 void write_name(FILE *h, const var_t *v)
128 {
129 if (is_attr( v->attrs, ATTR_PROPGET ))
130 fprintf(h, "get_" );
131 else if (is_attr( v->attrs, ATTR_PROPPUT ))
132 fprintf(h, "put_" );
133 else if (is_attr( v->attrs, ATTR_PROPPUTREF ))
134 fprintf(h, "putref_" );
135 fprintf(h, "%s", v->name);
136 }
137
138 void write_prefix_name(FILE *h, const char *prefix, const var_t *v)
139 {
140 fprintf(h, "%s", prefix);
141 write_name(h, v);
142 }
143
144 const char* get_name(const var_t *v)
145 {
146 return v->name;
147 }
148
149 void write_array(FILE *h, array_dims_t *dims, int field)
150 {
151 expr_t *v;
152
153 if (!dims) return;
154 fprintf(h, "[");
155 LIST_FOR_EACH_ENTRY( v, dims, expr_t, entry )
156 {
157 if (v->is_const)
158 fprintf(h, "%ld", v->cval); /* statically sized array */
159 else
160 if (field) fprintf(h, "1"); /* dynamically sized array */
161 if (list_next( dims, &v->entry ))
162 fprintf(h, ", ");
163 }
164 fprintf(h, "]");
165 }
166
167 static void write_field(FILE *h, var_t *v)
168 {
169 if (!v) return;
170 if (v->type) {
171 indent(h, 0);
172 write_type(h, v->type);
173 if (get_name(v))
174 fprintf(h, " %s", v->name);
175 else {
176 /* not all C/C++ compilers support anonymous structs and unions */
177 switch (v->type->type) {
178 case RPC_FC_STRUCT:
179 case RPC_FC_CVSTRUCT:
180 case RPC_FC_CPSTRUCT:
181 case RPC_FC_CSTRUCT:
182 case RPC_FC_PSTRUCT:
183 case RPC_FC_BOGUS_STRUCT:
184 case RPC_FC_ENCAPSULATED_UNION:
185 fprintf(h, " DUMMYSTRUCTNAME");
186 break;
187 case RPC_FC_NON_ENCAPSULATED_UNION:
188 fprintf(h, " DUMMYUNIONNAME");
189 break;
190 default:
191 /* ? */
192 break;
193 }
194 }
195 write_array(h, v->array, 1);
196 fprintf(h, ";\n");
197 }
198 }
199
200 static void write_fields(FILE *h, var_list_t *fields)
201 {
202 var_t *v;
203 if (!fields) return;
204 LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v);
205 }
206
207 static void write_enums(FILE *h, var_list_t *enums)
208 {
209 var_t *v;
210 if (!enums) return;
211 LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
212 {
213 if (get_name(v)) {
214 indent(h, 0);
215 write_name(h, v);
216 if (v->eval) {
217 fprintf(h, " = ");
218 write_expr(h, v->eval, 0);
219 }
220 }
221 if (list_next( enums, &v->entry )) fprintf(h, ",\n");
222 }
223 fprintf(h, "\n");
224 }
225
226 static int needs_space_after(type_t *t)
227 {
228 return t->kind == TKIND_ALIAS || ! is_ptr(t);
229 }
230
231 void write_type(FILE *h, type_t *t)
232 {
233 if (t->is_const) fprintf(h, "const ");
234
235 if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name);
236 else {
237 if (t->sign > 0) fprintf(h, "signed ");
238 else if (t->sign < 0) fprintf(h, "unsigned ");
239 switch (t->type) {
240 case RPC_FC_ENUM16:
241 case RPC_FC_ENUM32:
242 if (t->defined && !t->written && !t->ignore) {
243 if (t->name) fprintf(h, "enum %s {\n", t->name);
244 else fprintf(h, "enum {\n");
245 t->written = TRUE;
246 indentation++;
247 write_enums(h, t->fields);
248 indent(h, -1);
249 fprintf(h, "}");
250 }
251 else fprintf(h, "enum %s", t->name);
252 break;
253 case RPC_FC_STRUCT:
254 case RPC_FC_CVSTRUCT:
255 case RPC_FC_CPSTRUCT:
256 case RPC_FC_CSTRUCT:
257 case RPC_FC_PSTRUCT:
258 case RPC_FC_BOGUS_STRUCT:
259 case RPC_FC_ENCAPSULATED_UNION:
260 if (t->defined && !t->written && !t->ignore) {
261 if (t->name) fprintf(h, "struct %s {\n", t->name);
262 else fprintf(h, "struct {\n");
263 t->written = TRUE;
264 indentation++;
265 write_fields(h, t->fields);
266 indent(h, -1);
267 fprintf(h, "}");
268 }
269 else fprintf(h, "struct %s", t->name);
270 break;
271 case RPC_FC_NON_ENCAPSULATED_UNION:
272 if (t->defined && !t->written && !t->ignore) {
273 if (t->name) fprintf(h, "union %s {\n", t->name);
274 else fprintf(h, "union {\n");
275 t->written = TRUE;
276 indentation++;
277 write_fields(h, t->fields);
278 indent(h, -1);
279 fprintf(h, "}");
280 }
281 else fprintf(h, "union %s", t->name);
282 break;
283 case RPC_FC_RP:
284 case RPC_FC_UP:
285 case RPC_FC_FP:
286 case RPC_FC_OP:
287 if (t->ref) write_type(h, t->ref);
288 fprintf(h, "%s*", needs_space_after(t->ref) ? " " : "");
289 break;
290 default:
291 fprintf(h, "%s", t->name);
292 }
293 }
294 }
295
296
297 struct user_type
298 {
299 struct user_type *next;
300 char name[1];
301 };
302
303 static struct user_type *user_type_list;
304
305 static int user_type_registered(const char *name)
306 {
307 struct user_type *ut;
308 for (ut = user_type_list; ut; ut = ut->next)
309 if (!strcmp(name, ut->name))
310 return 1;
311 return 0;
312 }
313
314 static void check_for_user_types(const var_list_t *list)
315 {
316 const var_t *v;
317
318 if (!list) return;
319 LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
320 {
321 type_t *type;
322 for (type = v->type; type; type = type->kind == TKIND_ALIAS ? type->orig : type->ref) {
323 const char *name = type->name;
324 if (type->user_types_registered) continue;
325 type->user_types_registered = 1;
326 if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
327 if (!user_type_registered(name))
328 {
329 struct user_type *ut = xmalloc(sizeof(struct user_type) + strlen(name));
330 strcpy(ut->name, name);
331 ut->next = user_type_list;
332 user_type_list = ut;
333 }
334 /* don't carry on parsing fields within this type as we are already
335 * using a wire marshaled type */
336 break;
337 }
338 else
339 {
340 check_for_user_types(type->fields);
341 }
342 }
343 }
344 }
345
346 void write_user_types(void)
347 {
348 struct user_type *ut;
349 for (ut = user_type_list; ut; ut = ut->next)
350 {
351 const char *name = ut->name;
352 fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name);
353 fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name);
354 fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
355 fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name);
356 }
357 }
358
359 void write_typedef(type_t *type)
360 {
361 fprintf(header, "typedef ");
362 write_type(header, type->orig);
363 fprintf(header, "%s%s;\n", needs_space_after(type->orig) ? " " : "", type->name);
364 }
365
366 void write_expr(FILE *h, const expr_t *e, int brackets)
367 {
368 switch (e->type) {
369 case EXPR_VOID:
370 break;
371 case EXPR_NUM:
372 fprintf(h, "%lu", e->u.lval);
373 break;
374 case EXPR_HEXNUM:
375 fprintf(h, "0x%lx", e->u.lval);
376 break;
377 case EXPR_TRUEFALSE:
378 if (e->u.lval == 0)
379 fprintf(h, "FALSE");
380 else
381 fprintf(h, "TRUE");
382 break;
383 case EXPR_IDENTIFIER:
384 fprintf(h, "%s", e->u.sval);
385 break;
386 case EXPR_NEG:
387 fprintf(h, "-");
388 write_expr(h, e->ref, 1);
389 break;
390 case EXPR_NOT:
391 fprintf(h, "~");
392 write_expr(h, e->ref, 1);
393 break;
394 case EXPR_PPTR:
395 fprintf(h, "*");
396 write_expr(h, e->ref, 1);
397 break;
398 case EXPR_CAST:
399 fprintf(h, "(");
400 write_type(h, e->u.tref);
401 fprintf(h, ")");
402 write_expr(h, e->ref, 1);
403 break;
404 case EXPR_SIZEOF:
405 fprintf(h, "sizeof(");
406 write_type(h, e->u.tref);
407 fprintf(h, ")");
408 break;
409 case EXPR_SHL:
410 case EXPR_SHR:
411 case EXPR_MUL:
412 case EXPR_DIV:
413 case EXPR_ADD:
414 case EXPR_SUB:
415 case EXPR_AND:
416 case EXPR_OR:
417 if (brackets) fprintf(h, "(");
418 write_expr(h, e->ref, 1);
419 switch (e->type) {
420 case EXPR_SHL: fprintf(h, " << "); break;
421 case EXPR_SHR: fprintf(h, " >> "); break;
422 case EXPR_MUL: fprintf(h, " * "); break;
423 case EXPR_DIV: fprintf(h, " / "); break;
424 case EXPR_ADD: fprintf(h, " + "); break;
425 case EXPR_SUB: fprintf(h, " - "); break;
426 case EXPR_AND: fprintf(h, " & "); break;
427 case EXPR_OR: fprintf(h, " | "); break;
428 default: break;
429 }
430 write_expr(h, e->u.ext, 1);
431 if (brackets) fprintf(h, ")");
432 break;
433 case EXPR_COND:
434 if (brackets) fprintf(h, "(");
435 write_expr(h, e->ref, 1);
436 fprintf(h, " ? ");
437 write_expr(h, e->u.ext, 1);
438 fprintf(h, " : ");
439 write_expr(h, e->ext2, 1);
440 if (brackets) fprintf(h, ")");
441 break;
442 }
443 }
444
445 void write_constdef(const var_t *v)
446 {
447 fprintf(header, "#define %s (", get_name(v));
448 write_expr(header, v->eval, 0);
449 fprintf(header, ")\n\n");
450 }
451
452 void write_externdef(const var_t *v)
453 {
454 fprintf(header, "extern const ");
455 write_type(header, v->type);
456 if (get_name(v))
457 fprintf(header, " %s", v->name);
458 fprintf(header, ";\n\n");
459 }
460
461 void write_library(const char *name, const attr_list_t *attr)
462 {
463 const UUID *uuid = get_attrp(attr, ATTR_UUID);
464 fprintf(header, "\n");
465 write_guid(header, "LIBID", name, uuid);
466 fprintf(header, "\n");
467 }
468
469
470 const var_t* get_explicit_handle_var(const func_t* func)
471 {
472 const var_t* var;
473
474 if (!func->args)
475 return NULL;
476
477 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
478 if (var->type->type == RPC_FC_BIND_PRIMITIVE)
479 return var;
480
481 return NULL;
482 }
483
484 int has_out_arg_or_return(const func_t *func)
485 {
486 const var_t *var;
487
488 if (!is_void(func->def->type))
489 return 1;
490
491 if (!func->args)
492 return 0;
493
494 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
495 if (is_attr(var->attrs, ATTR_OUT))
496 return 1;
497
498 return 0;
499 }
500
501
502 /********** INTERFACES **********/
503
504 int is_object(const attr_list_t *list)
505 {
506 const attr_t *attr;
507 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
508 if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
509 return 0;
510 }
511
512 int is_local(const attr_list_t *a)
513 {
514 return is_attr(a, ATTR_LOCAL);
515 }
516
517 const var_t *is_callas(const attr_list_t *a)
518 {
519 return get_attrp(a, ATTR_CALLAS);
520 }
521
522 static void write_method_macro(const type_t *iface, const char *name)
523 {
524 const func_t *cur;
525
526 if (iface->ref) write_method_macro(iface->ref, name);
527
528 if (!iface->funcs) return;
529
530 fprintf(header, "/*** %s methods ***/\n", iface->name);
531 LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
532 {
533 var_t *def = cur->def;
534 if (!is_callas(def->attrs)) {
535 const var_t *arg;
536 int argc = 0;
537 int c;
538
539 if (cur->args) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) argc++;
540
541 fprintf(header, "#define %s_", name);
542 write_name(header,def);
543 fprintf(header, "(p");
544 for (c=0; c<argc; c++)
545 fprintf(header, ",%c", c+'a');
546 fprintf(header, ") ");
547
548 fprintf(header, "(p)->lpVtbl->");
549 write_name(header, def);
550 fprintf(header, "(p");
551 for (c=0; c<argc; c++)
552 fprintf(header, ",%c", c+'a');
553 fprintf(header, ")\n");
554 }
555 }
556 }
557
558 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
559 {
560 const var_t *arg;
561 int count = 0;
562
563 if (do_indent)
564 {
565 indentation++;
566 indent(h, 0);
567 }
568 if (method == 1) {
569 fprintf(h, "%s* This", name);
570 count++;
571 }
572 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
573 if (count) {
574 if (do_indent)
575 {
576 fprintf(h, ",\n");
577 indent(h, 0);
578 }
579 else fprintf(h, ",");
580 }
581 write_type(h, arg->type);
582 if (arg->args)
583 {
584 fprintf(h, " (STDMETHODCALLTYPE *");
585 write_name(h,arg);
586 fprintf(h, ")(");
587 write_args(h, arg->args, NULL, 0, FALSE);
588 fprintf(h, ")");
589 }
590 else
591 {
592 if (needs_space_after(arg->type))
593 fprintf(h, " ");
594 write_name(h, arg);
595 }
596 write_array(h, arg->array, 0);
597 count++;
598 }
599 if (do_indent) indentation--;
600 }
601
602 static void write_cpp_method_def(const type_t *iface)
603 {
604 const func_t *cur;
605
606 if (!iface->funcs) return;
607
608 LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
609 {
610 var_t *def = cur->def;
611 if (!is_callas(def->attrs)) {
612 indent(header, 0);
613 fprintf(header, "virtual ");
614 write_type(header, def->type);
615 fprintf(header, " STDMETHODCALLTYPE ");
616 write_name(header, def);
617 fprintf(header, "(\n");
618 write_args(header, cur->args, iface->name, 2, TRUE);
619 fprintf(header, ") = 0;\n");
620 fprintf(header, "\n");
621 }
622 }
623 }
624
625 static void do_write_c_method_def(const type_t *iface, const char *name)
626 {
627 const func_t *cur;
628
629 if (iface->ref) do_write_c_method_def(iface->ref, name);
630
631 if (!iface->funcs) return;
632 indent(header, 0);
633 fprintf(header, "/*** %s methods ***/\n", iface->name);
634 LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
635 {
636 const var_t *def = cur->def;
637 if (!is_callas(def->attrs)) {
638 indent(header, 0);
639 write_type(header, def->type);
640 fprintf(header, " (STDMETHODCALLTYPE *");
641 write_name(header, def);
642 fprintf(header, ")(\n");
643 write_args(header, cur->args, name, 1, TRUE);
644 fprintf(header, ");\n");
645 fprintf(header, "\n");
646 }
647 }
648 }
649
650 static void write_c_method_def(const type_t *iface)
651 {
652 do_write_c_method_def(iface, iface->name);
653 }
654
655 static void write_c_disp_method_def(const type_t *iface)
656 {
657 do_write_c_method_def(iface->ref, iface->name);
658 }
659
660 static void write_method_proto(const type_t *iface)
661 {
662 const func_t *cur;
663
664 if (!iface->funcs) return;
665 LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
666 {
667 const var_t *def = cur->def;
668 const var_t *cas = is_callas(def->attrs);
669
670 if (!is_local(def->attrs)) {
671 /* proxy prototype */
672 write_type(header, def->type);
673 fprintf(header, " CALLBACK %s_", iface->name);
674 write_name(header, def);
675 fprintf(header, "_Proxy(\n");
676 write_args(header, cur->args, iface->name, 1, TRUE);
677 fprintf(header, ");\n");
678 /* stub prototype */
679 fprintf(header, "void __RPC_STUB %s_", iface->name);
680 write_name(header,def);
681 fprintf(header, "_Stub(\n");
682 fprintf(header, " IRpcStubBuffer* This,\n");
683 fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n");
684 fprintf(header, " PRPC_MESSAGE pRpcMessage,\n");
685 fprintf(header, " DWORD* pdwStubPhase);\n");
686 check_for_user_types(cur->args);
687 }
688 if (cas) {
689 const func_t *m;
690 LIST_FOR_EACH_ENTRY( m, iface->funcs, const func_t, entry )
691 if (!strcmp(get_name(m->def), cas->name)) break;
692 if (&m->entry != iface->funcs) {
693 const var_t *mdef = m->def;
694 /* proxy prototype - use local prototype */
695 write_type(header, mdef->type);
696 fprintf(header, " CALLBACK %s_", iface->name);
697 write_name(header, mdef);
698 fprintf(header, "_Proxy(\n");
699 write_args(header, m->args, iface->name, 1, TRUE);
700 fprintf(header, ");\n");
701 /* stub prototype - use remotable prototype */
702 write_type(header, def->type);
703 fprintf(header, " __RPC_STUB %s_", iface->name);
704 write_name(header, mdef);
705 fprintf(header, "_Stub(\n");
706 write_args(header, cur->args, iface->name, 1, TRUE);
707 fprintf(header, ");\n");
708 }
709 else {
710 parser_warning("invalid call_as attribute (%s -> %s)\n", get_name(def), cas->name);
711 }
712 }
713 }
714 }
715
716 static void write_function_proto(const type_t *iface, const func_t *fun, const char *prefix)
717 {
718 var_t *def = fun->def;
719
720 /* FIXME: do we need to handle call_as? */
721 write_type(header, def->type);
722 fprintf(header, " ");
723 write_prefix_name(header, prefix, def);
724 fprintf(header, "(\n");
725 if (fun->args)
726 write_args(header, fun->args, iface->name, 0, TRUE);
727 else
728 fprintf(header, " void");
729 fprintf(header, ");\n");
730 }
731
732 static void write_function_protos(const type_t *iface)
733 {
734 const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
735 int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
736 const var_t* explicit_handle_var;
737 const func_t *cur;
738 int prefixes_differ = strcmp(prefix_client, prefix_server);
739
740 if (!iface->funcs) return;
741 LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
742 {
743 var_t *def = cur->def;
744
745 /* check for a defined binding handle */
746 explicit_handle_var = get_explicit_handle_var(cur);
747 if (explicit_handle) {
748 if (!explicit_handle_var) {
749 error("%s() does not define an explicit binding handle!\n", def->name);
750 return;
751 }
752 } else if (implicit_handle) {
753 if (explicit_handle_var) {
754 error("%s() must not define a binding handle!\n", def->name);
755 return;
756 }
757 }
758
759 if (prefixes_differ) {
760 fprintf(header, "/* client prototype */\n");
761 write_function_proto(iface, cur, prefix_client);
762 fprintf(header, "/* server prototype */\n");
763 }
764 write_function_proto(iface, cur, prefix_server);
765 }
766 }
767
768 void write_forward(type_t *iface)
769 {
770 /* C/C++ forwards should only be written for object interfaces, so if we
771 * have a full definition we only write one if we find [object] among the
772 * attributes - however, if we don't have a full definition at this point
773 * (i.e. this is an IDL forward), then we also assume that it is an object
774 * interface, since non-object interfaces shouldn't need forwards */
775 if ((!iface->defined || is_object(iface->attrs) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
776 && !iface->written) {
777 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
778 fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
779 fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
780 fprintf(header, "#endif\n\n" );
781 iface->written = TRUE;
782 }
783 }
784
785 static void write_iface_guid(const type_t *iface)
786 {
787 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
788 write_guid(header, "IID", iface->name, uuid);
789 }
790
791 static void write_dispiface_guid(const type_t *iface)
792 {
793 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
794 write_guid(header, "DIID", iface->name, uuid);
795 }
796
797 static void write_coclass_guid(type_t *cocl)
798 {
799 const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
800 write_guid(header, "CLSID", cocl->name, uuid);
801 }
802
803 static void write_com_interface(type_t *iface)
804 {
805 if (!iface->funcs && !iface->ref) {
806 parser_warning("%s has no methods", iface->name);
807 return;
808 }
809
810 fprintf(header, "/*****************************************************************************\n");
811 fprintf(header, " * %s interface\n", iface->name);
812 fprintf(header, " */\n");
813 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
814 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
815 write_iface_guid(iface);
816 write_forward(iface);
817 /* C++ interface */
818 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
819 if (iface->ref)
820 {
821 fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name);
822 fprintf(header, "{\n");
823 indentation++;
824 write_cpp_method_def(iface);
825 indentation--;
826 fprintf(header, "};\n");
827 }
828 else
829 {
830 fprintf(header, "interface %s\n", iface->name);
831 fprintf(header, "{\n");
832 fprintf(header, " BEGIN_INTERFACE\n");
833 fprintf(header, "\n");
834 indentation++;
835 write_cpp_method_def(iface);
836 indentation--;
837 fprintf(header, " END_INTERFACE\n");
838 fprintf(header, "};\n");
839 }
840 fprintf(header, "#else\n");
841 /* C interface */
842 fprintf(header, "typedef struct %sVtbl {\n", iface->name);
843 indentation++;
844 fprintf(header, " BEGIN_INTERFACE\n");
845 fprintf(header, "\n");
846 write_c_method_def(iface);
847 indentation--;
848 fprintf(header, " END_INTERFACE\n");
849 fprintf(header, "} %sVtbl;\n", iface->name);
850 fprintf(header, "interface %s {\n", iface->name);
851 fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
852 fprintf(header, "};\n");
853 fprintf(header, "\n");
854 fprintf(header, "#ifdef COBJMACROS\n");
855 write_method_macro(iface, iface->name);
856 fprintf(header, "#endif\n");
857 fprintf(header, "\n");
858 fprintf(header, "#endif\n");
859 fprintf(header, "\n");
860 write_method_proto(iface);
861 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
862 }
863
864 static void write_rpc_interface(const type_t *iface)
865 {
866 unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
867 const char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
868 static int allocate_written = 0;
869
870 if (!allocate_written)
871 {
872 allocate_written = 1;
873 fprintf(header, "void * __RPC_USER MIDL_user_allocate(size_t);\n");
874 fprintf(header, "void __RPC_USER MIDL_user_free(void *);\n\n");
875 }
876
877 fprintf(header, "/*****************************************************************************\n");
878 fprintf(header, " * %s interface (v%d.%d)\n", iface->name, LOWORD(ver), HIWORD(ver));
879 fprintf(header, " */\n");
880 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
881 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
882 if (iface->funcs)
883 {
884 write_iface_guid(iface);
885 if (var) fprintf(header, "extern handle_t %s;\n", var);
886 if (old_names)
887 {
888 fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
889 fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
890 }
891 else
892 {
893 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
894 prefix_client, iface->name, LOWORD(ver), HIWORD(ver));
895 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
896 prefix_server, iface->name, LOWORD(ver), HIWORD(ver));
897 }
898 write_function_protos(iface);
899 }
900 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
901
902 /* FIXME: server/client code */
903 }
904
905 void write_interface(type_t *iface)
906 {
907 if (is_object(iface->attrs))
908 write_com_interface(iface);
909 else
910 write_rpc_interface(iface);
911 }
912
913 void write_dispinterface(type_t *iface)
914 {
915 fprintf(header, "/*****************************************************************************\n");
916 fprintf(header, " * %s dispinterface\n", iface->name);
917 fprintf(header, " */\n");
918 fprintf(header,"#ifndef __%s_DISPINTERFACE_DEFINED__\n", iface->name);
919 fprintf(header,"#define __%s_DISPINTERFACE_DEFINED__\n\n", iface->name);
920 write_dispiface_guid(iface);
921 write_forward(iface);
922 /* C++ interface */
923 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
924 fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name);
925 fprintf(header, "{\n");
926 fprintf(header, "};\n");
927 fprintf(header, "#else\n");
928 /* C interface */
929 fprintf(header, "typedef struct %sVtbl {\n", iface->name);
930 indentation++;
931 fprintf(header, " BEGIN_INTERFACE\n");
932 fprintf(header, "\n");
933 write_c_disp_method_def(iface);
934 indentation--;
935 fprintf(header, " END_INTERFACE\n");
936 fprintf(header, "} %sVtbl;\n", iface->name);
937 fprintf(header, "interface %s {\n", iface->name);
938 fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
939 fprintf(header, "};\n");
940 fprintf(header, "\n");
941 fprintf(header, "#ifdef COBJMACROS\n");
942 write_method_macro(iface->ref, iface->name);
943 fprintf(header, "#endif\n");
944 fprintf(header, "\n");
945 fprintf(header, "#endif\n");
946 fprintf(header, "\n");
947 fprintf(header,"#endif /* __%s_DISPINTERFACE_DEFINED__ */\n\n", iface->name);
948 }
949
950 void write_coclass(type_t *cocl)
951 {
952 fprintf(header, "/*****************************************************************************\n");
953 fprintf(header, " * %s coclass\n", cocl->name);
954 fprintf(header, " */\n\n");
955 write_coclass_guid(cocl);
956 fprintf(header, "\n");
957 }
958
959 void write_coclass_forward(type_t *cocl)
960 {
961 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
962 fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
963 fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name);
964 fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
965 }