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