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