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