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