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