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