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