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