widl ICOM patch

Ove Kaaven ovehk at ping.uio.no
Sat Dec 14 08:42:11 CST 2002


(This is independent of the other widl patch)

This makes widl-generated headers not depend on the ICOM macros by default
(they still depend on ICOM_COM_INTERFACE_ATTRIBUTE and
ICOM_MSVTABLE_COMPAT_FIELDS, but those are too useful to go away and
simple enough to be defined directly in unknwn.idl/unknwn.h). But the
output can be modified by two new command-line options:

-b = compatibility with ICOM macros (defines *_IMETHODS, so that the
interface can be inherited from with ICOM macros)

-B = use ICOM macros (i.e. old behaviour) (can be useful for creating
something to paste into headers that can't be autogenerated)

Since most of Wine uses the ICOM macros, the unknwn.idl, and probably
other idl files, MUST be compiled with ICOM compatibility for Wine to
compile, so I included a patch to add -b to the makefile rule.

Log:
Ove Kaaven <ovek at transgaming.com>
Output raw ICOM-less C/C++ interface definitions by default. Added new
-b and -B command-line options for compatibility with ICOM macros.

Index: include/Makefile.in
===================================================================
RCS file: /home/wine/wine/include/Makefile.in,v
retrieving revision 1.70
diff -u -r1.70 Makefile.in
--- include/Makefile.in	12 Dec 2002 23:34:02 -0000	1.70
+++ include/Makefile.in	14 Dec 2002 14:17:02 -0000
@@ -244,7 +244,7 @@
 .SUFFIXES: .idl .h
 
 .idl.h:
-	$(LDPATH) $(WIDL) $(DEFS) -h -H $@ $<
+	$(LDPATH) $(WIDL) $(DEFS) -b -h -H $@ $<
 
 install::
 	$(MKINSTALLDIRS) $(includedir) $(includedir)/windows $(includedir)/msvcrt $(includedir)/msvcrt/sys
Index: tools/widl/header.c
===================================================================
RCS file: /home/wine/wine/tools/widl/header.c,v
retrieving revision 1.8
diff -u -r1.8 header.c
--- tools/widl/header.c	3 Dec 2002 19:12:07 -0000	1.8
+++ tools/widl/header.c	14 Dec 2002 14:19:44 -0000
@@ -72,7 +72,7 @@
   return v->name;
 }
 
-static void write_array(FILE *h, expr_t *v)
+static void write_array(FILE *h, expr_t *v, int field)
 {
   if (!v) return;
   while (NEXT_LINK(v)) v = NEXT_LINK(v);
@@ -81,7 +81,7 @@
     if (v->is_const)
       fprintf(h, "%ld", v->cval); /* statically sized array */
     else
-      fprintf(h, "1"); /* dynamically sized array */
+      if (field) fprintf(h, "1"); /* dynamically sized array */
     if (PREV_LINK(v))
       fprintf(h, ", ");
     v = PREV_LINK(v);
@@ -114,7 +114,7 @@
         break;
       }
     }
-    write_array(h, v->array);
+    write_array(h, v->array, 1);
     fprintf(h, ";\n");
   }
 }
@@ -404,11 +404,10 @@
   return get_attrp(a, ATTR_CALLAS);
 }
 
-static void write_method_def(type_t *iface)
+static void write_icom_method_def(type_t *iface)
 {
   func_t *cur = iface->funcs;
   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
-  fprintf(header, "#define %s_METHODS", iface->name);
   while (cur) {
     var_t *def = cur->def;
     if (!is_callas(def->attrs)) {
@@ -438,6 +437,9 @@
       while (arg) {
 	fprintf(header, ",");
 	write_type(header, arg->type, arg, arg->tname);
+	/* since the ICOM macros can't express arrays,
+	 * we have to pretend they're pointers instead */
+	if (arg->array) fprintf(header, "*");
 	fprintf(header, ",");
 	write_name(header,arg);
 	arg = PREV_LINK(arg);
@@ -476,12 +478,19 @@
 	fprintf(header, ",%c", c+'a');
       fprintf(header, ") ");
 
-      if (argc)
-	fprintf(header, "ICOM_CALL%d(", argc);
-      else
-	fprintf(header, "ICOM_CALL(");
-      write_name(header,def);
-      fprintf(header, ",p");
+      if (use_icom) {
+	if (argc)
+	  fprintf(header, "ICOM_CALL%d(", argc);
+	else
+	  fprintf(header, "ICOM_CALL(");
+	write_name(header, def);
+	fprintf(header, ",p");
+      }
+      else {
+	fprintf(header, "(p)->lpVtbl->");
+	write_name(header, def);
+	fprintf(header, "(p");
+      }
       for (c=0; c<argc; c++)
 	fprintf(header, ",%c", c+'a');
       fprintf(header, ")\n");
@@ -501,19 +510,74 @@
     while (NEXT_LINK(arg))
       arg = NEXT_LINK(arg);
   }
-  if (method) {
-    fprintf(h, "    %s* This", name);
+  if (h == header) {
+    indentation++;
+    indent(0);
+  } else fprintf(h, "    ");
+  if (method == 1) {
+    fprintf(h, "%s* This", name);
     count++;
   }
-  else fprintf(h, "    ");
   while (arg) {
-    if (count) fprintf(h, ",\n    ");
+    if (count) {
+      fprintf(h, ",\n");
+      if (h == header) indent(0);
+      else fprintf(h, "    ");
+    }
     write_type(h, arg->type, arg, arg->tname);
+    if (method && use_icom && arg->array) fprintf(header, "*"); /* as write_icom_method_def */
     fprintf(h, " ");
-    write_name(h,arg);
+    write_name(h, arg);
+    if (!(method && use_icom)) write_array(header, arg->array, 0);
     arg = PREV_LINK(arg);
     count++;
   }
+  if (h == header) indentation--;
+}
+
+static void write_cpp_method_def(type_t *iface)
+{
+  func_t *cur = iface->funcs;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_callas(def->attrs)) {
+      indent(0);
+      fprintf(header, "virtual ");
+      write_type(header, def->type, def, def->tname);
+      fprintf(header, " CALLBACK ");
+      write_name(header, def);
+      fprintf(header, "(\n");
+      write_args(header, cur->args, iface->name, 2);
+      fprintf(header, ") = 0;\n");
+      fprintf(header, "\n");
+    }
+    cur = PREV_LINK(cur);
+  }
+}
+
+static void write_c_method_def(type_t *iface)
+{
+  func_t *cur = iface->funcs;
+  while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
+
+  if (iface->ref) write_c_method_def(iface->ref);
+  indent(0);
+  fprintf(header, "/*** %s methods ***/\n", iface->name);
+  while (cur) {
+    var_t *def = cur->def;
+    if (!is_callas(def->attrs)) {
+      indent(0);
+      write_type(header, def->type, def, def->tname);
+      fprintf(header, " (CALLBACK *");
+      write_name(header, def);
+      fprintf(header, ")(\n");
+      write_args(header, cur->args, iface->name, 1);
+      fprintf(header, ");\n");
+      fprintf(header, "\n");
+    }
+    cur = PREV_LINK(cur);
+  }
 }
 
 static void write_method_proto(type_t *iface)
@@ -622,19 +686,59 @@
   fprintf(header, " */\n");
   write_guid(iface);
   write_forward(iface);
-  fprintf(header, "#define ICOM_INTERFACE %s\n", iface->name);
-  write_method_def(iface);
-  fprintf(header, "#define %s_IMETHODS \\\n", iface->name);
-  if (iface->ref)
-    fprintf(header, "    %s_IMETHODS \\\n", iface->ref->name);
-  fprintf(header, "    %s_METHODS\n", iface->name);
-  if (iface->ref)
-    fprintf(header, "ICOM_DEFINE(%s,%s)\n", iface->name, iface->ref->name);
-  else
-    fprintf(header, "ICOM_DEFINE1(%s)\n", iface->name);
-  fprintf(header, "#undef ICOM_INTERFACE\n");
-  fprintf(header, "\n");
-  write_method_macro(iface, iface->name);
+  if (use_icom) {
+    fprintf(header, "#define ICOM_INTERFACE %s\n", iface->name);
+    fprintf(header, "#define %s_METHODS", iface->name);
+    write_icom_method_def(iface);
+    fprintf(header, "#define %s_IMETHODS \\\n", iface->name);
+    if (iface->ref)
+      fprintf(header, "    %s_IMETHODS \\\n", iface->ref->name);
+    fprintf(header, "    %s_METHODS\n", iface->name);
+    if (iface->ref)
+      fprintf(header, "ICOM_DEFINE(%s,%s)\n", iface->name, iface->ref->name);
+    else
+      fprintf(header, "ICOM_DEFINE1(%s)\n", iface->name);
+    fprintf(header, "#undef ICOM_INTERFACE\n");
+    fprintf(header, "\n");
+    write_method_macro(iface, iface->name);
+  }
+  else {
+    /* C++ interface */
+    fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
+    fprintf(header, "struct %s", iface->name);
+    if (iface->ref)
+      fprintf(header, ": %s", iface->ref->name);
+    fprintf(header, " {\n");
+    indentation++;
+    fprintf(header, "\n");
+    write_cpp_method_def(iface);
+    indentation--;
+    fprintf(header, "} ICOM_COM_INTERFACE_ATTRIBUTE;\n");
+    fprintf(header, "#else\n");
+    /* C interface */
+    fprintf(header, "typedef struct %sVtbl %sVtbl;\n", iface->name, iface->name);
+    fprintf(header, "struct %s {\n", iface->name);
+    fprintf(header, "    const %sVtbl* lpVtbl;\n", iface->name);
+    fprintf(header, "};\n");
+    fprintf(header, "struct %sVtbl {\n", iface->name);
+    indentation++;
+    fprintf(header, "    ICOM_MSVTABLE_COMPAT_FIELDS\n");
+    fprintf(header, "\n");
+    write_c_method_def(iface);
+    indentation--;
+    fprintf(header, "};\n");
+    fprintf(header, "\n");
+    if (compat_icom) {
+      fprintf(header, "#define %s_IMETHODS", iface->name);
+      if (iface->ref)
+	fprintf(header, " \\\n    %s_IMETHODS", iface->ref->name);
+      write_icom_method_def(iface);
+      fprintf(header, "\n");
+    }
+    write_method_macro(iface, iface->name);
+    fprintf(header, "\n");
+    fprintf(header, "#endif\n");
+  }
   fprintf(header, "\n");
   write_method_proto(iface);
   fprintf(header, "\n");
Index: tools/widl/widl.c
===================================================================
RCS file: /home/wine/wine/tools/widl/widl.c,v
retrieving revision 1.8
diff -u -r1.8 widl.c
--- tools/widl/widl.c	3 Dec 2002 19:12:07 -0000	1.8
+++ tools/widl/widl.c	14 Dec 2002 14:19:45 -0000
@@ -39,8 +39,27 @@
 #include "proxy.h"
 #include "../wpp/wpp.h"
 
+/* future options to reserve characters for: */
+/* a = alignment of structures */
+/* A = ACF input filename */
+/* c = client stub only? */
+/* C = client stub filename */
+/* J = do not search standard include path */
+/* O = generate interpreted stubs */
+/* p = proxy only? */
+/* P = proxy filename */
+/* s = server stub only? */
+/* S = server stub filename */
+/* t = typelib only? */
+/* T = typelib filename */
+/* u = UUID file only? */
+/* U = UUID filename */
+/* w = select win16/win32 output (?) */
+
 static char usage[] =
 "Usage: widl [options...] infile.idl\n"
+"   -b          Make headers compatible with ICOM macros\n"
+"   -B          Make headers use ICOM macros\n"
 "   -d n        Set debug level to 'n'\n"
 "   -D id[=val] Define preprocessor identifier id=val\n"
 "   -E          Preprocess only\n"
@@ -69,6 +88,8 @@
 int preprocess_only = 0;
 int header_only = 0;
 int no_preprocess = 0;
+int compat_icom = 0;
+int use_icom = 0;
 
 char *input_name;
 char *header_name;
@@ -117,8 +138,14 @@
 
   now = time(NULL);
 
-  while((optc = getopt(argc, argv, "d:D:EhH:I:NVW")) != EOF) {
+  while((optc = getopt(argc, argv, "bBd:D:EhH:I:NVW")) != EOF) {
     switch(optc) {
+    case 'b':
+      compat_icom = 1;
+      break;
+    case 'B':
+      use_icom = 1;
+      break;
     case 'd':
       debuglevel = strtol(optarg, NULL, 0);
       break;
Index: tools/widl/widl.h
===================================================================
RCS file: /home/wine/wine/tools/widl/widl.h,v
retrieving revision 1.3
diff -u -r1.3 widl.h
--- tools/widl/widl.h	3 Dec 2002 19:12:07 -0000	1.3
+++ tools/widl/widl.h	14 Dec 2002 14:19:45 -0000
@@ -39,6 +39,8 @@
 extern int win32;
 extern int pedantic;
 extern int header_only;
+extern int compat_icom;
+extern int use_icom;
 
 extern char *input_name;
 extern char *header_name;




More information about the wine-patches mailing list