Add basic support for creating client and server stub files.
authorEric Kohl <eric.kohl@reactos.org>
Mon, 21 Feb 2005 12:38:50 +0000 (12:38 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Mon, 21 Feb 2005 12:38:50 +0000 (12:38 +0000)
svn path=/trunk/; revision=13704

reactos/rules.mak
reactos/tools/widl/Makefile
reactos/tools/widl/Makefile.in
reactos/tools/widl/client.c [new file with mode: 0644]
reactos/tools/widl/client.h [new file with mode: 0644]
reactos/tools/widl/parser.y
reactos/tools/widl/server.c [new file with mode: 0644]
reactos/tools/widl/server.h [new file with mode: 0644]
reactos/tools/widl/widl.c
reactos/tools/widl/widl.h
reactos/tools/widl/y.tab.c

index 1317b36..1dcce0c 100644 (file)
@@ -1,3 +1,7 @@
+export VERBOSE = yes
+export BUILD_MAP = yes
+export BUILD_SYM = no
+
 # Default to half-verbose mode
 ifeq ($(VERBOSE),no)
   Q = @
@@ -163,6 +167,7 @@ export BIN2RES = $(Q)$(TOOLS_PATH)/bin2res/bin2res
 export XSLTPROC = $(Q)xsltproc
 export MS2PS = $(Q)$(TOOLS_PATH)/ms2ps/ms2ps
 export WRC = $(Q)$(TOOLS_PATH)/wrc/wrc
+export WIDL = $(Q)$(TOOLS_PATH)/widl/widl
 
 export STD_CFLAGS = -I$(PATH_TO_TOP)/include -I$(W32API_PATH)/include -pipe -march=$(OARCH) -D_M_IX86
 export STD_CPPFLAGS = $(STD_CFLAGS)
index 69629ad..a434f81 100644 (file)
@@ -13,10 +13,12 @@ TARGET = widl$(EXE_POSTFIX)
 all: $(TARGET)\r
 \r
 BASE_OBJECTS = \\r
+       client.o \\r
        hash.o \\r
        header.o \\r
        lex.yy.o \\r
        proxy.o \\r
+       server.o \\r
        typelib.o \\r
        utils.o \\r
        widl.o \\r
index df68258..3cfcfe1 100644 (file)
@@ -10,9 +10,11 @@ PROGRAMS = widl$(EXEEXT)
 MODULE   = none
 
 C_SRCS = \
+       client.c \
        hash.c \
        header.c \
        proxy.c \
+       server.c \
        typelib.c \
        utils.c \
        widl.c \
diff --git a/reactos/tools/widl/client.c b/reactos/tools/widl/client.c
new file mode 100644 (file)
index 0000000..55163d9
--- /dev/null
@@ -0,0 +1,415 @@
+/*\r
+ * IDL Compiler\r
+ *\r
+ * Copyright 2005 Eric Kohl\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include "config.h"\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#ifdef HAVE_UNISTD_H\r
+# include <unistd.h>\r
+#endif\r
+#include <string.h>\r
+#include <assert.h>\r
+#include <ctype.h>\r
+#include <signal.h>\r
+\r
+#include "windef.h"\r
+#include "widl.h"\r
+#include "utils.h"\r
+#include "parser.h"\r
+#include "header.h"\r
+\r
+#define END_OF_LIST(list)       \\r
+  do {                          \\r
+    if (list) {                 \\r
+      while (NEXT_LINK(list))   \\r
+        list = NEXT_LINK(list); \\r
+    }                           \\r
+  } while(0)\r
+\r
+static FILE* client;\r
+static int indent = 0;\r
+\r
+static int print_client( const char *format, ... )\r
+{\r
+    va_list va;\r
+    int i, r;\r
+\r
+    va_start(va, format);\r
+    for (i = 0; i < indent; i++)\r
+        fprintf(client, "    ");\r
+    r = vfprintf(client, format, va);\r
+    va_end(va);\r
+    return r;\r
+}\r
+\r
+\r
+static void write_procformatstring(type_t *iface)\r
+{\r
+    func_t *cur = iface->funcs;\r
+\r
+    print_client("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");\r
+    print_client("{\n");\r
+    indent++;\r
+    print_client("0,\n");\r
+    print_client("{\n");\r
+    indent++;\r
+\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        var_t *def = cur->def;\r
+\r
+        if (is_void(def->type, NULL))\r
+        {\r
+            print_client("0x5b,    /* FC_END */\n");\r
+            print_client("0x5c,    /* FC_PAD */\n");\r
+        }\r
+        else\r
+        {\r
+            print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");\r
+            print_client("0x%02x,    /* <type> */\n", def->type->type);\r
+        }\r
+\r
+        cur = PREV_LINK(cur);\r
+    }\r
+\r
+    print_client("0x0\n");\r
+    indent--;\r
+    print_client("}\n");\r
+    indent--;\r
+    print_client("};\n");\r
+    print_client("\n");\r
+}\r
+\r
+\r
+static void write_typeformatstring(void)\r
+{\r
+    print_client("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");\r
+    print_client("{\n");\r
+    indent++;\r
+    print_client("0,\n");\r
+    print_client("{\n");\r
+    indent++;\r
+    print_client("NdrFcShort(0x0),\n");\r
+    print_client("0x0\n");\r
+    indent--;\r
+    print_client("}\n");\r
+    indent--;\r
+    print_client("};\n");\r
+    print_client("\n");\r
+}\r
+\r
+\r
+static void write_function_stubs(type_t *iface)\r
+{\r
+    func_t *cur = iface->funcs;\r
+    int method_count = 0;\r
+    unsigned int proc_offset = 0;\r
+\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        var_t *def = cur->def;\r
+\r
+        write_type(client, def->type, def, def->tname);\r
+        fprintf(client, " ");\r
+        write_name(client, def);\r
+        fprintf(client, "(\n");\r
+        indent++;\r
+        if (cur->args)\r
+            write_args(client, cur->args, iface->name, 0, TRUE);\r
+        else\r
+            print_client("void");\r
+        fprintf(client, ")\n");\r
+        indent--;\r
+\r
+        /* write the functions body */\r
+        fprintf(client, "{\n");\r
+        indent++;\r
+\r
+        /* declare return value '_RetVal' */\r
+        if (!is_void(def->type, NULL))\r
+        {\r
+            print_client("");\r
+            write_type(client, def->type, def, def->tname);\r
+            fprintf(client, " _RetVal;\n");\r
+        }\r
+\r
+        print_client("RPC_MESSAGE _RpcMessage;\n");\r
+        print_client("MIDL_STUB_MESSAGE _StubMsg;\n");\r
+        fprintf(client, "\n");\r
+        print_client("RpcTryFinally\n");\r
+        print_client("{\n");\r
+        indent++;\r
+\r
+        print_client("NdrClientInitializeNew(\n");\r
+        indent++;\r
+        print_client("(PRPC_MESSAGE)&_RpcMessage,\n");\r
+        print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");\r
+        print_client("(PMIDL_STUB_DESC)&%s_StubDesc,\n", iface->name);\r
+        print_client("%d);\n", method_count);\r
+        indent--;\r
+        fprintf(client, "\n");\r
+\r
+\r
+        /* FIXME: marshal arguments */\r
+        print_client("_StubMsg.BufferLength = 0UL;\n");\r
+        print_client("NdrNsGetBuffer(\n");\r
+        indent++;\r
+        print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");\r
+        print_client("_StubMsg.BufferLength,\n");\r
+        print_client("%s__MIDL_AutoBindHandle);\n", iface->name);\r
+        indent--;\r
+        fprintf(client, "\n");\r
+\r
+\r
+        /* send/recieve message */\r
+        print_client("NdrNsSendReceive(\n");\r
+        indent++;\r
+        print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");\r
+        print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer,\n");\r
+        print_client("(RPC_BINDING_HANDLE __RPC_FAR *) &%s__MIDL_AutoBindHandle);\n", iface->name);\r
+        indent--;\r
+\r
+        /* unmarshal return value */\r
+        if (is_void(def->type, NULL))\r
+        {\r
+            proc_offset += 2;\r
+        }\r
+        else\r
+        {\r
+            fprintf(client, "\n");\r
+\r
+            print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");\r
+            indent++;\r
+            print_client("NdrConvert(\n");\r
+            indent++;\r
+            print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");\r
+            print_client("(PFORMAT_STRING)&__MIDL_ProcFormatString[%u]);\n", proc_offset);\r
+            indent -= 2;\r
+            fprintf(client, "\n");\r
+\r
+            print_client("_RetVal = *((");\r
+            write_type(client, def->type, def, def->tname);\r
+            fprintf(client, " __RPC_FAR *)_StubMsg.Buffer)++;\n");\r
+\r
+            /* FIXME: update pro_offset */\r
+            proc_offset += 2;\r
+        }\r
+\r
+        indent--;\r
+        print_client("}\n");\r
+        print_client("RpcFinally\n");\r
+        print_client("{\n");\r
+        indent++;\r
+\r
+\r
+        /* FIXME: emit client finally code */\r
+\r
+        print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n");\r
+\r
+        indent--;\r
+        print_client("}\n");\r
+        print_client("RpcEndFinally\n");\r
+\r
+\r
+        /* emit return code */\r
+        if (!is_void(def->type, NULL))\r
+        {\r
+            fprintf(client, "\n");\r
+            print_client("return _RetVal;\n");\r
+        }\r
+\r
+        indent--;\r
+        fprintf(client, "}\n");\r
+        fprintf(client, "\n");\r
+\r
+        method_count++;\r
+        cur = PREV_LINK(cur);\r
+    }\r
+}\r
+\r
+static void write_bindinghandledecl(type_t *iface)\r
+{\r
+    print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n", iface->name);\r
+    fprintf(client, "\n");\r
+}\r
+\r
+static void write_stubdescdecl(type_t *iface)\r
+{\r
+    print_client("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);\r
+    fprintf(client, "\n");\r
+}\r
+\r
+\r
+static void write_stubdescriptor(type_t *iface)\r
+{\r
+    print_client("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);\r
+    print_client("{\n");\r
+    indent++;\r
+    print_client("(void __RPC_FAR *)& %s___RpcClientInterface,\n", iface->name);\r
+    print_client("MIDL_user_allocate,\n");\r
+    print_client("MIDL_user_free,\n");\r
+    print_client("&%s__MIDL_AutoBindHandle,\n", iface->name);\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("__MIDL_TypeFormatString.Format,\n");\r
+    print_client("1, /* -error bounds_check flag */\n");\r
+    print_client("0x10001, /* Ndr library version */\n");\r
+    print_client("0,\n");\r
+    print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,  /* notify & notify_flag routine table */\n");\r
+    print_client("1,  /* Flags */\n");\r
+    print_client("0,  /* Reserved3 */\n");\r
+    print_client("0,  /* Reserved4 */\n");\r
+    print_client("0   /* Reserved5 */\n");\r
+    indent--;\r
+    print_client("};\n");\r
+    fprintf(client, "\n");\r
+}\r
+\r
+\r
+static void write_clientinterfacedecl(type_t *iface)\r
+{\r
+    unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);\r
+    UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);\r
+\r
+    print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name );\r
+    print_client("{\n");\r
+    indent++;\r
+    print_client("sizeof(RPC_CLIENT_INTERFACE),\n");\r
+    print_client("{{0x%08lx,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n",\r
+                 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],\r
+                 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],\r
+                 uuid->Data4[7], LOWORD(ver), HIWORD(ver));\r
+    print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    print_client("0,\n");\r
+    indent--;\r
+    print_client("};\n");\r
+    print_client("RPC_IF_HANDLE %s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",\r
+                 iface->name, LOWORD(ver), HIWORD(ver), iface->name);\r
+    fprintf(client, "\n");\r
+}\r
+\r
+\r
+static void write_formatdesc( const char *str )\r
+{\r
+    print_client("typedef struct _MIDL_%s_FORMAT_STRING\n", str );\r
+    print_client("{\n");\r
+    indent++;\r
+    print_client("short Pad;\n");\r
+    print_client("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);\r
+    indent--;\r
+    print_client("} MIDL_%s_FORMAT_STRING;\n", str);\r
+    print_client("\n");\r
+}\r
+\r
+\r
+static void write_formatstringsdecl(type_t *iface)\r
+{\r
+    func_t *cur;\r
+    int byte_count = 1;\r
+\r
+    print_client("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */\r
+\r
+    /* determine the proc format string size */\r
+    cur = iface->funcs;\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        byte_count += 2; /* FIXME: determine real size */\r
+        cur = PREV_LINK(cur);\r
+    }\r
+    print_client("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count);\r
+\r
+    fprintf(client, "\n");\r
+    write_formatdesc("TYPE");\r
+    write_formatdesc("PROC");\r
+    fprintf(client, "\n");\r
+    print_client("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");\r
+    print_client("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");\r
+    print_client("\n");\r
+}\r
+\r
+\r
+static void init_client(void)\r
+{\r
+    if (client) return;\r
+    if (!(client = fopen(client_name, "w")))\r
+        error("Could not open %s for output\n", client_name);\r
+\r
+    print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name);\r
+    print_client("#include<string.h>\n");\r
+    print_client("#ifdef _ALPHA_\n");\r
+    print_client("#include<stdarg.h>\n");\r
+    print_client("#endif\n");\r
+    fprintf(client, "\n");\r
+    print_client("#include\"%s\"\n", header_name);\r
+    fprintf(client, "\n");\r
+}\r
+\r
+\r
+void write_client(ifref_t *ifaces)\r
+{\r
+    ifref_t *lcur = ifaces;\r
+    char *file_id = client_token;\r
+    int c;\r
+\r
+    if (!do_client)\r
+        return;\r
+    if (!lcur)\r
+        return;\r
+    END_OF_LIST(lcur);\r
+\r
+    init_client();\r
+    if (!client)\r
+        return;\r
+\r
+    write_formatstringsdecl(lcur->iface);\r
+\r
+    write_clientinterfacedecl(lcur->iface);\r
+    write_stubdescdecl(lcur->iface);\r
+    write_bindinghandledecl(lcur->iface);\r
+\r
+    write_function_stubs(lcur->iface);\r
+    write_stubdescriptor(lcur->iface);\r
+\r
+    print_client("#if !defined(__RPC_WIN32__)\n");\r
+    print_client("#error  Invalid build platform for this stub.\n");\r
+    print_client("#endif\n");\r
+    fprintf(client, "\n");\r
+\r
+    write_procformatstring(lcur->iface);\r
+    write_typeformatstring();\r
+\r
+    fprintf(client, "\n");\r
+\r
+    fclose(client);\r
+}\r
diff --git a/reactos/tools/widl/client.h b/reactos/tools/widl/client.h
new file mode 100644 (file)
index 0000000..d548348
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2005 Eric Kohl
+ *
+ * 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_CLIENT_H
+#define __WIDL_CLIENT_H
+
+extern void write_client(ifref_t *ifaces);
+
+#endif
index 80b7815..9142e1d 100644 (file)
@@ -39,6 +39,8 @@
 #include "header.h"
 #include "proxy.h"
 #include "typelib.h"
+#include "client.h"
+#include "server.h"
 
 #if defined(YYBYACC)
        /* Berkeley yacc (byacc) doesn't seem to know about these */
@@ -224,7 +226,7 @@ static type_t std_uhyper = { "MIDL_uhyper" };
 
 %%
 
-input:   gbl_statements                        { write_proxies($1); }
+input:   gbl_statements                        { write_proxies($1); write_client($1); write_server($1); }
        ;
 
 gbl_statements:                                        { $$ = NULL; }
diff --git a/reactos/tools/widl/server.c b/reactos/tools/widl/server.c
new file mode 100644 (file)
index 0000000..bd218f7
--- /dev/null
@@ -0,0 +1,433 @@
+/*\r
+ * IDL Compiler\r
+ *\r
+ * Copyright 2005 Eric Kohl\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or (at your option) any later version.\r
+ *\r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Lesser General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ */\r
+\r
+#include "config.h"\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#ifdef HAVE_UNISTD_H\r
+# include <unistd.h>\r
+#endif\r
+#include <string.h>\r
+#include <assert.h>\r
+#include <ctype.h>\r
+#include <signal.h>\r
+\r
+#include "windef.h"\r
+#include "widl.h"\r
+#include "utils.h"\r
+#include "parser.h"\r
+#include "header.h"\r
+\r
+#define END_OF_LIST(list)       \\r
+  do {                          \\r
+    if (list) {                 \\r
+      while (NEXT_LINK(list))   \\r
+        list = NEXT_LINK(list); \\r
+    }                           \\r
+  } while(0)\r
+\r
+static FILE* server;\r
+static int indent = 0;\r
+\r
+\r
+static int print_server(const char *format, ...)\r
+{\r
+    va_list va;\r
+    int i, r;\r
+\r
+    va_start(va, format);\r
+    for (i = 0; i < indent; i++)\r
+        fprintf(server, "    ");\r
+    r = vfprintf(server, format, va);\r
+    va_end(va);\r
+    return r;\r
+}\r
+\r
+\r
+static void write_procformatstring(type_t *iface)\r
+{\r
+    func_t *cur = iface->funcs;\r
+\r
+    print_server("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("0,\n");\r
+    print_server("{\n");\r
+    indent++;\r
+\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        var_t *def = cur->def;\r
+\r
+        if (is_void(def->type, NULL))\r
+        {\r
+            print_server("0x5b,    /* FC_END */\n");\r
+            print_server("0x5c,    /* FC_PAD */\n");\r
+        }\r
+        else\r
+        {\r
+            print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");\r
+            print_server("0x%02x,    /* <type> */\n", def->type->type);\r
+        }\r
+\r
+        cur = PREV_LINK(cur);\r
+    }\r
+\r
+    print_server("0x0\n");\r
+    indent--;\r
+    print_server("}\n");\r
+    indent--;\r
+    print_server("};\n");\r
+    print_server("\n");\r
+}\r
+\r
+\r
+static void write_typeformatstring(void)\r
+{\r
+    print_server("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("0,\n");\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("NdrFcShort(0x0),\n");\r
+    print_server("0x0\n");\r
+    indent--;\r
+    print_server("}\n");\r
+    indent--;\r
+    print_server("};\n");\r
+    print_server("\n");\r
+}\r
+\r
+\r
+static void write_function_stubs(type_t *iface)\r
+{\r
+    func_t *cur = iface->funcs;\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        var_t *def = cur->def;\r
+\r
+        write_type(server, def->type, def, def->tname);\r
+        fprintf(server, " __RPC_STUB\n");\r
+        fprintf(server, "%s_", iface->name);\r
+        write_name(server, def);\r
+        fprintf(server, "(\n");\r
+        indent++;\r
+        print_server("PRPC_MESSAGE _pRpcMessage)\n");\r
+        indent--;\r
+\r
+        /* write the functions body */\r
+        fprintf(server, "{\n");\r
+        indent++;\r
+\r
+        /* declare return value '_RetVal' */\r
+        if (!is_void(def->type, NULL))\r
+        {\r
+            print_server("");\r
+            write_type(server, def->type, def, def->tname);\r
+            fprintf(server, " _RetVal;\n");\r
+        }\r
+\r
+        print_server("MIDL_STUB_MESSAGE _StubMsg;\n");\r
+        print_server("RPC_STATUS _Status;\n");\r
+        fprintf(server, "\n");\r
+        print_server("((void)(_Status));\n");\r
+        print_server("NdrServerInitializeNew(\n");\r
+        indent++;\r
+        print_server("_pRpcMessage,\n");\r
+        print_server("&_StubMsg,\n");\r
+        print_server("&%s_StubDesc);\n", iface->name);\r
+        indent--;\r
+        fprintf(server, "\n");\r
+\r
+        print_server("RpcTryFinally\n");\r
+        print_server("{\n");\r
+        indent++;\r
+        print_server("RpcTryExcept\n");\r
+        print_server("{\n");\r
+        indent++;\r
+        print_server("if (_StubMsg.Buffer > _StubMsg.BufferEnd)\n");\r
+        print_server("{\n");\r
+        indent++;\r
+        print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");\r
+        indent--;\r
+        print_server("}\n");\r
+        indent--;\r
+        print_server("}\n");\r
+        print_server("RpcExcept(RPC_BAD_STUB_DATA_EXCEPTION_FILTER)\n");\r
+        print_server("{\n");\r
+        indent++;\r
+        print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");\r
+        indent--;\r
+        print_server("}\n");\r
+        print_server("RpcEndExcept\n");\r
+        fprintf(server, "\n");\r
+\r
+\r
+        /* Call the real server function */\r
+        if (!is_void(def->type, NULL))\r
+            print_server("_RetVal = ");\r
+        else\r
+            print_server("");\r
+        write_name(server, def);\r
+\r
+        /* FIXME: handle argument list */\r
+        fprintf(server, "();\n");\r
+\r
+        /* FIXME: Marshall the return value */\r
+        if (!is_void(def->type, NULL))\r
+        {\r
+            fprintf(server, "\n");\r
+            print_server("_StubMsg.BufferLength = %uU;\n", 4); /* FIXME */\r
+            print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n");\r
+            fprintf(server, "\n");\r
+            print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n");\r
+            print_server("if (_Status)\n");\r
+            indent++;\r
+            print_server("RpcRaiseException(_Status);\n");\r
+            indent--;\r
+            fprintf(server, "\n");\r
+            print_server("_StubMsg.Buffer = (unsigned char __RPC_FAR *)_pRpcMessage->Buffer;\n");\r
+            fprintf(server, "\n");\r
+\r
+            print_server("*((");\r
+            write_type(server, def->type, def, def->tname);\r
+            fprintf(server, " __RPC_FAR *)_StubMsg.Buffer)++ = _RetVal;\n");\r
+        }\r
+\r
+        indent--;\r
+        print_server("}\n");\r
+        print_server("RpcFinally\n");\r
+        print_server("{\n");\r
+        print_server("}\n");\r
+        print_server("RpcEndFinally\n");\r
+\r
+        /* calculate buffer length */\r
+        fprintf(server, "\n");\r
+        print_server("_pRpcMessage->BufferLength =\n");\r
+        indent++;\r
+        print_server("(unsigned int)((long)_StubMsg.Buffer - (long)_pRpcMessage->Buffer);\n");\r
+        indent--;\r
+        indent--;\r
+        fprintf(server, "}\n");\r
+        fprintf(server, "\n");\r
+\r
+        cur = PREV_LINK(cur);\r
+    }\r
+}\r
+\r
+\r
+static void write_dispatchtable(type_t *iface)\r
+{\r
+    unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);\r
+    unsigned long method_count = 0;\r
+    func_t *cur = iface->funcs;\r
+\r
+    print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name);\r
+    print_server("{\n");\r
+    indent++;\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        var_t *def = cur->def;\r
+\r
+        print_server("%s_", iface->name);\r
+        write_name(server, def);\r
+        fprintf(server, ",\n");\r
+\r
+        method_count++;\r
+        cur = PREV_LINK(cur);\r
+    }\r
+    print_server("0\n");\r
+    indent--;\r
+    print_server("};\n");\r
+    print_server("RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, LOWORD(ver), HIWORD(ver));\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("%u,\n", method_count);\r
+    print_server("%s_table\n", iface->name);\r
+    indent--;\r
+    print_server("};\n");\r
+    fprintf(server, "\n");\r
+}\r
+\r
+\r
+static void write_stubdescdecl(type_t *iface)\r
+{\r
+    print_server("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);\r
+    fprintf(server, "\n");\r
+}\r
+\r
+\r
+static void write_stubdescriptor(type_t *iface)\r
+{\r
+    print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("(void __RPC_FAR *)& %s___RpcServerInterface,\n", iface->name);\r
+    print_server("MIDL_user_allocate,\n");\r
+    print_server("MIDL_user_free,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("__MIDL_TypeFormatString.Format,\n");\r
+    print_server("1, /* -error bounds_check flag */\n");\r
+    print_server("0x10001, /* Ndr library version */\n");\r
+    print_server("0,\n");\r
+    print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,  /* notify & notify_flag routine table */\n");\r
+    print_server("1,  /* Flags */\n");\r
+    print_server("0,  /* Reserved3 */\n");\r
+    print_server("0,  /* Reserved4 */\n");\r
+    print_server("0   /* Reserved5 */\n");\r
+    indent--;\r
+    print_server("};\n");\r
+    fprintf(server, "\n");\r
+}\r
+\r
+\r
+static void write_serverinterfacedecl(type_t *iface)\r
+{\r
+    unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);\r
+    UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);\r
+\r
+    print_server("extern RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, LOWORD(ver), HIWORD(ver));\r
+    fprintf(server, "\n");\r
+    print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name );\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("sizeof(RPC_SERVER_INTERFACE),\n");\r
+    print_server("{{0x%08lx,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n",\r
+                 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],\r
+                 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],\r
+                 uuid->Data4[7], LOWORD(ver), HIWORD(ver));\r
+    print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */\r
+    print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, LOWORD(ver), HIWORD(ver));\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    print_server("0,\n");\r
+    indent--;\r
+    print_server("};\n");\r
+    print_server("RPC_IF_HANDLE %s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",\r
+                 iface->name, LOWORD(ver), HIWORD(ver), iface->name);\r
+    fprintf(server, "\n");\r
+}\r
+\r
+static void write_formatdesc( const char *str )\r
+{\r
+    print_server("typedef struct _MIDL_%s_FORMAT_STRING\n", str );\r
+    print_server("{\n");\r
+    indent++;\r
+    print_server("short Pad;\n");\r
+    print_server("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);\r
+    indent--;\r
+    print_server("} MIDL_%s_FORMAT_STRING;\n", str);\r
+    print_server("\n");\r
+}\r
+\r
+\r
+static void write_formatstringsdecl(type_t *iface)\r
+{\r
+    func_t *cur;\r
+    int byte_count = 1;\r
+\r
+    print_server("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */\r
+\r
+    /* determine the proc format string size */\r
+    cur = iface->funcs;\r
+    while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);\r
+    while (cur)\r
+    {\r
+        byte_count += 2; /* FIXME: determine real size */\r
+        cur = PREV_LINK(cur);\r
+    }\r
+    print_server("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count);\r
+\r
+    fprintf(server, "\n");\r
+    write_formatdesc("TYPE");\r
+    write_formatdesc("PROC");\r
+    fprintf(server, "\n");\r
+    print_server("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");\r
+    print_server("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");\r
+    print_server("\n");\r
+}\r
+\r
+\r
+static void init_server(void)\r
+{\r
+    if (server)\r
+        return;\r
+    if (!(server = fopen(server_name, "w")))\r
+        error("Could not open %s for output\n", server_name);\r
+\r
+    print_server("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name);\r
+    print_server("#include<string.h>\n");\r
+    fprintf(server, "\n");\r
+    print_server("#include\"%s\"\n", header_name);\r
+    fprintf(server, "\n");\r
+}\r
+\r
+\r
+void write_server(ifref_t *ifaces)\r
+{\r
+    ifref_t *lcur = ifaces;\r
+    char *file_id = server_token;\r
+    int c;\r
+\r
+    if (!do_server)\r
+        return;\r
+    if (!lcur)\r
+        return;\r
+    END_OF_LIST(lcur);\r
+\r
+    init_server();\r
+    if (!server)\r
+        return;\r
+\r
+    write_formatstringsdecl(lcur->iface);\r
+    write_serverinterfacedecl(lcur->iface);\r
+    write_stubdescdecl(lcur->iface);\r
+\r
+    write_function_stubs(lcur->iface);\r
+\r
+    write_stubdescriptor(lcur->iface);\r
+    write_dispatchtable(lcur->iface);\r
+\r
+    print_server("#if !defined(__RPC_WIN32__)\n");\r
+    print_server("#error  Invalid build platform for this stub.\n");\r
+    print_server("#endif\n");\r
+    fprintf(server, "\n");\r
+\r
+    write_procformatstring(lcur->iface);\r
+    write_typeformatstring();\r
+\r
+    fprintf(server, "\n");\r
+\r
+    fclose(server);\r
+}\r
diff --git a/reactos/tools/widl/server.h b/reactos/tools/widl/server.h
new file mode 100644 (file)
index 0000000..c96fbe1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2005 Eric Kohl
+ *
+ * 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_SERVER_H
+#define __WIDL_SERVER_H
+
+extern void write_server(ifref_t *ifaces);
+
+#endif
index 973522d..be5d9da 100644 (file)
 /* future options to reserve characters for: */
 /* a = alignment of structures */
 /* A = ACF input filename */
-/* c = client stub only? */
-/* C = client stub filename */
 /* J = do not search standard include path */
 /* O = generate interpreted stubs */
-/* p = proxy only? */
-/* P = proxy filename */
-/* s = server stub only? */
-/* S = server stub filename */
 /* u = UUID file only? */
 /* U = UUID filename */
 /* w = select win16/win32 output (?) */
 
 static char usage[] =
 "Usage: widl [options...] infile.idl\n"
+"   -c          Generate client stub\n"
+"   -C file     Name of client stub file (default is infile_c.c)\n"
 "   -d n        Set debug level to 'n'\n"
 "   -D id[=val] Define preprocessor identifier id=val\n"
 "   -E          Preprocess only\n"
@@ -63,6 +59,10 @@ static char usage[] =
 "   -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"
+"   -p          Generate proxy\n"
+"   -P file     Name of proxy file (default is infile_p.c)\n"
+"   -s          Generate server stub\n"
+"   -S file     Name of server stub file (default is infile_s.c)\n"
 "   -t          Generate typelib\n"
 "   -T file     Name of typelib file (default is infile.tlb)\n"
 "   -V          Print version and exit\n"
@@ -88,6 +88,8 @@ int preprocess_only = 0;
 int do_header = 0;
 int do_typelib = 0;
 int do_proxies = 0;
+int do_client = 0;
+int do_server = 0;
 int no_preprocess = 0;
 
 char *input_name;
@@ -96,6 +98,10 @@ char *header_token;
 char *typelib_name;
 char *proxy_name;
 char *proxy_token;
+char *client_name;
+char *client_token;
+char *server_name;
+char *server_token;
 char *temp_name;
 
 int line_number = 1;
@@ -137,8 +143,15 @@ int main(int argc,char *argv[])
 
   now = time(NULL);
 
-  while((optc = getopt(argc, argv, "d:D:EhH:I:NtT:VW")) != EOF) {
+  while((optc = getopt(argc, argv, "cC:d:D:EhH:I:NpP:sS:tT:VW")) != EOF) {
     switch(optc) {
+    case 'c':
+      do_everything = 0;
+      do_client = 1;
+      break;
+    case 'C':
+      client_name = strdup(optarg);
+      break;
     case 'd':
       debuglevel = strtol(optarg, NULL, 0);
       break;
@@ -162,6 +175,20 @@ int main(int argc,char *argv[])
     case 'N':
       no_preprocess = 1;
       break;
+    case 'p':
+      do_everything = 0;
+      do_proxies = 1;
+      break;
+    case 'P':
+      proxy_name = strdup(optarg);
+      break;
+    case 's':
+      do_everything = 0;
+      do_server = 1;
+      break;
+    case 'S':
+      server_name = strdup(optarg);
+      break;
     case 't':
       do_everything = 0;
       do_typelib = 1;
@@ -182,7 +209,7 @@ int main(int argc,char *argv[])
   }
 
   if(do_everything) {
-      do_header = do_typelib = do_proxies = 1;
+      do_header = do_typelib = do_proxies = do_client = do_server = 1;
   }
   if(optind < argc) {
     input_name = xstrdup(argv[optind]);
@@ -221,6 +248,18 @@ int main(int argc,char *argv[])
     strcat(proxy_name, "_p.c");
   }
 
+  if (!client_name && do_client) {
+    client_name = dup_basename(input_name, ".idl");
+    client_token = xstrdup(client_name);
+    strcat(client_name, "_c.c");
+  }
+
+  if (!server_name && do_server) {
+    server_name = dup_basename(input_name, ".idl");
+    server_token = xstrdup(server_name);
+    strcat(server_name, "_s.c");
+  }
+
   wpp_add_cmdline_define("__WIDL__");
 
   atexit(rm_tempfile);
@@ -284,6 +323,8 @@ int main(int argc,char *argv[])
     exit(1);
   }
   header_name = NULL;
+  client_name = NULL;
+  server_name = NULL;
   return 0;
 }
 
@@ -293,7 +334,11 @@ static void rm_tempfile(void)
   if(temp_name)
     unlink(temp_name);
   if (header_name)
-    unlink( header_name );
+    unlink(header_name);
+  if (client_name)
+    unlink(client_name);
+  if (server_name)
+    unlink(server_name);
 }
 
 static void segvhandler(int sig)
index e951699..b9d6474 100644 (file)
@@ -41,12 +41,18 @@ extern int pedantic;
 extern int do_header;
 extern int do_typelib;
 extern int do_proxies;
+extern int do_client;
+extern int do_server;
 
 extern char *input_name;
 extern char *header_name;
 extern char *typelib_name;
 extern char *proxy_name;
 extern char *proxy_token;
+extern char *client_name;
+extern char *client_token;
+extern char *server_name;
+extern char *server_token;
 extern time_t now;
 
 extern int line_number;
index f9e0997..8bed759 100644 (file)
 #include "header.h"\r
 #include "proxy.h"\r
 #include "typelib.h"\r
+#include "client.h"\r
+#include "server.h"\r
 \r
 #if defined(YYBYACC)\r
        /* Berkeley yacc (byacc) doesn't seem to know about these */\r
@@ -232,7 +234,7 @@ static type_t std_int64 = { "__int64" };
 static type_t std_uhyper = { "MIDL_uhyper" };\r
 \r
 \r
-#line 109 "parser.y"\r
+#line 111 "parser.y"\r
 typedef union {\r
        attr_t *attr;\r
        expr_t *expr;\r
@@ -413,30 +415,30 @@ static const short yyrhs[] = {   141,
 \r
 #if YYDEBUG != 0\r
 static const short yyrline[] = { 0,\r
-   227,   230,   231,   232,   233,   234,   235,   236,   239,   240,\r
-   241,   242,   243,   244,   247,   248,   249,   252,   253,   254,\r
-   255,   256,   257,   258,   259,   260,   263,   265,   268,   271,\r
-   273,   275,   278,   279,   282,   285,   286,   287,   291,   295,\r
-   298,   304,   311,   312,   313,   316,   317,   318,   321,   322,\r
-   325,   329,   330,   331,   334,   336,   337,   338,   339,   340,\r
-   341,   342,   343,   344,   345,   346,   347,   348,   349,   350,\r
-   351,   352,   353,   354,   355,   356,   357,   358,   359,   360,\r
-   361,   362,   363,   364,   365,   366,   367,   368,   369,   370,\r
-   371,   372,   373,   374,   375,   376,   377,   378,   379,   380,\r
-   381,   382,   383,   384,   385,   386,   387,   388,   389,   392,\r
-   393,   396,   397,   402,   406,   412,   419,   420,   421,   424,\r
-   425,   431,   436,   442,   450,   451,   464,   465,   468,   469,\r
-   470,   471,   472,   473,   474,   475,   476,   477,   478,   479,\r
-   480,   481,   482,   483,   484,   485,   488,   489,   492,   497,\r
-   502,   503,   508,   509,   510,   511,   514,   517,   528,   529,\r
-   532,   533,   534,   537,   539,   540,   541,   542,   545,   546,\r
-   547,   548,   549,   561,   562,   563,   564,   565,   568,   569,\r
-   572,   573,   574,   575,   576,   577,   580,   581,   584,   590,\r
-   595,   596,   599,   603,   604,   607,   619,   620,   623,   624,\r
-   627,   642,   643,   646,   647,   650,   658,   666,   673,   676,\r
-   678,   681,   682,   685,   690,   696,   697,   700,   701,   702,\r
-   705,   707,   710,   712,   715,   725,   726,   727,   728,   729,\r
-   730,   731,   732,   733,   734,   737,   749,   753,   766,   768\r
+   229,   232,   233,   234,   235,   236,   237,   238,   241,   242,\r
+   243,   244,   245,   246,   249,   250,   251,   254,   255,   256,\r
+   257,   258,   259,   260,   261,   262,   265,   267,   270,   273,\r
+   275,   277,   280,   281,   284,   287,   288,   289,   293,   297,\r
+   300,   306,   313,   314,   315,   318,   319,   320,   323,   324,\r
+   327,   331,   332,   333,   336,   338,   339,   340,   341,   342,\r
+   343,   344,   345,   346,   347,   348,   349,   350,   351,   352,\r
+   353,   354,   355,   356,   357,   358,   359,   360,   361,   362,\r
+   363,   364,   365,   366,   367,   368,   369,   370,   371,   372,\r
+   373,   374,   375,   376,   377,   378,   379,   380,   381,   382,\r
+   383,   384,   385,   386,   387,   388,   389,   390,   391,   394,\r
+   395,   398,   399,   404,   408,   414,   421,   422,   423,   426,\r
+   427,   433,   438,   444,   452,   453,   466,   467,   470,   471,\r
+   472,   473,   474,   475,   476,   477,   478,   479,   480,   481,\r
+   482,   483,   484,   485,   486,   487,   490,   491,   494,   499,\r
+   504,   505,   510,   511,   512,   513,   516,   519,   530,   531,\r
+   534,   535,   536,   539,   541,   542,   543,   544,   547,   548,\r
+   549,   550,   551,   563,   564,   565,   566,   567,   570,   571,\r
+   574,   575,   576,   577,   578,   579,   582,   583,   586,   592,\r
+   597,   598,   601,   605,   606,   609,   621,   622,   625,   626,\r
+   629,   644,   645,   648,   649,   652,   660,   668,   675,   678,\r
+   680,   683,   684,   687,   692,   698,   699,   702,   703,   704,\r
+   707,   709,   712,   714,   717,   727,   728,   729,   730,   731,\r
+   732,   733,   734,   735,   736,   739,   751,   755,   768,   770\r
 };\r
 #endif\r
 \r
@@ -1368,161 +1370,161 @@ yyreduce:
   switch (yyn) {\r
 \r
 case 1:\r
-#line 227 "parser.y"\r
-{ write_proxies(yyvsp[0].ifref); ;\r
+#line 229 "parser.y"\r
+{ write_proxies(yyvsp[0].ifref); write_client(yyvsp[0].ifref); write_server(yyvsp[0].ifref); ;\r
     break;}\r
 case 2:\r
-#line 230 "parser.y"\r
+#line 232 "parser.y"\r
 { yyval.ifref = NULL; ;\r
     break;}\r
 case 3:\r
-#line 231 "parser.y"\r
+#line 233 "parser.y"\r
 { yyval.ifref = yyvsp[-1].ifref; ;\r
     break;}\r
 case 4:\r
-#line 232 "parser.y"\r
+#line 234 "parser.y"\r
 { yyval.ifref = make_ifref(yyvsp[0].type); LINK(yyval.ifref, yyvsp[-1].ifref); ;\r
     break;}\r
 case 5:\r
-#line 233 "parser.y"\r
+#line 235 "parser.y"\r
 { yyval.ifref = yyvsp[-1].ifref; add_coclass(yyvsp[0].clas); ;\r
     break;}\r
 case 6:\r
-#line 234 "parser.y"\r
+#line 236 "parser.y"\r
 { yyval.ifref = yyvsp[-1].ifref; add_module(yyvsp[0].type); ;\r
     break;}\r
 case 7:\r
-#line 235 "parser.y"\r
+#line 237 "parser.y"\r
 { yyval.ifref = yyvsp[-1].ifref; ;\r
     break;}\r
 case 8:\r
-#line 236 "parser.y"\r
+#line 238 "parser.y"\r
 { yyval.ifref = yyvsp[-1].ifref; ;\r
     break;}\r
 case 9:\r
-#line 239 "parser.y"\r
+#line 241 "parser.y"\r
 {;\r
     break;}\r
 case 10:\r
-#line 240 "parser.y"\r
+#line 242 "parser.y"\r
 { if (!parse_only) add_interface(yyvsp[0].type); ;\r
     break;}\r
 case 11:\r
-#line 241 "parser.y"\r
+#line 243 "parser.y"\r
 { if (!parse_only) add_interface(yyvsp[0].type); ;\r
     break;}\r
 case 12:\r
-#line 242 "parser.y"\r
+#line 244 "parser.y"\r
 { if (!parse_only) add_coclass(yyvsp[0].clas); ;\r
     break;}\r
 case 13:\r
-#line 243 "parser.y"\r
+#line 245 "parser.y"\r
 { if (!parse_only) add_module(yyvsp[0].type); ;\r
     break;}\r
 case 14:\r
-#line 244 "parser.y"\r
+#line 246 "parser.y"\r
 {;\r
     break;}\r
 case 15:\r
-#line 247 "parser.y"\r
+#line 249 "parser.y"\r
 { yyval.func = NULL; ;\r
     break;}\r
 case 16:\r
-#line 248 "parser.y"\r
+#line 250 "parser.y"\r
 { yyval.func = yyvsp[-1].func; LINK(yyval.func, yyvsp[-2].func); ;\r
     break;}\r
 case 17:\r
-#line 249 "parser.y"\r
+#line 251 "parser.y"\r
 { yyval.func = yyvsp[-1].func; ;\r
     break;}\r
 case 18:\r
-#line 252 "parser.y"\r
+#line 254 "parser.y"\r
 {;\r
     break;}\r
 case 19:\r
-#line 253 "parser.y"\r
+#line 255 "parser.y"\r
 { if (!parse_only && do_header) { write_constdef(yyvsp[-1].var); } ;\r
     break;}\r
 case 20:\r
-#line 254 "parser.y"\r
+#line 256 "parser.y"\r
 {;\r
     break;}\r
 case 21:\r
-#line 255 "parser.y"\r
+#line 257 "parser.y"\r
 { if (!parse_only && do_header) { write_type(header, yyvsp[-1].type, NULL, NULL); fprintf(header, ";\n\n"); } ;\r
     break;}\r
 case 22:\r
-#line 256 "parser.y"\r
+#line 258 "parser.y"\r
 { if (!parse_only && do_header) { write_externdef(yyvsp[-1].var); } ;\r
     break;}\r
 case 23:\r
-#line 257 "parser.y"\r
+#line 259 "parser.y"\r
 {;\r
     break;}\r
 case 24:\r
-#line 258 "parser.y"\r
+#line 260 "parser.y"\r
 { if (!parse_only && do_header) { write_type(header, yyvsp[-1].type, NULL, NULL); fprintf(header, ";\n\n"); } ;\r
     break;}\r
 case 25:\r
-#line 259 "parser.y"\r
+#line 261 "parser.y"\r
 {;\r
     break;}\r
 case 26:\r
-#line 260 "parser.y"\r
+#line 262 "parser.y"\r
 { if (!parse_only && do_header) { write_type(header, yyvsp[-1].type, NULL, NULL); fprintf(header, ";\n\n"); } ;\r
     break;}\r
 case 27:\r
-#line 263 "parser.y"\r
+#line 265 "parser.y"\r
 { if (!parse_only && do_header) fprintf(header, "%s\n", yyvsp[-1].str); ;\r
     break;}\r
 case 28:\r
-#line 265 "parser.y"\r
+#line 267 "parser.y"\r
 { assert(yychar == YYEMPTY);\r
                                                  if (!do_import(yyvsp[-1].str)) yychar = aEOF; ;\r
     break;}\r
 case 29:\r
-#line 268 "parser.y"\r
+#line 270 "parser.y"\r
 {;\r
     break;}\r
 case 30:\r
-#line 271 "parser.y"\r
+#line 273 "parser.y"\r
 { yyval.str = yyvsp[0].str; ;\r
     break;}\r
 case 31:\r
-#line 273 "parser.y"\r
+#line 275 "parser.y"\r
 { start_typelib(yyvsp[-1].str, yyvsp[-2].attr); ;\r
     break;}\r
 case 32:\r
-#line 275 "parser.y"\r
+#line 277 "parser.y"\r
 { end_typelib(); ;\r
     break;}\r
 case 33:\r
-#line 278 "parser.y"\r
+#line 280 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 35:\r
-#line 282 "parser.y"\r
+#line 284 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 37:\r
-#line 286 "parser.y"\r
+#line 288 "parser.y"\r
 { LINK(yyvsp[0].var, yyvsp[-2].var); yyval.var = yyvsp[0].var; ;\r
     break;}\r
 case 39:\r
-#line 291 "parser.y"\r
+#line 293 "parser.y"\r
 { yyval.var = yyvsp[-1].var;\r
                                                  set_type(yyval.var, yyvsp[-2].tref, yyvsp[0].expr);\r
                                                  yyval.var->attrs = yyvsp[-3].attr;\r
                                                ;\r
     break;}\r
 case 40:\r
-#line 295 "parser.y"\r
+#line 297 "parser.y"\r
 { yyval.var = yyvsp[-1].var;\r
                                                  set_type(yyval.var, yyvsp[-2].tref, yyvsp[0].expr);\r
                                                ;\r
     break;}\r
 case 41:\r
-#line 298 "parser.y"\r
+#line 300 "parser.y"\r
 { yyval.var = yyvsp[-3].var;\r
                                                  yyval.var->ptr_level--;\r
                                                  set_type(yyval.var, yyvsp[-4].tref, NULL);\r
@@ -1531,7 +1533,7 @@ case 41:
                                                ;\r
     break;}\r
 case 42:\r
-#line 304 "parser.y"\r
+#line 306 "parser.y"\r
 { yyval.var = yyvsp[-3].var;\r
                                                  yyval.var->ptr_level--;\r
                                                  set_type(yyval.var, yyvsp[-4].tref, NULL);\r
@@ -1539,287 +1541,287 @@ case 42:
                                                ;\r
     break;}\r
 case 43:\r
-#line 311 "parser.y"\r
+#line 313 "parser.y"\r
 { yyval.expr = NULL; ;\r
     break;}\r
 case 44:\r
-#line 312 "parser.y"\r
+#line 314 "parser.y"\r
 { yyval.expr = yyvsp[-1].expr; ;\r
     break;}\r
 case 45:\r
-#line 313 "parser.y"\r
+#line 315 "parser.y"\r
 { yyval.expr = make_expr(EXPR_VOID); ;\r
     break;}\r
 case 47:\r
-#line 317 "parser.y"\r
+#line 319 "parser.y"\r
 { LINK(yyvsp[0].expr, yyvsp[-2].expr); yyval.expr = yyvsp[0].expr; ;\r
     break;}\r
 case 48:\r
-#line 318 "parser.y"\r
+#line 320 "parser.y"\r
 { LINK(yyvsp[0].expr, yyvsp[-3].expr); yyval.expr = yyvsp[0].expr; ;\r
     break;}\r
 case 49:\r
-#line 321 "parser.y"\r
+#line 323 "parser.y"\r
 { yyval.attr = NULL; ;\r
     break;}\r
 case 51:\r
-#line 326 "parser.y"\r
+#line 328 "parser.y"\r
 { yyval.attr = yyvsp[-1].attr; ;\r
     break;}\r
 case 53:\r
-#line 330 "parser.y"\r
+#line 332 "parser.y"\r
 { LINK(yyvsp[0].attr, yyvsp[-2].attr); yyval.attr = yyvsp[0].attr; ;\r
     break;}\r
 case 54:\r
-#line 331 "parser.y"\r
+#line 333 "parser.y"\r
 { LINK(yyvsp[0].attr, yyvsp[-3].attr); yyval.attr = yyvsp[0].attr; ;\r
     break;}\r
 case 55:\r
-#line 335 "parser.y"\r
+#line 337 "parser.y"\r
 { yyval.attr = make_attr(ATTR_ASYNC); ;\r
     break;}\r
 case 56:\r
-#line 336 "parser.y"\r
+#line 338 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_CALLAS, yyvsp[-1].var); ;\r
     break;}\r
 case 57:\r
-#line 337 "parser.y"\r
+#line 339 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_CASE, yyvsp[-1].expr); ;\r
     break;}\r
 case 58:\r
-#line 338 "parser.y"\r
+#line 340 "parser.y"\r
 { yyval.attr = make_attrv(ATTR_CONTEXTHANDLE, 0); ;\r
     break;}\r
 case 59:\r
-#line 339 "parser.y"\r
+#line 341 "parser.y"\r
 { yyval.attr = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ ;\r
     break;}\r
 case 60:\r
-#line 340 "parser.y"\r
+#line 342 "parser.y"\r
 { yyval.attr = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ ;\r
     break;}\r
 case 61:\r
-#line 341 "parser.y"\r
+#line 343 "parser.y"\r
 { yyval.attr = make_attr(ATTR_CONTROL); ;\r
     break;}\r
 case 62:\r
-#line 342 "parser.y"\r
+#line 344 "parser.y"\r
 { yyval.attr = make_attr(ATTR_DEFAULT); ;\r
     break;}\r
 case 63:\r
-#line 343 "parser.y"\r
+#line 345 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_DEFAULTVALUE_EXPR, yyvsp[-1].expr); ;\r
     break;}\r
 case 64:\r
-#line 344 "parser.y"\r
+#line 346 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_DEFAULTVALUE_STRING, yyvsp[-1].str); ;\r
     break;}\r
 case 65:\r
-#line 345 "parser.y"\r
+#line 347 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_DLLNAME, yyvsp[-1].str); ;\r
     break;}\r
 case 66:\r
-#line 346 "parser.y"\r
+#line 348 "parser.y"\r
 { yyval.attr = make_attr(ATTR_DUAL); ;\r
     break;}\r
 case 67:\r
-#line 347 "parser.y"\r
+#line 349 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_ENDPOINT, yyvsp[-1].str); ;\r
     break;}\r
 case 68:\r
-#line 348 "parser.y"\r
+#line 350 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_ENTRY_STRING, yyvsp[-1].str); ;\r
     break;}\r
 case 69:\r
-#line 349 "parser.y"\r
+#line 351 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_ENTRY_ORDINAL, yyvsp[-1].expr); ;\r
     break;}\r
 case 70:\r
-#line 350 "parser.y"\r
+#line 352 "parser.y"\r
 { yyval.attr = make_attr(ATTR_HANDLE); ;\r
     break;}\r
 case 71:\r
-#line 351 "parser.y"\r
+#line 353 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_HELPCONTEXT, yyvsp[-1].expr); ;\r
     break;}\r
 case 72:\r
-#line 352 "parser.y"\r
+#line 354 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_HELPFILE, yyvsp[-1].str); ;\r
     break;}\r
 case 73:\r
-#line 353 "parser.y"\r
+#line 355 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_HELPSTRING, yyvsp[-1].str); ;\r
     break;}\r
 case 74:\r
-#line 354 "parser.y"\r
+#line 356 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_HELPSTRINGCONTEXT, yyvsp[-1].expr); ;\r
     break;}\r
 case 75:\r
-#line 355 "parser.y"\r
+#line 357 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_HELPSTRINGDLL, yyvsp[-1].str); ;\r
     break;}\r
 case 76:\r
-#line 356 "parser.y"\r
+#line 358 "parser.y"\r
 { yyval.attr = make_attr(ATTR_HIDDEN); ;\r
     break;}\r
 case 77:\r
-#line 357 "parser.y"\r
+#line 359 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_ID, yyvsp[-1].expr); ;\r
     break;}\r
 case 78:\r
-#line 358 "parser.y"\r
+#line 360 "parser.y"\r
 { yyval.attr = make_attr(ATTR_IDEMPOTENT); ;\r
     break;}\r
 case 79:\r
-#line 359 "parser.y"\r
+#line 361 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_IIDIS, yyvsp[-1].var); ;\r
     break;}\r
 case 80:\r
-#line 360 "parser.y"\r
+#line 362 "parser.y"\r
 { yyval.attr = make_attr(ATTR_IN); ;\r
     break;}\r
 case 81:\r
-#line 361 "parser.y"\r
+#line 363 "parser.y"\r
 { yyval.attr = make_attr(ATTR_INPUTSYNC); ;\r
     break;}\r
 case 82:\r
-#line 362 "parser.y"\r
+#line 364 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_LENGTHIS, yyvsp[-1].expr); ;\r
     break;}\r
 case 83:\r
-#line 363 "parser.y"\r
+#line 365 "parser.y"\r
 { yyval.attr = make_attr(ATTR_LOCAL); ;\r
     break;}\r
 case 84:\r
-#line 364 "parser.y"\r
+#line 366 "parser.y"\r
 { yyval.attr = make_attr(ATTR_NONCREATABLE); ;\r
     break;}\r
 case 85:\r
-#line 365 "parser.y"\r
+#line 367 "parser.y"\r
 { yyval.attr = make_attr(ATTR_OBJECT); ;\r
     break;}\r
 case 86:\r
-#line 366 "parser.y"\r
+#line 368 "parser.y"\r
 { yyval.attr = make_attr(ATTR_ODL); ;\r
     break;}\r
 case 87:\r
-#line 367 "parser.y"\r
+#line 369 "parser.y"\r
 { yyval.attr = make_attr(ATTR_OLEAUTOMATION); ;\r
     break;}\r
 case 88:\r
-#line 368 "parser.y"\r
+#line 370 "parser.y"\r
 { yyval.attr = make_attr(ATTR_OPTIONAL); ;\r
     break;}\r
 case 89:\r
-#line 369 "parser.y"\r
+#line 371 "parser.y"\r
 { yyval.attr = make_attr(ATTR_OUT); ;\r
     break;}\r
 case 90:\r
-#line 370 "parser.y"\r
+#line 372 "parser.y"\r
 { yyval.attr = make_attrv(ATTR_POINTERDEFAULT, yyvsp[-1].num); ;\r
     break;}\r
 case 91:\r
-#line 371 "parser.y"\r
+#line 373 "parser.y"\r
 { yyval.attr = make_attr(ATTR_PROPGET); ;\r
     break;}\r
 case 92:\r
-#line 372 "parser.y"\r
+#line 374 "parser.y"\r
 { yyval.attr = make_attr(ATTR_PROPPUT); ;\r
     break;}\r
 case 93:\r
-#line 373 "parser.y"\r
+#line 375 "parser.y"\r
 { yyval.attr = make_attr(ATTR_PROPPUTREF); ;\r
     break;}\r
 case 94:\r
-#line 374 "parser.y"\r
+#line 376 "parser.y"\r
 { yyval.attr = make_attr(ATTR_PUBLIC); ;\r
     break;}\r
 case 95:\r
-#line 375 "parser.y"\r
+#line 377 "parser.y"\r
 { yyval.attr = make_attr(ATTR_READONLY); ;\r
     break;}\r
 case 96:\r
-#line 376 "parser.y"\r
+#line 378 "parser.y"\r
 { yyval.attr = make_attr(ATTR_RESTRICTED); ;\r
     break;}\r
 case 97:\r
-#line 377 "parser.y"\r
+#line 379 "parser.y"\r
 { yyval.attr = make_attr(ATTR_RETVAL); ;\r
     break;}\r
 case 98:\r
-#line 378 "parser.y"\r
+#line 380 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_SIZEIS, yyvsp[-1].expr); ;\r
     break;}\r
 case 99:\r
-#line 379 "parser.y"\r
+#line 381 "parser.y"\r
 { yyval.attr = make_attr(ATTR_SOURCE); ;\r
     break;}\r
 case 100:\r
-#line 380 "parser.y"\r
+#line 382 "parser.y"\r
 { yyval.attr = make_attr(ATTR_STRING); ;\r
     break;}\r
 case 101:\r
-#line 381 "parser.y"\r
+#line 383 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_SWITCHIS, yyvsp[-1].expr); ;\r
     break;}\r
 case 102:\r
-#line 382 "parser.y"\r
+#line 384 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_SWITCHTYPE, type_ref(yyvsp[-1].tref)); ;\r
     break;}\r
 case 103:\r
-#line 383 "parser.y"\r
+#line 385 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_TRANSMITAS, type_ref(yyvsp[-1].tref)); ;\r
     break;}\r
 case 104:\r
-#line 384 "parser.y"\r
+#line 386 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_UUID, yyvsp[-1].uuid); ;\r
     break;}\r
 case 105:\r
-#line 385 "parser.y"\r
+#line 387 "parser.y"\r
 { yyval.attr = make_attr(ATTR_V1ENUM); ;\r
     break;}\r
 case 106:\r
-#line 386 "parser.y"\r
+#line 388 "parser.y"\r
 { yyval.attr = make_attr(ATTR_VARARG); ;\r
     break;}\r
 case 107:\r
-#line 387 "parser.y"\r
+#line 389 "parser.y"\r
 { yyval.attr = make_attrv(ATTR_VERSION, yyvsp[-1].num); ;\r
     break;}\r
 case 108:\r
-#line 388 "parser.y"\r
+#line 390 "parser.y"\r
 { yyval.attr = make_attrp(ATTR_WIREMARSHAL, type_ref(yyvsp[-1].tref)); ;\r
     break;}\r
 case 109:\r
-#line 389 "parser.y"\r
+#line 391 "parser.y"\r
 { yyval.attr = make_attrv(ATTR_POINTERTYPE, yyvsp[0].num); ;\r
     break;}\r
 case 112:\r
-#line 396 "parser.y"\r
+#line 398 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 113:\r
-#line 397 "parser.y"\r
+#line 399 "parser.y"\r
 { if (yyvsp[0].var) { LINK(yyvsp[0].var, yyvsp[-1].var); yyval.var = yyvsp[0].var; }\r
                                                  else { yyval.var = yyvsp[-1].var; }\r
                                                ;\r
     break;}\r
 case 114:\r
-#line 402 "parser.y"\r
+#line 404 "parser.y"\r
 { attr_t *a = make_attrp(ATTR_CASE, yyvsp[-2].expr);\r
                                                  yyval.var = yyvsp[0].var; if (!yyval.var) yyval.var = make_var(NULL);\r
                                                  LINK(a, yyval.var->attrs); yyval.var->attrs = a;\r
                                                ;\r
     break;}\r
 case 115:\r
-#line 406 "parser.y"\r
+#line 408 "parser.y"\r
 { attr_t *a = make_attr(ATTR_DEFAULT);\r
                                                  yyval.var = yyvsp[0].var; if (!yyval.var) yyval.var = make_var(NULL);\r
                                                  LINK(a, yyval.var->attrs); yyval.var->attrs = a;\r
                                                ;\r
     break;}\r
 case 116:\r
-#line 412 "parser.y"\r
+#line 414 "parser.y"\r
 { yyval.var = reg_const(yyvsp[-2].var);\r
                                                  set_type(yyval.var, yyvsp[-3].tref, NULL);\r
                                                  yyval.var->eval = yyvsp[0].expr;\r
@@ -1827,22 +1829,22 @@ case 116:
                                                ;\r
     break;}\r
 case 117:\r
-#line 419 "parser.y"\r
+#line 421 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 118:\r
-#line 420 "parser.y"\r
+#line 422 "parser.y"\r
 { yyval.var = yyvsp[-1].var; ;\r
     break;}\r
 case 121:\r
-#line 425 "parser.y"\r
+#line 427 "parser.y"\r
 { LINK(yyvsp[0].var, yyvsp[-2].var); yyval.var = yyvsp[0].var;\r
                                                  if (yyvsp[-2].var && !yyvsp[0].var->eval)\r
                                                    yyvsp[0].var->lval = yyvsp[-2].var->lval + 1;\r
                                                ;\r
     break;}\r
 case 122:\r
-#line 431 "parser.y"\r
+#line 433 "parser.y"\r
 { yyval.var = reg_const(yyvsp[-2].var);\r
                                                  yyval.var->eval = yyvsp[0].expr;\r
                                                  yyval.var->lval = yyvsp[0].expr->cval;\r
@@ -1850,14 +1852,14 @@ case 122:
                                                ;\r
     break;}\r
 case 123:\r
-#line 436 "parser.y"\r
+#line 438 "parser.y"\r
 { yyval.var = reg_const(yyvsp[0].var);\r
                                                  yyval.var->lval = 0; /* default for first enum entry */\r
                                                   yyval.var->type = make_type(RPC_FC_LONG, &std_int);\r
                                                ;\r
     break;}\r
 case 124:\r
-#line 442 "parser.y"\r
+#line 444 "parser.y"\r
 { yyval.type = get_typev(RPC_FC_ENUM16, yyvsp[-3].var, tsENUM);\r
                                                  yyval.type->fields = yyvsp[-1].var;\r
                                                  yyval.type->defined = TRUE;\r
@@ -1866,133 +1868,133 @@ case 124:
                                                ;\r
     break;}\r
 case 126:\r
-#line 451 "parser.y"\r
+#line 453 "parser.y"\r
 { LINK(yyvsp[0].expr, yyvsp[-2].expr); yyval.expr = yyvsp[0].expr; ;\r
     break;}\r
 case 127:\r
-#line 464 "parser.y"\r
+#line 466 "parser.y"\r
 { yyval.expr = make_expr(EXPR_VOID); ;\r
     break;}\r
 case 129:\r
-#line 468 "parser.y"\r
+#line 470 "parser.y"\r
 { yyval.expr = make_exprl(EXPR_NUM, yyvsp[0].num); ;\r
     break;}\r
 case 130:\r
-#line 469 "parser.y"\r
+#line 471 "parser.y"\r
 { yyval.expr = make_exprl(EXPR_HEXNUM, yyvsp[0].num); ;\r
     break;}\r
 case 131:\r
-#line 470 "parser.y"\r
+#line 472 "parser.y"\r
 { yyval.expr = make_exprs(EXPR_IDENTIFIER, yyvsp[0].str); ;\r
     break;}\r
 case 132:\r
-#line 471 "parser.y"\r
+#line 473 "parser.y"\r
 { yyval.expr = make_expr3(EXPR_COND, yyvsp[-4].expr, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 133:\r
-#line 472 "parser.y"\r
+#line 474 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_OR , yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 134:\r
-#line 473 "parser.y"\r
+#line 475 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_AND, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 135:\r
-#line 474 "parser.y"\r
+#line 476 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_ADD, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 136:\r
-#line 475 "parser.y"\r
+#line 477 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_SUB, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 137:\r
-#line 476 "parser.y"\r
+#line 478 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_MUL, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 138:\r
-#line 477 "parser.y"\r
+#line 479 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_DIV, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 139:\r
-#line 478 "parser.y"\r
+#line 480 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_SHL, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 140:\r
-#line 479 "parser.y"\r
+#line 481 "parser.y"\r
 { yyval.expr = make_expr2(EXPR_SHR, yyvsp[-2].expr, yyvsp[0].expr); ;\r
     break;}\r
 case 141:\r
-#line 480 "parser.y"\r
+#line 482 "parser.y"\r
 { yyval.expr = make_expr1(EXPR_NOT, yyvsp[0].expr); ;\r
     break;}\r
 case 142:\r
-#line 481 "parser.y"\r
+#line 483 "parser.y"\r
 { yyval.expr = make_expr1(EXPR_NEG, yyvsp[0].expr); ;\r
     break;}\r
 case 143:\r
-#line 482 "parser.y"\r
+#line 484 "parser.y"\r
 { yyval.expr = make_expr1(EXPR_PPTR, yyvsp[0].expr); ;\r
     break;}\r
 case 144:\r
-#line 483 "parser.y"\r
+#line 485 "parser.y"\r
 { yyval.expr = make_exprt(EXPR_CAST, yyvsp[-2].tref, yyvsp[0].expr); ;\r
     break;}\r
 case 145:\r
-#line 484 "parser.y"\r
+#line 486 "parser.y"\r
 { yyval.expr = make_exprt(EXPR_SIZEOF, yyvsp[-1].tref, NULL); ;\r
     break;}\r
 case 146:\r
-#line 485 "parser.y"\r
+#line 487 "parser.y"\r
 { yyval.expr = yyvsp[-1].expr; ;\r
     break;}\r
 case 148:\r
-#line 489 "parser.y"\r
+#line 491 "parser.y"\r
 { LINK(yyvsp[0].expr, yyvsp[-2].expr); yyval.expr = yyvsp[0].expr; ;\r
     break;}\r
 case 149:\r
-#line 492 "parser.y"\r
+#line 494 "parser.y"\r
 { yyval.expr = yyvsp[0].expr;\r
                                                  if (!yyval.expr->is_const) yyerror("expression is not constant\n");\r
                                                ;\r
     break;}\r
 case 150:\r
-#line 497 "parser.y"\r
+#line 499 "parser.y"\r
 { yyval.var = yyvsp[0].var;\r
                                                  set_type(yyval.var, yyvsp[-1].tref, NULL);\r
                                                ;\r
     break;}\r
 case 151:\r
-#line 502 "parser.y"\r
+#line 504 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 152:\r
-#line 503 "parser.y"\r
+#line 505 "parser.y"\r
 { if (yyvsp[0].var) { LINK(yyvsp[0].var, yyvsp[-1].var); yyval.var = yyvsp[0].var; }\r
                                                  else { yyval.var = yyvsp[-1].var; }\r
                                                ;\r
     break;}\r
 case 153:\r
-#line 508 "parser.y"\r
+#line 510 "parser.y"\r
 { yyval.var = yyvsp[-1].var; ;\r
     break;}\r
 case 154:\r
-#line 509 "parser.y"\r
+#line 511 "parser.y"\r
 { yyval.var = make_var(NULL); yyval.var->type = yyvsp[-1].type; yyval.var->attrs = yyvsp[-2].attr; ;\r
     break;}\r
 case 155:\r
-#line 510 "parser.y"\r
+#line 512 "parser.y"\r
 { yyval.var = make_var(NULL); yyval.var->attrs = yyvsp[-1].attr; ;\r
     break;}\r
 case 156:\r
-#line 511 "parser.y"\r
+#line 513 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 157:\r
-#line 514 "parser.y"\r
+#line 516 "parser.y"\r
 { yyval.var = yyvsp[-1].var; set_type(yyval.var, yyvsp[-2].tref, yyvsp[0].expr); yyval.var->attrs = yyvsp[-3].attr; ;\r
     break;}\r
 case 158:\r
-#line 519 "parser.y"\r
+#line 521 "parser.y"\r
 { set_type(yyvsp[-3].var, yyvsp[-5].tref, NULL);\r
                                                  yyvsp[-3].var->attrs = yyvsp[-6].attr;\r
                                                  yyval.func = make_func(yyvsp[-3].var, yyvsp[-1].var);\r
@@ -2002,55 +2004,55 @@ case 158:
                                                ;\r
     break;}\r
 case 159:\r
-#line 528 "parser.y"\r
+#line 530 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 161:\r
-#line 532 "parser.y"\r
+#line 534 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 162:\r
-#line 533 "parser.y"\r
+#line 535 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 163:\r
-#line 534 "parser.y"\r
+#line 536 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 164:\r
-#line 537 "parser.y"\r
+#line 539 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 165:\r
-#line 539 "parser.y"\r
+#line 541 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 166:\r
-#line 540 "parser.y"\r
+#line 542 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 167:\r
-#line 541 "parser.y"\r
+#line 543 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 168:\r
-#line 542 "parser.y"\r
+#line 544 "parser.y"\r
 { yyval.var = make_var(yyvsp[0].str); ;\r
     break;}\r
 case 169:\r
-#line 545 "parser.y"\r
+#line 547 "parser.y"\r
 { yyval.type = make_type(RPC_FC_BYTE, NULL); ;\r
     break;}\r
 case 170:\r
-#line 546 "parser.y"\r
+#line 548 "parser.y"\r
 { yyval.type = make_type(RPC_FC_WCHAR, NULL); ;\r
     break;}\r
 case 172:\r
-#line 548 "parser.y"\r
+#line 550 "parser.y"\r
 { yyval.type = yyvsp[0].type; yyval.type->sign = 1; ;\r
     break;}\r
 case 173:\r
-#line 549 "parser.y"\r
+#line 551 "parser.y"\r
 { yyval.type = yyvsp[0].type; yyval.type->sign = -1;\r
                                                  switch (yyval.type->type) {\r
                                                  case RPC_FC_CHAR:  yyval.type->type = RPC_FC_BYTE; yyval.type->sign = 0; break;\r
@@ -2065,92 +2067,92 @@ case 173:
                                                ;\r
     break;}\r
 case 174:\r
-#line 561 "parser.y"\r
+#line 563 "parser.y"\r
 { yyval.type = make_type(RPC_FC_FLOAT, NULL); ;\r
     break;}\r
 case 175:\r
-#line 562 "parser.y"\r
+#line 564 "parser.y"\r
 { yyval.type = make_type(RPC_FC_DOUBLE, NULL); ;\r
     break;}\r
 case 176:\r
-#line 563 "parser.y"\r
+#line 565 "parser.y"\r
 { yyval.type = make_type(RPC_FC_BYTE, &std_bool); /* ? */ ;\r
     break;}\r
 case 177:\r
-#line 564 "parser.y"\r
+#line 566 "parser.y"\r
 { yyval.type = make_type(RPC_FC_ERROR_STATUS_T, NULL); ;\r
     break;}\r
 case 178:\r
-#line 565 "parser.y"\r
+#line 567 "parser.y"\r
 { yyval.type = make_type(RPC_FC_BIND_PRIMITIVE, NULL); /* ? */ ;\r
     break;}\r
 case 181:\r
-#line 572 "parser.y"\r
+#line 574 "parser.y"\r
 { yyval.type = make_type(RPC_FC_LONG, &std_int); ;\r
     break;}\r
 case 182:\r
-#line 573 "parser.y"\r
+#line 575 "parser.y"\r
 { yyval.type = make_type(RPC_FC_SHORT, NULL); ;\r
     break;}\r
 case 183:\r
-#line 574 "parser.y"\r
+#line 576 "parser.y"\r
 { yyval.type = make_type(RPC_FC_LONG, NULL); ;\r
     break;}\r
 case 184:\r
-#line 575 "parser.y"\r
+#line 577 "parser.y"\r
 { yyval.type = make_type(RPC_FC_HYPER, NULL); ;\r
     break;}\r
 case 185:\r
-#line 576 "parser.y"\r
+#line 578 "parser.y"\r
 { yyval.type = make_type(RPC_FC_HYPER, &std_int64); ;\r
     break;}\r
 case 186:\r
-#line 577 "parser.y"\r
+#line 579 "parser.y"\r
 { yyval.type = make_type(RPC_FC_CHAR, NULL); ;\r
     break;}\r
 case 187:\r
-#line 580 "parser.y"\r
+#line 582 "parser.y"\r
 { yyval.clas = make_class(yyvsp[0].str); ;\r
     break;}\r
 case 188:\r
-#line 581 "parser.y"\r
+#line 583 "parser.y"\r
 { yyval.clas = make_class(yyvsp[0].str); ;\r
     break;}\r
 case 189:\r
-#line 584 "parser.y"\r
+#line 586 "parser.y"\r
 { yyval.clas = yyvsp[0].clas;\r
                                                  yyval.clas->attrs = yyvsp[-1].attr;\r
                                                   if (!parse_only && do_header) write_coclass(yyval.clas);\r
                                                ;\r
     break;}\r
 case 190:\r
-#line 590 "parser.y"\r
+#line 592 "parser.y"\r
 { yyval.clas = yyvsp[-3].clas;\r
                                                  yyval.clas->ifaces = yyvsp[-1].ifref;\r
                                                ;\r
     break;}\r
 case 191:\r
-#line 595 "parser.y"\r
+#line 597 "parser.y"\r
 { yyval.ifref = NULL; ;\r
     break;}\r
 case 192:\r
-#line 596 "parser.y"\r
+#line 598 "parser.y"\r
 { LINK(yyvsp[0].ifref, yyvsp[-1].ifref); yyval.ifref = yyvsp[0].ifref; ;\r
     break;}\r
 case 193:\r
-#line 600 "parser.y"\r
+#line 602 "parser.y"\r
 { yyval.ifref = make_ifref(yyvsp[0].type); yyval.ifref->attrs = yyvsp[-1].attr; ;\r
     break;}\r
 case 194:\r
-#line 603 "parser.y"\r
+#line 605 "parser.y"\r
 { yyval.type = get_type(0, yyvsp[0].str, 0); ;\r
     break;}\r
 case 195:\r
-#line 604 "parser.y"\r
+#line 606 "parser.y"\r
 { yyval.type = get_type(0, yyvsp[0].str, 0); ;\r
     break;}\r
 case 196:\r
-#line 607 "parser.y"\r
+#line 609 "parser.y"\r
 { yyval.type = yyvsp[0].type;\r
                                                  if (yyval.type->defined) yyerror("multiple definition error\n");\r
                                                  yyval.type->attrs = yyvsp[-1].attr;\r
@@ -2163,23 +2165,23 @@ case 196:
                                                ;\r
     break;}\r
 case 197:\r
-#line 619 "parser.y"\r
+#line 621 "parser.y"\r
 { yyval.var = NULL; ;\r
     break;}\r
 case 198:\r
-#line 620 "parser.y"\r
+#line 622 "parser.y"\r
 { LINK(yyvsp[-1].var, yyvsp[-2].var); yyval.var = yyvsp[-1].var; ;\r
     break;}\r
 case 199:\r
-#line 623 "parser.y"\r
+#line 625 "parser.y"\r
 { yyval.func = NULL; ;\r
     break;}\r
 case 200:\r
-#line 624 "parser.y"\r
+#line 626 "parser.y"\r
 { LINK(yyvsp[-1].func, yyvsp[-2].func); yyval.func = yyvsp[-1].func; ;\r
     break;}\r
 case 201:\r
-#line 630 "parser.y"\r
+#line 632 "parser.y"\r
 { yyval.type = yyvsp[-4].type;\r
                                                  yyval.type->fields = yyvsp[-2].var;\r
                                                  yyval.type->funcs = yyvsp[-1].func;\r
@@ -2187,23 +2189,23 @@ case 201:
                                                ;\r
     break;}\r
 case 202:\r
-#line 642 "parser.y"\r
+#line 644 "parser.y"\r
 { yyval.type = NULL; ;\r
     break;}\r
 case 203:\r
-#line 643 "parser.y"\r
+#line 645 "parser.y"\r
 { yyval.type = find_type2(yyvsp[0].str, 0); ;\r
     break;}\r
 case 204:\r
-#line 646 "parser.y"\r
+#line 648 "parser.y"\r
 { yyval.type = get_type(RPC_FC_IP, yyvsp[0].str, 0); ;\r
     break;}\r
 case 205:\r
-#line 647 "parser.y"\r
+#line 649 "parser.y"\r
 { yyval.type = get_type(RPC_FC_IP, yyvsp[0].str, 0); ;\r
     break;}\r
 case 206:\r
-#line 650 "parser.y"\r
+#line 652 "parser.y"\r
 { yyval.type = yyvsp[0].type;\r
                                                  if (yyval.type->defined) yyerror("multiple definition error\n");\r
                                                  yyval.type->attrs = yyvsp[-1].attr;\r
@@ -2212,7 +2214,7 @@ case 206:
                                                ;\r
     break;}\r
 case 207:\r
-#line 659 "parser.y"\r
+#line 661 "parser.y"\r
 { yyval.type = yyvsp[-4].type;\r
                                                  yyval.type->ref = yyvsp[-3].type;\r
                                                  yyval.type->funcs = yyvsp[-1].func;\r
@@ -2220,7 +2222,7 @@ case 207:
                                                ;\r
     break;}\r
 case 208:\r
-#line 667 "parser.y"\r
+#line 669 "parser.y"\r
 { yyval.type = yyvsp[-6].type;\r
                                                  yyval.type->ref = find_type2(yyvsp[-4].str, 0);\r
                                                  if (!yyval.type->ref) yyerror("base class %s not found in import\n", yyvsp[-4].str);\r
@@ -2229,64 +2231,64 @@ case 208:
                                                ;\r
     break;}\r
 case 209:\r
-#line 673 "parser.y"\r
+#line 675 "parser.y"\r
 { yyval.type = yyvsp[0].type; ;\r
     break;}\r
 case 210:\r
-#line 677 "parser.y"\r
+#line 679 "parser.y"\r
 { yyval.type = yyvsp[-1].type; if (!parse_only && do_header) write_forward(yyval.type); ;\r
     break;}\r
 case 211:\r
-#line 678 "parser.y"\r
+#line 680 "parser.y"\r
 { yyval.type = yyvsp[-1].type; if (!parse_only && do_header) write_forward(yyval.type); ;\r
     break;}\r
 case 212:\r
-#line 681 "parser.y"\r
+#line 683 "parser.y"\r
 { yyval.type = make_type(0, NULL); yyval.type->name = yyvsp[0].str; ;\r
     break;}\r
 case 213:\r
-#line 682 "parser.y"\r
+#line 684 "parser.y"\r
 { yyval.type = make_type(0, NULL); yyval.type->name = yyvsp[0].str; ;\r
     break;}\r
 case 214:\r
-#line 685 "parser.y"\r
+#line 687 "parser.y"\r
 { yyval.type = yyvsp[0].type;\r
                                                  yyval.type->attrs = yyvsp[-1].attr;\r
                                                ;\r
     break;}\r
 case 215:\r
-#line 690 "parser.y"\r
+#line 692 "parser.y"\r
 { yyval.type = yyvsp[-3].type;\r
                                                  yyval.type->funcs = yyvsp[-1].func;\r
                                                  /* FIXME: if (!parse_only && do_header) write_module($$); */\r
                                                ;\r
     break;}\r
 case 216:\r
-#line 696 "parser.y"\r
+#line 698 "parser.y"\r
 { yyval.var = yyvsp[0].var; yyval.var->ptr_level++; ;\r
     break;}\r
 case 217:\r
-#line 697 "parser.y"\r
+#line 699 "parser.y"\r
 { yyval.var = yyvsp[0].var; /* FIXME */ ;\r
     break;}\r
 case 220:\r
-#line 702 "parser.y"\r
+#line 704 "parser.y"\r
 { yyval.var = yyvsp[-1].var; ;\r
     break;}\r
 case 222:\r
-#line 707 "parser.y"\r
+#line 709 "parser.y"\r
 { LINK(yyvsp[0].var, yyvsp[-2].var); yyval.var = yyvsp[0].var; ;\r
     break;}\r
 case 223:\r
-#line 711 "parser.y"\r
+#line 713 "parser.y"\r
 { yyval.num = RPC_FC_RP; ;\r
     break;}\r
 case 224:\r
-#line 712 "parser.y"\r
+#line 714 "parser.y"\r
 { yyval.num = RPC_FC_UP; ;\r
     break;}\r
 case 225:\r
-#line 715 "parser.y"\r
+#line 717 "parser.y"\r
 { yyval.type = get_typev(RPC_FC_STRUCT, yyvsp[-3].var, tsSTRUCT);\r
                                                   /* overwrite RPC_FC_STRUCT with a more exact type */\r
                                                  yyval.type->type = get_struct_type( yyvsp[-1].var );\r
@@ -2297,47 +2299,47 @@ case 225:
                                                 ;\r
     break;}\r
 case 226:\r
-#line 725 "parser.y"\r
+#line 727 "parser.y"\r
 { yyval.tref = make_tref(NULL, make_type(0, NULL)); ;\r
     break;}\r
 case 227:\r
-#line 726 "parser.y"\r
+#line 728 "parser.y"\r
 { yyval.tref = make_tref(yyvsp[0].str, find_type(yyvsp[0].str, 0)); ;\r
     break;}\r
 case 228:\r
-#line 727 "parser.y"\r
+#line 729 "parser.y"\r
 { yyval.tref = make_tref(NULL, yyvsp[0].type); ;\r
     break;}\r
 case 229:\r
-#line 728 "parser.y"\r
+#line 730 "parser.y"\r
 { yyval.tref = uniq_tref(yyvsp[0].tref); yyval.tref->ref->is_const = TRUE; ;\r
     break;}\r
 case 230:\r
-#line 729 "parser.y"\r
+#line 731 "parser.y"\r
 { yyval.tref = make_tref(NULL, yyvsp[0].type); ;\r
     break;}\r
 case 231:\r
-#line 730 "parser.y"\r
+#line 732 "parser.y"\r
 { yyval.tref = make_tref(NULL, find_type2(yyvsp[0].str, tsENUM)); ;\r
     break;}\r
 case 232:\r
-#line 731 "parser.y"\r
+#line 733 "parser.y"\r
 { yyval.tref = make_tref(NULL, yyvsp[0].type); ;\r
     break;}\r
 case 233:\r
-#line 732 "parser.y"\r
+#line 734 "parser.y"\r
 { yyval.tref = make_tref(NULL, get_type(RPC_FC_STRUCT, yyvsp[0].str, tsSTRUCT)); ;\r
     break;}\r
 case 234:\r
-#line 733 "parser.y"\r
+#line 735 "parser.y"\r
 { yyval.tref = make_tref(NULL, yyvsp[0].type); ;\r
     break;}\r
 case 235:\r
-#line 734 "parser.y"\r
+#line 736 "parser.y"\r
 { yyval.tref = make_tref(NULL, find_type2(yyvsp[0].str, tsUNION)); ;\r
     break;}\r
 case 236:\r
-#line 737 "parser.y"\r
+#line 739 "parser.y"\r
 { typeref_t *tref = uniq_tref(yyvsp[-1].tref); \r
                                                  yyvsp[0].var->tname = tref->name;\r
                                                  tref->name = NULL;\r
@@ -2350,14 +2352,14 @@ case 236:
                                                ;\r
     break;}\r
 case 237:\r
-#line 749 "parser.y"\r
+#line 751 "parser.y"\r
 { yyval.type = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, yyvsp[-3].var, tsUNION);\r
                                                  yyval.type->fields = yyvsp[-1].var;\r
                                                  yyval.type->defined = TRUE;\r
                                                ;\r
     break;}\r
 case 238:\r
-#line 755 "parser.y"\r
+#line 757 "parser.y"\r
 { var_t *u = yyvsp[-3].var;\r
                                                  yyval.type = get_typev(RPC_FC_ENCAPSULATED_UNION, yyvsp[-8].var, tsUNION);\r
                                                  if (!u) u = make_var("tagged_union");\r
@@ -2369,11 +2371,11 @@ case 238:
                                                ;\r
     break;}\r
 case 239:\r
-#line 767 "parser.y"\r
+#line 769 "parser.y"\r
 { yyval.num = MAKELONG(yyvsp[0].num, 0); ;\r
     break;}\r
 case 240:\r
-#line 768 "parser.y"\r
+#line 770 "parser.y"\r
 { yyval.num = MAKELONG(yyvsp[-2].num, yyvsp[0].num); ;\r
     break;}\r
 }\r
@@ -2598,7 +2600,7 @@ yyerrhandle:
     }\r
   return 1;\r
 }\r
-#line 771 "parser.y"\r
+#line 773 "parser.y"\r
 \r
 \r
 static attr_t *make_attr(enum attr_type type)\r