widl patch

Ove Kaaven ovek at arcticnet.no
Mon Jan 5 21:03:43 CST 2004


With this patch, widl can be made to parse a suitably adapted version of
the stdole2.odl file previously sent to wine-patches (but it can't yet
generate anything useful from it). Not unchanged, though, as widl is
supposed to be more of a MIDL than a mktyplib (even though I can't seem
to convince MIDL to generate stdole32.tlb). And there's a new typelib.c
file to eventually fill in...

Log:
Added rules to parse library, coclass, dispinterface, and module
definitions, and a number of attributes, and cleaned up a few things.
Started on a typelib generation framework.

? typelib.c
? typelib.h
Index: Makefile.in
===================================================================
RCS file: /home/wine/wine/tools/widl/Makefile.in,v
retrieving revision 1.8
diff -u -r1.8 Makefile.in
--- Makefile.in	1 May 2003 03:16:21 -0000	1.8
+++ Makefile.in	6 Jan 2004 02:11:36 -0000
@@ -12,6 +12,7 @@
 C_SRCS = \
 	header.c \
 	proxy.c \
+	typelib.c \
 	utils.c \
 	widl.c
 
Index: header.c
===================================================================
RCS file: /home/wine/wine/tools/widl/header.c,v
retrieving revision 1.19
diff -u -r1.19 header.c
--- header.c	3 Sep 2003 20:16:24 -0000	1.19
+++ header.c	6 Jan 2004 02:11:38 -0000
@@ -34,7 +34,6 @@
 #include "utils.h"
 #include "parser.h"
 #include "header.h"
-#include "proxy.h"
 
 static int indentation = 0;
 
@@ -409,7 +408,11 @@
 
 int is_object(attr_t *a)
 {
-  return is_attr(a, ATTR_OBJECT);
+  while (a) {
+    if (a->type == ATTR_OBJECT || a->type == ATTR_ODL) return 1;
+    a = NEXT_LINK(a);
+  }
+  return 0;
 }
 
 int is_local(attr_t *a)
@@ -773,10 +776,6 @@
   }
   write_method_proto(iface);
   fprintf(header, "\n");
-
-  if (!is_local(iface->attrs))
-    write_proxy(iface);
-  fprintf(header,"#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
 }
 
 void write_rpc_interface(type_t *iface)
Index: header.h
===================================================================
RCS file: /home/wine/wine/tools/widl/header.h,v
retrieving revision 1.4
diff -u -r1.4 header.h
--- header.h	3 Sep 2003 20:16:24 -0000	1.4
+++ header.h	6 Jan 2004 02:11:38 -0000
@@ -21,6 +21,9 @@
 #ifndef __WIDL_HEADER_H
 #define __WIDL_HEADER_H
 
+extern int is_attr(attr_t *a, enum attr_type t);
+extern void *get_attrp(attr_t *a, enum attr_type t);
+extern DWORD get_attrv(attr_t *a, enum attr_type t);
 extern int is_void(type_t *t, var_t *v);
 extern void write_name(FILE *h, var_t *v);
 extern char* get_name(var_t *v);
Index: parser.l
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.l,v
retrieving revision 1.14
diff -u -r1.14 parser.l
--- parser.l	3 Sep 2003 19:31:14 -0000	1.14
+++ parser.l	6 Jan 2004 02:11:39 -0000
@@ -207,8 +207,13 @@
 /* ... */
 	{"default",			tDEFAULT},
 /* ... */
+	{"dispinterface",		tDISPINTERFACE},
+/* ... */
+	{"dllname",			tDLLNAME},
 	{"double",			tDOUBLE},
+	{"dual",			tDUAL},
 /* ... */
+	{"entry",			tENTRY},
 	{"enum",			tENUM},
 	{"error_status_t",		tERRORSTATUST},
 /* ... */
@@ -218,8 +223,10 @@
 /* ... */
 	{"handle_t",			tHANDLET},
 /* ... */
-	{"hyper",			tHYPER},
+	{"helpstring",			tHELPSTRING},
 /* ... */
+	{"hyper",			tHYPER},
+	{"id",				tID},
 	{"idempotent",			tIDEMPOTENT},
 /* ... */
 	{"iid_is",			tIIDIS},
@@ -234,10 +241,15 @@
 	{"interface",			tINTERFACE},
 /* ... */
 	{"length_is",			tLENGTHIS},
+	{"library",			tLIBRARY},
 /* ... */
 	{"local",			tLOCAL},
 	{"long",			tLONG},
 /* ... */
+	{"methods",			tMETHODS},
+/* ... */
+	{"module",			tMODULE},
+/* ... */
 	{"object",			tOBJECT},
 	{"odl",				tODL},
 	{"oleautomation",		tOLEAUTOMATION},
@@ -246,13 +258,22 @@
 /* ... */
 	{"pointer_default",		tPOINTERDEFAULT},
 /* ... */
+	{"properties",			tPROPERTIES},
+/* ... */
+	{"public",			tPUBLIC},
+/* ... */
+	{"readonly",			tREADONLY},
 	{"ref",				tREF},
 /* ... */
+	{"retval",			tRETVAL},
+/* ... */
 	{"short",			tSHORT},
 	{"signed",			tSIGNED},
 	{"size_is",			tSIZEIS},
 	{"sizeof",			tSIZEOF},
 /* ... */
+	{"source",			tSOURCE},
+/* ... */	
 	{"string",			tSTRING},
 	{"struct",			tSTRUCT},
 	{"switch",			tSWITCH},
Index: parser.y
===================================================================
RCS file: /home/wine/wine/tools/widl/parser.y,v
retrieving revision 1.11
diff -u -r1.11 parser.y
--- parser.y	3 Sep 2003 20:16:24 -0000	1.11
+++ parser.y	6 Jan 2004 02:11:40 -0000
@@ -35,6 +35,8 @@
 #include "utils.h"
 #include "parser.h"
 #include "header.h"
+#include "proxy.h"
+#include "typelib.h"
 
 #if defined(YYBYACC)
 	/* Berkeley yacc (byacc) doesn't seem to know about these */
@@ -75,8 +77,10 @@
 static typeref_t *uniq_tref(typeref_t *ref);
 static type_t *type_ref(typeref_t *ref);
 static void set_type(var_t *v, typeref_t *ref, expr_t *arr);
+static ifref_t *make_ifref(type_t *iface);
 static var_t *make_var(char *name);
 static func_t *make_func(var_t *def, var_t *args);
+static class_t *make_class(char *name);
 
 static type_t *reg_type(type_t *type, char *name, int t);
 static type_t *reg_types(type_t *type, var_t *names, int t);
@@ -105,6 +109,8 @@
 	typeref_t *tref;
 	var_t *var;
 	func_t *func;
+	ifref_t *ifref;
+	class_t *clas;
 	char *str;
 	UUID *uuid;
 	unsigned int num;
@@ -123,28 +129,35 @@
 %token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE
 %token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE
 %token tDEFAULT
-%token tDOUBLE
-%token tENUM tERRORSTATUST
+%token tDISPINTERFACE
+%token tDLLNAME tDOUBLE tDUAL
+%token tENTRY tENUM tERRORSTATUST
 %token tEXTERN
 %token tFLOAT
 %token tHANDLET
-%token tHYPER
-%token tIDEMPOTENT
+%token tHELPSTRING
+%token tHYPER tID tIDEMPOTENT
 %token tIIDIS
 %token tIMPORT tIMPORTLIB
 %token tIN tINCLUDE tINLINE
 %token tINT tINT64
 %token tINTERFACE
-%token tLENGTHIS
+%token tLENGTHIS tLIBRARY
 %token tLOCAL
 %token tLONG
+%token tMETHODS
+%token tMODULE
 %token tOBJECT tODL tOLEAUTOMATION
 %token tOUT
 %token tPOINTERDEFAULT
-%token tREF
+%token tPROPERTIES
+%token tPUBLIC
+%token tREADONLY tREF
+%token tRETVAL
 %token tSHORT
 %token tSIGNED
 %token tSIZEIS tSIZEOF
+%token tSOURCE
 %token tSTDCALL
 %token tSTRING tSTRUCT
 %token tSWITCH tSWITCHIS tSWITCHTYPE
@@ -164,15 +177,22 @@
 %type <attr> m_attributes attributes attrib_list attribute
 %type <expr> m_exprs /* exprs expr_list */ m_expr expr expr_list_const expr_const
 %type <expr> array array_list
-%type <type> inherit interface interfacehdr interfacedef lib_statements
+%type <type> inherit interface interfacehdr interfacedef interfacedec
+%type <type> dispinterface dispinterfacehdr dispinterfacedef
+%type <type> module modulehdr moduledef
 %type <type> base_type int_std
 %type <type> enumdef structdef typedef uniondef
+%type <ifref> gbl_statements coclass_ints coclass_int
 %type <tref> type
 %type <var> m_args no_args args arg
 %type <var> fields field s_field cases case enums enum_list enum constdef externdef
 %type <var> m_ident t_ident ident p_ident pident pident_list
+%type <var> dispint_props
 %type <func> funcdef int_statements
+%type <func> dispint_meths
+%type <clas> coclass coclasshdr coclassdef
 %type <num> pointer_type version
+%type <str> libraryhdr
 
 %left ','
 %left '|'
@@ -187,19 +207,29 @@
 
 %%
 
-input:	  lib_statements			{ /* FIXME */ }
+input:	  gbl_statements			{ write_proxies($1); }
 	;
 
-lib_statements:					{ $$ = NULL; }
-	| lib_statements interface ';'		{ if (!parse_only) write_forward($2); }
-	| lib_statements interfacedef		{ LINK($2, $1); $$ = $2; }
-/*	| lib_statements librarydef (when implemented) */
-	| lib_statements statement
+gbl_statements:					{ $$ = NULL; }
+	| gbl_statements interfacedec		{ $$ = $1; }
+	| gbl_statements interfacedef		{ $$ = make_ifref($2); LINK($$, $1); }
+	| gbl_statements coclassdef		{ $$ = $1; add_coclass($2); }
+	| gbl_statements moduledef		{ $$ = $1; add_module($2); }
+	| gbl_statements librarydef		{ $$ = $1; }
+	| gbl_statements statement		{ $$ = $1; }
+	;
+
+imp_statements:					{}
+	| imp_statements interfacedec		{ add_interface($2); }
+	| imp_statements interfacedef		{ add_interface($2); }
+	| imp_statements coclassdef		{ add_coclass($2); }
+	| imp_statements moduledef		{ add_module($2); }
+	| imp_statements statement		{}
 	;
 
 int_statements:					{ $$ = NULL; }
-	| int_statements funcdef ';'		{ LINK($2, $1); $$ = $2; }
-	| int_statements statement
+	| int_statements funcdef ';'		{ $$ = $2; LINK($$, $1); }
+	| int_statements statement		{ $$ = $1; }
 	;
 
 statement: ';'					{}
@@ -208,19 +238,24 @@
 	| enumdef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
 	| externdef ';'				{ if (!parse_only) { write_externdef($1); } }
 	| import				{}
-/*	| interface ';'				{} */
-/*	| interfacedef				{} */
 	| structdef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
 	| typedef ';'				{}
 	| uniondef ';'				{ if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n\n"); } }
 	;
 
-cppquote:	tCPPQUOTE '(' aSTRING ')'	{ if (!parse_only) fprintf(header, "%s\n", $3); }
+cppquote: tCPPQUOTE '(' aSTRING ')'		{ if (!parse_only) fprintf(header, "%s\n", $3); }
 	;
-import_start:	tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
+import_start: tIMPORT aSTRING ';'		{ assert(yychar == YYEMPTY);
 						  if (!do_import($2)) yychar = aEOF; }
 	;
-import:		import_start input aEOF		{}
+import:   import_start imp_statements aEOF	{}
+	;
+
+libraryhdr: tLIBRARY aIDENTIFIER		{ $$ = $2; }
+	;
+library_start: attributes libraryhdr '{'	{ start_typelib($2, $1); }
+	;
+librarydef: library_start imp_statements '}'	{ end_typelib(); }
 	;
 
 m_args:						{ $$ = NULL; }
@@ -287,16 +322,27 @@
 	| tCONTEXTHANDLENOSERIALIZE		{ $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ }
 	| tCONTEXTHANDLESERIALIZE		{ $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ }
 	| tDEFAULT				{ $$ = make_attr(ATTR_DEFAULT); }
+	| tDLLNAME '(' aSTRING ')'		{ $$ = make_attrp(ATTR_DLLNAME, $3); }
+	| tDUAL					{ $$ = make_attr(ATTR_DUAL); }
+	| tENTRY '(' aSTRING ')'		{ $$ = make_attrp(ATTR_ENTRY_STRING, $3); }
+	| tENTRY '(' expr_const ')'		{ $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); }
+	| tHELPSTRING '(' aSTRING ')'		{ $$ = make_attrp(ATTR_HELPSTRING, $3); }
+	| tID '(' expr_const ')'		{ $$ = make_attrp(ATTR_ID, $3); }
 	| tIDEMPOTENT				{ $$ = make_attr(ATTR_IDEMPOTENT); }
 	| tIIDIS '(' ident ')'			{ $$ = make_attrp(ATTR_IIDIS, $3); }
 	| tIN					{ $$ = make_attr(ATTR_IN); }
 	| tLENGTHIS '(' m_exprs ')'		{ $$ = make_attrp(ATTR_LENGTHIS, $3); }
 	| tLOCAL				{ $$ = make_attr(ATTR_LOCAL); }
 	| tOBJECT				{ $$ = make_attr(ATTR_OBJECT); }
+	| tODL					{ $$ = make_attr(ATTR_ODL); }
 	| tOLEAUTOMATION			{ $$ = make_attr(ATTR_OLEAUTOMATION); }
 	| tOUT					{ $$ = make_attr(ATTR_OUT); }
 	| tPOINTERDEFAULT '(' pointer_type ')'	{ $$ = make_attrv(ATTR_POINTERDEFAULT, $3); }
+	| tPUBLIC				{ $$ = make_attr(ATTR_PUBLIC); }
+	| tREADONLY				{ $$ = make_attr(ATTR_READONLY); }
+	| tRETVAL				{ $$ = make_attr(ATTR_RETVAL); }
 	| tSIZEIS '(' m_exprs ')'		{ $$ = make_attrp(ATTR_SIZEIS, $3); }
+	| tSOURCE				{ $$ = make_attr(ATTR_SOURCE); }
 	| tSTRING				{ $$ = make_attr(ATTR_STRING); }
 	| tSWITCHIS '(' expr ')'		{ $$ = make_attrp(ATTR_SWITCHIS, $3); }
 	| tSWITCHTYPE '(' type ')'		{ $$ = make_attrp(ATTR_SWITCHTYPE, type_ref($3)); }
@@ -446,6 +492,7 @@
 
 ident:	  aIDENTIFIER				{ $$ = make_var($1); }
 /* some "reserved words" used in attributes are also used as field names in some MS IDL files */
+	| tRETVAL				{ $$ = make_var($<str>1); }
 	| tVERSION				{ $$ = make_var($<str>1); }
 	;
 
@@ -483,6 +530,67 @@
 	| tCHAR					{ $$ = make_type(RPC_FC_CHAR, NULL); }
 	;
 
+coclass:  tCOCLASS aIDENTIFIER			{ $$ = make_class($2); }
+	| tCOCLASS aKNOWNTYPE			{ $$ = make_class($2); }
+	;
+
+coclasshdr: attributes coclass			{ $$ = $2;
+						  $$->attrs = $1;
+						}
+	;
+
+coclassdef: coclasshdr '{' coclass_ints '}'	{ $$ = $1;
+						  $$->ifaces = $3;
+						}
+	;
+
+coclass_ints:					{ $$ = NULL; }
+	| coclass_ints coclass_int		{ LINK($2, $1); $$ = $2; }
+	;
+
+coclass_int:
+	  m_attributes interfacedec		{ $$ = make_ifref($2); $$->attrs = $1; }
+	;
+
+dispinterface: tDISPINTERFACE aIDENTIFIER	{ $$ = get_type(0, $2, 0); }
+	|      tDISPINTERFACE aKNOWNTYPE	{ $$ = get_type(0, $2, 0); }
+	;
+
+dispinterfacehdr: attributes dispinterface	{ $$ = $2;
+						  if ($$->defined) yyerror("multiple definition error\n");
+						  $$->attrs = $1;
+						/*  $$->attrs = make_attr(ATTR_DISPINTERFACE); */
+						/*  LINK($$->attrs, $1); */
+						  $$->ref = find_type("IDispatch", 0);
+						  if (!$$->ref) yyerror("IDispatch is undefined\n");
+						  $$->defined = TRUE;
+						  if (!parse_only) write_forward($$);
+						}
+	;
+
+dispint_props: tPROPERTIES ':'			{ $$ = NULL; }
+	| dispint_props s_field ';'		{ LINK($2, $1); $$ = $2; }
+	;
+
+dispint_meths: tMETHODS ':'			{ $$ = NULL; }
+	| dispint_meths funcdef ';'		{ LINK($2, $1); $$ = $2; }
+	;
+
+dispinterfacedef: dispinterfacehdr '{'
+	  dispint_props
+	  dispint_meths
+	  '}'					{ $$ = $1;
+						  $$->fields = $3;
+						  $$->funcs = $4;
+						  if (!parse_only) write_interface($$);
+						}
+/* FIXME: not sure how to handle this yet
+	| dispinterfacehdr '{' interface '}'	{ $$ = $1;
+						  if (!parse_only) write_interface($$);
+						}
+*/
+	;
+
 inherit:					{ $$ = NULL; }
 	| ':' aKNOWNTYPE			{ $$ = find_type2($2, 0); }
 	;
@@ -514,6 +622,27 @@
 						  $$->funcs = $6;
 						  if (!parse_only) write_interface($$);
 						}
+	| dispinterfacedef			{ $$ = $1; }
+	;
+
+interfacedec:
+	  interface ';'				{ $$ = $1; if (!parse_only) write_forward($$); }
+	| dispinterface ';'			{ $$ = $1; if (!parse_only) write_forward($$); }
+	;
+
+module:   tMODULE aIDENTIFIER			{ $$ = make_type(0, NULL); $$->name = $2; }
+	| tMODULE aKNOWNTYPE			{ $$ = make_type(0, NULL); $$->name = $2; }
+	;
+
+modulehdr: attributes module			{ $$ = $2;
+						  $$->attrs = $1;
+						}
+	;
+
+moduledef: modulehdr '{' int_statements '}'	{ $$ = $1;
+						  $$->funcs = $3;
+						  /* FIXME: if (!parse_only) write_module($$); */
+						}
 	;
 
 p_ident:  '*' pident %prec PPTR			{ $$ = $2; $$->ptr_level++; }
@@ -810,6 +939,15 @@
   v->array = arr;
 }
 
+static ifref_t *make_ifref(type_t *iface)
+{
+  ifref_t *l = xmalloc(sizeof(ifref_t));
+  l->iface = iface;
+  l->attrs = NULL;
+  INIT_LINK(l);
+  return l;
+}
+
 static var_t *make_var(char *name)
 {
   var_t *v = xmalloc(sizeof(var_t));
@@ -834,6 +972,16 @@
   f->idx = -1;
   INIT_LINK(f);
   return f;
+}
+
+static class_t *make_class(char *name)
+{
+  class_t *c = xmalloc(sizeof(class_t));
+  c->name = name;
+  c->attrs = NULL;
+  c->ifaces = NULL;
+  INIT_LINK(c);
+  return c;
 }
 
 #define HASHMAX 64
Index: proxy.c
===================================================================
RCS file: /home/wine/wine/tools/widl/proxy.c,v
retrieving revision 1.8
diff -u -r1.8 proxy.c
--- proxy.c	3 Sep 2003 20:16:24 -0000	1.8
+++ proxy.c	6 Jan 2004 02:11:40 -0000
@@ -35,6 +35,8 @@
 #include "parser.h"
 #include "header.h"
 
+static FILE* proxy;
+
 /* FIXME: support generation of stubless proxies */
 
 static void write_stubdesc(void)
@@ -218,22 +220,13 @@
   return i;
 }
 
-typedef struct _if_list if_list;
-struct _if_list {
-  type_t *iface;
-  DECL_LINK(if_list)
-};
-
-if_list *if_first;
-
-void write_proxy(type_t *iface)
+static void write_proxy(type_t *iface)
 {
   int midx = -1, stubs;
   func_t *cur = iface->funcs;
-  if_list *if_cur;
 
   if (!cur) return;
-  if (header_only) return;
+  if (!do_everything) return;
 
   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
 
@@ -241,12 +234,6 @@
 
   init_proxy();
 
-  if_cur = xmalloc(sizeof(if_list));
-  if_cur->iface = iface;
-  INIT_LINK(if_cur);
-  LINK(if_cur, if_first);
-  if_first = if_cur;
-
   fprintf(proxy, "/*****************************************************************************\n");
   fprintf(proxy, " * %s interface\n", iface->name);
   fprintf(proxy, " */\n");
@@ -296,15 +283,24 @@
   fprintf(proxy, "\n");
 }
 
-void finish_proxy(void)
+void write_proxies(ifref_t *ifaces)
 {
-  if_list *lcur = if_first;
-  if_list *cur;
+  ifref_t *lcur = ifaces;
+  ifref_t *cur;
   char *file_id = proxy_token;
   int c;
 
   if (!lcur) return;
   while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
+
+  cur = lcur;
+  while (cur) {
+    if (is_object(cur->iface->attrs) && !is_local(cur->iface->attrs))
+      write_proxy(cur->iface);
+    cur = PREV_LINK(cur);
+  }
+
+  if (!proxy) return;
 
   fprintf(proxy, "const CInterfaceProxyVtbl* _%s_ProxyVtblList[] = {\n", file_id);
   cur = lcur;
Index: proxy.h
===================================================================
RCS file: /home/wine/wine/tools/widl/proxy.h,v
retrieving revision 1.1
diff -u -r1.1 proxy.h
--- proxy.h	16 Jul 2002 03:20:46 -0000	1.1
+++ proxy.h	6 Jan 2004 02:11:40 -0000
@@ -21,7 +21,6 @@
 #ifndef __WIDL_PROXY_H
 #define __WIDL_PROXY_H
 
-extern void write_proxy(type_t *iface);
-extern void finish_proxy(void);
+extern void write_proxies(ifref_t *ifaces);
 
 #endif
Index: widl.c
===================================================================
RCS file: /home/wine/wine/tools/widl/widl.c,v
retrieving revision 1.14
diff -u -r1.14 widl.c
--- widl.c	3 Sep 2003 19:31:14 -0000	1.14
+++ widl.c	6 Jan 2004 02:11:41 -0000
@@ -50,8 +50,6 @@
 /* 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 (?) */
@@ -66,6 +64,8 @@
 "   -H file     Name of header file (default is infile.h)\n"
 "   -I path     Set include search dir to path (multiple -I allowed)\n"
 "   -N          Do not preprocess input\n"
+"   -t          Generate typelib only\n"
+"   -T file     Name of typelib file (default is infile.tlb)\n"
 "   -V          Print version and exit\n"
 "   -W          Enable pedantic warnings\n"
 "Debug level 'n' is a bitmask with following meaning:\n"
@@ -84,14 +84,17 @@
 int debuglevel = DEBUGLEVEL_NONE;
 
 int pedantic = 0;
+int do_everything = 1;
 int preprocess_only = 0;
 int header_only = 0;
+int typelib_only = 0;
 int no_preprocess = 0;
 int compat_icom = 0;
 
 char *input_name;
 char *header_name;
 char *header_token;
+char *typelib_name;
 char *proxy_name;
 char *proxy_token;
 char *temp_name;
@@ -135,7 +138,7 @@
 
   now = time(NULL);
 
-  while((optc = getopt(argc, argv, "bd:D:EhH:I:NVW")) != EOF) {
+  while((optc = getopt(argc, argv, "bd:D:EhH:I:NtT:VW")) != EOF) {
     switch(optc) {
     case 'b':
       compat_icom = 1;
@@ -147,9 +150,11 @@
       wpp_add_cmdline_define(optarg);
       break;
     case 'E':
+      do_everything = 0;
       preprocess_only = 1;
       break;
     case 'h':
+      do_everything = 0;
       header_only = 1;
       break;
     case 'H':
@@ -161,6 +166,13 @@
     case 'N':
       no_preprocess = 1;
       break;
+    case 't':
+      do_everything = 0;
+      typelib_only = 1;
+      break;
+    case 'T':
+      typelib_name = strdup(optarg);
+      break;
     case 'V':
       printf(version_string);
       return 0;
@@ -199,6 +211,11 @@
     strcat(header_name, ".h");
   }
 
+  if (!typelib_name) {
+    typelib_name = dup_basename(input_name, ".idl");
+    strcat(typelib_name, ".tlb");
+  }
+
   if (!proxy_name) {
     proxy_name = dup_basename(input_name, ".idl");
     proxy_token = xstrdup(proxy_name);
@@ -249,7 +266,6 @@
 
   ret = yyparse();
 
-  finish_proxy();
   fprintf(header, "#ifdef __cplusplus\n");
   fprintf(header, "}\n");
   fprintf(header, "#endif\n");
Index: widl.h
===================================================================
RCS file: /home/wine/wine/tools/widl/widl.h,v
retrieving revision 1.5
diff -u -r1.5 widl.h
--- widl.h	10 Apr 2003 21:13:58 -0000	1.5
+++ widl.h	6 Jan 2004 02:11:41 -0000
@@ -38,11 +38,14 @@
 
 extern int win32;
 extern int pedantic;
+extern int do_everything;
 extern int header_only;
+extern int typelib_only;
 extern int compat_icom;
 
 extern char *input_name;
 extern char *header_name;
+extern char *typelib_name;
 extern char *proxy_name;
 extern char *proxy_token;
 extern time_t now;
@@ -51,6 +54,5 @@
 extern int char_number;
 
 extern FILE* header;
-extern FILE* proxy;
 
 #endif
Index: widltypes.h
===================================================================
RCS file: /home/wine/wine/tools/widl/widltypes.h,v
retrieving revision 1.10
diff -u -r1.10 widltypes.h
--- widltypes.h	5 Sep 2003 23:15:40 -0000	1.10
+++ widltypes.h	6 Jan 2004 02:11:41 -0000
@@ -38,6 +38,8 @@
 typedef struct _typeref_t typeref_t;
 typedef struct _var_t var_t;
 typedef struct _func_t func_t;
+typedef struct _ifref_t ifref_t;
+typedef struct _class_t class_t;
 
 #define DECL_LINK(type) \
   type *l_next; \
@@ -56,17 +58,28 @@
     ATTR_CASE,
     ATTR_CONTEXTHANDLE,
     ATTR_DEFAULT,
+    ATTR_DLLNAME,
+    ATTR_DUAL,
+    ATTR_ENTRY_STRING,
+    ATTR_ENTRY_ORDINAL,
+    ATTR_HELPSTRING,
+    ATTR_ID,
     ATTR_IDEMPOTENT,
     ATTR_IIDIS,
     ATTR_IN,
     ATTR_LENGTHIS,
     ATTR_LOCAL,
     ATTR_OBJECT,
+    ATTR_ODL,
     ATTR_OLEAUTOMATION,
     ATTR_OUT,
     ATTR_POINTERDEFAULT,
     ATTR_POINTERTYPE,
+    ATTR_PUBLIC,
+    ATTR_READONLY,
+    ATTR_RETVAL,
     ATTR_SIZEIS,
+    ATTR_SOURCE,
     ATTR_STRING,
     ATTR_SWITCHIS,
     ATTR_SWITCHTYPE,
@@ -165,6 +178,23 @@
 
   /* parser-internal */
   DECL_LINK(func_t)
+};
+
+struct _ifref_t {
+  type_t *iface;
+  attr_t *attrs;
+
+  /* parser-internal */
+  DECL_LINK(ifref_t)
+};
+
+struct _class_t {
+  char *name;
+  attr_t *attrs;
+  ifref_t *ifaces;
+
+  /* parser-internal */
+  DECL_LINK(class_t)
 };
 
 #endif
--- /dev/null	2003-12-06 19:36:34.000000000 +0100
+++ typelib.h	2004-01-06 03:11:08.000000000 +0100
@@ -0,0 +1,17 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2004 Ove Kaaven
+ */
+
+#ifndef __WIDL_TYPELIB_H
+#define __WIDL_TYPELIB_H
+
+extern int in_typelib;
+extern void start_typelib(char *name, attr_t *attrs);
+extern void end_typelib(void);
+extern void add_interface(type_t *iface);
+extern void add_coclass(class_t *cls);
+extern void add_module(type_t *module);
+
+#endif
--- /dev/null	2003-12-06 19:36:34.000000000 +0100
+++ typelib.c	2004-01-06 03:26:34.000000000 +0100
@@ -0,0 +1,253 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2004 Ove Kaaven
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <signal.h>
+
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "header.h"
+#include "typelib.h"
+
+int in_typelib = 0;
+static FILE* typelib;
+
+/* Copied from wtypes.h. Not included directly because that would create a
+ * circular dependency (after all, wtypes.h is generated by widl...) */
+
+enum VARENUM {
+    VT_EMPTY = 0,
+    VT_NULL = 1,
+    VT_I2 = 2,
+    VT_I4 = 3,
+    VT_R4 = 4,
+    VT_R8 = 5,
+    VT_CY = 6,
+    VT_DATE = 7,
+    VT_BSTR = 8,
+    VT_DISPATCH = 9,
+    VT_ERROR = 10,
+    VT_BOOL = 11,
+    VT_VARIANT = 12,
+    VT_UNKNOWN = 13,
+    VT_DECIMAL = 14,
+    VT_I1 = 16,
+    VT_UI1 = 17,
+    VT_UI2 = 18,
+    VT_UI4 = 19,
+    VT_I8 = 20,
+    VT_UI8 = 21,
+    VT_INT = 22,
+    VT_UINT = 23,
+    VT_VOID = 24,
+    VT_HRESULT = 25,
+    VT_PTR = 26,
+    VT_SAFEARRAY = 27,
+    VT_CARRAY = 28,
+    VT_USERDEFINED = 29,
+    VT_LPSTR = 30,
+    VT_LPWSTR = 31,
+    VT_RECORD = 36,
+    VT_FILETIME = 64,
+    VT_BLOB = 65,
+    VT_STREAM = 66,
+    VT_STORAGE = 67,
+    VT_STREAMED_OBJECT = 68,
+    VT_STORED_OBJECT = 69,
+    VT_BLOB_OBJECT = 70,
+    VT_CF = 71,
+    VT_CLSID = 72,
+    VT_BSTR_BLOB = 0xfff,
+    VT_VECTOR = 0x1000,
+    VT_ARRAY = 0x2000,
+    VT_BYREF = 0x4000,
+    VT_RESERVED = 0x8000,
+    VT_ILLEGAL = 0xffff,
+    VT_ILLEGALMASKED = 0xfff,
+    VT_TYPEMASK = 0xfff
+};
+
+/* List of oleauto types that should be recognized by name.
+ * (most of) these seem to be intrinsic types in mktyplib. */
+
+static struct oatype {
+  const char *kw;
+  unsigned short vt;
+} oatypes[] = {
+  {"BSTR",      VT_BSTR},
+  {"CURRENCY",  VT_CY},
+  {"DATE",      VT_DATE},
+  {"DECIMAL",   VT_DECIMAL},
+  {"HRESULT",   VT_HRESULT},
+  {"LPSTR",     VT_LPSTR},
+  {"LPWSTR",    VT_LPWSTR},
+  {"SCODE",     VT_ERROR},
+  {"VARIANT",   VT_VARIANT}
+};
+#define NTYPES (sizeof(oatypes)/sizeof(oatypes[0]))
+#define KWP(p) ((struct oatype *)(p))
+
+static int kw_cmp_func(const void *s1, const void *s2)
+{
+        return strcmp(KWP(s1)->kw, KWP(s2)->kw);
+}
+
+static unsigned short builtin_vt(const char *kw)
+{
+  struct oatype key, *kwp;
+  key.kw = kw;
+#ifdef KW_BSEARCH
+  kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func);
+#else
+  {
+    int i;
+    for (kwp=NULL, i=0; i < NTYPES; i++)
+      if (!kw_cmp_func(&key, &oatypes[i])) {
+        kwp = &oatypes[i];
+        break;
+      }
+  }
+#endif
+  if (kwp) {
+    return kwp->vt;
+  }
+  return 0;
+}
+
+static int match(const char*n, const char*m)
+{
+  if (!n) return 0;
+  return !strcmp(n, m);
+}
+
+unsigned short get_type_vt(type_t *t)
+{
+  unsigned short vt;
+
+  if (t->name) {
+    vt = builtin_vt(t->name);
+    if (vt) return vt;
+  }
+
+  switch (t->type) {
+  case RPC_FC_BYTE:
+  case RPC_FC_USMALL:
+    return VT_UI1;
+  case RPC_FC_CHAR:
+  case RPC_FC_SMALL:
+    return VT_I1;
+  case RPC_FC_WCHAR:
+    return VT_I2; /* mktyplib seems to parse wchar_t as short */
+  case RPC_FC_SHORT:
+    return VT_I2;
+  case RPC_FC_USHORT:
+    return VT_UI2;
+  case RPC_FC_LONG:
+    if (t->ref && match(t->ref->name, "int")) return VT_INT;
+    return VT_I4;
+  case RPC_FC_ULONG:
+    if (t->ref && match(t->ref->name, "int")) return VT_UINT;
+    return VT_UI4;
+  case RPC_FC_HYPER:
+    if (t->sign < 0) return VT_UI8;
+    if (t->ref && match(t->ref->name, "MIDL_uhyper")) return VT_UI8;
+    return VT_I8;
+  case RPC_FC_FLOAT:
+    return VT_R4;
+  case RPC_FC_DOUBLE:
+    return VT_R8;
+  case RPC_FC_RP:
+  case RPC_FC_UP:
+  case RPC_FC_OP:
+  case RPC_FC_FP:
+    /* it's a pointer... */
+    if (t->ref && t->ref->type == RPC_FC_IP) {
+      /* it's to an interface, which one? */
+      if (match(t->ref->name, "IDispatch"))
+        return VT_DISPATCH;
+      if (match(t->ref->name, "IUnknown"))
+        return VT_UNKNOWN;
+    }
+    /* FIXME: should we recurse and add a VT_BYREF? */
+    /* Or just return VT_PTR? */
+    error("get_type_vt: unknown-deref-type: %d\n", t->ref->type);
+    break;
+  default:
+    error("get_type_vt: unknown-type: %d\n", t->type);
+  }
+  return 0;
+}
+
+unsigned short get_var_vt(var_t *v)
+{
+  unsigned short vt;
+
+  if (v->tname) {
+    vt = builtin_vt(v->tname);
+    if (vt) return vt;
+  }
+
+  return get_type_vt(v->type);
+}
+
+void start_typelib(char *name, attr_t *attrs)
+{
+  in_typelib++;
+  if (!do_everything && !typelib_only) return;
+  typelib = fopen(typelib_name, "wb");
+}
+
+void end_typelib(void)
+{
+  if (typelib) fclose(typelib);
+  in_typelib--;
+}
+
+void add_interface(type_t *iface)
+{
+  if (!typelib) return;
+
+  /* FIXME: add interface and dependent types to typelib */
+  printf("add interface: %s\n", iface->name);
+}
+
+void add_coclass(class_t *cls)
+{
+  ifref_t *lcur = cls->ifaces;
+  ifref_t *cur;
+
+  if (lcur) {
+    while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
+  }
+
+  if (!typelib) return;
+
+  /* install interfaces the coclass depends on */
+  cur = lcur;
+  while (cur) {
+    add_interface(cur->iface);
+    cur = PREV_LINK(cur);
+  }
+
+  /* FIXME: add coclass to typelib */
+  printf("add coclass: %s\n", cls->name);
+}
+
+void add_module(type_t *module)
+{
+  if (!typelib) return;
+
+  /* FIXME: add module to typelib */
+  printf("add module: %s\n", module->name);
+}





More information about the wine-patches mailing list