diff --git a/configure b/configure index 58b1b152a8..40e925fb9b 100755 --- a/configure +++ b/configure @@ -13314,7 +13314,7 @@ MAKE_DLL_RULES=dlls/Makedll.rules MAKE_PROG_RULES=programs/Makeprog.rules -ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules programs/Makeprog.rules Makefile debugger/Makefile dlls/Makefile dlls/advapi32/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/d3d8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dsound/Makefile dlls/gdi/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt20/Makefile dlls/msvideo/Makefile dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/user/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winspool/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile library/Makefile miscemu/Makefile ole/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineconsole/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wpp/Makefile tools/wrc/Makefile tsx11/Makefile unicode/Makefile" +ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules programs/Makeprog.rules Makefile debugger/Makefile dlls/Makefile dlls/advapi32/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/d3d8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dsound/Makefile dlls/gdi/Makefile dlls/glu32/Makefile dlls/icmp/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/kernel/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt20/Makefile dlls/msvideo/Makefile dlls/netapi32/Makefile dlls/ntdll/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleaut32/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/user/Makefile dlls/version/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winspool/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile library/Makefile miscemu/Makefile ole/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/osversioncheck/Makefile programs/progman/Makefile programs/regapi/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/regtest/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineconsole/Makefile programs/winefile/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/wmc/Makefile tools/wpp/Makefile tools/wrc/Makefile tsx11/Makefile unicode/Makefile" cat >confcache <<\_ACEOF @@ -13921,6 +13921,7 @@ do "programs/winver/Makefile" ) CONFIG_FILES="$CONFIG_FILES programs/winver/Makefile" ;; "server/Makefile" ) CONFIG_FILES="$CONFIG_FILES server/Makefile" ;; "tools/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/Makefile" ;; + "tools/widl/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/widl/Makefile" ;; "tools/winapi/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/winapi/Makefile" ;; "tools/winebuild/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/winebuild/Makefile" ;; "tools/winedump/Makefile" ) CONFIG_FILES="$CONFIG_FILES tools/winedump/Makefile" ;; diff --git a/configure.ac b/configure.ac index 926e021df1..3726b1f5ee 100644 --- a/configure.ac +++ b/configure.ac @@ -1374,6 +1374,7 @@ programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile +tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile diff --git a/include/wine/rpcfc.h b/include/wine/rpcfc.h new file mode 100644 index 0000000000..075f2127b1 --- /dev/null +++ b/include/wine/rpcfc.h @@ -0,0 +1,109 @@ +/* + * RPC format chars, as found by studying MIDL output. + */ + +#ifndef __WINE_RPCFC_H +#define __WINE_RPCFC_H + +/* base types */ +#define RPC_FC_BYTE 0x01 +#define RPC_FC_CHAR 0x02 +#define RPC_FC_SMALL 0x03 +#define RPC_FC_USMALL 0x04 +#define RPC_FC_WCHAR 0x05 +#define RPC_FC_SHORT 0x06 +#define RPC_FC_USHORT 0x07 +#define RPC_FC_LONG 0x08 +#define RPC_FC_ULONG 0x09 +#define RPC_FC_FLOAT 0x0a +#define RPC_FC_HYPER 0x0b +#define RPC_FC_DOUBLE 0x0c + +#define RPC_FC_ENUM32 0x0e + +/* other stuff */ +#define RPC_FC_RP 0x11 /* ? */ +#define RPC_FC_UP 0x12 /* unique pointer */ +#define RPC_FC_OP 0x13 /* ? */ +#define RPC_FC_FP 0x14 /* full pointer */ +/* FC_RP/UP/OP/FP: flags, NdrFcShort(typeofs) */ + #define RPC_FC_P_ONSTACK 0x4 /* [alloced_on_stack] */ + #define RPC_FC_P_SIMPLEPOINTER 0x8 /* [simple_pointer] */ + /* flag 10 is not tagged */ + +#define RPC_FC_STRUCT 0x15 +/* FC_STRUCT: fieldcount-1, NdrFcShort(size), fields */ + +#define RPC_FC_PSTRUCT 0x16 +#define RPC_FC_CSTRUCT 0x17 + +#define RPC_FC_BOGUS_STRUCT 0x1a + +#define RPC_FC_CARRAY 0x1b /* conformant array? */ +#define RPC_FC_CVARRAY 0x1c /* conformant varying array? */ +#define RPC_FC_SMFARRAY 0x1d /* simple fixed array? */ +/* FC_SMFARRAY: fieldcount-1, NdrFcShort(count), type */ + +#define RPC_FC_BOGUS_ARRAY 0x21 + +#define RPC_FC_C_WSTRING 0x25 + +#define RPC_FC_ENCAPSULATED_UNION 0x2a +#define RPC_FC_NON_ENCAPSULATED_UNION 0x2b + +#define RPC_FC_IP 0x2f /* interface pointer */ + +#define RPC_FC_AUTO_HANDLE 0x33 +/* FC_AUTO_HANDLE: oldflags, NdrFcLong(?), NdrFcShort(vtbl_idx), NdrFcShort(stacksiz), + * NdrFcShort(?), NdrFcShort(?), oi2flags, parmcount + * parameters: NdrFcShort(flags), NdrFcShort(stackofs), NdrFcShort(typeofs)/basetype */ + /* oldflags: 6c = object + oi2 */ + #define RPC_FC_AH_OI2F_SRVMUSTSIZE 0x01 + #define RPC_FC_AH_OI2F_CLTMUSTSIZE 0x02 + #define RPC_FC_AH_OI2F_HASRETURN 0x04 + #define RPC_FC_AH_PF_IN 0x0008 + #define RPC_FC_AH_PF_OUT 0x0010 + #define RPC_FC_AH_PF_RETURN 0x0020 + #define RPC_FC_AH_PF_BASETYPE 0x0040 + #define RPC_FC_AH_PF_BYVAL 0x0080 + #define RPC_FC_AH_PF_SIMPLEREF 0x0100 + /* PF: 03 = mustsize + mustfree */ + /* 2000 = srv alloc size=8, 4000 = srv alloc size=16 */ + +#define RPC_FC_POINTER 0x36 + +#define RPC_FC_ALIGNM4 0x38 +#define RPC_FC_ALIGNM8 0x39 + +#define RPC_FC_STRUCTPAD2 0x3e + +#define RPC_FC_NO_REPEAT 0x46 + +#define RPC_FC_VARIABLE_REPEAT 0x48 +#define RPC_FC_FIXED_OFFSET 0x49 + +#define RPC_FC_PP 0x4b + +#define RPC_FC_EMBEDDED_COMPLEX 0x4c +/* FC_EMBEDDED_COMPLEX: fieldcount-1, NdrFcShort(typeofs) */ + +#define RPC_FC_IN_PARAM 0x4d +/* FC_IN_PARAM: stacksiz, NdrFcShort(typeofs) */ +#define RPC_FC_IN_PARAM_BASETYPE 0x4e +/* FC_IN_PARAM_BASETYPE: basetype */ +#define RPC_FC_OUT_PARAM 0x51 +/* FC_OUT_PARAM: stacksiz, NdrFcShort(typeofs) */ +#define RPC_FC_RETURN_PARAM_BASETYPE 0x53 +/* FC_RETURN_PARAM_BASETYPE: basetype */ + +#define RPC_FC_DEREFERENCE 0x54 + +#define RPC_FC_CONSTANT_IID 0x5a +/* FC_CONSTANT_IID: NdrFcLong(), NdrFcShort(), NdrFcShort(), 8x () */ + +#define RPC_FC_END 0x5b +#define RPC_FC_PAD 0x5c + +#define RPC_FC_USER_MARSHAL 0xb4 + +#endif /* __WINE_RPCFC_H */ diff --git a/tools/Makefile.in b/tools/Makefile.in index 7af39fd03e..e6d1cb4f42 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -10,6 +10,7 @@ MODULE = none C_SRCS = makedep.c fnt2bdf.c bin2res.c SUBDIRS = \ + widl \ winebuild \ winedump \ wmc \ @@ -28,7 +29,7 @@ all: $(PROGRAMS) $(SUBDIRS) @MAKE_RULES@ -wrc: wpp +widl wrc: wpp makedep: makedep.o $(CC) $(CFLAGS) -o makedep makedep.o diff --git a/tools/widl/.cvsignore b/tools/widl/.cvsignore new file mode 100644 index 0000000000..dceff69c4b --- /dev/null +++ b/tools/widl/.cvsignore @@ -0,0 +1,5 @@ +Makefile +lex.yy.c +widl +y.tab.c +y.tab.h diff --git a/tools/widl/Makefile.in b/tools/widl/Makefile.in new file mode 100644 index 0000000000..98b2c08369 --- /dev/null +++ b/tools/widl/Makefile.in @@ -0,0 +1,50 @@ +DEFS = -D__WINE__ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +LEXOPT = -Cf #-w -b +YACCOPT = #-v +EXEEXT = @EXEEXT@ +EXTRAINCL = -I$(TOPSRCDIR)/tools/wpp +EXTRALIBS = -L$(TOPOBJDIR)/tools/wpp -lwpp + +PROGRAMS = widl$(EXEEXT) +MODULE = none + +C_SRCS = \ + header.c \ + proxy.c \ + utils.c \ + widl.c + +EXTRA_SRCS = parser.y parser.l +EXTRA_OBJS = y.tab.o @LEX_OUTPUT_ROOT@.o + +all: $(PROGRAMS) + +@MAKE_RULES@ + +widl: $(OBJS) $(TOPOBJDIR)/tools/wpp/libwpp.a + $(CC) $(CFLAGS) -o widl $(OBJS) $(EXTRALIBS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) $(LDFLAGS) + +widl.exe: $(OBJS) $(TOPOBJDIR)/tools/wpp/libwpp.a + $(CC) $(CFLAGS) -o widl.exe $(OBJS) $(EXTRALIBS) $(LIBWINE) $(LIBUNICODE) $(LEXLIB) -liberty $(LDFLAGS) + +y.tab.c y.tab.h: parser.y + $(YACC) $(YACCOPT) -d -t $(SRCDIR)/parser.y + +@LEX_OUTPUT_ROOT@.c: parser.l + $(LEX) $(LEXOPT) -d -8 $(SRCDIR)/parser.l + +clean:: + $(RM) parser.output parser.tab.h lex.backup y.output + +install:: $(PROGRAMS) + $(MKINSTALLDIRS) $(bindir) + $(INSTALL_PROGRAM) widl$(EXEEXT) $(bindir)/widl$(EXEEXT) + +uninstall:: + $(RM) $(bindir)/widl$(EXEEXT) + +### Dependencies: diff --git a/tools/widl/header.c b/tools/widl/header.c new file mode 100644 index 0000000000..8f6bbc0d74 --- /dev/null +++ b/tools/widl/header.c @@ -0,0 +1,408 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "proxy.h" +#include "y.tab.h" + +static int indentation = 0; + +static void indent(int delta) +{ + int c; + if (delta < 0) indentation += delta; + for (c=0; c 0) indentation += delta; +} + +int is_void(type_t *t, var_t *v) +{ + if (v && v->ptr_level) return 0; + if (!t->type && !t->ref) return 1; + return 0; +} + +static void write_pident(var_t *v) +{ + int c; + for (c=0; cptr_level; c++) { + fprintf(header, "*"); + } + if (v->name) fprintf(header, "%s", v->name); +} + +void write_name(FILE *h, var_t *v) +{ + fprintf(h, "%s", v->name); +} + +char* get_name(var_t *v) +{ + return v->name; +} + +static void write_fields(FILE *h, var_t *v) +{ + if (!v) return; + while (NEXT_LINK(v)) v = NEXT_LINK(v); + while (v) { + if (v->type) { + indent(0); + write_type(h, v->type, NULL, v->tname); + if (get_name(v)) { + fprintf(header, " "); + write_pident(v); + } + fprintf(header, ";\n"); + } + v = PREV_LINK(v); + } +} + +void write_type(FILE *h, type_t *t, var_t *v, char *n) +{ + int c; + + if (n) fprintf(h, "%s", n); + else { + if (t->is_const) fprintf(h, "const "); + if (t->type) { + switch (t->type) { + case RPC_FC_BYTE: + fprintf(h, "byte"); + break; + case RPC_FC_CHAR: + fprintf(h, "char"); + break; + case RPC_FC_USHORT: + fprintf(h, "unsigned "); + case RPC_FC_SHORT: + if (t->ref) fprintf(h, t->ref->name); + fprintf(h, "short"); + break; + case RPC_FC_ULONG: + fprintf(h, "unsigned "); + case RPC_FC_LONG: + if (t->ref) fprintf(h, t->ref->name); + else fprintf(h, "long"); + break; + case RPC_FC_STRUCT: + if (t->defined && !t->written) { + if (t->name) fprintf(h, "struct %s {\n", t->name); + else fprintf(h, "struct {\n"); + indentation++; + write_fields(h, t->fields); + indent(-1); + fprintf(h, "}"); + } + else fprintf(h, "struct %s", t->name); + break; + case RPC_FC_NON_ENCAPSULATED_UNION: + if (t->defined && !t->written) { + if (t->name) fprintf(h, "union %s {\n", t->name); + else fprintf(h, "union {\n"); + indentation++; + write_fields(h, t->fields); + indent(-1); + fprintf(h, "}"); + } + else fprintf(h, "union %s", t->name); + break; + default: + fprintf(h, "(unknown-type:%d)", t->type); + } + } + else { + if (t->ref) { + write_type(h, t->ref, NULL, t->name); + } + else fprintf(h, "void"); + } + } + if (v) { + for (c=0; cptr_level; c++) { + fprintf(h, "*"); + } + } +} + +void write_typedef(type_t *type, var_t *names) +{ + char *tname = names->tname; + while (NEXT_LINK(names)) names = NEXT_LINK(names); + fprintf(header, "typedef "); + write_type(header, type, NULL, tname); + fprintf(header, " "); + while (names) { + write_pident(names); + if (PREV_LINK(names)) + fprintf(header, ", "); + names = PREV_LINK(names); + } + fprintf(header, ";\n"); +} + +/********** INTERFACES **********/ + +int is_object(attr_t *a) +{ + while (a) { + if (a->type == tOBJECT) return 1; + a = NEXT_LINK(a); + } + return 0; +} + +int is_local(attr_t *a) +{ + while (a) { + if (a->type == tLOCAL) return 1; + a = NEXT_LINK(a); + } + return 0; +} + +var_t *is_callas(attr_t *a) +{ + while (a) { + if (a->type == tCALLAS) return a->u.pval; + a = NEXT_LINK(a); + } + return NULL; +} + +static void write_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)) { + var_t *arg = cur->args; + int argc = 0; + if (arg) { + argc++; + while (NEXT_LINK(arg)) { + arg = NEXT_LINK(arg); + argc++; + } + } + fprintf(header, " \\\n"); + if (!is_void(def->type, def)) { + if (argc) + fprintf(header, " ICOM_METHOD%d (", argc); + else + fprintf(header, " ICOM_METHOD ("); + write_type(header, def->type, def, def->tname); + fprintf(header, ","); + } else + if (argc) + fprintf(header, " ICOM_VMETHOD%d(", argc); + else + fprintf(header, " ICOM_VMETHOD ("); + write_name(header, def); + while (arg) { + fprintf(header, ","); + write_type(header, arg->type, arg, arg->tname); + fprintf(header, ","); + write_name(header,arg); + arg = PREV_LINK(arg); + } + fprintf(header, ")"); + } + cur = PREV_LINK(cur); + } + fprintf(header, "\n"); +} + +static int write_method_macro(type_t *iface, char *name) +{ + int idx; + func_t *cur = iface->funcs; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + + if (iface->ref) idx = write_method_macro(iface->ref, name); + else idx = 0; + fprintf(header, "/*** %s methods ***/\n", iface->name); + while (cur) { + var_t *def = cur->def; + if (!is_callas(def->attrs)) { + var_t *arg = cur->args; + int argc = 0; + int c; + while (arg) { + arg = NEXT_LINK(arg); + argc++; + } + + fprintf(header, "#define %s_", name); + write_name(header,def); + fprintf(header, "(p"); + for (c=0; cidx == -1) cur->idx = idx; + else if (cur->idx != idx) yyerror("BUG: method index mismatch in write_method_macro"); + idx++; + } + cur = PREV_LINK(cur); + } + return idx; +} + +void write_method_args(FILE *h, var_t *arg, char *name) +{ + if (arg) { + while (NEXT_LINK(arg)) + arg = NEXT_LINK(arg); + } + fprintf(h, " %s* This", name); + while (arg) { + fprintf(h, ",\n "); + write_type(h, arg->type, arg, arg->tname); + fprintf(h, " "); + write_name(h,arg); + arg = PREV_LINK(arg); + } +} + +static void write_method_proto(type_t *iface) +{ + func_t *cur = iface->funcs; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + while (cur) { + var_t *def = cur->def; + var_t *cas = is_callas(def->attrs); + if (!is_local(def->attrs)) { + /* proxy prototype */ + write_type(header, def->type, def, def->tname); + fprintf(header, " CALLBACK %s_", iface->name); + write_name(header,def); + fprintf(header, "_Proxy(\n"); + write_method_args(header, cur->args, iface->name); + fprintf(header, ");\n"); + /* stub prototype */ + fprintf(header, "void __RPC_STUB %s_", iface->name); + write_name(header,def); + fprintf(header, "_Stub(\n"); + fprintf(header, " IRpcStubBuffer* This,\n"); + fprintf(header, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); + fprintf(header, " PRPC_MESSAGE pRpcMessage,\n"); + fprintf(header, " DWORD* pdwStubPhase);\n"); + } + if (cas) { + func_t *m = iface->funcs; + while (m && strcmp(get_name(m->def), cas->name)) + m = NEXT_LINK(m); + if (m) { + var_t *mdef = m->def; + /* proxy prototype - use local prototype */ + write_type(header, mdef->type, mdef, mdef->tname); + fprintf(header, " CALLBACK %s_", iface->name); + write_name(header, mdef); + fprintf(header, "_Proxy(\n"); + write_method_args(header, m->args, iface->name); + fprintf(header, ");\n"); + /* stub prototype - use remotable prototype */ + write_type(header, def->type, def, def->tname); + fprintf(header, " __RPC_STUB %s_", iface->name); + write_name(header, mdef); + fprintf(header, "_Stub(\n"); + write_method_args(header, cur->args, iface->name); + fprintf(header, ");\n"); + } + else { + yywarning("invalid call_as attribute (%s -> %s)\n", get_name(def), cas->name); + } + } + + cur = PREV_LINK(cur); + } +} + +void write_forward(type_t *iface) +{ + if (!iface->written) { + fprintf(header, "typedef struct %s %s;\n", iface->name, iface->name); + iface->written = TRUE; + } +} + +void write_interface(type_t *iface) +{ + if (!is_object(iface->attrs)) { + if (!iface->funcs) return; + yywarning("RPC interfaces not supported yet\n"); + return; + } + + if (!iface->funcs) { + yywarning("%s has no methods", iface->name); + return; + } + + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s interface\n", iface->name); + fprintf(header, " */\n"); + write_forward(iface); + if (iface->ref) + 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); + fprintf(header, "#undef ICOM_INTERFACE\n"); + } + fprintf(header, "\n"); + write_method_macro(iface, iface->name); + fprintf(header, "\n"); + write_method_proto(iface); + fprintf(header, "\n"); + + if (!is_local(iface->attrs)) + write_proxy(iface); +} diff --git a/tools/widl/header.h b/tools/widl/header.h new file mode 100644 index 0000000000..d1d1a36f03 --- /dev/null +++ b/tools/widl/header.h @@ -0,0 +1,36 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIDL_HEADER_H +#define __WIDL_HEADER_H + +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); +extern void write_type(FILE *h, type_t *t, var_t *v, char *n); +extern int is_object(attr_t *a); +extern int is_local(attr_t *a); +extern var_t *is_callas(attr_t *a); +extern void write_method_args(FILE *h, var_t *arg, char *name); +extern void write_forward(type_t *iface); +extern void write_interface(type_t *iface); +extern void write_typedef(type_t *type, var_t *names); + +#endif diff --git a/tools/widl/parser.h b/tools/widl/parser.h new file mode 100644 index 0000000000..fb84ed6919 --- /dev/null +++ b/tools/widl/parser.h @@ -0,0 +1,41 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIDL_PARSER_H +#define __WIDL_PARSER_H + +int yyparse(void); + +extern FILE *yyin; +extern char *yytext; +extern int yydebug; +extern int yy_flex_debug; + +int yylex(void); + +extern int import_stack_ptr; +void do_import(char *fname); +void abort_import(void); + +#define parse_only import_stack_ptr + +int is_type(const char *name); + +#endif diff --git a/tools/widl/parser.l b/tools/widl/parser.l new file mode 100644 index 0000000000..47a4748678 --- /dev/null +++ b/tools/widl/parser.l @@ -0,0 +1,311 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +%option stack +%option never-interactive + +nl \r?\n +ws [ \f\t\r] +cident [a-zA-Z_][0-9a-zA-Z_]* +int [0-9]+ +hexd [0-9a-fA-F] +hex 0x{hexd}+ +uuid {hexd}{8}-{hexd}{4}-{hexd}{4}-{hexd}{4}-{hexd}{12} + +%x QUOTE + +%{ + +#include +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "wpp.h" + +#include "y.tab.h" + +#define YY_USE_PROTOS +#define YY_NO_UNPUT +#define YY_NO_TOP_STATE + +extern char *temp_name; + +static void addcchar(char c); +static char *get_buffered_cstring(void); + +static char *cbuffer; +static int cbufidx; +static int cbufalloc = 0; + +static int kw_token(const char *kw); + +#define MAX_IMPORT_DEPTH 10 +struct { + YY_BUFFER_STATE state; + char *temp_name; +} import_stack[MAX_IMPORT_DEPTH]; +int import_stack_ptr = 0; + +static void pop_import(void); + +%} + +/* + ************************************************************************** + * The flexer starts here + ************************************************************************** + */ +%% +^#.* +\" yy_push_state(QUOTE); cbufidx = 0; +\" { + yy_pop_state(); + yylval.str = get_buffered_cstring(); + return aSTRING; + } +\\\\ | +\\\" addcchar(yytext[1]); +\\. addcchar('\\'); addcchar(yytext[1]); +. addcchar(yytext[0]); +{uuid} return aUUID; +{hex} return aNUM; +{int} return aNUM; +{cident} return kw_token(yytext); +\n +{ws} +\<\< return SHL; +\>\> return SHR; +. return yytext[0]; +<> { + if (import_stack_ptr) pop_import(); + else yyterminate(); + } +%% + +#ifndef yywrap +int yywrap(void) +{ + return 1; +} +#endif + +static struct { + const char *kw; + int token; + int val; +} keywords[] = { + {"__cdecl", tCDECL}, + {"__int64", tINT64}, + {"__stdcall", tSTDCALL}, + {"_stdcall", tSTDCALL}, + {"aggregatable", tAGGREGATABLE}, + {"allocate", tALLOCATE}, + {"appobject", tAPPOBJECT}, + {"arrays", tARRAYS}, + {"async", tASYNC}, + {"async_uuid", tASYNCUUID}, + {"auto_handle", tAUTOHANDLE}, + {"bindable", tBINDABLE}, + {"boolean", tBOOLEAN}, + {"broadcast", tBROADCAST}, + {"byte", tBYTE}, + {"byte_count", tBYTECOUNT}, + {"call_as", tCALLAS}, + {"callback", tCALLBACK}, + {"case", tCASE}, + {"char", tCHAR}, + {"coclass", tCOCLASS}, + {"code", tCODE}, + {"comm_status", tCOMMSTATUS}, + {"const", tCONST}, + {"context_handle", tCONTEXTHANDLE}, + {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, + {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, + {"control", tCONTROL}, + {"cpp_quote", tCPPQUOTE}, +/* ... */ + {"default", tDEFAULT}, +/* ... */ + {"double", tDOUBLE}, +/* ... */ + {"enum", tENUM}, +/* ... */ + {"extern", tEXTERN}, +/* ... */ + {"float", tFLOAT}, +/* ... */ + {"hyper", tHYPER}, +/* ... */ + {"iid_is", tIIDIS}, +/* ... */ + {"import", tIMPORT}, + {"importlib", tIMPORTLIB}, + {"in", tIN}, + {"include", tINCLUDE}, + {"in_line", tINLINE}, + {"int", tINT}, +/* ... */ + {"interface", tINTERFACE}, +/* ... */ + {"length_is", tLENGTHIS}, +/* ... */ + {"local", tLOCAL}, + {"long", tLONG}, +/* ... */ + {"object", tOBJECT}, + {"odl", tODL}, + {"oleautomation", tOLEAUTOMATION}, +/* ... */ + {"out", tOUT}, +/* ... */ + {"pointer_default", tPOINTERDEFAULT}, +/* ... */ + {"ref", tREF}, +/* ... */ + {"short", tSHORT}, + {"signed", tSIGNED}, + {"size_is", tSIZEIS}, + {"sizeof", tSIZEOF}, +/* ... */ + {"string", tSTRING}, + {"struct", tSTRUCT}, + {"switch", tSWITCH}, + {"switch_is", tSWITCHIS}, + {"switch_type", tSWITCHTYPE}, +/* ... */ + {"typedef", tTYPEDEF}, + {"union", tUNION}, +/* ... */ + {"unique", tUNIQUE}, + {"unsigned", tUNSIGNED}, +/* ... */ + {"uuid", tUUID}, + {"v1_enum", tV1ENUM}, +/* ... */ + {"version", tVERSION}, + {"void", tVOID}, + {"wchar_t", tWCHAR}, + {"wire_marshal", tWIREMARSHAL}, + {NULL} +}; + +static int kw_token(const char *kw) +{ + int i; + for (i=0; keywords[i].kw; i++) + if (strcmp(kw, keywords[i].kw) == 0) + return keywords[i].token; + yylval.str = xstrdup(kw); + return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; +} + +static void addcchar(char c) +{ + if(cbufidx >= cbufalloc) + { + cbufalloc += 1024; + cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0])); + if(cbufalloc > 65536) + yywarning("Reallocating string buffer larger than 64kB"); + } + cbuffer[cbufidx++] = c; +} + +static char *get_buffered_cstring(void) +{ + addcchar(0); + return xstrdup(cbuffer); +} + +static void pop_import(void) +{ + int ptr = import_stack_ptr-1; + + fclose(yyin); + yy_delete_buffer( YY_CURRENT_BUFFER ); + yy_switch_to_buffer( import_stack[ptr].state ); + if (temp_name) { + unlink(temp_name); + free(temp_name); + } + temp_name = import_stack[ptr].temp_name; + import_stack_ptr--; +} + +struct imports { + char *name; + struct imports *next; +} *first_import; + +void do_import(char *fname) +{ + FILE *f; + char *hname, *path; + struct imports *import; + int ptr = import_stack_ptr; + int ret; + + if (!parse_only) { + hname = dup_basename(fname, ".idl"); + strcat(hname, ".h"); + + fprintf(header, "#include \"%s\"\n", hname); + free(hname); + } + + import = first_import; + while (import && strcmp(import->name, fname)) + import = import->next; + if (import) return; /* already imported */ + + import = xmalloc(sizeof(struct imports)); + import->name = xstrdup(fname); + import->next = first_import; + first_import = import; + + if (!(path = wpp_find_include( fname, 1 ))) + yyerror("Unable to open include file %s", fname); + + import_stack[ptr].temp_name = temp_name; + import_stack_ptr++; + + ret = wpp_parse_temp( path, &temp_name ); + free( path ); + if (ret) exit(1); + + if((f = fopen(temp_name, "r")) == NULL) + yyerror("Unable to open %s", temp_name); + + import_stack[ptr].state = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); +} + +void abort_import(void) +{ + int ptr; + + for (ptr=0; ptr +#include +#include +#include +#include +#include +#ifdef HAVE_ALLOCA_H +#include +#endif + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" + +#if defined(YYBYACC) + /* Berkeley yacc (byacc) doesn't seem to know about these */ + /* Some *BSD supplied versions do define these though */ +# ifndef YYEMPTY +# define YYEMPTY (-1) /* Empty lookahead value of yychar */ +# endif +# ifndef YYLEX +# define YYLEX yylex() +# endif + +#elif defined(YYBISON) + /* Bison was used for original development */ + /* #define YYEMPTY -2 */ + /* #define YYLEX yylex() */ + +#else + /* No yacc we know yet */ +# if !defined(YYEMPTY) || !defined(YYLEX) +# error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX. +# elif defined(__GNUC__) /* gcc defines the #warning directive */ +# warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested + /* #else we just take a chance that it works... */ +# endif +#endif + +static attr_t *make_attr(int type); +static attr_t *make_attrv(int type, DWORD val); +static attr_t *make_attrp(int type, void *val); +static type_t *make_type(BYTE type, type_t *ref); +static typeref_t *make_tref(char *name, type_t *ref); +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); +static var_t *make_var(char *name); +static func_t *make_func(var_t *def, var_t *args); + +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); +static type_t *find_type(char *name, int t); +static type_t *find_type2(char *name, int t); +static type_t *get_type(BYTE type, char *name, int t); +static type_t *get_typev(BYTE type, var_t *name, int t); + +#define tsENUM 1 +#define tsSTRUCT 2 +#define tsUNION 3 + +static type_t std_int = { "int" }; + +%} +%union { + attr_t *attr; + type_t *type; + typeref_t *tref; + var_t *var; + func_t *func; + char *str; + int num; +} + +%token aIDENTIFIER +%token aKNOWNTYPE +%token aNUM +%token aSTRING +%token aUUID +%token SHL SHR +%token tAGGREGATABLE tALLOCATE tAPPOBJECT tARRAYS tASYNC tASYNCUUID +%token tAUTOHANDLE tBINDABLE tBOOLEAN tBROADCAST tBYTE tBYTECOUNT +%token tCALLAS tCALLBACK tCASE tCDECL tCHAR tCOCLASS tCODE tCOMMSTATUS +%token tCONST tCONTEXTHANDLE tCONTEXTHANDLENOSERIALIZE +%token tCONTEXTHANDLESERIALIZE tCONTROL tCPPQUOTE +%token tDEFAULT +%token tDOUBLE +%token tENUM +%token tEXTERN +%token tFLOAT +%token tHYPER +%token tIIDIS +%token tIMPORT tIMPORTLIB +%token tIN tINCLUDE tINLINE +%token tINT tINT64 +%token tINTERFACE +%token tLENGTHIS +%token tLOCAL +%token tLONG +%token tOBJECT tODL tOLEAUTOMATION +%token tOUT +%token tPOINTERDEFAULT +%token tREF +%token tSHORT +%token tSIGNED +%token tSIZEIS tSIZEOF +%token tSTDCALL +%token tSTRING tSTRUCT +%token tSWITCH tSWITCHIS tSWITCHTYPE +%token tTYPEDEF +%token tUNION +%token tUNIQUE +%token tUNSIGNED +%token tUUID +%token tV1ENUM +%token tVERSION +%token tVOID +%token tWCHAR tWIREMARSHAL + +/* used in attr_t */ +%token tPOINTERTYPE + +%type m_attributes attributes attrib_list attribute +%type inherit interface interfacedef +%type base_type int_std +%type enumdef structdef typedef uniondef +%type type +%type m_args no_args args arg +%type fields field +%type m_ident t_ident ident p_ident pident pident_list +%type funcdef statements +%type expr pointer_type + +%left ',' +%left '|' +%left '&' +%left '-' '+' +%left '*' '/' +%left SHL SHR +%right CAST +%right PPTR +%right NEG + +%% + +statements: { $$ = NULL; } + | statements funcdef ';' { LINK($2, $1); $$ = $2; } + | statements statement + ; + +statement: ';' {} + | constdef {} + | cppquote {} + | enumdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } } + | externdef ';' {} + | import {} + | interface ';' {} + | interfacedef {} + | structdef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } } + | typedef ';' {} + | uniondef ';' { if (!parse_only) { write_type(header, $1, NULL, NULL); fprintf(header, ";\n"); } } + ; + +cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only) fprintf(header, "%s\n", $3); } +; +import: tIMPORT aSTRING ';' { do_import($2); } +; + +m_args: { $$ = NULL; } + | args + ; + +no_args: tVOID { $$ = NULL; } + ; + +args: arg + | args ',' arg { LINK($3, $1); $$ = $3; } + | no_args + ; + +/* split into two rules to get bison to resolve a tVOID conflict */ +arg: attributes type pident array { $$ = $3; + set_type($$, $2); + $$->attrs = $1; /* FIXME: array */ + } + | type pident array { $$ = $2; + set_type($$, $1); /* FIXME: array */ + } + ; + +aexprs: + | aexpr_list + ; + +aexpr_list: aexpr + | aexprs ',' aexpr + ; + +aexpr: aNUM {} + | aIDENTIFIER {} + | aexpr '|' aexpr + | aexpr '&' aexpr + | aexpr '+' aexpr + | aexpr '-' aexpr + | aexpr '*' aexpr + | aexpr '/' aexpr + | '-' aexpr %prec NEG + | '*' aexpr %prec PPTR + | '(' type ')' aexpr %prec CAST + | '(' aexpr ')' + | tSIZEOF '(' type ')' + ; + +array: + | '[' aexprs ']' + | '[' '*' ']' + ; + +m_attributes: { $$ = NULL; } + | attributes + ; + +attributes: + m_attributes '[' attrib_list ']' { LINK_LAST($3, $1); $$ = $3; } + ; + +attrib_list: attribute + | attrib_list ',' attribute { LINK_SAFE($3, $1); $$ = $3; /* FIXME: don't use SAFE */ } + ; + +attribute: + tASYNC { $$ = make_attr(tASYNC); } + | tCALLAS '(' ident ')' { $$ = make_attrp(tCALLAS, $3); } + | tCASE '(' expr_list ')' { $$ = NULL; } + | tCONTEXTHANDLE { $$ = NULL; } + | tCONTEXTHANDLENOSERIALIZE { $$ = NULL; } + | tCONTEXTHANDLESERIALIZE { $$ = NULL; } + | tDEFAULT { $$ = make_attr(tDEFAULT); } + | tIIDIS '(' ident ')' { $$ = make_attrp(tIIDIS, $3); } + | tIN { $$ = make_attr(tIN); } + | tLENGTHIS '(' aexprs ')' { $$ = NULL; } + | tLOCAL { $$ = make_attr(tLOCAL); } + | tOBJECT { $$ = make_attr(tOBJECT); } + | tOLEAUTOMATION { $$ = make_attr(tOLEAUTOMATION); } + | tOUT { $$ = make_attr(tOUT); } + | tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(tPOINTERDEFAULT, $3); } + | tSIZEIS '(' aexprs ')' { $$ = NULL; } + | tSTRING { $$ = make_attr(tSTRING); } + | tSWITCHIS '(' aexpr ')' { $$ = NULL; } + | tSWITCHTYPE '(' type ')' { $$ = NULL; } + | tUUID '(' aUUID ')' { $$ = NULL; } + | tV1ENUM { $$ = make_attr(tV1ENUM); } + | tVERSION '(' version ')' { $$ = NULL; } + | tWIREMARSHAL '(' type ')' { $$ = make_attrp(tWIREMARSHAL, type_ref($3)); } + | pointer_type { $$ = make_attrv(tPOINTERTYPE, $1); } + ; + +callconv: + | tSTDCALL + ; + +cases: + | cases case + ; + +case: tCASE expr ':' field + | tDEFAULT ':' field + ; + +constdef: tCONST type ident '=' expr + ; + +enums: + | enum_list ',' + | enum_list + ; + +enum_list: enum + | enum_list ',' enum + ; + +enum: ident '=' expr {} + | ident {} + ; + +enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_SHORT /* FIXME */, $2, tsENUM); + $$->defined = TRUE; + } + ; + +expr_list: expr {} + | expr_list ',' expr {} + ; + +expr: aNUM + | aIDENTIFIER {} + | expr '|' expr {} + | expr SHL expr {} + | expr SHR expr {} + | '-' expr %prec NEG {} + ; + +externdef: tEXTERN tCONST type ident + ; + +fields: { $$ = NULL; } + | fields field { LINK($2, $1); $$ = $2; } + ; + +field: m_attributes type pident array ';' { $$ = $3; set_type($$, $2); $$->attrs = $1; /* FIXME: array */ } + | m_attributes uniondef ';' { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; } + | attributes ';' { $$ = make_var(NULL); $$->attrs = $1; } + | ';' { $$ = NULL; } + ; + +funcdef: + m_attributes type callconv pident + '(' m_args ')' { set_type($4, $2); + $4->attrs = $1; + $$ = make_func($4, $6); + } + ; + +m_ident: { $$ = NULL; } + | ident + ; + +t_ident: { $$ = NULL; } + | aIDENTIFIER { $$ = make_var($1); } + | aKNOWNTYPE { $$ = make_var($1); } + ; + +ident: aIDENTIFIER { $$ = make_var($1); } + ; + +base_type: tBYTE { $$ = make_type(RPC_FC_BYTE, NULL); } + | tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); } + | tUNSIGNED tCHAR { $$ = make_type(RPC_FC_CHAR, NULL); } + | tWCHAR { $$ = make_type(RPC_FC_WCHAR, NULL); } + | int_std + | tSIGNED int_std { $$ = $2; /* FIXME */ } + | tUNSIGNED int_std { $$ = $2; /* FIXME */ } + | tFLOAT { $$ = make_type(RPC_FC_FLOAT, NULL); } + | tDOUBLE { $$ = make_type(RPC_FC_DOUBLE, NULL); } + | tBOOLEAN { $$ = make_type(RPC_FC_BYTE, NULL); /* ? */ } + ; + +m_int: + | tINT + ; + +int_std: tINT { $$ = make_type(RPC_FC_LONG, &std_int); } /* win32 only */ + | tSHORT m_int { $$ = make_type(RPC_FC_SHORT, NULL); } + | tLONG m_int { $$ = make_type(RPC_FC_LONG, NULL); } + | tHYPER m_int { $$ = make_type(RPC_FC_HYPER, NULL); } + | tINT64 { $$ = make_type(RPC_FC_HYPER, NULL); } + ; + +inherit: { $$ = NULL; } + | ':' aKNOWNTYPE { $$ = find_type2($2, 0); } + ; + +interface: tINTERFACE aIDENTIFIER { $$ = get_type(RPC_FC_IP, $2, 0); if (!parse_only) write_forward($$); } + | tINTERFACE aKNOWNTYPE { $$ = get_type(RPC_FC_IP, $2, 0); if (!parse_only) write_forward($$); } + ; + +interfacedef: attributes interface inherit + '{' statements '}' { $$ = $2; + if ($$->defined) yyerror("multiple definition error\n"); + $$->ref = $3; + $$->attrs = $1; + $$->funcs = $5; + $$->defined = TRUE; + if (!parse_only) write_interface($$); + } + ; + +p_ident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; } + | tCONST p_ident { $$ = $2; } + ; + +pident: ident + | p_ident + | '(' pident ')' { $$ = $2; } + ; + +pident_list: + pident + | pident_list ',' pident { LINK($3, $1); $$ = $3; } + ; + +pointer_type: + tREF { $$ = RPC_FC_RP; } + | tUNIQUE { $$ = RPC_FC_UP; } + ; + +structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT); + $$->fields = $4; + $$->defined = TRUE; + } + ; + +type: tVOID { $$ = make_tref(NULL, make_type(0, NULL)); } + | aKNOWNTYPE { $$ = make_tref($1, find_type($1, 0)); } + | base_type { $$ = make_tref(NULL, $1); } + | tCONST type { $$ = uniq_tref($2); $$->ref->is_const = TRUE; } + | enumdef { $$ = make_tref(NULL, $1); } + | tENUM aIDENTIFIER { $$ = make_tref(NULL, find_type2($2, tsENUM)); } + | structdef { $$ = make_tref(NULL, $1); } + | tSTRUCT aIDENTIFIER { $$ = make_tref(NULL, get_type(RPC_FC_STRUCT, $2, tsSTRUCT)); } + | uniondef { $$ = make_tref(NULL, $1); } + | tUNION aIDENTIFIER { $$ = make_tref(NULL, find_type2($2, tsUNION)); } + ; + +typedef: tTYPEDEF m_attributes type pident_list { typeref_t *tref = uniq_tref($3); + $4->tname = tref->name; + tref->name = NULL; + $$ = type_ref(tref); + $$->attrs = $2; + if (!parse_only) write_typedef($$, $4); + reg_types($$, $4, 0); + } + ; + +uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION); + $$->fields = $4; + $$->defined = TRUE; + } + | tUNION t_ident + tSWITCH '(' type ident ')' + m_ident '{' cases '}' { $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION); + $$->defined = TRUE; + } + ; + +version: + aNUM {} + | aNUM '.' aNUM {} + ; + +%% + +static attr_t *make_attr(int type) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.ival = 0; + return a; +} + +static attr_t *make_attrv(int type, DWORD val) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.ival = val; + return a; +} + +static attr_t *make_attrp(int type, void *val) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.pval = val; + return a; +} + +static type_t *make_type(BYTE type, type_t *ref) +{ + type_t *t = xmalloc(sizeof(type_t)); + t->name = NULL; + t->type = type; + t->ref = ref; + t->rname = NULL; + t->attrs = NULL; + t->funcs = NULL; + t->fields = NULL; + t->ignore = parse_only; + t->is_const = FALSE; + t->defined = FALSE; + t->written = FALSE; + INIT_LINK(t); + return t; +} + +static typeref_t *make_tref(char *name, type_t *ref) +{ + typeref_t *t = xmalloc(sizeof(typeref_t)); + t->name = name; + t->ref = ref; + t->uniq = ref ? 0 : 1; + return t; +} + +static typeref_t *uniq_tref(typeref_t *ref) +{ + typeref_t *t = ref; + type_t *tp; + if (t->uniq) return t; + tp = make_type(0, t->ref); + tp->name = t->name; + t->name = NULL; + t->ref = tp; + t->uniq = 1; + return t; +} + +static type_t *type_ref(typeref_t *ref) +{ + type_t *t = ref->ref; + if (ref->name) free(ref->name); + free(ref); + return t; +} + +static void set_type(var_t *v, typeref_t *ref) +{ + v->type = ref->ref; + v->tname = ref->name; + ref->name = NULL; + free(ref); +} + +static var_t *make_var(char *name) +{ + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; + v->ptr_level = 0; + v->type = NULL; + v->tname = NULL; + v->attrs = NULL; + INIT_LINK(v); + return v; +} + +static func_t *make_func(var_t *def, var_t *args) +{ + func_t *f = xmalloc(sizeof(func_t)); + f->def = def; + f->args = args; + f->ignore = parse_only; + f->idx = -1; + INIT_LINK(f); + return f; +} + +struct rtype { + char *name; + type_t *type; + int t; + struct rtype *next; +}; + +struct rtype *first; + +static type_t *reg_type(type_t *type, char *name, int t) +{ + struct rtype *nt; + if (!name) { + yyerror("registering named type without name\n"); + return type; + } + nt = xmalloc(sizeof(struct rtype)); + nt->name = name; + nt->type = type; + nt->t = t; + nt->next = first; + first = nt; + return type; +} + +static type_t *reg_types(type_t *type, var_t *names, int t) +{ + type_t *ptr = type; + int ptrc = 0; + + while (names) { + var_t *next = NEXT_LINK(names); + if (names->name) { + type_t *cur = ptr; + int cptr = names->ptr_level; + if (cptr > ptrc) { + while (cptr > ptrc) { + cur = ptr = make_type(RPC_FC_FP, cur); /* FIXME: pointer type from attrs? */ + ptrc++; + } + } else { + while (cptr < ptrc) { + cur = cur->ref; + cptr++; + } + } + reg_type(cur, names->name, t); + } + free(names); + names = next; + } + return type; +} + +static type_t *find_type(char *name, int t) +{ + struct rtype *cur = first; + while (cur && (cur->t != t || strcmp(cur->name, name))) + cur = cur->next; + if (!cur) { + yyerror("type %s not found\n", name); + return NULL; + } + return cur->type; +} + +static type_t *find_type2(char *name, int t) +{ + type_t *tp = find_type(name, t); + free(name); + return tp; +} + +int is_type(const char *name) +{ + struct rtype *cur = first; + while (cur && (cur->t || strcmp(cur->name, name))) + cur = cur->next; + if (cur) return TRUE; + return FALSE; +} + +static type_t *get_type(BYTE type, char *name, int t) +{ + struct rtype *cur = NULL; + type_t *tp; + if (name) { + cur = first; + while (cur && (cur->t != t || strcmp(cur->name, name))) + cur = cur->next; + } + if (cur) { + free(name); + return cur->type; + } + tp = make_type(type, NULL); + tp->name = name; + if (!name) return tp; + return reg_type(tp, name, t); +} + +static type_t *get_typev(BYTE type, var_t *name, int t) +{ + char *sname = NULL; + if (name) { + sname = name->name; + free(name); + } + return get_type(type, sname, t); +} diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c new file mode 100644 index 0000000000..e32eda1628 --- /dev/null +++ b/tools/widl/proxy.c @@ -0,0 +1,368 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "y.tab.h" + +/* FIXME: support generation of stubless proxies */ + +static void write_stubdesc(void) +{ + fprintf(proxy, "const MIDL_STUB_DESC Object_StubDesc = {\n"); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " NdrOleAllocate,\n"); + fprintf(proxy, " NdrOleFree,\n"); + fprintf(proxy, " {0}, 0, 0, 0, 0,\n"); + fprintf(proxy, " 0 /* __MIDL_TypeFormatString.Format */\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); +} + +static void init_proxy(void) +{ + if (proxy) return; + proxy = fopen(proxy_name, "w"); + fprintf(proxy, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION); + fprintf(proxy, "#include \"rpcproxy.h\"\n"); + fprintf(proxy, "#include \"%s\"\n", header_name); + fprintf(proxy, "\n"); + write_stubdesc(); +} + +static void gen_proxy(type_t *iface, func_t *cur, int idx) +{ + var_t *def = cur->def; + int has_ret = !is_void(def->type, def); + + write_type(proxy, def->type, def, def->tname); + fprintf(proxy, " CALLBACK %s_", iface->name); + write_name(proxy, def); + fprintf(proxy, "_Proxy(\n"); + write_method_args(proxy, cur->args, iface->name); + fprintf(proxy, ")\n"); + fprintf(proxy, "{\n"); + /* local variables */ + if (has_ret) { + fprintf(proxy, " "); + write_type(proxy, def->type, def, def->tname); + fprintf(proxy, " _Ret;\n"); + } + fprintf(proxy, " RPC_MESSAGE _Msg;\n"); + fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n"); + fprintf(proxy, "\n"); + + /* FIXME: trace */ + /* FIXME: clear output vars? */ + + fprintf(proxy, " NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx); + + /* FIXME: size buffer */ + + fprintf(proxy, " NdrProxyGetBuffer(This, &_StubMsg);\n"); + + /* FIXME: marshall */ + + fprintf(proxy, " NdrProxySendReceive(This, &_StubMsg);\n"); + + /* FIXME: unmarshall */ + + fprintf(proxy, " NdrProxyFreeBuffer(This, &_StubMsg);\n"); + + if (has_ret) { + fprintf(proxy, " return _Ret;\n"); + } + fprintf(proxy, "}\n"); + fprintf(proxy, "\n"); +} + +static void gen_stub(type_t *iface, func_t *cur, char *cas) +{ + var_t *def = cur->def; + var_t *arg; + int has_ret = !is_void(def->type, def); + + fprintf(proxy, "void __RPC_STUB %s_", iface->name); + write_name(proxy, def); + fprintf(proxy, "_Stub(\n"); + fprintf(proxy, " IRpcStubBuffer* This,\n"); + fprintf(proxy, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); + fprintf(proxy, " PRPC_MESSAGE pRpcMessage,\n"); + fprintf(proxy, " DWORD* pdwStubPhase)\n"); + fprintf(proxy, "{\n"); + /* local variables */ + if (has_ret) { + fprintf(proxy, " "); + write_type(proxy, def->type, def, def->tname); + fprintf(proxy, " _Ret;\n"); + } + fprintf(proxy, " %s* _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name); + fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n"); + arg = cur->args; + while (arg) { + fprintf(proxy, " "); + write_type(proxy, arg->type, arg, arg->tname); + fprintf(proxy, " "); + write_name(proxy, arg); + fprintf(proxy, ";\n"); + arg = NEXT_LINK(arg); + } + fprintf(proxy, "\n"); + + /* FIXME: trace */ + /* FIXME: clear output vars? */ + + fprintf(proxy, " NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n"); + + /* FIXME: unmarshall */ + + fprintf(proxy, " *pdwStubPhase = STUB_CALL_SERVER;\n"); + fprintf(proxy, " "); + if (has_ret) fprintf(proxy, "_Ret = "); + fprintf(proxy, "%s_", iface->name); + if (cas) fprintf(proxy, "%s_Stub", cas); + else write_name(proxy, def); + fprintf(proxy, "(_This"); + arg = cur->args; + if (arg) { + while (NEXT_LINK(arg)) arg = NEXT_LINK(arg); + while (arg) { + fprintf(proxy, ", "); + write_name(proxy, arg); + arg = PREV_LINK(arg); + } + } + fprintf(proxy, ");\n"); + fprintf(proxy, " *pdwStubPhase = STUB_MARSHAL;\n"); + + /* FIXME: size buffer */ + + fprintf(proxy, " NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n"); + + /* FIXME: marshall */ + + fprintf(proxy, "}\n"); + fprintf(proxy, "\n"); +} + +static int write_proxy_methods(type_t *iface) +{ + func_t *cur = iface->funcs; + int i = 0; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + + if (iface->ref) i = write_proxy_methods(iface->ref); + while (cur) { + var_t *def = cur->def; + if (!is_callas(def->attrs)) { + if (i) fprintf(proxy, ",\n "); + fprintf(proxy, "%s_", iface->name); + write_name(proxy, def); + fprintf(proxy, "_Proxy"); + i++; + } + cur = PREV_LINK(cur); + } + return i; +} + +static int write_stub_methods(type_t *iface) +{ + func_t *cur = iface->funcs; + int i = 0; + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + + if (iface->ref) i = write_stub_methods(iface->ref); + else return i; /* skip IUnknown */ + while (cur) { + var_t *def = cur->def; + if (!is_local(def->attrs)) { + if (i) fprintf(proxy, ",\n"); + fprintf(proxy, " %s_", iface->name); + write_name(proxy, def); + fprintf(proxy, "_Stub"); + i++; + } + cur = PREV_LINK(cur); + } + 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) +{ + int midx = -1, stubs; + func_t *cur = iface->funcs; + if_list *if_cur; + + if (!cur) { + yywarning("%s has no methods", iface->name); + return; + } + + while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); + + /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */ + + 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"); + while (cur) { + var_t *def = cur->def; + if (!is_local(def->attrs)) { + var_t *cas = is_callas(def->attrs); + char *cname = cas ? cas->name : NULL; + int idx = cur->idx; + if (cname) { + func_t *m = iface->funcs; + while (m && strcmp(get_name(m->def), cname)) + m = NEXT_LINK(m); + idx = m->idx; + } + gen_proxy(iface, cur, idx); + gen_stub(iface, cur, cname); + if (midx == -1) midx = idx; + else if (midx != idx) yyerror("method index mismatch in write_proxy"); + midx++; + } + cur = PREV_LINK(cur); + } + + /* proxy vtable */ + fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name); + fprintf(proxy, " {&IID_%s},\n", iface->name); + fprintf(proxy, " {"); + write_proxy_methods(iface); + fprintf(proxy, "}\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + /* stub vtable */ + fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name); + stubs = write_stub_methods(iface); + fprintf(proxy, "\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name); + fprintf(proxy, " {&IID_%s,\n", iface->name); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " %d,\n", stubs+3); + fprintf(proxy, " &%s_table[-3]},\n", iface->name); + fprintf(proxy, " {CStdStubBuffer_METHODS}\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); +} + +void finish_proxy(void) +{ + if_list *lcur = if_first; + if_list *cur; + int c; + + if (!lcur) return; + while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur); + + fprintf(proxy, "const CInterfaceProxyVtbl* _XXX_ProxyVtblList[] = {\n"); + cur = lcur; + while (cur) { + fprintf(proxy, " (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name); + cur = PREV_LINK(cur); + } + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "const CInterfaceStubVtbl* _XXX_StubVtblList[] = {\n"); + cur = lcur; + while (cur) { + fprintf(proxy, " (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name); + cur = PREV_LINK(cur); + } + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "const PCInterfaceName _XXX_InterfaceNamesList[] = {\n"); + cur = lcur; + while (cur) { + fprintf(proxy, " \"%s\",\n", cur->iface->name); + cur = PREV_LINK(cur); + } + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "#define _XXX_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n"); + fprintf(proxy, "\n"); + fprintf(proxy, "int __stdcall _XXX_IID_Lookup(const IID* pIID, int* pIndex)\n"); + fprintf(proxy, "{\n"); + cur = lcur; + c = 0; + while (cur) { + fprintf(proxy, " if (!_XXX_CHECK_IID(%d)) {\n", c); + fprintf(proxy, " *pIndex = %d\n", c); + fprintf(proxy, " return 1;\n"); + fprintf(proxy, " }\n"); + cur = PREV_LINK(cur); + c++; + } + fprintf(proxy, " return 0;\n"); + fprintf(proxy, "}\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "const ExtendedProxyFileInfo XXX_ProxyFileInfo = {\n"); + fprintf(proxy, " (PCInterfaceProxyVtblList*)&_XXX_ProxyVtblList,\n"); + fprintf(proxy, " (PCInterfaceStubVtblList*)&_XXX_StubVtblList,\n"); + fprintf(proxy, " (const PCInterfaceName*)&_XXX_InterfaceNamesList,\n"); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " &_XXX_IID_Lookup,\n"); + fprintf(proxy, " %d,\n", c); + fprintf(proxy, " 1\n"); + fprintf(proxy, "};\n"); + + fclose(proxy); +} diff --git a/tools/widl/proxy.h b/tools/widl/proxy.h new file mode 100644 index 0000000000..aad02c598a --- /dev/null +++ b/tools/widl/proxy.h @@ -0,0 +1,27 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIDL_PROXY_H +#define __WIDL_PROXY_H + +extern void write_proxy(type_t *iface); +extern void finish_proxy(void); + +#endif diff --git a/tools/widl/utils.c b/tools/widl/utils.c new file mode 100644 index 0000000000..0420e1c6d5 --- /dev/null +++ b/tools/widl/utils.c @@ -0,0 +1,201 @@ +/* + * Utility routines + * + * Copyright 1998 Bertho A. Stultiens + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "wine/unicode.h" +#include "widl.h" +#include "utils.h" +#include "parser.h" + +/* #define WANT_NEAR_INDICATION */ + +#ifdef WANT_NEAR_INDICATION +void make_print(char *str) +{ + while(*str) + { + if(!isprint(*str)) + *str = ' '; + str++; + } +} +#endif + +static void generic_msg(const char *s, const char *t, const char *n, va_list ap) +{ + fprintf(stderr, "%s:%d:%d: %s: ", input_name ? input_name : "stdin", line_number, char_number, t); + vfprintf(stderr, s, ap); +#ifdef WANT_NEAR_INDICATION + { + char *cpy; + if(n) + { + cpy = xstrdup(n); + make_print(cpy); + fprintf(stderr, " near '%s'", cpy); + free(cpy); + } + } +#endif + fprintf(stderr, "\n"); +} + + +int yyerror(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Error", yytext, ap); + va_end(ap); + exit(1); + return 1; +} + +int yywarning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Warning", yytext, ap); + va_end(ap); + return 0; +} + +void internal_error(const char *file, int line, const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "Internal error (please report) %s %d: ", file, line); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(3); +} + +void error(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "Error: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(2); +} + +void warning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "Warning: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void chat(const char *s, ...) +{ + if(debuglevel & DEBUGLEVEL_CHAT) + { + va_list ap; + va_start(ap, s); + fprintf(stderr, "FYI: "); + vfprintf(stderr, s, ap); + fprintf(stderr, "\n"); + va_end(ap); + } +} + +char *dup_basename(const char *name, const char *ext) +{ + int namelen; + int extlen = strlen(ext); + char *base; + char *slash; + + if(!name) + name = "widl.tab"; + + slash = strrchr(name, '/'); + if (slash) + name = slash + 1; + + namelen = strlen(name); + + /* +4 for later extension and +1 for '\0' */ + base = (char *)xmalloc(namelen +4 +1); + strcpy(base, name); + if(!strcasecmp(name + namelen-extlen, ext)) + { + base[namelen - extlen] = '\0'; + } + return base; +} + +void *xmalloc(size_t size) +{ + void *res; + + assert(size > 0); + res = malloc(size); + if(res == NULL) + { + error("Virtual memory exhausted.\n"); + } + /* + * We set it to 0. + * This is *paramount* because we depend on it + * just about everywhere in the rest of the code. + */ + memset(res, 0, size); + return res; +} + + +void *xrealloc(void *p, size_t size) +{ + void *res; + + assert(size > 0); + res = realloc(p, size); + if(res == NULL) + { + error("Virtual memory exhausted.\n"); + } + return res; +} + +char *xstrdup(const char *str) +{ + char *s; + + assert(str != NULL); + s = (char *)xmalloc(strlen(str)+1); + return strcpy(s, str); +} diff --git a/tools/widl/utils.h b/tools/widl/utils.h new file mode 100644 index 0000000000..6ef92b4839 --- /dev/null +++ b/tools/widl/utils.h @@ -0,0 +1,41 @@ +/* + * Utility routines' prototypes etc. + * + * Copyright 1998 Bertho A. Stultiens (BS) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIDL_UTILS_H +#define __WIDL_UTILS_H + +#include "widltypes.h" + +#include /* size_t */ + +void *xmalloc(size_t); +void *xrealloc(void *, size_t); +char *xstrdup(const char *str); + +int yyerror(const char *s, ...) __attribute__((format (printf, 1, 2))); +int yywarning(const char *s, ...) __attribute__((format (printf, 1, 2))); +void internal_error(const char *file, int line, const char *s, ...) __attribute__((format (printf, 3, 4))); +void error(const char *s, ...) __attribute__((format (printf, 1, 2))); +void warning(const char *s, ...) __attribute__((format (printf, 1, 2))); +void chat(const char *s, ...) __attribute__((format (printf, 1, 2))); + +char *dup_basename(const char *name, const char *ext); + +#endif diff --git a/tools/widl/widl.c b/tools/widl/widl.c new file mode 100644 index 0000000000..f726d2b35c --- /dev/null +++ b/tools/widl/widl.c @@ -0,0 +1,213 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * based on WRC code by Bertho Stultiens + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#define WIDL_FULLVERSION "0.1" + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "proxy.h" +#include "wpp.h" + +static char usage[] = +"Usage: widl [options...] infile.idl\n" +" -d n Set debug level to 'n'\n" +" -D id[=val] Define preprocessor identifier id=val\n" +" -E Preprocess only\n" +" -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" +" -V Print version and exit\n" +" -W Enable pedantic warnings\n" +"Debug level 'n' is a bitmask with following meaning:\n" +" * 0x01 Tell which resource is parsed (verbose mode)\n" +" * 0x02 Dump internal structures\n" +" * 0x04 Create a parser trace (yydebug=1)\n" +" * 0x08 Preprocessor messages\n" +" * 0x10 Preprocessor lex messages\n" +" * 0x20 Preprocessor yacc trace\n" +; + +char version_string[] = "Wine IDL Compiler Version " WIDL_FULLVERSION "\n" + "Copyright 2002 Ove Kaaven\n"; + +int win32 = 1; +int debuglevel = DEBUGLEVEL_NONE; + +int pedantic = 0; +int preprocess_only = 0; +int no_preprocess = 0; + +char *input_name; +char *header_name; +char *proxy_name; +char *temp_name; + +int line_number = 1; +int char_number = 1; + +FILE *header; +FILE *proxy; + +time_t now; + +int getopt (int argc, char *const *argv, const char *optstring); +static void rm_tempfile(void); +static void segvhandler(int sig); + +int main(int argc,char *argv[]) +{ + extern char* optarg; + extern int optind; + int optc; + int ret; + + signal(SIGSEGV, segvhandler); + + now = time(NULL); + + while((optc = getopt(argc, argv, "d:D:EH:I:NVW")) != EOF) { + switch(optc) { + case 'd': + debuglevel = strtol(optarg, NULL, 0); + break; + case 'D': + wpp_add_cmdline_define(optarg); + break; + case 'E': + preprocess_only = 1; + break; + case 'H': + header_name = strdup(optarg); + break; + case 'I': + wpp_add_include_path(optarg); + break; + case 'N': + no_preprocess = 1; + break; + case 'V': + printf(version_string); + return 0; + case 'W': + pedantic = 1; + break; + default: + fprintf(stderr, usage); + return 1; + } + } + + if(optind < argc) { + input_name = argv[optind]; + } + else { + fprintf(stderr, usage); + return 1; + } + + if(debuglevel) + { + setbuf(stdout,0); + setbuf(stderr,0); + } + + yydebug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0; + yy_flex_debug = debuglevel & DEBUGLEVEL_TRACE ? 1 : 0; + + wpp_set_debug( (debuglevel & DEBUGLEVEL_PPLEX) != 0, + (debuglevel & DEBUGLEVEL_PPTRACE) != 0, + (debuglevel & DEBUGLEVEL_PPMSG) != 0 ); + + if (!header_name) { + header_name = dup_basename(input_name, ".idl"); + strcat(header_name, ".h"); + } + + if (!proxy_name) { + proxy_name = dup_basename(input_name, ".idl"); + strcat(proxy_name, "_p.c"); + } + + atexit(rm_tempfile); + if (!no_preprocess) + { + chat("Starting preprocess"); + + if (!preprocess_only) + { + ret = wpp_parse_temp( input_name, &temp_name ); + } + else + { + ret = wpp_parse( input_name, stdout ); + } + + if(ret) exit(1); + if(preprocess_only) exit(0); + input_name = temp_name; + } + + if(!(yyin = fopen(input_name, "r"))) { + fprintf(stderr, "Could not open %s for input\n", input_name); + return 1; + } + + header = fopen(header_name, "w"); + fprintf(header, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION); + + ret = yyparse(); + + finish_proxy(); + fclose(header); + fclose(yyin); + + if(ret) { + exit(1); + } + + return 0; +} + +static void rm_tempfile(void) +{ + abort_import(); + if(temp_name) + unlink(temp_name); +} + +static void segvhandler(int sig) +{ + fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number); + fflush(stdout); + fflush(stderr); + abort(); +} diff --git a/tools/widl/widl.h b/tools/widl/widl.h new file mode 100644 index 0000000000..f5d0b73b2d --- /dev/null +++ b/tools/widl/widl.h @@ -0,0 +1,53 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIDL_WIDL_H +#define __WIDL_WIDL_H + +#include "widltypes.h" + +#include + +#define WIDL_FULLVERSION "0.1" + +extern int debuglevel; +#define DEBUGLEVEL_NONE 0x0000 +#define DEBUGLEVEL_CHAT 0x0001 +#define DEBUGLEVEL_DUMP 0x0002 +#define DEBUGLEVEL_TRACE 0x0004 +#define DEBUGLEVEL_PPMSG 0x0008 +#define DEBUGLEVEL_PPLEX 0x0010 +#define DEBUGLEVEL_PPTRACE 0x0020 + +extern int win32; +extern int pedantic; + +extern char *input_name; +extern char *header_name; +extern char *proxy_name; +extern time_t now; + +extern int line_number; +extern int char_number; + +extern FILE* header; +extern FILE* proxy; + +#endif diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h new file mode 100644 index 0000000000..9af962a8b5 --- /dev/null +++ b/tools/widl/widltypes.h @@ -0,0 +1,97 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __WIDL_WIDLTYPES_H +#define __WIDL_WIDLTYPES_H + +#include "windef.h" +#include "oleauto.h" +#include "wine/rpcfc.h" + +typedef struct _attr_t attr_t; +typedef struct _type_t type_t; +typedef struct _typeref_t typeref_t; +typedef struct _var_t var_t; +typedef struct _func_t func_t; + +#define DECL_LINK(type) \ + type *l_next; \ + type *l_prev; + +#define LINK(x,y) do { x->l_next = y; if (y) y->l_prev = x; } while (0) +#define LINK_LAST(x,y) do { if (y) { typeof(x) _c = x; while (_c->l_next) _c = _c->l_next; LINK(_c, y); } } while (0) +#define LINK_SAFE(x,y) do { if (x) LINK_LAST(x,y); else { x = y; } } while (0) + +#define INIT_LINK(x) do { x->l_next = NULL; x->l_prev = NULL; } while (0) +#define NEXT_LINK(x) ((x)->l_next) +#define PREV_LINK(x) ((x)->l_prev) + +struct _attr_t { + int type; + union { + DWORD ival; + void *pval; + } u; + /* parser-internal */ + DECL_LINK(attr_t) +}; + +struct _type_t { + char *name; + BYTE type; + struct _type_t *ref; + char *rname; + attr_t *attrs; + func_t *funcs; + var_t *fields; + int ignore, is_const; + int defined, written; + + /* parser-internal */ + DECL_LINK(type_t) +}; + +struct _typeref_t { + char *name; + type_t *ref; + int uniq; +}; + +struct _var_t { + char *name; + int ptr_level; + type_t *type; + char *tname; + attr_t *attrs; + + /* parser-internal */ + DECL_LINK(var_t) +}; + +struct _func_t { + var_t *def; + var_t *args; + int ignore, idx; + + /* parser-internal */ + DECL_LINK(func_t) +}; + +#endif