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