widl: Add support for generic binding handles.
[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
37 typedef struct _user_type_t generic_handle_t;
38
39 static int indentation = 0;
40 user_type_list_t user_type_list = LIST_INIT(user_type_list);
41 static context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
42 static struct list generic_handle_list = LIST_INIT(generic_handle_list);
43
44 static void indent(FILE *h, int delta)
45 {
46   int c;
47   if (delta < 0) indentation += delta;
48   for (c=0; c<indentation; c++) fprintf(h, "    ");
49   if (delta > 0) indentation += delta;
50 }
51
52 int is_ptrchain_attr(const var_t *var, enum attr_type t)
53 {
54     if (is_attr(var->attrs, t))
55         return 1;
56     else
57     {
58         type_t *type = var->type;
59         for (;;)
60         {
61             if (is_attr(type->attrs, t))
62                 return 1;
63             else if (type->kind == TKIND_ALIAS)
64                 type = type->orig;
65             else if (is_ptr(type))
66                 type = type->ref;
67             else return 0;
68         }
69     }
70 }
71
72 int is_aliaschain_attr(const type_t *type, enum attr_type attr)
73 {
74     const type_t *t = type;
75     for (;;)
76     {
77         if (is_attr(t->attrs, attr))
78             return 1;
79         else if (t->kind == TKIND_ALIAS)
80             t = t->orig;
81         else return 0;
82     }
83 }
84
85 int is_attr(const attr_list_t *list, enum attr_type t)
86 {
87     const attr_t *attr;
88     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
89         if (attr->type == t) return 1;
90     return 0;
91 }
92
93 void *get_attrp(const attr_list_t *list, enum attr_type t)
94 {
95     const attr_t *attr;
96     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
97         if (attr->type == t) return attr->u.pval;
98     return NULL;
99 }
100
101 unsigned long get_attrv(const attr_list_t *list, enum attr_type t)
102 {
103     const attr_t *attr;
104     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
105         if (attr->type == t) return attr->u.ival;
106     return 0;
107 }
108
109 int is_void(const type_t *t)
110 {
111   if (!t->type && !t->ref) return 1;
112   return 0;
113 }
114
115 int is_conformant_array(const type_t *t)
116 {
117     return t->type == RPC_FC_CARRAY
118         || t->type == RPC_FC_CVARRAY
119         || (t->type == RPC_FC_BOGUS_ARRAY && t->size_is);
120 }
121
122 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
123 {
124   if (!uuid) return;
125   fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
126         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
127         guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
128         uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
129         uuid->Data4[6], uuid->Data4[7]);
130 }
131
132 void write_name(FILE *h, const var_t *v)
133 {
134   if (is_attr( v->attrs, ATTR_PROPGET ))
135     fprintf(h, "get_" );
136   else if (is_attr( v->attrs, ATTR_PROPPUT ))
137     fprintf(h, "put_" );
138   else if (is_attr( v->attrs, ATTR_PROPPUTREF ))
139     fprintf(h, "putref_" );
140   fprintf(h, "%s", v->name);
141 }
142
143 void write_prefix_name(FILE *h, const char *prefix, const var_t *v)
144 {
145   fprintf(h, "%s", prefix);
146   write_name(h, v);
147 }
148
149 static void write_field(FILE *h, var_t *v)
150 {
151   if (!v) return;
152   if (v->type) {
153     const char *name = v->name;
154     if (name == NULL) {
155       switch (v->type->type) {
156       case RPC_FC_STRUCT:
157       case RPC_FC_CVSTRUCT:
158       case RPC_FC_CPSTRUCT:
159       case RPC_FC_CSTRUCT:
160       case RPC_FC_PSTRUCT:
161       case RPC_FC_BOGUS_STRUCT:
162       case RPC_FC_ENCAPSULATED_UNION:
163         name = "DUMMYSTRUCTNAME";
164         break;
165       case RPC_FC_NON_ENCAPSULATED_UNION:
166         name = "DUMMYUNIONNAME";
167         break;
168       default:
169         /* ? */
170         break;
171       }
172     }
173     indent(h, 0);
174     write_type_def_or_decl(h, v->type, TRUE, "%s", name);
175     fprintf(h, ";\n");
176   }
177 }
178
179 static void write_fields(FILE *h, var_list_t *fields)
180 {
181     var_t *v;
182     if (!fields) return;
183     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v);
184 }
185
186 static void write_enums(FILE *h, var_list_t *enums)
187 {
188   var_t *v;
189   if (!enums) return;
190   LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
191   {
192     if (v->name) {
193       indent(h, 0);
194       write_name(h, v);
195       if (v->eval) {
196         fprintf(h, " = ");
197         write_expr(h, v->eval, 0);
198       }
199     }
200     if (list_next( enums, &v->entry )) fprintf(h, ",\n");
201   }
202   fprintf(h, "\n");
203 }
204
205 int needs_space_after(type_t *t)
206 {
207   return (t->kind == TKIND_ALIAS
208           || (!is_ptr(t) && (!is_conformant_array(t) || t->declarray)));
209 }
210
211 void write_type_left(FILE *h, type_t *t, int declonly)
212 {
213   if (!h) return;
214
215   if (t->is_const) fprintf(h, "const ");
216
217   if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name);
218   else if (t->declarray) write_type_left(h, t->ref, declonly);
219   else {
220     if (t->sign > 0) fprintf(h, "signed ");
221     else if (t->sign < 0) fprintf(h, "unsigned ");
222     switch (t->type) {
223       case RPC_FC_ENUM16:
224       case RPC_FC_ENUM32:
225         if (!declonly && t->defined && !t->written && !t->ignore) {
226           if (t->name) fprintf(h, "enum %s {\n", t->name);
227           else fprintf(h, "enum {\n");
228           t->written = TRUE;
229           indentation++;
230           write_enums(h, t->fields);
231           indent(h, -1);
232           fprintf(h, "}");
233         }
234         else fprintf(h, "enum %s", t->name ? t->name : "");
235         break;
236       case RPC_FC_STRUCT:
237       case RPC_FC_CVSTRUCT:
238       case RPC_FC_CPSTRUCT:
239       case RPC_FC_CSTRUCT:
240       case RPC_FC_PSTRUCT:
241       case RPC_FC_BOGUS_STRUCT:
242       case RPC_FC_ENCAPSULATED_UNION:
243         if (!declonly && t->defined && !t->written && !t->ignore) {
244           if (t->name) fprintf(h, "struct %s {\n", t->name);
245           else fprintf(h, "struct {\n");
246           t->written = TRUE;
247           indentation++;
248           write_fields(h, t->fields);
249           indent(h, -1);
250           fprintf(h, "}");
251         }
252         else fprintf(h, "struct %s", t->name ? t->name : "");
253         break;
254       case RPC_FC_NON_ENCAPSULATED_UNION:
255         if (!declonly && t->defined && !t->written && !t->ignore) {
256           if (t->name) fprintf(h, "union %s {\n", t->name);
257           else fprintf(h, "union {\n");
258           t->written = TRUE;
259           indentation++;
260           write_fields(h, t->fields);
261           indent(h, -1);
262           fprintf(h, "}");
263         }
264         else fprintf(h, "union %s", t->name ? t->name : "");
265         break;
266       case RPC_FC_RP:
267       case RPC_FC_UP:
268       case RPC_FC_FP:
269       case RPC_FC_OP:
270       case RPC_FC_CARRAY:
271       case RPC_FC_CVARRAY:
272       case RPC_FC_BOGUS_ARRAY:
273         write_type_left(h, t->ref, declonly);
274         fprintf(h, "%s*", needs_space_after(t->ref) ? " " : "");
275         break;
276       default:
277         fprintf(h, "%s", t->name);
278     }
279   }
280 }
281
282 void write_type_right(FILE *h, type_t *t, int is_field)
283 {
284   if (!h) return;
285
286   if (t->declarray) {
287     if (is_conformant_array(t)) {
288       fprintf(h, "[%s]", is_field ? "1" : "");
289       t = t->ref;
290     }
291     for ( ; t->declarray; t = t->ref)
292       fprintf(h, "[%lu]", t->dim);
293   }
294 }
295
296 void write_type_v(FILE *h, type_t *t, int is_field, int declonly,
297                   const char *fmt, va_list args)
298 {
299   if (!h) return;
300
301   write_type_left(h, t, declonly);
302   if (fmt) {
303     if (needs_space_after(t))
304       fprintf(h, " ");
305     vfprintf(h, fmt, args);
306   }
307   write_type_right(h, t, is_field);
308 }
309
310 void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *fmt, ...)
311 {
312   va_list args;
313   va_start(args, fmt);
314   write_type_v(f, t, field, FALSE, fmt, args);
315   va_end(args);
316 }
317
318 void write_type_decl(FILE *f, type_t *t, const char *fmt, ...)
319 {
320   va_list args;
321   va_start(args, fmt);
322   write_type_v(f, t, FALSE, TRUE, fmt, args);
323   va_end(args);
324 }
325
326 void write_type_decl_left(FILE *f, type_t *t)
327 {
328   write_type_left(f, t, TRUE);
329 }
330
331 static int user_type_registered(const char *name)
332 {
333   user_type_t *ut;
334   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
335     if (!strcmp(name, ut->name))
336       return 1;
337   return 0;
338 }
339
340 static int context_handle_registered(const char *name)
341 {
342   context_handle_t *ch;
343   LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
344     if (!strcmp(name, ch->name))
345       return 1;
346   return 0;
347 }
348
349 static int generic_handle_registered(const char *name)
350 {
351   generic_handle_t *gh;
352   LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
353     if (!strcmp(name, gh->name))
354       return 1;
355   return 0;
356 }
357
358 /* check for types which require additional prototypes to be generated in the
359  * header */
360 void check_for_additional_prototype_types(const var_list_t *list)
361 {
362   const var_t *v;
363
364   if (!list) return;
365   LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
366   {
367     type_t *type;
368     for (type = v->type; type; type = type->kind == TKIND_ALIAS ? type->orig : type->ref) {
369       const char *name = type->name;
370       if (type->user_types_registered) continue;
371       type->user_types_registered = 1;
372       if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) {
373         if (!context_handle_registered(name))
374         {
375           context_handle_t *ch = xmalloc(sizeof(*ch));
376           ch->name = xstrdup(name);
377           list_add_tail(&context_handle_list, &ch->entry);
378         }
379         /* don't carry on parsing fields within this type */
380         break;
381       }
382       if (type->type != RPC_FC_BIND_PRIMITIVE && is_attr(type->attrs, ATTR_HANDLE)) {
383         if (!generic_handle_registered(name))
384         {
385           generic_handle_t *gh = xmalloc(sizeof(*gh));
386           gh->name = xstrdup(name);
387           list_add_tail(&generic_handle_list, &gh->entry);
388         }
389         /* don't carry on parsing fields within this type */
390         break;
391       }
392       if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
393         if (!user_type_registered(name))
394         {
395           user_type_t *ut = xmalloc(sizeof *ut);
396           ut->name = xstrdup(name);
397           list_add_tail(&user_type_list, &ut->entry);
398         }
399         /* don't carry on parsing fields within this type as we are already
400          * using a wire marshaled type */
401         break;
402       }
403       else
404       {
405         check_for_additional_prototype_types(type->fields);
406       }
407     }
408   }
409 }
410
411 void write_user_types(void)
412 {
413   user_type_t *ut;
414   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
415   {
416     const char *name = ut->name;
417     fprintf(header, "ULONG           __RPC_USER %s_UserSize     (ULONG *, ULONG, %s *);\n", name, name);
418     fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal  (ULONG *, unsigned char *, %s *);\n", name, name);
419     fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
420     fprintf(header, "void            __RPC_USER %s_UserFree     (ULONG *, %s *);\n", name, name);
421   }
422 }
423
424 void write_context_handle_rundowns(void)
425 {
426   context_handle_t *ch;
427   LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
428   {
429     const char *name = ch->name;
430     fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name);
431   }
432 }
433
434 void write_generic_handle_routines(void)
435 {
436   generic_handle_t *gh;
437   LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
438   {
439     const char *name = gh->name;
440     fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name);
441     fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name);
442   }
443 }
444
445 void write_typedef(type_t *type)
446 {
447   fprintf(header, "typedef ");
448   write_type_def_or_decl(header, type->orig, FALSE, "%s", type->name);
449   fprintf(header, ";\n");
450 }
451
452 void write_expr(FILE *h, const expr_t *e, int brackets)
453 {
454   switch (e->type) {
455   case EXPR_VOID:
456     break;
457   case EXPR_NUM:
458     fprintf(h, "%lu", e->u.lval);
459     break;
460   case EXPR_HEXNUM:
461     fprintf(h, "0x%lx", e->u.lval);
462     break;
463   case EXPR_DOUBLE:
464     fprintf(h, "%#.15g", e->u.dval);
465     break;
466   case EXPR_TRUEFALSE:
467     if (e->u.lval == 0)
468       fprintf(h, "FALSE");
469     else
470       fprintf(h, "TRUE");
471     break;
472   case EXPR_IDENTIFIER:
473     fprintf(h, "%s", e->u.sval);
474     break;
475   case EXPR_NEG:
476     fprintf(h, "-");
477     write_expr(h, e->ref, 1);
478     break;
479   case EXPR_NOT:
480     fprintf(h, "~");
481     write_expr(h, e->ref, 1);
482     break;
483   case EXPR_PPTR:
484     fprintf(h, "*");
485     write_expr(h, e->ref, 1);
486     break;
487   case EXPR_CAST:
488     fprintf(h, "(");
489     write_type_decl(h, e->u.tref, NULL);
490     fprintf(h, ")");
491     write_expr(h, e->ref, 1);
492     break;
493   case EXPR_SIZEOF:
494     fprintf(h, "sizeof(");
495     write_type_decl(h, e->u.tref, NULL);
496     fprintf(h, ")");
497     break;
498   case EXPR_SHL:
499   case EXPR_SHR:
500   case EXPR_MUL:
501   case EXPR_DIV:
502   case EXPR_ADD:
503   case EXPR_SUB:
504   case EXPR_AND:
505   case EXPR_OR:
506     if (brackets) fprintf(h, "(");
507     write_expr(h, e->ref, 1);
508     switch (e->type) {
509     case EXPR_SHL: fprintf(h, " << "); break;
510     case EXPR_SHR: fprintf(h, " >> "); break;
511     case EXPR_MUL: fprintf(h, " * "); break;
512     case EXPR_DIV: fprintf(h, " / "); break;
513     case EXPR_ADD: fprintf(h, " + "); break;
514     case EXPR_SUB: fprintf(h, " - "); break;
515     case EXPR_AND: fprintf(h, " & "); break;
516     case EXPR_OR:  fprintf(h, " | "); break;
517     default: break;
518     }
519     write_expr(h, e->u.ext, 1);
520     if (brackets) fprintf(h, ")");
521     break;
522   case EXPR_COND:
523     if (brackets) fprintf(h, "(");
524     write_expr(h, e->ref, 1);
525     fprintf(h, " ? ");
526     write_expr(h, e->u.ext, 1);
527     fprintf(h, " : ");
528     write_expr(h, e->ext2, 1);
529     if (brackets) fprintf(h, ")");
530     break;
531   case EXPR_ADDRESSOF:
532     fprintf(h, "&");
533     write_expr(h, e->ref, 1);
534     break;
535   }
536 }
537
538 void write_constdef(const var_t *v)
539 {
540   fprintf(header, "#define %s (", v->name);
541   write_expr(header, v->eval, 0);
542   fprintf(header, ")\n\n");
543 }
544
545 void write_externdef(const var_t *v)
546 {
547   fprintf(header, "extern const ");
548   write_type_def_or_decl(header, v->type, FALSE, "%s", v->name);
549   fprintf(header, ";\n\n");
550 }
551
552 void write_library(const char *name, const attr_list_t *attr)
553 {
554   const UUID *uuid = get_attrp(attr, ATTR_UUID);
555   fprintf(header, "\n");
556   write_guid(header, "LIBID", name, uuid);
557   fprintf(header, "\n");
558 }
559
560
561 const var_t* get_explicit_handle_var(const func_t* func)
562 {
563     const var_t* var;
564
565     if (!func->args)
566         return NULL;
567
568     LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
569         if (var->type->type == RPC_FC_BIND_PRIMITIVE)
570             return var;
571
572     return NULL;
573 }
574
575 const type_t* get_explicit_generic_handle_type(const var_t* var)
576 {
577     const type_t *t;
578     for (t = var->type; is_ptr(t); t = t->ref)
579         if (t->type != RPC_FC_BIND_PRIMITIVE && is_attr(t->attrs, ATTR_HANDLE))
580             return t;
581     return NULL;
582 }
583
584 const var_t* get_explicit_generic_handle_var(const func_t* func)
585 {
586     const var_t* var;
587
588     if (!func->args)
589         return NULL;
590
591     LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
592         if (get_explicit_generic_handle_type(var))
593             return var;
594
595     return NULL;
596 }
597
598 int has_out_arg_or_return(const func_t *func)
599 {
600     const var_t *var;
601
602     if (!is_void(func->def->type))
603         return 1;
604
605     if (!func->args)
606         return 0;
607
608     LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
609         if (is_attr(var->attrs, ATTR_OUT))
610             return 1;
611
612     return 0;
613 }
614
615
616 /********** INTERFACES **********/
617
618 int is_object(const attr_list_t *list)
619 {
620     const attr_t *attr;
621     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
622         if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
623     return 0;
624 }
625
626 int is_local(const attr_list_t *a)
627 {
628   return is_attr(a, ATTR_LOCAL);
629 }
630
631 const var_t *is_callas(const attr_list_t *a)
632 {
633   return get_attrp(a, ATTR_CALLAS);
634 }
635
636 static void write_method_macro(const type_t *iface, const char *name)
637 {
638   const func_t *cur;
639
640   if (iface->ref) write_method_macro(iface->ref, name);
641
642   if (!iface->funcs) return;
643
644   fprintf(header, "/*** %s methods ***/\n", iface->name);
645   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
646   {
647     var_t *def = cur->def;
648     if (!is_callas(def->attrs)) {
649       const var_t *arg;
650
651       fprintf(header, "#define %s_", name);
652       write_name(header,def);
653       fprintf(header, "(This");
654       if (cur->args)
655           LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry )
656               fprintf(header, ",%s", arg->name);
657       fprintf(header, ") ");
658
659       fprintf(header, "(This)->lpVtbl->");
660       write_name(header, def);
661       fprintf(header, "(This");
662       if (cur->args)
663           LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry )
664               fprintf(header, ",%s", arg->name);
665       fprintf(header, ")\n");
666     }
667   }
668 }
669
670 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
671 {
672   const var_t *arg;
673   int count = 0;
674
675   if (do_indent)
676   {
677       indentation++;
678       indent(h, 0);
679   }
680   if (method == 1) {
681     fprintf(h, "%s* This", name);
682     count++;
683   }
684   if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
685     if (count) {
686         if (do_indent)
687         {
688             fprintf(h, ",\n");
689             indent(h, 0);
690         }
691         else fprintf(h, ",");
692     }
693     if (arg->args)
694     {
695       write_type_decl_left(h, arg->type);
696       fprintf(h, " (STDMETHODCALLTYPE *");
697       write_name(h,arg);
698       fprintf(h, ")(");
699       write_args(h, arg->args, NULL, 0, FALSE);
700       fprintf(h, ")");
701     }
702     else
703       write_type_decl(h, arg->type, "%s", arg->name);
704     count++;
705   }
706   if (do_indent) indentation--;
707 }
708
709 static void write_cpp_method_def(const type_t *iface)
710 {
711   const func_t *cur;
712
713   if (!iface->funcs) return;
714
715   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
716   {
717     var_t *def = cur->def;
718     if (!is_callas(def->attrs)) {
719       indent(header, 0);
720       fprintf(header, "virtual ");
721       write_type_decl_left(header, def->type);
722       fprintf(header, " STDMETHODCALLTYPE ");
723       write_name(header, def);
724       fprintf(header, "(\n");
725       write_args(header, cur->args, iface->name, 2, TRUE);
726       fprintf(header, ") = 0;\n");
727       fprintf(header, "\n");
728     }
729   }
730 }
731
732 static void do_write_c_method_def(const type_t *iface, const char *name)
733 {
734   const func_t *cur;
735
736   if (iface->ref) do_write_c_method_def(iface->ref, name);
737
738   if (!iface->funcs) return;
739   indent(header, 0);
740   fprintf(header, "/*** %s methods ***/\n", iface->name);
741   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
742   {
743     const var_t *def = cur->def;
744     if (!is_callas(def->attrs)) {
745       indent(header, 0);
746       write_type_decl_left(header, def->type);
747       fprintf(header, " (STDMETHODCALLTYPE *");
748       write_name(header, def);
749       fprintf(header, ")(\n");
750       write_args(header, cur->args, name, 1, TRUE);
751       fprintf(header, ");\n");
752       fprintf(header, "\n");
753     }
754   }
755 }
756
757 static void write_c_method_def(const type_t *iface)
758 {
759   do_write_c_method_def(iface, iface->name);
760 }
761
762 static void write_c_disp_method_def(const type_t *iface)
763 {
764   do_write_c_method_def(iface->ref, iface->name);
765 }
766
767 static void write_method_proto(const type_t *iface)
768 {
769   const func_t *cur;
770
771   if (!iface->funcs) return;
772   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
773   {
774     const var_t *def = cur->def;
775
776     if (!is_local(def->attrs)) {
777       /* proxy prototype */
778       write_type_decl_left(header, def->type);
779       fprintf(header, " CALLBACK %s_", iface->name);
780       write_name(header, def);
781       fprintf(header, "_Proxy(\n");
782       write_args(header, cur->args, iface->name, 1, TRUE);
783       fprintf(header, ");\n");
784       /* stub prototype */
785       fprintf(header, "void __RPC_STUB %s_", iface->name);
786       write_name(header,def);
787       fprintf(header, "_Stub(\n");
788       fprintf(header, "    IRpcStubBuffer* This,\n");
789       fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
790       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
791       fprintf(header, "    DWORD* pdwStubPhase);\n");
792     }
793   }
794 }
795
796 void write_locals(FILE *fp, const type_t *iface, int body)
797 {
798   static const char comment[]
799     = "/* WIDL-generated stub.  You must provide an implementation for this.  */";
800   const func_list_t *funcs = iface->funcs;
801   const func_t *cur;
802
803   if (!is_object(iface->attrs) || !funcs)
804     return;
805
806   LIST_FOR_EACH_ENTRY(cur, funcs, const func_t, entry) {
807     const var_t *def = cur->def;
808     const var_t *cas = is_callas(def->attrs);
809
810     if (cas) {
811       const func_t *m;
812       LIST_FOR_EACH_ENTRY(m, iface->funcs, const func_t, entry)
813         if (!strcmp(m->def->name, cas->name))
814           break;
815       if (&m->entry != iface->funcs) {
816         const var_t *mdef = m->def;
817         /* proxy prototype - use local prototype */
818         write_type_decl_left(fp, mdef->type);
819         fprintf(fp, " CALLBACK %s_", iface->name);
820         write_name(fp, mdef);
821         fprintf(fp, "_Proxy(\n");
822         write_args(fp, m->args, iface->name, 1, TRUE);
823         fprintf(fp, ")");
824         if (body) {
825           type_t *rt = mdef->type;
826           fprintf(fp, "\n{\n");
827           fprintf(fp, "    %s\n", comment);
828           if (rt->name && strcmp(rt->name, "HRESULT") == 0)
829             fprintf(fp, "    return E_NOTIMPL;\n");
830           else if (rt->type) {
831             fprintf(fp, "    ");
832             write_type_decl(fp, rt, "rv");
833             fprintf(fp, ";\n");
834             fprintf(fp, "    memset(&rv, 0, sizeof rv);\n");
835             fprintf(fp, "    return rv;\n");
836           }
837           fprintf(fp, "}\n\n");
838         }
839         else
840           fprintf(fp, ";\n");
841         /* stub prototype - use remotable prototype */
842         write_type_decl_left(fp, def->type);
843         fprintf(fp, " __RPC_STUB %s_", iface->name);
844         write_name(fp, mdef);
845         fprintf(fp, "_Stub(\n");
846         write_args(fp, cur->args, iface->name, 1, TRUE);
847         fprintf(fp, ")");
848         if (body)
849           /* Remotable methods must all return HRESULTs.  */
850           fprintf(fp, "\n{\n    %s\n    return E_NOTIMPL;\n}\n\n", comment);
851         else
852           fprintf(fp, ";\n");
853       }
854       else
855         error_loc("invalid call_as attribute (%s -> %s)\n", def->name, cas->name);
856     }
857   }
858 }
859
860 static void write_function_proto(const type_t *iface, const func_t *fun, const char *prefix)
861 {
862   var_t *def = fun->def;
863
864   /* FIXME: do we need to handle call_as? */
865   write_type_decl_left(header, def->type);
866   fprintf(header, " ");
867   write_prefix_name(header, prefix, def);
868   fprintf(header, "(\n");
869   if (fun->args)
870     write_args(header, fun->args, iface->name, 0, TRUE);
871   else
872     fprintf(header, "    void");
873   fprintf(header, ");\n");
874 }
875
876 static void write_function_protos(const type_t *iface)
877 {
878   const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
879   int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
880   const var_t* explicit_handle_var;
881   const func_t *cur;
882   int prefixes_differ = strcmp(prefix_client, prefix_server);
883
884   if (!iface->funcs) return;
885   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
886   {
887     var_t *def = cur->def;
888
889     /* check for a defined binding handle */
890     explicit_handle_var = get_explicit_handle_var(cur);
891     if (explicit_handle) {
892       if (!explicit_handle_var) {
893         error("%s() does not define an explicit binding handle!\n", def->name);
894         return;
895       }
896     } else if (implicit_handle) {
897       if (explicit_handle_var) {
898         error("%s() must not define a binding handle!\n", def->name);
899         return;
900       }
901     }
902
903     if (prefixes_differ) {
904       fprintf(header, "/* client prototype */\n");
905       write_function_proto(iface, cur, prefix_client);
906       fprintf(header, "/* server prototype */\n");
907     }
908     write_function_proto(iface, cur, prefix_server);
909   }
910 }
911
912 void write_forward(type_t *iface)
913 {
914   /* C/C++ forwards should only be written for object interfaces, so if we
915    * have a full definition we only write one if we find [object] among the
916    * attributes - however, if we don't have a full definition at this point
917    * (i.e. this is an IDL forward), then we also assume that it is an object
918    * interface, since non-object interfaces shouldn't need forwards */
919   if ((!iface->defined || is_object(iface->attrs) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
920         && !iface->written) {
921     fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
922     fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
923     fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
924     fprintf(header, "#endif\n\n" );
925     iface->written = TRUE;
926   }
927 }
928
929 static void write_iface_guid(const type_t *iface)
930 {
931   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
932   write_guid(header, "IID", iface->name, uuid);
933
934
935 static void write_dispiface_guid(const type_t *iface)
936 {
937   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
938   write_guid(header, "DIID", iface->name, uuid);
939 }
940
941 static void write_coclass_guid(type_t *cocl)
942 {
943   const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
944   write_guid(header, "CLSID", cocl->name, uuid);
945 }
946
947 static void write_com_interface(type_t *iface)
948 {
949   if (!iface->funcs && !iface->ref) {
950     parser_warning("%s has no methods\n", iface->name);
951     return;
952   }
953
954   fprintf(header, "/*****************************************************************************\n");
955   fprintf(header, " * %s interface\n", iface->name);
956   fprintf(header, " */\n");
957   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
958   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
959   write_iface_guid(iface);
960   write_forward(iface);
961   /* C++ interface */
962   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
963   if (iface->ref)
964   {
965       fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name);
966       fprintf(header, "{\n");
967       indentation++;
968       write_cpp_method_def(iface);
969       indentation--;
970       fprintf(header, "};\n");
971   }
972   else
973   {
974       fprintf(header, "interface %s\n", iface->name);
975       fprintf(header, "{\n");
976       fprintf(header, "    BEGIN_INTERFACE\n");
977       fprintf(header, "\n");
978       indentation++;
979       write_cpp_method_def(iface);
980       indentation--;
981       fprintf(header, "    END_INTERFACE\n");
982       fprintf(header, "};\n");
983   }
984   fprintf(header, "#else\n");
985   /* C interface */
986   fprintf(header, "typedef struct %sVtbl {\n", iface->name);
987   indentation++;
988   fprintf(header, "    BEGIN_INTERFACE\n");
989   fprintf(header, "\n");
990   write_c_method_def(iface);
991   indentation--;
992   fprintf(header, "    END_INTERFACE\n");
993   fprintf(header, "} %sVtbl;\n", iface->name);
994   fprintf(header, "interface %s {\n", iface->name);
995   fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
996   fprintf(header, "};\n");
997   fprintf(header, "\n");
998   fprintf(header, "#ifdef COBJMACROS\n");
999   write_method_macro(iface, iface->name);
1000   fprintf(header, "#endif\n");
1001   fprintf(header, "\n");
1002   fprintf(header, "#endif\n");
1003   fprintf(header, "\n");
1004   write_method_proto(iface);
1005   write_locals(header, iface, FALSE);
1006   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
1007 }
1008
1009 static void write_rpc_interface(const type_t *iface)
1010 {
1011   unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
1012   const char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
1013   static int allocate_written = 0;
1014
1015   if (!allocate_written)
1016   {
1017     allocate_written = 1;
1018     fprintf(header, "void * __RPC_USER MIDL_user_allocate(size_t);\n");
1019     fprintf(header, "void __RPC_USER MIDL_user_free(void *);\n\n");
1020   }
1021
1022   fprintf(header, "/*****************************************************************************\n");
1023   fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1024   fprintf(header, " */\n");
1025   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
1026   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
1027   if (iface->funcs)
1028   {
1029     write_iface_guid(iface);
1030     if (var) fprintf(header, "extern handle_t %s;\n", var);
1031     if (old_names)
1032     {
1033         fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
1034         fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
1035     }
1036     else
1037     {
1038         fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
1039                 prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1040         fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
1041                 prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1042     }
1043     write_function_protos(iface);
1044   }
1045   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
1046
1047   /* FIXME: server/client code */
1048 }
1049
1050 void write_interface(type_t *iface)
1051 {
1052   if (is_object(iface->attrs))
1053     write_com_interface(iface);
1054   else
1055     write_rpc_interface(iface);
1056 }
1057
1058 void write_dispinterface(type_t *iface)
1059 {
1060   fprintf(header, "/*****************************************************************************\n");
1061   fprintf(header, " * %s dispinterface\n", iface->name);
1062   fprintf(header, " */\n");
1063   fprintf(header,"#ifndef __%s_DISPINTERFACE_DEFINED__\n", iface->name);
1064   fprintf(header,"#define __%s_DISPINTERFACE_DEFINED__\n\n", iface->name);
1065   write_dispiface_guid(iface);
1066   write_forward(iface);
1067   /* C++ interface */
1068   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
1069   fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name);
1070   fprintf(header, "{\n");
1071   fprintf(header, "};\n");
1072   fprintf(header, "#else\n");
1073   /* C interface */
1074   fprintf(header, "typedef struct %sVtbl {\n", iface->name);
1075   indentation++;
1076   fprintf(header, "    BEGIN_INTERFACE\n");
1077   fprintf(header, "\n");
1078   write_c_disp_method_def(iface);
1079   indentation--;
1080   fprintf(header, "    END_INTERFACE\n");
1081   fprintf(header, "} %sVtbl;\n", iface->name);
1082   fprintf(header, "interface %s {\n", iface->name);
1083   fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
1084   fprintf(header, "};\n");
1085   fprintf(header, "\n");
1086   fprintf(header, "#ifdef COBJMACROS\n");
1087   write_method_macro(iface->ref, iface->name);
1088   fprintf(header, "#endif\n");
1089   fprintf(header, "\n");
1090   fprintf(header, "#endif\n");
1091   fprintf(header, "\n");
1092   fprintf(header,"#endif  /* __%s_DISPINTERFACE_DEFINED__ */\n\n", iface->name);
1093 }
1094
1095 void write_coclass(type_t *cocl)
1096 {
1097   fprintf(header, "/*****************************************************************************\n");
1098   fprintf(header, " * %s coclass\n", cocl->name);
1099   fprintf(header, " */\n\n");
1100   write_coclass_guid(cocl);
1101   fprintf(header, "\n");
1102 }
1103
1104 void write_coclass_forward(type_t *cocl)
1105 {
1106   fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
1107   fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
1108   fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name);
1109   fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
1110 }