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