push 98299ad1251baa2727aab065c47e9d935978c732
[wine/hacks.git] / tools / widl / header.c
blobf86d2b0db3b15513743b6cb0aac7a1db1eb4be27
1 /*
2 * IDL Compiler
4 * Copyright 2002 Ove Kaaven
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.
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.
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
21 #include "config.h"
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>
32 #include "widl.h"
33 #include "utils.h"
34 #include "parser.h"
35 #include "header.h"
36 #include "expr.h"
37 #include "typetree.h"
39 typedef struct _user_type_t generic_handle_t;
41 static int indentation = 0;
42 user_type_list_t user_type_list = LIST_INIT(user_type_list);
43 static context_handle_list_t context_handle_list = LIST_INIT(context_handle_list);
44 static struct list generic_handle_list = LIST_INIT(generic_handle_list);
46 static void indent(FILE *h, int delta)
48 int c;
49 if (delta < 0) indentation += delta;
50 for (c=0; c<indentation; c++) fprintf(h, " ");
51 if (delta > 0) indentation += delta;
54 int is_ptrchain_attr(const var_t *var, enum attr_type t)
56 if (is_attr(var->attrs, t))
57 return 1;
58 else
60 type_t *type = var->type;
61 for (;;)
63 if (is_attr(type->attrs, t))
64 return 1;
65 else if (type_is_alias(type))
66 type = type_alias_get_aliasee(type);
67 else if (is_ptr(type))
68 type = type_pointer_get_ref(type);
69 else return 0;
74 int is_aliaschain_attr(const type_t *type, enum attr_type attr)
76 const type_t *t = type;
77 for (;;)
79 if (is_attr(t->attrs, attr))
80 return 1;
81 else if (type_is_alias(t))
82 t = type_alias_get_aliasee(t);
83 else return 0;
87 int is_attr(const attr_list_t *list, enum attr_type t)
89 const attr_t *attr;
90 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
91 if (attr->type == t) return 1;
92 return 0;
95 void *get_attrp(const attr_list_t *list, enum attr_type t)
97 const attr_t *attr;
98 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
99 if (attr->type == t) return attr->u.pval;
100 return NULL;
103 unsigned long get_attrv(const attr_list_t *list, enum attr_type t)
105 const attr_t *attr;
106 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
107 if (attr->type == t) return attr->u.ival;
108 return 0;
111 int is_void(const type_t *t)
113 return type_get_type(t) == TYPE_VOID;
116 int is_conformant_array(const type_t *t)
118 return is_array(t) && type_array_has_conformance(t);
121 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
123 if (!uuid) return;
124 fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
125 "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
126 guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
127 uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
128 uuid->Data4[6], uuid->Data4[7]);
131 const char *get_name(const var_t *v)
133 static char buffer[256];
135 if (is_attr( v->attrs, ATTR_PROPGET ))
136 strcpy( buffer, "get_" );
137 else if (is_attr( v->attrs, ATTR_PROPPUT ))
138 strcpy( buffer, "put_" );
139 else if (is_attr( v->attrs, ATTR_PROPPUTREF ))
140 strcpy( buffer, "putref_" );
141 else
142 buffer[0] = 0;
143 strcat( buffer, v->name );
144 return buffer;
147 static void write_field(FILE *h, var_t *v)
149 if (!v) return;
150 if (v->type) {
151 indent(h, 0);
152 write_type_def_or_decl(h, v->type, TRUE, v->name);
153 fprintf(h, ";\n");
157 static void write_fields(FILE *h, var_list_t *fields)
159 var_t *v;
160 if (!fields) return;
161 LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v);
164 static void write_enums(FILE *h, var_list_t *enums)
166 var_t *v;
167 if (!enums) return;
168 LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
170 if (v->name) {
171 indent(h, 0);
172 fprintf(h, "%s", get_name(v));
173 if (v->eval) {
174 fprintf(h, " = ");
175 write_expr(h, v->eval, 0, 1, NULL, NULL, "");
178 if (list_next( enums, &v->entry )) fprintf(h, ",\n");
180 fprintf(h, "\n");
183 int needs_space_after(type_t *t)
185 return (type_is_alias(t) ||
186 (!is_ptr(t) && (!is_conformant_array(t) || t->declarray || (is_array(t) && t->name))));
189 void write_type_left(FILE *h, type_t *t, int declonly)
191 if (!h) return;
193 if (is_attr(t->attrs, ATTR_CONST) &&
194 (type_is_alias(t) || t->declarray || !is_ptr(t)))
195 fprintf(h, "const ");
197 if (type_is_alias(t)) fprintf(h, "%s", t->name);
198 else if (t->declarray) write_type_left(h, type_array_get_element(t), declonly);
199 else {
200 if (t->sign > 0) fprintf(h, "signed ");
201 else if (t->sign < 0) fprintf(h, "unsigned ");
203 if (is_array(t) && !t->name) {
204 write_type_left(h, type_array_get_element(t), declonly);
205 fprintf(h, "%s*", needs_space_after(type_array_get_element(t)) ? " " : "");
206 } else switch (t->type) {
207 case RPC_FC_ENUM16:
208 case RPC_FC_ENUM32:
209 if (!declonly && t->defined && !t->written) {
210 if (t->name) fprintf(h, "enum %s {\n", t->name);
211 else fprintf(h, "enum {\n");
212 t->written = TRUE;
213 indentation++;
214 write_enums(h, type_enum_get_values(t));
215 indent(h, -1);
216 fprintf(h, "}");
218 else fprintf(h, "enum %s", t->name ? t->name : "");
219 break;
220 case RPC_FC_STRUCT:
221 case RPC_FC_CVSTRUCT:
222 case RPC_FC_CPSTRUCT:
223 case RPC_FC_CSTRUCT:
224 case RPC_FC_PSTRUCT:
225 case RPC_FC_BOGUS_STRUCT:
226 case RPC_FC_ENCAPSULATED_UNION:
227 if (!declonly && t->defined && !t->written) {
228 if (t->name) fprintf(h, "struct %s {\n", t->name);
229 else fprintf(h, "struct {\n");
230 t->written = TRUE;
231 indentation++;
232 if (t->type == RPC_FC_ENCAPSULATED_UNION)
233 write_fields(h, type_encapsulated_union_get_fields(t));
234 else
235 write_fields(h, type_struct_get_fields(t));
236 indent(h, -1);
237 fprintf(h, "}");
239 else fprintf(h, "struct %s", t->name ? t->name : "");
240 break;
241 case RPC_FC_NON_ENCAPSULATED_UNION:
242 if (!declonly && t->defined && !t->written) {
243 if (t->name) fprintf(h, "union %s {\n", t->name);
244 else fprintf(h, "union {\n");
245 t->written = TRUE;
246 indentation++;
247 write_fields(h, type_union_get_cases(t));
248 indent(h, -1);
249 fprintf(h, "}");
251 else fprintf(h, "union %s", t->name ? t->name : "");
252 break;
253 case RPC_FC_RP:
254 case RPC_FC_UP:
255 case RPC_FC_FP:
256 case RPC_FC_OP:
257 write_type_left(h, type_pointer_get_ref(t), declonly);
258 fprintf(h, "%s*", needs_space_after(type_pointer_get_ref(t)) ? " " : "");
259 if (is_attr(t->attrs, ATTR_CONST)) fprintf(h, "const ");
260 break;
261 default:
262 fprintf(h, "%s", t->name);
267 void write_type_right(FILE *h, type_t *t, int is_field)
269 if (!h) return;
271 if (t->declarray) {
272 if (is_conformant_array(t)) {
273 fprintf(h, "[%s]", is_field ? "1" : "");
274 t = type_array_get_element(t);
276 for ( ; t->declarray; t = type_array_get_element(t))
277 fprintf(h, "[%u]", type_array_get_dim(t));
281 static void write_type_v(FILE *h, type_t *t, int is_field, int declonly, const char *name)
283 type_t *pt;
284 int ptr_level = 0;
286 if (!h) return;
288 for (pt = t; is_ptr(pt); pt = type_pointer_get_ref(pt), ptr_level++)
291 if (pt->type == RPC_FC_FUNCTION) {
292 int i;
293 const char *callconv = get_attrp(pt->attrs, ATTR_CALLCONV);
294 if (!callconv) callconv = "";
295 if (is_attr(pt->attrs, ATTR_INLINE)) fprintf(h, "inline ");
296 write_type_left(h, type_function_get_rettype(pt), declonly);
297 fputc(' ', h);
298 if (ptr_level) fputc('(', h);
299 fprintf(h, "%s ", callconv);
300 for (i = 0; i < ptr_level; i++)
301 fputc('*', h);
302 } else
303 write_type_left(h, t, declonly);
305 if (name) fprintf(h, "%s%s", needs_space_after(t) ? " " : "", name );
307 if (pt->type == RPC_FC_FUNCTION) {
308 if (ptr_level) fputc(')', h);
309 fputc('(', h);
310 write_args(h, type_function_get_args(pt), NULL, 0, FALSE);
311 fputc(')', h);
312 } else
313 write_type_right(h, t, is_field);
316 void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *name)
318 write_type_v(f, t, field, FALSE, name);
321 void write_type_decl(FILE *f, type_t *t, const char *name)
323 write_type_v(f, t, FALSE, TRUE, name);
326 void write_type_decl_left(FILE *f, type_t *t)
328 write_type_left(f, t, TRUE);
331 static int user_type_registered(const char *name)
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;
340 static int context_handle_registered(const char *name)
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;
349 static int generic_handle_registered(const char *name)
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;
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)
362 const var_t *v;
364 if (!list) return;
365 LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
367 type_t *type = v->type;
368 if (!type) continue;
369 for (;;) {
370 const char *name = type->name;
371 if (type->user_types_registered) break;
372 type->user_types_registered = 1;
373 if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) {
374 if (!context_handle_registered(name))
376 context_handle_t *ch = xmalloc(sizeof(*ch));
377 ch->name = xstrdup(name);
378 list_add_tail(&context_handle_list, &ch->entry);
380 /* don't carry on parsing fields within this type */
381 break;
383 if (type->type != RPC_FC_BIND_PRIMITIVE && is_attr(type->attrs, ATTR_HANDLE)) {
384 if (!generic_handle_registered(name))
386 generic_handle_t *gh = xmalloc(sizeof(*gh));
387 gh->name = xstrdup(name);
388 list_add_tail(&generic_handle_list, &gh->entry);
390 /* don't carry on parsing fields within this type */
391 break;
393 if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
394 if (!user_type_registered(name))
396 user_type_t *ut = xmalloc(sizeof *ut);
397 ut->name = xstrdup(name);
398 list_add_tail(&user_type_list, &ut->entry);
400 /* don't carry on parsing fields within this type as we are already
401 * using a wire marshaled type */
402 break;
404 else if (type_is_complete(type))
406 var_list_t *vars = NULL;
407 if (type->type == RPC_FC_ENUM16 || type->type == RPC_FC_ENUM32)
408 vars = type_enum_get_values(type);
409 else if (is_struct(type->type))
410 vars = type_struct_get_fields(type);
411 else if (is_union(type->type))
412 vars = type_union_get_cases(type);
413 check_for_additional_prototype_types(vars);
416 if (type_is_alias(type))
417 type = type_alias_get_aliasee(type);
418 else if (is_ptr(type))
419 type = type_pointer_get_ref(type);
420 else if (is_array(type))
421 type = type_array_get_element(type);
422 else
423 break;
428 static void write_user_types(FILE *header)
430 user_type_t *ut;
431 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
433 const char *name = ut->name;
434 fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name);
435 fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name);
436 fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
437 fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name);
441 static void write_context_handle_rundowns(FILE *header)
443 context_handle_t *ch;
444 LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry)
446 const char *name = ch->name;
447 fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name);
451 static void write_generic_handle_routines(FILE *header)
453 generic_handle_t *gh;
454 LIST_FOR_EACH_ENTRY(gh, &generic_handle_list, generic_handle_t, entry)
456 const char *name = gh->name;
457 fprintf(header, "handle_t __RPC_USER %s_bind(%s);\n", name, name);
458 fprintf(header, "void __RPC_USER %s_unbind(%s, handle_t);\n", name, name);
462 static void write_typedef(FILE *header, type_t *type)
464 fprintf(header, "typedef ");
465 write_type_def_or_decl(header, type_alias_get_aliasee(type), FALSE, type->name);
466 fprintf(header, ";\n");
469 int is_const_decl(const var_t *var)
471 const type_t *t;
472 /* strangely, MIDL accepts a const attribute on any pointer in the
473 * declaration to mean that data isn't being instantiated. this appears
474 * to be a bug, but there is no benefit to being incompatible with MIDL,
475 * so we'll do the same thing */
476 for (t = var->type; ; )
478 if (is_attr(t->attrs, ATTR_CONST))
479 return TRUE;
480 else if (is_ptr(t))
481 t = type_pointer_get_ref(t);
482 else break;
484 return FALSE;
487 static void write_declaration(FILE *header, const var_t *v)
489 if (is_const_decl(v) && v->eval)
491 fprintf(header, "#define %s (", v->name);
492 write_expr(header, v->eval, 0, 1, NULL, NULL, "");
493 fprintf(header, ")\n\n");
495 else
497 switch (v->stgclass)
499 case STG_NONE:
500 case STG_REGISTER: /* ignored */
501 break;
502 case STG_STATIC:
503 fprintf(header, "static ");
504 break;
505 case STG_EXTERN:
506 fprintf(header, "extern ");
507 break;
509 write_type_def_or_decl(header, v->type, FALSE, v->name);
510 fprintf(header, ";\n\n");
514 static void write_library(FILE *header, const typelib_t *typelib)
516 const UUID *uuid = get_attrp(typelib->attrs, ATTR_UUID);
517 fprintf(header, "\n");
518 write_guid(header, "LIBID", typelib->name, uuid);
519 fprintf(header, "\n");
523 const var_t* get_explicit_handle_var(const var_t *func)
525 const var_t* var;
527 if (!type_get_function_args(func->type))
528 return NULL;
530 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
531 if (var->type->type == RPC_FC_BIND_PRIMITIVE)
532 return var;
534 return NULL;
537 const type_t* get_explicit_generic_handle_type(const var_t* var)
539 const type_t *t;
540 for (t = var->type; is_ptr(t); t = type_pointer_get_ref(t))
541 if (t->type != RPC_FC_BIND_PRIMITIVE && is_attr(t->attrs, ATTR_HANDLE))
542 return t;
543 return NULL;
546 const var_t* get_explicit_generic_handle_var(const var_t *func)
548 const var_t* var;
550 if (!type_get_function_args(func->type))
551 return NULL;
553 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
554 if (get_explicit_generic_handle_type(var))
555 return var;
557 return NULL;
560 const var_t* get_context_handle_var(const var_t *func)
562 const var_t* var;
564 if (!type_get_function_args(func->type))
565 return NULL;
567 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
568 if (is_attr(var->attrs, ATTR_IN) && is_context_handle(var->type))
569 return var;
571 return NULL;
574 int has_out_arg_or_return(const var_t *func)
576 const var_t *var;
578 if (!is_void(type_function_get_rettype(func->type)))
579 return 1;
581 if (!type_get_function_args(func->type))
582 return 0;
584 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
585 if (is_attr(var->attrs, ATTR_OUT))
586 return 1;
588 return 0;
592 /********** INTERFACES **********/
594 int is_object(const attr_list_t *list)
596 const attr_t *attr;
597 if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
598 if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
599 return 0;
602 int is_local(const attr_list_t *a)
604 return is_attr(a, ATTR_LOCAL);
607 const var_t *is_callas(const attr_list_t *a)
609 return get_attrp(a, ATTR_CALLAS);
612 static void write_method_macro(FILE *header, const type_t *iface, const char *name)
614 const statement_t *stmt;
615 int first_iface = 1;
617 if (type_iface_get_inherit(iface))
618 write_method_macro(header, type_iface_get_inherit(iface), name);
620 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
622 const var_t *func = stmt->u.var;
624 if (first_iface)
626 fprintf(header, "/*** %s methods ***/\n", iface->name);
627 first_iface = 0;
630 if (!is_callas(func->attrs)) {
631 const var_t *arg;
633 fprintf(header, "#define %s_%s(This", name, get_name(func));
634 if (type_get_function_args(func->type))
635 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
636 fprintf(header, ",%s", arg->name);
637 fprintf(header, ") ");
639 fprintf(header, "(This)->lpVtbl->%s(This", get_name(func));
640 if (type_get_function_args(func->type))
641 LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
642 fprintf(header, ",%s", arg->name);
643 fprintf(header, ")\n");
648 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
650 const var_t *arg;
651 int count = 0;
653 if (do_indent)
655 indentation++;
656 indent(h, 0);
658 if (method == 1) {
659 fprintf(h, "%s* This", name);
660 count++;
662 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
663 if (count) {
664 if (do_indent)
666 fprintf(h, ",\n");
667 indent(h, 0);
669 else fprintf(h, ",");
671 write_type_decl(h, arg->type, arg->name);
672 count++;
674 if (do_indent) indentation--;
677 static void write_cpp_method_def(FILE *header, const type_t *iface)
679 const statement_t *stmt;
681 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
683 const var_t *func = stmt->u.var;
684 if (!is_callas(func->attrs)) {
685 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
686 if (!callconv) callconv = "";
687 indent(header, 0);
688 fprintf(header, "virtual ");
689 write_type_decl_left(header, type_function_get_rettype(func->type));
690 fprintf(header, " %s %s(\n", callconv, get_name(func));
691 write_args(header, type_get_function_args(func->type), iface->name, 2, TRUE);
692 fprintf(header, ") = 0;\n");
693 fprintf(header, "\n");
698 static void do_write_c_method_def(FILE *header, const type_t *iface, const char *name)
700 const statement_t *stmt;
701 int first_iface = 1;
703 if (type_iface_get_inherit(iface))
704 do_write_c_method_def(header, type_iface_get_inherit(iface), name);
706 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
708 const var_t *func = stmt->u.var;
709 if (first_iface) {
710 indent(header, 0);
711 fprintf(header, "/*** %s methods ***/\n", iface->name);
712 first_iface = 0;
714 if (!is_callas(func->attrs)) {
715 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
716 if (!callconv) callconv = "";
717 indent(header, 0);
718 write_type_decl_left(header, type_function_get_rettype(func->type));
719 fprintf(header, " (%s *%s)(\n", callconv, get_name(func));
720 write_args(header, type_get_function_args(func->type), name, 1, TRUE);
721 fprintf(header, ");\n");
722 fprintf(header, "\n");
727 static void write_c_method_def(FILE *header, const type_t *iface)
729 do_write_c_method_def(header, iface, iface->name);
732 static void write_c_disp_method_def(FILE *header, const type_t *iface)
734 do_write_c_method_def(header, type_iface_get_inherit(iface), iface->name);
737 static void write_method_proto(FILE *header, const type_t *iface)
739 const statement_t *stmt;
741 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface))
743 const var_t *func = stmt->u.var;
745 if (!is_local(func->attrs)) {
746 const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
747 if (!callconv) callconv = "";
748 /* proxy prototype */
749 write_type_decl_left(header, type_function_get_rettype(func->type));
750 fprintf(header, " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(func));
751 write_args(header, type_get_function_args(func->type), iface->name, 1, TRUE);
752 fprintf(header, ");\n");
753 /* stub prototype */
754 fprintf(header, "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(func));
755 fprintf(header, " IRpcStubBuffer* This,\n");
756 fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n");
757 fprintf(header, " PRPC_MESSAGE pRpcMessage,\n");
758 fprintf(header, " DWORD* pdwStubPhase);\n");
763 static void write_locals(FILE *fp, const type_t *iface, int body)
765 static const char comment[]
766 = "/* WIDL-generated stub. You must provide an implementation for this. */";
767 const statement_t *stmt;
769 if (!is_object(iface->attrs))
770 return;
772 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) {
773 const var_t *func = stmt->u.var;
774 const var_t *cas = is_callas(func->attrs);
776 if (cas) {
777 const statement_t *stmt2 = NULL;
778 STATEMENTS_FOR_EACH_FUNC(stmt2, type_iface_get_stmts(iface))
779 if (!strcmp(stmt2->u.var->name, cas->name))
780 break;
781 if (&stmt2->entry != type_iface_get_stmts(iface)) {
782 const var_t *m = stmt2->u.var;
783 /* proxy prototype - use local prototype */
784 write_type_decl_left(fp, type_function_get_rettype(m->type));
785 fprintf(fp, " CALLBACK %s_%s_Proxy(\n", iface->name, get_name(m));
786 write_args(fp, type_get_function_args(m->type), iface->name, 1, TRUE);
787 fprintf(fp, ")");
788 if (body) {
789 type_t *rt = type_function_get_rettype(m->type);
790 fprintf(fp, "\n{\n");
791 fprintf(fp, " %s\n", comment);
792 if (rt->name && strcmp(rt->name, "HRESULT") == 0)
793 fprintf(fp, " return E_NOTIMPL;\n");
794 else if (rt->type) {
795 fprintf(fp, " ");
796 write_type_decl(fp, rt, "rv");
797 fprintf(fp, ";\n");
798 fprintf(fp, " memset(&rv, 0, sizeof rv);\n");
799 fprintf(fp, " return rv;\n");
801 fprintf(fp, "}\n\n");
803 else
804 fprintf(fp, ";\n");
805 /* stub prototype - use remotable prototype */
806 write_type_decl_left(fp, type_function_get_rettype(func->type));
807 fprintf(fp, " __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(m));
808 write_args(fp, type_get_function_args(func->type), iface->name, 1, TRUE);
809 fprintf(fp, ")");
810 if (body)
811 /* Remotable methods must all return HRESULTs. */
812 fprintf(fp, "\n{\n %s\n return E_NOTIMPL;\n}\n\n", comment);
813 else
814 fprintf(fp, ";\n");
816 else
817 error_loc("invalid call_as attribute (%s -> %s)\n", func->name, cas->name);
822 static void write_local_stubs_stmts(FILE *local_stubs, const statement_list_t *stmts)
824 const statement_t *stmt;
825 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
827 if (stmt->type == STMT_TYPE && stmt->u.type->type == RPC_FC_IP)
828 write_locals(local_stubs, stmt->u.type, TRUE);
829 else if (stmt->type == STMT_LIBRARY)
830 write_local_stubs_stmts(local_stubs, stmt->u.lib->stmts);
834 void write_local_stubs(const statement_list_t *stmts)
836 FILE *local_stubs;
838 if (!local_stubs_name) return;
840 local_stubs = fopen(local_stubs_name, "w");
841 if (!local_stubs) {
842 error("Could not open %s for output\n", local_stubs_name);
843 return;
845 fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name);
846 fprintf(local_stubs, "#include <objbase.h>\n");
847 fprintf(local_stubs, "#include \"%s\"\n\n", header_name);
849 write_local_stubs_stmts(local_stubs, stmts);
851 fclose(local_stubs);
854 static void write_function_proto(FILE *header, const type_t *iface, const var_t *fun, const char *prefix)
856 const char *callconv = get_attrp(fun->type->attrs, ATTR_CALLCONV);
858 /* FIXME: do we need to handle call_as? */
859 write_type_decl_left(header, type_function_get_rettype(fun->type));
860 fprintf(header, " ");
861 if (callconv) fprintf(header, "%s ", callconv);
862 fprintf(header, "%s%s(\n", prefix, get_name(fun));
863 if (type_get_function_args(fun->type))
864 write_args(header, type_get_function_args(fun->type), iface->name, 0, TRUE);
865 else
866 fprintf(header, " void");
867 fprintf(header, ");\n\n");
870 static void write_forward(FILE *header, type_t *iface)
872 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
873 fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
874 fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
875 fprintf(header, "#endif\n\n" );
878 static void write_iface_guid(FILE *header, const type_t *iface)
880 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
881 write_guid(header, "IID", iface->name, uuid);
884 static void write_dispiface_guid(FILE *header, const type_t *iface)
886 const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
887 write_guid(header, "DIID", iface->name, uuid);
890 static void write_coclass_guid(FILE *header, const type_t *cocl)
892 const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
893 write_guid(header, "CLSID", cocl->name, uuid);
896 static void write_com_interface_start(FILE *header, const type_t *iface)
898 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
899 fprintf(header, "/*****************************************************************************\n");
900 fprintf(header, " * %s %sinterface\n", iface->name, dispinterface ? "disp" : "");
901 fprintf(header, " */\n");
902 fprintf(header,"#ifndef __%s_%sINTERFACE_DEFINED__\n", iface->name, dispinterface ? "DISP" : "");
903 fprintf(header,"#define __%s_%sINTERFACE_DEFINED__\n\n", iface->name, dispinterface ? "DISP" : "");
906 static void write_com_interface_end(FILE *header, type_t *iface)
908 int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
909 if (dispinterface)
910 write_dispiface_guid(header, iface);
911 else
912 write_iface_guid(header, iface);
913 /* C++ interface */
914 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
915 if (type_iface_get_inherit(iface))
917 fprintf(header, "interface %s : public %s\n", iface->name,
918 type_iface_get_inherit(iface)->name);
919 fprintf(header, "{\n");
921 else
923 fprintf(header, "interface %s\n", iface->name);
924 fprintf(header, "{\n");
925 fprintf(header, " BEGIN_INTERFACE\n");
926 fprintf(header, "\n");
928 /* dispinterfaces don't have real functions, so don't write C++ functions for
929 * them */
930 if (!dispinterface)
932 indentation++;
933 write_cpp_method_def(header, iface);
934 indentation--;
936 if (!type_iface_get_inherit(iface))
937 fprintf(header, " END_INTERFACE\n");
938 fprintf(header, "};\n");
939 fprintf(header, "#else\n");
940 /* C interface */
941 fprintf(header, "typedef struct %sVtbl {\n", iface->name);
942 indentation++;
943 fprintf(header, " BEGIN_INTERFACE\n");
944 fprintf(header, "\n");
945 if (dispinterface)
946 write_c_disp_method_def(header, iface);
947 else
948 write_c_method_def(header, iface);
949 indentation--;
950 fprintf(header, " END_INTERFACE\n");
951 fprintf(header, "} %sVtbl;\n", iface->name);
952 fprintf(header, "interface %s {\n", iface->name);
953 fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
954 fprintf(header, "};\n");
955 fprintf(header, "\n");
956 fprintf(header, "#ifdef COBJMACROS\n");
957 /* dispinterfaces don't have real functions, so don't write macros for them,
958 * only for the interface this interface inherits from, i.e. IDispatch */
959 write_method_macro(header, dispinterface ? type_iface_get_inherit(iface) : iface, iface->name);
960 fprintf(header, "#endif\n");
961 fprintf(header, "\n");
962 fprintf(header, "#endif\n");
963 fprintf(header, "\n");
964 /* dispinterfaces don't have real functions, so don't write prototypes for
965 * them */
966 if (!dispinterface)
968 write_method_proto(header, iface);
969 write_locals(header, iface, FALSE);
970 fprintf(header, "\n");
972 fprintf(header,"#endif /* __%s_%sINTERFACE_DEFINED__ */\n\n", iface->name, dispinterface ? "DISP" : "");
975 static void write_rpc_interface_start(FILE *header, const type_t *iface)
977 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
978 const char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
979 static int allocate_written = 0;
981 if (!allocate_written)
983 allocate_written = 1;
984 fprintf(header, "void * __RPC_USER MIDL_user_allocate(SIZE_T);\n");
985 fprintf(header, "void __RPC_USER MIDL_user_free(void *);\n\n");
988 fprintf(header, "/*****************************************************************************\n");
989 fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
990 fprintf(header, " */\n");
991 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
992 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
993 if (var) fprintf(header, "extern handle_t %s;\n", var);
994 if (old_names)
996 fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
997 fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
999 else
1001 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
1002 prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1003 fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
1004 prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver));
1008 static void write_rpc_interface_end(FILE *header, const type_t *iface)
1010 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
1013 static void write_coclass(FILE *header, type_t *cocl)
1015 fprintf(header, "/*****************************************************************************\n");
1016 fprintf(header, " * %s coclass\n", cocl->name);
1017 fprintf(header, " */\n\n");
1018 write_coclass_guid(header, cocl);
1019 fprintf(header, "\n");
1022 static void write_coclass_forward(FILE *header, type_t *cocl)
1024 fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
1025 fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
1026 fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name);
1027 fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
1030 static void write_import(FILE *header, const char *fname)
1032 char *hname, *p;
1034 hname = dup_basename(fname, ".idl");
1035 p = hname + strlen(hname) - 2;
1036 if (p <= hname || strcmp( p, ".h" )) strcat(hname, ".h");
1038 fprintf(header, "#include <%s>\n", hname);
1039 free(hname);
1042 static void write_imports(FILE *header, const statement_list_t *stmts)
1044 const statement_t *stmt;
1045 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1047 switch (stmt->type)
1049 case STMT_TYPE:
1050 if (stmt->u.type->type == RPC_FC_IP)
1051 write_imports(header, type_iface_get_stmts(stmt->u.type));
1052 break;
1053 case STMT_TYPEREF:
1054 case STMT_IMPORTLIB:
1055 /* not included in header */
1056 break;
1057 case STMT_IMPORT:
1058 write_import(header, stmt->u.str);
1059 break;
1060 case STMT_TYPEDEF:
1061 case STMT_MODULE:
1062 case STMT_CPPQUOTE:
1063 case STMT_DECLARATION:
1064 /* not processed here */
1065 break;
1066 case STMT_LIBRARY:
1067 write_imports(header, stmt->u.lib->stmts);
1068 break;
1073 static void write_forward_decls(FILE *header, const statement_list_t *stmts)
1075 const statement_t *stmt;
1076 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1078 switch (stmt->type)
1080 case STMT_TYPE:
1081 if (stmt->u.type->type == RPC_FC_IP)
1083 if (is_object(stmt->u.type->attrs) || is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE))
1084 write_forward(header, stmt->u.type);
1086 else if (stmt->u.type->type == RPC_FC_COCLASS)
1087 write_coclass_forward(header, stmt->u.type);
1088 break;
1089 case STMT_TYPEREF:
1090 case STMT_IMPORTLIB:
1091 /* not included in header */
1092 break;
1093 case STMT_IMPORT:
1094 case STMT_TYPEDEF:
1095 case STMT_MODULE:
1096 case STMT_CPPQUOTE:
1097 case STMT_DECLARATION:
1098 /* not processed here */
1099 break;
1100 case STMT_LIBRARY:
1101 write_forward_decls(header, stmt->u.lib->stmts);
1102 break;
1107 static void write_header_stmts(FILE *header, const statement_list_t *stmts, const type_t *iface, int ignore_funcs)
1109 const statement_t *stmt;
1110 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1112 switch (stmt->type)
1114 case STMT_TYPE:
1115 if (stmt->u.type->type == RPC_FC_IP)
1117 type_t *iface = stmt->u.type;
1118 if (is_attr(stmt->u.type->attrs, ATTR_DISPINTERFACE) || is_object(stmt->u.type->attrs))
1120 write_com_interface_start(header, iface);
1121 write_header_stmts(header, type_iface_get_stmts(iface), stmt->u.type, TRUE);
1122 write_com_interface_end(header, iface);
1124 else
1126 write_rpc_interface_start(header, iface);
1127 write_header_stmts(header, type_iface_get_stmts(iface), iface, FALSE);
1128 write_rpc_interface_end(header, iface);
1131 else if (stmt->u.type->type == RPC_FC_COCLASS)
1132 write_coclass(header, stmt->u.type);
1133 else
1135 write_type_def_or_decl(header, stmt->u.type, FALSE, NULL);
1136 fprintf(header, ";\n\n");
1138 break;
1139 case STMT_TYPEREF:
1140 /* FIXME: shouldn't write out forward declarations for undefined
1141 * interfaces but a number of our IDL files depend on this */
1142 if (stmt->u.type->type == RPC_FC_IP && !stmt->u.type->written)
1143 write_forward(header, stmt->u.type);
1144 break;
1145 case STMT_IMPORTLIB:
1146 case STMT_MODULE:
1147 /* not included in header */
1148 break;
1149 case STMT_IMPORT:
1150 /* not processed here */
1151 break;
1152 case STMT_TYPEDEF:
1154 const type_list_t *type_entry = stmt->u.type_list;
1155 for (; type_entry; type_entry = type_entry->next)
1156 write_typedef(header, type_entry->type);
1157 break;
1159 case STMT_LIBRARY:
1160 write_library(header, stmt->u.lib);
1161 write_header_stmts(header, stmt->u.lib->stmts, NULL, FALSE);
1162 break;
1163 case STMT_CPPQUOTE:
1164 fprintf(header, "%s\n", stmt->u.str);
1165 break;
1166 case STMT_DECLARATION:
1167 if (iface && stmt->u.var->type->type == RPC_FC_FUNCTION)
1169 if (!ignore_funcs)
1171 int prefixes_differ = strcmp(prefix_client, prefix_server);
1173 if (prefixes_differ)
1175 fprintf(header, "/* client prototype */\n");
1176 write_function_proto(header, iface, stmt->u.var, prefix_client);
1177 fprintf(header, "/* server prototype */\n");
1179 write_function_proto(header, iface, stmt->u.var, prefix_server);
1182 else
1183 write_declaration(header, stmt->u.var);
1184 break;
1189 void write_header(const statement_list_t *stmts)
1191 FILE *header;
1193 if (!do_header) return;
1195 if(!(header = fopen(header_name, "w"))) {
1196 error("Could not open %s for output\n", header_name);
1197 return;
1199 fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n\n", PACKAGE_VERSION, input_name);
1200 fprintf(header, "#include <rpc.h>\n" );
1201 fprintf(header, "#include <rpcndr.h>\n\n" );
1203 fprintf(header, "#ifndef __WIDL_%s\n", header_token);
1204 fprintf(header, "#define __WIDL_%s\n\n", header_token);
1205 start_cplusplus_guard(header);
1207 fprintf(header, "/* Headers for imported files */\n\n");
1208 write_imports(header, stmts);
1209 fprintf(header, "\n");
1211 /* FIXME: should be before imported file includes */
1212 fprintf(header, "/* Forward declarations */\n\n");
1213 write_forward_decls(header, stmts);
1214 fprintf(header, "\n");
1216 write_header_stmts(header, stmts, NULL, FALSE);
1218 fprintf(header, "/* Begin additional prototypes for all interfaces */\n");
1219 fprintf(header, "\n");
1220 write_user_types(header);
1221 write_generic_handle_routines(header);
1222 write_context_handle_rundowns(header);
1223 fprintf(header, "\n");
1224 fprintf(header, "/* End additional prototypes */\n");
1225 fprintf(header, "\n");
1227 end_cplusplus_guard(header);
1228 fprintf(header, "#endif /* __WIDL_%s */\n", header_token);
1230 fclose(header);