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); +}