d3drm: Fix leakage of pData2 on error.
[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 <ctype.h>
31
32 #include "widl.h"
33 #include "utils.h"
34 #include "parser.h"
35 #include "header.h"
36 #include "expr.h"
37 #include "typetree.h"
38
39 static int indentation = 0;
40 static int is_object_interface = 0;
41 user_type_list_t user_type_list = LIST_INIT(user_type_list);
42 context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
43 generic_handle_list_t generic_handle_list = LIST_INIT(generic_handle_list);
44
45 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name);
46
47 static void indent(FILE *h, int delta)
48 {
49   int c;
50   if (delta < 0) indentation += delta;
51   for (c=0; c<indentation; c++) fprintf(h, "    ");
52   if (delta > 0) indentation += delta;
53 }
54
55 int is_ptrchain_attr(const var_t *var, enum attr_type t)
56 {
57     if (is_attr(var->attrs, t))
58         return 1;
59     else
60     {
61         type_t *type = var->type;
62         for (;;)
63         {
64             if (is_attr(type->attrs, t))
65                 return 1;
66             else if (type_is_alias(type))
67                 type = type_alias_get_aliasee(type);
68             else if (is_ptr(type))
69                 type = type_pointer_get_ref(type);
70             else return 0;
71         }
72     }
73 }
74
75 int is_aliaschain_attr(const type_t *type, enum attr_type attr)
76 {
77     const type_t *t = type;
78     for (;;)
79     {
80         if (is_attr(t->attrs, attr))
81             return 1;
82         else if (type_is_alias(t))
83             t = type_alias_get_aliasee(t);
84         else return 0;
85     }
86 }
87
88 int is_attr(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 1;
93     return 0;
94 }
95
96 void *get_attrp(const attr_list_t *list, enum attr_type t)
97 {
98     const attr_t *attr;
99     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
100         if (attr->type == t) return attr->u.pval;
101     return NULL;
102 }
103
104 unsigned int get_attrv(const attr_list_t *list, enum attr_type t)
105 {
106     const attr_t *attr;
107     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
108         if (attr->type == t) return attr->u.ival;
109     return 0;
110 }
111
112 int is_void(const type_t *t)
113 {
114     return type_get_type(t) == TYPE_VOID;
115 }
116
117 int is_conformant_array(const type_t *t)
118 {
119     return is_array(t) && type_array_has_conformance(t);
120 }
121
122 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
123 {
124   if (!uuid) return;
125   fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
126         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
127         guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
128         uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
129         uuid->Data4[6], uuid->Data4[7]);
130 }
131
132 static void write_uuid_decl(FILE *f, const char *name, const UUID *uuid)
133 {
134   fprintf(f, "#ifdef __CRT_UUID_DECL\n");
135   fprintf(f, "__CRT_UUID_DECL(%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
136         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
137         name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
138         uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
139         uuid->Data4[7]);
140   fprintf(f, "#endif\n");
141 }
142
143 static const char *uuid_string(const UUID *uuid)
144 {
145   static char buf[37];
146
147   sprintf(buf, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
148         uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], uuid->Data4[2],
149         uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]);
150
151   return buf;
152 }
153
154 const char *get_name(const var_t *v)
155 {
156     static char buffer[256];
157
158     if (is_attr( v->attrs, ATTR_PROPGET ))
159         strcpy( buffer, "get_" );
160     else if (is_attr( v->attrs, ATTR_PROPPUT ))
161         strcpy( buffer, "put_" );
162     else if (is_attr( v->attrs, ATTR_PROPPUTREF ))
163         strcpy( buffer, "putref_" );
164     else
165         buffer[0] = 0;
166     strcat( buffer, v->name );
167     return buffer;
168 }
169
170 static void write_field(FILE *h, var_t *v)
171 {
172   if (!v) return;
173   if (v->type) {
174     indent(h, 0);
175     write_type_def_or_decl(h, v->type, TRUE, v->name);
176     fprintf(h, ";\n");
177   }
178 }
179
180 static void write_fields(FILE *h, var_list_t *fields)
181 {
182     var_t *v;
183     if (!fields) return;
184     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v);
185 }
186
187 static void write_enums(FILE *h, var_list_t *enums)
188 {
189   var_t *v;
190   if (!enums) return;
191   LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
192   {
193     if (v->name) {
194       indent(h, 0);
195       fprintf(h, "%s", get_name(v));
196       if (v->eval) {
197         fprintf(h, " = ");
198         write_expr(h, v->eval, 0, 1, NULL, NULL, "");
199       }
200     }
201     if (list_next( enums, &v->entry )) fprintf(h, ",\n");
202   }
203   fprintf(h, "\n");
204 }
205
206 int needs_space_after(type_t *t)
207 {
208   return (type_is_alias(t) ||
209           (!is_ptr(t) && (!is_array(t) || !type_array_is_decl_as_ptr(t) || t->name)));
210 }
211
212 void write_type_left(FILE *h, type_t *t, int declonly)
213 {
214   if (!h) return;
215
216   if (is_attr(t->attrs, ATTR_CONST) &&
217       (type_is_alias(t) || !is_ptr(t)))
218     fprintf(h, "const ");
219
220   if (type_is_alias(t)) fprintf(h, "%s", t->name);
221   else {
222     switch (type_get_type_detect_alias(t)) {
223       case TYPE_ENUM:
224         if (!declonly && t->defined && !t->written) {
225           if (t->name) fprintf(h, "enum %s {\n", t->name);
226           else fprintf(h, "enum {\n");
227           t->written = TRUE;
228           indentation++;
229           write_enums(h, type_enum_get_values(t));
230           indent(h, -1);
231           fprintf(h, "}");
232         }
233         else fprintf(h, "enum %s", t->name ? t->name : "");
234         break;
235       case TYPE_STRUCT:
236       case TYPE_ENCAPSULATED_UNION:
237         if (!declonly && t->defined && !t->written) {
238           if (t->name) fprintf(h, "struct %s {\n", t->name);
239           else fprintf(h, "struct {\n");
240           t->written = TRUE;
241           indentation++;
242           if (type_get_type(t) != TYPE_STRUCT)
243             write_fields(h, type_encapsulated_union_get_fields(t));
244           else
245             write_fields(h, type_struct_get_fields(t));
246           indent(h, -1);
247           fprintf(h, "}");
248         }
249         else fprintf(h, "struct %s", t->name ? t->name : "");
250         break;
251       case TYPE_UNION:
252         if (!declonly && t->defined && !t->written) {
253           if (t->name) fprintf(h, "union %s {\n", t->name);
254           else fprintf(h, "union {\n");
255           t->written = TRUE;
256           indentation++;
257           write_fields(h, type_union_get_cases(t));
258           indent(h, -1);
259           fprintf(h, "}");
260         }
261         else fprintf(h, "union %s", t->name ? t->name : "");
262         break;
263       case TYPE_POINTER:
264         write_type_left(h, type_pointer_get_ref(t), declonly);
265         fprintf(h, "%s*", needs_space_after(type_pointer_get_ref(t)) ? " " : "");
266         if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
267         break;
268       case TYPE_ARRAY:
269         if (t->name && type_array_is_decl_as_ptr(t))
270           fprintf(h, "%s", t->name);
271         else
272         {
273           write_type_left(h, type_array_get_element(t), declonly);
274           if (type_array_is_decl_as_ptr(t))
275             fprintf(h, "%s*", needs_space_after(type_array_get_element(t)) ? " " : "");
276         }
277         break;
278       case TYPE_BASIC:
279         if (type_basic_get_type(t) != TYPE_BASIC_INT32 &&
280             type_basic_get_type(t) != TYPE_BASIC_INT64 &&
281             type_basic_get_type(t) != TYPE_BASIC_HYPER)
282         {
283           if (type_basic_get_sign(t) < 0) fprintf(h, "signed ");
284           else if (type_basic_get_sign(t) > 0) fprintf(h, "unsigned ");
285         }
286         switch (type_basic_get_type(t))
287         {
288         case TYPE_BASIC_INT8: fprintf(h, "small"); break;
289         case TYPE_BASIC_INT16: fprintf(h, "short"); break;
290         case TYPE_BASIC_INT: fprintf(h, "int"); break;
291         case TYPE_BASIC_INT3264: fprintf(h, "__int3264"); break;
292         case TYPE_BASIC_BYTE: fprintf(h, "byte"); break;
293         case TYPE_BASIC_CHAR: fprintf(h, "char"); break;
294         case TYPE_BASIC_WCHAR: fprintf(h, "wchar_t"); break;
295         case TYPE_BASIC_FLOAT: fprintf(h, "float"); break;
296         case TYPE_BASIC_DOUBLE: fprintf(h, "double"); break;
297         case TYPE_BASIC_ERROR_STATUS_T: fprintf(h, "error_status_t"); break;
298         case TYPE_BASIC_HANDLE: fprintf(h, "handle_t"); break;
299         case TYPE_BASIC_INT32:
300           if (type_basic_get_sign(t) > 0)
301             fprintf(h, "ULONG");
302           else
303             fprintf(h, "LONG");
304           break;
305         case TYPE_BASIC_INT64:
306           if (type_basic_get_sign(t) > 0)
307             fprintf(h, "UINT64");
308           else
309             fprintf(h, "INT64");
310           break;
311         case TYPE_BASIC_HYPER:
312           if (type_basic_get_sign(t) > 0)
313             fprintf(h, "MIDL_uhyper");
314           else
315             fprintf(h, "hyper");
316           break;
317         }
318         break;
319       case TYPE_INTERFACE:
320       case TYPE_MODULE:
321       case TYPE_COCLASS:
322         fprintf(h, "%s", t->name);
323         break;
324       case TYPE_VOID:
325         fprintf(h, "void");
326         break;
327       case TYPE_BITFIELD:
328         write_type_left(h, type_bitfield_get_field(t), declonly);
329         break;
330       case TYPE_ALIAS:
331       case TYPE_FUNCTION:
332         /* handled elsewhere */
333         assert(0);
334         break;
335     }
336   }
337 }
338
339 void write_type_right(FILE *h, type_t *t, int is_field)
340 {
341   if (!h) return;
342
343   switch (type_get_type(t))
344   {
345   case TYPE_ARRAY:
346     if (!type_array_is_decl_as_ptr(t))
347     {
348       if (is_conformant_array(t))
349       {
350         fprintf(h, "[%s]", is_field ? "1" : "");
351         t = type_array_get_element(t);
352       }
353       for ( ;
354            type_get_type(t) == TYPE_ARRAY && !type_array_is_decl_as_ptr(t);
355            t = type_array_get_element(t))
356         fprintf(h, "[%u]", type_array_get_dim(t));
357     }
358     break;
359   case TYPE_BITFIELD:
360     fprintf(h, " : %u", type_bitfield_get_bits(t)->cval);
361     break;
362   case TYPE_VOID:
363   case TYPE_BASIC:
364   case TYPE_ENUM:
365   case TYPE_STRUCT:
366   case TYPE_ENCAPSULATED_UNION:
367   case TYPE_UNION:
368   case TYPE_ALIAS:
369   case TYPE_MODULE:
370   case TYPE_COCLASS:
371   case TYPE_FUNCTION:
372   case TYPE_INTERFACE:
373   case TYPE_POINTER:
374     break;
375   }
376 }
377
378 static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name)
379 {
380   type_t *pt = NULL;
381   int ptr_level = 0;
382
383   if (!h) return;
384
385   if (t) {
386     for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++)
387       ;
388
389     if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
390       int i;
391       const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
392       if (!callconv && is_object_interface) callconv = "STDMETHODCALLTYPE";
393       if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
394       write_type_left(h, type_function_get_rettype(pt), declonly);
395       fputc(' ', h);
396       if (ptr_level) fputc('(', h);
397       if (callconv) fprintf(h, "%s ", callconv);
398       for (i = 0; i < ptr_level; i++)
399         fputc('*', h);
400     } else
401       write_type_left(h, t, declonly);
402   }
403
404   if (name) fprintf(h, "%s%s", !t || needs_space_after(t) ? " " : "", name );
405
406   if (t) {
407     if (type_get_type_detect_alias(pt) == TYPE_FUNCTION) {
408       const var_list_t *args = type_function_get_args(pt);
409
410       if (ptr_level) fputc(')', h);
411       fputc('(', h);
412       if (args)
413           write_args(h, args, NULL, 0, FALSE);
414       else
415           fprintf(h, "void");
416       fputc(')', h);
417     } else
418       write_type_right(h, t, is_field);
419   }
420 }
421
422 static void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name)
423 {
424   write_type_v(f, t, field, FALSE, name);
425 }
426
427 void write_type_decl(FILE *f, type_t *t, const char *name)
428 {
429   write_type_v(f, t, FALSE, TRUE, name);
430 }
431
432 void write_type_decl_left(FILE *f, type_t *t)
433 {
434   write_type_left(f, t, TRUE);
435 }
436
437 static int user_type_registered(const char *name)
438 {
439   user_type_t *ut;
440   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
441     if (!strcmp(name, ut->name))
442       return 1;
443   return 0;
444 }
445
446 static int context_handle_registered(const char *name)
447 {
448   context_handle_t *ch;
449   LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
450     if (!strcmp(name, ch->name))
451       return 1;
452   return 0;
453 }
454
455 static int generic_handle_registered(const char *name)
456 {
457   generic_handle_t *gh;
458   LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
459     if (!strcmp(name, gh->name))
460       return 1;
461   return 0;
462 }
463
464 unsigned int get_context_handle_offset( const type_t *type )
465 {
466     context_handle_t *ch;
467     unsigned int index = 0;
468
469     while (!is_attr( type->attrs, ATTR_CONTEXTHANDLE ))
470     {
471         if (type_is_alias( type )) type = type_alias_get_aliasee( type );
472         else if (is_ptr( type )) type = type_pointer_get_ref( type );
473         else error( "internal error: %s is not a context handle\n", type->name );
474     }
475     LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry )
476     {
477         if (!strcmp( type->name, ch->name )) return index;
478         index++;
479     }
480     error( "internal error: %s is not registered as a context handle\n", type->name );
481     return index;
482 }
483
484 unsigned int get_generic_handle_offset( const type_t *type )
485 {
486     generic_handle_t *gh;
487     unsigned int index = 0;
488
489     while (!is_attr( type->attrs, ATTR_HANDLE ))
490     {
491         if (type_is_alias( type )) type = type_alias_get_aliasee( type );
492         else if (is_ptr( type )) type = type_pointer_get_ref( type );
493         else error( "internal error: %s is not a generic handle\n", type->name );
494     }
495     LIST_FOR_EACH_ENTRY( gh, &generic_handle_list, generic_handle_t, entry )
496     {
497         if (!strcmp( type->name, gh->name )) return index;
498         index++;
499     }
500     error( "internal error: %s is not registered as a generic handle\n", type->name );
501     return index;
502 }
503
504 /* check for types which require additional prototypes to be generated in the
505  * header */
506 void check_for_additional_prototype_types(const var_list_t *list)
507 {
508   const var_t *v;
509
510   if (!list) return;
511   LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
512   {
513     type_t *type = v->type;
514     if (!type) continue;
515     for (;;) {
516       const char *name = type->name;
517       if (type->user_types_registered) break;
518       type->user_types_registered = 1;
519       if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) {
520         if (!context_handle_registered(name))
521         {
522           context_handle_t *ch = xmalloc(sizeof(*ch));
523           ch->name = xstrdup(name);
524           list_add_tail(&context_handle_list, &ch->entry);
525         }
526         /* don't carry on parsing fields within this type */
527         break;
528       }
529       if ((type_get_type(type) != TYPE_BASIC ||
530            type_basic_get_type(type) != TYPE_BASIC_HANDLE) &&
531           is_attr(type->attrs, ATTR_HANDLE)) {
532         if (!generic_handle_registered(name))
533         {
534           generic_handle_t *gh = xmalloc(sizeof(*gh));
535           gh->name = xstrdup(name);
536           list_add_tail(&generic_handle_list, &gh->entry);
537         }
538         /* don't carry on parsing fields within this type */
539         break;
540       }
541       if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
542         if (!user_type_registered(name))
543         {
544           user_type_t *ut = xmalloc(sizeof *ut);
545           ut->name = xstrdup(name);
546           list_add_tail(&user_type_list, &ut->entry);
547         }
548         /* don't carry on parsing fields within this type as we are already
549          * using a wire marshaled type */
550         break;
551       }
552       else if (type_is_complete(type))
553       {
554         var_list_t *vars;
555         switch (type_get_type_detect_alias(type))
556         {
557         case TYPE_ENUM:
558           vars = type_enum_get_values(type);
559           break;
560         case TYPE_STRUCT:
561           vars = type_struct_get_fields(type);
562           break;
563         case TYPE_UNION:
564           vars = type_union_get_cases(type);
565           break;
566         default:
567           vars = NULL;
568           break;
569         }
570         check_for_additional_prototype_types(vars);
571       }
572
573       if (type_is_alias(type))
574         type = type_alias_get_aliasee(type);
575       else if (is_ptr(type))
576         type = type_pointer_get_ref(type);
577       else if (is_array(type))
578         type = type_array_get_element(type);
579       else
580         break;
581     }
582   }
583 }
584
585 static void write_user_types(FILE *header)
586 {
587   user_type_t *ut;
588   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
589   {
590     const char *name = ut->name;
591     fprintf(header, "ULONG           __RPC_USER %s_UserSize     (ULONG *, ULONG, %s *);\n", name, name);
592     fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal  (ULONG *, unsigned char *, %s *);\n", name, name);
593     fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
594     fprintf(header, "void            __RPC_USER %s_UserFree     (ULONG *, %s *);\n", name, name);
595   }
596 }
597
598 static void write_context_handle_rundowns(FILE *header)
599 {
600   context_handle_t *ch;
601   LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
602   {
603     const char *name = ch->name;
604     fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name);
605   }
606 }
607
608 static void write_generic_handle_routines(FILE *header)
609 {
610   generic_handle_t *gh;
611   LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
612   {
613     const char *name = gh->name;
614     fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name);
615     fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name);
616   }
617 }
618
619 static void write_typedef(FILE *header, type_t *type)
620 {
621   fprintf(header, "typedef ");
622   write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name);
623   fprintf(header, ";\n");
624 }
625
626 int is_const_decl(const var_t *var)
627 {
628   const type_t *t;
629   /* strangely, MIDL accepts a const attribute on any pointer in the
630   * declaration to mean that data isn't being instantiated. this appears
631   * to be a bug, but there is no benefit to being incompatible with MIDL,
632   * so we'll do the same thing */
633   for (t = var->type; ; )
634   {
635     if (is_attr(t->attrs, ATTR_CONST))
636       return TRUE;
637     else if (is_ptr(t))
638       t = type_pointer_get_ref(t);
639     else break;
640   }
641   return FALSE;
642 }
643
644 static void write_declaration(FILE *header, const var_t *v)
645 {
646   if (is_const_decl(v) && v->eval)
647   {
648     fprintf(header, "#define %s (", v->name);
649     write_expr(header, v->eval, 0, 1, NULL, NULL, "");
650     fprintf(header, ")\n\n");
651   }
652   else
653   {
654     switch (v->stgclass)
655     {
656       case STG_NONE:
657       case STG_REGISTER: /* ignored */
658         break;
659       case STG_STATIC:
660         fprintf(header, "static ");
661         break;
662       case STG_EXTERN:
663         fprintf(header, "extern ");
664         break;
665     }
666     write_type_def_or_decl(header, v->type, FALSE, v->name);
667     fprintf(header, ";\n\n");
668   }
669 }
670
671 static void write_library(FILE *header, const typelib_t *typelib)
672 {
673   const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID);
674   fprintf(header, "\n");
675   write_guid(header, "LIBID", typelib->name, uuid);
676   fprintf(header, "\n");
677 }
678
679
680 const type_t* get_explicit_generic_handle_type(const var_t* var)
681 {
682     const type_t *t;
683     for (t = var->type;
684          is_ptr(t) || type_is_alias(t);
685          t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t))
686         if ((type_get_type_detect_alias(t) != TYPE_BASIC || type_basic_get_type(t) != TYPE_BASIC_HANDLE) &&
687             is_attr(t->attrs, ATTR_HANDLE))
688             return t;
689     return NULL;
690 }
691
692 const var_t *get_func_handle_var( const type_t *iface, const var_t *func,
693                                   unsigned char *explicit_fc, unsigned char *implicit_fc )
694 {
695     const var_t *var;
696     const var_list_t *args = type_get_function_args( func->type );
697
698     *explicit_fc = *implicit_fc = 0;
699     if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
700     {
701         if (!is_attr( var->attrs, ATTR_IN ) && is_attr( var->attrs, ATTR_OUT )) continue;
702         if (type_get_type( var->type ) == TYPE_BASIC && type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
703         {
704             *explicit_fc = RPC_FC_BIND_PRIMITIVE;
705             return var;
706         }
707         if (get_explicit_generic_handle_type( var ))
708         {
709             *explicit_fc = RPC_FC_BIND_GENERIC;
710             return var;
711         }
712         if (is_context_handle( var->type ))
713         {
714             *explicit_fc = RPC_FC_BIND_CONTEXT;
715             return var;
716         }
717     }
718
719     if ((var = get_attrp( iface->attrs, ATTR_IMPLICIT_HANDLE )))
720     {
721         if (type_get_type( var->type ) == TYPE_BASIC &&
722             type_basic_get_type( var->type ) == TYPE_BASIC_HANDLE)
723             *implicit_fc = RPC_FC_BIND_PRIMITIVE;
724         else
725             *implicit_fc = RPC_FC_BIND_GENERIC;
726         return var;
727     }
728
729     *implicit_fc = RPC_FC_AUTO_HANDLE;
730     return NULL;
731 }
732
733 int has_out_arg_or_return(const var_t *func)
734 {
735     const var_t *var;
736
737     if (!is_void(type_function_get_rettype(func->type)))
738         return 1;
739
740     if (!type_get_function_args(func->type))
741         return 0;
742
743     LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
744         if (is_attr(var->attrs, ATTR_OUT))
745             return 1;
746
747     return 0;
748 }
749
750
751 /********** INTERFACES **********/
752
753 int is_object(const type_t *iface)
754 {
755     const attr_t *attr;
756     if (type_is_defined(iface) && type_iface_get_inherit(iface))
757         return 1;
758     if (iface->attrs) LIST_FOR_EACH_ENTRY( attr, iface->attrs, const attr_t, entry )
759         if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
760     return 0;
761 }
762
763 int is_local(const attr_list_t *a)
764 {
765   return is_attr(a, ATTR_LOCAL);
766 }
767
768 const var_t *is_callas(const attr_list_t *a)
769 {
770   return get_attrp(a, ATTR_CALLAS);
771 }
772
773 static void write_method_macro(FILE *header, const type_t *iface, const char *name)
774 {
775   const statement_t *stmt;
776   int first_iface = 1;
777
778   if (type_iface_get_inherit(iface))
779     write_method_macro(header, type_iface_get_inherit(iface), name);
780
781   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
782   {
783     const var_t *func = stmt->u.var;
784
785     if (first_iface)
786     {
787       fprintf(header, "/*** %s methods ***/\n", iface->name);
788       first_iface = 0;
789     }
790
791     if (!is_callas(func->attrs)) {
792       const var_t *arg;
793
794       fprintf(header, "#define %s_%s(This", name, get_name(func));
795       if (type_get_function_args(func->type))
796           LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
797               fprintf(header, ",%s", arg->name);
798       fprintf(header, ") ");
799
800       fprintf(header, "(This)->lpVtbl->%s(This", get_name(func));
801       if (type_get_function_args(func->type))
802           LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
803               fprintf(header, ",%s", arg->name);
804       fprintf(header, ")\n");
805     }
806   }
807 }
808
809 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
810 {
811   const var_t *arg;
812   int count = 0;
813
814   if (do_indent)
815   {
816       indentation++;
817       indent(h, 0);
818   }
819   if (method == 1) {
820     fprintf(h, "%s* This", name);
821     count++;
822   }
823   if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
824     if (count) {
825         if (do_indent)
826         {
827             fprintf(h, ",\n");
828             indent(h, 0);
829         }
830         else fprintf(h, ",");
831     }
832     write_type_decl(h, arg->type, arg->name);
833     count++;
834   }
835   if (do_indent) indentation--;
836 }
837
838 static void write_cpp_method_def(FILE *header, const type_t *iface)
839 {
840   const statement_t *stmt;
841
842   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
843   {
844     const var_t *func = stmt->u.var;
845     if (!is_callas(func->attrs)) {
846       const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
847       if (!callconv) callconv = "STDMETHODCALLTYPE";
848       indent(header, 0);
849       fprintf(header, "virtual ");
850       write_type_decl_left(header, type_function_get_rettype(func->type));
851       fprintf(header, " %s %s(\n", callconv, get_name(func));
852       write_args(header, type_get_function_args(func->type), iface->name, 2, TRUE);
853       fprintf(header, ") = 0;\n");
854       fprintf(header, "\n");
855     }
856   }
857 }
858
859 static void do_write_c_method_def(FILE *header, const type_t *iface, const char *name)
860 {
861   const statement_t *stmt;
862   int first_iface = 1;
863
864   if (type_iface_get_inherit(iface))
865     do_write_c_method_def(header, type_iface_get_inherit(iface), name);
866
867   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
868   {
869     const var_t *func = stmt->u.var;
870     if (first_iface) {
871       indent(header, 0);
872       fprintf(header, "/*** %s methods ***/\n", iface->name);
873       first_iface = 0;
874     }
875     if (!is_callas(func->attrs)) {
876       const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
877       if (!callconv) callconv = "STDMETHODCALLTYPE";
878       indent(header, 0);
879       write_type_decl_left(header, type_function_get_rettype(func->type));
880       fprintf(header, " (%s *%s)(\n", callconv, get_name(func));
881       write_args(header, type_get_function_args(func->type), name, 1, TRUE);
882       fprintf(header, ");\n");
883       fprintf(header, "\n");
884     }
885   }
886 }
887
888 static void write_c_method_def(FILE *header, const type_t *iface)
889 {
890   do_write_c_method_def(header, iface, iface->name);
891 }
892
893 static void write_c_disp_method_def(FILE *header, const type_t *iface)
894 {
895   do_write_c_method_def(header, type_iface_get_inherit(iface), iface->name);
896 }
897
898 static void write_method_proto(FILE *header, const type_t *iface)
899 {
900   const statement_t *stmt;
901
902   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
903   {
904     const var_t *func = stmt->u.var;
905
906     if (!is_local(func->attrs)) {
907       const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
908       if (!callconv) callconv = "STDMETHODCALLTYPE";
909       /* proxy prototype */
910       write_type_decl_left(header, type_function_get_rettype(func->type));
911       fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
912       write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE);
913       fprintf(header, ");\n");
914       /* stub prototype */
915       fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func));
916       fprintf(header, "    IRpcStubBuffer* This,\n");
917       fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
918       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
919       fprintf(header, "    DWORD* pdwStubPhase);\n");
920     }
921   }
922 }
923
924 static void write_locals(FILE *fp, const type_t *iface, int body)
925 {
926   static const char comment[]
927     = "/* WIDL-generated stub.  You must provide an implementation for this.  */";
928   const statement_t *stmt;
929
930   if (!is_object(iface))
931     return;
932
933   STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
934     const var_t *func = stmt->u.var;
935     const var_t *cas = is_callas(func->attrs);
936
937     if (cas) {
938       const statement_t *stmt2 = NULL;
939       STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface))
940         if (!strcmp(stmt2->u.var->name, cas->name))
941           break;
942       if (&stmt2->entry != type_iface_get_stmts(iface)) {
943         const var_t *m = stmt2->u.var;
944         /* proxy prototype - use local prototype */
945         write_type_decl_left(fp, type_function_get_rettype(m->type));
946         fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m));
947         write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE);
948         fprintf(fp, ")");
949         if (body) {
950           type_t *rt = type_function_get_rettype(m->type);
951           fprintf(fp, "\n{\n");
952           fprintf(fp, "    %s\n", comment);
953           if (rt->name && strcmp(rt->name, "HRESULT") == 0)
954             fprintf(fp, "    return E_NOTIMPL;\n");
955           else if (type_get_type(rt) != TYPE_VOID) {
956             fprintf(fp, "    ");
957             write_type_decl(fp, rt, "rv");
958             fprintf(fp, ";\n");
959             fprintf(fp, "    memset(&rv, 0, sizeof rv);\n");
960             fprintf(fp, "    return rv;\n");
961           }
962           fprintf(fp, "}\n\n");
963         }
964         else
965           fprintf(fp, ";\n");
966         /* stub prototype - use remotable prototype */
967         write_type_decl_left(fp, type_function_get_rettype(func->type));
968         fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m));
969         write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE);
970         fprintf(fp, ")");
971         if (body)
972           /* Remotable methods must all return HRESULTs.  */
973           fprintf(fp, "\n{\n    %s\n    return E_NOTIMPL;\n}\n\n", comment);
974         else
975           fprintf(fp, ";\n");
976       }
977       else
978         error_loc("invalid call_as attribute (%s -> %s)\n", func->name, cas->name);
979     }
980   }
981 }
982
983 static void write_local_stubs_stmts(FILE *local_stubs, const statement_list_t *stmts)
984 {
985   const statement_t *stmt;
986   if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
987   {
988     if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
989       write_locals(local_stubs, stmt->u.type, TRUE);
990   }
991 }
992
993 void write_local_stubs(const statement_list_t *stmts)
994 {
995   FILE *local_stubs;
996
997   if (!local_stubs_name) return;
998
999   local_stubs = fopen(local_stubs_name, "w");
1000   if (!local_stubs) {
1001     error("Could not open %s for output\n", local_stubs_name);
1002     return;
1003   }
1004   fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name);
1005   fprintf(local_stubs, "#include <objbase.h>\n");
1006   fprintf(local_stubs, "#include \"%s\"\n\n", header_name);
1007
1008   write_local_stubs_stmts(local_stubs, stmts);
1009
1010   fclose(local_stubs);
1011 }
1012
1013 static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix)
1014 {
1015   const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV);
1016
1017   if (!callconv) callconv = "__cdecl";
1018   /* FIXME: do we need to handle call_as? */
1019   write_type_decl_left(header, type_function_get_rettype(fun->type));
1020   fprintf(header, " %s ", callconv);
1021   fprintf(header, "%s%s(\n", prefix, get_name(fun));
1022   if (type_get_function_args(fun->type))
1023     write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE);
1024   else
1025     fprintf(header, "    void");
1026   fprintf(header, ");\n\n");
1027 }
1028
1029 static void write_forward(FILE *header, type_t *iface)
1030 {
1031   fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
1032   fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
1033   fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
1034   fprintf(header, "#endif\n\n" );
1035 }
1036
1037 static void write_com_interface_start(FILE *header, const type_t *iface)
1038 {
1039   int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
1040   fprintf(header, "/*****************************************************************************\n");
1041   fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : "");
1042   fprintf(header, " */\n");
1043   fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->name, dispinterface ? "DISP" : "");
1044   fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->name, dispinterface ? "DISP" : "");
1045 }
1046
1047 static void write_com_interface_end(FILE *header, type_t *iface)
1048 {
1049   int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
1050   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
1051
1052   if (uuid)
1053       write_guid(header, dispinterface ? "DIID" : "IID", iface->name, uuid);
1054
1055   /* C++ interface */
1056   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
1057   if (uuid)
1058       fprintf(header, "MIDL_INTERFACE(\"%s\")\n", uuid_string(uuid));
1059   else
1060       fprintf(header, "interface ");
1061   if (type_iface_get_inherit(iface))
1062   {
1063     fprintf(header, "%s : public %s\n", iface->name,
1064             type_iface_get_inherit(iface)->name);
1065     fprintf(header, "{\n");
1066   }
1067   else
1068   {
1069     fprintf(header, "%s\n", iface->name);
1070     fprintf(header, "{\n");
1071     fprintf(header, "    BEGIN_INTERFACE\n");
1072     fprintf(header, "\n");
1073   }
1074   /* dispinterfaces don't have real functions, so don't write C++ functions for
1075    * them */
1076   if (!dispinterface)
1077   {
1078     indentation++;
1079     write_cpp_method_def(header, iface);
1080     indentation--;
1081   }
1082   if (!type_iface_get_inherit(iface))
1083     fprintf(header, "    END_INTERFACE\n");
1084   fprintf(header, "};\n");
1085   if (uuid)
1086       write_uuid_decl(header, iface->name, uuid);
1087   fprintf(header, "#else\n");
1088   /* C interface */
1089   fprintf(header, "typedef struct %sVtbl {\n", iface->name);
1090   indentation++;
1091   fprintf(header, "    BEGIN_INTERFACE\n");
1092   fprintf(header, "\n");
1093   if (dispinterface)
1094     write_c_disp_method_def(header, iface);
1095   else
1096     write_c_method_def(header, iface);
1097   indentation--;
1098   fprintf(header, "    END_INTERFACE\n");
1099   fprintf(header, "} %sVtbl;\n", iface->name);
1100   fprintf(header, "interface %s {\n", iface->name);
1101   fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
1102   fprintf(header, "};\n");
1103   fprintf(header, "\n");
1104   fprintf(header, "#ifdef COBJMACROS\n");
1105   /* dispinterfaces don't have real functions, so don't write macros for them,
1106    * only for the interface this interface inherits from, i.e. IDispatch */
1107   write_method_macro(header, dispinterface ? type_iface_get_inherit(iface) : iface, iface->name);
1108   fprintf(header, "#endif\n");
1109   fprintf(header, "\n");
1110   fprintf(header, "#endif\n");
1111   fprintf(header, "\n");
1112   /* dispinterfaces don't have real functions, so don't write prototypes for
1113    * them */
1114   if (!dispinterface)
1115   {
1116     write_method_proto(header, iface);
1117     write_locals(header, iface, FALSE);
1118     fprintf(header, "\n");
1119   }
1120   fprintf(header,"#endif  /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->name, dispinterface ? "DISP" : "");
1121 }
1122
1123 static void write_rpc_interface_start(FILE *header, const type_t *iface)
1124 {
1125   unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
1126   const var_t *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
1127
1128   fprintf(header, "/*****************************************************************************\n");
1129   fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1130   fprintf(header, " */\n");
1131   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
1132   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
1133   if (var)
1134   {
1135       fprintf(header, "extern ");
1136       write_type_decl( header, var->type, var->name );
1137       fprintf(header, ";\n");
1138   }
1139   if (old_names)
1140   {
1141       fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
1142       fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
1143   }
1144   else
1145   {
1146       fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
1147               prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1148       fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
1149               prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1150   }
1151 }
1152
1153 static void write_rpc_interface_end(FILE *header, const type_t *iface)
1154 {
1155   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
1156 }
1157
1158 static void write_coclass(FILE *header, type_t *cocl)
1159 {
1160   const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
1161
1162   fprintf(header, "/*****************************************************************************\n");
1163   fprintf(header, " * %s coclass\n", cocl->name);
1164   fprintf(header, " */\n\n");
1165   if (uuid)
1166       write_guid(header, "CLSID", cocl->name, uuid);
1167   fprintf(header, "\n#ifdef __cplusplus\n");
1168   if (uuid)
1169   {
1170       fprintf(header, "class DECLSPEC_UUID(\"%s\") %s;\n", uuid_string(uuid), cocl->name);
1171       write_uuid_decl(header, cocl->name, uuid);
1172   }
1173   else
1174   {
1175       fprintf(header, "class %s;\n", cocl->name);
1176   }
1177   fprintf(header, "#endif\n");
1178   fprintf(header, "\n");
1179 }
1180
1181 static void write_coclass_forward(FILE *header, type_t *cocl)
1182 {
1183   fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
1184   fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
1185   fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name);
1186   fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
1187 }
1188
1189 static void write_import(FILE *header, const char *fname)
1190 {
1191   char *hname, *p;
1192
1193   hname = dup_basename(fname, ".idl");
1194   p = hname + strlen(hname) - 2;
1195   if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h");
1196
1197   fprintf(header, "#include <%s>\n", hname);
1198   free(hname);
1199 }
1200
1201 static void write_imports(FILE *header, const statement_list_t *stmts)
1202 {
1203   const statement_t *stmt;
1204   if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1205   {
1206     switch (stmt->type)
1207     {
1208       case STMT_TYPE:
1209         if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
1210           write_imports(header, type_iface_get_stmts(stmt->u.type));
1211         break;
1212       case STMT_TYPEREF:
1213       case STMT_IMPORTLIB:
1214         /* not included in header */
1215         break;
1216       case STMT_IMPORT:
1217         write_import(header, stmt->u.str);
1218         break;
1219       case STMT_TYPEDEF:
1220       case STMT_MODULE:
1221       case STMT_CPPQUOTE:
1222       case STMT_DECLARATION:
1223         /* not processed here */
1224         break;
1225       case STMT_LIBRARY:
1226         write_imports(header, stmt->u.lib->stmts);
1227         break;
1228     }
1229   }
1230 }
1231
1232 static void write_forward_decls(FILE *header, const statement_list_t *stmts)
1233 {
1234   const statement_t *stmt;
1235   if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1236   {
1237     switch (stmt->type)
1238     {
1239       case STMT_TYPE:
1240         if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
1241         {
1242           if (is_object(stmt->u.type) || is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE))
1243             write_forward(header, stmt->u.type);
1244         }
1245         else if (type_get_type(stmt->u.type) == TYPE_COCLASS)
1246           write_coclass_forward(header, stmt->u.type);
1247         break;
1248       case STMT_TYPEREF:
1249       case STMT_IMPORTLIB:
1250         /* not included in header */
1251         break;
1252       case STMT_IMPORT:
1253       case STMT_TYPEDEF:
1254       case STMT_MODULE:
1255       case STMT_CPPQUOTE:
1256       case STMT_DECLARATION:
1257         /* not processed here */
1258         break;
1259       case STMT_LIBRARY:
1260         write_forward_decls(header, stmt->u.lib->stmts);
1261         break;
1262     }
1263   }
1264 }
1265
1266 static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs)
1267 {
1268   const statement_t *stmt;
1269   if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1270   {
1271     switch (stmt->type)
1272     {
1273       case STMT_TYPE:
1274         if (type_get_type(stmt->u.type) == TYPE_INTERFACE)
1275         {
1276           type_t *iface = stmt->u.type;
1277           if (is_object(iface)) is_object_interface++;
1278           if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type))
1279           {
1280             write_com_interface_start(header, iface);
1281             write_header_stmts(header, type_iface_get_stmts(iface), stmt->u.type, TRUE);
1282             write_com_interface_end(header, iface);
1283           }
1284           else
1285           {
1286             write_rpc_interface_start(header, iface);
1287             write_header_stmts(header, type_iface_get_stmts(iface), iface, FALSE);
1288             write_rpc_interface_end(header, iface);
1289           }
1290           if (is_object(iface)) is_object_interface--;
1291         }
1292         else if (type_get_type(stmt->u.type) == TYPE_COCLASS)
1293           write_coclass(header, stmt->u.type);
1294         else
1295         {
1296           write_type_def_or_decl(header, stmt->u.type, FALSE, NULL);
1297           fprintf(header, ";\n\n");
1298         }
1299         break;
1300       case STMT_TYPEREF:
1301         /* FIXME: shouldn't write out forward declarations for undefined
1302         * interfaces but a number of our IDL files depend on this */
1303         if (type_get_type(stmt->u.type) == TYPE_INTERFACE && !stmt->u.type->written)
1304           write_forward(header, stmt->u.type);
1305         break;
1306       case STMT_IMPORTLIB:
1307       case STMT_MODULE:
1308         /* not included in header */
1309         break;
1310       case STMT_IMPORT:
1311         /* not processed here */
1312         break;
1313       case STMT_TYPEDEF:
1314       {
1315         const type_list_t *type_entry = stmt->u.type_list;
1316         for (; type_entry; type_entry = type_entry->next)
1317           write_typedef(header, type_entry->type);
1318         break;
1319       }
1320       case STMT_LIBRARY:
1321         write_library(header, stmt->u.lib);
1322         write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE);
1323         break;
1324       case STMT_CPPQUOTE:
1325         fprintf(header, "%s\n", stmt->u.str);
1326         break;
1327       case STMT_DECLARATION:
1328         if (iface && type_get_type(stmt->u.var->type) == TYPE_FUNCTION)
1329         {
1330           if (!ignore_funcs)
1331           {
1332             int prefixes_differ = strcmp(prefix_client, prefix_server);
1333
1334             if (prefixes_differ)
1335             {
1336               fprintf(header, "/* client prototype */\n");
1337               write_function_proto(header, iface, stmt->u.var, prefix_client);
1338               fprintf(header, "/* server prototype */\n");
1339             }
1340             write_function_proto(header, iface, stmt->u.var, prefix_server);
1341           }
1342         }
1343         else
1344           write_declaration(header, stmt->u.var);
1345         break;
1346     }
1347   }
1348 }
1349
1350 void write_header(const statement_list_t *stmts)
1351 {
1352   FILE *header;
1353
1354   if (!do_header) return;
1355
1356   if(!(header = fopen(header_name, "w"))) {
1357     error("Could not open %s for output\n", header_name);
1358     return;
1359   }
1360   fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name);
1361
1362   fprintf(header, "#ifndef __REQUIRED_RPCNDR_H_VERSION__\n");
1363   fprintf(header, "#define __REQUIRED_RPCNDR_H_VERSION__ 475\n");
1364   fprintf(header, "#endif\n\n");
1365
1366   fprintf(header, "#include <rpc.h>\n" );
1367   fprintf(header, "#include <rpcndr.h>\n\n" );
1368
1369   fprintf(header, "#ifndef COM_NO_WINDOWS_H\n");
1370   fprintf(header, "#include <windows.h>\n");
1371   fprintf(header, "#include <ole2.h>\n");
1372   fprintf(header, "#endif\n\n");
1373
1374   fprintf(header, "#ifndef __%s__\n", header_token);
1375   fprintf(header, "#define __%s__\n\n", header_token);
1376
1377   fprintf(header, "/* Forward declarations */\n\n");
1378   write_forward_decls(header, stmts);
1379
1380   fprintf(header, "/* Headers for imported files */\n\n");
1381   write_imports(header, stmts);
1382   fprintf(header, "\n");
1383   start_cplusplus_guard(header);
1384
1385   write_header_stmts(header, stmts, NULL, FALSE);
1386
1387   fprintf(header, "/* Begin additional prototypes for all interfaces */\n");
1388   fprintf(header, "\n");
1389   write_user_types(header);
1390   write_generic_handle_routines(header);
1391   write_context_handle_rundowns(header);
1392   fprintf(header, "\n");
1393   fprintf(header, "/* End additional prototypes */\n");
1394   fprintf(header, "\n");
1395
1396   end_cplusplus_guard(header);
1397   fprintf(header, "#endif /* __%s__ */\n", header_token);
1398
1399   fclose(header);
1400 }