- Added creation of dispinterface header.
[wine] / 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_BIND_PRIMITIVE:
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 /********** INTERFACES **********/
431
432 int is_object(attr_t *a)
433 {
434   while (a) {
435     if (a->type == ATTR_OBJECT || a->type == ATTR_ODL) return 1;
436     a = NEXT_LINK(a);
437   }
438   return 0;
439 }
440
441 int is_local(attr_t *a)
442 {
443   return is_attr(a, ATTR_LOCAL);
444 }
445
446 var_t *is_callas(attr_t *a)
447 {
448   return get_attrp(a, ATTR_CALLAS);
449 }
450
451 static int write_method_macro(type_t *iface, char *name)
452 {
453   int idx;
454   func_t *cur = iface->funcs;
455
456   if (iface->ref) idx = write_method_macro(iface->ref, name);
457   else idx = 0;
458
459   if (!cur) return idx;
460   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
461
462   fprintf(header, "/*** %s methods ***/\n", iface->name);
463   while (cur) {
464     var_t *def = cur->def;
465     if (!is_callas(def->attrs)) {
466       var_t *arg = cur->args;
467       int argc = 0;
468       int c;
469       while (arg) {
470         arg = NEXT_LINK(arg);
471         argc++;
472       }
473
474       fprintf(header, "#define %s_", name);
475       write_name(header,def);
476       fprintf(header, "(p");
477       for (c=0; c<argc; c++)
478         fprintf(header, ",%c", c+'a');
479       fprintf(header, ") ");
480
481       fprintf(header, "(p)->lpVtbl->");
482       write_name(header, def);
483       fprintf(header, "(p");
484       for (c=0; c<argc; c++)
485         fprintf(header, ",%c", c+'a');
486       fprintf(header, ")\n");
487       if (cur->idx == -1) cur->idx = idx;
488       else if (cur->idx != idx) yyerror("BUG: method index mismatch in write_method_macro");
489       idx++;
490     }
491     cur = PREV_LINK(cur);
492   }
493   return idx;
494 }
495
496 void write_args(FILE *h, var_t *arg, char *name, int method, int do_indent)
497 {
498   int count = 0;
499   if (arg) {
500     while (NEXT_LINK(arg))
501       arg = NEXT_LINK(arg);
502   }
503   if (do_indent)
504   {
505       if (h == header) {
506           indentation++;
507           indent(0);
508       } else fprintf(h, "    ");
509   }
510   if (method == 1) {
511     fprintf(h, "%s* This", name);
512     count++;
513   }
514   while (arg) {
515     if (count) {
516         if (do_indent)
517         {
518             fprintf(h, ",\n");
519             if (h == header) indent(0);
520             else fprintf(h, "    ");
521         }
522         else fprintf(h, ",");
523     }
524     write_type(h, arg->type, arg, arg->tname);
525     if (arg->args)
526     {
527       fprintf(h, " (STDMETHODCALLTYPE *");
528       write_name(h,arg);
529       fprintf(h, ")(");
530       write_args(h, arg->args, NULL, 0, FALSE);
531       fprintf(h, ")");
532     }
533     else
534     {
535       fprintf(h, " ");
536       write_name(h, arg);
537     }
538     write_array(h, arg->array, 0);
539     arg = PREV_LINK(arg);
540     count++;
541   }
542   if (do_indent && h == header) indentation--;
543 }
544
545 static void write_cpp_method_def(type_t *iface)
546 {
547   func_t *cur = iface->funcs;
548
549   if (!cur) return;
550   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
551   while (cur) {
552     var_t *def = cur->def;
553     if (!is_callas(def->attrs)) {
554       indent(0);
555       fprintf(header, "virtual ");
556       write_type(header, def->type, def, def->tname);
557       fprintf(header, " STDMETHODCALLTYPE ");
558       write_name(header, def);
559       fprintf(header, "(\n");
560       write_args(header, cur->args, iface->name, 2, TRUE);
561       fprintf(header, ") = 0;\n");
562       fprintf(header, "\n");
563     }
564     cur = PREV_LINK(cur);
565   }
566 }
567
568 static void do_write_c_method_def(type_t *iface, char *name)
569 {
570   func_t *cur = iface->funcs;
571
572   if (iface->ref) do_write_c_method_def(iface->ref, name);
573
574   if (!cur) return;
575   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
576   indent(0);
577   fprintf(header, "/*** %s methods ***/\n", iface->name);
578   while (cur) {
579     var_t *def = cur->def;
580     if (!is_callas(def->attrs)) {
581       indent(0);
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, name, 1, TRUE);
587       fprintf(header, ");\n");
588       fprintf(header, "\n");
589     }
590     cur = PREV_LINK(cur);
591   }
592 }
593
594 static void write_c_method_def(type_t *iface)
595 {
596   do_write_c_method_def(iface, iface->name);
597 }
598
599 static void write_c_disp_method_def(type_t *iface)
600 {
601   do_write_c_method_def(iface->ref, iface->name);
602 }
603
604 static void write_method_proto(type_t *iface)
605 {
606   func_t *cur = iface->funcs;
607
608   if (!cur) return;
609   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
610   while (cur) {
611     var_t *def = cur->def;
612     var_t *cas = is_callas(def->attrs);
613     if (!is_local(def->attrs)) {
614       /* proxy prototype */
615       write_type(header, def->type, def, def->tname);
616       fprintf(header, " CALLBACK %s_", iface->name);
617       write_name(header, def);
618       fprintf(header, "_Proxy(\n");
619       write_args(header, cur->args, iface->name, 1, TRUE);
620       fprintf(header, ");\n");
621       /* stub prototype */
622       fprintf(header, "void __RPC_STUB %s_", iface->name);
623       write_name(header,def);
624       fprintf(header, "_Stub(\n");
625       fprintf(header, "    struct IRpcStubBuffer* This,\n");
626       fprintf(header, "    struct IRpcChannelBuffer* pRpcChannelBuffer,\n");
627       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
628       fprintf(header, "    DWORD* pdwStubPhase);\n");
629     }
630     if (cas) {
631       func_t *m = iface->funcs;
632       while (m && strcmp(get_name(m->def), cas->name))
633         m = NEXT_LINK(m);
634       if (m) {
635         var_t *mdef = m->def;
636         /* proxy prototype - use local prototype */
637         write_type(header, mdef->type, mdef, mdef->tname);
638         fprintf(header, " CALLBACK %s_", iface->name);
639         write_name(header, mdef);
640         fprintf(header, "_Proxy(\n");
641         write_args(header, m->args, iface->name, 1, TRUE);
642         fprintf(header, ");\n");
643         /* stub prototype - use remotable prototype */
644         write_type(header, def->type, def, def->tname);
645         fprintf(header, " __RPC_STUB %s_", iface->name);
646         write_name(header, mdef);
647         fprintf(header, "_Stub(\n");
648         write_args(header, cur->args, iface->name, 1, TRUE);
649         fprintf(header, ");\n");
650       }
651       else {
652         yywarning("invalid call_as attribute (%s -> %s)\n", get_name(def), cas->name);
653       }
654     }
655
656     cur = PREV_LINK(cur);
657   }
658 }
659
660 static void write_function_proto(type_t *iface)
661 {
662   func_t *cur = iface->funcs;
663   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
664   while (cur) {
665     var_t *def = cur->def;
666     /* FIXME: do we need to handle call_as? */
667     write_type(header, def->type, def, def->tname);
668     fprintf(header, " ");
669     write_name(header, def);
670     fprintf(header, "(\n");
671     write_args(header, cur->args, iface->name, 0, TRUE);
672     fprintf(header, ");\n");
673
674     cur = PREV_LINK(cur);
675   }
676 }
677
678 void write_forward(type_t *iface)
679 {
680   /* C/C++ forwards should only be written for object interfaces, so if we
681    * have a full definition we only write one if we find [object] among the
682    * attributes - however, if we don't have a full definition at this point
683    * (i.e. this is an IDL forward), then we also assume that it is an object
684    * interface, since non-object interfaces shouldn't need forwards */
685   if ((!iface->defined || is_object(iface->attrs)) && !iface->written) {
686     fprintf(header,"#ifndef __%s_FWD_DEFINED__\n", iface->name);
687     fprintf(header,"#define __%s_FWD_DEFINED__\n", iface->name);
688     fprintf(header, "typedef struct %s %s;\n", iface->name, iface->name);
689     fprintf(header, "#endif\n\n" );
690     iface->written = TRUE;
691   }
692 }
693
694 void write_guid(const char *guid_prefix, const char *name, UUID *uuid)
695 {
696   if (!uuid) return;
697   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",
698           guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
699           uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]);
700 }
701
702 void write_iface_guid(type_t *iface)
703 {
704   UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
705   write_guid("IID", iface->name, uuid);
706
707
708 void write_dispiface_guid(type_t *iface)
709 {
710   UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
711   write_guid("DIID", iface->name, uuid);
712 }
713
714 void write_coclass_guid(class_t *cocl)
715 {
716   UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
717   write_guid("CLSID", cocl->name, uuid);
718 }
719
720 void write_com_interface(type_t *iface)
721 {
722   if (!iface->funcs && !iface->ref) {
723     yywarning("%s has no methods", iface->name);
724     return;
725   }
726
727   fprintf(header, "/*****************************************************************************\n");
728   fprintf(header, " * %s interface\n", iface->name);
729   fprintf(header, " */\n");
730   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
731   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
732   write_iface_guid(iface);
733   write_forward(iface);
734   /* C++ interface */
735   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
736   if (iface->ref)
737   {
738       fprintf(header, "struct %s : public %s\n", iface->name, iface->ref->name);
739       fprintf(header, "{\n");
740       indentation++;
741       write_cpp_method_def(iface);
742       indentation--;
743       fprintf(header, "};\n");
744   }
745   else
746   {
747       fprintf(header, "struct %s\n", iface->name);
748       fprintf(header, "{\n");
749       fprintf(header, "    BEGIN_INTERFACE\n");
750       fprintf(header, "\n");
751       indentation++;
752       write_cpp_method_def(iface);
753       indentation--;
754       fprintf(header, "    END_INTERFACE\n");
755       fprintf(header, "};\n");
756   }
757   fprintf(header, "#else\n");
758   /* C interface */
759   fprintf(header, "typedef struct %sVtbl %sVtbl;\n", iface->name, iface->name);
760   fprintf(header, "struct %s {\n", iface->name);
761   fprintf(header, "    const %sVtbl* lpVtbl;\n", iface->name);
762   fprintf(header, "};\n");
763   fprintf(header, "struct %sVtbl {\n", iface->name);
764   indentation++;
765   fprintf(header, "    BEGIN_INTERFACE\n");
766   fprintf(header, "\n");
767   write_c_method_def(iface);
768   indentation--;
769   fprintf(header, "    END_INTERFACE\n");
770   fprintf(header, "};\n");
771   fprintf(header, "\n");
772   fprintf(header, "#ifdef COBJMACROS\n");
773   write_method_macro(iface, iface->name);
774   fprintf(header, "#endif\n");
775   fprintf(header, "\n");
776   fprintf(header, "#endif\n");
777   fprintf(header, "\n");
778   write_method_proto(iface);
779   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
780 }
781
782 void write_rpc_interface(type_t *iface)
783 {
784   unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
785
786   if (!iface->funcs) return;
787
788   fprintf(header, "/*****************************************************************************\n");
789   fprintf(header, " * %s interface (v%d.%d)\n", iface->name, LOWORD(ver), HIWORD(ver));
790   fprintf(header, " */\n");
791   write_iface_guid(iface);
792   fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_c_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
793   fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_s_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
794   write_function_proto(iface);
795   fprintf(header, "\n");
796
797   /* FIXME: server/client code */
798 }
799
800 void write_interface(type_t *iface)
801 {
802   if (is_object(iface->attrs))
803     write_com_interface(iface);
804   else
805     write_rpc_interface(iface);
806 }
807
808 void write_dispinterface(type_t *iface)
809 {
810   fprintf(header, "/*****************************************************************************\n");
811   fprintf(header, " * %s dispinterface\n", iface->name);
812   fprintf(header, " */\n");
813   fprintf(header,"#ifndef __%s_DISPINTERFACE_DEFINED__\n", iface->name);
814   fprintf(header,"#define __%s_DISPINTERFACE_DEFINED__\n\n", iface->name);
815   write_dispiface_guid(iface);
816   write_forward(iface);
817   /* C++ interface */
818   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
819   fprintf(header, "struct %s : public %s\n", iface->name, iface->ref->name);
820   fprintf(header, "{\n");
821   fprintf(header, "};\n");
822   fprintf(header, "#else\n");
823   /* C interface */
824   fprintf(header, "typedef struct %sVtbl %sVtbl;\n", iface->name, iface->name);
825   fprintf(header, "struct %s {\n", iface->name);
826   fprintf(header, "    const %sVtbl* lpVtbl;\n", iface->name);
827   fprintf(header, "};\n");
828   fprintf(header, "struct %sVtbl {\n", iface->name);
829   indentation++;
830   fprintf(header, "    BEGIN_INTERFACE\n");
831   fprintf(header, "\n");
832   write_c_disp_method_def(iface);
833   indentation--;
834   fprintf(header, "    END_INTERFACE\n");
835   fprintf(header, "};\n");
836   fprintf(header, "\n");
837   fprintf(header, "#ifdef COBJMACROS\n");
838   write_method_macro(iface->ref, iface->name);
839   fprintf(header, "#endif\n");
840   fprintf(header, "\n");
841   fprintf(header, "#endif\n");
842   fprintf(header, "\n");
843   fprintf(header,"#endif  /* __%s_DISPINTERFACE_DEFINED__ */\n\n", iface->name);
844 }
845
846 void write_coclass(class_t *cocl)
847 {
848   fprintf(header, "/*****************************************************************************\n");
849   fprintf(header, " * %s coclass\n", cocl->name);
850   fprintf(header, " */\n\n");
851   write_coclass_guid(cocl);
852   fprintf(header, "\n");
853 }