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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
38 static int indentation = 0;
40 static void indent(int delta)
43 if (delta < 0) indentation += delta;
44 for (c=0; c<indentation; c++) fprintf(header, " ");
45 if (delta > 0) indentation += delta;
48 int is_attr(attr_t *a, enum attr_type t)
51 if (a->type == t) return 1;
57 void *get_attrp(attr_t *a, enum attr_type t)
60 if (a->type == t) return a->u.pval;
66 unsigned long get_attrv(attr_t *a, enum attr_type t)
69 if (a->type == t) return a->u.ival;
75 int is_void(type_t *t, var_t *v)
77 if (v && v->ptr_level) return 0;
78 if (!t->type && !t->ref) return 1;
82 static void write_pident(FILE *h, var_t *v)
85 for (c=0; c<v->ptr_level; c++) {
88 if (v->name) fprintf(h, "%s", v->name);
91 void write_name(FILE *h, var_t *v)
93 if (is_attr( v->attrs, ATTR_PROPGET ))
95 else if (is_attr( v->attrs, ATTR_PROPPUT ))
97 fprintf(h, "%s", v->name);
100 char* get_name(var_t *v)
105 static void write_array(FILE *h, expr_t *v, int field)
108 while (NEXT_LINK(v)) v = NEXT_LINK(v);
112 fprintf(h, "%ld", v->cval); /* statically sized array */
114 if (field) fprintf(h, "1"); /* dynamically sized array */
122 static void write_field(FILE *h, var_t *v)
127 write_type(h, v->type, NULL, v->tname);
133 /* not all C/C++ compilers support anonymous structs and unions */
134 switch (v->type->type) {
136 case RPC_FC_CVSTRUCT:
137 case RPC_FC_CPSTRUCT:
140 case RPC_FC_BOGUS_STRUCT:
141 case RPC_FC_ENCAPSULATED_UNION:
142 fprintf(h, " DUMMYSTRUCTNAME");
144 case RPC_FC_NON_ENCAPSULATED_UNION:
145 fprintf(h, " DUMMYUNIONNAME");
152 write_array(h, v->array, 1);
157 static void write_fields(FILE *h, var_t *v)
161 while (NEXT_LINK(v)) v = NEXT_LINK(v);
164 if (v == first) break;
169 static void write_enums(FILE *h, var_t *v)
172 while (NEXT_LINK(v)) v = NEXT_LINK(v);
179 write_expr(h, v->eval);
189 void write_type(FILE *h, type_t *t, var_t *v, char *n)
193 if (n) fprintf(h, "%s", n);
195 if (t->is_const) fprintf(h, "const ");
197 if (t->sign > 0) fprintf(h, "signed ");
198 else if (t->sign < 0) fprintf(h, "unsigned ");
201 if (t->ref) fprintf(h, t->ref->name);
202 else fprintf(h, "byte");
205 if (t->ref) fprintf(h, t->ref->name);
206 else fprintf(h, "char");
209 fprintf(h, "wchar_t");
213 if (t->ref) fprintf(h, t->ref->name);
214 else fprintf(h, "short");
218 if (t->ref) fprintf(h, t->ref->name);
219 else fprintf(h, "long");
222 if (t->ref) fprintf(h, t->ref->name);
223 else fprintf(h, "hyper");
229 fprintf(h, "double");
233 if (t->defined && !t->written) {
234 if (t->name) fprintf(h, "enum %s {\n", t->name);
235 else fprintf(h, "enum {\n");
238 write_enums(h, t->fields);
242 else fprintf(h, "enum %s", t->name);
244 case RPC_FC_ERROR_STATUS_T:
245 if (t->ref) fprintf(h, t->ref->name);
246 else fprintf(h, "error_status_t");
248 case RPC_FC_BIND_PRIMITIVE:
249 if (t->ref) fprintf(h, t->ref->name);
250 else fprintf(h, "handle_t");
253 case RPC_FC_CVSTRUCT:
254 case RPC_FC_CPSTRUCT:
257 case RPC_FC_BOGUS_STRUCT:
258 case RPC_FC_ENCAPSULATED_UNION:
259 if (t->defined && !t->written) {
260 if (t->name) fprintf(h, "struct %s {\n", t->name);
261 else fprintf(h, "struct {\n");
264 write_fields(h, t->fields);
268 else fprintf(h, "struct %s", t->name);
270 case RPC_FC_NON_ENCAPSULATED_UNION:
271 if (t->defined && !t->written) {
272 if (t->name) fprintf(h, "union %s {\n", t->name);
273 else fprintf(h, "union {\n");
276 write_fields(h, t->fields);
280 else fprintf(h, "union %s", t->name);
283 fprintf(h, "(unknown-type:%d)", t->type);
288 write_type(h, t->ref, NULL, t->name);
290 else fprintf(h, "void");
294 for (c=0; c<v->ptr_level; c++) {
300 void write_typedef(type_t *type, var_t *names)
302 char *tname = names->tname;
304 while (NEXT_LINK(names)) names = NEXT_LINK(names);
306 fprintf(header, "typedef ");
307 write_type(header, type, NULL, tname);
308 fprintf(header, " ");
310 write_pident(header, names);
311 if (PREV_LINK(names))
312 fprintf(header, ", ");
313 names = PREV_LINK(names);
315 fprintf(header, ";\n");
317 if (get_attrp(type->attrs, ATTR_WIREMARSHAL)) {
320 char *name = get_name(names);
321 fprintf(header, "unsigned long __RPC_USER %s_UserSize (unsigned long *, unsigned long, %s *);\n", name, name);
322 fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (unsigned long *, unsigned char *, %s *);\n", name, name);
323 fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(unsigned long *, unsigned char *, %s *);\n", name, name);
324 fprintf(header, "void __RPC_USER %s_UserFree (unsigned long *, %s *);\n", name, name);
325 if (PREV_LINK(names))
326 fprintf(header, ", ");
327 names = PREV_LINK(names);
331 fprintf(header, "\n");
334 static void do_write_expr(FILE *h, expr_t *e, int p)
340 fprintf(h, "%ld", e->u.lval);
343 fprintf(h, "0x%lx", e->u.lval);
345 case EXPR_IDENTIFIER:
346 fprintf(h, "%s", e->u.sval);
350 do_write_expr(h, e->ref, 1);
354 do_write_expr(h, e->ref, 1);
358 do_write_expr(h, e->ref, 1);
362 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
364 do_write_expr(h, e->ref, 1);
367 fprintf(h, "sizeof(");
368 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
379 if (p) fprintf(h, "(");
380 do_write_expr(h, e->ref, 1);
382 case EXPR_SHL: fprintf(h, " << "); break;
383 case EXPR_SHR: fprintf(h, " >> "); break;
384 case EXPR_MUL: fprintf(h, " * "); break;
385 case EXPR_DIV: fprintf(h, " / "); break;
386 case EXPR_ADD: fprintf(h, " + "); break;
387 case EXPR_SUB: fprintf(h, " - "); break;
388 case EXPR_AND: fprintf(h, " & "); break;
389 case EXPR_OR: fprintf(h, " | "); break;
392 do_write_expr(h, e->u.ext, 1);
393 if (p) fprintf(h, ")");
396 if (p) fprintf(h, "(");
397 do_write_expr(h, e->ref, 1);
399 do_write_expr(h, e->u.ext, 1);
401 do_write_expr(h, e->ext2, 1);
402 if (p) fprintf(h, ")");
407 void write_expr(FILE *h, expr_t *e)
409 do_write_expr(h, e, 0);
412 void write_constdef(var_t *v)
414 fprintf(header, "#define %s (", get_name(v));
415 write_expr(header, v->eval);
416 fprintf(header, ")\n\n");
419 void write_externdef(var_t *v)
421 fprintf(header, "extern const ");
422 write_type(header, v->type, NULL, v->tname);
424 fprintf(header, " ");
425 write_pident(header, v);
427 fprintf(header, ";\n\n");
430 /********** INTERFACES **********/
432 int is_object(attr_t *a)
435 if (a->type == ATTR_OBJECT || a->type == ATTR_ODL) return 1;
441 int is_local(attr_t *a)
443 return is_attr(a, ATTR_LOCAL);
446 var_t *is_callas(attr_t *a)
448 return get_attrp(a, ATTR_CALLAS);
451 static int write_method_macro(type_t *iface, char *name)
454 func_t *cur = iface->funcs;
456 if (iface->ref) idx = write_method_macro(iface->ref, name);
459 if (!cur) return idx;
460 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
462 fprintf(header, "/*** %s methods ***/\n", iface->name);
464 var_t *def = cur->def;
465 if (!is_callas(def->attrs)) {
466 var_t *arg = cur->args;
470 arg = NEXT_LINK(arg);
474 fprintf(header, "#define %s_", name);
475 write_name(header,def);
476 fprintf(header, "(p");
477 for (c=0; c<argc; c++)
478 fprintf(header, ",%c", c+'a');
479 fprintf(header, ") ");
481 fprintf(header, "(p)->lpVtbl->");
482 write_name(header, def);
483 fprintf(header, "(p");
484 for (c=0; c<argc; c++)
485 fprintf(header, ",%c", c+'a');
486 fprintf(header, ")\n");
487 if (cur->idx == -1) cur->idx = idx;
488 else if (cur->idx != idx) yyerror("BUG: method index mismatch in write_method_macro");
491 cur = PREV_LINK(cur);
496 void write_args(FILE *h, var_t *arg, char *name, int method, int do_indent)
500 while (NEXT_LINK(arg))
501 arg = NEXT_LINK(arg);
508 } else fprintf(h, " ");
511 fprintf(h, "%s* This", name);
519 if (h == header) indent(0);
520 else fprintf(h, " ");
522 else fprintf(h, ",");
524 write_type(h, arg->type, arg, arg->tname);
527 fprintf(h, " (STDMETHODCALLTYPE *");
530 write_args(h, arg->args, NULL, 0, FALSE);
538 write_array(h, arg->array, 0);
539 arg = PREV_LINK(arg);
542 if (do_indent && h == header) indentation--;
545 static void write_cpp_method_def(type_t *iface)
547 func_t *cur = iface->funcs;
550 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
552 var_t *def = cur->def;
553 if (!is_callas(def->attrs)) {
555 fprintf(header, "virtual ");
556 write_type(header, def->type, def, def->tname);
557 fprintf(header, " STDMETHODCALLTYPE ");
558 write_name(header, def);
559 fprintf(header, "(\n");
560 write_args(header, cur->args, iface->name, 2, TRUE);
561 fprintf(header, ") = 0;\n");
562 fprintf(header, "\n");
564 cur = PREV_LINK(cur);
568 static void do_write_c_method_def(type_t *iface, char *name)
570 func_t *cur = iface->funcs;
572 if (iface->ref) do_write_c_method_def(iface->ref, name);
575 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
577 fprintf(header, "/*** %s methods ***/\n", iface->name);
579 var_t *def = cur->def;
580 if (!is_callas(def->attrs)) {
582 write_type(header, def->type, def, def->tname);
583 fprintf(header, " (STDMETHODCALLTYPE *");
584 write_name(header, def);
585 fprintf(header, ")(\n");
586 write_args(header, cur->args, name, 1, TRUE);
587 fprintf(header, ");\n");
588 fprintf(header, "\n");
590 cur = PREV_LINK(cur);
594 static void write_c_method_def(type_t *iface)
596 do_write_c_method_def(iface, iface->name);
599 static void write_c_disp_method_def(type_t *iface)
601 do_write_c_method_def(iface->ref, iface->name);
604 static void write_method_proto(type_t *iface)
606 func_t *cur = iface->funcs;
609 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
611 var_t *def = cur->def;
612 var_t *cas = is_callas(def->attrs);
613 if (!is_local(def->attrs)) {
614 /* proxy prototype */
615 write_type(header, def->type, def, def->tname);
616 fprintf(header, " CALLBACK %s_", iface->name);
617 write_name(header, def);
618 fprintf(header, "_Proxy(\n");
619 write_args(header, cur->args, iface->name, 1, TRUE);
620 fprintf(header, ");\n");
622 fprintf(header, "void __RPC_STUB %s_", iface->name);
623 write_name(header,def);
624 fprintf(header, "_Stub(\n");
625 fprintf(header, " struct IRpcStubBuffer* This,\n");
626 fprintf(header, " struct IRpcChannelBuffer* pRpcChannelBuffer,\n");
627 fprintf(header, " PRPC_MESSAGE pRpcMessage,\n");
628 fprintf(header, " DWORD* pdwStubPhase);\n");
631 func_t *m = iface->funcs;
632 while (m && strcmp(get_name(m->def), cas->name))
635 var_t *mdef = m->def;
636 /* proxy prototype - use local prototype */
637 write_type(header, mdef->type, mdef, mdef->tname);
638 fprintf(header, " CALLBACK %s_", iface->name);
639 write_name(header, mdef);
640 fprintf(header, "_Proxy(\n");
641 write_args(header, m->args, iface->name, 1, TRUE);
642 fprintf(header, ");\n");
643 /* stub prototype - use remotable prototype */
644 write_type(header, def->type, def, def->tname);
645 fprintf(header, " __RPC_STUB %s_", iface->name);
646 write_name(header, mdef);
647 fprintf(header, "_Stub(\n");
648 write_args(header, cur->args, iface->name, 1, TRUE);
649 fprintf(header, ");\n");
652 yywarning("invalid call_as attribute (%s -> %s)\n", get_name(def), cas->name);
656 cur = PREV_LINK(cur);
660 static void write_function_proto(type_t *iface)
662 func_t *cur = iface->funcs;
663 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
665 var_t *def = cur->def;
666 /* FIXME: do we need to handle call_as? */
667 write_type(header, def->type, def, def->tname);
668 fprintf(header, " ");
669 write_name(header, def);
670 fprintf(header, "(\n");
671 write_args(header, cur->args, iface->name, 0, TRUE);
672 fprintf(header, ");\n");
674 cur = PREV_LINK(cur);
678 void write_forward(type_t *iface)
680 /* C/C++ forwards should only be written for object interfaces, so if we
681 * have a full definition we only write one if we find [object] among the
682 * attributes - however, if we don't have a full definition at this point
683 * (i.e. this is an IDL forward), then we also assume that it is an object
684 * interface, since non-object interfaces shouldn't need forwards */
685 if ((!iface->defined || is_object(iface->attrs)) && !iface->written) {
686 fprintf(header,"#ifndef __%s_FWD_DEFINED__\n", iface->name);
687 fprintf(header,"#define __%s_FWD_DEFINED__\n", iface->name);
688 fprintf(header, "typedef struct %s %s;\n", iface->name, iface->name);
689 fprintf(header, "#endif\n\n" );
690 iface->written = TRUE;
694 void write_guid(const char *guid_prefix, const char *name, UUID *uuid)
697 fprintf(header, "DEFINE_GUID(%s_%s, 0x%08lx, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
698 guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
699 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], uuid->Data4[7]);
702 void write_iface_guid(type_t *iface)
704 UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
705 write_guid("IID", iface->name, uuid);
708 void write_dispiface_guid(type_t *iface)
710 UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
711 write_guid("DIID", iface->name, uuid);
714 void write_coclass_guid(class_t *cocl)
716 UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
717 write_guid("CLSID", cocl->name, uuid);
720 void write_com_interface(type_t *iface)
722 if (!iface->funcs && !iface->ref) {
723 yywarning("%s has no methods", iface->name);
727 fprintf(header, "/*****************************************************************************\n");
728 fprintf(header, " * %s interface\n", iface->name);
729 fprintf(header, " */\n");
730 fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
731 fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
732 write_iface_guid(iface);
733 write_forward(iface);
735 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
738 fprintf(header, "struct %s : public %s\n", iface->name, iface->ref->name);
739 fprintf(header, "{\n");
741 write_cpp_method_def(iface);
743 fprintf(header, "};\n");
747 fprintf(header, "struct %s\n", iface->name);
748 fprintf(header, "{\n");
749 fprintf(header, " BEGIN_INTERFACE\n");
750 fprintf(header, "\n");
752 write_cpp_method_def(iface);
754 fprintf(header, " END_INTERFACE\n");
755 fprintf(header, "};\n");
757 fprintf(header, "#else\n");
759 fprintf(header, "typedef struct %sVtbl %sVtbl;\n", iface->name, iface->name);
760 fprintf(header, "struct %s {\n", iface->name);
761 fprintf(header, " const %sVtbl* lpVtbl;\n", iface->name);
762 fprintf(header, "};\n");
763 fprintf(header, "struct %sVtbl {\n", iface->name);
765 fprintf(header, " BEGIN_INTERFACE\n");
766 fprintf(header, "\n");
767 write_c_method_def(iface);
769 fprintf(header, " END_INTERFACE\n");
770 fprintf(header, "};\n");
771 fprintf(header, "\n");
772 fprintf(header, "#ifdef COBJMACROS\n");
773 write_method_macro(iface, iface->name);
774 fprintf(header, "#endif\n");
775 fprintf(header, "\n");
776 fprintf(header, "#endif\n");
777 fprintf(header, "\n");
778 write_method_proto(iface);
779 fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
782 void write_rpc_interface(type_t *iface)
784 unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
786 if (!iface->funcs) return;
788 fprintf(header, "/*****************************************************************************\n");
789 fprintf(header, " * %s interface (v%d.%d)\n", iface->name, LOWORD(ver), HIWORD(ver));
790 fprintf(header, " */\n");
791 write_iface_guid(iface);
792 fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_c_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
793 fprintf(header, "extern RPC_IF_HANDLE %s_v%d_%d_s_ifspec;\n", iface->name, LOWORD(ver), HIWORD(ver));
794 write_function_proto(iface);
795 fprintf(header, "\n");
797 /* FIXME: server/client code */
800 void write_interface(type_t *iface)
802 if (is_object(iface->attrs))
803 write_com_interface(iface);
805 write_rpc_interface(iface);
808 void write_dispinterface(type_t *iface)
810 fprintf(header, "/*****************************************************************************\n");
811 fprintf(header, " * %s dispinterface\n", iface->name);
812 fprintf(header, " */\n");
813 fprintf(header,"#ifndef __%s_DISPINTERFACE_DEFINED__\n", iface->name);
814 fprintf(header,"#define __%s_DISPINTERFACE_DEFINED__\n\n", iface->name);
815 write_dispiface_guid(iface);
816 write_forward(iface);
818 fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
819 fprintf(header, "struct %s : public %s\n", iface->name, iface->ref->name);
820 fprintf(header, "{\n");
821 fprintf(header, "};\n");
822 fprintf(header, "#else\n");
824 fprintf(header, "typedef struct %sVtbl %sVtbl;\n", iface->name, iface->name);
825 fprintf(header, "struct %s {\n", iface->name);
826 fprintf(header, " const %sVtbl* lpVtbl;\n", iface->name);
827 fprintf(header, "};\n");
828 fprintf(header, "struct %sVtbl {\n", iface->name);
830 fprintf(header, " BEGIN_INTERFACE\n");
831 fprintf(header, "\n");
832 write_c_disp_method_def(iface);
834 fprintf(header, " END_INTERFACE\n");
835 fprintf(header, "};\n");
836 fprintf(header, "\n");
837 fprintf(header, "#ifdef COBJMACROS\n");
838 write_method_macro(iface->ref, iface->name);
839 fprintf(header, "#endif\n");
840 fprintf(header, "\n");
841 fprintf(header, "#endif\n");
842 fprintf(header, "\n");
843 fprintf(header,"#endif /* __%s_DISPINTERFACE_DEFINED__ */\n\n", iface->name);
846 void write_coclass(class_t *cocl)
848 fprintf(header, "/*****************************************************************************\n");
849 fprintf(header, " * %s coclass\n", cocl->name);
850 fprintf(header, " */\n\n");
851 write_coclass_guid(cocl);
852 fprintf(header, "\n");