diff --git a/reactos/tools/widl_20080105/client.c b/reactos/tools/widl_20080105/client.c new file mode 100644 index 00000000000..5cd2a81800b --- /dev/null +++ b/reactos/tools/widl_20080105/client.c @@ -0,0 +1,447 @@ +/* + * IDL Compiler + * + * Copyright 2005-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" + +#include "widltypes.h" +#include "typegen.h" + +static FILE* client; +static int indent = 0; + +static void print_client( const char *format, ... ) +{ + va_list va; + va_start(va, format); + print(client, indent, format, va); + va_end(va); +} + + +static void check_pointers(const func_t *func) +{ + const var_t *var; + + if (!func->args) + return; + + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + { + if (is_var_ptr(var) && cant_be_null(var)) + { + print_client("if (!%s)\n", var->name); + print_client("{\n"); + indent++; + print_client("RpcRaiseException(RPC_X_NULL_REF_POINTER);\n"); + indent--; + print_client("}\n\n"); + } + } +} + +static void write_function_stubs(type_t *iface, unsigned int *proc_offset) +{ + const func_t *func; + const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE); + const var_t *var; + int method_count = 0; + + if (!implicit_handle) + print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n\n", iface->name); + + if (iface->funcs) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry ) + { + const var_t *def = func->def; + const var_t* explicit_handle_var; + + /* check for a defined binding handle */ + explicit_handle_var = get_explicit_handle_var(func); + if (explicit_handle) + { + if (!explicit_handle_var) + { + error("%s() does not define an explicit binding handle!\n", def->name); + return; + } + } + else if (implicit_handle) + { + if (explicit_handle_var) + { + error("%s() must not define a binding handle!\n", def->name); + return; + } + } + + write_type_decl_left(client, def->type); + if (needs_space_after(def->type)) + fprintf(client, " "); + write_prefix_name(client, prefix_client, def); + fprintf(client, "(\n"); + indent++; + if (func->args) + write_args(client, func->args, iface->name, 0, TRUE); + else + print_client("void"); + fprintf(client, ")\n"); + indent--; + + /* write the functions body */ + fprintf(client, "{\n"); + indent++; + + /* declare return value '_RetVal' */ + if (!is_void(def->type)) + { + print_client(""); + write_type_decl_left(client, def->type); + fprintf(client, " _RetVal;\n"); + } + + if (implicit_handle || explicit_handle_var) + print_client("RPC_BINDING_HANDLE _Handle = 0;\n"); + + print_client("RPC_MESSAGE _RpcMessage;\n"); + print_client("MIDL_STUB_MESSAGE _StubMsg;\n"); + if (!is_void(def->type) && decl_indirect(def->type)) + { + print_client("void *_p_%s = &%s;\n", + "_RetVal", "_RetVal"); + } + fprintf(client, "\n"); + + /* check pointers */ + check_pointers(func); + + print_client("RpcTryFinally\n"); + print_client("{\n"); + indent++; + + print_client("NdrClientInitializeNew(\n"); + indent++; + print_client("(PRPC_MESSAGE)&_RpcMessage,\n"); + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(PMIDL_STUB_DESC)&%s_StubDesc,\n", iface->name); + print_client("%d);\n", method_count); + indent--; + fprintf(client, "\n"); + + if (implicit_handle) + { + print_client("_Handle = %s;\n", implicit_handle); + fprintf(client, "\n"); + } + else if (explicit_handle_var) + { + print_client("_Handle = %s;\n", explicit_handle_var->name); + fprintf(client, "\n"); + } + + write_remoting_arguments(client, indent, func, PASS_IN, PHASE_BUFFERSIZE); + + print_client("NdrGetBuffer(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("_StubMsg.BufferLength,\n"); + if (implicit_handle || explicit_handle_var) + print_client("_Handle);\n"); + else + print_client("%s__MIDL_AutoBindHandle);\n", iface->name); + indent--; + fprintf(client, "\n"); + + /* marshal arguments */ + write_remoting_arguments(client, indent, func, PASS_IN, PHASE_MARSHAL); + + /* send/receive message */ + /* print_client("NdrNsSendReceive(\n"); */ + /* print_client("(unsigned char *)_StubMsg.Buffer,\n"); */ + /* print_client("(RPC_BINDING_HANDLE *) &%s__MIDL_AutoBindHandle);\n", iface->name); */ + print_client("NdrSendReceive(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(unsigned char *)_StubMsg.Buffer);\n\n"); + indent--; + + print_client("_StubMsg.BufferStart = (unsigned char *)_RpcMessage.Buffer;\n"); + print_client("_StubMsg.BufferEnd = _StubMsg.BufferStart + _RpcMessage.BufferLength;\n"); + + if (has_out_arg_or_return(func)) + { + fprintf(client, "\n"); + + print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); + indent++; + print_client("NdrConvert(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", *proc_offset); + indent -= 2; + } + + /* unmarshall arguments */ + fprintf(client, "\n"); + write_remoting_arguments(client, indent, func, PASS_OUT, PHASE_UNMARSHAL); + + /* unmarshal return value */ + if (!is_void(def->type)) + { + if (decl_indirect(def->type)) + print_client("MIDL_memset(&%s, 0, sizeof(%s));\n", "_RetVal", "_RetVal"); + else if (is_ptr(def->type) || is_array(def->type)) + print_client("%s = 0;\n", "_RetVal"); + write_remoting_arguments(client, indent, func, PASS_RETURN, PHASE_UNMARSHAL); + } + + /* update proc_offset */ + if (func->args) + { + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + *proc_offset += get_size_procformatstring_var(var); + } + if (!is_void(def->type)) + *proc_offset += get_size_procformatstring_var(def); + else + *proc_offset += 2; /* FC_END and FC_PAD */ + + indent--; + print_client("}\n"); + print_client("RpcFinally\n"); + print_client("{\n"); + indent++; + + + /* FIXME: emit client finally code */ + + print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n"); + + indent--; + print_client("}\n"); + print_client("RpcEndFinally\n"); + + + /* emit return code */ + if (!is_void(def->type)) + { + fprintf(client, "\n"); + print_client("return _RetVal;\n"); + } + + indent--; + fprintf(client, "}\n"); + fprintf(client, "\n"); + + method_count++; + } +} + + +static void write_stubdescdecl(type_t *iface) +{ + print_client("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name); + fprintf(client, "\n"); +} + + +static void write_stubdescriptor(type_t *iface, int expr_eval_routines) +{ + const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + + print_client("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name); + print_client("{\n"); + indent++; + print_client("(void *)& %s___RpcClientInterface,\n", iface->name); + print_client("MIDL_user_allocate,\n"); + print_client("MIDL_user_free,\n"); + print_client("{\n"); + indent++; + if (implicit_handle) + print_client("&%s,\n", implicit_handle); + else + print_client("&%s__MIDL_AutoBindHandle,\n", iface->name); + indent--; + print_client("},\n"); + print_client("0,\n"); + print_client("0,\n"); + if (expr_eval_routines) + print_client("ExprEvalRoutines,\n"); + else + print_client("0,\n"); + print_client("0,\n"); + print_client("__MIDL_TypeFormatString.Format,\n"); + print_client("1, /* -error bounds_check flag */\n"); + print_client("0x10001, /* Ndr library version */\n"); + print_client("0,\n"); + print_client("0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_client("0,\n"); + print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); + print_client("0, /* notify & notify_flag routine table */\n"); + print_client("1, /* Flags */\n"); + print_client("0, /* Reserved3 */\n"); + print_client("0, /* Reserved4 */\n"); + print_client("0 /* Reserved5 */\n"); + indent--; + print_client("};\n"); + fprintf(client, "\n"); +} + + +static void write_clientinterfacedecl(type_t *iface) +{ + unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT); + + if (endpoints) write_endpoints( client, iface->name, endpoints ); + + print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name ); + print_client("{\n"); + indent++; + print_client("sizeof(RPC_CLIENT_INTERFACE),\n"); + 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", + uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], + uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], + uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver)); + print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */ + print_client("0,\n"); + if (endpoints) + { + print_client("%u,\n", list_count(endpoints)); + print_client("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name); + } + else + { + print_client("0,\n"); + print_client("0,\n"); + } + print_client("0,\n"); + print_client("0,\n"); + print_client("0,\n"); + indent--; + print_client("};\n"); + if (old_names) + print_client("RPC_IF_HANDLE %s_ClientIfHandle = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", + iface->name, iface->name); + else + print_client("RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n", + prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name); + fprintf(client, "\n"); +} + + +static void write_implicithandledecl(type_t *iface) +{ + const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + + if (implicit_handle) + { + fprintf(client, "handle_t %s;\n", implicit_handle); + fprintf(client, "\n"); + } +} + + +static void init_client(void) +{ + if (client) return; + if (!(client = fopen(client_name, "w"))) + error("Could not open %s for output\n", client_name); + + print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); + print_client("#include \n"); + print_client("#ifdef _ALPHA_\n"); + print_client("#include \n"); + print_client("#endif\n"); + fprintf(client, "\n"); + print_client("#include \"%s\"\n", header_name); + fprintf(client, "\n"); +} + + +void write_client(ifref_list_t *ifaces) +{ + unsigned int proc_offset = 0; + int expr_eval_routines; + ifref_t *iface; + + if (!do_client) + return; + if (do_everything && !need_stub_files(ifaces)) + return; + + init_client(); + if (!client) + return; + + write_formatstringsdecl(client, indent, ifaces, need_stub); + expr_eval_routines = write_expr_eval_routines(client, client_token); + if (expr_eval_routines) + write_expr_eval_routine_list(client, client_token); + write_user_quad_list(client); + + if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, ifref_t, entry ) + { + if (!need_stub(iface->iface)) + continue; + + fprintf(client, "/*****************************************************************************\n"); + fprintf(client, " * %s interface\n", iface->iface->name); + fprintf(client, " */\n"); + fprintf(client, "\n"); + + if (iface->iface->funcs) + { + write_implicithandledecl(iface->iface); + + write_clientinterfacedecl(iface->iface); + write_stubdescdecl(iface->iface); + write_function_stubs(iface->iface, &proc_offset); + + print_client("#if !defined(__RPC_WIN32__)\n"); + print_client("#error Invalid build platform for this stub.\n"); + print_client("#endif\n"); + + fprintf(client, "\n"); + write_stubdescriptor(iface->iface, expr_eval_routines); + } + } + + fprintf(client, "\n"); + + write_procformatstring(client, ifaces, need_stub); + write_typeformatstring(client, ifaces, need_stub); + + fclose(client); +} diff --git a/reactos/tools/widl_20080105/hash.c b/reactos/tools/widl_20080105/hash.c new file mode 100644 index 00000000000..46eafeed9fa --- /dev/null +++ b/reactos/tools/widl_20080105/hash.c @@ -0,0 +1,622 @@ +/* + * Oleaut32 hash functions + * + * Copyright 1999 Corel Corporation + * Copyright 2001-2003 Jon Griffiths + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" + +#include "hash.h" + +static const unsigned char Lookup_16[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + + /* Windows */ + 0x7F, 0x7F, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x8C, + 0x7F, 0x7F, 0x7F, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x7F, 0x7F, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55, + 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, + 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x55, 0xDE, 0x55, + + /* Mac */ + 0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0x41, 0x4F, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0x41, 0x4F, 0xBD, 0x41, 0x4F, 0xC0, + 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x41, 0x41, 0x4F, + 0xCE, 0xCE, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x55, 0x55, 0xDA, + 0xDB, 0xDC, 0xDD, 0x3F, 0x3F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x41, 0x45, 0x41, + 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F, 0x3F, 0x4F, 0x55, 0x55, 0x55, + 0x49, 0x7F, 0xF7, 0x7F, 0xF9, 0xFA, 0xFB, 0x3F, 0xFD, 0xFE, 0x7F +}; + +static const unsigned char Lookup_32[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + + /* Windows */ + 0x7F, 0x7F, 0x82, 0x7F, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x53, + 0x54, 0x5A, 0x5A, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x7F, 0x99, + 0x53, 0x9B, 0x53, 0x54, 0x5A, 0x5A, 0xA0, 0x7F, 0xA2, 0x4C, 0xA4, 0x41, 0xA6, + 0xA7, 0xA8, 0xA9, 0x53, 0xAB, 0xAC, 0x96, 0xAE, 0x5A, 0xB0, 0xB1, 0xB2, 0x4C, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x41, 0x53, 0xBB, 0x4C, 0xBD, 0x4C, 0x5A, 0x52, + 0x41, 0x41, 0x41, 0x41, 0x4C, 0x43, 0x43, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, + 0x49, 0x44, 0xD0, 0x4E, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x52, 0x55, 0x55, + 0x55, 0x55, 0x59, 0x54, 0xDF, 0x52, 0x41, 0x41, 0x41, 0x41, 0x4C, 0x43, 0x43, + 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x44, 0xD0, 0x4E, 0x4E, 0x4F, 0x4F, + 0x4F, 0x4F, 0xF7, 0x52, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0xFF, + + /* Mac */ + 0x41, 0x41, 0x41, 0x45, 0x41, 0x4F, 0x55, 0x41, 0x41, 0x43, 0x41, 0x43, 0x43, + 0x43, 0x45, 0x5A, 0x5A, 0x44, 0x49, 0x44, 0x45, 0x45, 0x45, 0x4F, 0x45, 0x4F, + 0x4F, 0x4F, 0x55, 0x45, 0x45, 0x55, 0xA0, 0xA1, 0x45, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0x45, 0xAC, 0xAD, 0x47, 0x49, 0x49, 0x49, 0xB2, 0xB3, + 0x49, 0x4B, 0xB6, 0xB7, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4E, 0x4E, + 0x4E, 0xC2, 0xC3, 0x4E, 0x4E, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0x4E, 0x4F, 0x4F, + 0x4F, 0x4F, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x4F, 0x52, 0x52, + 0x52, 0xDC, 0xDD, 0x52, 0x52, 0x52, 0x53, 0xE2, 0xE3, 0x53, 0x53, 0x53, 0x41, + 0x54, 0x54, 0x49, 0x5A, 0x5A, 0x55, 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x55, + 0x55, 0x55, 0x55, 0x59, 0x59, 0x4B, 0x5A, 0x4C, 0x4C, 0x47, 0xFF +}; + +static const unsigned char Lookup_48[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + + /* Windows */ + 0x7F, 0x7F, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x7F, 0x89, 0x53, 0x8B, 0x8C, + 0x7F, 0x7F, 0x7F, 0x7F, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x96, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x7F, 0x7F, 0x59, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55, + 0x55, 0x55, 0x59, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, + 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0xDE, 0x59, + + /* Mac */ + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, + 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAB, 0xAD, 0xAE, 0xAE, 0xB0, 0xB1, 0xB2, 0xB3, + 0xA7, 0xB5, 0xB6, 0xB7, 0xB8, 0xB8, 0xBA, 0xBA, 0xBC, 0xBC, 0xBE, 0xBE, 0xB7, + 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCB, 0xCD, + 0xCD, 0xC1, 0xD0, 0xD0, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD8, 0xDA, + 0xDA, 0xDC, 0xDD, 0xDD, 0x9F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, + 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F +}; + +static const unsigned char Lookup_64[128 * 3] = { + /* Common */ + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + +/* Windows */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55, + 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + /* Mac */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x96, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0xD7, 0x4F, 0x55, 0x55, + 0x55, 0x55, 0x55, 0xDE, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const unsigned char Lookup_80[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + +/* Windows */ + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + + /* Mac */ + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, +}; + +static const unsigned char Lookup_112[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x00, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x56, 0x58, 0x55, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + +/* Windows */ + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, + + /* Mac */ + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, +}; + +static const unsigned char Lookup_128[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00, + +/* Windows */ + 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x00, 0x8B, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x00, 0x99, + 0x00, 0x9B, 0x00, 0x00, 0x00, 0x00, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x00, 0xAB, 0xAC, 0x2D, 0xAE, 0x2D, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xBA, + 0xA2, 0xC2, 0xC3, 0xC4, 0xB8, 0xC6, 0xB9, 0xC8, 0xBA, 0xCA, 0xCB, 0xCC, 0xCD, + 0xCE, 0xBC, 0xD0, 0xD1, 0x00, 0xD3, 0xD4, 0xBE, 0xD6, 0xD7, 0xD8, 0xBF, 0xBA, + 0xBE, 0xA2, 0xB8, 0xB9, 0xBA, 0xBE, 0xA2, 0xC2, 0xC3, 0xC4, 0xB8, 0xC6, 0xB9, + 0xC8, 0xBA, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xBC, 0xD0, 0xD1, 0xD3, 0xD3, 0xD4, + 0xBE, 0xD6, 0xD7, 0xD8, 0xBF, 0xBA, 0xBE, 0xBC, 0xBE, 0xBF, 0x00, + + /* Mac */ + 0x41, 0x31, 0x32, 0x45, 0x33, 0x4F, 0x55, 0x87, 0x41, 0x41, 0x41, 0x00, 0x8C, + 0x43, 0x45, 0x45, 0x45, 0x45, 0x92, 0x93, 0x49, 0x49, 0x96, 0x97, 0x98, 0x4F, + 0x4F, 0x9B, 0x3F, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xAB, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xB0, + 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x09, 0xBD, 0xCC, 0xB0, + 0xB6, 0xCF, 0x2D, 0x2D, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xB8, 0xAB, 0xC3, 0xBD, + 0xB6, 0xB8, 0xAB, 0xC3, 0xBF, 0xBD, 0xB0, 0xB5, 0xBE, 0xA2, 0xB6, 0xBC, 0xA1, + 0xB8, 0xAB, 0xA5, 0xBA, 0xA4, 0xBB, 0xC1, 0xC3, 0xA6, 0xBF, 0xC4, 0xAA, 0xC6, + 0xA3, 0xBF, 0xAA, 0xCC, 0xBD, 0xB7, 0xAB, 0xBD, 0xAB, 0xBD, 0x3F, +}; + +static const unsigned char Lookup_144[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00, + +/* Windows */ + 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, + 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0xDA, + 0x55, 0x55, 0xDD, 0xDE, 0xDF, 0x41, 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, + 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, + 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0xDA, 0x55, 0x55, 0xDD, 0xDE, 0x59, + + /* Mac */ + 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, + 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0xDA, + 0x55, 0x55, 0xDD, 0xDE, 0xDF, 0x41, 0xC1, 0x41, 0x41, 0x41, 0x41, 0xC6, 0x43, + 0x45, 0xC9, 0x45, 0x45, 0x49, 0xCD, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0xD3, 0x4F, + 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0xDA, 0x55, 0x55, 0xDD, 0xDE, 0x59, +}; + +static const unsigned char Lookup_160[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00, + +/* Windows */ + 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0x4F, 0x55, 0x55, + 0x55, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, + 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0xD6, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0xDC, 0xDD, 0xDE, 0x59, + + /* Mac */ + 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0x4F, 0x55, 0x55, + 0x55, 0xDC, 0xDD, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0xC6, 0xC7, + 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0xD0, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0xD6, 0xF7, 0x4F, 0x55, 0x55, 0x55, 0xDC, 0xDD, 0xDE, 0x59, +}; + +static const unsigned char Lookup_176[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x00, + + /* Windows */ + 0x00, 0x00, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x00, 0x89, 0x53, 0x8B, 0x8C, + 0x00, 0x00, 0x00, 0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x2D, 0x2D, 0x98, 0x99, + 0x53, 0x9B, 0x8C, 0x00, 0x00, 0x59, 0x09, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0x41, 0xAB, 0xAC, 0x2D, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0x4F, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0x41, + 0x41, 0x41, 0x41, 0xC4, 0xC5, 0xC4, 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, + 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0xD6, 0xD7, 0xD6, 0x55, 0x55, + 0x55, 0x59, 0x59, 0xDE, 0xDF, 0x41, 0x41, 0x41, 0x41, 0xC4, 0xC5, 0xC4, 0x43, + 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x44, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0xD6, 0xF7, 0xD6, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0x59, + + /* Mac */ + 0x80, 0x81, 0x43, 0x45, 0x4E, 0x85, 0x59, 0x41, 0x41, 0x41, 0x80, 0x41, 0x81, + 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F, + 0x85, 0x4F, 0x55, 0x55, 0x55, 0x59, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0x80, 0x85, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0x41, 0x4F, 0xBD, 0x80, 0x85, 0xC0, + 0xC1, 0xC2, 0xC3, 0x46, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0x09, 0x41, 0x41, 0x4F, + 0xCE, 0xCE, 0x2D, 0x2D, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0x59, 0x59, 0xDA, + 0xDB, 0xDC, 0xDD, 0x3F, 0x3F, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0x41, 0x45, 0x41, + 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4F, 0x4F, 0x3F, 0x4F, 0x55, 0x55, 0x55, + 0x49, 0x00, 0xF7, 0x00, 0xF9, 0xFA, 0xFB, 0x3F, 0xFD, 0xFE, 0x00 +}; + +static const unsigned char Lookup_208[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + +/* Windows */ + 0x80, 0x81, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x5E, 0x89, 0x8A, 0x8B, 0x8C, + 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x9B, 0x8C, 0x9D, 0x00, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, + 0xC1, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC7, 0xC8, 0xC9, 0xC9, 0xCB, 0xCC, 0xCD, + 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xDB, 0x00, 0xDD, 0xDE, 0xDF, 0x41, 0xE1, 0x41, 0xE3, 0xE4, 0xE5, 0xE6, 0x43, + 0x45, 0x45, 0x45, 0x45, 0xEC, 0xEC, 0x49, 0x49, 0xF0, 0xF1, 0xF2, 0xF3, 0x4F, + 0xF5, 0xF6, 0xF7, 0xF8, 0x55, 0xFA, 0x55, 0x55, 0x00, 0x00, 0xFF, + + /* Mac */ + 0x41, 0x81, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x8B, 0x8C, + 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x93, 0x49, 0x49, 0x4E, 0x4F, 0x98, 0x4F, + 0x4F, 0x9B, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, + 0xC1, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC7, 0xC8, 0xC9, 0xC9, 0xCB, 0xCC, 0xCD, + 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0x00, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xE9, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +}; + +static const unsigned char Lookup_224[128 * 3] = { + /* Common */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, + 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + +/* Windows */ + 0x80, 0x81, 0x82, 0x46, 0x84, 0x85, 0x86, 0x87, 0x5E, 0x89, 0x8A, 0x8B, 0x8C, + 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, + 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0x32, 0x33, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0x31, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, + 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, + 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEA, 0xEC, 0xED, 0xED, 0xEF, 0xEF, 0xF1, 0xF2, 0xF3, 0xF3, + 0xF5, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0x00, 0x00, 0xFF, + + /* Mac */ + 0x41, 0x41, 0x43, 0x45, 0x4E, 0x4F, 0x55, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, + 0x43, 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, 0x4E, 0x4F, 0x4F, 0x4F, + 0x4F, 0x4F, 0x55, 0x55, 0x55, 0x55, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, + 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, 0xC0, + 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, + 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, + 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEA, 0xEC, 0xED, 0xED, 0xEF, 0xEF, 0xF1, 0xF2, 0xF3, 0xF3, + 0xF5, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, +}; + +/*********************************************************************** + * lhash_val_of_name_sys + * + * Copy of oleaut32.LHashValOfNameSysA + * Produce a string hash value. + * + * PARAMS + * skind [I] Type of the system. + * lcid [I] Locale id for the hash. + * lpStr [I] String to hash. + * + * RETURNS + * Success: The hash value of the string. + * Failure: 0, if lpStr is NULL. + * + * NOTES + * This function produces a two part hash: The high word is based on + * skind and lcid, while the low word is based on a repeated string + * hash of skind/str. + */ +unsigned long lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr) +{ + ULONG nOffset, nMask = skind == SYS_MAC ? 1 : 0; + ULONG nHiWord, nLoWord = 0x0deadbee; + const unsigned char *str = (const unsigned char *)lpStr, *pnLookup = NULL; + + if (!str) + return 0; + + switch (PRIMARYLANGID(LANGIDFROMLCID(lcid))) + { + default: + fprintf(stderr, "Unknown lcid %x, treating as latin-based, please report\n", lcid); + /* .. Fall Through .. */ + case LANG_AFRIKAANS: case LANG_ALBANIAN: case LANG_ARMENIAN: + case LANG_ASSAMESE: case LANG_AZERI: case LANG_BASQUE: + case LANG_BELARUSIAN: case LANG_BENGALI: case LANG_BULGARIAN: + case LANG_CATALAN: case LANG_DANISH: case LANG_DIVEHI: + case LANG_DUTCH: case LANG_ENGLISH: case LANG_ESTONIAN: + case LANG_FAEROESE: case LANG_FINNISH: case LANG_FRENCH: + case LANG_GALICIAN: case LANG_GEORGIAN: case LANG_GERMAN: + case LANG_GUJARATI: case LANG_HINDI: case LANG_INDONESIAN: + case LANG_ITALIAN: case LANG_KANNADA: case LANG_KASHMIRI: + case LANG_KAZAK: case LANG_KONKANI: case LANG_KYRGYZ: + case LANG_LATVIAN: case LANG_LITHUANIAN: case LANG_MACEDONIAN: + case LANG_MALAY: case LANG_MALAYALAM: case LANG_MANIPURI: + case LANG_MARATHI: case LANG_MONGOLIAN: case LANG_NEPALI: + case LANG_ORIYA: case LANG_PORTUGUESE: case LANG_PUNJABI: + case LANG_ROMANIAN: case LANG_SANSKRIT: case LANG_SERBIAN: + case LANG_SINDHI: case LANG_SLOVENIAN: case LANG_SWAHILI: + case LANG_SWEDISH: case LANG_SYRIAC: case LANG_TAMIL: + case LANG_TATAR: case LANG_TELUGU: case LANG_THAI: + case LANG_UKRAINIAN: case LANG_URDU: case LANG_UZBEK: +#ifndef __REACTOS__ + case LANG_VIETNAMESE: case LANG_GAELIC: case LANG_MALTESE: + case LANG_TAJIK: case LANG_ROMANSH: case LANG_IRISH: + case LANG_SAMI: case LANG_UPPER_SORBIAN: case LANG_SUTU: + case LANG_TSONGA: case LANG_TSWANA: case LANG_VENDA: + case LANG_XHOSA: case LANG_ZULU: case LANG_ESPERANTO: + case LANG_WALON: case LANG_CORNISH: case LANG_WELSH: + case LANG_BRETON: +#else + case LANG_VIETNAMESE: case LANG_MALTESE: case LANG_IRISH: + case LANG_SAMI: case LANG_UPPER_SORBIAN: case LANG_TSWANA: + case LANG_XHOSA: case LANG_ZULU: case LANG_WELSH: + case LANG_BRETON: +#endif + nOffset = 16; + pnLookup = Lookup_16; + break; + case LANG_CZECH: case LANG_HUNGARIAN: case LANG_POLISH: + case LANG_SLOVAK: case LANG_SPANISH: + nOffset = 32; + pnLookup = Lookup_32; + break; + case LANG_HEBREW: + nOffset = 48; + pnLookup = Lookup_48; + break; + case LANG_JAPANESE: + nOffset = 64; + pnLookup = Lookup_64; + break; + case LANG_KOREAN: + nOffset = 80; + pnLookup = Lookup_80; + break; + case LANG_CHINESE: + nOffset = 112; + pnLookup = Lookup_112; + break; + case LANG_GREEK: + nOffset = 128; + pnLookup = Lookup_128; + break; + case LANG_ICELANDIC: + nOffset = 144; + pnLookup = Lookup_144; + break; + case LANG_TURKISH: + nOffset = 160; + pnLookup = Lookup_160; + break; + case LANG_NORWEGIAN: + if (SUBLANGID(LANGIDFROMLCID(lcid)) == SUBLANG_NORWEGIAN_NYNORSK) + { + nOffset = 176; + pnLookup = Lookup_176; + } + else + { + nOffset = 16; + pnLookup = Lookup_16; + } + break; + case LANG_ARABIC: + case LANG_FARSI: + nOffset = 208; + pnLookup = Lookup_208; + break; + case LANG_RUSSIAN: + nOffset = 224; + pnLookup = Lookup_224; + break; + } + + nHiWord = (nOffset | nMask) << 16; + + while (*str) + { + nLoWord = 37 * nLoWord + pnLookup[*str > 0x7f && nMask ? *str + 0x80 : *str]; + str++; + } + /* Constrain to a prime modulo and sizeof(WORD) */ + nLoWord = (nLoWord % 65599) & 0xffff; + + return nHiWord | nLoWord; +} diff --git a/reactos/tools/widl_20080105/hash.h b/reactos/tools/widl_20080105/hash.h new file mode 100644 index 00000000000..bb787abab83 --- /dev/null +++ b/reactos/tools/widl_20080105/hash.h @@ -0,0 +1,33 @@ +/* + * Hash definitions + * + * Copyright 2005 Huw Davies + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + */ + +#ifndef __WIDL_HASH_H +#define __WIDL_HASH_H + +typedef enum tag_syskind_t { + SYS_WIN16 = 0, + SYS_WIN32, + SYS_MAC +} syskind_t; + +extern unsigned long lhash_val_of_name_sys( syskind_t skind, LCID lcid, LPCSTR lpStr); + +#endif diff --git a/reactos/tools/widl_20080105/header.c b/reactos/tools/widl_20080105/header.c new file mode 100644 index 00000000000..fd895348b3a --- /dev/null +++ b/reactos/tools/widl_20080105/header.c @@ -0,0 +1,1043 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" + +static int indentation = 0; +user_type_list_t user_type_list = LIST_INIT(user_type_list); +static context_handle_list_t context_handle_list = LIST_INIT(context_handle_list); + +static void indent(FILE *h, int delta) +{ + int c; + if (delta < 0) indentation += delta; + for (c=0; c 0) indentation += delta; +} + +int is_ptrchain_attr(const var_t *var, enum attr_type t) +{ + if (is_attr(var->attrs, t)) + return 1; + else + { + type_t *type = var->type; + for (;;) + { + if (is_attr(type->attrs, t)) + return 1; + else if (type->kind == TKIND_ALIAS) + type = type->orig; + else if (is_ptr(type)) + type = type->ref; + else return 0; + } + } +} + +int is_attr(const attr_list_t *list, enum attr_type t) +{ + const attr_t *attr; + if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == t) return 1; + return 0; +} + +void *get_attrp(const attr_list_t *list, enum attr_type t) +{ + const attr_t *attr; + if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == t) return attr->u.pval; + return NULL; +} + +unsigned long get_attrv(const attr_list_t *list, enum attr_type t) +{ + const attr_t *attr; + if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == t) return attr->u.ival; + return 0; +} + +int is_void(const type_t *t) +{ + if (!t->type && !t->ref) return 1; + return 0; +} + +int is_conformant_array(const type_t *t) +{ + return t->type == RPC_FC_CARRAY + || t->type == RPC_FC_CVARRAY + || (t->type == RPC_FC_BOGUS_ARRAY && t->size_is); +} + +void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid) +{ + if (!uuid) return; + fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x," + "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n", + guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], + uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], + uuid->Data4[6], uuid->Data4[7]); +} + +void write_name(FILE *h, const var_t *v) +{ + if (is_attr( v->attrs, ATTR_PROPGET )) + fprintf(h, "get_" ); + else if (is_attr( v->attrs, ATTR_PROPPUT )) + fprintf(h, "put_" ); + else if (is_attr( v->attrs, ATTR_PROPPUTREF )) + fprintf(h, "putref_" ); + fprintf(h, "%s", v->name); +} + +void write_prefix_name(FILE *h, const char *prefix, const var_t *v) +{ + fprintf(h, "%s", prefix); + write_name(h, v); +} + +static void write_field(FILE *h, var_t *v) +{ + if (!v) return; + if (v->type) { + const char *name = v->name; + if (name == NULL) { + switch (v->type->type) { + case RPC_FC_STRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_ENCAPSULATED_UNION: + name = "DUMMYSTRUCTNAME"; + break; + case RPC_FC_NON_ENCAPSULATED_UNION: + name = "DUMMYUNIONNAME"; + break; + default: + /* ? */ + break; + } + } + indent(h, 0); + write_type_def_or_decl(h, v->type, TRUE, "%s", name); + fprintf(h, ";\n"); + } +} + +static void write_fields(FILE *h, var_list_t *fields) +{ + var_t *v; + if (!fields) return; + LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v); +} + +static void write_enums(FILE *h, var_list_t *enums) +{ + var_t *v; + if (!enums) return; + LIST_FOR_EACH_ENTRY( v, enums, var_t, entry ) + { + if (v->name) { + indent(h, 0); + write_name(h, v); + if (v->eval) { + fprintf(h, " = "); + write_expr(h, v->eval, 0); + } + } + if (list_next( enums, &v->entry )) fprintf(h, ",\n"); + } + fprintf(h, "\n"); +} + +int needs_space_after(type_t *t) +{ + return (t->kind == TKIND_ALIAS + || (!is_ptr(t) && (!is_conformant_array(t) || t->declarray))); +} + +void write_type_left(FILE *h, type_t *t, int declonly) +{ + if (!h) return; + + if (t->is_const) fprintf(h, "const "); + + if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name); + else if (t->declarray) write_type_left(h, t->ref, declonly); + else { + if (t->sign > 0) fprintf(h, "signed "); + else if (t->sign < 0) fprintf(h, "unsigned "); + switch (t->type) { + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + if (!declonly && t->defined && !t->written && !t->ignore) { + if (t->name) fprintf(h, "enum %s {\n", t->name); + else fprintf(h, "enum {\n"); + t->written = TRUE; + indentation++; + write_enums(h, t->fields); + indent(h, -1); + fprintf(h, "}"); + } + else fprintf(h, "enum %s", t->name ? t->name : ""); + break; + case RPC_FC_STRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_ENCAPSULATED_UNION: + if (!declonly && t->defined && !t->written && !t->ignore) { + if (t->name) fprintf(h, "struct %s {\n", t->name); + else fprintf(h, "struct {\n"); + t->written = TRUE; + indentation++; + write_fields(h, t->fields); + indent(h, -1); + fprintf(h, "}"); + } + else fprintf(h, "struct %s", t->name ? t->name : ""); + break; + case RPC_FC_NON_ENCAPSULATED_UNION: + if (!declonly && t->defined && !t->written && !t->ignore) { + if (t->name) fprintf(h, "union %s {\n", t->name); + else fprintf(h, "union {\n"); + t->written = TRUE; + indentation++; + write_fields(h, t->fields); + indent(h, -1); + fprintf(h, "}"); + } + else fprintf(h, "union %s", t->name ? t->name : ""); + break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_FP: + case RPC_FC_OP: + case RPC_FC_CARRAY: + case RPC_FC_CVARRAY: + case RPC_FC_BOGUS_ARRAY: + write_type_left(h, t->ref, declonly); + fprintf(h, "%s*", needs_space_after(t->ref) ? " " : ""); + break; + default: + fprintf(h, "%s", t->name); + } + } +} + +void write_type_right(FILE *h, type_t *t, int is_field) +{ + if (!h) return; + + if (t->declarray) { + if (is_conformant_array(t)) { + fprintf(h, "[%s]", is_field ? "1" : ""); + t = t->ref; + } + for ( ; t->declarray; t = t->ref) + fprintf(h, "[%lu]", t->dim); + } +} + +void write_type_v(FILE *h, type_t *t, int is_field, int declonly, + const char *fmt, va_list args) +{ + if (!h) return; + + write_type_left(h, t, declonly); + if (fmt) { + if (needs_space_after(t)) + fprintf(h, " "); + vfprintf(h, fmt, args); + } + write_type_right(h, t, is_field); +} + +void write_type_def_or_decl(FILE *f, type_t *t, int field, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + write_type_v(f, t, field, FALSE, fmt, args); + va_end(args); +} + +void write_type_decl(FILE *f, type_t *t, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + write_type_v(f, t, FALSE, TRUE, fmt, args); + va_end(args); +} + +void write_type_decl_left(FILE *f, type_t *t) +{ + write_type_left(f, t, TRUE); +} + +static int user_type_registered(const char *name) +{ + user_type_t *ut; + LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) + if (!strcmp(name, ut->name)) + return 1; + return 0; +} + +static int context_handle_registered(const char *name) +{ + context_handle_t *ch; + LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) + if (!strcmp(name, ch->name)) + return 1; + return 0; +} + +void check_for_user_types_and_context_handles(const var_list_t *list) +{ + const var_t *v; + + if (!list) return; + LIST_FOR_EACH_ENTRY( v, list, const var_t, entry ) + { + type_t *type; + for (type = v->type; type; type = type->kind == TKIND_ALIAS ? type->orig : type->ref) { + const char *name = type->name; + if (type->user_types_registered) continue; + type->user_types_registered = 1; + if (is_attr(type->attrs, ATTR_CONTEXTHANDLE)) { + if (!context_handle_registered(name)) + { + context_handle_t *ch = xmalloc(sizeof(*ch)); + ch->name = xstrdup(name); + list_add_tail(&context_handle_list, &ch->entry); + } + /* don't carry on parsing fields within this type */ + break; + } + if (is_attr(type->attrs, ATTR_WIREMARSHAL)) { + if (!user_type_registered(name)) + { + user_type_t *ut = xmalloc(sizeof *ut); + ut->name = xstrdup(name); + list_add_tail(&user_type_list, &ut->entry); + } + /* don't carry on parsing fields within this type as we are already + * using a wire marshaled type */ + break; + } + else + { + check_for_user_types_and_context_handles(type->fields); + } + } + } +} + +void write_user_types(void) +{ + user_type_t *ut; + LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) + { + const char *name = ut->name; + fprintf(header, "ULONG __RPC_USER %s_UserSize (ULONG *, ULONG, %s *);\n", name, name); + fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal (ULONG *, unsigned char *, %s *);\n", name, name); + fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name); + fprintf(header, "void __RPC_USER %s_UserFree (ULONG *, %s *);\n", name, name); + } +} + +void write_context_handle_rundowns(void) +{ + context_handle_t *ch; + LIST_FOR_EACH_ENTRY(ch, &context_handle_list, context_handle_t, entry) + { + const char *name = ch->name; + fprintf(header, "void __RPC_USER %s_rundown(%s);\n", name, name); + } +} + +void write_typedef(type_t *type) +{ + fprintf(header, "typedef "); + write_type_def_or_decl(header, type->orig, FALSE, "%s", type->name); + fprintf(header, ";\n"); +} + +void write_expr(FILE *h, const expr_t *e, int brackets) +{ + switch (e->type) { + case EXPR_VOID: + break; + case EXPR_NUM: + fprintf(h, "%lu", e->u.lval); + break; + case EXPR_HEXNUM: + fprintf(h, "0x%lx", e->u.lval); + break; + case EXPR_DOUBLE: + fprintf(h, "%#.15g", e->u.dval); + break; + case EXPR_TRUEFALSE: + if (e->u.lval == 0) + fprintf(h, "FALSE"); + else + fprintf(h, "TRUE"); + break; + case EXPR_IDENTIFIER: + fprintf(h, "%s", e->u.sval); + break; + case EXPR_NEG: + fprintf(h, "-"); + write_expr(h, e->ref, 1); + break; + case EXPR_NOT: + fprintf(h, "~"); + write_expr(h, e->ref, 1); + break; + case EXPR_PPTR: + fprintf(h, "*"); + write_expr(h, e->ref, 1); + break; + case EXPR_CAST: + fprintf(h, "("); + write_type_decl(h, e->u.tref, NULL); + fprintf(h, ")"); + write_expr(h, e->ref, 1); + break; + case EXPR_SIZEOF: + fprintf(h, "sizeof("); + write_type_decl(h, e->u.tref, NULL); + fprintf(h, ")"); + break; + case EXPR_SHL: + case EXPR_SHR: + case EXPR_MUL: + case EXPR_DIV: + case EXPR_ADD: + case EXPR_SUB: + case EXPR_AND: + case EXPR_OR: + if (brackets) fprintf(h, "("); + write_expr(h, e->ref, 1); + switch (e->type) { + case EXPR_SHL: fprintf(h, " << "); break; + case EXPR_SHR: fprintf(h, " >> "); break; + case EXPR_MUL: fprintf(h, " * "); break; + case EXPR_DIV: fprintf(h, " / "); break; + case EXPR_ADD: fprintf(h, " + "); break; + case EXPR_SUB: fprintf(h, " - "); break; + case EXPR_AND: fprintf(h, " & "); break; + case EXPR_OR: fprintf(h, " | "); break; + default: break; + } + write_expr(h, e->u.ext, 1); + if (brackets) fprintf(h, ")"); + break; + case EXPR_COND: + if (brackets) fprintf(h, "("); + write_expr(h, e->ref, 1); + fprintf(h, " ? "); + write_expr(h, e->u.ext, 1); + fprintf(h, " : "); + write_expr(h, e->ext2, 1); + if (brackets) fprintf(h, ")"); + break; + case EXPR_ADDRESSOF: + fprintf(h, "&"); + write_expr(h, e->ref, 1); + break; + } +} + +void write_constdef(const var_t *v) +{ + fprintf(header, "#define %s (", v->name); + write_expr(header, v->eval, 0); + fprintf(header, ")\n\n"); +} + +void write_externdef(const var_t *v) +{ + fprintf(header, "extern const "); + write_type_def_or_decl(header, v->type, FALSE, "%s", v->name); + fprintf(header, ";\n\n"); +} + +void write_library(const char *name, const attr_list_t *attr) +{ + const UUID *uuid = get_attrp(attr, ATTR_UUID); + fprintf(header, "\n"); + write_guid(header, "LIBID", name, uuid); + fprintf(header, "\n"); +} + + +const var_t* get_explicit_handle_var(const func_t* func) +{ + const var_t* var; + + if (!func->args) + return NULL; + + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + if (var->type->type == RPC_FC_BIND_PRIMITIVE) + return var; + + return NULL; +} + +int has_out_arg_or_return(const func_t *func) +{ + const var_t *var; + + if (!is_void(func->def->type)) + return 1; + + if (!func->args) + return 0; + + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + if (is_attr(var->attrs, ATTR_OUT)) + return 1; + + return 0; +} + + +/********** INTERFACES **********/ + +int is_object(const attr_list_t *list) +{ + const attr_t *attr; + if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry ) + if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1; + return 0; +} + +int is_local(const attr_list_t *a) +{ + return is_attr(a, ATTR_LOCAL); +} + +const var_t *is_callas(const attr_list_t *a) +{ + return get_attrp(a, ATTR_CALLAS); +} + +static void write_method_macro(const type_t *iface, const char *name) +{ + const func_t *cur; + + if (iface->ref) write_method_macro(iface->ref, name); + + if (!iface->funcs) return; + + fprintf(header, "/*** %s methods ***/\n", iface->name); + LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) + { + var_t *def = cur->def; + if (!is_callas(def->attrs)) { + const var_t *arg; + int argc = 0; + int c; + + if (cur->args) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) argc++; + + fprintf(header, "#define %s_", name); + write_name(header,def); + fprintf(header, "(p"); + for (c=0; clpVtbl->"); + write_name(header, def); + fprintf(header, "(p"); + for (c=0; cargs) + { + write_type_decl_left(h, arg->type); + fprintf(h, " (STDMETHODCALLTYPE *"); + write_name(h,arg); + fprintf(h, ")("); + write_args(h, arg->args, NULL, 0, FALSE); + fprintf(h, ")"); + } + else + write_type_decl(h, arg->type, "%s", arg->name); + count++; + } + if (do_indent) indentation--; +} + +static void write_cpp_method_def(const type_t *iface) +{ + const func_t *cur; + + if (!iface->funcs) return; + + LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) + { + var_t *def = cur->def; + if (!is_callas(def->attrs)) { + indent(header, 0); + fprintf(header, "virtual "); + write_type_decl_left(header, def->type); + fprintf(header, " STDMETHODCALLTYPE "); + write_name(header, def); + fprintf(header, "(\n"); + write_args(header, cur->args, iface->name, 2, TRUE); + fprintf(header, ") = 0;\n"); + fprintf(header, "\n"); + } + } +} + +static void do_write_c_method_def(const type_t *iface, const char *name) +{ + const func_t *cur; + + if (iface->ref) do_write_c_method_def(iface->ref, name); + + if (!iface->funcs) return; + indent(header, 0); + fprintf(header, "/*** %s methods ***/\n", iface->name); + LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) + { + const var_t *def = cur->def; + if (!is_callas(def->attrs)) { + indent(header, 0); + write_type_decl_left(header, def->type); + fprintf(header, " (STDMETHODCALLTYPE *"); + write_name(header, def); + fprintf(header, ")(\n"); + write_args(header, cur->args, name, 1, TRUE); + fprintf(header, ");\n"); + fprintf(header, "\n"); + } + } +} + +static void write_c_method_def(const type_t *iface) +{ + do_write_c_method_def(iface, iface->name); +} + +static void write_c_disp_method_def(const type_t *iface) +{ + do_write_c_method_def(iface->ref, iface->name); +} + +static void write_method_proto(const type_t *iface) +{ + const func_t *cur; + + if (!iface->funcs) return; + LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) + { + const var_t *def = cur->def; + + if (!is_local(def->attrs)) { + /* proxy prototype */ + write_type_decl_left(header, def->type); + fprintf(header, " CALLBACK %s_", iface->name); + write_name(header, def); + fprintf(header, "_Proxy(\n"); + write_args(header, cur->args, iface->name, 1, TRUE); + 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"); + } + } +} + +void write_locals(FILE *fp, const type_t *iface, int body) +{ + static const char comment[] + = "/* WIDL-generated stub. You must provide an implementation for this. */"; + const func_list_t *funcs = iface->funcs; + const func_t *cur; + + if (!is_object(iface->attrs) || !funcs) + return; + + LIST_FOR_EACH_ENTRY(cur, funcs, const func_t, entry) { + const var_t *def = cur->def; + const var_t *cas = is_callas(def->attrs); + + if (cas) { + const func_t *m; + LIST_FOR_EACH_ENTRY(m, iface->funcs, const func_t, entry) + if (!strcmp(m->def->name, cas->name)) + break; + if (&m->entry != iface->funcs) { + const var_t *mdef = m->def; + /* proxy prototype - use local prototype */ + write_type_decl_left(fp, mdef->type); + fprintf(fp, " CALLBACK %s_", iface->name); + write_name(fp, mdef); + fprintf(fp, "_Proxy(\n"); + write_args(fp, m->args, iface->name, 1, TRUE); + fprintf(fp, ")"); + if (body) { + type_t *rt = mdef->type; + fprintf(fp, "\n{\n"); + fprintf(fp, " %s\n", comment); + if (rt->name && strcmp(rt->name, "HRESULT") == 0) + fprintf(fp, " return E_NOTIMPL;\n"); + else if (rt->type) { + fprintf(fp, " "); + write_type_decl(fp, rt, "rv"); + fprintf(fp, ";\n"); + fprintf(fp, " memset(&rv, 0, sizeof rv);\n"); + fprintf(fp, " return rv;\n"); + } + fprintf(fp, "}\n\n"); + } + else + fprintf(fp, ";\n"); + /* stub prototype - use remotable prototype */ + write_type_decl_left(fp, def->type); + fprintf(fp, " __RPC_STUB %s_", iface->name); + write_name(fp, mdef); + fprintf(fp, "_Stub(\n"); + write_args(fp, cur->args, iface->name, 1, TRUE); + fprintf(fp, ")"); + if (body) + /* Remotable methods must all return HRESULTs. */ + fprintf(fp, "\n{\n %s\n return E_NOTIMPL;\n}\n\n", comment); + else + fprintf(fp, ";\n"); + } + else + error_loc("invalid call_as attribute (%s -> %s)\n", def->name, cas->name); + } + } +} + +static void write_function_proto(const type_t *iface, const func_t *fun, const char *prefix) +{ + var_t *def = fun->def; + + /* FIXME: do we need to handle call_as? */ + write_type_decl_left(header, def->type); + fprintf(header, " "); + write_prefix_name(header, prefix, def); + fprintf(header, "(\n"); + if (fun->args) + write_args(header, fun->args, iface->name, 0, TRUE); + else + fprintf(header, " void"); + fprintf(header, ");\n"); +} + +static void write_function_protos(const type_t *iface) +{ + const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE); + const var_t* explicit_handle_var; + const func_t *cur; + int prefixes_differ = strcmp(prefix_client, prefix_server); + + if (!iface->funcs) return; + LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) + { + var_t *def = cur->def; + + /* check for a defined binding handle */ + explicit_handle_var = get_explicit_handle_var(cur); + if (explicit_handle) { + if (!explicit_handle_var) { + error("%s() does not define an explicit binding handle!\n", def->name); + return; + } + } else if (implicit_handle) { + if (explicit_handle_var) { + error("%s() must not define a binding handle!\n", def->name); + return; + } + } + + if (prefixes_differ) { + fprintf(header, "/* client prototype */\n"); + write_function_proto(iface, cur, prefix_client); + fprintf(header, "/* server prototype */\n"); + } + write_function_proto(iface, cur, prefix_server); + } +} + +void write_forward(type_t *iface) +{ + /* C/C++ forwards should only be written for object interfaces, so if we + * have a full definition we only write one if we find [object] among the + * attributes - however, if we don't have a full definition at this point + * (i.e. this is an IDL forward), then we also assume that it is an object + * interface, since non-object interfaces shouldn't need forwards */ + if ((!iface->defined || is_object(iface->attrs) || is_attr(iface->attrs, ATTR_DISPINTERFACE)) + && !iface->written) { + fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name); + fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name); + fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name); + fprintf(header, "#endif\n\n" ); + iface->written = TRUE; + } +} + +static void write_iface_guid(const type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + write_guid(header, "IID", iface->name, uuid); +} + +static void write_dispiface_guid(const type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + write_guid(header, "DIID", iface->name, uuid); +} + +static void write_coclass_guid(type_t *cocl) +{ + const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID); + write_guid(header, "CLSID", cocl->name, uuid); +} + +static void write_com_interface(type_t *iface) +{ + if (!iface->funcs && !iface->ref) { + parser_warning("%s has no methods\n", iface->name); + return; + } + + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s interface\n", iface->name); + fprintf(header, " */\n"); + fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); + fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); + write_iface_guid(iface); + write_forward(iface); + /* C++ interface */ + fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); + if (iface->ref) + { + fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name); + fprintf(header, "{\n"); + indentation++; + write_cpp_method_def(iface); + indentation--; + fprintf(header, "};\n"); + } + else + { + fprintf(header, "interface %s\n", iface->name); + fprintf(header, "{\n"); + fprintf(header, " BEGIN_INTERFACE\n"); + fprintf(header, "\n"); + indentation++; + write_cpp_method_def(iface); + indentation--; + fprintf(header, " END_INTERFACE\n"); + fprintf(header, "};\n"); + } + fprintf(header, "#else\n"); + /* C interface */ + fprintf(header, "typedef struct %sVtbl {\n", iface->name); + indentation++; + fprintf(header, " BEGIN_INTERFACE\n"); + fprintf(header, "\n"); + write_c_method_def(iface); + indentation--; + fprintf(header, " END_INTERFACE\n"); + fprintf(header, "} %sVtbl;\n", iface->name); + fprintf(header, "interface %s {\n", iface->name); + fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->name); + fprintf(header, "};\n"); + fprintf(header, "\n"); + fprintf(header, "#ifdef COBJMACROS\n"); + write_method_macro(iface, iface->name); + fprintf(header, "#endif\n"); + fprintf(header, "\n"); + fprintf(header, "#endif\n"); + fprintf(header, "\n"); + write_method_proto(iface); + write_locals(header, iface, FALSE); + fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); +} + +static void write_rpc_interface(const type_t *iface) +{ + unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); + const char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + static int allocate_written = 0; + + if (!allocate_written) + { + allocate_written = 1; + fprintf(header, "void * __RPC_USER MIDL_user_allocate(size_t);\n"); + fprintf(header, "void __RPC_USER MIDL_user_free(void *);\n\n"); + } + + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s interface (v%d.%d)\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + fprintf(header, " */\n"); + fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name); + fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name); + if (iface->funcs) + { + write_iface_guid(iface); + if (var) fprintf(header, "extern handle_t %s;\n", var); + if (old_names) + { + fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name); + fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name); + } + else + { + fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n", + prefix_client, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n", + prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + } + write_function_protos(iface); + } + fprintf(header,"\n#endif /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name); + + /* FIXME: server/client code */ +} + +void write_interface(type_t *iface) +{ + if (is_object(iface->attrs)) + write_com_interface(iface); + else + write_rpc_interface(iface); +} + +void write_dispinterface(type_t *iface) +{ + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s dispinterface\n", iface->name); + fprintf(header, " */\n"); + fprintf(header,"#ifndef __%s_DISPINTERFACE_DEFINED__\n", iface->name); + fprintf(header,"#define __%s_DISPINTERFACE_DEFINED__\n\n", iface->name); + write_dispiface_guid(iface); + write_forward(iface); + /* C++ interface */ + fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n"); + fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name); + fprintf(header, "{\n"); + fprintf(header, "};\n"); + fprintf(header, "#else\n"); + /* C interface */ + fprintf(header, "typedef struct %sVtbl {\n", iface->name); + indentation++; + fprintf(header, " BEGIN_INTERFACE\n"); + fprintf(header, "\n"); + write_c_disp_method_def(iface); + indentation--; + fprintf(header, " END_INTERFACE\n"); + fprintf(header, "} %sVtbl;\n", iface->name); + fprintf(header, "interface %s {\n", iface->name); + fprintf(header, " CONST_VTBL %sVtbl* lpVtbl;\n", iface->name); + fprintf(header, "};\n"); + fprintf(header, "\n"); + fprintf(header, "#ifdef COBJMACROS\n"); + write_method_macro(iface->ref, iface->name); + fprintf(header, "#endif\n"); + fprintf(header, "\n"); + fprintf(header, "#endif\n"); + fprintf(header, "\n"); + fprintf(header,"#endif /* __%s_DISPINTERFACE_DEFINED__ */\n\n", iface->name); +} + +void write_coclass(type_t *cocl) +{ + fprintf(header, "/*****************************************************************************\n"); + fprintf(header, " * %s coclass\n", cocl->name); + fprintf(header, " */\n\n"); + write_coclass_guid(cocl); + fprintf(header, "\n"); +} + +void write_coclass_forward(type_t *cocl) +{ + fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name); + fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name); + fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name); + fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name ); +} diff --git a/reactos/tools/widl_20080105/header.h b/reactos/tools/widl_20080105/header.h new file mode 100644 index 00000000000..41784a0b152 --- /dev/null +++ b/reactos/tools/widl_20080105/header.h @@ -0,0 +1,93 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WIDL_HEADER_H +#define __WIDL_HEADER_H + +#include "widltypes.h" + +extern int is_ptrchain_attr(const var_t *var, enum attr_type t); +extern int is_attr(const attr_list_t *list, enum attr_type t); +extern void *get_attrp(const attr_list_t *list, enum attr_type t); +extern unsigned long get_attrv(const attr_list_t *list, enum attr_type t); +extern int is_void(const type_t *t); +extern int is_conformant_array(const type_t *t); +extern int is_declptr(const type_t *t); +extern void write_name(FILE *h, const var_t *v); +extern void write_prefix_name(FILE *h, const char *prefix, const var_t *v); +extern const char* get_name(const var_t *v); +extern void write_type_left(FILE *h, type_t *t, int declonly); +extern void write_type_right(FILE *h, type_t *t, int is_field); +extern void write_type_def_or_decl(FILE *h, type_t *t, int is_field, const char *fmt, ...); +extern void write_type_decl(FILE *f, type_t *t, const char *fmt, ...); +extern void write_type_decl_left(FILE *f, type_t *t); +extern int needs_space_after(type_t *t); +extern int is_object(const attr_list_t *list); +extern int is_local(const attr_list_t *list); +extern int need_stub(const type_t *iface); +extern int need_proxy(const type_t *iface); +extern int need_stub_files(const ifref_list_t *ifaces); +extern int need_proxy_file(const ifref_list_t *ifaces); +extern const var_t *is_callas(const attr_list_t *list); +extern void write_args(FILE *h, const var_list_t *arg, const char *name, int obj, int do_indent); +extern void write_array(FILE *h, array_dims_t *v, int field); +extern void write_forward(type_t *iface); +extern void write_interface(type_t *iface); +extern void write_dispinterface(type_t *iface); +extern void write_locals(FILE *fp, const type_t *iface, int body); +extern void write_coclass(type_t *cocl); +extern void write_coclass_forward(type_t *cocl); +extern void write_typedef(type_t *type); +extern void write_expr(FILE *h, const expr_t *e, int brackets); +extern void write_constdef(const var_t *v); +extern void write_externdef(const var_t *v); +extern void write_library(const char *name, const attr_list_t *attr); +extern void write_user_types(void); +extern void write_context_handle_rundowns(void); +extern const var_t* get_explicit_handle_var(const func_t* func); +extern int has_out_arg_or_return(const func_t *func); +extern void write_guid(FILE *f, const char *guid_prefix, const char *name, + const UUID *uuid); + +static inline int last_ptr(const type_t *type) +{ + return is_ptr(type) && !is_declptr(type->ref); +} + +static inline int last_array(const type_t *type) +{ + return is_array(type) && !is_array(type->ref); +} + +static inline int is_string_type(const attr_list_t *attrs, const type_t *type) +{ + return is_attr(attrs, ATTR_STRING) && (last_ptr(type) || last_array(type)); +} + +static inline int is_context_handle(const type_t *type) +{ + const type_t *t; + for (t = type; is_ptr(t); t = t->ref) + if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) + return 1; + return 0; +} + +#endif diff --git a/reactos/tools/widl_20080105/parser.h b/reactos/tools/widl_20080105/parser.h new file mode 100644 index 00000000000..c46364aee41 --- /dev/null +++ b/reactos/tools/widl_20080105/parser.h @@ -0,0 +1,47 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WIDL_PARSER_H +#define __WIDL_PARSER_H + +typedef struct +{ + type_t *interface; + unsigned char old_pointer_default; +} interface_info_t; + +int parser_parse(void); + +extern FILE *parser_in; +extern char *parser_text; +extern int parser_debug; +extern int yy_flex_debug; + +int parser_lex(void); + +extern int import_stack_ptr; +int do_import(char *fname); +void abort_import(void); + +#define parse_only import_stack_ptr + +int is_type(const char *name); + +#endif diff --git a/reactos/tools/widl_20080105/parser.l b/reactos/tools/widl_20080105/parser.l new file mode 100644 index 00000000000..d2fd3c1248c --- /dev/null +++ b/reactos/tools/widl_20080105/parser.l @@ -0,0 +1,443 @@ +/* -*-C-*- + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +%option stack +%option nounput noyy_top_state +%option 8bit never-interactive prefix="parser_" + +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} +double [0-9]+\.[0-9]+([eE][+-]?[0-9]+)* + +%x QUOTE +%x ATTR +%x PP_LINE + +%{ + +#include "config.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "wine/wpp.h" + +#include "parser.tab.h" + +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); +static int attr_token(const char *kw); + +#define MAX_IMPORT_DEPTH 10 +struct { + YY_BUFFER_STATE state; + char *input_name; + int line_number; + char *temp_name; +} import_stack[MAX_IMPORT_DEPTH]; +int import_stack_ptr = 0; + +static void pop_import(void); + +UUID *parse_uuid(const char *u) +{ + UUID* uuid = xmalloc(sizeof(UUID)); + char b[3]; + /* it would be nice to use UuidFromStringA */ + uuid->Data1 = strtoul(u, NULL, 16); + uuid->Data2 = strtoul(u+9, NULL, 16); + uuid->Data3 = strtoul(u+14, NULL, 16); + b[2] = 0; + memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16); + memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16); + memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16); + memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16); + memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16); + memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16); + memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16); + memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16); + return uuid; +} + +%} + +/* + ************************************************************************** + * The flexer starts here + ************************************************************************** + */ +%% +^{ws}*\#{ws}* yy_push_state(PP_LINE); +[^\n]* { + int lineno; + char *cptr, *fname; + yy_pop_state(); + lineno = (int)strtol(yytext, &cptr, 10); + if(!lineno) + error_loc("Malformed '#...' line-directive; invalid linenumber\n"); + fname = strchr(cptr, '"'); + if(!fname) + error_loc("Malformed '#...' line-directive; missing filename\n"); + fname++; + cptr = strchr(fname, '"'); + if(!cptr) + error_loc("Malformed '#...' line-directive; missing terminating \"\n"); + *cptr = '\0'; + line_number = lineno - 1; /* We didn't read the newline */ + free( input_name ); + input_name = xstrdup(fname); + } +\" yy_push_state(QUOTE); cbufidx = 0; +\" { + yy_pop_state(); + parser_lval.str = get_buffered_cstring(); + return aSTRING; + } +\\\\ | +\\\" addcchar(yytext[1]); +\\. addcchar('\\'); addcchar(yytext[1]); +. addcchar(yytext[0]); +\[ yy_push_state(ATTR); return '['; +\] yy_pop_state(); return ']'; +{cident} return attr_token(yytext); +{uuid} { + parser_lval.uuid = parse_uuid(yytext); + return aUUID; + } +{hex} { + parser_lval.num = strtoul(yytext, NULL, 0); + return aHEXNUM; + } +{int} { + parser_lval.num = strtoul(yytext, NULL, 0); + return aNUM; + } +{double} { + parser_lval.dbl = strtod(yytext, NULL); + return aDOUBLE; + } +SAFEARRAY{ws}*/\( return tSAFEARRAY; +{cident} return kw_token(yytext); +\n line_number++; +{ws} +\<\< return SHL; +\>\> return SHR; +. return yytext[0]; +<> { + if (import_stack_ptr) { + pop_import(); + return aEOF; + } + else yyterminate(); + } +%% + +#ifndef parser_wrap +int parser_wrap(void) +{ + return 1; +} +#endif + +struct keyword { + const char *kw; + int token; +}; + +static const struct keyword keywords[] = { + {"FALSE", tFALSE}, + {"TRUE", tTRUE}, + {"__cdecl", tCDECL}, + {"__int64", tINT64}, + {"__stdcall", tSTDCALL}, + {"_stdcall", tSTDCALL}, + {"boolean", tBOOLEAN}, + {"byte", tBYTE}, + {"callback", tCALLBACK}, + {"case", tCASE}, + {"char", tCHAR}, + {"coclass", tCOCLASS}, + {"code", tCODE}, + {"comm_status", tCOMMSTATUS}, + {"const", tCONST}, + {"cpp_quote", tCPPQUOTE}, + {"default", tDEFAULT}, + {"dispinterface", tDISPINTERFACE}, + {"double", tDOUBLE}, + {"enum", tENUM}, + {"error_status_t", tERRORSTATUST}, + {"extern", tEXTERN}, + {"float", tFLOAT}, + {"handle_t", tHANDLET}, + {"hyper", tHYPER}, + {"import", tIMPORT}, + {"importlib", tIMPORTLIB}, + {"in_line", tINLINE}, + {"int", tINT}, + {"interface", tINTERFACE}, + {"library", tLIBRARY}, + {"long", tLONG}, + {"methods", tMETHODS}, + {"module", tMODULE}, + {"properties", tPROPERTIES}, + {"short", tSHORT}, + {"signed", tSIGNED}, + {"sizeof", tSIZEOF}, + {"small", tSMALL}, + {"struct", tSTRUCT}, + {"switch", tSWITCH}, + {"typedef", tTYPEDEF}, + {"union", tUNION}, + {"unsigned", tUNSIGNED}, + {"void", tVOID}, + {"wchar_t", tWCHAR}, +}; +#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) + +/* keywords only recognized in attribute lists */ +static const struct keyword attr_keywords[] = +{ + {"aggregatable", tAGGREGATABLE}, + {"allocate", tALLOCATE}, + {"appobject", tAPPOBJECT}, + {"async", tASYNC}, + {"async_uuid", tASYNCUUID}, + {"auto_handle", tAUTOHANDLE}, + {"bindable", tBINDABLE}, + {"broadcast", tBROADCAST}, + {"byte_count", tBYTECOUNT}, + {"call_as", tCALLAS}, + {"context_handle", tCONTEXTHANDLE}, + {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, + {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, + {"control", tCONTROL}, + {"defaultcollelem", tDEFAULTCOLLELEM}, + {"defaultvalue", tDEFAULTVALUE}, + {"defaultvtable", tDEFAULTVTABLE}, + {"displaybind", tDISPLAYBIND}, + {"dllname", tDLLNAME}, + {"dual", tDUAL}, + {"endpoint", tENDPOINT}, + {"entry", tENTRY}, + {"explicit_handle", tEXPLICITHANDLE}, + {"handle", tHANDLE}, + {"helpcontext", tHELPCONTEXT}, + {"helpfile", tHELPFILE}, + {"helpstring", tHELPSTRING}, + {"helpstringcontext", tHELPSTRINGCONTEXT}, + {"helpstringdll", tHELPSTRINGDLL}, + {"hidden", tHIDDEN}, + {"id", tID}, + {"idempotent", tIDEMPOTENT}, + {"iid_is", tIIDIS}, + {"immediatebind", tIMMEDIATEBIND}, + {"implicit_handle", tIMPLICITHANDLE}, + {"in", tIN}, + {"input_sync", tINPUTSYNC}, + {"lcid", tLCID}, + {"length_is", tLENGTHIS}, + {"local", tLOCAL}, + {"nonbrowsable", tNONBROWSABLE}, + {"noncreatable", tNONCREATABLE}, + {"nonextensible", tNONEXTENSIBLE}, + {"object", tOBJECT}, + {"odl", tODL}, + {"oleautomation", tOLEAUTOMATION}, + {"optional", tOPTIONAL}, + {"out", tOUT}, + {"pointer_default", tPOINTERDEFAULT}, + {"propget", tPROPGET}, + {"propput", tPROPPUT}, + {"propputref", tPROPPUTREF}, + {"ptr", tPTR}, + {"public", tPUBLIC}, + {"range", tRANGE}, + {"readonly", tREADONLY}, + {"ref", tREF}, + {"requestedit", tREQUESTEDIT}, + {"restricted", tRESTRICTED}, + {"retval", tRETVAL}, + {"single", tSINGLE}, + {"size_is", tSIZEIS}, + {"source", tSOURCE}, + {"string", tSTRING}, + {"switch_is", tSWITCHIS}, + {"switch_type", tSWITCHTYPE}, + {"transmit_as", tTRANSMITAS}, + {"unique", tUNIQUE}, + {"uuid", tUUID}, + {"v1_enum", tV1ENUM}, + {"vararg", tVARARG}, + {"version", tVERSION}, + {"wire_marshal", tWIREMARSHAL}, +}; + + +#define KWP(p) ((const struct keyword *)(p)) + +static int kw_cmp_func(const void *s1, const void *s2) +{ + return strcmp(KWP(s1)->kw, KWP(s2)->kw); +} + +static int kw_token(const char *kw) +{ + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func); + if (kwp) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } + parser_lval.str = xstrdup(kw); + return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; +} + +static int attr_token(const char *kw) +{ + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]), + sizeof(attr_keywords[0]), kw_cmp_func); + if (kwp) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } + return kw_token(kw); +} + +static void addcchar(char c) +{ + if(cbufidx >= cbufalloc) + { + cbufalloc += 1024; + cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0])); + if(cbufalloc > 65536) + parser_warning("Reallocating string buffer larger than 64kB\n"); + } + 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; + free( input_name ); + input_name = import_stack[ptr].input_name; + line_number = import_stack[ptr].line_number; + import_stack_ptr--; +} + +struct imports { + char *name; + struct imports *next; +} *first_import; + +int do_import(char *fname) +{ + FILE *f; + char *hname, *path, *p; + struct imports *import; + int ptr = import_stack_ptr; + int ret; + + if (!parse_only && do_header) { + hname = dup_basename(fname, ".idl"); + p = hname + strlen(hname) - 2; + if (p <= hname || strcmp( p, ".h" )) 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 0; /* already imported */ + + import = xmalloc(sizeof(struct imports)); + import->name = xstrdup(fname); + import->next = first_import; + first_import = import; + + if (!(path = wpp_find_include( fname, input_name ))) + error_loc("Unable to open include file %s\n", fname); + + import_stack[ptr].temp_name = temp_name; + import_stack[ptr].input_name = input_name; + import_stack[ptr].line_number = line_number; + import_stack_ptr++; + input_name = path; + line_number = 1; + + ret = wpp_parse_temp( path, NULL, &temp_name ); + if (ret) exit(1); + + if((f = fopen(temp_name, "r")) == NULL) + error_loc("Unable to open %s\n", temp_name); + + import_stack[ptr].state = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); + return 1; +} + +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" +#include "typelib.h" +#include "typegen.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 + +unsigned char pointer_default = RPC_FC_UP; + +typedef struct list typelist_t; +struct typenode { + type_t *type; + struct list entry; +}; + +typelist_t incomplete_types = LIST_INIT(incomplete_types); + +static void add_incomplete(type_t *t); +static void fix_incomplete(void); + +static str_list_t *append_str(str_list_t *list, char *str); +static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); +static attr_t *make_attr(enum attr_type type); +static attr_t *make_attrv(enum attr_type type, unsigned long val); +static attr_t *make_attrp(enum attr_type type, void *val); +static expr_t *make_expr(enum expr_type type); +static expr_t *make_exprl(enum expr_type type, long val); +static expr_t *make_exprd(enum expr_type type, double val); +static expr_t *make_exprs(enum expr_type type, char *val); +static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr); +static expr_t *make_expr1(enum expr_type type, expr_t *expr); +static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2); +static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3); +static type_t *make_type(unsigned char type, type_t *ref); +static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); +static array_dims_t *append_array(array_dims_t *list, expr_t *expr); +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, int top); +static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); +static ifref_t *make_ifref(type_t *iface); +static var_list_t *append_var(var_list_t *list, var_t *var); +static var_t *make_var(char *name); +static pident_list_t *append_pident(pident_list_t *list, pident_t *p); +static pident_t *make_pident(var_t *var); +static func_list_t *append_func(func_list_t *list, func_t *func); +static func_t *make_func(var_t *def, var_list_t *args); +static type_t *make_class(char *name); +static type_t *make_safearray(type_t *type); +static type_t *make_builtin(char *name); +static type_t *make_int(int sign); + +static type_t *reg_type(type_t *type, const char *name, int t); +static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs); +static type_t *find_type(const char *name, int t); +static type_t *find_type2(char *name, int t); +static type_t *get_type(unsigned char type, char *name, int t); +static type_t *get_typev(unsigned char type, var_t *name, int t); +static int get_struct_type(var_list_t *fields); + +static var_t *reg_const(var_t *var); +static var_t *find_const(char *name, int f); + +static void write_libid(const char *name, const attr_list_t *attr); +static void write_clsid(type_t *cls); +static void write_diid(type_t *iface); +static void write_iid(type_t *iface); + +static int compute_method_indexes(type_t *iface); +static char *gen_name(void); +static void process_typedefs(var_list_t *names); +static void check_arg(var_t *arg); +static void check_all_user_types(ifref_list_t *ifaces); + +#define tsENUM 1 +#define tsSTRUCT 2 +#define tsUNION 3 + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 136 "parser.y" +typedef union YYSTYPE { + attr_t *attr; + attr_list_t *attr_list; + str_list_t *str_list; + expr_t *expr; + expr_list_t *expr_list; + array_dims_t *array_dims; + type_t *type; + var_t *var; + var_list_t *var_list; + pident_t *pident; + pident_list_t *pident_list; + func_t *func; + func_list_t *func_list; + ifref_t *ifref; + ifref_list_t *ifref_list; + char *str; + UUID *uuid; + unsigned int num; + double dbl; + interface_info_t ifinfo; +} YYSTYPE; +/* Line 196 of yacc.c. */ +#line 522 "parser.tab.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 219 of yacc.c. */ +#line 534 "parser.tab.c" + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# else +# define YYSTACK_ALLOC alloca +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYINCLUDED_STDLIB_H +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) +# endif +# ifdef __cplusplus +extern "C" { +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifdef __cplusplus +} +# endif +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short int yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined (__GNUC__) && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short int yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 1065 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 155 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 76 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 271 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 499 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 390 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 136, 2, + 147, 148, 139, 138, 132, 137, 154, 140, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 134, 146, + 2, 153, 2, 133, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 151, 2, 152, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 149, 135, 150, 141, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 142, 143, 144, + 145 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned short int yyprhs[] = +{ + 0, 0, 3, 5, 6, 9, 12, 16, 19, 22, + 25, 28, 29, 32, 35, 39, 42, 45, 48, 51, + 52, 56, 59, 61, 64, 66, 69, 72, 74, 77, + 80, 83, 88, 92, 96, 101, 104, 108, 112, 113, + 115, 117, 119, 123, 125, 130, 134, 141, 147, 148, + 152, 156, 158, 162, 167, 168, 170, 174, 176, 180, + 185, 187, 191, 192, 194, 196, 198, 200, 202, 207, + 212, 214, 216, 218, 220, 222, 224, 229, 234, 236, + 238, 243, 245, 250, 255, 260, 262, 264, 269, 274, + 279, 284, 289, 291, 296, 298, 303, 305, 311, 313, + 315, 320, 322, 324, 326, 328, 330, 332, 334, 336, + 338, 343, 345, 347, 349, 351, 358, 360, 362, 364, + 366, 371, 373, 375, 380, 385, 390, 395, 397, 399, + 404, 409, 411, 413, 415, 416, 418, 419, 422, 427, + 431, 437, 438, 441, 443, 445, 449, 453, 455, 461, + 463, 467, 468, 470, 472, 474, 476, 478, 480, 482, + 488, 492, 496, 500, 504, 508, 512, 516, 520, 523, + 526, 529, 532, 537, 542, 546, 548, 552, 554, 559, + 560, 563, 566, 570, 573, 575, 580, 588, 589, 591, + 592, 594, 596, 598, 600, 602, 604, 606, 609, 612, + 614, 616, 618, 620, 622, 624, 626, 627, 629, 631, + 634, 636, 639, 642, 644, 646, 649, 652, 655, 660, + 661, 664, 667, 670, 673, 676, 679, 683, 686, 690, + 696, 702, 703, 706, 709, 712, 715, 721, 729, 731, + 734, 737, 740, 743, 746, 751, 754, 757, 759, 761, + 765, 767, 771, 773, 775, 777, 783, 785, 787, 789, + 792, 794, 797, 799, 802, 804, 807, 812, 817, 823, + 834, 836 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const short int yyrhs[] = +{ + 156, 0, -1, 157, -1, -1, 157, 218, -1, 157, + 217, -1, 157, 204, 146, -1, 157, 206, -1, 157, + 221, -1, 157, 167, -1, 157, 160, -1, -1, 158, + 218, -1, 158, 217, -1, 158, 204, 146, -1, 158, + 206, -1, 158, 221, -1, 158, 160, -1, 158, 164, + -1, -1, 159, 197, 146, -1, 159, 160, -1, 146, + -1, 183, 146, -1, 161, -1, 187, 146, -1, 193, + 146, -1, 163, -1, 226, 146, -1, 228, 146, -1, + 229, 146, -1, 37, 147, 8, 148, -1, 69, 8, + 146, -1, 162, 158, 10, -1, 70, 147, 8, 148, + -1, 79, 3, -1, 175, 165, 149, -1, 166, 158, + 150, -1, -1, 170, -1, 129, -1, 171, -1, 170, + 132, 171, -1, 169, -1, 175, 227, 223, 172, -1, + 227, 223, 172, -1, 175, 227, 223, 147, 168, 148, + -1, 227, 223, 147, 168, 148, -1, -1, 151, 173, + 152, -1, 151, 139, 152, -1, 189, -1, 173, 132, + 190, -1, 173, 152, 151, 190, -1, -1, 175, -1, + 151, 176, 152, -1, 178, -1, 176, 132, 178, -1, + 176, 152, 151, 178, -1, 8, -1, 177, 132, 8, + -1, -1, 13, -1, 15, -1, 16, -1, 18, -1, + 19, -1, 24, 147, 200, 148, -1, 26, 147, 191, + 148, -1, 33, -1, 34, -1, 35, -1, 36, -1, + 38, -1, 39, -1, 40, 147, 192, 148, -1, 40, + 147, 8, 148, -1, 41, -1, 42, -1, 44, 147, + 8, 148, -1, 46, -1, 47, 147, 177, 148, -1, + 48, 147, 8, 148, -1, 48, 147, 192, 148, -1, + 51, -1, 55, -1, 57, 147, 192, 148, -1, 58, + 147, 8, 148, -1, 59, 147, 8, 148, -1, 60, + 147, 192, 148, -1, 61, 147, 8, 148, -1, 62, + -1, 64, 147, 192, 148, -1, 65, -1, 66, 147, + 190, 148, -1, 67, -1, 68, 147, 56, 3, 148, + -1, 71, -1, 73, -1, 78, 147, 188, 148, -1, + 80, -1, 84, -1, 85, -1, 86, -1, 87, -1, + 88, -1, 89, -1, 90, -1, 91, -1, 92, 147, + 225, 148, -1, 94, -1, 95, -1, 96, -1, 98, + -1, 99, 147, 192, 132, 192, 148, -1, 100, -1, + 102, -1, 103, -1, 104, -1, 109, 147, 188, 148, + -1, 112, -1, 114, -1, 117, 147, 190, 148, -1, + 118, 147, 227, 148, -1, 119, 147, 227, 148, -1, + 125, 147, 179, 148, -1, 126, -1, 127, -1, 128, + 147, 230, 148, -1, 131, 147, 227, 148, -1, 225, + -1, 9, -1, 8, -1, -1, 113, -1, -1, 181, + 182, -1, 26, 190, 134, 195, -1, 38, 134, 195, + -1, 32, 227, 200, 153, 192, -1, -1, 185, 132, + -1, 185, -1, 186, -1, 185, 132, 186, -1, 200, + 153, 192, -1, 200, -1, 49, 199, 149, 184, 150, + -1, 189, -1, 188, 132, 189, -1, -1, 190, -1, + 5, -1, 6, -1, 7, -1, 53, -1, 120, -1, + 3, -1, 190, 133, 190, 134, 190, -1, 190, 135, + 190, -1, 190, 136, 190, -1, 190, 138, 190, -1, + 190, 137, 190, -1, 190, 139, 190, -1, 190, 140, + 190, -1, 190, 11, 190, -1, 190, 12, 190, -1, + 141, 190, -1, 137, 190, -1, 136, 190, -1, 139, + 190, -1, 147, 227, 148, 190, -1, 110, 147, 227, + 148, -1, 147, 190, 148, -1, 192, -1, 191, 132, + 192, -1, 190, -1, 52, 32, 227, 200, -1, -1, + 194, 195, -1, 196, 146, -1, 174, 229, 146, -1, + 175, 146, -1, 146, -1, 174, 227, 223, 172, -1, + 174, 227, 180, 223, 147, 168, 148, -1, -1, 200, + -1, -1, 3, -1, 4, -1, 3, -1, 4, -1, + 22, -1, 130, -1, 203, -1, 107, 203, -1, 124, + 203, -1, 124, -1, 54, -1, 108, -1, 45, -1, + 20, -1, 50, -1, 56, -1, -1, 74, -1, 74, + -1, 106, 202, -1, 111, -1, 81, 202, -1, 63, + 202, -1, 75, -1, 28, -1, 29, 3, -1, 29, + 4, -1, 175, 204, -1, 205, 149, 207, 150, -1, + -1, 207, 208, -1, 174, 218, -1, 43, 3, -1, + 43, 4, -1, 175, 209, -1, 93, 134, -1, 211, + 196, 146, -1, 82, 134, -1, 212, 197, 146, -1, + 210, 149, 211, 212, 150, -1, 210, 149, 215, 146, + 150, -1, -1, 134, 4, -1, 76, 3, -1, 76, + 4, -1, 175, 215, -1, 216, 214, 149, 159, 150, + -1, 216, 134, 3, 149, 163, 159, 150, -1, 213, + -1, 215, 146, -1, 209, 146, -1, 83, 3, -1, + 83, 4, -1, 175, 219, -1, 220, 149, 159, 150, + -1, 139, 223, -1, 32, 222, -1, 200, -1, 222, + -1, 147, 223, 148, -1, 223, -1, 224, 132, 223, + -1, 101, -1, 123, -1, 97, -1, 115, 199, 149, + 194, 150, -1, 129, -1, 4, -1, 201, -1, 32, + 227, -1, 187, -1, 49, 3, -1, 226, -1, 115, + 3, -1, 229, -1, 122, 3, -1, 105, 147, 227, + 148, -1, 121, 174, 227, 224, -1, 122, 199, 149, + 194, 150, -1, 122, 199, 116, 147, 196, 148, 198, + 149, 181, 150, -1, 5, -1, 5, 154, 5, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short int yyrline[] = +{ + 0, 285, 285, 294, 295, 296, 297, 301, 306, 307, + 308, 311, 312, 313, 314, 315, 319, 320, 321, 324, + 325, 326, 329, 330, 331, 332, 337, 338, 339, 344, + 345, 352, 354, 357, 360, 363, 365, 370, 373, 374, + 377, 380, 381, 382, 386, 391, 395, 401, 408, 409, + 410, 413, 414, 415, 418, 419, 423, 429, 430, 431, + 434, 435, 438, 439, 440, 441, 442, 443, 444, 445, + 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, + 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, + 486, 487, 488, 489, 490, 491, 494, 495, 496, 497, + 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, + 508, 509, 513, 514, 519, 520, 523, 524, 527, 531, + 537, 543, 544, 545, 548, 552, 561, 565, 570, 579, + 580, 593, 594, 597, 598, 599, 600, 601, 602, 603, + 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, + 614, 615, 616, 617, 618, 621, 622, 625, 631, 636, + 637, 640, 641, 642, 643, 646, 654, 666, 667, 670, + 671, 672, 675, 677, 680, 681, 682, 683, 684, 700, + 701, 702, 703, 704, 705, 706, 709, 710, 713, 714, + 715, 716, 717, 718, 719, 722, 723, 729, 738, 744, + 745, 749, 752, 753, 756, 768, 769, 772, 773, 776, + 785, 794, 795, 798, 799, 802, 813, 825, 836, 840, + 841, 844, 845, 848, 853, 859, 860, 863, 864, 865, + 869, 870, 874, 875, 876, 879, 890, 891, 892, 893, + 894, 895, 896, 897, 898, 899, 900, 903, 908, 913, + 930, 931 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "aIDENTIFIER", "aKNOWNTYPE", "aNUM", + "aHEXNUM", "aDOUBLE", "aSTRING", "aUUID", "aEOF", "SHL", "SHR", + "tAGGREGATABLE", "tALLOCATE", "tAPPOBJECT", "tASYNC", "tASYNCUUID", + "tAUTOHANDLE", "tBINDABLE", "tBOOLEAN", "tBROADCAST", "tBYTE", + "tBYTECOUNT", "tCALLAS", "tCALLBACK", "tCASE", "tCDECL", "tCHAR", + "tCOCLASS", "tCODE", "tCOMMSTATUS", "tCONST", "tCONTEXTHANDLE", + "tCONTEXTHANDLENOSERIALIZE", "tCONTEXTHANDLESERIALIZE", "tCONTROL", + "tCPPQUOTE", "tDEFAULT", "tDEFAULTCOLLELEM", "tDEFAULTVALUE", + "tDEFAULTVTABLE", "tDISPLAYBIND", "tDISPINTERFACE", "tDLLNAME", + "tDOUBLE", "tDUAL", "tENDPOINT", "tENTRY", "tENUM", "tERRORSTATUST", + "tEXPLICITHANDLE", "tEXTERN", "tFALSE", "tFLOAT", "tHANDLE", "tHANDLET", + "tHELPCONTEXT", "tHELPFILE", "tHELPSTRING", "tHELPSTRINGCONTEXT", + "tHELPSTRINGDLL", "tHIDDEN", "tHYPER", "tID", "tIDEMPOTENT", "tIIDIS", + "tIMMEDIATEBIND", "tIMPLICITHANDLE", "tIMPORT", "tIMPORTLIB", "tIN", + "tINLINE", "tINPUTSYNC", "tINT", "tINT64", "tINTERFACE", "tLCID", + "tLENGTHIS", "tLIBRARY", "tLOCAL", "tLONG", "tMETHODS", "tMODULE", + "tNONBROWSABLE", "tNONCREATABLE", "tNONEXTENSIBLE", "tOBJECT", "tODL", + "tOLEAUTOMATION", "tOPTIONAL", "tOUT", "tPOINTERDEFAULT", "tPROPERTIES", + "tPROPGET", "tPROPPUT", "tPROPPUTREF", "tPTR", "tPUBLIC", "tRANGE", + "tREADONLY", "tREF", "tREQUESTEDIT", "tRESTRICTED", "tRETVAL", + "tSAFEARRAY", "tSHORT", "tSIGNED", "tSINGLE", "tSIZEIS", "tSIZEOF", + "tSMALL", "tSOURCE", "tSTDCALL", "tSTRING", "tSTRUCT", "tSWITCH", + "tSWITCHIS", "tSWITCHTYPE", "tTRANSMITAS", "tTRUE", "tTYPEDEF", "tUNION", + "tUNIQUE", "tUNSIGNED", "tUUID", "tV1ENUM", "tVARARG", "tVERSION", + "tVOID", "tWCHAR", "tWIREMARSHAL", "','", "'?'", "':'", "'|'", "'&'", + "'-'", "'+'", "'*'", "'/'", "'~'", "CAST", "PPTR", "NEG", "ADDRESSOF", + "';'", "'('", "')'", "'{'", "'}'", "'['", "']'", "'='", "'.'", "$accept", + "input", "gbl_statements", "imp_statements", "int_statements", + "statement", "cppquote", "import_start", "import", "importlib", + "libraryhdr", "library_start", "librarydef", "m_args", "no_args", "args", + "arg", "array", "array_list", "m_attributes", "attributes", + "attrib_list", "str_list", "attribute", "uuid_string", "callconv", + "cases", "case", "constdef", "enums", "enum_list", "enum", "enumdef", + "m_exprs", "m_expr", "expr", "expr_list_const", "expr_const", + "externdef", "fields", "field", "s_field", "funcdef", "m_ident", + "t_ident", "ident", "base_type", "m_int", "int_std", "coclass", + "coclasshdr", "coclassdef", "coclass_ints", "coclass_int", + "dispinterface", "dispinterfacehdr", "dispint_props", "dispint_meths", + "dispinterfacedef", "inherit", "interface", "interfacehdr", + "interfacedef", "interfacedec", "module", "modulehdr", "moduledef", + "p_ident", "pident", "pident_list", "pointer_type", "structdef", "type", + "typedef", "uniondef", "version", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short int yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, + 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, + 385, 386, 44, 63, 58, 124, 38, 45, 43, 42, + 47, 126, 387, 388, 389, 390, 59, 40, 41, 123, + 125, 91, 93, 61, 46 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 155, 156, 157, 157, 157, 157, 157, 157, 157, + 157, 158, 158, 158, 158, 158, 158, 158, 158, 159, + 159, 159, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, + 169, 170, 170, 170, 171, 171, 171, 171, 172, 172, + 172, 173, 173, 173, 174, 174, 175, 176, 176, 176, + 177, 177, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, + 178, 178, 179, 179, 180, 180, 181, 181, 182, 182, + 183, 184, 184, 184, 185, 185, 186, 186, 187, 188, + 188, 189, 189, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 190, 190, 191, 191, 192, 193, 194, + 194, 195, 195, 195, 195, 196, 197, 198, 198, 199, + 199, 199, 200, 200, 201, 201, 201, 201, 201, 201, + 201, 201, 201, 201, 201, 201, 202, 202, 203, 203, + 203, 203, 203, 203, 203, 204, 204, 205, 206, 207, + 207, 208, 209, 209, 210, 211, 211, 212, 212, 213, + 213, 214, 214, 215, 215, 216, 217, 217, 217, 218, + 218, 219, 219, 220, 221, 222, 222, 223, 223, 223, + 224, 224, 225, 225, 225, 226, 227, 227, 227, 227, + 227, 227, 227, 227, 227, 227, 227, 228, 229, 229, + 230, 230 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 1, 0, 2, 2, 3, 2, 2, 2, + 2, 0, 2, 2, 3, 2, 2, 2, 2, 0, + 3, 2, 1, 2, 1, 2, 2, 1, 2, 2, + 2, 4, 3, 3, 4, 2, 3, 3, 0, 1, + 1, 1, 3, 1, 4, 3, 6, 5, 0, 3, + 3, 1, 3, 4, 0, 1, 3, 1, 3, 4, + 1, 3, 0, 1, 1, 1, 1, 1, 4, 4, + 1, 1, 1, 1, 1, 1, 4, 4, 1, 1, + 4, 1, 4, 4, 4, 1, 1, 4, 4, 4, + 4, 4, 1, 4, 1, 4, 1, 5, 1, 1, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 1, 6, 1, 1, 1, 1, + 4, 1, 1, 4, 4, 4, 4, 1, 1, 4, + 4, 1, 1, 1, 0, 1, 0, 2, 4, 3, + 5, 0, 2, 1, 1, 3, 3, 1, 5, 1, + 3, 0, 1, 1, 1, 1, 1, 1, 1, 5, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 4, 4, 3, 1, 3, 1, 4, 0, + 2, 2, 3, 2, 1, 4, 7, 0, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, + 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, + 1, 2, 2, 1, 1, 2, 2, 2, 4, 0, + 2, 2, 2, 2, 2, 2, 3, 2, 3, 5, + 5, 0, 2, 2, 2, 2, 5, 7, 1, 2, + 2, 2, 2, 2, 4, 2, 2, 1, 1, 3, + 1, 3, 1, 1, 1, 5, 1, 1, 1, 2, + 1, 2, 1, 2, 1, 2, 4, 4, 5, 10, + 1, 3 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned short int yydefact[] = +{ + 3, 0, 2, 1, 0, 0, 0, 0, 189, 0, + 0, 0, 189, 54, 189, 22, 62, 10, 24, 11, + 27, 11, 9, 0, 0, 0, 0, 0, 0, 7, + 0, 0, 238, 0, 231, 5, 4, 0, 8, 0, + 0, 0, 215, 216, 257, 203, 194, 214, 0, 202, + 189, 204, 200, 205, 206, 208, 213, 206, 0, 206, + 0, 201, 210, 189, 189, 199, 256, 195, 260, 258, + 196, 262, 0, 264, 0, 222, 223, 190, 191, 0, + 0, 0, 233, 234, 0, 0, 55, 0, 63, 64, + 65, 66, 67, 0, 0, 70, 71, 72, 73, 74, + 75, 0, 78, 79, 0, 81, 0, 0, 85, 86, + 0, 0, 0, 0, 0, 92, 0, 94, 0, 96, + 0, 98, 99, 0, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 0, 111, 112, 113, 254, 114, 0, + 116, 252, 117, 118, 119, 0, 121, 122, 0, 0, + 0, 253, 0, 127, 128, 0, 0, 0, 57, 131, + 0, 0, 0, 0, 0, 217, 224, 235, 243, 23, + 25, 26, 6, 219, 240, 0, 239, 0, 0, 19, + 28, 29, 30, 259, 261, 207, 212, 211, 0, 209, + 197, 263, 265, 198, 192, 193, 0, 0, 141, 0, + 32, 179, 0, 0, 179, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 151, + 0, 0, 151, 0, 0, 0, 0, 0, 0, 62, + 56, 33, 0, 17, 18, 0, 0, 15, 13, 12, + 16, 37, 35, 241, 242, 36, 54, 0, 54, 0, + 0, 232, 19, 54, 0, 0, 31, 0, 143, 144, + 147, 178, 54, 0, 0, 0, 247, 248, 250, 267, + 54, 54, 0, 158, 153, 154, 155, 156, 0, 157, + 0, 0, 0, 0, 0, 177, 0, 175, 0, 0, + 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 149, 152, 0, 0, 0, 0, + 0, 0, 133, 132, 0, 270, 0, 0, 58, 62, + 0, 14, 218, 0, 220, 225, 0, 0, 0, 54, + 0, 0, 54, 244, 21, 0, 0, 266, 140, 148, + 142, 0, 184, 255, 0, 55, 180, 0, 246, 245, + 0, 0, 0, 268, 68, 0, 170, 169, 171, 168, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 69, 77, 76, 80, 0, 82, 83, 84, + 87, 88, 89, 90, 91, 93, 95, 0, 151, 100, + 110, 0, 120, 123, 124, 125, 126, 0, 129, 130, + 59, 0, 221, 227, 0, 226, 229, 0, 230, 19, + 236, 134, 20, 145, 146, 264, 183, 181, 249, 251, + 187, 0, 174, 0, 166, 167, 0, 160, 161, 163, + 162, 164, 165, 176, 61, 97, 150, 0, 271, 34, + 48, 228, 54, 135, 0, 182, 0, 188, 173, 172, + 0, 115, 151, 185, 237, 0, 136, 159, 0, 0, + 51, 38, 0, 50, 0, 49, 256, 0, 43, 39, + 41, 0, 0, 0, 0, 269, 137, 52, 0, 186, + 0, 0, 48, 0, 54, 53, 42, 48, 38, 45, + 54, 139, 38, 44, 0, 138, 0, 47, 46 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const short int yydefgoto[] = +{ + -1, 1, 2, 160, 253, 334, 18, 19, 20, 234, + 164, 21, 22, 467, 468, 469, 470, 453, 459, 335, + 86, 157, 292, 158, 314, 444, 462, 476, 24, 257, + 258, 259, 68, 303, 304, 285, 286, 287, 26, 262, + 346, 347, 336, 446, 79, 266, 69, 186, 70, 165, + 28, 237, 246, 324, 30, 31, 248, 329, 32, 178, + 33, 34, 238, 239, 168, 37, 240, 267, 268, 269, + 159, 71, 472, 40, 73, 316 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -376 +static const short int yypact[] = +{ + -376, 24, 773, -376, 86, 684, -43, 190, 193, 79, + 109, 210, 193, -28, 193, -376, 934, -376, -376, -376, + -376, -376, -376, 27, -20, -14, -7, -5, 20, -376, + 14, 40, -376, 53, 0, -376, -376, 59, -376, 77, + 89, 92, -376, -376, -376, -376, -376, -376, 684, -376, + 213, -376, -376, -376, 178, -376, -376, 178, 108, 178, + -6, -376, -376, 226, 228, -6, -376, -376, -376, -376, + -376, -376, 237, -376, 251, -376, -376, -376, -376, 115, + 684, 122, -376, -376, 123, 684, -376, -91, -376, -376, + -376, -376, -376, 128, 132, -376, -376, -376, -376, -376, + -376, 136, -376, -376, 138, -376, 143, 145, -376, -376, + 146, 147, 148, 151, 152, -376, 153, -376, 154, -376, + 155, -376, -376, 158, -376, -376, -376, -376, -376, -376, + -376, -376, -376, 159, -376, -376, -376, -376, -376, 160, + -376, -376, -376, -376, -376, 161, -376, -376, 162, 163, + 164, -376, 165, -376, -376, 167, 169, -79, -376, -376, + 615, 731, 314, 239, 170, -376, -376, -376, -376, -376, + -376, -376, -376, -376, -376, -16, -376, 241, 171, -376, + -376, -376, -376, -376, 173, -376, -376, -376, 684, -376, + -376, 173, -85, -376, -376, -376, 175, 176, 237, 237, + -376, -376, 48, 179, -376, 237, 382, 243, 310, 321, + 450, 382, 322, 324, 382, 326, 382, 382, 280, 382, + -51, 382, 382, 382, 684, 684, 217, 334, 684, 934, + 195, -376, 194, -376, -376, 16, 198, -376, -376, -376, + -376, -376, -376, -376, -376, -376, 116, 214, -63, 206, + 205, -376, -376, 605, 216, 382, -376, 215, 234, -376, + 218, -376, -32, -15, 48, 48, -376, -376, -376, 240, + -28, -30, 221, -376, -376, -376, -376, -376, 229, -376, + 382, 382, 382, 382, 502, 17, -93, -376, 225, 227, + 230, -376, -83, 233, 235, 238, 244, 245, 246, 247, + 248, 67, 374, -47, -376, 17, 249, 259, -46, 222, + 254, 255, -376, -376, 257, 252, 261, 262, -376, 934, + 399, -376, -376, -10, -376, -376, 277, 684, 266, 131, + 263, 345, 786, -376, -376, 684, 270, -376, -376, -376, + 237, 382, -376, -376, 684, 272, -376, 273, -376, -376, + 285, 48, 286, -376, -376, 684, -376, -376, -376, -376, + 542, 288, 382, 382, 382, 382, 382, 382, 382, 382, + 382, 382, -376, -376, -376, -376, 412, -376, -376, -376, + -376, -376, -376, -376, -376, -376, -376, 289, 382, -376, + -376, 382, -376, -376, -376, -376, -376, 416, -376, -376, + -376, 290, -376, -376, 48, -376, -376, 295, -376, -376, + -376, 333, -376, -376, -376, 303, -376, -376, -376, -376, + 237, 291, -376, 382, -376, -376, 292, 9, 72, -3, + -3, 276, 276, -376, -376, -376, -376, 302, -376, -376, + 300, -376, 795, -376, 48, -376, 305, -376, -376, -376, + 382, -376, 509, -376, -376, 313, -376, 17, 137, -78, + -376, 293, -12, -376, 382, 311, -41, 315, -376, 329, + -376, 684, 48, 382, 330, -376, -376, 17, 382, -376, + 420, 48, -80, 561, -104, 17, -376, 23, 293, -376, + -104, -376, 293, -376, 318, -376, 320, -376, -376 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const short int yypgoto[] = +{ + -376, -376, -376, 451, -236, 11, -376, -376, 140, -376, + -376, -376, -376, -300, -376, -376, -1, -360, -376, -9, + -2, -376, -376, -211, -376, -376, -376, -376, -376, -376, + -376, 133, 3, 258, -365, -187, -376, -173, -376, 281, + -375, -208, 168, -376, 49, -70, -376, 74, 65, 25, + -376, 475, -376, -376, -13, -376, -376, -376, -376, -376, + -8, -376, 482, 4, -376, -376, 485, 236, -253, -376, + 269, 5, -4, -376, 1, -376 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -191 +static const short int yytable[] = +{ + 23, 72, 196, 41, 85, 25, 36, 39, 362, 363, + 166, 349, 350, 17, 473, 167, 332, 263, 318, 326, + 362, 363, 47, 436, 3, 203, 474, 27, 362, 363, + 301, -190, 305, 7, 289, 305, 309, 294, 295, 371, + 328, 298, 342, 300, 183, 4, 137, 16, 307, 376, + 141, 194, 195, 229, 464, 372, 4, 54, 204, 7, + 11, 84, 352, 87, -190, 377, 11, 488, 55, 56, + 7, 452, 151, 230, 465, 57, 199, 247, 362, 363, + 263, 202, 338, 362, 363, 388, 388, 460, 16, 42, + 43, -40, 11, 356, 357, 358, 359, 360, 419, 163, + 59, 389, 392, 11, 74, 62, 162, -40, 400, 491, + 163, 80, 84, 87, 342, 495, 342, 81, 343, 16, + 353, 16, 489, 16, 264, 190, 169, 493, 260, 261, + 193, 187, 170, 189, 177, 272, 369, 370, 475, 171, + 273, 172, 274, 275, 276, 366, 367, 368, 369, 370, + 364, 440, 365, 366, 367, 368, 369, 370, 235, 235, + 174, 41, 41, 25, 25, 39, 39, 249, 414, 173, + 492, 233, 233, 442, 452, 424, 425, 426, 427, 428, + 429, 430, 431, 432, 254, 236, 236, 264, 494, 175, + 277, 455, 496, 75, 76, 265, 77, 78, 433, 176, + 364, 305, 365, 366, 367, 368, 369, 370, 179, 367, + 368, 369, 370, 82, 83, 386, 184, 78, 437, 482, + 310, 311, 166, 180, 317, 312, 313, 167, 487, 191, + 78, 192, 78, 362, 363, 181, 449, 323, 182, 327, + 194, 195, 243, 244, 250, 251, 273, 278, 274, 275, + 276, 288, 185, 344, 41, 188, 25, 279, 39, 197, + 345, 327, 344, 457, 198, 305, 322, 16, 200, 345, + 260, 358, 201, 280, 281, 205, 282, 477, 283, 206, + 361, 406, 16, 207, 284, 208, 483, 362, 363, 463, + 209, 485, 210, 211, 212, 213, 277, 44, 214, 215, + 216, 217, 218, 362, 363, 219, 220, 221, 222, 223, + 224, 225, 226, 45, 227, 46, 228, 242, 290, 245, + 252, 47, -190, 404, 256, 48, 270, 402, 255, 291, + 296, 411, 297, 41, 299, 25, 302, 39, 49, 315, + 404, 320, 50, 51, 321, 415, 319, 52, 325, 53, + 447, 421, 330, 278, 331, 364, 54, 365, 366, 367, + 368, 369, 370, 279, 337, 339, 340, 55, 56, 354, + 393, 341, 351, 373, 57, 374, 355, 387, 375, 280, + 281, 378, 282, 379, 283, 273, 380, 274, 275, 276, + 284, 391, 381, 382, 383, 384, 385, 390, 58, 59, + 60, 61, 394, 395, 62, 396, 397, 401, 63, 398, + 399, 403, 405, 408, 10, 64, 412, 65, 416, 417, + 434, 438, 466, 67, 44, 364, 450, 365, 366, 367, + 368, 369, 370, 418, 420, 277, 423, 435, 439, 448, + 45, 441, 46, 41, 16, 25, 443, 39, 47, 445, + 451, 452, 48, 273, 456, 274, 275, 276, 293, 471, + 461, 480, 478, 479, 484, 49, 497, 481, 498, 50, + 51, 409, 161, 413, 52, 344, 53, 29, 471, 486, + 308, 344, 345, 54, 35, 271, 471, 38, 345, 306, + 471, 0, 278, 0, 55, 56, 0, 407, 0, 348, + 0, 57, 279, 277, 0, 273, 44, 274, 275, 276, + 0, 0, 273, 0, 274, 275, 276, 0, 280, 281, + 0, 282, 45, 283, 46, 58, 59, 60, 61, 284, + 47, 62, 0, 0, 48, 63, 0, 0, 0, 0, + 0, 0, 64, 0, 65, 0, 0, 49, 0, 66, + 67, 50, 51, 362, 363, 277, 52, 0, 53, 0, + 278, 0, 277, 0, 0, 54, 0, 0, 0, 0, + 279, 16, 362, 363, 0, 0, 55, 56, 0, 0, + 0, 0, 0, 57, 0, 0, 280, 281, 0, 282, + 0, 283, 0, 0, 0, 0, 0, 284, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 58, 59, 60, + 61, 0, 278, 62, 0, 0, 0, 63, 0, 278, + 0, 0, 279, 0, 64, 231, 65, 0, 0, 279, + 0, 66, 67, 0, 0, 0, 0, 5, 280, 281, + 0, 282, 6, 283, 4, 280, 281, 5, 458, 284, + 283, 0, 6, 0, 8, 0, 284, 9, 7, 0, + 0, 0, 0, 0, 8, 0, 0, 9, 0, 0, + 0, 0, 0, 0, 10, 364, 0, 365, 366, 367, + 368, 369, 370, 0, 10, 232, 0, 0, 44, 0, + 422, 11, 0, 0, 364, 490, 365, 366, 367, 368, + 369, 370, 0, 0, 45, 0, 46, 0, 0, 0, + 0, 0, 47, 0, 0, 0, 48, 0, 0, 0, + 12, 0, 0, 0, 0, 0, 13, 14, 0, 49, + 12, 0, 0, 50, 51, 0, 13, 14, 52, 0, + 53, 0, 0, 0, 0, 0, 0, 54, 0, 0, + 0, 15, 0, 0, 0, 333, 16, 0, 55, 56, + 4, 15, 0, 5, 0, 57, 16, 0, 6, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, + 8, 0, 0, 9, 0, 0, 0, 0, 0, 58, + 59, 60, 61, 0, 0, 62, 0, 0, 0, 63, + 10, 232, 4, 0, 0, 5, 64, 11, 65, 0, + 6, 0, 0, 66, 67, 0, 7, 0, 5, 0, + 0, 0, 8, 6, 0, 9, 0, 5, 0, 0, + 0, 0, 6, 0, 0, 8, 0, 0, 9, 0, + 0, 0, 10, 0, 8, 0, 12, 9, 0, 11, + 0, 0, 13, 14, 0, 10, 0, 0, 0, 0, + 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, + 0, 241, 16, 0, 0, 0, 0, 0, 12, 0, + 0, 0, 0, 0, 13, 14, 0, 0, 0, 0, + 0, 12, 0, 0, 0, 0, 0, 13, 14, 0, + 12, 0, 0, 0, 0, 0, 13, 14, 0, 15, + 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, 410, 16, 0, 0, + 0, 15, 0, 0, 0, 454, 16, 88, 0, 89, + 90, 0, 91, 92, 0, 0, 0, 0, 93, 0, + 94, 0, 0, 0, 0, 0, 0, 95, 96, 97, + 98, 0, 99, 100, 101, 102, 103, 0, 104, 0, + 105, 106, 107, 0, 0, 108, 0, 0, 0, 109, + 0, 110, 111, 112, 113, 114, 115, 0, 116, 117, + 118, 119, 120, 0, 0, 121, 0, 122, 0, 0, + 0, 0, 123, 0, 124, 0, 0, 0, 125, 126, + 127, 128, 129, 130, 131, 132, 133, 0, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, 144, 0, + 0, 0, 0, 145, 0, 0, 146, 0, 147, 0, + 0, 148, 149, 150, 0, 0, 0, 151, 0, 152, + 153, 154, 155, 0, 0, 156 +}; + +static const short int yycheck[] = +{ + 2, 5, 72, 2, 13, 2, 2, 2, 11, 12, + 23, 264, 265, 2, 26, 23, 252, 32, 229, 82, + 11, 12, 28, 388, 0, 116, 38, 2, 11, 12, + 217, 116, 219, 43, 207, 222, 223, 210, 211, 132, + 248, 214, 146, 216, 48, 29, 97, 151, 221, 132, + 101, 3, 4, 132, 132, 148, 29, 63, 149, 43, + 76, 12, 270, 14, 149, 148, 76, 147, 74, 75, + 43, 151, 123, 152, 152, 81, 80, 93, 11, 12, + 32, 85, 255, 11, 12, 132, 132, 452, 151, 3, + 4, 132, 76, 280, 281, 282, 283, 284, 351, 83, + 106, 148, 148, 76, 147, 111, 79, 148, 319, 484, + 83, 32, 63, 64, 146, 490, 146, 8, 150, 151, + 150, 151, 482, 151, 139, 60, 146, 487, 198, 199, + 65, 57, 146, 59, 134, 205, 139, 140, 150, 146, + 3, 146, 5, 6, 7, 136, 137, 138, 139, 140, + 133, 404, 135, 136, 137, 138, 139, 140, 160, 161, + 146, 160, 161, 160, 161, 160, 161, 175, 341, 149, + 147, 160, 161, 409, 151, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 188, 160, 161, 139, 488, 149, + 53, 444, 492, 3, 4, 147, 3, 4, 371, 146, + 133, 388, 135, 136, 137, 138, 139, 140, 149, 137, + 138, 139, 140, 3, 4, 148, 3, 4, 391, 472, + 224, 225, 235, 146, 228, 8, 9, 235, 481, 3, + 4, 3, 4, 11, 12, 146, 423, 246, 146, 248, + 3, 4, 3, 4, 3, 4, 3, 110, 5, 6, + 7, 8, 74, 262, 253, 147, 253, 120, 253, 8, + 262, 270, 271, 450, 149, 452, 150, 151, 146, 271, + 340, 458, 149, 136, 137, 147, 139, 464, 141, 147, + 284, 150, 151, 147, 147, 147, 473, 11, 12, 152, + 147, 478, 147, 147, 147, 147, 53, 4, 147, 147, + 147, 147, 147, 11, 12, 147, 147, 147, 147, 147, + 147, 147, 147, 20, 147, 22, 147, 3, 8, 149, + 149, 28, 149, 327, 148, 32, 147, 323, 153, 8, + 8, 335, 8, 332, 8, 332, 56, 332, 45, 5, + 344, 147, 49, 50, 146, 344, 151, 54, 134, 56, + 420, 355, 146, 110, 149, 133, 63, 135, 136, 137, + 138, 139, 140, 120, 148, 150, 132, 74, 75, 148, + 148, 153, 132, 148, 81, 148, 147, 3, 148, 136, + 137, 148, 139, 148, 141, 3, 148, 5, 6, 7, + 147, 132, 148, 148, 148, 148, 148, 148, 105, 106, + 107, 108, 148, 148, 111, 148, 154, 8, 115, 148, + 148, 134, 146, 150, 69, 122, 146, 124, 146, 146, + 8, 5, 129, 130, 4, 133, 134, 135, 136, 137, + 138, 139, 140, 148, 148, 53, 148, 148, 148, 148, + 20, 146, 22, 442, 151, 442, 113, 442, 28, 146, + 148, 151, 32, 3, 149, 5, 6, 7, 8, 461, + 147, 132, 151, 148, 134, 45, 148, 471, 148, 49, + 50, 331, 21, 340, 54, 484, 56, 2, 480, 480, + 222, 490, 484, 63, 2, 204, 488, 2, 490, 220, + 492, -1, 110, -1, 74, 75, -1, 329, -1, 263, + -1, 81, 120, 53, -1, 3, 4, 5, 6, 7, + -1, -1, 3, -1, 5, 6, 7, -1, 136, 137, + -1, 139, 20, 141, 22, 105, 106, 107, 108, 147, + 28, 111, -1, -1, 32, 115, -1, -1, -1, -1, + -1, -1, 122, -1, 124, -1, -1, 45, -1, 129, + 130, 49, 50, 11, 12, 53, 54, -1, 56, -1, + 110, -1, 53, -1, -1, 63, -1, -1, -1, -1, + 120, 151, 11, 12, -1, -1, 74, 75, -1, -1, + -1, -1, -1, 81, -1, -1, 136, 137, -1, 139, + -1, 141, -1, -1, -1, -1, -1, 147, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 105, 106, 107, + 108, -1, 110, 111, -1, -1, -1, 115, -1, 110, + -1, -1, 120, -1, 122, 10, 124, -1, -1, 120, + -1, 129, 130, -1, -1, -1, -1, 32, 136, 137, + -1, 139, 37, 141, 29, 136, 137, 32, 139, 147, + 141, -1, 37, -1, 49, -1, 147, 52, 43, -1, + -1, -1, -1, -1, 49, -1, -1, 52, -1, -1, + -1, -1, -1, -1, 69, 133, -1, 135, 136, 137, + 138, 139, 140, -1, 69, 70, -1, -1, 4, -1, + 148, 76, -1, -1, 133, 134, 135, 136, 137, 138, + 139, 140, -1, -1, 20, -1, 22, -1, -1, -1, + -1, -1, 28, -1, -1, -1, 32, -1, -1, -1, + 115, -1, -1, -1, -1, -1, 121, 122, -1, 45, + 115, -1, -1, 49, 50, -1, 121, 122, 54, -1, + 56, -1, -1, -1, -1, -1, -1, 63, -1, -1, + -1, 146, -1, -1, -1, 150, 151, -1, 74, 75, + 29, 146, -1, 32, -1, 81, 151, -1, 37, -1, + -1, -1, -1, -1, 43, -1, -1, -1, -1, -1, + 49, -1, -1, 52, -1, -1, -1, -1, -1, 105, + 106, 107, 108, -1, -1, 111, -1, -1, -1, 115, + 69, 70, 29, -1, -1, 32, 122, 76, 124, -1, + 37, -1, -1, 129, 130, -1, 43, -1, 32, -1, + -1, -1, 49, 37, -1, 52, -1, 32, -1, -1, + -1, -1, 37, -1, -1, 49, -1, -1, 52, -1, + -1, -1, 69, -1, 49, -1, 115, 52, -1, 76, + -1, -1, 121, 122, -1, 69, -1, -1, -1, -1, + -1, -1, -1, -1, 69, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 146, -1, -1, + -1, 150, 151, -1, -1, -1, -1, -1, 115, -1, + -1, -1, -1, -1, 121, 122, -1, -1, -1, -1, + -1, 115, -1, -1, -1, -1, -1, 121, 122, -1, + 115, -1, -1, -1, -1, -1, 121, 122, -1, 146, + -1, -1, -1, -1, 151, -1, -1, -1, -1, -1, + -1, -1, 146, -1, -1, -1, 150, 151, -1, -1, + -1, 146, -1, -1, -1, 150, 151, 13, -1, 15, + 16, -1, 18, 19, -1, -1, -1, -1, 24, -1, + 26, -1, -1, -1, -1, -1, -1, 33, 34, 35, + 36, -1, 38, 39, 40, 41, 42, -1, 44, -1, + 46, 47, 48, -1, -1, 51, -1, -1, -1, 55, + -1, 57, 58, 59, 60, 61, 62, -1, 64, 65, + 66, 67, 68, -1, -1, 71, -1, 73, -1, -1, + -1, -1, 78, -1, 80, -1, -1, -1, 84, 85, + 86, 87, 88, 89, 90, 91, 92, -1, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, -1, + -1, -1, -1, 109, -1, -1, 112, -1, 114, -1, + -1, 117, 118, 119, -1, -1, -1, 123, -1, 125, + 126, 127, 128, -1, -1, 131 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 156, 157, 0, 29, 32, 37, 43, 49, 52, + 69, 76, 115, 121, 122, 146, 151, 160, 161, 162, + 163, 166, 167, 175, 183, 187, 193, 204, 205, 206, + 209, 210, 213, 215, 216, 217, 218, 220, 221, 226, + 228, 229, 3, 4, 4, 20, 22, 28, 32, 45, + 49, 50, 54, 56, 63, 74, 75, 81, 105, 106, + 107, 108, 111, 115, 122, 124, 129, 130, 187, 201, + 203, 226, 227, 229, 147, 3, 4, 3, 4, 199, + 32, 8, 3, 4, 199, 174, 175, 199, 13, 15, + 16, 18, 19, 24, 26, 33, 34, 35, 36, 38, + 39, 40, 41, 42, 44, 46, 47, 48, 51, 55, + 57, 58, 59, 60, 61, 62, 64, 65, 66, 67, + 68, 71, 73, 78, 80, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 94, 95, 96, 97, 98, 99, + 100, 101, 102, 103, 104, 109, 112, 114, 117, 118, + 119, 123, 125, 126, 127, 128, 131, 176, 178, 225, + 158, 158, 79, 83, 165, 204, 209, 215, 219, 146, + 146, 146, 146, 149, 146, 149, 146, 134, 214, 149, + 146, 146, 146, 227, 3, 74, 202, 202, 147, 202, + 203, 3, 3, 203, 3, 4, 200, 8, 149, 227, + 146, 149, 227, 116, 149, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 132, + 152, 10, 70, 160, 164, 175, 204, 206, 217, 218, + 221, 150, 3, 3, 4, 149, 207, 93, 211, 215, + 3, 4, 149, 159, 227, 153, 148, 184, 185, 186, + 200, 200, 194, 32, 139, 147, 200, 222, 223, 224, + 147, 194, 200, 3, 5, 6, 7, 53, 110, 120, + 136, 137, 139, 141, 147, 190, 191, 192, 8, 192, + 8, 8, 177, 8, 192, 192, 8, 8, 192, 8, + 192, 190, 56, 188, 189, 190, 225, 192, 188, 190, + 227, 227, 8, 9, 179, 5, 230, 227, 178, 151, + 147, 146, 150, 174, 208, 134, 82, 174, 196, 212, + 146, 149, 159, 150, 160, 174, 197, 148, 192, 150, + 132, 153, 146, 150, 174, 175, 195, 196, 222, 223, + 223, 132, 196, 150, 148, 147, 190, 190, 190, 190, + 190, 227, 11, 12, 133, 135, 136, 137, 138, 139, + 140, 132, 148, 148, 148, 148, 132, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 3, 132, 148, + 148, 132, 148, 148, 148, 148, 148, 154, 148, 148, + 178, 8, 218, 134, 227, 146, 150, 197, 150, 163, + 150, 227, 146, 186, 192, 229, 146, 146, 148, 223, + 148, 227, 148, 148, 190, 190, 190, 190, 190, 190, + 190, 190, 190, 192, 8, 148, 189, 192, 5, 148, + 223, 146, 159, 113, 180, 146, 198, 200, 148, 190, + 134, 148, 151, 172, 150, 223, 149, 190, 139, 173, + 189, 147, 181, 152, 132, 152, 129, 168, 169, 170, + 171, 175, 227, 26, 38, 150, 182, 190, 151, 148, + 132, 227, 223, 190, 134, 190, 171, 223, 147, 172, + 134, 195, 147, 172, 168, 195, 168, 148, 148 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (N) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (0) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short int *bottom, short int *top) +#else +static void +yy_stack_print (bottom, top) + short int *bottom; + short int *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", + yyrule - 1, yylno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + size_t yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +#endif /* YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + ; +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short int yyssa[YYINITDEPTH]; + short int *yyss = yyssa; + short int *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short int *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short int *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a look-ahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to look-ahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 285 "parser.y" + { fix_incomplete(); + check_all_user_types((yyvsp[0].ifref_list)); + write_proxies((yyvsp[0].ifref_list)); + write_client((yyvsp[0].ifref_list)); + write_server((yyvsp[0].ifref_list)); + write_dlldata((yyvsp[0].ifref_list)); + ;} + break; + + case 3: +#line 294 "parser.y" + { (yyval.ifref_list) = NULL; ;} + break; + + case 4: +#line 295 "parser.y" + { (yyval.ifref_list) = (yyvsp[-1].ifref_list); ;} + break; + + case 5: +#line 296 "parser.y" + { (yyval.ifref_list) = append_ifref( (yyvsp[-1].ifref_list), make_ifref((yyvsp[0].type)) ); ;} + break; + + case 6: +#line 297 "parser.y" + { (yyval.ifref_list) = (yyvsp[-2].ifref_list); + reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, 0); + if (!parse_only && do_header) write_coclass_forward((yyvsp[-1].type)); + ;} + break; + + case 7: +#line 301 "parser.y" + { (yyval.ifref_list) = (yyvsp[-1].ifref_list); + add_typelib_entry((yyvsp[0].type)); + reg_type((yyvsp[0].type), (yyvsp[0].type)->name, 0); + if (!parse_only && do_header) write_coclass_forward((yyvsp[0].type)); + ;} + break; + + case 8: +#line 306 "parser.y" + { (yyval.ifref_list) = (yyvsp[-1].ifref_list); add_typelib_entry((yyvsp[0].type)); ;} + break; + + case 9: +#line 307 "parser.y" + { (yyval.ifref_list) = (yyvsp[-1].ifref_list); ;} + break; + + case 10: +#line 308 "parser.y" + { (yyval.ifref_list) = (yyvsp[-1].ifref_list); ;} + break; + + case 11: +#line 311 "parser.y" + {;} + break; + + case 12: +#line 312 "parser.y" + { if (!parse_only) add_typelib_entry((yyvsp[0].type)); ;} + break; + + case 13: +#line 313 "parser.y" + { if (!parse_only) add_typelib_entry((yyvsp[0].type)); ;} + break; + + case 14: +#line 314 "parser.y" + { reg_type((yyvsp[-1].type), (yyvsp[-1].type)->name, 0); if (!parse_only && do_header) write_coclass_forward((yyvsp[-1].type)); ;} + break; + + case 15: +#line 315 "parser.y" + { if (!parse_only) add_typelib_entry((yyvsp[0].type)); + reg_type((yyvsp[0].type), (yyvsp[0].type)->name, 0); + if (!parse_only && do_header) write_coclass_forward((yyvsp[0].type)); + ;} + break; + + case 16: +#line 319 "parser.y" + { if (!parse_only) add_typelib_entry((yyvsp[0].type)); ;} + break; + + case 17: +#line 320 "parser.y" + {;} + break; + + case 18: +#line 321 "parser.y" + {;} + break; + + case 19: +#line 324 "parser.y" + { (yyval.func_list) = NULL; ;} + break; + + case 20: +#line 325 "parser.y" + { (yyval.func_list) = append_func( (yyvsp[-2].func_list), (yyvsp[-1].func) ); ;} + break; + + case 21: +#line 326 "parser.y" + { (yyval.func_list) = (yyvsp[-1].func_list); ;} + break; + + case 22: +#line 329 "parser.y" + {;} + break; + + case 23: +#line 330 "parser.y" + { if (!parse_only && do_header) { write_constdef((yyvsp[-1].var)); } ;} + break; + + case 24: +#line 331 "parser.y" + {;} + break; + + case 25: +#line 332 "parser.y" + { if (!parse_only && do_header) { + write_type_def_or_decl(header, (yyvsp[-1].type), FALSE, NULL); + fprintf(header, ";\n\n"); + } + ;} + break; + + case 26: +#line 337 "parser.y" + { if (!parse_only && do_header) { write_externdef((yyvsp[-1].var)); } ;} + break; + + case 27: +#line 338 "parser.y" + {;} + break; + + case 28: +#line 339 "parser.y" + { if (!parse_only && do_header) { + write_type_def_or_decl(header, (yyvsp[-1].type), FALSE, NULL); + fprintf(header, ";\n\n"); + } + ;} + break; + + case 29: +#line 344 "parser.y" + {;} + break; + + case 30: +#line 345 "parser.y" + { if (!parse_only && do_header) { + write_type_def_or_decl(header, (yyvsp[-1].type), FALSE, NULL); + fprintf(header, ";\n\n"); + } + ;} + break; + + case 31: +#line 352 "parser.y" + { if (!parse_only && do_header) fprintf(header, "%s\n", (yyvsp[-1].str)); ;} + break; + + case 32: +#line 354 "parser.y" + { assert(yychar == YYEMPTY); + if (!do_import((yyvsp[-1].str))) yychar = aEOF; ;} + break; + + case 33: +#line 357 "parser.y" + {;} + break; + + case 34: +#line 360 "parser.y" + { if(!parse_only) add_importlib((yyvsp[-1].str)); ;} + break; + + case 35: +#line 363 "parser.y" + { (yyval.str) = (yyvsp[0].str); ;} + break; + + case 36: +#line 365 "parser.y" + { start_typelib((yyvsp[-1].str), (yyvsp[-2].attr_list)); + if (!parse_only && do_header) write_library((yyvsp[-1].str), (yyvsp[-2].attr_list)); + if (!parse_only && do_idfile) write_libid((yyvsp[-1].str), (yyvsp[-2].attr_list)); + ;} + break; + + case 37: +#line 370 "parser.y" + { end_typelib(); ;} + break; + + case 38: +#line 373 "parser.y" + { (yyval.var_list) = NULL; ;} + break; + + case 40: +#line 377 "parser.y" + { (yyval.var_list) = NULL; ;} + break; + + case 41: +#line 380 "parser.y" + { check_arg((yyvsp[0].var)); (yyval.var_list) = append_var( NULL, (yyvsp[0].var) ); ;} + break; + + case 42: +#line 381 "parser.y" + { check_arg((yyvsp[0].var)); (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var)); ;} + break; + + case 44: +#line 386 "parser.y" + { (yyval.var) = (yyvsp[-1].pident)->var; + (yyval.var)->attrs = (yyvsp[-3].attr_list); + set_type((yyval.var), (yyvsp[-2].type), (yyvsp[-1].pident)->ptr_level, (yyvsp[0].array_dims), TRUE); + free((yyvsp[-1].pident)); + ;} + break; + + case 45: +#line 391 "parser.y" + { (yyval.var) = (yyvsp[-1].pident)->var; + set_type((yyval.var), (yyvsp[-2].type), (yyvsp[-1].pident)->ptr_level, (yyvsp[0].array_dims), TRUE); + free((yyvsp[-1].pident)); + ;} + break; + + case 46: +#line 395 "parser.y" + { (yyval.var) = (yyvsp[-3].pident)->var; + (yyval.var)->attrs = (yyvsp[-5].attr_list); + set_type((yyval.var), (yyvsp[-4].type), (yyvsp[-3].pident)->ptr_level - 1, NULL, TRUE); + free((yyvsp[-3].pident)); + (yyval.var)->args = (yyvsp[-1].var_list); + ;} + break; + + case 47: +#line 401 "parser.y" + { (yyval.var) = (yyvsp[-3].pident)->var; + set_type((yyval.var), (yyvsp[-4].type), (yyvsp[-3].pident)->ptr_level - 1, NULL, TRUE); + free((yyvsp[-3].pident)); + (yyval.var)->args = (yyvsp[-1].var_list); + ;} + break; + + case 48: +#line 408 "parser.y" + { (yyval.array_dims) = NULL; ;} + break; + + case 49: +#line 409 "parser.y" + { (yyval.array_dims) = (yyvsp[-1].array_dims); ;} + break; + + case 50: +#line 410 "parser.y" + { (yyval.array_dims) = append_array( NULL, make_expr(EXPR_VOID) ); ;} + break; + + case 51: +#line 413 "parser.y" + { (yyval.array_dims) = append_array( NULL, (yyvsp[0].expr) ); ;} + break; + + case 52: +#line 414 "parser.y" + { (yyval.array_dims) = append_array( (yyvsp[-2].array_dims), (yyvsp[0].expr) ); ;} + break; + + case 53: +#line 415 "parser.y" + { (yyval.array_dims) = append_array( (yyvsp[-3].array_dims), (yyvsp[0].expr) ); ;} + break; + + case 54: +#line 418 "parser.y" + { (yyval.attr_list) = NULL; ;} + break; + + case 56: +#line 423 "parser.y" + { (yyval.attr_list) = (yyvsp[-1].attr_list); + if (!(yyval.attr_list)) + error_loc("empty attribute lists unsupported\n"); + ;} + break; + + case 57: +#line 429 "parser.y" + { (yyval.attr_list) = append_attr( NULL, (yyvsp[0].attr) ); ;} + break; + + case 58: +#line 430 "parser.y" + { (yyval.attr_list) = append_attr( (yyvsp[-2].attr_list), (yyvsp[0].attr) ); ;} + break; + + case 59: +#line 431 "parser.y" + { (yyval.attr_list) = append_attr( (yyvsp[-3].attr_list), (yyvsp[0].attr) ); ;} + break; + + case 60: +#line 434 "parser.y" + { (yyval.str_list) = append_str( NULL, (yyvsp[0].str) ); ;} + break; + + case 61: +#line 435 "parser.y" + { (yyval.str_list) = append_str( (yyvsp[-2].str_list), (yyvsp[0].str) ); ;} + break; + + case 62: +#line 438 "parser.y" + { (yyval.attr) = NULL; ;} + break; + + case 63: +#line 439 "parser.y" + { (yyval.attr) = make_attr(ATTR_AGGREGATABLE); ;} + break; + + case 64: +#line 440 "parser.y" + { (yyval.attr) = make_attr(ATTR_APPOBJECT); ;} + break; + + case 65: +#line 441 "parser.y" + { (yyval.attr) = make_attr(ATTR_ASYNC); ;} + break; + + case 66: +#line 442 "parser.y" + { (yyval.attr) = make_attr(ATTR_AUTO_HANDLE); ;} + break; + + case 67: +#line 443 "parser.y" + { (yyval.attr) = make_attr(ATTR_BINDABLE); ;} + break; + + case 68: +#line 444 "parser.y" + { (yyval.attr) = make_attrp(ATTR_CALLAS, (yyvsp[-1].var)); ;} + break; + + case 69: +#line 445 "parser.y" + { (yyval.attr) = make_attrp(ATTR_CASE, (yyvsp[-1].expr_list)); ;} + break; + + case 70: +#line 446 "parser.y" + { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); ;} + break; + + case 71: +#line 447 "parser.y" + { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ ;} + break; + + case 72: +#line 448 "parser.y" + { (yyval.attr) = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ ;} + break; + + case 73: +#line 449 "parser.y" + { (yyval.attr) = make_attr(ATTR_CONTROL); ;} + break; + + case 74: +#line 450 "parser.y" + { (yyval.attr) = make_attr(ATTR_DEFAULT); ;} + break; + + case 75: +#line 451 "parser.y" + { (yyval.attr) = make_attr(ATTR_DEFAULTCOLLELEM); ;} + break; + + case 76: +#line 452 "parser.y" + { (yyval.attr) = make_attrp(ATTR_DEFAULTVALUE_EXPR, (yyvsp[-1].expr)); ;} + break; + + case 77: +#line 453 "parser.y" + { (yyval.attr) = make_attrp(ATTR_DEFAULTVALUE_STRING, (yyvsp[-1].str)); ;} + break; + + case 78: +#line 454 "parser.y" + { (yyval.attr) = make_attr(ATTR_DEFAULTVTABLE); ;} + break; + + case 79: +#line 455 "parser.y" + { (yyval.attr) = make_attr(ATTR_DISPLAYBIND); ;} + break; + + case 80: +#line 456 "parser.y" + { (yyval.attr) = make_attrp(ATTR_DLLNAME, (yyvsp[-1].str)); ;} + break; + + case 81: +#line 457 "parser.y" + { (yyval.attr) = make_attr(ATTR_DUAL); ;} + break; + + case 82: +#line 458 "parser.y" + { (yyval.attr) = make_attrp(ATTR_ENDPOINT, (yyvsp[-1].str_list)); ;} + break; + + case 83: +#line 459 "parser.y" + { (yyval.attr) = make_attrp(ATTR_ENTRY_STRING, (yyvsp[-1].str)); ;} + break; + + case 84: +#line 460 "parser.y" + { (yyval.attr) = make_attrp(ATTR_ENTRY_ORDINAL, (yyvsp[-1].expr)); ;} + break; + + case 85: +#line 461 "parser.y" + { (yyval.attr) = make_attr(ATTR_EXPLICIT_HANDLE); ;} + break; + + case 86: +#line 462 "parser.y" + { (yyval.attr) = make_attr(ATTR_HANDLE); ;} + break; + + case 87: +#line 463 "parser.y" + { (yyval.attr) = make_attrp(ATTR_HELPCONTEXT, (yyvsp[-1].expr)); ;} + break; + + case 88: +#line 464 "parser.y" + { (yyval.attr) = make_attrp(ATTR_HELPFILE, (yyvsp[-1].str)); ;} + break; + + case 89: +#line 465 "parser.y" + { (yyval.attr) = make_attrp(ATTR_HELPSTRING, (yyvsp[-1].str)); ;} + break; + + case 90: +#line 466 "parser.y" + { (yyval.attr) = make_attrp(ATTR_HELPSTRINGCONTEXT, (yyvsp[-1].expr)); ;} + break; + + case 91: +#line 467 "parser.y" + { (yyval.attr) = make_attrp(ATTR_HELPSTRINGDLL, (yyvsp[-1].str)); ;} + break; + + case 92: +#line 468 "parser.y" + { (yyval.attr) = make_attr(ATTR_HIDDEN); ;} + break; + + case 93: +#line 469 "parser.y" + { (yyval.attr) = make_attrp(ATTR_ID, (yyvsp[-1].expr)); ;} + break; + + case 94: +#line 470 "parser.y" + { (yyval.attr) = make_attr(ATTR_IDEMPOTENT); ;} + break; + + case 95: +#line 471 "parser.y" + { (yyval.attr) = make_attrp(ATTR_IIDIS, (yyvsp[-1].expr)); ;} + break; + + case 96: +#line 472 "parser.y" + { (yyval.attr) = make_attr(ATTR_IMMEDIATEBIND); ;} + break; + + case 97: +#line 473 "parser.y" + { (yyval.attr) = make_attrp(ATTR_IMPLICIT_HANDLE, (yyvsp[-1].str)); ;} + break; + + case 98: +#line 474 "parser.y" + { (yyval.attr) = make_attr(ATTR_IN); ;} + break; + + case 99: +#line 475 "parser.y" + { (yyval.attr) = make_attr(ATTR_INPUTSYNC); ;} + break; + + case 100: +#line 476 "parser.y" + { (yyval.attr) = make_attrp(ATTR_LENGTHIS, (yyvsp[-1].expr_list)); ;} + break; + + case 101: +#line 477 "parser.y" + { (yyval.attr) = make_attr(ATTR_LOCAL); ;} + break; + + case 102: +#line 478 "parser.y" + { (yyval.attr) = make_attr(ATTR_NONBROWSABLE); ;} + break; + + case 103: +#line 479 "parser.y" + { (yyval.attr) = make_attr(ATTR_NONCREATABLE); ;} + break; + + case 104: +#line 480 "parser.y" + { (yyval.attr) = make_attr(ATTR_NONEXTENSIBLE); ;} + break; + + case 105: +#line 481 "parser.y" + { (yyval.attr) = make_attr(ATTR_OBJECT); ;} + break; + + case 106: +#line 482 "parser.y" + { (yyval.attr) = make_attr(ATTR_ODL); ;} + break; + + case 107: +#line 483 "parser.y" + { (yyval.attr) = make_attr(ATTR_OLEAUTOMATION); ;} + break; + + case 108: +#line 484 "parser.y" + { (yyval.attr) = make_attr(ATTR_OPTIONAL); ;} + break; + + case 109: +#line 485 "parser.y" + { (yyval.attr) = make_attr(ATTR_OUT); ;} + break; + + case 110: +#line 486 "parser.y" + { (yyval.attr) = make_attrv(ATTR_POINTERDEFAULT, (yyvsp[-1].num)); ;} + break; + + case 111: +#line 487 "parser.y" + { (yyval.attr) = make_attr(ATTR_PROPGET); ;} + break; + + case 112: +#line 488 "parser.y" + { (yyval.attr) = make_attr(ATTR_PROPPUT); ;} + break; + + case 113: +#line 489 "parser.y" + { (yyval.attr) = make_attr(ATTR_PROPPUTREF); ;} + break; + + case 114: +#line 490 "parser.y" + { (yyval.attr) = make_attr(ATTR_PUBLIC); ;} + break; + + case 115: +#line 491 "parser.y" + { expr_list_t *list = append_expr( NULL, (yyvsp[-3].expr) ); + list = append_expr( list, (yyvsp[-1].expr) ); + (yyval.attr) = make_attrp(ATTR_RANGE, list); ;} + break; + + case 116: +#line 494 "parser.y" + { (yyval.attr) = make_attr(ATTR_READONLY); ;} + break; + + case 117: +#line 495 "parser.y" + { (yyval.attr) = make_attr(ATTR_REQUESTEDIT); ;} + break; + + case 118: +#line 496 "parser.y" + { (yyval.attr) = make_attr(ATTR_RESTRICTED); ;} + break; + + case 119: +#line 497 "parser.y" + { (yyval.attr) = make_attr(ATTR_RETVAL); ;} + break; + + case 120: +#line 498 "parser.y" + { (yyval.attr) = make_attrp(ATTR_SIZEIS, (yyvsp[-1].expr_list)); ;} + break; + + case 121: +#line 499 "parser.y" + { (yyval.attr) = make_attr(ATTR_SOURCE); ;} + break; + + case 122: +#line 500 "parser.y" + { (yyval.attr) = make_attr(ATTR_STRING); ;} + break; + + case 123: +#line 501 "parser.y" + { (yyval.attr) = make_attrp(ATTR_SWITCHIS, (yyvsp[-1].expr)); ;} + break; + + case 124: +#line 502 "parser.y" + { (yyval.attr) = make_attrp(ATTR_SWITCHTYPE, (yyvsp[-1].type)); ;} + break; + + case 125: +#line 503 "parser.y" + { (yyval.attr) = make_attrp(ATTR_TRANSMITAS, (yyvsp[-1].type)); ;} + break; + + case 126: +#line 504 "parser.y" + { (yyval.attr) = make_attrp(ATTR_UUID, (yyvsp[-1].uuid)); ;} + break; + + case 127: +#line 505 "parser.y" + { (yyval.attr) = make_attr(ATTR_V1ENUM); ;} + break; + + case 128: +#line 506 "parser.y" + { (yyval.attr) = make_attr(ATTR_VARARG); ;} + break; + + case 129: +#line 507 "parser.y" + { (yyval.attr) = make_attrv(ATTR_VERSION, (yyvsp[-1].num)); ;} + break; + + case 130: +#line 508 "parser.y" + { (yyval.attr) = make_attrp(ATTR_WIREMARSHAL, (yyvsp[-1].type)); ;} + break; + + case 131: +#line 509 "parser.y" + { (yyval.attr) = make_attrv(ATTR_POINTERTYPE, (yyvsp[0].num)); ;} + break; + + case 133: +#line 514 "parser.y" + { if (!is_valid_uuid((yyvsp[0].str))) + error_loc("invalid UUID: %s\n", (yyvsp[0].str)); + (yyval.uuid) = parse_uuid((yyvsp[0].str)); ;} + break; + + case 136: +#line 523 "parser.y" + { (yyval.var_list) = NULL; ;} + break; + + case 137: +#line 524 "parser.y" + { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); ;} + break; + + case 138: +#line 527 "parser.y" + { attr_t *a = make_attrp(ATTR_CASE, append_expr( NULL, (yyvsp[-2].expr) )); + (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var(NULL); + (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a ); + ;} + break; + + case 139: +#line 531 "parser.y" + { attr_t *a = make_attr(ATTR_DEFAULT); + (yyval.var) = (yyvsp[0].var); if (!(yyval.var)) (yyval.var) = make_var(NULL); + (yyval.var)->attrs = append_attr( (yyval.var)->attrs, a ); + ;} + break; + + case 140: +#line 537 "parser.y" + { (yyval.var) = reg_const((yyvsp[-2].var)); + set_type((yyval.var), (yyvsp[-3].type), 0, NULL, FALSE); + (yyval.var)->eval = (yyvsp[0].expr); + ;} + break; + + case 141: +#line 543 "parser.y" + { (yyval.var_list) = NULL; ;} + break; + + case 142: +#line 544 "parser.y" + { (yyval.var_list) = (yyvsp[-1].var_list); ;} + break; + + case 144: +#line 548 "parser.y" + { if (!(yyvsp[0].var)->eval) + (yyvsp[0].var)->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */); + (yyval.var_list) = append_var( NULL, (yyvsp[0].var) ); + ;} + break; + + case 145: +#line 552 "parser.y" + { if (!(yyvsp[0].var)->eval) + { + var_t *last = LIST_ENTRY( list_tail((yyval.var_list)), var_t, entry ); + (yyvsp[0].var)->eval = make_exprl(EXPR_NUM, last->eval->cval + 1); + } + (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[0].var) ); + ;} + break; + + case 146: +#line 561 "parser.y" + { (yyval.var) = reg_const((yyvsp[-2].var)); + (yyval.var)->eval = (yyvsp[0].expr); + (yyval.var)->type = make_int(0); + ;} + break; + + case 147: +#line 565 "parser.y" + { (yyval.var) = reg_const((yyvsp[0].var)); + (yyval.var)->type = make_int(0); + ;} + break; + + case 148: +#line 570 "parser.y" + { (yyval.type) = get_typev(RPC_FC_ENUM16, (yyvsp[-3].var), tsENUM); + (yyval.type)->kind = TKIND_ENUM; + (yyval.type)->fields = (yyvsp[-1].var_list); + (yyval.type)->defined = TRUE; + if(in_typelib) + add_typelib_entry((yyval.type)); + ;} + break; + + case 149: +#line 579 "parser.y" + { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); ;} + break; + + case 150: +#line 580 "parser.y" + { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); ;} + break; + + case 151: +#line 593 "parser.y" + { (yyval.expr) = make_expr(EXPR_VOID); ;} + break; + + case 153: +#line 597 "parser.y" + { (yyval.expr) = make_exprl(EXPR_NUM, (yyvsp[0].num)); ;} + break; + + case 154: +#line 598 "parser.y" + { (yyval.expr) = make_exprl(EXPR_HEXNUM, (yyvsp[0].num)); ;} + break; + + case 155: +#line 599 "parser.y" + { (yyval.expr) = make_exprd(EXPR_DOUBLE, (yyvsp[0].dbl)); ;} + break; + + case 156: +#line 600 "parser.y" + { (yyval.expr) = make_exprl(EXPR_TRUEFALSE, 0); ;} + break; + + case 157: +#line 601 "parser.y" + { (yyval.expr) = make_exprl(EXPR_TRUEFALSE, 1); ;} + break; + + case 158: +#line 602 "parser.y" + { (yyval.expr) = make_exprs(EXPR_IDENTIFIER, (yyvsp[0].str)); ;} + break; + + case 159: +#line 603 "parser.y" + { (yyval.expr) = make_expr3(EXPR_COND, (yyvsp[-4].expr), (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 160: +#line 604 "parser.y" + { (yyval.expr) = make_expr2(EXPR_OR , (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 161: +#line 605 "parser.y" + { (yyval.expr) = make_expr2(EXPR_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 162: +#line 606 "parser.y" + { (yyval.expr) = make_expr2(EXPR_ADD, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 163: +#line 607 "parser.y" + { (yyval.expr) = make_expr2(EXPR_SUB, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 164: +#line 608 "parser.y" + { (yyval.expr) = make_expr2(EXPR_MUL, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 165: +#line 609 "parser.y" + { (yyval.expr) = make_expr2(EXPR_DIV, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 166: +#line 610 "parser.y" + { (yyval.expr) = make_expr2(EXPR_SHL, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 167: +#line 611 "parser.y" + { (yyval.expr) = make_expr2(EXPR_SHR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} + break; + + case 168: +#line 612 "parser.y" + { (yyval.expr) = make_expr1(EXPR_NOT, (yyvsp[0].expr)); ;} + break; + + case 169: +#line 613 "parser.y" + { (yyval.expr) = make_expr1(EXPR_NEG, (yyvsp[0].expr)); ;} + break; + + case 170: +#line 614 "parser.y" + { (yyval.expr) = make_expr1(EXPR_ADDRESSOF, (yyvsp[0].expr)); ;} + break; + + case 171: +#line 615 "parser.y" + { (yyval.expr) = make_expr1(EXPR_PPTR, (yyvsp[0].expr)); ;} + break; + + case 172: +#line 616 "parser.y" + { (yyval.expr) = make_exprt(EXPR_CAST, (yyvsp[-2].type), (yyvsp[0].expr)); ;} + break; + + case 173: +#line 617 "parser.y" + { (yyval.expr) = make_exprt(EXPR_SIZEOF, (yyvsp[-1].type), NULL); ;} + break; + + case 174: +#line 618 "parser.y" + { (yyval.expr) = (yyvsp[-1].expr); ;} + break; + + case 175: +#line 621 "parser.y" + { (yyval.expr_list) = append_expr( NULL, (yyvsp[0].expr) ); ;} + break; + + case 176: +#line 622 "parser.y" + { (yyval.expr_list) = append_expr( (yyvsp[-2].expr_list), (yyvsp[0].expr) ); ;} + break; + + case 177: +#line 625 "parser.y" + { (yyval.expr) = (yyvsp[0].expr); + if (!(yyval.expr)->is_const) + error_loc("expression is not constant\n"); + ;} + break; + + case 178: +#line 631 "parser.y" + { (yyval.var) = (yyvsp[0].var); + set_type((yyval.var), (yyvsp[-1].type), 0, NULL, FALSE); + ;} + break; + + case 179: +#line 636 "parser.y" + { (yyval.var_list) = NULL; ;} + break; + + case 180: +#line 637 "parser.y" + { (yyval.var_list) = append_var( (yyvsp[-1].var_list), (yyvsp[0].var) ); ;} + break; + + case 181: +#line 640 "parser.y" + { (yyval.var) = (yyvsp[-1].var); ;} + break; + + case 182: +#line 641 "parser.y" + { (yyval.var) = make_var(NULL); (yyval.var)->type = (yyvsp[-1].type); (yyval.var)->attrs = (yyvsp[-2].attr_list); ;} + break; + + case 183: +#line 642 "parser.y" + { (yyval.var) = make_var(NULL); (yyval.var)->attrs = (yyvsp[-1].attr_list); ;} + break; + + case 184: +#line 643 "parser.y" + { (yyval.var) = NULL; ;} + break; + + case 185: +#line 646 "parser.y" + { (yyval.var) = (yyvsp[-1].pident)->var; + (yyval.var)->attrs = (yyvsp[-3].attr_list); + set_type((yyval.var), (yyvsp[-2].type), (yyvsp[-1].pident)->ptr_level, (yyvsp[0].array_dims), FALSE); + free((yyvsp[-1].pident)); + ;} + break; + + case 186: +#line 655 "parser.y" + { var_t *v = (yyvsp[-3].pident)->var; + v->attrs = (yyvsp[-6].attr_list); + set_type(v, (yyvsp[-5].type), (yyvsp[-3].pident)->ptr_level, NULL, FALSE); + free((yyvsp[-3].pident)); + (yyval.func) = make_func(v, (yyvsp[-1].var_list)); + if (is_attr(v->attrs, ATTR_IN)) { + error_loc("inapplicable attribute [in] for function '%s'\n",(yyval.func)->def->name); + } + ;} + break; + + case 187: +#line 666 "parser.y" + { (yyval.var) = NULL; ;} + break; + + case 189: +#line 670 "parser.y" + { (yyval.var) = NULL; ;} + break; + + case 190: +#line 671 "parser.y" + { (yyval.var) = make_var((yyvsp[0].str)); ;} + break; + + case 191: +#line 672 "parser.y" + { (yyval.var) = make_var((yyvsp[0].str)); ;} + break; + + case 192: +#line 675 "parser.y" + { (yyval.var) = make_var((yyvsp[0].str)); ;} + break; + + case 193: +#line 677 "parser.y" + { (yyval.var) = make_var((yyvsp[0].str)); ;} + break; + + case 194: +#line 680 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 195: +#line 681 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 197: +#line 683 "parser.y" + { (yyval.type) = (yyvsp[0].type); (yyval.type)->sign = 1; ;} + break; + + case 198: +#line 684 "parser.y" + { (yyval.type) = (yyvsp[0].type); (yyval.type)->sign = -1; + switch ((yyval.type)->type) { + case RPC_FC_CHAR: break; + case RPC_FC_SMALL: (yyval.type)->type = RPC_FC_USMALL; break; + case RPC_FC_SHORT: (yyval.type)->type = RPC_FC_USHORT; break; + case RPC_FC_LONG: (yyval.type)->type = RPC_FC_ULONG; break; + case RPC_FC_HYPER: + if ((yyval.type)->name[0] == 'h') /* hyper, as opposed to __int64 */ + { + (yyval.type) = alias((yyval.type), "MIDL_uhyper"); + (yyval.type)->sign = 0; + } + break; + default: break; + } + ;} + break; + + case 199: +#line 700 "parser.y" + { (yyval.type) = make_int(-1); ;} + break; + + case 200: +#line 701 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 201: +#line 702 "parser.y" + { (yyval.type) = duptype(find_type("float", 0), 1); ;} + break; + + case 202: +#line 703 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 203: +#line 704 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 204: +#line 705 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 205: +#line 706 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 208: +#line 713 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 209: +#line 714 "parser.y" + { (yyval.type) = make_builtin((yyvsp[-1].str)); ;} + break; + + case 210: +#line 715 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 211: +#line 716 "parser.y" + { (yyval.type) = make_builtin((yyvsp[-1].str)); ;} + break; + + case 212: +#line 717 "parser.y" + { (yyval.type) = make_builtin((yyvsp[-1].str)); ;} + break; + + case 213: +#line 718 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 214: +#line 719 "parser.y" + { (yyval.type) = make_builtin((yyvsp[0].str)); ;} + break; + + case 215: +#line 722 "parser.y" + { (yyval.type) = make_class((yyvsp[0].str)); ;} + break; + + case 216: +#line 723 "parser.y" + { (yyval.type) = find_type((yyvsp[0].str), 0); + if ((yyval.type)->defined) error_loc("multiple definition error\n"); + if ((yyval.type)->kind != TKIND_COCLASS) error_loc("%s was not declared a coclass\n", (yyvsp[0].str)); + ;} + break; + + case 217: +#line 729 "parser.y" + { (yyval.type) = (yyvsp[0].type); + (yyval.type)->attrs = (yyvsp[-1].attr_list); + if (!parse_only && do_header) + write_coclass((yyval.type)); + if (!parse_only && do_idfile) + write_clsid((yyval.type)); + ;} + break; + + case 218: +#line 738 "parser.y" + { (yyval.type) = (yyvsp[-3].type); + (yyval.type)->ifaces = (yyvsp[-1].ifref_list); + (yyval.type)->defined = TRUE; + ;} + break; + + case 219: +#line 744 "parser.y" + { (yyval.ifref_list) = NULL; ;} + break; + + case 220: +#line 745 "parser.y" + { (yyval.ifref_list) = append_ifref( (yyvsp[-1].ifref_list), (yyvsp[0].ifref) ); ;} + break; + + case 221: +#line 749 "parser.y" + { (yyval.ifref) = make_ifref((yyvsp[0].type)); (yyval.ifref)->attrs = (yyvsp[-1].attr_list); ;} + break; + + case 222: +#line 752 "parser.y" + { (yyval.type) = get_type(0, (yyvsp[0].str), 0); (yyval.type)->kind = TKIND_DISPATCH; ;} + break; + + case 223: +#line 753 "parser.y" + { (yyval.type) = get_type(0, (yyvsp[0].str), 0); (yyval.type)->kind = TKIND_DISPATCH; ;} + break; + + case 224: +#line 756 "parser.y" + { attr_t *attrs; + (yyval.type) = (yyvsp[0].type); + if ((yyval.type)->defined) error_loc("multiple definition error\n"); + attrs = make_attr(ATTR_DISPINTERFACE); + (yyval.type)->attrs = append_attr( (yyvsp[-1].attr_list), attrs ); + (yyval.type)->ref = find_type("IDispatch", 0); + if (!(yyval.type)->ref) error_loc("IDispatch is undefined\n"); + (yyval.type)->defined = TRUE; + if (!parse_only && do_header) write_forward((yyval.type)); + ;} + break; + + case 225: +#line 768 "parser.y" + { (yyval.var_list) = NULL; ;} + break; + + case 226: +#line 769 "parser.y" + { (yyval.var_list) = append_var( (yyvsp[-2].var_list), (yyvsp[-1].var) ); ;} + break; + + case 227: +#line 772 "parser.y" + { (yyval.func_list) = NULL; ;} + break; + + case 228: +#line 773 "parser.y" + { (yyval.func_list) = append_func( (yyvsp[-2].func_list), (yyvsp[-1].func) ); ;} + break; + + case 229: +#line 779 "parser.y" + { (yyval.type) = (yyvsp[-4].type); + (yyval.type)->fields = (yyvsp[-2].var_list); + (yyval.type)->funcs = (yyvsp[-1].func_list); + if (!parse_only && do_header) write_dispinterface((yyval.type)); + if (!parse_only && do_idfile) write_diid((yyval.type)); + ;} + break; + + case 230: +#line 786 "parser.y" + { (yyval.type) = (yyvsp[-4].type); + (yyval.type)->fields = (yyvsp[-2].type)->fields; + (yyval.type)->funcs = (yyvsp[-2].type)->funcs; + if (!parse_only && do_header) write_dispinterface((yyval.type)); + if (!parse_only && do_idfile) write_diid((yyval.type)); + ;} + break; + + case 231: +#line 794 "parser.y" + { (yyval.type) = NULL; ;} + break; + + case 232: +#line 795 "parser.y" + { (yyval.type) = find_type2((yyvsp[0].str), 0); ;} + break; + + case 233: +#line 798 "parser.y" + { (yyval.type) = get_type(RPC_FC_IP, (yyvsp[0].str), 0); (yyval.type)->kind = TKIND_INTERFACE; ;} + break; + + case 234: +#line 799 "parser.y" + { (yyval.type) = get_type(RPC_FC_IP, (yyvsp[0].str), 0); (yyval.type)->kind = TKIND_INTERFACE; ;} + break; + + case 235: +#line 802 "parser.y" + { (yyval.ifinfo).interface = (yyvsp[0].type); + (yyval.ifinfo).old_pointer_default = pointer_default; + if (is_attr((yyvsp[-1].attr_list), ATTR_POINTERDEFAULT)) + pointer_default = get_attrv((yyvsp[-1].attr_list), ATTR_POINTERDEFAULT); + if ((yyvsp[0].type)->defined) error_loc("multiple definition error\n"); + (yyvsp[0].type)->attrs = (yyvsp[-1].attr_list); + (yyvsp[0].type)->defined = TRUE; + if (!parse_only && do_header) write_forward((yyvsp[0].type)); + ;} + break; + + case 236: +#line 814 "parser.y" + { (yyval.type) = (yyvsp[-4].ifinfo).interface; + (yyval.type)->ref = (yyvsp[-3].type); + (yyval.type)->funcs = (yyvsp[-1].func_list); + compute_method_indexes((yyval.type)); + if (!parse_only && do_header) write_interface((yyval.type)); + if (!parse_only && local_stubs) write_locals(local_stubs, (yyval.type), TRUE); + if (!parse_only && do_idfile) write_iid((yyval.type)); + pointer_default = (yyvsp[-4].ifinfo).old_pointer_default; + ;} + break; + + case 237: +#line 826 "parser.y" + { (yyval.type) = (yyvsp[-6].ifinfo).interface; + (yyval.type)->ref = find_type2((yyvsp[-4].str), 0); + if (!(yyval.type)->ref) error_loc("base class '%s' not found in import\n", (yyvsp[-4].str)); + (yyval.type)->funcs = (yyvsp[-1].func_list); + compute_method_indexes((yyval.type)); + if (!parse_only && do_header) write_interface((yyval.type)); + if (!parse_only && local_stubs) write_locals(local_stubs, (yyval.type), TRUE); + if (!parse_only && do_idfile) write_iid((yyval.type)); + pointer_default = (yyvsp[-6].ifinfo).old_pointer_default; + ;} + break; + + case 238: +#line 836 "parser.y" + { (yyval.type) = (yyvsp[0].type); ;} + break; + + case 239: +#line 840 "parser.y" + { (yyval.type) = (yyvsp[-1].type); if (!parse_only && do_header) write_forward((yyval.type)); ;} + break; + + case 240: +#line 841 "parser.y" + { (yyval.type) = (yyvsp[-1].type); if (!parse_only && do_header) write_forward((yyval.type)); ;} + break; + + case 241: +#line 844 "parser.y" + { (yyval.type) = make_type(0, NULL); (yyval.type)->name = (yyvsp[0].str); (yyval.type)->kind = TKIND_MODULE; ;} + break; + + case 242: +#line 845 "parser.y" + { (yyval.type) = make_type(0, NULL); (yyval.type)->name = (yyvsp[0].str); (yyval.type)->kind = TKIND_MODULE; ;} + break; + + case 243: +#line 848 "parser.y" + { (yyval.type) = (yyvsp[0].type); + (yyval.type)->attrs = (yyvsp[-1].attr_list); + ;} + break; + + case 244: +#line 853 "parser.y" + { (yyval.type) = (yyvsp[-3].type); + (yyval.type)->funcs = (yyvsp[-1].func_list); + /* FIXME: if (!parse_only && do_header) write_module($$); */ + ;} + break; + + case 245: +#line 859 "parser.y" + { (yyval.pident) = (yyvsp[0].pident); (yyval.pident)->ptr_level++; ;} + break; + + case 246: +#line 860 "parser.y" + { (yyval.pident) = (yyvsp[0].pident); /* FIXME */ ;} + break; + + case 247: +#line 863 "parser.y" + { (yyval.pident) = make_pident((yyvsp[0].var)); ;} + break; + + case 249: +#line 865 "parser.y" + { (yyval.pident) = (yyvsp[-1].pident); ;} + break; + + case 250: +#line 869 "parser.y" + { (yyval.pident_list) = append_pident( NULL, (yyvsp[0].pident) ); ;} + break; + + case 251: +#line 870 "parser.y" + { (yyval.pident_list) = append_pident( (yyvsp[-2].pident_list), (yyvsp[0].pident) ); ;} + break; + + case 252: +#line 874 "parser.y" + { (yyval.num) = RPC_FC_RP; ;} + break; + + case 253: +#line 875 "parser.y" + { (yyval.num) = RPC_FC_UP; ;} + break; + + case 254: +#line 876 "parser.y" + { (yyval.num) = RPC_FC_FP; ;} + break; + + case 255: +#line 879 "parser.y" + { (yyval.type) = get_typev(RPC_FC_STRUCT, (yyvsp[-3].var), tsSTRUCT); + /* overwrite RPC_FC_STRUCT with a more exact type */ + (yyval.type)->type = get_struct_type( (yyvsp[-1].var_list) ); + (yyval.type)->kind = TKIND_RECORD; + (yyval.type)->fields = (yyvsp[-1].var_list); + (yyval.type)->defined = TRUE; + if(in_typelib) + add_typelib_entry((yyval.type)); + ;} + break; + + case 256: +#line 890 "parser.y" + { (yyval.type) = duptype(find_type("void", 0), 1); ;} + break; + + case 257: +#line 891 "parser.y" + { (yyval.type) = find_type((yyvsp[0].str), 0); ;} + break; + + case 258: +#line 892 "parser.y" + { (yyval.type) = (yyvsp[0].type); ;} + break; + + case 259: +#line 893 "parser.y" + { (yyval.type) = duptype((yyvsp[0].type), 1); (yyval.type)->is_const = TRUE; ;} + break; + + case 260: +#line 894 "parser.y" + { (yyval.type) = (yyvsp[0].type); ;} + break; + + case 261: +#line 895 "parser.y" + { (yyval.type) = find_type2((yyvsp[0].str), tsENUM); ;} + break; + + case 262: +#line 896 "parser.y" + { (yyval.type) = (yyvsp[0].type); ;} + break; + + case 263: +#line 897 "parser.y" + { (yyval.type) = get_type(RPC_FC_STRUCT, (yyvsp[0].str), tsSTRUCT); ;} + break; + + case 264: +#line 898 "parser.y" + { (yyval.type) = (yyvsp[0].type); ;} + break; + + case 265: +#line 899 "parser.y" + { (yyval.type) = find_type2((yyvsp[0].str), tsUNION); ;} + break; + + case 266: +#line 900 "parser.y" + { (yyval.type) = make_safearray((yyvsp[-1].type)); ;} + break; + + case 267: +#line 903 "parser.y" + { reg_typedefs((yyvsp[-1].type), (yyvsp[0].pident_list), (yyvsp[-2].attr_list)); + process_typedefs((yyvsp[0].pident_list)); + ;} + break; + + case 268: +#line 908 "parser.y" + { (yyval.type) = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, (yyvsp[-3].var), tsUNION); + (yyval.type)->kind = TKIND_UNION; + (yyval.type)->fields = (yyvsp[-1].var_list); + (yyval.type)->defined = TRUE; + ;} + break; + + case 269: +#line 915 "parser.y" + { var_t *u = (yyvsp[-3].var); + (yyval.type) = get_typev(RPC_FC_ENCAPSULATED_UNION, (yyvsp[-8].var), tsUNION); + (yyval.type)->kind = TKIND_UNION; + if (!u) u = make_var( xstrdup("tagged_union") ); + u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL); + u->type->kind = TKIND_UNION; + u->type->fields = (yyvsp[-1].var_list); + u->type->defined = TRUE; + (yyval.type)->fields = append_var( (yyval.type)->fields, (yyvsp[-5].var) ); + (yyval.type)->fields = append_var( (yyval.type)->fields, u ); + (yyval.type)->defined = TRUE; + ;} + break; + + case 270: +#line 930 "parser.y" + { (yyval.num) = MAKEVERSION((yyvsp[0].num), 0); ;} + break; + + case 271: +#line 931 "parser.y" + { (yyval.num) = MAKEVERSION((yyvsp[-2].num), (yyvsp[0].num)); ;} + break; + + + default: break; + } + +/* Line 1126 of yacc.c. */ +#line 3627 "parser.tab.c" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + char *yymsg = 0; +# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +#if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +#endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + + if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yymsg; + int yyi = 0; + while ((*yyp = *yyf)) + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + { + yyerror (YY_("syntax error")); + goto yyexhaustedlab; + } + } + else +#endif /* YYERROR_VERBOSE */ + yyerror (YY_("syntax error")); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (0) + goto yyerrorlab; + +yyvsp -= yylen; + yyssp -= yylen; + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", yystos[yystate], yyvsp); + YYPOPSTACK; + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK; + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 934 "parser.y" + + +static void decl_builtin(const char *name, unsigned char type) +{ + type_t *t = make_type(type, NULL); + t->name = xstrdup(name); + reg_type(t, name, 0); +} + +static type_t *make_builtin(char *name) +{ + /* NAME is strdup'd in the lexer */ + type_t *t = duptype(find_type(name, 0), 0); + t->name = name; + return t; +} + +static type_t *make_int(int sign) +{ + type_t *t = duptype(find_type("int", 0), 1); + + t->sign = sign; + if (sign < 0) + t->type = t->type == RPC_FC_LONG ? RPC_FC_ULONG : RPC_FC_USHORT; + + return t; +} + +void init_types(void) +{ + decl_builtin("void", 0); + decl_builtin("byte", RPC_FC_BYTE); + decl_builtin("wchar_t", RPC_FC_WCHAR); + decl_builtin("int", RPC_FC_LONG); /* win32 */ + decl_builtin("short", RPC_FC_SHORT); + decl_builtin("small", RPC_FC_SMALL); + decl_builtin("long", RPC_FC_LONG); + decl_builtin("hyper", RPC_FC_HYPER); + decl_builtin("__int64", RPC_FC_HYPER); + decl_builtin("char", RPC_FC_CHAR); + decl_builtin("float", RPC_FC_FLOAT); + decl_builtin("double", RPC_FC_DOUBLE); + decl_builtin("boolean", RPC_FC_BYTE); + decl_builtin("error_status_t", RPC_FC_ERROR_STATUS_T); + decl_builtin("handle_t", RPC_FC_BIND_PRIMITIVE); +} + +static str_list_t *append_str(str_list_t *list, char *str) +{ + struct str_list_entry_t *entry; + + if (!str) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + entry = xmalloc( sizeof(*entry) ); + entry->str = str; + list_add_tail( list, &entry->entry ); + return list; +} + +static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) +{ + if (!attr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &attr->entry ); + return list; +} + +static attr_t *make_attr(enum attr_type type) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.ival = 0; + return a; +} + +static attr_t *make_attrv(enum attr_type type, unsigned long val) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.ival = val; + return a; +} + +static attr_t *make_attrp(enum attr_type type, void *val) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.pval = val; + return a; +} + +static expr_t *make_expr(enum expr_type type) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.lval = 0; + e->is_const = FALSE; + e->cval = 0; + return e; +} + +static expr_t *make_exprl(enum expr_type type, long val) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.lval = val; + e->is_const = FALSE; + /* check for numeric constant */ + if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) { + /* make sure true/false value is valid */ + assert(type != EXPR_TRUEFALSE || val == 0 || val == 1); + e->is_const = TRUE; + e->cval = val; + } + return e; +} + +static expr_t *make_exprd(enum expr_type type, double val) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.dval = val; + e->is_const = TRUE; + e->cval = val; + return e; +} + +static expr_t *make_exprs(enum expr_type type, char *val) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.sval = val; + e->is_const = FALSE; + /* check for predefined constants */ + if (type == EXPR_IDENTIFIER) { + var_t *c = find_const(val, 0); + if (c) { + e->u.sval = c->name; + free(val); + e->is_const = TRUE; + e->cval = c->eval->cval; + } + } + return e; +} + +static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr; + e->u.tref = tref; + e->is_const = FALSE; + /* check for cast of constant expression */ + if (type == EXPR_SIZEOF) { + switch (tref->type) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + e->is_const = TRUE; + e->cval = 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + e->is_const = TRUE; + e->cval = 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_FLOAT: + case RPC_FC_ERROR_STATUS_T: + e->is_const = TRUE; + e->cval = 4; + break; + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + e->is_const = TRUE; + e->cval = 8; + break; + } + } + if (type == EXPR_CAST && expr->is_const) { + e->is_const = TRUE; + e->cval = expr->cval; + } + return e; +} + +static expr_t *make_expr1(enum expr_type type, expr_t *expr) +{ + expr_t *e; + if (type == EXPR_ADDRESSOF && expr->type != EXPR_IDENTIFIER) + error("address-of operator applied to invalid expression\n"); + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr; + e->u.lval = 0; + e->is_const = FALSE; + /* check for compile-time optimization */ + if (expr->is_const) { + e->is_const = TRUE; + switch (type) { + case EXPR_NEG: + e->cval = -expr->cval; + break; + case EXPR_NOT: + e->cval = ~expr->cval; + break; + default: + e->is_const = FALSE; + break; + } + } + return e; +} + +static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr1; + e->u.ext = expr2; + e->is_const = FALSE; + /* check for compile-time optimization */ + if (expr1->is_const && expr2->is_const) { + e->is_const = TRUE; + switch (type) { + case EXPR_ADD: + e->cval = expr1->cval + expr2->cval; + break; + case EXPR_SUB: + e->cval = expr1->cval - expr2->cval; + break; + case EXPR_MUL: + e->cval = expr1->cval * expr2->cval; + break; + case EXPR_DIV: + e->cval = expr1->cval / expr2->cval; + break; + case EXPR_OR: + e->cval = expr1->cval | expr2->cval; + break; + case EXPR_AND: + e->cval = expr1->cval & expr2->cval; + break; + case EXPR_SHL: + e->cval = expr1->cval << expr2->cval; + break; + case EXPR_SHR: + e->cval = expr1->cval >> expr2->cval; + break; + default: + e->is_const = FALSE; + break; + } + } + return e; +} + +static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr1; + e->u.ext = expr2; + e->ext2 = expr3; + e->is_const = FALSE; + /* check for compile-time optimization */ + if (expr1->is_const && expr2->is_const && expr3->is_const) { + e->is_const = TRUE; + switch (type) { + case EXPR_COND: + e->cval = expr1->cval ? expr2->cval : expr3->cval; + break; + default: + e->is_const = FALSE; + break; + } + } + return e; +} + +static expr_list_t *append_expr(expr_list_t *list, expr_t *expr) +{ + if (!expr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &expr->entry ); + return list; +} + +static array_dims_t *append_array(array_dims_t *list, expr_t *expr) +{ + if (!expr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &expr->entry ); + return list; +} + +static struct list type_pool = LIST_INIT(type_pool); +typedef struct +{ + type_t data; + struct list link; +} type_pool_node_t; + +type_t *alloc_type(void) +{ + type_pool_node_t *node = xmalloc(sizeof *node); + list_add_tail(&type_pool, &node->link); + return &node->data; +} + +void set_all_tfswrite(int val) +{ + type_pool_node_t *node; + LIST_FOR_EACH_ENTRY(node, &type_pool, type_pool_node_t, link) + node->data.tfswrite = val; +} + +static type_t *make_type(unsigned char type, type_t *ref) +{ + type_t *t = alloc_type(); + t->name = NULL; + t->kind = TKIND_PRIMITIVE; + t->type = type; + t->ref = ref; + t->attrs = NULL; + t->orig = NULL; + t->funcs = NULL; + t->fields = NULL; + t->ifaces = NULL; + t->dim = 0; + t->size_is = NULL; + t->length_is = NULL; + t->typestring_offset = 0; + t->ptrdesc = 0; + t->declarray = FALSE; + t->ignore = (parse_only != 0); + t->is_const = FALSE; + t->sign = 0; + t->defined = FALSE; + t->written = FALSE; + t->user_types_registered = FALSE; + t->tfswrite = FALSE; + t->typelib_idx = -1; + return t; +} + +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, + int top) +{ + expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS); + expr_list_t *lengs = get_attrp(v->attrs, ATTR_LENGTHIS); + int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); + int ptr_type = ptr_attr; + int sizeless, has_varconf; + expr_t *dim; + type_t *atype, **ptype; + + v->type = type; + + if (!ptr_type && top) + ptr_type = RPC_FC_RP; + + for ( ; 0 < ptr_level; --ptr_level) + { + v->type = make_type(pointer_default, v->type); + if (ptr_level == 1 && ptr_type && !arr) + { + v->type->type = ptr_type; + ptr_type = 0; + } + } + + if (ptr_type && !arr) + { + if (is_ptr(v->type)) + { + if (v->type->type != ptr_type) + { + v->type = duptype(v->type, 1); + v->type->type = ptr_type; + } + } + else if (!arr && ptr_attr) + error("%s: pointer attribute applied to non-pointer type\n", v->name); + } + + sizeless = FALSE; + if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry) + { + if (sizeless) + error("%s: only the first array dimension can be unspecified\n", v->name); + + if (dim->is_const) + { + unsigned int align = 0; + size_t size = type_memsize(v->type, &align); + + if (dim->cval <= 0) + error("%s: array dimension must be positive\n", v->name); + + if (0xffffffffuL / size < (unsigned long) dim->cval) + error("%s: total array size is too large\n", v->name); + else if (0xffffuL < size * dim->cval) + v->type = make_type(RPC_FC_LGFARRAY, v->type); + else + v->type = make_type(RPC_FC_SMFARRAY, v->type); + } + else + { + sizeless = TRUE; + v->type = make_type(RPC_FC_CARRAY, v->type); + } + + v->type->declarray = TRUE; + v->type->dim = dim->cval; + } + + ptype = &v->type; + has_varconf = FALSE; + if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry) + { + if (dim->type != EXPR_VOID) + { + has_varconf = TRUE; + atype = *ptype = duptype(*ptype, 0); + + if (atype->type == RPC_FC_SMFARRAY || atype->type == RPC_FC_LGFARRAY) + error("%s: cannot specify size_is for a fixed sized array\n", v->name); + + if (atype->type != RPC_FC_CARRAY && !is_ptr(atype)) + error("%s: size_is attribute applied to illegal type\n", v->name); + + atype->type = RPC_FC_CARRAY; + atype->size_is = dim; + } + + ptype = &(*ptype)->ref; + if (*ptype == NULL) + error("%s: too many expressions in size_is attribute\n", v->name); + } + + ptype = &v->type; + if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry) + { + if (dim->type != EXPR_VOID) + { + has_varconf = TRUE; + atype = *ptype = duptype(*ptype, 0); + + if (atype->type == RPC_FC_SMFARRAY) + atype->type = RPC_FC_SMVARRAY; + else if (atype->type == RPC_FC_LGFARRAY) + atype->type = RPC_FC_LGVARRAY; + else if (atype->type == RPC_FC_CARRAY) + atype->type = RPC_FC_CVARRAY; + else + error("%s: length_is attribute applied to illegal type\n", v->name); + + atype->length_is = dim; + } + + ptype = &(*ptype)->ref; + if (*ptype == NULL) + error("%s: too many expressions in length_is attribute\n", v->name); + } + + if (has_varconf && !last_array(v->type)) + { + ptype = &v->type; + for (ptype = &v->type; is_array(*ptype); ptype = &(*ptype)->ref) + { + *ptype = duptype(*ptype, 0); + (*ptype)->type = RPC_FC_BOGUS_ARRAY; + } + } + + if (is_array(v->type)) + { + const type_t *rt = v->type->ref; + if (is_user_type(rt)) + v->type->type = RPC_FC_BOGUS_ARRAY; + else + switch (rt->type) + { + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_ENUM16: + v->type->type = RPC_FC_BOGUS_ARRAY; + break; + /* FC_RP should be above, but widl overuses these, and will break things. */ + case RPC_FC_UP: + case RPC_FC_RP: + if (rt->ref->type == RPC_FC_IP) + v->type->type = RPC_FC_BOGUS_ARRAY; + break; + } + } +} + +static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) +{ + if (!iface) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &iface->entry ); + return list; +} + +static ifref_t *make_ifref(type_t *iface) +{ + ifref_t *l = xmalloc(sizeof(ifref_t)); + l->iface = iface; + l->attrs = NULL; + return l; +} + +static var_list_t *append_var(var_list_t *list, var_t *var) +{ + if (!var) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &var->entry ); + return list; +} + +static var_t *make_var(char *name) +{ + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; + v->type = NULL; + v->args = NULL; + v->attrs = NULL; + v->eval = NULL; + return v; +} + +static pident_list_t *append_pident(pident_list_t *list, pident_t *p) +{ + if (!p) return list; + if (!list) { + list = xmalloc(sizeof(*list)); + list_init(list); + } + list_add_tail(list, &p->entry); + return list; +} + +static pident_t *make_pident(var_t *var) +{ + pident_t *p = xmalloc(sizeof(*p)); + p->var = var; + p->ptr_level = 0; + return p; +} + +static func_list_t *append_func(func_list_t *list, func_t *func) +{ + if (!func) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &func->entry ); + return list; +} + +static func_t *make_func(var_t *def, var_list_t *args) +{ + func_t *f = xmalloc(sizeof(func_t)); + f->def = def; + f->args = args; + f->ignore = parse_only; + f->idx = -1; + return f; +} + +static type_t *make_class(char *name) +{ + type_t *c = make_type(0, NULL); + c->name = name; + c->kind = TKIND_COCLASS; + return c; +} + +static type_t *make_safearray(type_t *type) +{ + type_t *sa = duptype(find_type("SAFEARRAY", 0), 1); + sa->ref = type; + return make_type(pointer_default, sa); +} + +#define HASHMAX 64 + +static int hash_ident(const char *name) +{ + const char *p = name; + int sum = 0; + /* a simple sum hash is probably good enough */ + while (*p) { + sum += *p; + p++; + } + return sum & (HASHMAX-1); +} + +/***** type repository *****/ + +struct rtype { + const char *name; + type_t *type; + int t; + struct rtype *next; +}; + +struct rtype *type_hash[HASHMAX]; + +static type_t *reg_type(type_t *type, const char *name, int t) +{ + struct rtype *nt; + int hash; + if (!name) { + error_loc("registering named type without name\n"); + return type; + } + hash = hash_ident(name); + nt = xmalloc(sizeof(struct rtype)); + nt->name = name; + nt->type = type; + nt->t = t; + nt->next = type_hash[hash]; + type_hash[hash] = nt; + return type; +} + +static int is_incomplete(const type_t *t) +{ + return !t->defined && (is_struct(t->type) || is_union(t->type)); +} + +static void add_incomplete(type_t *t) +{ + struct typenode *tn = xmalloc(sizeof *tn); + tn->type = t; + list_add_tail(&incomplete_types, &tn->entry); +} + +static void fix_type(type_t *t) +{ + if (t->kind == TKIND_ALIAS && is_incomplete(t)) { + type_t *ot = t->orig; + fix_type(ot); + t->fields = ot->fields; + t->defined = ot->defined; + } +} + +static void fix_incomplete(void) +{ + struct typenode *tn, *next; + + LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) { + fix_type(tn->type); + free(tn); + } +} + +static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *attrs) +{ + type_t *ptr = type; + const pident_t *pident; + int ptrc = 0; + int is_str = is_attr(attrs, ATTR_STRING); + unsigned char ptr_type = get_attrv(attrs, ATTR_POINTERTYPE); + + if (is_str) + { + type_t *t = type; + unsigned char c; + + while (is_ptr(t)) + t = t->ref; + + c = t->type; + if (c != RPC_FC_CHAR && c != RPC_FC_BYTE && c != RPC_FC_WCHAR) + { + pident = LIST_ENTRY( list_head( pidents ), const pident_t, entry ); + error_loc("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays\n", + pident->var->name); + } + } + + /* We must generate names for tagless enum, struct or union. + Typedef-ing a tagless enum, struct or union means we want the typedef + to be included in a library whether it has other attributes or not, + hence the public attribute. */ + if ((type->kind == TKIND_ENUM || type->kind == TKIND_RECORD + || type->kind == TKIND_UNION) && ! type->name && ! parse_only) + { + if (! is_attr(attrs, ATTR_PUBLIC)) + attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) ); + type->name = gen_name(); + } + + LIST_FOR_EACH_ENTRY( pident, pidents, const pident_t, entry ) + { + var_t *name = pident->var; + + if (name->name) { + type_t *cur = ptr; + int cptr = pident->ptr_level; + if (cptr > ptrc) { + while (cptr > ptrc) { + cur = ptr = make_type(pointer_default, cur); + ptrc++; + } + } else { + while (cptr < ptrc) { + cur = cur->ref; + cptr++; + } + } + cur = alias(cur, name->name); + cur->attrs = attrs; + if (ptr_type) + { + if (is_ptr(cur)) + cur->type = ptr_type; + else + error_loc("'%s': pointer attribute applied to non-pointer type\n", + cur->name); + } + else if (is_str && ! is_ptr(cur)) + error_loc("'%s': [string] attribute applied to non-pointer type\n", + cur->name); + + if (is_incomplete(cur)) + add_incomplete(cur); + reg_type(cur, cur->name, 0); + } + } + return type; +} + +static type_t *find_type(const char *name, int t) +{ + struct rtype *cur = type_hash[hash_ident(name)]; + while (cur && (cur->t != t || strcmp(cur->name, name))) + cur = cur->next; + if (!cur) { + error_loc("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 = type_hash[hash_ident(name)]; + while (cur && (cur->t || strcmp(cur->name, name))) + cur = cur->next; + if (cur) return TRUE; + return FALSE; +} + +static type_t *get_type(unsigned char type, char *name, int t) +{ + struct rtype *cur = NULL; + type_t *tp; + if (name) { + cur = type_hash[hash_ident(name)]; + 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(unsigned char type, var_t *name, int t) +{ + char *sname = NULL; + if (name) { + sname = name->name; + free(name); + } + return get_type(type, sname, t); +} + +static int get_struct_type(var_list_t *fields) +{ + int has_pointer = 0; + int has_conformance = 0; + int has_variance = 0; + var_t *field; + + if (get_padding(fields)) + return RPC_FC_BOGUS_STRUCT; + + if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) + { + type_t *t = field->type; + + if (is_user_type(t)) + return RPC_FC_BOGUS_STRUCT; + + if (is_ptr(t)) + { + do + t = t->ref; + while (is_ptr(t)); + + switch (t->type) + { + case RPC_FC_IP: + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_BOGUS_STRUCT: + return RPC_FC_BOGUS_STRUCT; + } + + has_pointer = 1; + continue; + } + + if (field->type->declarray) + { + if (is_string_type(field->attrs, field->type)) + { + if (is_conformant_array(field->type)) + has_conformance = 1; + has_variance = 1; + continue; + } + + if (is_array(field->type->ref)) + return RPC_FC_BOGUS_STRUCT; + + if (is_conformant_array(field->type)) + { + has_conformance = 1; + if (field->type->declarray && list_next(fields, &field->entry)) + error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", + field->name); + } + if (field->type->length_is) + has_variance = 1; + + t = field->type->ref; + } + + switch (t->type) + { + /* + * RPC_FC_BYTE, RPC_FC_STRUCT, etc + * Simple types don't effect the type of struct. + * A struct containing a simple struct is still a simple struct. + * So long as we can block copy the data, we return RPC_FC_STRUCT. + */ + case 0: /* void pointer */ + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + case RPC_FC_HYPER: + case RPC_FC_FLOAT: + case RPC_FC_DOUBLE: + case RPC_FC_STRUCT: + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + break; + + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_FP: + case RPC_FC_OP: + case RPC_FC_CARRAY: + case RPC_FC_CVARRAY: + case RPC_FC_BOGUS_ARRAY: + has_pointer = 1; + break; + + /* + * Propagate member attributes + * a struct should be at least as complex as its member + */ + case RPC_FC_CVSTRUCT: + has_conformance = 1; + has_variance = 1; + has_pointer = 1; + break; + + case RPC_FC_CPSTRUCT: + has_conformance = 1; + if (list_next( fields, &field->entry )) + error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", + field->name); + has_pointer = 1; + break; + + case RPC_FC_CSTRUCT: + has_conformance = 1; + if (list_next( fields, &field->entry )) + error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", + field->name); + break; + + case RPC_FC_PSTRUCT: + has_pointer = 1; + break; + + default: + error_loc("Unknown struct member %s with type (0x%02x)\n", field->name, t->type); + /* fallthru - treat it as complex */ + + /* as soon as we see one of these these members, it's bogus... */ + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_BOGUS_STRUCT: + return RPC_FC_BOGUS_STRUCT; + } + } + + if( has_variance ) + { + if ( has_conformance ) + return RPC_FC_CVSTRUCT; + else + return RPC_FC_BOGUS_STRUCT; + } + if( has_conformance && has_pointer ) + return RPC_FC_CPSTRUCT; + if( has_conformance ) + return RPC_FC_CSTRUCT; + if( has_pointer ) + return RPC_FC_PSTRUCT; + return RPC_FC_STRUCT; +} + +/***** constant repository *****/ + +struct rconst { + char *name; + var_t *var; + struct rconst *next; +}; + +struct rconst *const_hash[HASHMAX]; + +static var_t *reg_const(var_t *var) +{ + struct rconst *nc; + int hash; + if (!var->name) { + error_loc("registering constant without name\n"); + return var; + } + hash = hash_ident(var->name); + nc = xmalloc(sizeof(struct rconst)); + nc->name = var->name; + nc->var = var; + nc->next = const_hash[hash]; + const_hash[hash] = nc; + return var; +} + +static var_t *find_const(char *name, int f) +{ + struct rconst *cur = const_hash[hash_ident(name)]; + while (cur && strcmp(cur->name, name)) + cur = cur->next; + if (!cur) { + if (f) error_loc("constant '%s' not found\n", name); + return NULL; + } + return cur->var; +} + +static void write_libid(const char *name, const attr_list_t *attr) +{ + const UUID *uuid = get_attrp(attr, ATTR_UUID); + write_guid(idfile, "LIBID", name, uuid); +} + +static void write_clsid(type_t *cls) +{ + const UUID *uuid = get_attrp(cls->attrs, ATTR_UUID); + write_guid(idfile, "CLSID", cls->name, uuid); +} + +static void write_diid(type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + write_guid(idfile, "DIID", iface->name, uuid); +} + +static void write_iid(type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + write_guid(idfile, "IID", iface->name, uuid); +} + +static int compute_method_indexes(type_t *iface) +{ + int idx; + func_t *f; + + if (iface->ref) + idx = compute_method_indexes(iface->ref); + else + idx = 0; + + if (!iface->funcs) + return idx; + + LIST_FOR_EACH_ENTRY( f, iface->funcs, func_t, entry ) + if (! is_callas(f->def->attrs)) + f->idx = idx++; + + return idx; +} + +static char *gen_name(void) +{ + static const char format[] = "__WIDL_%s_generated_name_%08lX"; + static unsigned long n = 0; + static const char *file_id; + static size_t size; + char *name; + + if (! file_id) + { + char *dst = dup_basename(input_name, ".idl"); + file_id = dst; + + for (; *dst; ++dst) + if (! isalnum((unsigned char) *dst)) + *dst = '_'; + + size = sizeof format - 7 + strlen(file_id) + 8; + } + + name = xmalloc(size); + sprintf(name, format, file_id, n++); + return name; +} + +static void process_typedefs(pident_list_t *pidents) +{ + pident_t *pident, *next; + + if (!pidents) return; + LIST_FOR_EACH_ENTRY_SAFE( pident, next, pidents, pident_t, entry ) + { + var_t *var = pident->var; + type_t *type = find_type(var->name, 0); + + if (! parse_only && do_header) + write_typedef(type); + if (in_typelib && type->attrs) + add_typelib_entry(type); + + free(pident); + free(var); + } +} + +static void check_arg(var_t *arg) +{ + type_t *t = arg->type; + + if (t->type == 0 && ! is_var_ptr(arg)) + error_loc("argument '%s' has void type\n", arg->name); +} + +static void check_all_user_types(ifref_list_t *ifrefs) +{ + const ifref_t *ifref; + const func_t *f; + + if (ifrefs) LIST_FOR_EACH_ENTRY(ifref, ifrefs, const ifref_t, entry) + { + const func_list_t *fs = ifref->iface->funcs; + if (fs) LIST_FOR_EACH_ENTRY(f, fs, const func_t, entry) + check_for_user_types_and_context_handles(f->args); + } +} + +int is_valid_uuid(const char *s) +{ + int i; + + for (i = 0; i < 36; ++i) + if (i == 8 || i == 13 || i == 18 || i == 23) + { + if (s[i] != '-') + return FALSE; + } + else + if (!isxdigit(s[i])) + return FALSE; + + return s[i] == '\0'; +} + diff --git a/reactos/tools/widl_20080105/parser.tab.h b/reactos/tools/widl_20080105/parser.tab.h new file mode 100644 index 00000000000..33694501d63 --- /dev/null +++ b/reactos/tools/widl_20080105/parser.tab.h @@ -0,0 +1,339 @@ +/* A Bison parser, made by GNU Bison 2.1. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + aIDENTIFIER = 258, + aKNOWNTYPE = 259, + aNUM = 260, + aHEXNUM = 261, + aDOUBLE = 262, + aSTRING = 263, + aUUID = 264, + aEOF = 265, + SHL = 266, + SHR = 267, + tAGGREGATABLE = 268, + tALLOCATE = 269, + tAPPOBJECT = 270, + tASYNC = 271, + tASYNCUUID = 272, + tAUTOHANDLE = 273, + tBINDABLE = 274, + tBOOLEAN = 275, + tBROADCAST = 276, + tBYTE = 277, + tBYTECOUNT = 278, + tCALLAS = 279, + tCALLBACK = 280, + tCASE = 281, + tCDECL = 282, + tCHAR = 283, + tCOCLASS = 284, + tCODE = 285, + tCOMMSTATUS = 286, + tCONST = 287, + tCONTEXTHANDLE = 288, + tCONTEXTHANDLENOSERIALIZE = 289, + tCONTEXTHANDLESERIALIZE = 290, + tCONTROL = 291, + tCPPQUOTE = 292, + tDEFAULT = 293, + tDEFAULTCOLLELEM = 294, + tDEFAULTVALUE = 295, + tDEFAULTVTABLE = 296, + tDISPLAYBIND = 297, + tDISPINTERFACE = 298, + tDLLNAME = 299, + tDOUBLE = 300, + tDUAL = 301, + tENDPOINT = 302, + tENTRY = 303, + tENUM = 304, + tERRORSTATUST = 305, + tEXPLICITHANDLE = 306, + tEXTERN = 307, + tFALSE = 308, + tFLOAT = 309, + tHANDLE = 310, + tHANDLET = 311, + tHELPCONTEXT = 312, + tHELPFILE = 313, + tHELPSTRING = 314, + tHELPSTRINGCONTEXT = 315, + tHELPSTRINGDLL = 316, + tHIDDEN = 317, + tHYPER = 318, + tID = 319, + tIDEMPOTENT = 320, + tIIDIS = 321, + tIMMEDIATEBIND = 322, + tIMPLICITHANDLE = 323, + tIMPORT = 324, + tIMPORTLIB = 325, + tIN = 326, + tINLINE = 327, + tINPUTSYNC = 328, + tINT = 329, + tINT64 = 330, + tINTERFACE = 331, + tLCID = 332, + tLENGTHIS = 333, + tLIBRARY = 334, + tLOCAL = 335, + tLONG = 336, + tMETHODS = 337, + tMODULE = 338, + tNONBROWSABLE = 339, + tNONCREATABLE = 340, + tNONEXTENSIBLE = 341, + tOBJECT = 342, + tODL = 343, + tOLEAUTOMATION = 344, + tOPTIONAL = 345, + tOUT = 346, + tPOINTERDEFAULT = 347, + tPROPERTIES = 348, + tPROPGET = 349, + tPROPPUT = 350, + tPROPPUTREF = 351, + tPTR = 352, + tPUBLIC = 353, + tRANGE = 354, + tREADONLY = 355, + tREF = 356, + tREQUESTEDIT = 357, + tRESTRICTED = 358, + tRETVAL = 359, + tSAFEARRAY = 360, + tSHORT = 361, + tSIGNED = 362, + tSINGLE = 363, + tSIZEIS = 364, + tSIZEOF = 365, + tSMALL = 366, + tSOURCE = 367, + tSTDCALL = 368, + tSTRING = 369, + tSTRUCT = 370, + tSWITCH = 371, + tSWITCHIS = 372, + tSWITCHTYPE = 373, + tTRANSMITAS = 374, + tTRUE = 375, + tTYPEDEF = 376, + tUNION = 377, + tUNIQUE = 378, + tUNSIGNED = 379, + tUUID = 380, + tV1ENUM = 381, + tVARARG = 382, + tVERSION = 383, + tVOID = 384, + tWCHAR = 385, + tWIREMARSHAL = 386, + CAST = 387, + PPTR = 388, + NEG = 389, + ADDRESSOF = 390 + }; +#endif +/* Tokens. */ +#define aIDENTIFIER 258 +#define aKNOWNTYPE 259 +#define aNUM 260 +#define aHEXNUM 261 +#define aDOUBLE 262 +#define aSTRING 263 +#define aUUID 264 +#define aEOF 265 +#define SHL 266 +#define SHR 267 +#define tAGGREGATABLE 268 +#define tALLOCATE 269 +#define tAPPOBJECT 270 +#define tASYNC 271 +#define tASYNCUUID 272 +#define tAUTOHANDLE 273 +#define tBINDABLE 274 +#define tBOOLEAN 275 +#define tBROADCAST 276 +#define tBYTE 277 +#define tBYTECOUNT 278 +#define tCALLAS 279 +#define tCALLBACK 280 +#define tCASE 281 +#define tCDECL 282 +#define tCHAR 283 +#define tCOCLASS 284 +#define tCODE 285 +#define tCOMMSTATUS 286 +#define tCONST 287 +#define tCONTEXTHANDLE 288 +#define tCONTEXTHANDLENOSERIALIZE 289 +#define tCONTEXTHANDLESERIALIZE 290 +#define tCONTROL 291 +#define tCPPQUOTE 292 +#define tDEFAULT 293 +#define tDEFAULTCOLLELEM 294 +#define tDEFAULTVALUE 295 +#define tDEFAULTVTABLE 296 +#define tDISPLAYBIND 297 +#define tDISPINTERFACE 298 +#define tDLLNAME 299 +#define tDOUBLE 300 +#define tDUAL 301 +#define tENDPOINT 302 +#define tENTRY 303 +#define tENUM 304 +#define tERRORSTATUST 305 +#define tEXPLICITHANDLE 306 +#define tEXTERN 307 +#define tFALSE 308 +#define tFLOAT 309 +#define tHANDLE 310 +#define tHANDLET 311 +#define tHELPCONTEXT 312 +#define tHELPFILE 313 +#define tHELPSTRING 314 +#define tHELPSTRINGCONTEXT 315 +#define tHELPSTRINGDLL 316 +#define tHIDDEN 317 +#define tHYPER 318 +#define tID 319 +#define tIDEMPOTENT 320 +#define tIIDIS 321 +#define tIMMEDIATEBIND 322 +#define tIMPLICITHANDLE 323 +#define tIMPORT 324 +#define tIMPORTLIB 325 +#define tIN 326 +#define tINLINE 327 +#define tINPUTSYNC 328 +#define tINT 329 +#define tINT64 330 +#define tINTERFACE 331 +#define tLCID 332 +#define tLENGTHIS 333 +#define tLIBRARY 334 +#define tLOCAL 335 +#define tLONG 336 +#define tMETHODS 337 +#define tMODULE 338 +#define tNONBROWSABLE 339 +#define tNONCREATABLE 340 +#define tNONEXTENSIBLE 341 +#define tOBJECT 342 +#define tODL 343 +#define tOLEAUTOMATION 344 +#define tOPTIONAL 345 +#define tOUT 346 +#define tPOINTERDEFAULT 347 +#define tPROPERTIES 348 +#define tPROPGET 349 +#define tPROPPUT 350 +#define tPROPPUTREF 351 +#define tPTR 352 +#define tPUBLIC 353 +#define tRANGE 354 +#define tREADONLY 355 +#define tREF 356 +#define tREQUESTEDIT 357 +#define tRESTRICTED 358 +#define tRETVAL 359 +#define tSAFEARRAY 360 +#define tSHORT 361 +#define tSIGNED 362 +#define tSINGLE 363 +#define tSIZEIS 364 +#define tSIZEOF 365 +#define tSMALL 366 +#define tSOURCE 367 +#define tSTDCALL 368 +#define tSTRING 369 +#define tSTRUCT 370 +#define tSWITCH 371 +#define tSWITCHIS 372 +#define tSWITCHTYPE 373 +#define tTRANSMITAS 374 +#define tTRUE 375 +#define tTYPEDEF 376 +#define tUNION 377 +#define tUNIQUE 378 +#define tUNSIGNED 379 +#define tUUID 380 +#define tV1ENUM 381 +#define tVARARG 382 +#define tVERSION 383 +#define tVOID 384 +#define tWCHAR 385 +#define tWIREMARSHAL 386 +#define CAST 387 +#define PPTR 388 +#define NEG 389 +#define ADDRESSOF 390 + + + + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 136 "parser.y" +typedef union YYSTYPE { + attr_t *attr; + attr_list_t *attr_list; + str_list_t *str_list; + expr_t *expr; + expr_list_t *expr_list; + array_dims_t *array_dims; + type_t *type; + var_t *var; + var_list_t *var_list; + pident_t *pident; + pident_list_t *pident_list; + func_t *func; + func_list_t *func_list; + ifref_t *ifref; + ifref_list_t *ifref_list; + char *str; + UUID *uuid; + unsigned int num; + double dbl; + interface_info_t ifinfo; +} YYSTYPE; +/* Line 1447 of yacc.c. */ +#line 331 "parser.tab.h" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +extern YYSTYPE parser_lval; + + + diff --git a/reactos/tools/widl_20080105/parser.y b/reactos/tools/widl_20080105/parser.y new file mode 100644 index 00000000000..6c8337efefc --- /dev/null +++ b/reactos/tools/widl_20080105/parser.y @@ -0,0 +1,2091 @@ +%{ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ALLOCA_H +#include +#endif + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "typelib.h" +#include "typegen.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 + +unsigned char pointer_default = RPC_FC_UP; + +typedef struct list typelist_t; +struct typenode { + type_t *type; + struct list entry; +}; + +typelist_t incomplete_types = LIST_INIT(incomplete_types); + +static void add_incomplete(type_t *t); +static void fix_incomplete(void); + +static str_list_t *append_str(str_list_t *list, char *str); +static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); +static attr_t *make_attr(enum attr_type type); +static attr_t *make_attrv(enum attr_type type, unsigned long val); +static attr_t *make_attrp(enum attr_type type, void *val); +static expr_t *make_expr(enum expr_type type); +static expr_t *make_exprl(enum expr_type type, long val); +static expr_t *make_exprd(enum expr_type type, double val); +static expr_t *make_exprs(enum expr_type type, char *val); +static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr); +static expr_t *make_expr1(enum expr_type type, expr_t *expr); +static expr_t *make_expr2(enum expr_type type, expr_t *exp1, expr_t *exp2); +static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3); +static type_t *make_type(unsigned char type, type_t *ref); +static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); +static array_dims_t *append_array(array_dims_t *list, expr_t *expr); +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, int top); +static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); +static ifref_t *make_ifref(type_t *iface); +static var_list_t *append_var(var_list_t *list, var_t *var); +static var_t *make_var(char *name); +static pident_list_t *append_pident(pident_list_t *list, pident_t *p); +static pident_t *make_pident(var_t *var); +static func_list_t *append_func(func_list_t *list, func_t *func); +static func_t *make_func(var_t *def, var_list_t *args); +static type_t *make_class(char *name); +static type_t *make_safearray(type_t *type); +static type_t *make_builtin(char *name); +static type_t *make_int(int sign); + +static type_t *reg_type(type_t *type, const char *name, int t); +static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs); +static type_t *find_type(const char *name, int t); +static type_t *find_type2(char *name, int t); +static type_t *get_type(unsigned char type, char *name, int t); +static type_t *get_typev(unsigned char type, var_t *name, int t); +static int get_struct_type(var_list_t *fields); + +static var_t *reg_const(var_t *var); +static var_t *find_const(char *name, int f); + +static void write_libid(const char *name, const attr_list_t *attr); +static void write_clsid(type_t *cls); +static void write_diid(type_t *iface); +static void write_iid(type_t *iface); + +static int compute_method_indexes(type_t *iface); +static char *gen_name(void); +static void process_typedefs(var_list_t *names); +static void check_arg(var_t *arg); +static void check_all_user_types(ifref_list_t *ifaces); + +#define tsENUM 1 +#define tsSTRUCT 2 +#define tsUNION 3 + +%} +%union { + attr_t *attr; + attr_list_t *attr_list; + str_list_t *str_list; + expr_t *expr; + expr_list_t *expr_list; + array_dims_t *array_dims; + type_t *type; + var_t *var; + var_list_t *var_list; + pident_t *pident; + pident_list_t *pident_list; + func_t *func; + func_list_t *func_list; + ifref_t *ifref; + ifref_list_t *ifref_list; + char *str; + UUID *uuid; + unsigned int num; + double dbl; + interface_info_t ifinfo; +} + +%token aIDENTIFIER +%token aKNOWNTYPE +%token aNUM aHEXNUM +%token aDOUBLE +%token aSTRING +%token aUUID +%token aEOF +%token SHL SHR +%token tAGGREGATABLE tALLOCATE tAPPOBJECT 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 tDEFAULTCOLLELEM +%token tDEFAULTVALUE +%token tDEFAULTVTABLE +%token tDISPLAYBIND +%token tDISPINTERFACE +%token tDLLNAME tDOUBLE tDUAL +%token tENDPOINT +%token tENTRY tENUM tERRORSTATUST +%token tEXPLICITHANDLE tEXTERN +%token tFALSE +%token tFLOAT +%token tHANDLE +%token tHANDLET +%token tHELPCONTEXT tHELPFILE +%token tHELPSTRING tHELPSTRINGCONTEXT tHELPSTRINGDLL +%token tHIDDEN +%token tHYPER tID tIDEMPOTENT +%token tIIDIS +%token tIMMEDIATEBIND +%token tIMPLICITHANDLE +%token tIMPORT tIMPORTLIB +%token tIN tINLINE +%token tINPUTSYNC +%token tINT tINT64 +%token tINTERFACE +%token tLCID +%token tLENGTHIS tLIBRARY +%token tLOCAL +%token tLONG +%token tMETHODS +%token tMODULE +%token tNONBROWSABLE +%token tNONCREATABLE +%token tNONEXTENSIBLE +%token tOBJECT tODL tOLEAUTOMATION +%token tOPTIONAL +%token tOUT +%token tPOINTERDEFAULT +%token tPROPERTIES +%token tPROPGET tPROPPUT tPROPPUTREF +%token tPTR +%token tPUBLIC +%token tRANGE +%token tREADONLY tREF +%token tREQUESTEDIT +%token tRESTRICTED +%token tRETVAL +%token tSAFEARRAY +%token tSHORT +%token tSIGNED +%token tSINGLE +%token tSIZEIS tSIZEOF +%token tSMALL +%token tSOURCE +%token tSTDCALL +%token tSTRING tSTRUCT +%token tSWITCH tSWITCHIS tSWITCHTYPE +%token tTRANSMITAS +%token tTRUE +%token tTYPEDEF +%token tUNION +%token tUNIQUE +%token tUNSIGNED +%token tUUID +%token tV1ENUM +%token tVARARG +%token tVERSION +%token tVOID +%token tWCHAR tWIREMARSHAL + +%type attribute +%type m_attributes attributes attrib_list +%type str_list +%type m_expr expr expr_const +%type m_exprs /* exprs expr_list */ expr_list_const +%type array array_list +%type interfacehdr +%type inherit interface interfacedef interfacedec +%type dispinterface dispinterfacehdr dispinterfacedef +%type module modulehdr moduledef +%type base_type int_std +%type enumdef structdef uniondef +%type type +%type coclass_int +%type gbl_statements coclass_ints +%type arg field s_field case enum constdef externdef +%type m_args no_args args fields cases enums enum_list dispint_props +%type m_ident t_ident ident +%type p_ident pident +%type pident_list +%type funcdef +%type int_statements dispint_meths +%type coclass coclasshdr coclassdef +%type pointer_type version +%type libraryhdr +%type uuid_string + +%left ',' +%right '?' ':' +%left '|' +%left '&' +%left '-' '+' +%left '*' '/' +%left SHL SHR +%right '~' +%right CAST +%right PPTR +%right NEG +%right ADDRESSOF + +%% + +input: gbl_statements { fix_incomplete(); + check_all_user_types($1); + write_proxies($1); + write_client($1); + write_server($1); + write_dlldata($1); + } + ; + +gbl_statements: { $$ = NULL; } + | gbl_statements interfacedec { $$ = $1; } + | gbl_statements interfacedef { $$ = append_ifref( $1, make_ifref($2) ); } + | gbl_statements coclass ';' { $$ = $1; + reg_type($2, $2->name, 0); + if (!parse_only && do_header) write_coclass_forward($2); + } + | gbl_statements coclassdef { $$ = $1; + add_typelib_entry($2); + reg_type($2, $2->name, 0); + if (!parse_only && do_header) write_coclass_forward($2); + } + | gbl_statements moduledef { $$ = $1; add_typelib_entry($2); } + | gbl_statements librarydef { $$ = $1; } + | gbl_statements statement { $$ = $1; } + ; + +imp_statements: {} + | imp_statements interfacedec { if (!parse_only) add_typelib_entry($2); } + | imp_statements interfacedef { if (!parse_only) add_typelib_entry($2); } + | imp_statements coclass ';' { reg_type($2, $2->name, 0); if (!parse_only && do_header) write_coclass_forward($2); } + | imp_statements coclassdef { if (!parse_only) add_typelib_entry($2); + reg_type($2, $2->name, 0); + if (!parse_only && do_header) write_coclass_forward($2); + } + | imp_statements moduledef { if (!parse_only) add_typelib_entry($2); } + | imp_statements statement {} + | imp_statements importlib {} + ; + +int_statements: { $$ = NULL; } + | int_statements funcdef ';' { $$ = append_func( $1, $2 ); } + | int_statements statement { $$ = $1; } + ; + +statement: ';' {} + | constdef ';' { if (!parse_only && do_header) { write_constdef($1); } } + | cppquote {} + | enumdef ';' { if (!parse_only && do_header) { + write_type_def_or_decl(header, $1, FALSE, NULL); + fprintf(header, ";\n\n"); + } + } + | externdef ';' { if (!parse_only && do_header) { write_externdef($1); } } + | import {} + | structdef ';' { if (!parse_only && do_header) { + write_type_def_or_decl(header, $1, FALSE, NULL); + fprintf(header, ";\n\n"); + } + } + | typedef ';' {} + | uniondef ';' { if (!parse_only && do_header) { + write_type_def_or_decl(header, $1, FALSE, NULL); + fprintf(header, ";\n\n"); + } + } + ; + +cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only && do_header) fprintf(header, "%s\n", $3); } + ; +import_start: tIMPORT aSTRING ';' { assert(yychar == YYEMPTY); + if (!do_import($2)) yychar = aEOF; } + ; +import: import_start imp_statements aEOF {} + ; + +importlib: tIMPORTLIB '(' aSTRING ')' { if(!parse_only) add_importlib($3); } + ; + +libraryhdr: tLIBRARY aIDENTIFIER { $$ = $2; } + ; +library_start: attributes libraryhdr '{' { start_typelib($2, $1); + if (!parse_only && do_header) write_library($2, $1); + if (!parse_only && do_idfile) write_libid($2, $1); + } + ; +librarydef: library_start imp_statements '}' { end_typelib(); } + ; + +m_args: { $$ = NULL; } + | args + ; + +no_args: tVOID { $$ = NULL; } + ; + +args: arg { check_arg($1); $$ = append_var( NULL, $1 ); } + | args ',' arg { check_arg($3); $$ = append_var( $1, $3); } + | no_args + ; + +/* split into two rules to get bison to resolve a tVOID conflict */ +arg: attributes type pident array { $$ = $3->var; + $$->attrs = $1; + set_type($$, $2, $3->ptr_level, $4, TRUE); + free($3); + } + | type pident array { $$ = $2->var; + set_type($$, $1, $2->ptr_level, $3, TRUE); + free($2); + } + | attributes type pident '(' m_args ')' { $$ = $3->var; + $$->attrs = $1; + set_type($$, $2, $3->ptr_level - 1, NULL, TRUE); + free($3); + $$->args = $5; + } + | type pident '(' m_args ')' { $$ = $2->var; + set_type($$, $1, $2->ptr_level - 1, NULL, TRUE); + free($2); + $$->args = $4; + } + ; + +array: { $$ = NULL; } + | '[' array_list ']' { $$ = $2; } + | '[' '*' ']' { $$ = append_array( NULL, make_expr(EXPR_VOID) ); } + ; + +array_list: m_expr /* size of first dimension is optional */ { $$ = append_array( NULL, $1 ); } + | array_list ',' expr { $$ = append_array( $1, $3 ); } + | array_list ']' '[' expr { $$ = append_array( $1, $4 ); } + ; + +m_attributes: { $$ = NULL; } + | attributes + ; + +attributes: + '[' attrib_list ']' { $$ = $2; + if (!$$) + error_loc("empty attribute lists unsupported\n"); + } + ; + +attrib_list: attribute { $$ = append_attr( NULL, $1 ); } + | attrib_list ',' attribute { $$ = append_attr( $1, $3 ); } + | attrib_list ']' '[' attribute { $$ = append_attr( $1, $4 ); } + ; + +str_list: aSTRING { $$ = append_str( NULL, $1 ); } + | str_list ',' aSTRING { $$ = append_str( $1, $3 ); } + ; + +attribute: { $$ = NULL; } + | tAGGREGATABLE { $$ = make_attr(ATTR_AGGREGATABLE); } + | tAPPOBJECT { $$ = make_attr(ATTR_APPOBJECT); } + | tASYNC { $$ = make_attr(ATTR_ASYNC); } + | tAUTOHANDLE { $$ = make_attr(ATTR_AUTO_HANDLE); } + | tBINDABLE { $$ = make_attr(ATTR_BINDABLE); } + | tCALLAS '(' ident ')' { $$ = make_attrp(ATTR_CALLAS, $3); } + | tCASE '(' expr_list_const ')' { $$ = make_attrp(ATTR_CASE, $3); } + | tCONTEXTHANDLE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); } + | tCONTEXTHANDLENOSERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_DONT_SERIALIZE */ } + | tCONTEXTHANDLESERIALIZE { $$ = make_attrv(ATTR_CONTEXTHANDLE, 0); /* RPC_CONTEXT_HANDLE_SERIALIZE */ } + | tCONTROL { $$ = make_attr(ATTR_CONTROL); } + | tDEFAULT { $$ = make_attr(ATTR_DEFAULT); } + | tDEFAULTCOLLELEM { $$ = make_attr(ATTR_DEFAULTCOLLELEM); } + | tDEFAULTVALUE '(' expr_const ')' { $$ = make_attrp(ATTR_DEFAULTVALUE_EXPR, $3); } + | tDEFAULTVALUE '(' aSTRING ')' { $$ = make_attrp(ATTR_DEFAULTVALUE_STRING, $3); } + | tDEFAULTVTABLE { $$ = make_attr(ATTR_DEFAULTVTABLE); } + | tDISPLAYBIND { $$ = make_attr(ATTR_DISPLAYBIND); } + | tDLLNAME '(' aSTRING ')' { $$ = make_attrp(ATTR_DLLNAME, $3); } + | tDUAL { $$ = make_attr(ATTR_DUAL); } + | tENDPOINT '(' str_list ')' { $$ = make_attrp(ATTR_ENDPOINT, $3); } + | tENTRY '(' aSTRING ')' { $$ = make_attrp(ATTR_ENTRY_STRING, $3); } + | tENTRY '(' expr_const ')' { $$ = make_attrp(ATTR_ENTRY_ORDINAL, $3); } + | tEXPLICITHANDLE { $$ = make_attr(ATTR_EXPLICIT_HANDLE); } + | tHANDLE { $$ = make_attr(ATTR_HANDLE); } + | tHELPCONTEXT '(' expr_const ')' { $$ = make_attrp(ATTR_HELPCONTEXT, $3); } + | tHELPFILE '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPFILE, $3); } + | tHELPSTRING '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPSTRING, $3); } + | tHELPSTRINGCONTEXT '(' expr_const ')' { $$ = make_attrp(ATTR_HELPSTRINGCONTEXT, $3); } + | tHELPSTRINGDLL '(' aSTRING ')' { $$ = make_attrp(ATTR_HELPSTRINGDLL, $3); } + | tHIDDEN { $$ = make_attr(ATTR_HIDDEN); } + | tID '(' expr_const ')' { $$ = make_attrp(ATTR_ID, $3); } + | tIDEMPOTENT { $$ = make_attr(ATTR_IDEMPOTENT); } + | tIIDIS '(' expr ')' { $$ = make_attrp(ATTR_IIDIS, $3); } + | tIMMEDIATEBIND { $$ = make_attr(ATTR_IMMEDIATEBIND); } + | tIMPLICITHANDLE '(' tHANDLET aIDENTIFIER ')' { $$ = make_attrp(ATTR_IMPLICIT_HANDLE, $4); } + | tIN { $$ = make_attr(ATTR_IN); } + | tINPUTSYNC { $$ = make_attr(ATTR_INPUTSYNC); } + | tLENGTHIS '(' m_exprs ')' { $$ = make_attrp(ATTR_LENGTHIS, $3); } + | tLOCAL { $$ = make_attr(ATTR_LOCAL); } + | tNONBROWSABLE { $$ = make_attr(ATTR_NONBROWSABLE); } + | tNONCREATABLE { $$ = make_attr(ATTR_NONCREATABLE); } + | tNONEXTENSIBLE { $$ = make_attr(ATTR_NONEXTENSIBLE); } + | tOBJECT { $$ = make_attr(ATTR_OBJECT); } + | tODL { $$ = make_attr(ATTR_ODL); } + | tOLEAUTOMATION { $$ = make_attr(ATTR_OLEAUTOMATION); } + | tOPTIONAL { $$ = make_attr(ATTR_OPTIONAL); } + | tOUT { $$ = make_attr(ATTR_OUT); } + | tPOINTERDEFAULT '(' pointer_type ')' { $$ = make_attrv(ATTR_POINTERDEFAULT, $3); } + | tPROPGET { $$ = make_attr(ATTR_PROPGET); } + | tPROPPUT { $$ = make_attr(ATTR_PROPPUT); } + | tPROPPUTREF { $$ = make_attr(ATTR_PROPPUTREF); } + | tPUBLIC { $$ = make_attr(ATTR_PUBLIC); } + | tRANGE '(' expr_const ',' expr_const ')' { expr_list_t *list = append_expr( NULL, $3 ); + list = append_expr( list, $5 ); + $$ = make_attrp(ATTR_RANGE, list); } + | tREADONLY { $$ = make_attr(ATTR_READONLY); } + | tREQUESTEDIT { $$ = make_attr(ATTR_REQUESTEDIT); } + | tRESTRICTED { $$ = make_attr(ATTR_RESTRICTED); } + | tRETVAL { $$ = make_attr(ATTR_RETVAL); } + | tSIZEIS '(' m_exprs ')' { $$ = make_attrp(ATTR_SIZEIS, $3); } + | tSOURCE { $$ = make_attr(ATTR_SOURCE); } + | tSTRING { $$ = make_attr(ATTR_STRING); } + | tSWITCHIS '(' expr ')' { $$ = make_attrp(ATTR_SWITCHIS, $3); } + | tSWITCHTYPE '(' type ')' { $$ = make_attrp(ATTR_SWITCHTYPE, $3); } + | tTRANSMITAS '(' type ')' { $$ = make_attrp(ATTR_TRANSMITAS, $3); } + | tUUID '(' uuid_string ')' { $$ = make_attrp(ATTR_UUID, $3); } + | tV1ENUM { $$ = make_attr(ATTR_V1ENUM); } + | tVARARG { $$ = make_attr(ATTR_VARARG); } + | tVERSION '(' version ')' { $$ = make_attrv(ATTR_VERSION, $3); } + | tWIREMARSHAL '(' type ')' { $$ = make_attrp(ATTR_WIREMARSHAL, $3); } + | pointer_type { $$ = make_attrv(ATTR_POINTERTYPE, $1); } + ; + +uuid_string: + aUUID + | aSTRING { if (!is_valid_uuid($1)) + error_loc("invalid UUID: %s\n", $1); + $$ = parse_uuid($1); } + ; + +callconv: + | tSTDCALL + ; + +cases: { $$ = NULL; } + | cases case { $$ = append_var( $1, $2 ); } + ; + +case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, append_expr( NULL, $2 )); + $$ = $4; if (!$$) $$ = make_var(NULL); + $$->attrs = append_attr( $$->attrs, a ); + } + | tDEFAULT ':' field { attr_t *a = make_attr(ATTR_DEFAULT); + $$ = $3; if (!$$) $$ = make_var(NULL); + $$->attrs = append_attr( $$->attrs, a ); + } + ; + +constdef: tCONST type ident '=' expr_const { $$ = reg_const($3); + set_type($$, $2, 0, NULL, FALSE); + $$->eval = $5; + } + ; + +enums: { $$ = NULL; } + | enum_list ',' { $$ = $1; } + | enum_list + ; + +enum_list: enum { if (!$1->eval) + $1->eval = make_exprl(EXPR_NUM, 0 /* default for first enum entry */); + $$ = append_var( NULL, $1 ); + } + | enum_list ',' enum { if (!$3->eval) + { + var_t *last = LIST_ENTRY( list_tail($$), var_t, entry ); + $3->eval = make_exprl(EXPR_NUM, last->eval->cval + 1); + } + $$ = append_var( $1, $3 ); + } + ; + +enum: ident '=' expr_const { $$ = reg_const($1); + $$->eval = $3; + $$->type = make_int(0); + } + | ident { $$ = reg_const($1); + $$->type = make_int(0); + } + ; + +enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM); + $$->kind = TKIND_ENUM; + $$->fields = $4; + $$->defined = TRUE; + if(in_typelib) + add_typelib_entry($$); + } + ; + +m_exprs: m_expr { $$ = append_expr( NULL, $1 ); } + | m_exprs ',' m_expr { $$ = append_expr( $1, $3 ); } + ; + +/* +exprs: { $$ = make_expr(EXPR_VOID); } + | expr_list + ; + +expr_list: expr + | expr_list ',' expr { LINK($3, $1); $$ = $3; } + ; +*/ + +m_expr: { $$ = make_expr(EXPR_VOID); } + | expr + ; + +expr: aNUM { $$ = make_exprl(EXPR_NUM, $1); } + | aHEXNUM { $$ = make_exprl(EXPR_HEXNUM, $1); } + | aDOUBLE { $$ = make_exprd(EXPR_DOUBLE, $1); } + | tFALSE { $$ = make_exprl(EXPR_TRUEFALSE, 0); } + | tTRUE { $$ = make_exprl(EXPR_TRUEFALSE, 1); } + | aIDENTIFIER { $$ = make_exprs(EXPR_IDENTIFIER, $1); } + | expr '?' expr ':' expr { $$ = make_expr3(EXPR_COND, $1, $3, $5); } + | expr '|' expr { $$ = make_expr2(EXPR_OR , $1, $3); } + | expr '&' expr { $$ = make_expr2(EXPR_AND, $1, $3); } + | expr '+' expr { $$ = make_expr2(EXPR_ADD, $1, $3); } + | expr '-' expr { $$ = make_expr2(EXPR_SUB, $1, $3); } + | expr '*' expr { $$ = make_expr2(EXPR_MUL, $1, $3); } + | expr '/' expr { $$ = make_expr2(EXPR_DIV, $1, $3); } + | expr SHL expr { $$ = make_expr2(EXPR_SHL, $1, $3); } + | expr SHR expr { $$ = make_expr2(EXPR_SHR, $1, $3); } + | '~' expr { $$ = make_expr1(EXPR_NOT, $2); } + | '-' expr %prec NEG { $$ = make_expr1(EXPR_NEG, $2); } + | '&' expr %prec ADDRESSOF { $$ = make_expr1(EXPR_ADDRESSOF, $2); } + | '*' expr %prec PPTR { $$ = make_expr1(EXPR_PPTR, $2); } + | '(' type ')' expr %prec CAST { $$ = make_exprt(EXPR_CAST, $2, $4); } + | tSIZEOF '(' type ')' { $$ = make_exprt(EXPR_SIZEOF, $3, NULL); } + | '(' expr ')' { $$ = $2; } + ; + +expr_list_const: expr_const { $$ = append_expr( NULL, $1 ); } + | expr_list_const ',' expr_const { $$ = append_expr( $1, $3 ); } + ; + +expr_const: expr { $$ = $1; + if (!$$->is_const) + error_loc("expression is not constant\n"); + } + ; + +externdef: tEXTERN tCONST type ident { $$ = $4; + set_type($$, $3, 0, NULL, FALSE); + } + ; + +fields: { $$ = NULL; } + | fields field { $$ = append_var( $1, $2 ); } + ; + +field: s_field ';' { $$ = $1; } + | m_attributes uniondef ';' { $$ = make_var(NULL); $$->type = $2; $$->attrs = $1; } + | attributes ';' { $$ = make_var(NULL); $$->attrs = $1; } + | ';' { $$ = NULL; } + ; + +s_field: m_attributes type pident array { $$ = $3->var; + $$->attrs = $1; + set_type($$, $2, $3->ptr_level, $4, FALSE); + free($3); + } + ; + +funcdef: + m_attributes type callconv pident + '(' m_args ')' { var_t *v = $4->var; + v->attrs = $1; + set_type(v, $2, $4->ptr_level, NULL, FALSE); + free($4); + $$ = make_func(v, $6); + if (is_attr(v->attrs, ATTR_IN)) { + error_loc("inapplicable attribute [in] for function '%s'\n",$$->def->name); + } + } + ; + +m_ident: { $$ = NULL; } + | ident + ; + +t_ident: { $$ = NULL; } + | aIDENTIFIER { $$ = make_var($1); } + | aKNOWNTYPE { $$ = make_var($1); } + ; + +ident: aIDENTIFIER { $$ = make_var($1); } +/* some "reserved words" used in attributes are also used as field names in some MS IDL files */ + | aKNOWNTYPE { $$ = make_var($1); } + ; + +base_type: tBYTE { $$ = make_builtin($1); } + | tWCHAR { $$ = make_builtin($1); } + | int_std + | tSIGNED int_std { $$ = $2; $$->sign = 1; } + | tUNSIGNED int_std { $$ = $2; $$->sign = -1; + switch ($$->type) { + case RPC_FC_CHAR: break; + case RPC_FC_SMALL: $$->type = RPC_FC_USMALL; break; + case RPC_FC_SHORT: $$->type = RPC_FC_USHORT; break; + case RPC_FC_LONG: $$->type = RPC_FC_ULONG; break; + case RPC_FC_HYPER: + if ($$->name[0] == 'h') /* hyper, as opposed to __int64 */ + { + $$ = alias($$, "MIDL_uhyper"); + $$->sign = 0; + } + break; + default: break; + } + } + | tUNSIGNED { $$ = make_int(-1); } + | tFLOAT { $$ = make_builtin($1); } + | tSINGLE { $$ = duptype(find_type("float", 0), 1); } + | tDOUBLE { $$ = make_builtin($1); } + | tBOOLEAN { $$ = make_builtin($1); } + | tERRORSTATUST { $$ = make_builtin($1); } + | tHANDLET { $$ = make_builtin($1); } + ; + +m_int: + | tINT + ; + +int_std: tINT { $$ = make_builtin($1); } + | tSHORT m_int { $$ = make_builtin($1); } + | tSMALL { $$ = make_builtin($1); } + | tLONG m_int { $$ = make_builtin($1); } + | tHYPER m_int { $$ = make_builtin($1); } + | tINT64 { $$ = make_builtin($1); } + | tCHAR { $$ = make_builtin($1); } + ; + +coclass: tCOCLASS aIDENTIFIER { $$ = make_class($2); } + | tCOCLASS aKNOWNTYPE { $$ = find_type($2, 0); + if ($$->defined) error_loc("multiple definition error\n"); + if ($$->kind != TKIND_COCLASS) error_loc("%s was not declared a coclass\n", $2); + } + ; + +coclasshdr: attributes coclass { $$ = $2; + $$->attrs = $1; + if (!parse_only && do_header) + write_coclass($$); + if (!parse_only && do_idfile) + write_clsid($$); + } + ; + +coclassdef: coclasshdr '{' coclass_ints '}' { $$ = $1; + $$->ifaces = $3; + $$->defined = TRUE; + } + ; + +coclass_ints: { $$ = NULL; } + | coclass_ints coclass_int { $$ = append_ifref( $1, $2 ); } + ; + +coclass_int: + m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } + ; + +dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; } + | tDISPINTERFACE aKNOWNTYPE { $$ = get_type(0, $2, 0); $$->kind = TKIND_DISPATCH; } + ; + +dispinterfacehdr: attributes dispinterface { attr_t *attrs; + $$ = $2; + if ($$->defined) error_loc("multiple definition error\n"); + attrs = make_attr(ATTR_DISPINTERFACE); + $$->attrs = append_attr( $1, attrs ); + $$->ref = find_type("IDispatch", 0); + if (!$$->ref) error_loc("IDispatch is undefined\n"); + $$->defined = TRUE; + if (!parse_only && do_header) write_forward($$); + } + ; + +dispint_props: tPROPERTIES ':' { $$ = NULL; } + | dispint_props s_field ';' { $$ = append_var( $1, $2 ); } + ; + +dispint_meths: tMETHODS ':' { $$ = NULL; } + | dispint_meths funcdef ';' { $$ = append_func( $1, $2 ); } + ; + +dispinterfacedef: dispinterfacehdr '{' + dispint_props + dispint_meths + '}' { $$ = $1; + $$->fields = $3; + $$->funcs = $4; + if (!parse_only && do_header) write_dispinterface($$); + if (!parse_only && do_idfile) write_diid($$); + } + | dispinterfacehdr + '{' interface ';' '}' { $$ = $1; + $$->fields = $3->fields; + $$->funcs = $3->funcs; + if (!parse_only && do_header) write_dispinterface($$); + if (!parse_only && do_idfile) write_diid($$); + } + ; + +inherit: { $$ = NULL; } + | ':' aKNOWNTYPE { $$ = find_type2($2, 0); } + ; + +interface: tINTERFACE aIDENTIFIER { $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_INTERFACE; } + | tINTERFACE aKNOWNTYPE { $$ = get_type(RPC_FC_IP, $2, 0); $$->kind = TKIND_INTERFACE; } + ; + +interfacehdr: attributes interface { $$.interface = $2; + $$.old_pointer_default = pointer_default; + if (is_attr($1, ATTR_POINTERDEFAULT)) + pointer_default = get_attrv($1, ATTR_POINTERDEFAULT); + if ($2->defined) error_loc("multiple definition error\n"); + $2->attrs = $1; + $2->defined = TRUE; + if (!parse_only && do_header) write_forward($2); + } + ; + +interfacedef: interfacehdr inherit + '{' int_statements '}' { $$ = $1.interface; + $$->ref = $2; + $$->funcs = $4; + compute_method_indexes($$); + if (!parse_only && do_header) write_interface($$); + if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE); + if (!parse_only && do_idfile) write_iid($$); + pointer_default = $1.old_pointer_default; + } +/* MIDL is able to import the definition of a base class from inside the + * definition of a derived class, I'll try to support it with this rule */ + | interfacehdr ':' aIDENTIFIER + '{' import int_statements '}' { $$ = $1.interface; + $$->ref = find_type2($3, 0); + if (!$$->ref) error_loc("base class '%s' not found in import\n", $3); + $$->funcs = $6; + compute_method_indexes($$); + if (!parse_only && do_header) write_interface($$); + if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE); + if (!parse_only && do_idfile) write_iid($$); + pointer_default = $1.old_pointer_default; + } + | dispinterfacedef { $$ = $1; } + ; + +interfacedec: + interface ';' { $$ = $1; if (!parse_only && do_header) write_forward($$); } + | dispinterface ';' { $$ = $1; if (!parse_only && do_header) write_forward($$); } + ; + +module: tMODULE aIDENTIFIER { $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; } + | tMODULE aKNOWNTYPE { $$ = make_type(0, NULL); $$->name = $2; $$->kind = TKIND_MODULE; } + ; + +modulehdr: attributes module { $$ = $2; + $$->attrs = $1; + } + ; + +moduledef: modulehdr '{' int_statements '}' { $$ = $1; + $$->funcs = $3; + /* FIXME: if (!parse_only && do_header) write_module($$); */ + } + ; + +p_ident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; } + | tCONST p_ident { $$ = $2; /* FIXME */ } + ; + +pident: ident { $$ = make_pident($1); } + | p_ident + | '(' pident ')' { $$ = $2; } + ; + +pident_list: + pident { $$ = append_pident( NULL, $1 ); } + | pident_list ',' pident { $$ = append_pident( $1, $3 ); } + ; + +pointer_type: + tREF { $$ = RPC_FC_RP; } + | tUNIQUE { $$ = RPC_FC_UP; } + | tPTR { $$ = RPC_FC_FP; } + ; + +structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, tsSTRUCT); + /* overwrite RPC_FC_STRUCT with a more exact type */ + $$->type = get_struct_type( $4 ); + $$->kind = TKIND_RECORD; + $$->fields = $4; + $$->defined = TRUE; + if(in_typelib) + add_typelib_entry($$); + } + ; + +type: tVOID { $$ = duptype(find_type("void", 0), 1); } + | aKNOWNTYPE { $$ = find_type($1, 0); } + | base_type { $$ = $1; } + | tCONST type { $$ = duptype($2, 1); $$->is_const = TRUE; } + | enumdef { $$ = $1; } + | tENUM aIDENTIFIER { $$ = find_type2($2, tsENUM); } + | structdef { $$ = $1; } + | tSTRUCT aIDENTIFIER { $$ = get_type(RPC_FC_STRUCT, $2, tsSTRUCT); } + | uniondef { $$ = $1; } + | tUNION aIDENTIFIER { $$ = find_type2($2, tsUNION); } + | tSAFEARRAY '(' type ')' { $$ = make_safearray($3); } + ; + +typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs($3, $4, $2); + process_typedefs($4); + } + ; + +uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION); + $$->kind = TKIND_UNION; + $$->fields = $4; + $$->defined = TRUE; + } + | tUNION t_ident + tSWITCH '(' s_field ')' + m_ident '{' cases '}' { var_t *u = $7; + $$ = get_typev(RPC_FC_ENCAPSULATED_UNION, $2, tsUNION); + $$->kind = TKIND_UNION; + if (!u) u = make_var( xstrdup("tagged_union") ); + u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL); + u->type->kind = TKIND_UNION; + u->type->fields = $9; + u->type->defined = TRUE; + $$->fields = append_var( $$->fields, $5 ); + $$->fields = append_var( $$->fields, u ); + $$->defined = TRUE; + } + ; + +version: + aNUM { $$ = MAKEVERSION($1, 0); } + | aNUM '.' aNUM { $$ = MAKEVERSION($1, $3); } + ; + +%% + +static void decl_builtin(const char *name, unsigned char type) +{ + type_t *t = make_type(type, NULL); + t->name = xstrdup(name); + reg_type(t, name, 0); +} + +static type_t *make_builtin(char *name) +{ + /* NAME is strdup'd in the lexer */ + type_t *t = duptype(find_type(name, 0), 0); + t->name = name; + return t; +} + +static type_t *make_int(int sign) +{ + type_t *t = duptype(find_type("int", 0), 1); + + t->sign = sign; + if (sign < 0) + t->type = t->type == RPC_FC_LONG ? RPC_FC_ULONG : RPC_FC_USHORT; + + return t; +} + +void init_types(void) +{ + decl_builtin("void", 0); + decl_builtin("byte", RPC_FC_BYTE); + decl_builtin("wchar_t", RPC_FC_WCHAR); + decl_builtin("int", RPC_FC_LONG); /* win32 */ + decl_builtin("short", RPC_FC_SHORT); + decl_builtin("small", RPC_FC_SMALL); + decl_builtin("long", RPC_FC_LONG); + decl_builtin("hyper", RPC_FC_HYPER); + decl_builtin("__int64", RPC_FC_HYPER); + decl_builtin("char", RPC_FC_CHAR); + decl_builtin("float", RPC_FC_FLOAT); + decl_builtin("double", RPC_FC_DOUBLE); + decl_builtin("boolean", RPC_FC_BYTE); + decl_builtin("error_status_t", RPC_FC_ERROR_STATUS_T); + decl_builtin("handle_t", RPC_FC_BIND_PRIMITIVE); +} + +static str_list_t *append_str(str_list_t *list, char *str) +{ + struct str_list_entry_t *entry; + + if (!str) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + entry = xmalloc( sizeof(*entry) ); + entry->str = str; + list_add_tail( list, &entry->entry ); + return list; +} + +static attr_list_t *append_attr(attr_list_t *list, attr_t *attr) +{ + if (!attr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &attr->entry ); + return list; +} + +static attr_t *make_attr(enum attr_type type) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.ival = 0; + return a; +} + +static attr_t *make_attrv(enum attr_type type, unsigned long val) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.ival = val; + return a; +} + +static attr_t *make_attrp(enum attr_type type, void *val) +{ + attr_t *a = xmalloc(sizeof(attr_t)); + a->type = type; + a->u.pval = val; + return a; +} + +static expr_t *make_expr(enum expr_type type) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.lval = 0; + e->is_const = FALSE; + e->cval = 0; + return e; +} + +static expr_t *make_exprl(enum expr_type type, long val) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.lval = val; + e->is_const = FALSE; + /* check for numeric constant */ + if (type == EXPR_NUM || type == EXPR_HEXNUM || type == EXPR_TRUEFALSE) { + /* make sure true/false value is valid */ + assert(type != EXPR_TRUEFALSE || val == 0 || val == 1); + e->is_const = TRUE; + e->cval = val; + } + return e; +} + +static expr_t *make_exprd(enum expr_type type, double val) +{ + expr_t *e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.dval = val; + e->is_const = TRUE; + e->cval = val; + return e; +} + +static expr_t *make_exprs(enum expr_type type, char *val) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = NULL; + e->u.sval = val; + e->is_const = FALSE; + /* check for predefined constants */ + if (type == EXPR_IDENTIFIER) { + var_t *c = find_const(val, 0); + if (c) { + e->u.sval = c->name; + free(val); + e->is_const = TRUE; + e->cval = c->eval->cval; + } + } + return e; +} + +static expr_t *make_exprt(enum expr_type type, type_t *tref, expr_t *expr) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr; + e->u.tref = tref; + e->is_const = FALSE; + /* check for cast of constant expression */ + if (type == EXPR_SIZEOF) { + switch (tref->type) { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + e->is_const = TRUE; + e->cval = 1; + break; + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + e->is_const = TRUE; + e->cval = 2; + break; + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_FLOAT: + case RPC_FC_ERROR_STATUS_T: + e->is_const = TRUE; + e->cval = 4; + break; + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + e->is_const = TRUE; + e->cval = 8; + break; + } + } + if (type == EXPR_CAST && expr->is_const) { + e->is_const = TRUE; + e->cval = expr->cval; + } + return e; +} + +static expr_t *make_expr1(enum expr_type type, expr_t *expr) +{ + expr_t *e; + if (type == EXPR_ADDRESSOF && expr->type != EXPR_IDENTIFIER) + error("address-of operator applied to invalid expression\n"); + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr; + e->u.lval = 0; + e->is_const = FALSE; + /* check for compile-time optimization */ + if (expr->is_const) { + e->is_const = TRUE; + switch (type) { + case EXPR_NEG: + e->cval = -expr->cval; + break; + case EXPR_NOT: + e->cval = ~expr->cval; + break; + default: + e->is_const = FALSE; + break; + } + } + return e; +} + +static expr_t *make_expr2(enum expr_type type, expr_t *expr1, expr_t *expr2) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr1; + e->u.ext = expr2; + e->is_const = FALSE; + /* check for compile-time optimization */ + if (expr1->is_const && expr2->is_const) { + e->is_const = TRUE; + switch (type) { + case EXPR_ADD: + e->cval = expr1->cval + expr2->cval; + break; + case EXPR_SUB: + e->cval = expr1->cval - expr2->cval; + break; + case EXPR_MUL: + e->cval = expr1->cval * expr2->cval; + break; + case EXPR_DIV: + e->cval = expr1->cval / expr2->cval; + break; + case EXPR_OR: + e->cval = expr1->cval | expr2->cval; + break; + case EXPR_AND: + e->cval = expr1->cval & expr2->cval; + break; + case EXPR_SHL: + e->cval = expr1->cval << expr2->cval; + break; + case EXPR_SHR: + e->cval = expr1->cval >> expr2->cval; + break; + default: + e->is_const = FALSE; + break; + } + } + return e; +} + +static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, expr_t *expr3) +{ + expr_t *e; + e = xmalloc(sizeof(expr_t)); + e->type = type; + e->ref = expr1; + e->u.ext = expr2; + e->ext2 = expr3; + e->is_const = FALSE; + /* check for compile-time optimization */ + if (expr1->is_const && expr2->is_const && expr3->is_const) { + e->is_const = TRUE; + switch (type) { + case EXPR_COND: + e->cval = expr1->cval ? expr2->cval : expr3->cval; + break; + default: + e->is_const = FALSE; + break; + } + } + return e; +} + +static expr_list_t *append_expr(expr_list_t *list, expr_t *expr) +{ + if (!expr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &expr->entry ); + return list; +} + +static array_dims_t *append_array(array_dims_t *list, expr_t *expr) +{ + if (!expr) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &expr->entry ); + return list; +} + +static struct list type_pool = LIST_INIT(type_pool); +typedef struct +{ + type_t data; + struct list link; +} type_pool_node_t; + +type_t *alloc_type(void) +{ + type_pool_node_t *node = xmalloc(sizeof *node); + list_add_tail(&type_pool, &node->link); + return &node->data; +} + +void set_all_tfswrite(int val) +{ + type_pool_node_t *node; + LIST_FOR_EACH_ENTRY(node, &type_pool, type_pool_node_t, link) + node->data.tfswrite = val; +} + +static type_t *make_type(unsigned char type, type_t *ref) +{ + type_t *t = alloc_type(); + t->name = NULL; + t->kind = TKIND_PRIMITIVE; + t->type = type; + t->ref = ref; + t->attrs = NULL; + t->orig = NULL; + t->funcs = NULL; + t->fields = NULL; + t->ifaces = NULL; + t->dim = 0; + t->size_is = NULL; + t->length_is = NULL; + t->typestring_offset = 0; + t->ptrdesc = 0; + t->declarray = FALSE; + t->ignore = (parse_only != 0); + t->is_const = FALSE; + t->sign = 0; + t->defined = FALSE; + t->written = FALSE; + t->user_types_registered = FALSE; + t->tfswrite = FALSE; + t->typelib_idx = -1; + return t; +} + +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, + int top) +{ + expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS); + expr_list_t *lengs = get_attrp(v->attrs, ATTR_LENGTHIS); + int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); + int ptr_type = ptr_attr; + int sizeless, has_varconf; + expr_t *dim; + type_t *atype, **ptype; + + v->type = type; + + if (!ptr_type && top) + ptr_type = RPC_FC_RP; + + for ( ; 0 < ptr_level; --ptr_level) + { + v->type = make_type(pointer_default, v->type); + if (ptr_level == 1 && ptr_type && !arr) + { + v->type->type = ptr_type; + ptr_type = 0; + } + } + + if (ptr_type && !arr) + { + if (is_ptr(v->type)) + { + if (v->type->type != ptr_type) + { + v->type = duptype(v->type, 1); + v->type->type = ptr_type; + } + } + else if (!arr && ptr_attr) + error("%s: pointer attribute applied to non-pointer type\n", v->name); + } + + sizeless = FALSE; + if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry) + { + if (sizeless) + error("%s: only the first array dimension can be unspecified\n", v->name); + + if (dim->is_const) + { + unsigned int align = 0; + size_t size = type_memsize(v->type, &align); + + if (dim->cval <= 0) + error("%s: array dimension must be positive\n", v->name); + + if (0xffffffffuL / size < (unsigned long) dim->cval) + error("%s: total array size is too large\n", v->name); + else if (0xffffuL < size * dim->cval) + v->type = make_type(RPC_FC_LGFARRAY, v->type); + else + v->type = make_type(RPC_FC_SMFARRAY, v->type); + } + else + { + sizeless = TRUE; + v->type = make_type(RPC_FC_CARRAY, v->type); + } + + v->type->declarray = TRUE; + v->type->dim = dim->cval; + } + + ptype = &v->type; + has_varconf = FALSE; + if (sizes) LIST_FOR_EACH_ENTRY(dim, sizes, expr_t, entry) + { + if (dim->type != EXPR_VOID) + { + has_varconf = TRUE; + atype = *ptype = duptype(*ptype, 0); + + if (atype->type == RPC_FC_SMFARRAY || atype->type == RPC_FC_LGFARRAY) + error("%s: cannot specify size_is for a fixed sized array\n", v->name); + + if (atype->type != RPC_FC_CARRAY && !is_ptr(atype)) + error("%s: size_is attribute applied to illegal type\n", v->name); + + atype->type = RPC_FC_CARRAY; + atype->size_is = dim; + } + + ptype = &(*ptype)->ref; + if (*ptype == NULL) + error("%s: too many expressions in size_is attribute\n", v->name); + } + + ptype = &v->type; + if (lengs) LIST_FOR_EACH_ENTRY(dim, lengs, expr_t, entry) + { + if (dim->type != EXPR_VOID) + { + has_varconf = TRUE; + atype = *ptype = duptype(*ptype, 0); + + if (atype->type == RPC_FC_SMFARRAY) + atype->type = RPC_FC_SMVARRAY; + else if (atype->type == RPC_FC_LGFARRAY) + atype->type = RPC_FC_LGVARRAY; + else if (atype->type == RPC_FC_CARRAY) + atype->type = RPC_FC_CVARRAY; + else + error("%s: length_is attribute applied to illegal type\n", v->name); + + atype->length_is = dim; + } + + ptype = &(*ptype)->ref; + if (*ptype == NULL) + error("%s: too many expressions in length_is attribute\n", v->name); + } + + if (has_varconf && !last_array(v->type)) + { + ptype = &v->type; + for (ptype = &v->type; is_array(*ptype); ptype = &(*ptype)->ref) + { + *ptype = duptype(*ptype, 0); + (*ptype)->type = RPC_FC_BOGUS_ARRAY; + } + } + + if (is_array(v->type)) + { + const type_t *rt = v->type->ref; + if (is_user_type(rt)) + v->type->type = RPC_FC_BOGUS_ARRAY; + else + switch (rt->type) + { + case RPC_FC_BOGUS_STRUCT: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_ENUM16: + v->type->type = RPC_FC_BOGUS_ARRAY; + break; + /* FC_RP should be above, but widl overuses these, and will break things. */ + case RPC_FC_UP: + case RPC_FC_RP: + if (rt->ref->type == RPC_FC_IP) + v->type->type = RPC_FC_BOGUS_ARRAY; + break; + } + } +} + +static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) +{ + if (!iface) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &iface->entry ); + return list; +} + +static ifref_t *make_ifref(type_t *iface) +{ + ifref_t *l = xmalloc(sizeof(ifref_t)); + l->iface = iface; + l->attrs = NULL; + return l; +} + +static var_list_t *append_var(var_list_t *list, var_t *var) +{ + if (!var) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &var->entry ); + return list; +} + +static var_t *make_var(char *name) +{ + var_t *v = xmalloc(sizeof(var_t)); + v->name = name; + v->type = NULL; + v->args = NULL; + v->attrs = NULL; + v->eval = NULL; + return v; +} + +static pident_list_t *append_pident(pident_list_t *list, pident_t *p) +{ + if (!p) return list; + if (!list) { + list = xmalloc(sizeof(*list)); + list_init(list); + } + list_add_tail(list, &p->entry); + return list; +} + +static pident_t *make_pident(var_t *var) +{ + pident_t *p = xmalloc(sizeof(*p)); + p->var = var; + p->ptr_level = 0; + return p; +} + +static func_list_t *append_func(func_list_t *list, func_t *func) +{ + if (!func) return list; + if (!list) + { + list = xmalloc( sizeof(*list) ); + list_init( list ); + } + list_add_tail( list, &func->entry ); + return list; +} + +static func_t *make_func(var_t *def, var_list_t *args) +{ + func_t *f = xmalloc(sizeof(func_t)); + f->def = def; + f->args = args; + f->ignore = parse_only; + f->idx = -1; + return f; +} + +static type_t *make_class(char *name) +{ + type_t *c = make_type(0, NULL); + c->name = name; + c->kind = TKIND_COCLASS; + return c; +} + +static type_t *make_safearray(type_t *type) +{ + type_t *sa = duptype(find_type("SAFEARRAY", 0), 1); + sa->ref = type; + return make_type(pointer_default, sa); +} + +#define HASHMAX 64 + +static int hash_ident(const char *name) +{ + const char *p = name; + int sum = 0; + /* a simple sum hash is probably good enough */ + while (*p) { + sum += *p; + p++; + } + return sum & (HASHMAX-1); +} + +/***** type repository *****/ + +struct rtype { + const char *name; + type_t *type; + int t; + struct rtype *next; +}; + +struct rtype *type_hash[HASHMAX]; + +static type_t *reg_type(type_t *type, const char *name, int t) +{ + struct rtype *nt; + int hash; + if (!name) { + error_loc("registering named type without name\n"); + return type; + } + hash = hash_ident(name); + nt = xmalloc(sizeof(struct rtype)); + nt->name = name; + nt->type = type; + nt->t = t; + nt->next = type_hash[hash]; + type_hash[hash] = nt; + return type; +} + +static int is_incomplete(const type_t *t) +{ + return !t->defined && (is_struct(t->type) || is_union(t->type)); +} + +static void add_incomplete(type_t *t) +{ + struct typenode *tn = xmalloc(sizeof *tn); + tn->type = t; + list_add_tail(&incomplete_types, &tn->entry); +} + +static void fix_type(type_t *t) +{ + if (t->kind == TKIND_ALIAS && is_incomplete(t)) { + type_t *ot = t->orig; + fix_type(ot); + t->fields = ot->fields; + t->defined = ot->defined; + } +} + +static void fix_incomplete(void) +{ + struct typenode *tn, *next; + + LIST_FOR_EACH_ENTRY_SAFE(tn, next, &incomplete_types, struct typenode, entry) { + fix_type(tn->type); + free(tn); + } +} + +static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *attrs) +{ + type_t *ptr = type; + const pident_t *pident; + int ptrc = 0; + int is_str = is_attr(attrs, ATTR_STRING); + unsigned char ptr_type = get_attrv(attrs, ATTR_POINTERTYPE); + + if (is_str) + { + type_t *t = type; + unsigned char c; + + while (is_ptr(t)) + t = t->ref; + + c = t->type; + if (c != RPC_FC_CHAR && c != RPC_FC_BYTE && c != RPC_FC_WCHAR) + { + pident = LIST_ENTRY( list_head( pidents ), const pident_t, entry ); + error_loc("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays\n", + pident->var->name); + } + } + + /* We must generate names for tagless enum, struct or union. + Typedef-ing a tagless enum, struct or union means we want the typedef + to be included in a library whether it has other attributes or not, + hence the public attribute. */ + if ((type->kind == TKIND_ENUM || type->kind == TKIND_RECORD + || type->kind == TKIND_UNION) && ! type->name && ! parse_only) + { + if (! is_attr(attrs, ATTR_PUBLIC)) + attrs = append_attr( attrs, make_attr(ATTR_PUBLIC) ); + type->name = gen_name(); + } + + LIST_FOR_EACH_ENTRY( pident, pidents, const pident_t, entry ) + { + var_t *name = pident->var; + + if (name->name) { + type_t *cur = ptr; + int cptr = pident->ptr_level; + if (cptr > ptrc) { + while (cptr > ptrc) { + cur = ptr = make_type(pointer_default, cur); + ptrc++; + } + } else { + while (cptr < ptrc) { + cur = cur->ref; + cptr++; + } + } + cur = alias(cur, name->name); + cur->attrs = attrs; + if (ptr_type) + { + if (is_ptr(cur)) + cur->type = ptr_type; + else + error_loc("'%s': pointer attribute applied to non-pointer type\n", + cur->name); + } + else if (is_str && ! is_ptr(cur)) + error_loc("'%s': [string] attribute applied to non-pointer type\n", + cur->name); + + if (is_incomplete(cur)) + add_incomplete(cur); + reg_type(cur, cur->name, 0); + } + } + return type; +} + +static type_t *find_type(const char *name, int t) +{ + struct rtype *cur = type_hash[hash_ident(name)]; + while (cur && (cur->t != t || strcmp(cur->name, name))) + cur = cur->next; + if (!cur) { + error_loc("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 = type_hash[hash_ident(name)]; + while (cur && (cur->t || strcmp(cur->name, name))) + cur = cur->next; + if (cur) return TRUE; + return FALSE; +} + +static type_t *get_type(unsigned char type, char *name, int t) +{ + struct rtype *cur = NULL; + type_t *tp; + if (name) { + cur = type_hash[hash_ident(name)]; + 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(unsigned char type, var_t *name, int t) +{ + char *sname = NULL; + if (name) { + sname = name->name; + free(name); + } + return get_type(type, sname, t); +} + +static int get_struct_type(var_list_t *fields) +{ + int has_pointer = 0; + int has_conformance = 0; + int has_variance = 0; + var_t *field; + + if (get_padding(fields)) + return RPC_FC_BOGUS_STRUCT; + + if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) + { + type_t *t = field->type; + + if (is_user_type(t)) + return RPC_FC_BOGUS_STRUCT; + + if (is_ptr(t)) + { + do + t = t->ref; + while (is_ptr(t)); + + switch (t->type) + { + case RPC_FC_IP: + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_BOGUS_STRUCT: + return RPC_FC_BOGUS_STRUCT; + } + + has_pointer = 1; + continue; + } + + if (field->type->declarray) + { + if (is_string_type(field->attrs, field->type)) + { + if (is_conformant_array(field->type)) + has_conformance = 1; + has_variance = 1; + continue; + } + + if (is_array(field->type->ref)) + return RPC_FC_BOGUS_STRUCT; + + if (is_conformant_array(field->type)) + { + has_conformance = 1; + if (field->type->declarray && list_next(fields, &field->entry)) + error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", + field->name); + } + if (field->type->length_is) + has_variance = 1; + + t = field->type->ref; + } + + switch (t->type) + { + /* + * RPC_FC_BYTE, RPC_FC_STRUCT, etc + * Simple types don't effect the type of struct. + * A struct containing a simple struct is still a simple struct. + * So long as we can block copy the data, we return RPC_FC_STRUCT. + */ + case 0: /* void pointer */ + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_INT3264: + case RPC_FC_UINT3264: + case RPC_FC_HYPER: + case RPC_FC_FLOAT: + case RPC_FC_DOUBLE: + case RPC_FC_STRUCT: + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + break; + + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_FP: + case RPC_FC_OP: + case RPC_FC_CARRAY: + case RPC_FC_CVARRAY: + case RPC_FC_BOGUS_ARRAY: + has_pointer = 1; + break; + + /* + * Propagate member attributes + * a struct should be at least as complex as its member + */ + case RPC_FC_CVSTRUCT: + has_conformance = 1; + has_variance = 1; + has_pointer = 1; + break; + + case RPC_FC_CPSTRUCT: + has_conformance = 1; + if (list_next( fields, &field->entry )) + error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", + field->name); + has_pointer = 1; + break; + + case RPC_FC_CSTRUCT: + has_conformance = 1; + if (list_next( fields, &field->entry )) + error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", + field->name); + break; + + case RPC_FC_PSTRUCT: + has_pointer = 1; + break; + + default: + error_loc("Unknown struct member %s with type (0x%02x)\n", field->name, t->type); + /* fallthru - treat it as complex */ + + /* as soon as we see one of these these members, it's bogus... */ + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + case RPC_FC_BOGUS_STRUCT: + return RPC_FC_BOGUS_STRUCT; + } + } + + if( has_variance ) + { + if ( has_conformance ) + return RPC_FC_CVSTRUCT; + else + return RPC_FC_BOGUS_STRUCT; + } + if( has_conformance && has_pointer ) + return RPC_FC_CPSTRUCT; + if( has_conformance ) + return RPC_FC_CSTRUCT; + if( has_pointer ) + return RPC_FC_PSTRUCT; + return RPC_FC_STRUCT; +} + +/***** constant repository *****/ + +struct rconst { + char *name; + var_t *var; + struct rconst *next; +}; + +struct rconst *const_hash[HASHMAX]; + +static var_t *reg_const(var_t *var) +{ + struct rconst *nc; + int hash; + if (!var->name) { + error_loc("registering constant without name\n"); + return var; + } + hash = hash_ident(var->name); + nc = xmalloc(sizeof(struct rconst)); + nc->name = var->name; + nc->var = var; + nc->next = const_hash[hash]; + const_hash[hash] = nc; + return var; +} + +static var_t *find_const(char *name, int f) +{ + struct rconst *cur = const_hash[hash_ident(name)]; + while (cur && strcmp(cur->name, name)) + cur = cur->next; + if (!cur) { + if (f) error_loc("constant '%s' not found\n", name); + return NULL; + } + return cur->var; +} + +static void write_libid(const char *name, const attr_list_t *attr) +{ + const UUID *uuid = get_attrp(attr, ATTR_UUID); + write_guid(idfile, "LIBID", name, uuid); +} + +static void write_clsid(type_t *cls) +{ + const UUID *uuid = get_attrp(cls->attrs, ATTR_UUID); + write_guid(idfile, "CLSID", cls->name, uuid); +} + +static void write_diid(type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + write_guid(idfile, "DIID", iface->name, uuid); +} + +static void write_iid(type_t *iface) +{ + const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + write_guid(idfile, "IID", iface->name, uuid); +} + +static int compute_method_indexes(type_t *iface) +{ + int idx; + func_t *f; + + if (iface->ref) + idx = compute_method_indexes(iface->ref); + else + idx = 0; + + if (!iface->funcs) + return idx; + + LIST_FOR_EACH_ENTRY( f, iface->funcs, func_t, entry ) + if (! is_callas(f->def->attrs)) + f->idx = idx++; + + return idx; +} + +static char *gen_name(void) +{ + static const char format[] = "__WIDL_%s_generated_name_%08lX"; + static unsigned long n = 0; + static const char *file_id; + static size_t size; + char *name; + + if (! file_id) + { + char *dst = dup_basename(input_name, ".idl"); + file_id = dst; + + for (; *dst; ++dst) + if (! isalnum((unsigned char) *dst)) + *dst = '_'; + + size = sizeof format - 7 + strlen(file_id) + 8; + } + + name = xmalloc(size); + sprintf(name, format, file_id, n++); + return name; +} + +static void process_typedefs(pident_list_t *pidents) +{ + pident_t *pident, *next; + + if (!pidents) return; + LIST_FOR_EACH_ENTRY_SAFE( pident, next, pidents, pident_t, entry ) + { + var_t *var = pident->var; + type_t *type = find_type(var->name, 0); + + if (! parse_only && do_header) + write_typedef(type); + if (in_typelib && type->attrs) + add_typelib_entry(type); + + free(pident); + free(var); + } +} + +static void check_arg(var_t *arg) +{ + type_t *t = arg->type; + + if (t->type == 0 && ! is_var_ptr(arg)) + error_loc("argument '%s' has void type\n", arg->name); +} + +static void check_all_user_types(ifref_list_t *ifrefs) +{ + const ifref_t *ifref; + const func_t *f; + + if (ifrefs) LIST_FOR_EACH_ENTRY(ifref, ifrefs, const ifref_t, entry) + { + const func_list_t *fs = ifref->iface->funcs; + if (fs) LIST_FOR_EACH_ENTRY(f, fs, const func_t, entry) + check_for_user_types_and_context_handles(f->args); + } +} + +int is_valid_uuid(const char *s) +{ + int i; + + for (i = 0; i < 36; ++i) + if (i == 8 || i == 13 || i == 18 || i == 23) + { + if (s[i] != '-') + return FALSE; + } + else + if (!isxdigit(s[i])) + return FALSE; + + return s[i] == '\0'; +} diff --git a/reactos/tools/widl_20080105/parser.yy.c b/reactos/tools/widl_20080105/parser.yy.c new file mode 100644 index 00000000000..fbe3c5d00ca --- /dev/null +++ b/reactos/tools/widl_20080105/parser.yy.c @@ -0,0 +1,2113 @@ +#define yy_create_buffer parser__create_buffer +#define yy_delete_buffer parser__delete_buffer +#define yy_scan_buffer parser__scan_buffer +#define yy_scan_string parser__scan_string +#define yy_scan_bytes parser__scan_bytes +#define yy_flex_debug parser__flex_debug +#define yy_init_buffer parser__init_buffer +#define yy_flush_buffer parser__flush_buffer +#define yy_load_buffer_state parser__load_buffer_state +#define yy_switch_to_buffer parser__switch_to_buffer +#define yyin parser_in +#define yyleng parser_leng +#define yylex parser_lex +#define yyout parser_out +#define yyrestart parser_restart +#define yytext parser_text +#define yywrap parser_wrap + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.85 95/04/24 10:48:47 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 23 +#define YY_END_OF_BUFFER 24 +static yyconst short int yy_accept[113] = + { 0, + 0, 0, 0, 0, 0, 0, 2, 2, 24, 22, + 19, 18, 3, 14, 14, 22, 22, 17, 17, 9, + 19, 1, 8, 23, 4, 8, 14, 14, 11, 11, + 10, 2, 0, 14, 0, 20, 21, 17, 17, 0, + 1, 1, 7, 6, 5, 14, 0, 11, 11, 2, + 15, 13, 17, 14, 0, 11, 0, 17, 14, 0, + 11, 0, 15, 17, 14, 0, 11, 17, 14, 0, + 11, 17, 14, 0, 11, 17, 14, 0, 11, 17, + 0, 14, 0, 16, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 12, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 5, 1, 1, 1, 1, 6, + 1, 1, 7, 1, 8, 9, 1, 10, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 1, 1, 12, + 1, 13, 1, 1, 14, 15, 15, 15, 16, 17, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 19, 20, 18, 18, 18, 18, 18, 21, 18, + 22, 23, 24, 1, 18, 1, 15, 15, 15, 15, + + 25, 15, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 26, + 18, 18, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[27] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, + 3, 1, 1, 3, 3, 3, 3, 4, 4, 4, + 4, 1, 1, 1, 3, 5 + } ; + +static yyconst short int yy_base[151] = + { 0, + 0, 25, 25, 28, 42, 31, 265, 264, 266, 269, + 269, 269, 269, 60, 28, 253, 251, 0, 249, 269, + 38, 260, 269, 269, 269, 31, 39, 62, 79, 0, + 269, 0, 31, 35, 0, 269, 269, 0, 244, 72, + 258, 257, 269, 269, 269, 65, 0, 96, 0, 0, + 113, 0, 242, 68, 0, 129, 149, 240, 70, 0, + 151, 72, 74, 229, 81, 0, 168, 224, 91, 0, + 185, 212, 98, 0, 202, 204, 117, 216, 207, 124, + 0, 108, 129, 269, 0, 0, 0, 206, 0, 0, + 0, 0, 201, 0, 0, 0, 0, 200, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 269, 269, 228, 233, 236, 241, 244, 247, 252, 204, + 195, 194, 189, 188, 187, 178, 177, 172, 171, 170, + 161, 160, 155, 150, 149, 148, 139, 138, 134, 133, + 131, 130, 129, 117, 100, 84, 61, 52, 44, 31 + } ; + +static yyconst short int yy_def[151] = + { 0, + 112, 1, 113, 113, 1, 5, 114, 114, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 115, 115, 112, + 112, 112, 112, 112, 112, 116, 117, 117, 112, 118, + 112, 119, 112, 112, 120, 112, 112, 115, 115, 112, + 112, 112, 112, 112, 112, 121, 121, 112, 118, 119, + 112, 120, 115, 122, 122, 112, 112, 115, 123, 123, + 112, 112, 51, 115, 124, 124, 112, 115, 125, 125, + 112, 115, 126, 126, 112, 115, 112, 112, 118, 115, + 127, 112, 112, 112, 128, 129, 130, 112, 131, 132, + 133, 134, 112, 135, 136, 137, 138, 112, 139, 140, + + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 112, 0, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112 + } ; + +static yyconst short int yy_nxt[296] = + { 0, + 10, 11, 12, 13, 10, 10, 10, 10, 10, 14, + 15, 16, 17, 18, 18, 18, 18, 18, 18, 19, + 18, 20, 10, 10, 18, 18, 21, 24, 25, 22, + 24, 25, 21, 111, 44, 22, 33, 34, 34, 40, + 51, 51, 41, 33, 34, 34, 110, 26, 46, 46, + 26, 27, 28, 45, 109, 29, 29, 29, 29, 30, + 30, 30, 30, 108, 35, 31, 29, 30, 33, 34, + 34, 46, 46, 40, 54, 54, 41, 59, 59, 65, + 65, 63, 63, 63, 63, 35, 107, 112, 48, 48, + 69, 69, 48, 48, 48, 48, 49, 49, 49, 49, + + 73, 73, 106, 48, 49, 56, 56, 77, 77, 56, + 56, 56, 56, 49, 49, 49, 49, 82, 82, 105, + 56, 49, 51, 51, 81, 83, 82, 82, 57, 84, + 83, 104, 103, 102, 84, 101, 100, 57, 61, 61, + 98, 97, 61, 61, 61, 61, 49, 49, 49, 49, + 96, 95, 93, 61, 49, 62, 62, 92, 63, 63, + 67, 67, 91, 90, 67, 67, 67, 67, 49, 49, + 49, 49, 88, 87, 86, 67, 49, 71, 71, 85, + 78, 71, 71, 71, 71, 49, 49, 49, 49, 74, + 70, 66, 71, 49, 75, 75, 60, 55, 75, 75, + + 75, 75, 49, 49, 49, 49, 52, 99, 94, 75, + 49, 79, 79, 89, 81, 79, 79, 79, 79, 49, + 49, 49, 49, 81, 80, 76, 79, 49, 23, 23, + 23, 23, 23, 32, 32, 32, 32, 32, 38, 38, + 38, 43, 72, 43, 43, 43, 47, 68, 47, 49, + 49, 49, 50, 64, 50, 50, 50, 58, 42, 42, + 53, 42, 39, 37, 36, 112, 24, 24, 9, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112 + + } ; + +static yyconst short int yy_chk[296] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 3, 3, 2, + 4, 4, 6, 150, 26, 6, 15, 15, 15, 21, + 33, 33, 21, 34, 34, 34, 149, 3, 27, 27, + 4, 5, 5, 26, 148, 5, 5, 5, 5, 5, + 5, 5, 5, 147, 27, 5, 5, 5, 14, 14, + 14, 28, 28, 40, 46, 46, 40, 54, 54, 59, + 59, 62, 62, 63, 63, 14, 146, 28, 29, 29, + 65, 65, 29, 29, 29, 29, 29, 29, 29, 29, + + 69, 69, 145, 29, 29, 48, 48, 73, 73, 48, + 48, 48, 48, 48, 48, 48, 48, 82, 82, 144, + 48, 48, 51, 51, 77, 80, 77, 77, 51, 80, + 83, 143, 142, 141, 83, 140, 139, 51, 56, 56, + 138, 137, 56, 56, 56, 56, 56, 56, 56, 56, + 136, 135, 134, 56, 56, 57, 57, 133, 57, 57, + 61, 61, 132, 131, 61, 61, 61, 61, 61, 61, + 61, 61, 130, 129, 128, 61, 61, 67, 67, 127, + 126, 67, 67, 67, 67, 67, 67, 67, 67, 125, + 124, 123, 67, 67, 71, 71, 122, 121, 71, 71, + + 71, 71, 71, 71, 71, 71, 120, 98, 93, 71, + 71, 75, 75, 88, 79, 75, 75, 75, 75, 75, + 75, 75, 75, 78, 76, 72, 75, 75, 113, 113, + 113, 113, 113, 114, 114, 114, 114, 114, 115, 115, + 115, 116, 68, 116, 116, 116, 117, 64, 117, 118, + 118, 118, 119, 58, 119, 119, 119, 53, 42, 41, + 39, 22, 19, 17, 16, 9, 8, 7, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112 + + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "parser.l" +#define INITIAL 0 +/* -*-C-*- + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define YY_STACK_USED 1 +#define YY_NO_UNPUT 1 +#define YY_NO_TOP_STATE 1 +#define YY_NEVER_INTERACTIVE 1 +#define QUOTE 1 + +#define ATTR 2 + +#define PP_LINE 3 + +#line 39 "parser.l" + +#include "config.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "wine/wpp.h" + +#include "parser.tab.h" + +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); +static int attr_token(const char *kw); + +#define MAX_IMPORT_DEPTH 10 +struct { + YY_BUFFER_STATE state; + char *input_name; + int line_number; + char *temp_name; +} import_stack[MAX_IMPORT_DEPTH]; +int import_stack_ptr = 0; + +static void pop_import(void); + +UUID *parse_uuid(const char *u) +{ + UUID* uuid = xmalloc(sizeof(UUID)); + char b[3]; + /* it would be nice to use UuidFromStringA */ + uuid->Data1 = strtoul(u, NULL, 16); + uuid->Data2 = strtoul(u+9, NULL, 16); + uuid->Data3 = strtoul(u+14, NULL, 16); + b[2] = 0; + memcpy(b, u+19, 2); uuid->Data4[0] = strtoul(b, NULL, 16); + memcpy(b, u+21, 2); uuid->Data4[1] = strtoul(b, NULL, 16); + memcpy(b, u+24, 2); uuid->Data4[2] = strtoul(b, NULL, 16); + memcpy(b, u+26, 2); uuid->Data4[3] = strtoul(b, NULL, 16); + memcpy(b, u+28, 2); uuid->Data4[4] = strtoul(b, NULL, 16); + memcpy(b, u+30, 2); uuid->Data4[5] = strtoul(b, NULL, 16); + memcpy(b, u+32, 2); uuid->Data4[6] = strtoul(b, NULL, 16); + memcpy(b, u+34, 2); uuid->Data4[7] = strtoul(b, NULL, 16); + return uuid; +} + +/* + ************************************************************************** + * The flexer starts here + ************************************************************************** + */ +#line 584 "lex.parser_.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 108 "parser.l" + +#line 736 "lex.parser_.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 113 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 269 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 109 "parser.l" +yy_push_state(PP_LINE); + YY_BREAK +case 2: +YY_RULE_SETUP +#line 110 "parser.l" +{ + int lineno; + char *cptr, *fname; + yy_pop_state(); + lineno = (int)strtol(yytext, &cptr, 10); + if(!lineno) + error_loc("Malformed '#...' line-directive; invalid linenumber\n"); + fname = strchr(cptr, '"'); + if(!fname) + error_loc("Malformed '#...' line-directive; missing filename\n"); + fname++; + cptr = strchr(fname, '"'); + if(!cptr) + error_loc("Malformed '#...' line-directive; missing terminating \"\n"); + *cptr = '\0'; + line_number = lineno - 1; /* We didn't read the newline */ + free( input_name ); + input_name = xstrdup(fname); + } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 129 "parser.l" +yy_push_state(QUOTE); cbufidx = 0; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 130 "parser.l" +{ + yy_pop_state(); + parser_lval.str = get_buffered_cstring(); + return aSTRING; + } + YY_BREAK +case 5: +#line 136 "parser.l" +case 6: +YY_RULE_SETUP +#line 136 "parser.l" +addcchar(yytext[1]); + YY_BREAK +case 7: +YY_RULE_SETUP +#line 137 "parser.l" +addcchar('\\'); addcchar(yytext[1]); + YY_BREAK +case 8: +YY_RULE_SETUP +#line 138 "parser.l" +addcchar(yytext[0]); + YY_BREAK +case 9: +YY_RULE_SETUP +#line 139 "parser.l" +yy_push_state(ATTR); return '['; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 140 "parser.l" +yy_pop_state(); return ']'; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 141 "parser.l" +return attr_token(yytext); + YY_BREAK +case 12: +YY_RULE_SETUP +#line 142 "parser.l" +{ + parser_lval.uuid = parse_uuid(yytext); + return aUUID; + } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 146 "parser.l" +{ + parser_lval.num = strtoul(yytext, NULL, 0); + return aHEXNUM; + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 150 "parser.l" +{ + parser_lval.num = strtoul(yytext, NULL, 0); + return aNUM; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 154 "parser.l" +{ + parser_lval.dbl = strtod(yytext, NULL); + return aDOUBLE; + } + YY_BREAK +case 16: +*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ +yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 158 "parser.l" +return tSAFEARRAY; + YY_BREAK +case 17: +YY_RULE_SETUP +#line 159 "parser.l" +return kw_token(yytext); + YY_BREAK +case 18: +YY_RULE_SETUP +#line 160 "parser.l" +line_number++; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 161 "parser.l" + + YY_BREAK +case 20: +YY_RULE_SETUP +#line 162 "parser.l" +return SHL; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 163 "parser.l" +return SHR; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 164 "parser.l" +return yytext[0]; + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(QUOTE): +case YY_STATE_EOF(ATTR): +case YY_STATE_EOF(PP_LINE): +#line 165 "parser.l" +{ + if (import_stack_ptr) { + pop_import(); + return aEOF; + } + else yyterminate(); + } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 172 "parser.l" +ECHO; + YY_BREAK +#line 982 "lex.parser_.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 113 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 113 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 112); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 172 "parser.l" + + +#ifndef parser_wrap +int parser_wrap(void) +{ + return 1; +} +#endif + +struct keyword { + const char *kw; + int token; +}; + +static const struct keyword keywords[] = { + {"FALSE", tFALSE}, + {"TRUE", tTRUE}, + {"__cdecl", tCDECL}, + {"__int64", tINT64}, + {"__stdcall", tSTDCALL}, + {"_stdcall", tSTDCALL}, + {"boolean", tBOOLEAN}, + {"byte", tBYTE}, + {"callback", tCALLBACK}, + {"case", tCASE}, + {"char", tCHAR}, + {"coclass", tCOCLASS}, + {"code", tCODE}, + {"comm_status", tCOMMSTATUS}, + {"const", tCONST}, + {"cpp_quote", tCPPQUOTE}, + {"default", tDEFAULT}, + {"dispinterface", tDISPINTERFACE}, + {"double", tDOUBLE}, + {"enum", tENUM}, + {"error_status_t", tERRORSTATUST}, + {"extern", tEXTERN}, + {"float", tFLOAT}, + {"handle_t", tHANDLET}, + {"hyper", tHYPER}, + {"import", tIMPORT}, + {"importlib", tIMPORTLIB}, + {"in_line", tINLINE}, + {"int", tINT}, + {"interface", tINTERFACE}, + {"library", tLIBRARY}, + {"long", tLONG}, + {"methods", tMETHODS}, + {"module", tMODULE}, + {"properties", tPROPERTIES}, + {"short", tSHORT}, + {"signed", tSIGNED}, + {"sizeof", tSIZEOF}, + {"small", tSMALL}, + {"struct", tSTRUCT}, + {"switch", tSWITCH}, + {"typedef", tTYPEDEF}, + {"union", tUNION}, + {"unsigned", tUNSIGNED}, + {"void", tVOID}, + {"wchar_t", tWCHAR}, +}; +#define NKEYWORDS (sizeof(keywords)/sizeof(keywords[0])) + +/* keywords only recognized in attribute lists */ +static const struct keyword attr_keywords[] = +{ + {"aggregatable", tAGGREGATABLE}, + {"allocate", tALLOCATE}, + {"appobject", tAPPOBJECT}, + {"async", tASYNC}, + {"async_uuid", tASYNCUUID}, + {"auto_handle", tAUTOHANDLE}, + {"bindable", tBINDABLE}, + {"broadcast", tBROADCAST}, + {"byte_count", tBYTECOUNT}, + {"call_as", tCALLAS}, + {"context_handle", tCONTEXTHANDLE}, + {"context_handle_noserialize", tCONTEXTHANDLENOSERIALIZE}, + {"context_handle_serialize", tCONTEXTHANDLENOSERIALIZE}, + {"control", tCONTROL}, + {"defaultcollelem", tDEFAULTCOLLELEM}, + {"defaultvalue", tDEFAULTVALUE}, + {"defaultvtable", tDEFAULTVTABLE}, + {"displaybind", tDISPLAYBIND}, + {"dllname", tDLLNAME}, + {"dual", tDUAL}, + {"endpoint", tENDPOINT}, + {"entry", tENTRY}, + {"explicit_handle", tEXPLICITHANDLE}, + {"handle", tHANDLE}, + {"helpcontext", tHELPCONTEXT}, + {"helpfile", tHELPFILE}, + {"helpstring", tHELPSTRING}, + {"helpstringcontext", tHELPSTRINGCONTEXT}, + {"helpstringdll", tHELPSTRINGDLL}, + {"hidden", tHIDDEN}, + {"id", tID}, + {"idempotent", tIDEMPOTENT}, + {"iid_is", tIIDIS}, + {"immediatebind", tIMMEDIATEBIND}, + {"implicit_handle", tIMPLICITHANDLE}, + {"in", tIN}, + {"input_sync", tINPUTSYNC}, + {"lcid", tLCID}, + {"length_is", tLENGTHIS}, + {"local", tLOCAL}, + {"nonbrowsable", tNONBROWSABLE}, + {"noncreatable", tNONCREATABLE}, + {"nonextensible", tNONEXTENSIBLE}, + {"object", tOBJECT}, + {"odl", tODL}, + {"oleautomation", tOLEAUTOMATION}, + {"optional", tOPTIONAL}, + {"out", tOUT}, + {"pointer_default", tPOINTERDEFAULT}, + {"propget", tPROPGET}, + {"propput", tPROPPUT}, + {"propputref", tPROPPUTREF}, + {"ptr", tPTR}, + {"public", tPUBLIC}, + {"range", tRANGE}, + {"readonly", tREADONLY}, + {"ref", tREF}, + {"requestedit", tREQUESTEDIT}, + {"restricted", tRESTRICTED}, + {"retval", tRETVAL}, + {"single", tSINGLE}, + {"size_is", tSIZEIS}, + {"source", tSOURCE}, + {"string", tSTRING}, + {"switch_is", tSWITCHIS}, + {"switch_type", tSWITCHTYPE}, + {"transmit_as", tTRANSMITAS}, + {"unique", tUNIQUE}, + {"uuid", tUUID}, + {"v1_enum", tV1ENUM}, + {"vararg", tVARARG}, + {"version", tVERSION}, + {"wire_marshal", tWIREMARSHAL}, +}; + + +#define KWP(p) ((const struct keyword *)(p)) + +static int kw_cmp_func(const void *s1, const void *s2) +{ + return strcmp(KWP(s1)->kw, KWP(s2)->kw); +} + +static int kw_token(const char *kw) +{ + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, keywords, NKEYWORDS, sizeof(keywords[0]), kw_cmp_func); + if (kwp) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } + parser_lval.str = xstrdup(kw); + return is_type(kw) ? aKNOWNTYPE : aIDENTIFIER; +} + +static int attr_token(const char *kw) +{ + struct keyword key, *kwp; + key.kw = kw; + kwp = bsearch(&key, attr_keywords, sizeof(attr_keywords)/sizeof(attr_keywords[0]), + sizeof(attr_keywords[0]), kw_cmp_func); + if (kwp) { + parser_lval.str = xstrdup(kwp->kw); + return kwp->token; + } + return kw_token(kw); +} + +static void addcchar(char c) +{ + if(cbufidx >= cbufalloc) + { + cbufalloc += 1024; + cbuffer = xrealloc(cbuffer, cbufalloc * sizeof(cbuffer[0])); + if(cbufalloc > 65536) + parser_warning("Reallocating string buffer larger than 64kB\n"); + } + 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; + free( input_name ); + input_name = import_stack[ptr].input_name; + line_number = import_stack[ptr].line_number; + import_stack_ptr--; +} + +struct imports { + char *name; + struct imports *next; +} *first_import; + +int do_import(char *fname) +{ + FILE *f; + char *hname, *path, *p; + struct imports *import; + int ptr = import_stack_ptr; + int ret; + + if (!parse_only && do_header) { + hname = dup_basename(fname, ".idl"); + p = hname + strlen(hname) - 2; + if (p <= hname || strcmp( p, ".h" )) 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 0; /* already imported */ + + import = xmalloc(sizeof(struct imports)); + import->name = xstrdup(fname); + import->next = first_import; + first_import = import; + + if (!(path = wpp_find_include( fname, input_name ))) + error_loc("Unable to open include file %s\n", fname); + + import_stack[ptr].temp_name = temp_name; + import_stack[ptr].input_name = input_name; + import_stack[ptr].line_number = line_number; + import_stack_ptr++; + input_name = path; + line_number = 1; + + ret = wpp_parse_temp( path, NULL, &temp_name ); + if (ret) exit(1); + + if((f = fopen(temp_name, "r")) == NULL) + error_loc("Unable to open %s\n", temp_name); + + import_stack[ptr].state = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); + return 1; +} + +void abort_import(void) +{ + int ptr; + + for (ptr=0; ptr +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_PROCESS_H +#include +#endif + +/* We need to provide a type for gcc_uint64_t. */ +#ifdef __GNUC__ +__extension__ typedef unsigned long long gcc_uint64_t; +#else +typedef unsigned long gcc_uint64_t; +#endif + +#ifndef TMP_MAX +#define TMP_MAX 16384 +#endif + +/* + +@deftypefn Replacement int mkstemps (char *@var{template}, int @var{suffix_len}) + +Generate a unique temporary file name from @var{template}. +@var{template} has the form: + +@example + @var{path}/ccXXXXXX@var{suffix} +@end example + +@var{suffix_len} tells us how long @var{suffix} is (it can be zero +length). The last six characters of @var{template} before @var{suffix} +must be @samp{XXXXXX}; they are replaced with a string that makes the +filename unique. Returns a file descriptor open on the file for +reading and writing. + +@end deftypefn + +*/ + +int +mkstemps ( + char *template, + int suffix_len) +{ + static const char letters[] + = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + static gcc_uint64_t value; +#ifdef HAVE_GETTIMEOFDAY + struct timeval tv; +#endif + char *XXXXXX; + size_t len; + int count; + + len = strlen (template); + + if ((int) len < 6 + suffix_len + || strncmp (&template[len - 6 - suffix_len], "XXXXXX", 6)) + { + return -1; + } + + XXXXXX = &template[len - 6 - suffix_len]; + +#ifdef HAVE_GETTIMEOFDAY + /* Get some more or less random data. */ + gettimeofday (&tv, NULL); + value += ((gcc_uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); +#else + value += getpid (); +#endif + + for (count = 0; count < TMP_MAX; ++count) + { + gcc_uint64_t v = value; + int fd; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + +#ifdef VMS + fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600, "fop=tmd"); +#else + fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600); +#endif + if (fd >= 0) + /* The file does not exist. */ + return fd; + + /* This is a random value. It is only necessary that the next + TMP_MAX values generated by adding 7777 to VALUE are different + with (module 2^32). */ + value += 7777; + } + + /* We return the null string if we can't find a unique file name. */ + template[0] = '\0'; + return -1; +} diff --git a/reactos/tools/widl_20080105/proxy.c b/reactos/tools/widl_20080105/proxy.c new file mode 100644 index 00000000000..731629f732c --- /dev/null +++ b/reactos/tools/widl_20080105/proxy.c @@ -0,0 +1,709 @@ +/* + * IDL Compiler + * + * Copyright 2002 Ove Kaaven + * Copyright 2004 Mike McCormack + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "typegen.h" + +#define END_OF_LIST(list) \ + do { \ + if (list) { \ + while (NEXT_LINK(list)) \ + list = NEXT_LINK(list); \ + } \ + } while(0) + +static FILE* proxy; +static int indent = 0; + +/* FIXME: support generation of stubless proxies */ + +static void print_proxy( const char *format, ... ) +{ + va_list va; + va_start( va, format ); + print( proxy, indent, format, va ); + va_end( va ); +} + +static void write_stubdescproto(void) +{ + print_proxy( "static const MIDL_STUB_DESC Object_StubDesc;\n"); + print_proxy( "\n"); +} + +static void write_stubdesc(int expr_eval_routines) +{ + print_proxy( "static const MIDL_STUB_DESC Object_StubDesc =\n{\n"); + indent++; + print_proxy( "0,\n"); + print_proxy( "NdrOleAllocate,\n"); + print_proxy( "NdrOleFree,\n"); + print_proxy( "{0}, 0, 0, %s, 0,\n", expr_eval_routines ? "ExprEvalRoutines" : "0"); + print_proxy( "__MIDL_TypeFormatString.Format,\n"); + print_proxy( "1, /* -error bounds_check flag */\n"); + print_proxy( "0x10001, /* Ndr library version */\n"); + print_proxy( "0,\n"); + print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_proxy( "0,\n"); + print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); + print_proxy( "0, /* notify & notify_flag routine table */\n"); + print_proxy( "1, /* Flags */\n"); + print_proxy( "0, /* Reserved3 */\n"); + print_proxy( "0, /* Reserved4 */\n"); + print_proxy( "0 /* Reserved5 */\n"); + indent--; + print_proxy( "};\n"); + print_proxy( "\n"); +} + +static void init_proxy(ifref_list_t *ifaces) +{ + if (proxy) return; + if(!(proxy = fopen(proxy_name, "w"))) + error("Could not open %s for output\n", proxy_name); + print_proxy( "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); + print_proxy( "\n"); + print_proxy( "#ifndef __REDQ_RPCPROXY_H_VERSION__\n"); + print_proxy( "#define __REQUIRED_RPCPROXY_H_VERSION__ 440\n"); + print_proxy( "#endif /* __REDQ_RPCPROXY_H_VERSION__ */\n"); + print_proxy( "\n"); + print_proxy( "#define __midl_proxy\n"); + print_proxy( "#include \"objbase.h\"\n"); + print_proxy( "#include \"rpcproxy.h\"\n"); + print_proxy( "#ifndef __RPCPROXY_H_VERSION__\n"); + print_proxy( "#error This code needs a newer version of rpcproxy.h\n"); + print_proxy( "#endif /* __RPCPROXY_H_VERSION__ */\n"); + print_proxy( "\n"); + print_proxy( "#include \"%s\"\n", header_name); + print_proxy( "\n"); + write_formatstringsdecl(proxy, indent, ifaces, need_proxy); + write_stubdescproto(); +} + +static void clear_output_vars( const var_list_t *args ) +{ + const var_t *arg; + + if (!args) return; + LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) + { + if (is_attr(arg->attrs, ATTR_OUT) && !is_attr(arg->attrs, ATTR_IN)) { + print_proxy( "if(%s)\n", arg->name ); + indent++; + print_proxy( "MIDL_memset( %s, 0, sizeof( *%s ));\n", arg->name, arg->name ); + indent--; + } + } +} + +int is_var_ptr(const var_t *v) +{ + return is_ptr(v->type); +} + +int cant_be_null(const var_t *v) +{ + /* Search backwards for the most recent pointer attribute. */ + const attr_list_t *attrs = v->attrs; + const type_t *type = v->type; + + if (! attrs && type) + { + attrs = type->attrs; + type = type->ref; + } + + while (attrs) + { + int t = get_attrv(attrs, ATTR_POINTERTYPE); + + if (t == RPC_FC_FP || t == RPC_FC_OP || t == RPC_FC_UP) + return 0; + + if (t == RPC_FC_RP) + return 1; + + if (type) + { + attrs = type->attrs; + type = type->ref; + } + else + attrs = NULL; + } + + return 1; /* Default is RPC_FC_RP. */ +} + +static void proxy_check_pointers( const var_list_t *args ) +{ + const var_t *arg; + + if (!args) return; + LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) + { + if (is_var_ptr(arg) && cant_be_null(arg)) { + print_proxy( "if(!%s)\n", arg->name ); + indent++; + print_proxy( "RpcRaiseException(RPC_X_NULL_REF_POINTER);\n"); + indent--; + } + } +} + +static void free_variable( const var_t *arg ) +{ + unsigned int type_offset = arg->type->typestring_offset; + expr_t *iid; + type_t *type = arg->type; + expr_t *size = get_size_is_expr(type, arg->name); + + if (size) + { + print_proxy( "_StubMsg.MaxCount = " ); + write_expr(proxy, size, 0); + fprintf(proxy, ";\n\n"); + print_proxy( "NdrClearOutParameters( &_StubMsg, "); + fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset ); + fprintf(proxy, "(void*)%s );\n", arg->name ); + return; + } + + switch( type->type ) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_ENUM16: + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM32: + case RPC_FC_STRUCT: + break; + + case RPC_FC_FP: + case RPC_FC_IP: + iid = get_attrp( arg->attrs, ATTR_IIDIS ); + if( iid ) + { + print_proxy( "_StubMsg.MaxCount = (unsigned long) " ); + write_expr(proxy, iid, 1); + print_proxy( ";\n\n" ); + } + print_proxy( "NdrClearOutParameters( &_StubMsg, "); + fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset ); + fprintf(proxy, "(void*)%s );\n", arg->name ); + break; + + default: + print_proxy("/* FIXME: %s code for %s type %d missing */\n", __FUNCTION__, arg->name, type->type ); + } +} + +static void proxy_free_variables( var_list_t *args ) +{ + const var_t *arg; + + if (!args) return; + LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) + if (is_attr(arg->attrs, ATTR_OUT)) + { + free_variable( arg ); + fprintf(proxy, "\n"); + } +} + +static void gen_proxy(type_t *iface, const func_t *cur, int idx, + unsigned int proc_offset) +{ + var_t *def = cur->def; + int has_ret = !is_void(def->type); + + indent = 0; + write_type_decl_left(proxy, def->type); + print_proxy( " STDMETHODCALLTYPE %s_", iface->name); + write_name(proxy, def); + print_proxy( "_Proxy(\n"); + write_args(proxy, cur->args, iface->name, 1, TRUE); + print_proxy( ")\n"); + print_proxy( "{\n"); + indent ++; + /* local variables */ + if (has_ret) { + print_proxy( "" ); + write_type_decl_left(proxy, def->type); + print_proxy( " _RetVal;\n"); + } + print_proxy( "RPC_MESSAGE _RpcMessage;\n" ); + print_proxy( "MIDL_STUB_MESSAGE _StubMsg;\n" ); + if (has_ret) { + if (decl_indirect(def->type)) + print_proxy("void *_p_%s = &%s;\n", + "_RetVal", "_RetVal"); + } + print_proxy( "\n"); + + /* FIXME: trace */ + clear_output_vars( cur->args ); + + print_proxy( "RpcTryExcept\n" ); + print_proxy( "{\n" ); + indent++; + print_proxy( "NdrProxyInitialize(This, &_RpcMessage, &_StubMsg, &Object_StubDesc, %d);\n", idx); + proxy_check_pointers( cur->args ); + + print_proxy( "RpcTryFinally\n" ); + print_proxy( "{\n" ); + indent++; + + write_remoting_arguments(proxy, indent, cur, PASS_IN, PHASE_BUFFERSIZE); + + print_proxy( "NdrProxyGetBuffer(This, &_StubMsg);\n" ); + + write_remoting_arguments(proxy, indent, cur, PASS_IN, PHASE_MARSHAL); + + print_proxy( "NdrProxySendReceive(This, &_StubMsg);\n" ); + fprintf(proxy, "\n"); + print_proxy( "_StubMsg.BufferStart = _RpcMessage.Buffer;\n" ); + print_proxy( "_StubMsg.BufferEnd = _StubMsg.BufferStart + _RpcMessage.BufferLength;\n\n" ); + + print_proxy("if ((_RpcMessage.DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n"); + indent++; + print_proxy("NdrConvert( &_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset ); + indent--; + fprintf(proxy, "\n"); + + write_remoting_arguments(proxy, indent, cur, PASS_OUT, PHASE_UNMARSHAL); + + if (has_ret) + { + if (decl_indirect(def->type)) + print_proxy("MIDL_memset(&%s, 0, sizeof(%s));\n", "_RetVal", "_RetVal"); + else if (is_ptr(def->type) || is_array(def->type)) + print_proxy("%s = 0;\n", "_RetVal"); + write_remoting_arguments(proxy, indent, cur, PASS_RETURN, PHASE_UNMARSHAL); + } + + indent--; + print_proxy( "}\n"); + print_proxy( "RpcFinally\n" ); + print_proxy( "{\n" ); + indent++; + print_proxy( "NdrProxyFreeBuffer(This, &_StubMsg);\n" ); + indent--; + print_proxy( "}\n"); + print_proxy( "RpcEndFinally\n" ); + indent--; + print_proxy( "}\n" ); + print_proxy( "RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)\n" ); + print_proxy( "{\n" ); + if (has_ret) { + indent++; + proxy_free_variables( cur->args ); + print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" ); + indent--; + } + print_proxy( "}\n" ); + print_proxy( "RpcEndExcept\n" ); + + if (has_ret) { + print_proxy( "return _RetVal;\n" ); + } + indent--; + print_proxy( "}\n"); + print_proxy( "\n"); +} + +static void gen_stub(type_t *iface, const func_t *cur, const char *cas, + unsigned int proc_offset) +{ + var_t *def = cur->def; + const var_t *arg; + int has_ret = !is_void(def->type); + + indent = 0; + print_proxy( "void __RPC_STUB %s_", iface->name); + write_name(proxy, def); + print_proxy( "_Stub(\n"); + indent++; + print_proxy( "IRpcStubBuffer* This,\n"); + print_proxy( "IRpcChannelBuffer *_pRpcChannelBuffer,\n"); + print_proxy( "PRPC_MESSAGE _pRpcMessage,\n"); + print_proxy( "DWORD* _pdwStubPhase)\n"); + indent--; + print_proxy( "{\n"); + indent++; + print_proxy("%s * _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name); + print_proxy("MIDL_STUB_MESSAGE _StubMsg;\n"); + declare_stub_args( proxy, indent, cur ); + fprintf(proxy, "\n"); + + /* FIXME: trace */ + + print_proxy("NdrStubInitialize(_pRpcMessage, &_StubMsg, &Object_StubDesc, _pRpcChannelBuffer);\n"); + fprintf(proxy, "\n"); + + write_parameters_init(proxy, indent, cur); + + print_proxy("RpcTryFinally\n"); + print_proxy("{\n"); + indent++; + print_proxy("if ((_pRpcMessage->DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n"); + indent++; + print_proxy("NdrConvert( &_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset ); + indent--; + fprintf(proxy, "\n"); + + write_remoting_arguments(proxy, indent, cur, PASS_IN, PHASE_UNMARSHAL); + fprintf(proxy, "\n"); + + assign_stub_out_args( proxy, indent, cur ); + + print_proxy("*_pdwStubPhase = STUB_CALL_SERVER;\n"); + fprintf(proxy, "\n"); + print_proxy(""); + if (has_ret) fprintf(proxy, "_RetVal = "); + if (cas) fprintf(proxy, "%s_%s_Stub", iface->name, cas); + else + { + fprintf(proxy, "_This->lpVtbl->"); + write_name(proxy, def); + } + fprintf(proxy, "(_This"); + + if (cur->args) + { + LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) + { + fprintf(proxy, ", "); + if (arg->type->declarray) + fprintf(proxy, "*"); + write_name(proxy, arg); + } + } + fprintf(proxy, ");\n"); + fprintf(proxy, "\n"); + print_proxy("*_pdwStubPhase = STUB_MARSHAL;\n"); + fprintf(proxy, "\n"); + + write_remoting_arguments(proxy, indent, cur, PASS_OUT, PHASE_BUFFERSIZE); + + print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);\n"); + + write_remoting_arguments(proxy, indent, cur, PASS_OUT, PHASE_MARSHAL); + fprintf(proxy, "\n"); + + if (has_ret) + print_phase_basetype(proxy, indent, PHASE_MARSHAL, PASS_RETURN, def, "_RetVal"); + + indent--; + print_proxy("}\n"); + print_proxy("RpcFinally\n"); + print_proxy("{\n"); + + write_remoting_arguments(proxy, indent+1, cur, PASS_OUT, PHASE_FREE); + + print_proxy("}\n"); + print_proxy("RpcEndFinally\n"); + + print_proxy("_pRpcMessage->BufferLength = _StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer;\n"); + indent--; + + print_proxy("}\n"); + print_proxy("\n"); +} + +static int write_proxy_methods(type_t *iface) +{ + const func_t *cur; + int i = 0; + + if (iface->ref) i = write_proxy_methods(iface->ref); + if (iface->funcs) LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) { + var_t *def = cur->def; + if (!is_callas(def->attrs)) { + if (i) fprintf(proxy, ",\n"); + print_proxy( "%s_", iface->name); + write_name(proxy, def); + fprintf(proxy, "_Proxy"); + i++; + } + } + return i; +} + +static int write_stub_methods(type_t *iface) +{ + const func_t *cur; + int i = 0; + + if (iface->ref) i = write_stub_methods(iface->ref); + else return i; /* skip IUnknown */ + + if (iface->funcs) LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) { + var_t *def = cur->def; + if (!is_local(def->attrs)) { + if (i) fprintf(proxy,",\n"); + print_proxy( "%s_", iface->name); + write_name(proxy, def); + fprintf(proxy, "_Stub"); + i++; + } + } + return i; +} + +static void write_proxy(type_t *iface, unsigned int *proc_offset) +{ + int midx = -1, stubs; + const func_t *cur; + + if (!iface->funcs) return; + + /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */ + + fprintf(proxy, "/*****************************************************************************\n"); + fprintf(proxy, " * %s interface\n", iface->name); + fprintf(proxy, " */\n"); + LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) + { + const var_t *def = cur->def; + if (!is_local(def->attrs)) { + const var_t *cas = is_callas(def->attrs); + const char *cname = cas ? cas->name : NULL; + int idx = cur->idx; + if (cname) { + const func_t *m; + LIST_FOR_EACH_ENTRY( m, iface->funcs, const func_t, entry ) + if (!strcmp(m->def->name, cname)) + { + idx = m->idx; + break; + } + } + gen_proxy(iface, cur, idx, *proc_offset); + gen_stub(iface, cur, cname, *proc_offset); + *proc_offset += get_size_procformatstring_func( cur ); + if (midx == -1) midx = idx; + else if (midx != idx) error("method index mismatch in write_proxy\n"); + midx++; + } + } + + /* proxy vtable */ + print_proxy( "static const CINTERFACE_PROXY_VTABLE(%d) _%sProxyVtbl =\n", midx, iface->name); + print_proxy( "{\n"); + indent++; + print_proxy( "{\n", iface->name); + indent++; + print_proxy( "&IID_%s,\n", iface->name); + indent--; + print_proxy( "},\n"); + print_proxy( "{\n"); + indent++; + write_proxy_methods(iface); + fprintf(proxy, "\n"); + indent--; + print_proxy( "}\n"); + indent--; + print_proxy( "};\n"); + fprintf(proxy, "\n\n"); + + /* stub vtable */ + print_proxy( "static const PRPC_STUB_FUNCTION %s_table[] =\n", iface->name); + print_proxy( "{\n"); + indent++; + stubs = write_stub_methods(iface); + fprintf(proxy, "\n"); + indent--; + fprintf(proxy, "};\n"); + print_proxy( "\n"); + print_proxy( "static const CInterfaceStubVtbl _%sStubVtbl =\n", iface->name); + print_proxy( "{\n"); + indent++; + print_proxy( "{\n"); + indent++; + print_proxy( "&IID_%s,\n", iface->name); + print_proxy( "0,\n"); + print_proxy( "%d,\n", stubs+3); + print_proxy( "&%s_table[-3],\n", iface->name); + indent--; + print_proxy( "},\n", iface->name); + print_proxy( "{\n"); + indent++; + print_proxy( "CStdStubBuffer_METHODS\n"); + indent--; + print_proxy( "}\n"); + indent--; + print_proxy( "};\n"); + print_proxy( "\n"); +} + +static int does_any_iface(const ifref_list_t *ifaces, type_pred_t pred) +{ + ifref_t *ir; + + if (ifaces) + LIST_FOR_EACH_ENTRY(ir, ifaces, ifref_t, entry) + if (pred(ir->iface)) + return TRUE; + + return FALSE; +} + +int need_proxy(const type_t *iface) +{ + return is_object(iface->attrs) && !is_local(iface->attrs); +} + +int need_stub(const type_t *iface) +{ + return !is_object(iface->attrs) && !is_local(iface->attrs); +} + +int need_proxy_file(const ifref_list_t *ifaces) +{ + return does_any_iface(ifaces, need_proxy); +} + +int need_stub_files(const ifref_list_t *ifaces) +{ + return does_any_iface(ifaces, need_stub); +} + +void write_proxies(ifref_list_t *ifaces) +{ + ifref_t *cur; + int expr_eval_routines; + char *file_id = proxy_token; + int c; + unsigned int proc_offset = 0; + + if (!do_proxies) return; + if (do_everything && !need_proxy_file(ifaces)) return; + + init_proxy(ifaces); + if(!proxy) return; + + if (ifaces) + LIST_FOR_EACH_ENTRY( cur, ifaces, ifref_t, entry ) + if (need_proxy(cur->iface)) + write_proxy(cur->iface, &proc_offset); + + expr_eval_routines = write_expr_eval_routines(proxy, proxy_token); + if (expr_eval_routines) + write_expr_eval_routine_list(proxy, proxy_token); + write_user_quad_list(proxy); + write_stubdesc(expr_eval_routines); + + print_proxy( "#if !defined(__RPC_WIN32__)\n"); + print_proxy( "#error Currently only Wine and WIN32 are supported.\n"); + print_proxy( "#endif\n"); + print_proxy( "\n"); + write_procformatstring(proxy, ifaces, need_proxy); + write_typeformatstring(proxy, ifaces, need_proxy); + + fprintf(proxy, "static const CInterfaceProxyVtbl* const _%s_ProxyVtblList[] =\n", file_id); + fprintf(proxy, "{\n"); + if (ifaces) + LIST_FOR_EACH_ENTRY( cur, ifaces, ifref_t, entry ) + if(cur->iface->ref && cur->iface->funcs && need_proxy(cur->iface)) + fprintf(proxy, " (const CInterfaceProxyVtbl*)&_%sProxyVtbl,\n", cur->iface->name); + + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "static const CInterfaceStubVtbl* const _%s_StubVtblList[] =\n", file_id); + fprintf(proxy, "{\n"); + if (ifaces) + LIST_FOR_EACH_ENTRY( cur, ifaces, ifref_t, entry ) + if(cur->iface->ref && cur->iface->funcs && need_proxy(cur->iface)) + fprintf(proxy, " (const CInterfaceStubVtbl*)&_%sStubVtbl,\n", cur->iface->name); + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "static PCInterfaceName const _%s_InterfaceNamesList[] =\n", file_id); + fprintf(proxy, "{\n"); + if (ifaces) + LIST_FOR_EACH_ENTRY( cur, ifaces, ifref_t, entry ) + if(cur->iface->ref && cur->iface->funcs && need_proxy(cur->iface)) + fprintf(proxy, " \"%s\",\n", cur->iface->name); + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "#define _%s_CHECK_IID(n) IID_GENERIC_CHECK_IID(_%s, pIID, n)\n", file_id, file_id); + fprintf(proxy, "\n"); + fprintf(proxy, "int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id); + fprintf(proxy, "{\n"); + c = 0; + if (ifaces) + LIST_FOR_EACH_ENTRY( cur, ifaces, ifref_t, entry ) + if(cur->iface->ref && cur->iface->funcs && need_proxy(cur->iface)) + { + fprintf(proxy, " if (!_%s_CHECK_IID(%d))\n", file_id, c); + fprintf(proxy, " {\n"); + fprintf(proxy, " *pIndex = %d;\n", c); + fprintf(proxy, " return 1;\n"); + fprintf(proxy, " }\n"); + c++; + } + fprintf(proxy, " return 0;\n"); + fprintf(proxy, "}\n"); + fprintf(proxy, "\n"); + + fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo =\n", file_id); + fprintf(proxy, "{\n"); + fprintf(proxy, " (const PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id); + fprintf(proxy, " (const PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id); + fprintf(proxy, " _%s_InterfaceNamesList,\n", file_id); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " &_%s_IID_Lookup,\n", file_id); + fprintf(proxy, " %d,\n", c); + fprintf(proxy, " 1,\n"); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " 0,\n"); + fprintf(proxy, " 0\n"); + fprintf(proxy, "};\n"); + + fclose(proxy); +} diff --git a/reactos/tools/widl_20080105/server.c b/reactos/tools/widl_20080105/server.c new file mode 100644 index 00000000000..3fc6dd80053 --- /dev/null +++ b/reactos/tools/widl_20080105/server.c @@ -0,0 +1,453 @@ +/* + * IDL Compiler + * + * Copyright 2005-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" + +#include "typegen.h" + +static FILE* server; +static int indent = 0; + + +static void print_server(const char *format, ...) +{ + va_list va; + va_start(va, format); + print(server, indent, format, va); + va_end(va); +} + +static void write_function_stubs(type_t *iface, unsigned int *proc_offset) +{ + char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE); + int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE); + const func_t *func; + const var_t *var; + const var_t* explicit_handle_var; + + if (!iface->funcs) return; + LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry ) + { + const var_t *def = func->def; + + /* check for a defined binding handle */ + explicit_handle_var = get_explicit_handle_var(func); + if (explicit_handle) + { + if (!explicit_handle_var) + { + error("%s() does not define an explicit binding handle!\n", def->name); + return; + } + } + else if (implicit_handle) + { + if (explicit_handle_var) + { + error("%s() must not define a binding handle!\n", def->name); + return; + } + } + + fprintf(server, "void __RPC_STUB\n"); + fprintf(server, "%s_", iface->name); + write_name(server, def); + fprintf(server, "(\n"); + indent++; + print_server("PRPC_MESSAGE _pRpcMessage)\n"); + indent--; + + /* write the functions body */ + fprintf(server, "{\n"); + indent++; + + /* Declare arguments */ + declare_stub_args(server, indent, func); + + print_server("MIDL_STUB_MESSAGE _StubMsg;\n"); + print_server("RPC_STATUS _Status;\n"); + fprintf(server, "\n"); + + + print_server("((void)(_Status));\n"); + print_server("NdrServerInitializeNew(\n"); + indent++; + print_server("_pRpcMessage,\n"); + print_server("&_StubMsg,\n"); + print_server("&%s_StubDesc);\n", iface->name); + indent--; + fprintf(server, "\n"); + + write_parameters_init(server, indent, func); + + if (explicit_handle_var) + { + print_server("%s = _pRpcMessage->Handle;\n", explicit_handle_var->name); + fprintf(server, "\n"); + } + + print_server("RpcTryFinally\n"); + print_server("{\n"); + indent++; + print_server("RpcTryExcept\n"); + print_server("{\n"); + indent++; + + if (func->args) + { + print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); + indent++; + print_server("NdrConvert(\n"); + indent++; + print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_server("(PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", *proc_offset); + indent -= 2; + fprintf(server, "\n"); + + /* unmarshall arguments */ + write_remoting_arguments(server, indent, func, PASS_IN, PHASE_UNMARSHAL); + } + + print_server("if (_StubMsg.Buffer > _StubMsg.BufferEnd)\n"); + print_server("{\n"); + indent++; + print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); + indent--; + print_server("}\n"); + indent--; + print_server("}\n"); + print_server("RpcExcept(RPC_BAD_STUB_DATA_EXCEPTION_FILTER)\n"); + print_server("{\n"); + indent++; + print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); + indent--; + print_server("}\n"); + print_server("RpcEndExcept\n"); + fprintf(server, "\n"); + + /* Assign 'out' arguments */ + assign_stub_out_args(server, indent, func); + + /* Call the real server function */ + if (!is_void(def->type)) + print_server("_RetVal = "); + else + print_server(""); + write_prefix_name(server, prefix_server, def); + + if (func->args) + { + int first_arg = 1; + + fprintf(server, "(\n"); + indent++; + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + { + if (first_arg) + first_arg = 0; + else + fprintf(server, ",\n"); + if (is_context_handle(var->type)) + { + print_server("("); + write_type_decl_left(server, var->type); + fprintf(server, ")%sNDRSContextValue(%s)", is_ptr(var->type) ? "" : "*", var->name); + } + else + { + print_server(""); + if (var->type->declarray) + fprintf(server, "*"); + write_name(server, var); + } + } + fprintf(server, ");\n"); + indent--; + } + else + { + fprintf(server, "();\n"); + } + + if (has_out_arg_or_return(func)) + { + write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_BUFFERSIZE); + + if (!is_void(def->type)) + write_remoting_arguments(server, indent, func, PASS_RETURN, PHASE_BUFFERSIZE); + + print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n"); + fprintf(server, "\n"); + print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n"); + print_server("if (_Status)\n"); + indent++; + print_server("RpcRaiseException(_Status);\n"); + indent--; + fprintf(server, "\n"); + print_server("_StubMsg.Buffer = (unsigned char *)_pRpcMessage->Buffer;\n"); + fprintf(server, "\n"); + } + + /* marshall arguments */ + write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_MARSHAL); + + /* marshall the return value */ + if (!is_void(def->type)) + write_remoting_arguments(server, indent, func, PASS_RETURN, PHASE_MARSHAL); + + indent--; + print_server("}\n"); + print_server("RpcFinally\n"); + print_server("{\n"); + indent++; + + write_remoting_arguments(server, indent, func, PASS_OUT, PHASE_FREE); + + indent--; + print_server("}\n"); + print_server("RpcEndFinally\n"); + + /* calculate buffer length */ + fprintf(server, "\n"); + print_server("_pRpcMessage->BufferLength =\n"); + indent++; + print_server("(unsigned int)(_StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer);\n"); + indent--; + indent--; + fprintf(server, "}\n"); + fprintf(server, "\n"); + + /* update proc_offset */ + *proc_offset += get_size_procformatstring_func( func ); + } +} + + +static void write_dispatchtable(type_t *iface) +{ + unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + unsigned long method_count = 0; + const func_t *func; + + print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name); + print_server("{\n"); + indent++; + + if (iface->funcs) LIST_FOR_EACH_ENTRY( func, iface->funcs, const func_t, entry ) + { + var_t *def = func->def; + + print_server("%s_", iface->name); + write_name(server, def); + fprintf(server, ",\n"); + + method_count++; + } + print_server("0\n"); + indent--; + print_server("};\n"); + print_server("RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + print_server("{\n"); + indent++; + print_server("%u,\n", method_count); + print_server("%s_table\n", iface->name); + indent--; + print_server("};\n"); + fprintf(server, "\n"); +} + + +static void write_stubdescdecl(type_t *iface) +{ + print_server("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name); + fprintf(server, "\n"); +} + + +static void write_stubdescriptor(type_t *iface, int expr_eval_routines) +{ + print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name); + print_server("{\n"); + indent++; + print_server("(void *)& %s___RpcServerInterface,\n", iface->name); + print_server("MIDL_user_allocate,\n"); + print_server("MIDL_user_free,\n"); + print_server("{\n"); + indent++; + print_server("0,\n"); + indent--; + print_server("},\n"); + print_server("0,\n"); + print_server("0,\n"); + if (expr_eval_routines) + print_server("ExprEvalRoutines,\n"); + else + print_server("0,\n"); + print_server("0,\n"); + print_server("__MIDL_TypeFormatString.Format,\n"); + print_server("1, /* -error bounds_check flag */\n"); + print_server("0x10001, /* Ndr library version */\n"); + print_server("0,\n"); + print_server("0x50100a4, /* MIDL Version 5.1.164 */\n"); + print_server("0,\n"); + print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); + print_server("0, /* notify & notify_flag routine table */\n"); + print_server("1, /* Flags */\n"); + print_server("0, /* Reserved3 */\n"); + print_server("0, /* Reserved4 */\n"); + print_server("0 /* Reserved5 */\n"); + indent--; + print_server("};\n"); + fprintf(server, "\n"); +} + + +static void write_serverinterfacedecl(type_t *iface) +{ + unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION); + UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); + const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT); + + if (endpoints) write_endpoints( server, iface->name, endpoints ); + + print_server("extern RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + fprintf(server, "\n"); + print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name ); + print_server("{\n"); + indent++; + print_server("sizeof(RPC_SERVER_INTERFACE),\n"); + 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", + uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], + uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], + uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver)); + print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */ + print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); + if (endpoints) + { + print_server("%u,\n", list_count(endpoints)); + print_server("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name); + } + else + { + print_server("0,\n"); + print_server("0,\n"); + } + print_server("0,\n"); + print_server("0,\n"); + print_server("0,\n"); + indent--; + print_server("};\n"); + if (old_names) + print_server("RPC_IF_HANDLE %s_ServerIfHandle = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", + iface->name, iface->name); + else + print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", + prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name); + fprintf(server, "\n"); +} + + +static void init_server(void) +{ + if (server) + return; + if (!(server = fopen(server_name, "w"))) + error("Could not open %s for output\n", server_name); + + print_server("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); + print_server("#include \n"); + fprintf(server, "\n"); + print_server("#define _SEH_NO_NATIVE_NLG\n"); + print_server("#include \"%s\"\n", header_name); + fprintf(server, "\n"); +} + + +void write_server(ifref_list_t *ifaces) +{ + unsigned int proc_offset = 0; + int expr_eval_routines; + ifref_t *iface; + + if (!do_server) + return; + if (do_everything && !need_stub_files(ifaces)) + return; + + init_server(); + if (!server) + return; + + write_formatstringsdecl(server, indent, ifaces, need_stub); + expr_eval_routines = write_expr_eval_routines(server, server_token); + if (expr_eval_routines) + write_expr_eval_routine_list(server, server_token); + write_user_quad_list(server); + + if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, ifref_t, entry ) + { + if (!need_stub(iface->iface)) + continue; + + fprintf(server, "/*****************************************************************************\n"); + fprintf(server, " * %s interface\n", iface->iface->name); + fprintf(server, " */\n"); + fprintf(server, "\n"); + + if (iface->iface->funcs) + { + write_serverinterfacedecl(iface->iface); + write_stubdescdecl(iface->iface); + + write_function_stubs(iface->iface, &proc_offset); + + print_server("#if !defined(__RPC_WIN32__)\n"); + print_server("#error Invalid build platform for this stub.\n"); + print_server("#endif\n"); + + fprintf(server, "\n"); + write_stubdescriptor(iface->iface, expr_eval_routines); + write_dispatchtable(iface->iface); + } + } + + fprintf(server, "\n"); + + write_procformatstring(server, ifaces, need_stub); + write_typeformatstring(server, ifaces, need_stub); + + fclose(server); +} diff --git a/reactos/tools/widl_20080105/typegen.c b/reactos/tools/widl_20080105/typegen.c new file mode 100644 index 00000000000..f40399f16b2 --- /dev/null +++ b/reactos/tools/widl_20080105/typegen.c @@ -0,0 +1,3309 @@ +/* + * Format String Generator for IDL Compiler + * + * Copyright 2005-2006 Eric Kohl + * Copyright 2005-2006 Robert Shearman + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "wine/list.h" + +#include "typegen.h" + +static const func_t *current_func; +static const type_t *current_structure; + +static struct list expr_eval_routines = LIST_INIT(expr_eval_routines); +struct expr_eval_routine +{ + struct list entry; + const type_t *structure; + unsigned int baseoff; + const expr_t *expr; +}; + +static size_t fields_memsize(const var_list_t *fields, unsigned int *align); +static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff); +static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, + const char *name, int write_ptr, unsigned int *tfsoff); +static const var_t *find_array_or_string_in_struct(const type_t *type); + +const char *string_of_type(unsigned char type) +{ + switch (type) + { + case RPC_FC_BYTE: return "FC_BYTE"; + case RPC_FC_CHAR: return "FC_CHAR"; + case RPC_FC_SMALL: return "FC_SMALL"; + case RPC_FC_USMALL: return "FC_USMALL"; + case RPC_FC_WCHAR: return "FC_WCHAR"; + case RPC_FC_SHORT: return "FC_SHORT"; + case RPC_FC_USHORT: return "FC_USHORT"; + case RPC_FC_LONG: return "FC_LONG"; + case RPC_FC_ULONG: return "FC_ULONG"; + case RPC_FC_FLOAT: return "FC_FLOAT"; + case RPC_FC_HYPER: return "FC_HYPER"; + case RPC_FC_DOUBLE: return "FC_DOUBLE"; + case RPC_FC_ENUM16: return "FC_ENUM16"; + case RPC_FC_ENUM32: return "FC_ENUM32"; + case RPC_FC_IGNORE: return "FC_IGNORE"; + case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T"; + case RPC_FC_RP: return "FC_RP"; + case RPC_FC_UP: return "FC_UP"; + case RPC_FC_OP: return "FC_OP"; + case RPC_FC_FP: return "FC_FP"; + case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION"; + case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION"; + case RPC_FC_STRUCT: return "FC_STRUCT"; + case RPC_FC_PSTRUCT: return "FC_PSTRUCT"; + case RPC_FC_CSTRUCT: return "FC_CSTRUCT"; + case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT"; + case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT"; + case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT"; + case RPC_FC_SMFARRAY: return "FC_SMFARRAY"; + case RPC_FC_LGFARRAY: return "FC_LGFARRAY"; + case RPC_FC_SMVARRAY: return "FC_SMVARRAY"; + case RPC_FC_LGVARRAY: return "FC_LGVARRAY"; + case RPC_FC_CARRAY: return "FC_CARRAY"; + case RPC_FC_CVARRAY: return "FC_CVARRAY"; + case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY"; + case RPC_FC_ALIGNM4: return "FC_ALIGNM4"; + case RPC_FC_ALIGNM8: return "FC_ALIGNM8"; + case RPC_FC_POINTER: return "FC_POINTER"; + case RPC_FC_C_CSTRING: return "FC_C_CSTRING"; + case RPC_FC_C_WSTRING: return "FC_C_WSTRING"; + case RPC_FC_CSTRING: return "FC_CSTRING"; + case RPC_FC_WSTRING: return "FC_WSTRING"; + default: + error("string_of_type: unknown type 0x%02x\n", type); + return NULL; + } +} + +int is_struct(unsigned char type) +{ + switch (type) + { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_BOGUS_STRUCT: + return 1; + default: + return 0; + } +} + +static int is_non_complex_struct(const type_t *type) +{ + switch (type->type) + { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + return 1; + default: + return 0; + } +} + +int is_union(unsigned char type) +{ + switch (type) + { + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + return 1; + default: + return 0; + } +} + +static int type_has_pointers(const type_t *type) +{ + if (is_user_type(type)) + return FALSE; + else if (is_ptr(type)) + return TRUE; + else if (is_array(type)) + return type_has_pointers(type->ref); + else if (is_struct(type->type)) + { + const var_t *field; + if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) + { + if (type_has_pointers(field->type)) + return TRUE; + } + } + else if (is_union(type->type)) + { + var_list_t *fields; + const var_t *field; + if (type->type == RPC_FC_ENCAPSULATED_UNION) + { + const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry); + fields = uv->type->fields; + } + else + fields = type->fields; + if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + { + if (field->type && type_has_pointers(field->type)) + return TRUE; + } + } + + return FALSE; +} + +static unsigned short user_type_offset(const char *name) +{ + user_type_t *ut; + unsigned short off = 0; + LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) + { + if (strcmp(name, ut->name) == 0) + return off; + ++off; + } + error("user_type_offset: couldn't find type (%s)\n", name); + return 0; +} + +static void update_tfsoff(type_t *type, unsigned int offset, FILE *file) +{ + type->typestring_offset = offset; + if (file) type->tfswrite = FALSE; +} + +static void guard_rec(type_t *type) +{ + /* types that contain references to themselves (like a linked list), + need to be shielded from infinite recursion when writing embedded + types */ + if (type->typestring_offset) + type->tfswrite = FALSE; + else + type->typestring_offset = 1; +} + +static type_t *get_user_type(const type_t *t, const char **pname) +{ + for (;;) + { + type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL); + if (ut) + { + if (pname) + *pname = t->name; + return ut; + } + + if (t->kind == TKIND_ALIAS) + t = t->orig; + else + return 0; + } +} + +int is_user_type(const type_t *t) +{ + return get_user_type(t, NULL) != NULL; +} + +static int is_embedded_complex(const type_t *type) +{ + unsigned char tc = type->type; + return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type) + || (is_ptr(type) && type->ref->type == RPC_FC_IP); +} + +static const char *get_context_handle_type_name(const type_t *type) +{ + const type_t *t; + for (t = type; is_ptr(t); t = t->ref) + if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) + return t->name; + assert(0); + return NULL; +} + +/* This is actually fairly involved to implement precisely, due to the + effects attributes may have and things like that. Right now this is + only used for optimization, so just check for a very small set of + criteria that guarantee the types are equivalent; assume every thing + else is different. */ +static int compare_type(const type_t *a, const type_t *b) +{ + if (a == b + || (a->name + && b->name + && strcmp(a->name, b->name) == 0)) + return 0; + /* Ordering doesn't need to be implemented yet. */ + return 1; +} + +static int compare_expr(const expr_t *a, const expr_t *b) +{ + int ret; + + if (a->type != b->type) + return a->type - b->type; + + switch (a->type) + { + case EXPR_NUM: + case EXPR_HEXNUM: + case EXPR_TRUEFALSE: + return a->u.lval - b->u.lval; + case EXPR_DOUBLE: + return a->u.dval - b->u.dval; + case EXPR_IDENTIFIER: + return strcmp(a->u.sval, b->u.sval); + case EXPR_COND: + ret = compare_expr(a->ref, b->ref); + if (ret != 0) + return ret; + ret = compare_expr(a->u.ext, b->u.ext); + if (ret != 0) + return ret; + return compare_expr(a->ext2, b->ext2); + case EXPR_OR: + case EXPR_AND: + case EXPR_ADD: + case EXPR_SUB: + case EXPR_MUL: + case EXPR_DIV: + case EXPR_SHL: + case EXPR_SHR: + ret = compare_expr(a->ref, b->ref); + if (ret != 0) + return ret; + return compare_expr(a->u.ext, b->u.ext); + case EXPR_CAST: + ret = compare_type(a->u.tref, b->u.tref); + if (ret != 0) + return ret; + /* Fall through. */ + case EXPR_NOT: + case EXPR_NEG: + case EXPR_PPTR: + case EXPR_ADDRESSOF: + return compare_expr(a->ref, b->ref); + case EXPR_SIZEOF: + return compare_type(a->u.tref, b->u.tref); + case EXPR_VOID: + return 0; + } + return -1; +} + +#define WRITE_FCTYPE(file, fctype, typestring_offset) \ + do { \ + if (file) \ + fprintf(file, "/* %2u */\n", typestring_offset); \ + print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \ + } \ + while (0) + +static void print_file(FILE *file, int indent, const char *format, ...) +{ + va_list va; + va_start(va, format); + print(file, indent, format, va); + va_end(va); +} + +void print(FILE *file, int indent, const char *format, va_list va) +{ + if (file) + { + if (format[0] != '\n') + while (0 < indent--) + fprintf(file, " "); + vfprintf(file, format, va); + } +} + + +static void write_var_init(FILE *file, int indent, const type_t *t, const char *n) +{ + if (decl_indirect(t)) + print_file(file, indent, "MIDL_memset(&%s, 0, sizeof(%s));\n", n, n); + else if (is_ptr(t) || is_array(t)) + print_file(file, indent, "%s = 0;\n", n); +} + +void write_parameters_init(FILE *file, int indent, const func_t *func) +{ + const var_t *var; + + if (!is_void(func->def->type)) + write_var_init(file, indent, func->def->type, "_RetVal"); + + if (!func->args) + return; + + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + write_var_init(file, indent, var->type, var->name); + + fprintf(file, "\n"); +} + +static void write_formatdesc(FILE *f, int indent, const char *str) +{ + print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str); + print_file(f, indent, "{\n"); + print_file(f, indent + 1, "short Pad;\n"); + print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str); + print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str); + print_file(f, indent, "\n"); +} + +void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred) +{ + print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n", + get_size_typeformatstring(ifaces, pred)); + + print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n", + get_size_procformatstring(ifaces, pred)); + + fprintf(f, "\n"); + write_formatdesc(f, indent, "TYPE"); + write_formatdesc(f, indent, "PROC"); + fprintf(f, "\n"); + print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n"); + print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n"); + print_file(f, indent, "\n"); +} + +static inline int is_base_type(unsigned char type) +{ + switch (type) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_USMALL: + case RPC_FC_SMALL: + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + case RPC_FC_ULONG: + case RPC_FC_LONG: + case RPC_FC_HYPER: + case RPC_FC_IGNORE: + case RPC_FC_FLOAT: + case RPC_FC_DOUBLE: + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_BIND_PRIMITIVE: + return TRUE; + + default: + return FALSE; + } +} + +int decl_indirect(const type_t *t) +{ + return is_user_type(t) + || (!is_base_type(t->type) + && !is_ptr(t) + && !is_array(t)); +} + +static size_t write_procformatstring_var(FILE *file, int indent, + const var_t *var, int is_return) +{ + size_t size; + const type_t *type = var->type; + + int is_in = is_attr(var->attrs, ATTR_IN); + int is_out = is_attr(var->attrs, ATTR_OUT); + + if (!is_in && !is_out) is_in = TRUE; + + if (!type->declarray && is_base_type(type->type)) + { + if (is_return) + print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n"); + else + print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n"); + + if (type->type == RPC_FC_BIND_PRIMITIVE) + { + print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE); + size = 2; /* includes param type prefix */ + } + else if (is_base_type(type->type)) + { + print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type)); + size = 2; /* includes param type prefix */ + } + else + { + error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type); + size = 0; + } + } + else + { + if (is_return) + print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n"); + else if (is_in && is_out) + print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n"); + else if (is_out) + print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n"); + else + print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n"); + + print_file(file, indent, "0x01,\n"); + print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset); + size = 4; /* includes param type prefix */ + } + return size; +} + +void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred) +{ + const ifref_t *iface; + int indent = 0; + const var_t *var; + + print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n"); + print_file(file, indent, "{\n"); + indent++; + print_file(file, indent, "0,\n"); + print_file(file, indent, "{\n"); + indent++; + + if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry ) + { + if (!pred(iface->iface)) + continue; + + if (iface->iface->funcs) + { + const func_t *func; + LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry ) + { + if (is_local(func->def->attrs)) continue; + /* emit argument data */ + if (func->args) + { + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + write_procformatstring_var(file, indent, var, FALSE); + } + + /* emit return value data */ + var = func->def; + if (is_void(var->type)) + { + print_file(file, indent, "0x5b, /* FC_END */\n"); + print_file(file, indent, "0x5c, /* FC_PAD */\n"); + } + else + write_procformatstring_var(file, indent, var, TRUE); + } + } + } + + print_file(file, indent, "0x0\n"); + indent--; + print_file(file, indent, "}\n"); + indent--; + print_file(file, indent, "};\n"); + print_file(file, indent, "\n"); +} + +static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset) +{ + if (is_base_type(type->type)) + { + print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type)); + *typestring_offset += 1; + return 1; + } + + return 0; +} + +/* write conformance / variance descriptor */ +static size_t write_conf_or_var_desc(FILE *file, const type_t *structure, + unsigned int baseoff, const type_t *type, + const expr_t *expr) +{ + unsigned char operator_type = 0; + unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE; + const char *conftype_string = ""; + const char *operator_string = "no operators"; + const expr_t *subexpr; + + if (!expr) + { + print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n"); + return 4; + } + + if (!structure) + { + /* Top-level conformance calculations are done inline. */ + print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n", + RPC_FC_TOP_LEVEL_CONFORMANCE); + print_file (file, 2, "0x0,\n"); + print_file (file, 2, "NdrFcShort(0x0),\n"); + return 4; + } + + if (expr->is_const) + { + if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX) + error("write_conf_or_var_desc: constant value %ld is greater than " + "the maximum constant size of %d\n", expr->cval, + UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX); + + print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n", + RPC_FC_CONSTANT_CONFORMANCE, expr->cval); + print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX); + print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX); + + return 4; + } + + if (is_ptr(type) || (is_array(type) && !type->declarray)) + { + conftype = RPC_FC_POINTER_CONFORMANCE; + conftype_string = "field pointer, "; + } + + subexpr = expr; + switch (subexpr->type) + { + case EXPR_PPTR: + subexpr = subexpr->ref; + operator_type = RPC_FC_DEREFERENCE; + operator_string = "FC_DEREFERENCE"; + break; + case EXPR_DIV: + if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2)) + { + subexpr = subexpr->ref; + operator_type = RPC_FC_DIV_2; + operator_string = "FC_DIV_2"; + } + break; + case EXPR_MUL: + if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2)) + { + subexpr = subexpr->ref; + operator_type = RPC_FC_MULT_2; + operator_string = "FC_MULT_2"; + } + break; + case EXPR_SUB: + if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1)) + { + subexpr = subexpr->ref; + operator_type = RPC_FC_SUB_1; + operator_string = "FC_SUB_1"; + } + break; + case EXPR_ADD: + if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1)) + { + subexpr = subexpr->ref; + operator_type = RPC_FC_ADD_1; + operator_string = "FC_ADD_1"; + } + break; + default: + break; + } + + if (subexpr->type == EXPR_IDENTIFIER) + { + const type_t *correlation_variable = NULL; + unsigned char correlation_variable_type; + unsigned char param_type = 0; + size_t offset = 0; + const var_t *var; + + if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry ) + { + unsigned int align = 0; + /* FIXME: take alignment into account */ + if (var->name && !strcmp(var->name, subexpr->u.sval)) + { + correlation_variable = var->type; + break; + } + offset += type_memsize(var->type, &align); + } + if (!correlation_variable) + error("write_conf_or_var_desc: couldn't find variable %s in structure\n", + subexpr->u.sval); + + offset -= baseoff; + correlation_variable_type = correlation_variable->type; + + switch (correlation_variable_type) + { + case RPC_FC_CHAR: + case RPC_FC_SMALL: + param_type = RPC_FC_SMALL; + break; + case RPC_FC_BYTE: + case RPC_FC_USMALL: + param_type = RPC_FC_USMALL; + break; + case RPC_FC_WCHAR: + case RPC_FC_SHORT: + case RPC_FC_ENUM16: + param_type = RPC_FC_SHORT; + break; + case RPC_FC_USHORT: + param_type = RPC_FC_USHORT; + break; + case RPC_FC_LONG: + case RPC_FC_ENUM32: + param_type = RPC_FC_LONG; + break; + case RPC_FC_ULONG: + param_type = RPC_FC_ULONG; + break; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + if (sizeof(void *) == 4) /* FIXME */ + param_type = RPC_FC_LONG; + else + param_type = RPC_FC_HYPER; + break; + default: + error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n", + correlation_variable_type); + } + + print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n", + conftype | param_type, conftype_string, string_of_type(param_type)); + print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string); + print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n", + offset, offset); + } + else + { + unsigned int callback_offset = 0; + struct expr_eval_routine *eval; + int found = 0; + + LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) + { + if (!strcmp (eval->structure->name, structure->name) + && !compare_expr (eval->expr, expr)) + { + found = 1; + break; + } + callback_offset++; + } + + if (!found) + { + eval = xmalloc (sizeof(*eval)); + eval->structure = structure; + eval->baseoff = baseoff; + eval->expr = expr; + list_add_tail (&expr_eval_routines, &eval->entry); + } + + if (callback_offset > USHRT_MAX) + error("Maximum number of callback routines reached\n"); + + print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string); + print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK"); + print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset); + } + return 4; +} + +static size_t fields_memsize(const var_list_t *fields, unsigned int *align) +{ + int have_align = FALSE; + size_t size = 0; + const var_t *v; + + if (!fields) return 0; + LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) + { + unsigned int falign = 0; + size_t fsize = type_memsize(v->type, &falign); + if (!have_align) + { + *align = falign; + have_align = TRUE; + } + size = (size + (falign - 1)) & ~(falign - 1); + size += fsize; + } + + size = (size + (*align - 1)) & ~(*align - 1); + return size; +} + +static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa) +{ + size_t size, maxs = 0; + unsigned int align = *pmaxa; + const var_t *v; + + if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) + { + /* we could have an empty default field with NULL type */ + if (v->type) + { + size = type_memsize(v->type, &align); + if (maxs < size) maxs = size; + if (*pmaxa < align) *pmaxa = align; + } + } + + return maxs; +} + +int get_padding(const var_list_t *fields) +{ + unsigned short offset = 0; + int salign = -1; + const var_t *f; + + if (!fields) + return 0; + + LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) + { + type_t *ft = f->type; + unsigned int align = 0; + size_t size = type_memsize(ft, &align); + if (salign == -1) + salign = align; + offset = (offset + (align - 1)) & ~(align - 1); + offset += size; + } + + return ((offset + (salign - 1)) & ~(salign - 1)) - offset; +} + +size_t type_memsize(const type_t *t, unsigned int *align) +{ + size_t size = 0; + + if (t->declarray && is_conformant_array(t)) + { + type_memsize(t->ref, align); + size = 0; + } + else if (is_ptr(t) || is_conformant_array(t)) + { + size = sizeof(void *); + if (size > *align) *align = size; + } + else switch (t->type) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_USMALL: + case RPC_FC_SMALL: + size = 1; + if (size > *align) *align = size; + break; + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + case RPC_FC_ENUM16: + size = 2; + if (size > *align) *align = size; + break; + case RPC_FC_ULONG: + case RPC_FC_LONG: + case RPC_FC_ERROR_STATUS_T: + case RPC_FC_ENUM32: + case RPC_FC_FLOAT: + size = 4; + if (size > *align) *align = size; + break; + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + size = 8; + if (size > *align) *align = size; + break; + case RPC_FC_STRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_BOGUS_STRUCT: + size = fields_memsize(t->fields, align); + break; + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + size = union_memsize(t->fields, align); + break; + case RPC_FC_SMFARRAY: + case RPC_FC_LGFARRAY: + case RPC_FC_SMVARRAY: + case RPC_FC_LGVARRAY: + case RPC_FC_BOGUS_ARRAY: + size = t->dim * type_memsize(t->ref, align); + break; + default: + error("type_memsize: Unknown type %d\n", t->type); + size = 0; + } + + return size; +} + +static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset) +{ + short absoff = type->ref->typestring_offset; + short reloff = absoff - (offset + 2); + int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0; + + print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n", + type->type, ptr_attr, string_of_type(type->type)); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n", + reloff, reloff, absoff); + return 4; +} + +static unsigned char conf_string_type_of_char_type(unsigned char t) +{ + switch (t) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + return RPC_FC_C_CSTRING; + case RPC_FC_WCHAR: + return RPC_FC_C_WSTRING; + } + + error("string_type_of_char_type: unrecognized type %d\n", t); + return 0; +} + +static unsigned int write_simple_pointer(FILE *file, const type_t *type) +{ + unsigned char fc + = is_string_type(type->attrs, type) + ? conf_string_type_of_char_type(type->ref->type) + : type->ref->type; + print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n", + type->type, string_of_type(type->type)); + print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); + print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); + return 4; +} + +static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff) +{ + print_file(file, 0, "/* %u (", tfsoff); + write_type_decl(file, t, NULL); + print_file(file, 0, ") */\n"); +} + +static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset) +{ + unsigned int offset = *typestring_offset; + + print_start_tfs_comment(file, type, offset); + update_tfsoff(type, offset, file); + + if (type->ref->typestring_offset) + *typestring_offset += write_nonsimple_pointer(file, type, offset); + else if (is_base_type(type->ref->type)) + *typestring_offset += write_simple_pointer(file, type); + + return offset; +} + +static int processed(const type_t *type) +{ + return type->typestring_offset && !type->tfswrite; +} + +static int user_type_has_variable_size(const type_t *t) +{ + if (is_ptr(t)) + return TRUE; + else + switch (t->type) + { + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + return TRUE; + } + /* Note: Since this only applies to user types, we can't have a conformant + array here, and strings should get filed under pointer in this case. */ + return FALSE; +} + +static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) +{ + unsigned int start, absoff, flags; + unsigned int align = 0, ualign = 0; + const char *name; + type_t *utype = get_user_type(type, &name); + size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign); + size_t size = type_memsize(type, &align); + unsigned short funoff = user_type_offset(name); + short reloff; + + guard_rec(type); + + if (is_base_type(utype->type)) + { + absoff = *tfsoff; + print_start_tfs_comment(file, utype, absoff); + print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type)); + print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); + *tfsoff += 2; + } + else + { + if (!processed(utype)) + write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff); + absoff = utype->typestring_offset; + } + + if (utype->type == RPC_FC_RP) + flags = 0x40; + else if (utype->type == RPC_FC_UP) + flags = 0x80; + else + flags = 0; + + start = *tfsoff; + update_tfsoff(type, start, file); + print_start_tfs_comment(file, type, start); + print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL); + print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n", + flags | (align - 1), align - 1, flags); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff); + print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size); + print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize); + *tfsoff += 8; + reloff = absoff - *tfsoff; + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff); + *tfsoff += 2; +} + +static void write_member_type(FILE *file, const type_t *cont, + const attr_list_t *attrs, const type_t *type, + unsigned int *corroff, unsigned int *tfsoff) +{ + if (is_embedded_complex(type) && !is_conformant_array(type)) + { + size_t absoff; + short reloff; + + if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS)) + { + absoff = *corroff; + *corroff += 8; + } + else + { + absoff = type->typestring_offset; + } + reloff = absoff - (*tfsoff + 2); + + print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n"); + /* FIXME: actually compute necessary padding */ + print_file(file, 2, "0x0,\t/* FIXME: padding */\n"); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", + reloff, reloff, absoff); + *tfsoff += 4; + } + else if (is_ptr(type) || is_conformant_array(type)) + { + unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT + ? RPC_FC_POINTER + : RPC_FC_LONG); + print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); + *tfsoff += 1; + } + else if (!write_base_type(file, type, tfsoff)) + error("Unsupported member type 0x%x\n", type->type); +} + +static void write_end(FILE *file, unsigned int *tfsoff) +{ + if (*tfsoff % 2 == 0) + { + print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD); + *tfsoff += 1; + } + print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END); + *tfsoff += 1; +} + +static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) +{ + unsigned int offset = 0; + var_list_t *fs = type->fields; + var_t *f; + + if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) + { + unsigned int align = 0; + type_t *ft = f->type; + if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS)) + { + unsigned int absoff = ft->typestring_offset; + short reloff = absoff - (*tfsoff + 6); + print_file(file, 0, "/* %d */\n", *tfsoff); + print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type)); + print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG); + write_conf_or_var_desc(file, current_structure, offset, ft, + get_attrp(f->attrs, ATTR_SWITCHIS)); + print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); + *tfsoff += 8; + } + + /* FIXME: take alignment into account */ + offset += type_memsize(ft, &align); + } +} + +static int write_no_repeat_pointer_descriptions( + FILE *file, type_t *type, + size_t *offset_in_memory, size_t *offset_in_buffer, + unsigned int *typestring_offset) +{ + int written = 0; + unsigned int align; + + if (is_ptr(type) || (!type->declarray && is_conformant_array(type))) + { + print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT); + print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD); + + /* pointer instance */ + print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory); + print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer); + *typestring_offset += 6; + + if (is_ptr(type)) + write_pointer_tfs(file, type, typestring_offset); + else + { + unsigned absoff = type->typestring_offset; + short reloff = absoff - (*typestring_offset + 2); + /* FIXME: get pointer attributes from field */ + print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP"); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); + *typestring_offset += 4; + } + + align = 0; + *offset_in_memory += type_memsize(type, &align); + /* FIXME: is there a case where these two are different? */ + align = 0; + *offset_in_buffer += type_memsize(type, &align); + + return 1; + } + + if (is_non_complex_struct(type)) + { + const var_t *v; + LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry ) + written += write_no_repeat_pointer_descriptions( + file, v->type, + offset_in_memory, offset_in_buffer, typestring_offset); + } + else + { + align = 0; + *offset_in_memory += type_memsize(type, &align); + /* FIXME: is there a case where these two are different? */ + align = 0; + *offset_in_buffer += type_memsize(type, &align); + } + + return written; +} + +static int write_pointer_description_offsets( + FILE *file, const attr_list_t *attrs, type_t *type, + size_t *offset_in_memory, size_t *offset_in_buffer, + unsigned int *typestring_offset) +{ + int written = 0; + unsigned int align; + + if (is_ptr(type) && type->ref->type != RPC_FC_IP) + { + if (offset_in_memory && offset_in_buffer) + { + /* pointer instance */ + /* FIXME: sometimes from end of structure, sometimes from beginning */ + print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory); + print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer); + + align = 0; + *offset_in_memory += type_memsize(type, &align); + /* FIXME: is there a case where these two are different? */ + align = 0; + *offset_in_buffer += type_memsize(type, &align); + } + *typestring_offset += 4; + + if (processed(type->ref) || is_base_type(type->ref->type)) + write_pointer_tfs(file, type, typestring_offset); + else + error("write_pointer_description_offsets: type format string unknown\n"); + + return 1; + } + + if (is_array(type)) + { + return write_pointer_description_offsets( + file, attrs, type->ref, offset_in_memory, offset_in_buffer, + typestring_offset); + } + else if (is_non_complex_struct(type)) + { + /* otherwise search for interesting fields to parse */ + const var_t *v; + LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry ) + { + written += write_pointer_description_offsets( + file, v->attrs, v->type, offset_in_memory, offset_in_buffer, + typestring_offset); + } + } + else + { + align = 0; + if (offset_in_memory) + *offset_in_memory += type_memsize(type, &align); + /* FIXME: is there a case where these two are different? */ + align = 0; + if (offset_in_buffer) + *offset_in_buffer += type_memsize(type, &align); + } + + return written; +} + +/* Note: if file is NULL return value is number of pointers to write, else + * it is the number of type format characters written */ +static int write_fixed_array_pointer_descriptions( + FILE *file, const attr_list_t *attrs, type_t *type, + size_t *offset_in_memory, size_t *offset_in_buffer, + unsigned int *typestring_offset) +{ + unsigned int align; + int pointer_count = 0; + + if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY) + { + unsigned int temp = 0; + /* unfortunately, this needs to be done in two passes to avoid + * writing out redundant FC_FIXED_REPEAT descriptions */ + pointer_count = write_pointer_description_offsets( + NULL, attrs, type->ref, NULL, NULL, &temp); + if (pointer_count > 0) + { + unsigned int increment_size; + size_t offset_of_array_pointer_mem = 0; + size_t offset_of_array_pointer_buf = 0; + + align = 0; + increment_size = type_memsize(type->ref, &align); + + print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT); + print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD); + print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim); + print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size); + print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory); + print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count); + *typestring_offset += 10; + + pointer_count = write_pointer_description_offsets( + file, attrs, type, &offset_of_array_pointer_mem, + &offset_of_array_pointer_buf, typestring_offset); + } + } + else if (is_struct(type->type)) + { + const var_t *v; + LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry ) + { + pointer_count += write_fixed_array_pointer_descriptions( + file, v->attrs, v->type, offset_in_memory, offset_in_buffer, + typestring_offset); + } + } + else + { + align = 0; + if (offset_in_memory) + *offset_in_memory += type_memsize(type, &align); + /* FIXME: is there a case where these two are different? */ + align = 0; + if (offset_in_buffer) + *offset_in_buffer += type_memsize(type, &align); + } + + return pointer_count; +} + +/* Note: if file is NULL return value is number of pointers to write, else + * it is the number of type format characters written */ +static int write_conformant_array_pointer_descriptions( + FILE *file, const attr_list_t *attrs, type_t *type, + size_t offset_in_memory, unsigned int *typestring_offset) +{ + unsigned int align; + int pointer_count = 0; + + if (is_conformant_array(type) && !type->length_is) + { + unsigned int temp = 0; + /* unfortunately, this needs to be done in two passes to avoid + * writing out redundant FC_VARIABLE_REPEAT descriptions */ + pointer_count = write_pointer_description_offsets( + NULL, attrs, type->ref, NULL, NULL, &temp); + if (pointer_count > 0) + { + unsigned int increment_size; + size_t offset_of_array_pointer_mem = offset_in_memory; + size_t offset_of_array_pointer_buf = offset_in_memory; + + align = 0; + increment_size = type_memsize(type->ref, &align); + + if (increment_size > USHRT_MAX) + error("array size of %u bytes is too large\n", increment_size); + + print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT); + print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET); + print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size); + print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory); + print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count); + *typestring_offset += 8; + + pointer_count = write_pointer_description_offsets( + file, attrs, type->ref, &offset_of_array_pointer_mem, + &offset_of_array_pointer_buf, typestring_offset); + } + } + + return pointer_count; +} + +/* Note: if file is NULL return value is number of pointers to write, else + * it is the number of type format characters written */ +static int write_varying_array_pointer_descriptions( + FILE *file, const attr_list_t *attrs, type_t *type, + size_t *offset_in_memory, size_t *offset_in_buffer, + unsigned int *typestring_offset) +{ + unsigned int align; + int pointer_count = 0; + + /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */ + + if (is_array(type) && type->length_is) + { + unsigned int temp = 0; + /* unfortunately, this needs to be done in two passes to avoid + * writing out redundant FC_VARIABLE_REPEAT descriptions */ + pointer_count = write_pointer_description_offsets( + NULL, attrs, type->ref, NULL, NULL, &temp); + if (pointer_count > 0) + { + unsigned int increment_size; + size_t offset_of_array_pointer_mem = 0; + size_t offset_of_array_pointer_buf = 0; + + align = 0; + increment_size = type_memsize(type->ref, &align); + + if (increment_size > USHRT_MAX) + error("array size of %u bytes is too large\n", increment_size); + + print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT); + print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET); + print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size); + print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory); + print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count); + *typestring_offset += 8; + + pointer_count = write_pointer_description_offsets( + file, attrs, type, &offset_of_array_pointer_mem, + &offset_of_array_pointer_buf, typestring_offset); + } + } + else if (is_struct(type->type)) + { + const var_t *v; + LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry ) + { + pointer_count += write_varying_array_pointer_descriptions( + file, v->attrs, v->type, offset_in_memory, offset_in_buffer, + typestring_offset); + } + } + else + { + align = 0; + if (offset_in_memory) + *offset_in_memory += type_memsize(type, &align); + /* FIXME: is there a case where these two are different? */ + align = 0; + if (offset_in_buffer) + *offset_in_buffer += type_memsize(type, &align); + } + + return pointer_count; +} + +static void write_pointer_description(FILE *file, type_t *type, + unsigned int *typestring_offset) +{ + size_t offset_in_buffer; + size_t offset_in_memory; + + /* pass 1: search for single instance of a pointer (i.e. don't descend + * into arrays) */ + if (!is_array(type)) + { + offset_in_memory = 0; + offset_in_buffer = 0; + write_no_repeat_pointer_descriptions( + file, type, + &offset_in_memory, &offset_in_buffer, typestring_offset); + } + + /* pass 2: search for pointers in fixed arrays */ + offset_in_memory = 0; + offset_in_buffer = 0; + write_fixed_array_pointer_descriptions( + file, NULL, type, + &offset_in_memory, &offset_in_buffer, typestring_offset); + + /* pass 3: search for pointers in conformant only arrays (but don't descend + * into conformant varying or varying arrays) */ + if ((!type->declarray || !current_structure) && is_conformant_array(type)) + write_conformant_array_pointer_descriptions( + file, NULL, type, 0, typestring_offset); + else if (type->type == RPC_FC_CPSTRUCT) + { + unsigned int align = 0; + type_t *carray = find_array_or_string_in_struct(type)->type; + write_conformant_array_pointer_descriptions( + file, NULL, carray, + type_memsize(type, &align), + typestring_offset); + } + + /* pass 4: search for pointers in varying arrays */ + offset_in_memory = 0; + offset_in_buffer = 0; + write_varying_array_pointer_descriptions( + file, NULL, type, + &offset_in_memory, &offset_in_buffer, typestring_offset); +} + +int is_declptr(const type_t *t) +{ + return is_ptr(t) || (is_conformant_array(t) && !t->declarray); +} + +static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, + type_t *type, + const char *name, unsigned int *typestring_offset, + int toplevel) +{ + size_t start_offset = *typestring_offset; + unsigned char rtype; + + update_tfsoff(type, start_offset, file); + + if (toplevel && is_declptr(type)) + { + unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER; + int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE); + if (!pointer_type) + pointer_type = RPC_FC_RP; + print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n", + pointer_type, flag, string_of_type(pointer_type), + flag ? " [simple_pointer]" : ""); + *typestring_offset += 2; + if (!flag) + { + print_file(file, 2, "NdrFcShort(0x2),\n"); + *typestring_offset += 2; + } + } + + rtype = type->ref->type; + + if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR)) + { + error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name); + return start_offset; + } + + if (type->declarray && !is_conformant_array(type)) + { + /* FIXME: multi-dimensional array */ + if (0xffffuL < type->dim) + error("array size for parameter %s exceeds %u bytes by %lu bytes\n", + name, 0xffffu, type->dim - 0xffffu); + + if (rtype == RPC_FC_CHAR) + WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset); + else + WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset); + print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); + *typestring_offset += 2; + + print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim); + *typestring_offset += 2; + + return start_offset; + } + else if (type->size_is) + { + unsigned int align = 0; + + if (rtype == RPC_FC_CHAR) + WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); + else + WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset); + print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED); + *typestring_offset += 2; + + *typestring_offset += write_conf_or_var_desc( + file, current_structure, + (type->declarray && current_structure + ? type_memsize(current_structure, &align) + : 0), + type, type->size_is); + + return start_offset; + } + else + { + if (rtype == RPC_FC_WCHAR) + WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset); + else + WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); + print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); + *typestring_offset += 2; + + return start_offset; + } +} + +static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, + const char *name, unsigned int *typestring_offset) +{ + const expr_t *length_is = type->length_is; + const expr_t *size_is = type->size_is; + unsigned int align = 0; + size_t size; + size_t start_offset; + int has_pointer; + int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); + unsigned int baseoff + = type->declarray && current_structure + ? type_memsize(current_structure, &align) + : 0; + + if (!pointer_type) + pointer_type = RPC_FC_RP; + + if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset)) + has_pointer = TRUE; + else + has_pointer = type_has_pointers(type->ref); + + align = 0; + size = type_memsize((is_conformant_array(type) ? type->ref : type), &align); + + start_offset = *typestring_offset; + update_tfsoff(type, start_offset, file); + print_start_tfs_comment(file, type, start_offset); + print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type)); + print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); + *typestring_offset += 2; + + align = 0; + if (type->type != RPC_FC_BOGUS_ARRAY) + { + unsigned char tc = type->type; + + if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY) + { + print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size); + *typestring_offset += 4; + } + else + { + print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size); + *typestring_offset += 2; + } + + if (is_conformant_array(type)) + *typestring_offset + += write_conf_or_var_desc(file, current_structure, baseoff, + type, size_is); + + if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY) + { + unsigned int elalign = 0; + size_t elsize = type_memsize(type->ref, &elalign); + + if (type->type == RPC_FC_LGVARRAY) + { + print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim); + *typestring_offset += 4; + } + else + { + print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim); + *typestring_offset += 2; + } + + print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize); + *typestring_offset += 2; + } + + if (length_is) + *typestring_offset + += write_conf_or_var_desc(file, current_structure, baseoff, + type, length_is); + + if (has_pointer && (!type->declarray || !current_structure)) + { + print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); + print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); + *typestring_offset += 2; + write_pointer_description(file, type, typestring_offset); + print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); + *typestring_offset += 1; + } + + write_member_type(file, type, NULL, type->ref, NULL, typestring_offset); + write_end(file, typestring_offset); + } + else + { + unsigned int dim = size_is ? 0 : type->dim; + print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim); + *typestring_offset += 2; + *typestring_offset + += write_conf_or_var_desc(file, current_structure, baseoff, + type, size_is); + *typestring_offset + += write_conf_or_var_desc(file, current_structure, baseoff, + type, length_is); + write_member_type(file, type, NULL, type->ref, NULL, typestring_offset); + write_end(file, typestring_offset); + } + + return start_offset; +} + +static const var_t *find_array_or_string_in_struct(const type_t *type) +{ + const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry ); + const type_t *ft = last_field->type; + + if (ft->declarray && is_conformant_array(ft)) + return last_field; + + if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT) + return find_array_or_string_in_struct(last_field->type); + else + return NULL; +} + +static void write_struct_members(FILE *file, const type_t *type, + unsigned int *corroff, unsigned int *typestring_offset) +{ + const var_t *field; + unsigned short offset = 0; + int salign = -1; + int padding; + + if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) + { + type_t *ft = field->type; + if (!ft->declarray || !is_conformant_array(ft)) + { + unsigned int align = 0; + size_t size = type_memsize(ft, &align); + if (salign == -1) + salign = align; + if ((align - 1) & offset) + { + unsigned char fc = 0; + switch (align) + { + case 4: + fc = RPC_FC_ALIGNM4; + break; + case 8: + fc = RPC_FC_ALIGNM8; + break; + default: + error("write_struct_members: cannot align type %d\n", ft->type); + } + print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); + offset = (offset + (align - 1)) & ~(align - 1); + *typestring_offset += 1; + } + write_member_type(file, type, field->attrs, field->type, corroff, + typestring_offset); + offset += size; + } + } + + padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset; + if (padding) + { + print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n", + RPC_FC_STRUCTPAD1 + padding - 1, + padding); + *typestring_offset += 1; + } + + write_end(file, typestring_offset); +} + +static size_t write_struct_tfs(FILE *file, type_t *type, + const char *name, unsigned int *tfsoff) +{ + const type_t *save_current_structure = current_structure; + unsigned int total_size; + const var_t *array; + size_t start_offset; + size_t array_offset; + int has_pointers = 0; + unsigned int align = 0; + unsigned int corroff; + var_t *f; + + guard_rec(type); + current_structure = type; + + total_size = type_memsize(type, &align); + if (total_size > USHRT_MAX) + error("structure size for %s exceeds %d bytes by %d bytes\n", + name, USHRT_MAX, total_size - USHRT_MAX); + + if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry) + has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name, + FALSE, tfsoff); + if (!has_pointers) has_pointers = type_has_pointers(type); + + array = find_array_or_string_in_struct(type); + if (array && !processed(array->type)) + array_offset + = is_attr(array->attrs, ATTR_STRING) + ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff, FALSE) + : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff); + + corroff = *tfsoff; + write_descriptors(file, type, tfsoff); + + start_offset = *tfsoff; + update_tfsoff(type, start_offset, file); + print_start_tfs_comment(file, type, start_offset); + print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type)); + print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size); + *tfsoff += 4; + + if (array) + { + unsigned int absoff = array->type->typestring_offset; + short reloff = absoff - *tfsoff; + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", + reloff, reloff, absoff); + *tfsoff += 2; + } + else if (type->type == RPC_FC_BOGUS_STRUCT) + { + print_file(file, 2, "NdrFcShort(0x0),\n"); + *tfsoff += 2; + } + + if (type->type == RPC_FC_BOGUS_STRUCT) + { + /* On the sizing pass, type->ptrdesc may be zero, but it's ok as + nothing is written to file yet. On the actual writing pass, + this will have been updated. */ + unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff; + short reloff = absoff - *tfsoff; + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); + *tfsoff += 2; + } + else if ((type->type == RPC_FC_PSTRUCT) || + (type->type == RPC_FC_CPSTRUCT) || + (type->type == RPC_FC_CVSTRUCT && has_pointers)) + { + print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); + print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); + *tfsoff += 2; + write_pointer_description(file, type, tfsoff); + print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); + *tfsoff += 1; + } + + write_struct_members(file, type, &corroff, tfsoff); + + if (type->type == RPC_FC_BOGUS_STRUCT) + { + const var_list_t *fs = type->fields; + const var_t *f; + + type->ptrdesc = *tfsoff; + if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry) + { + type_t *ft = f->type; + if (is_ptr(ft)) + write_pointer_tfs(file, ft, tfsoff); + else if (!ft->declarray && is_conformant_array(ft)) + { + unsigned int absoff = ft->typestring_offset; + short reloff = absoff - (*tfsoff + 2); + int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE); + /* FIXME: We need to store pointer attributes for arrays + so we don't lose pointer_default info. */ + if (ptr_type == 0) + ptr_type = RPC_FC_UP; + print_file(file, 0, "/* %d */\n", *tfsoff); + print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type, + string_of_type(ptr_type)); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); + *tfsoff += 4; + } + } + if (type->ptrdesc == *tfsoff) + type->ptrdesc = 0; + } + + current_structure = save_current_structure; + return start_offset; +} + +static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type, + unsigned char flags, size_t offset, + unsigned int *typeformat_offset) +{ + size_t start_offset = *typeformat_offset; + short reloff = offset - (*typeformat_offset + 2); + int in_attr, out_attr; + in_attr = is_attr(attrs, ATTR_IN); + out_attr = is_attr(attrs, ATTR_OUT); + if (!in_attr && !out_attr) in_attr = 1; + + if (out_attr && !in_attr && pointer_type == RPC_FC_RP) + flags |= 0x04; + + print_file(file, 2, "0x%x, 0x%x,\t\t/* %s", + pointer_type, + flags, + string_of_type(pointer_type)); + if (file) + { + if (flags & 0x04) + fprintf(file, " [allocated_on_stack]"); + if (flags & 0x10) + fprintf(file, " [pointer_deref]"); + fprintf(file, " */\n"); + } + + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset); + *typeformat_offset += 4; + + return start_offset; +} + +static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff) +{ + if (t == NULL) + { + print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n"); + } + else if (is_base_type(t->type)) + { + print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n", + t->type, string_of_type(t->type)); + } + else if (t->typestring_offset) + { + short reloff = t->typestring_offset - *tfsoff; + print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n", + reloff, reloff, t->typestring_offset); + } + else + error("write_branch_type: type unimplemented (0x%x)\n", t->type); + + *tfsoff += 2; +} + +static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff) +{ + unsigned int align = 0; + unsigned int start_offset; + size_t size = type_memsize(type, &align); + var_list_t *fields; + size_t nbranch = 0; + type_t *deftype = NULL; + short nodeftype = 0xffff; + var_t *f; + + guard_rec(type); + + if (type->type == RPC_FC_ENCAPSULATED_UNION) + { + const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry); + fields = uv->type->fields; + } + else + fields = type->fields; + + if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) + { + expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); + if (cases) + nbranch += list_count(cases); + if (f->type) + write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff); + } + + start_offset = *tfsoff; + update_tfsoff(type, start_offset, file); + print_start_tfs_comment(file, type, start_offset); + if (type->type == RPC_FC_ENCAPSULATED_UNION) + { + const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry); + const type_t *st = sv->type; + + switch (st->type) + { + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type)); + print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", + 0x40 | st->type, string_of_type(st->type)); + *tfsoff += 2; + break; + default: + error("union switch type must be an integer, char, or enum\n"); + } + } + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size); + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch); + *tfsoff += 4; + + if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) + { + type_t *ft = f->type; + expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); + int deflt = is_attr(f->attrs, ATTR_DEFAULT); + expr_t *c; + + if (cases == NULL && !deflt) + error("union field %s with neither case nor default attribute\n", f->name); + + if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry) + { + /* MIDL doesn't check for duplicate cases, even though that seems + like a reasonable thing to do, it just dumps them to the TFS + like we're going to do here. */ + print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval); + *tfsoff += 4; + write_branch_type(file, ft, tfsoff); + } + + /* MIDL allows multiple default branches, even though that seems + illogical, it just chooses the last one, which is what we will + do. */ + if (deflt) + { + deftype = ft; + nodeftype = 0; + } + } + + if (deftype) + { + write_branch_type(file, deftype, tfsoff); + } + else + { + print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype); + *tfsoff += 2; + } + + return start_offset; +} + +static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type, + unsigned int *typeformat_offset) +{ + size_t i; + size_t start_offset = *typeformat_offset; + expr_t *iid = get_attrp(attrs, ATTR_IIDIS); + + if (iid) + { + print_file(file, 2, "0x2f, /* FC_IP */\n"); + print_file(file, 2, "0x5c, /* FC_PAD */\n"); + *typeformat_offset + += write_conf_or_var_desc(file, NULL, 0, type, iid) + 2; + } + else + { + const type_t *base = is_ptr(type) ? type->ref : type; + const UUID *uuid = get_attrp(base->attrs, ATTR_UUID); + + if (! uuid) + error("%s: interface %s missing UUID\n", __FUNCTION__, base->name); + + update_tfsoff(type, start_offset, file); + print_start_tfs_comment(file, type, start_offset); + print_file(file, 2, "0x2f,\t/* FC_IP */\n"); + print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n"); + print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1); + print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2); + print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3); + for (i = 0; i < 8; ++i) + print_file(file, 2, "0x%02x,\n", uuid->Data4[i]); + + if (file) + fprintf(file, "\n"); + + *typeformat_offset += 18; + } + return start_offset; +} + +static size_t write_contexthandle_tfs(FILE *file, const type_t *type, + const var_t *var, + unsigned int *typeformat_offset) +{ + size_t start_offset = *typeformat_offset; + unsigned char flags = 0x08 /* strict */; + + if (is_ptr(type)) + { + flags |= 0x80; + if (type->type != RPC_FC_RP) + flags |= 0x01; + } + if (is_attr(var->attrs, ATTR_IN)) + flags |= 0x40; + if (is_attr(var->attrs, ATTR_OUT)) + flags |= 0x20; + + WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset); + print_file(file, 2, "0x%x,\t/* Context flags: ", flags); + if (((flags & 0x21) != 0x21) && (flags & 0x01)) + print_file(file, 0, "can't be null, "); + if (flags & 0x02) + print_file(file, 0, "serialize, "); + if (flags & 0x04) + print_file(file, 0, "no serialize, "); + if (flags & 0x08) + print_file(file, 0, "strict, "); + if ((flags & 0x21) == 0x20) + print_file(file, 0, "out, "); + if ((flags & 0x21) == 0x21) + print_file(file, 0, "return, "); + if (flags & 0x40) + print_file(file, 0, "in, "); + if (flags & 0x80) + print_file(file, 0, "via ptr, "); + print_file(file, 0, "*/\n"); + print_file(file, 2, "0, /* FIXME: rundown routine index*/\n"); + print_file(file, 2, "0, /* FIXME: param num */\n"); + *typeformat_offset += 4; + + return start_offset; +} + +static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func, + type_t *type, const var_t *var, + unsigned int *typeformat_offset) +{ + size_t offset; + + if (is_context_handle(type)) + return write_contexthandle_tfs(file, type, var, typeformat_offset); + + if (is_user_type(type)) + { + write_user_tfs(file, type, typeformat_offset); + return type->typestring_offset; + } + + if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING)) + return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset, TRUE); + + if (is_array(type)) + { + int ptr_type; + size_t off; + off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset); + ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE); + /* Top level pointers to conformant arrays may be handled specially + since we can bypass the pointer, but if the array is burried + beneath another pointer (e.g., "[size_is(,n)] int **p" then we + always need to write the pointer. */ + if (!ptr_type && var->type != type) + /* FIXME: This should use pointer_default, but the information + isn't kept around for arrays. */ + ptr_type = RPC_FC_UP; + if (ptr_type && ptr_type != RPC_FC_RP) + { + unsigned int absoff = type->typestring_offset; + short reloff = absoff - (*typeformat_offset + 2); + off = *typeformat_offset; + print_file(file, 0, "/* %d */\n", off); + print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type, + string_of_type(ptr_type)); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", + reloff, reloff, absoff); + *typeformat_offset += 4; + } + return off; + } + + if (!is_ptr(type)) + { + /* basic types don't need a type format string */ + if (is_base_type(type->type)) + return 0; + + switch (type->type) + { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_BOGUS_STRUCT: + return write_struct_tfs(file, type, var->name, typeformat_offset); + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + return write_union_tfs(file, type, typeformat_offset); + case RPC_FC_IGNORE: + case RPC_FC_BIND_PRIMITIVE: + /* nothing to do */ + return 0; + default: + error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name); + } + } + else if (last_ptr(type)) + { + size_t start_offset = *typeformat_offset; + int in_attr = is_attr(var->attrs, ATTR_IN); + int out_attr = is_attr(var->attrs, ATTR_OUT); + const type_t *base = type->ref; + + if (base->type == RPC_FC_IP + || (base->type == 0 + && is_attr(var->attrs, ATTR_IIDIS))) + { + return write_ip_tfs(file, var->attrs, type, typeformat_offset); + } + + /* special case for pointers to base types */ + if (is_base_type(base->type)) + { + print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n", + type->type, (!in_attr && out_attr) ? 0x0C : 0x08, + string_of_type(type->type), + (!in_attr && out_attr) ? "[allocated_on_stack] " : ""); + print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type)); + print_file(file, indent, "0x5c, /* FC_PAD */\n"); + *typeformat_offset += 4; + return start_offset; + } + } + + assert(is_ptr(type)); + + offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset); + if (file) + fprintf(file, "/* %2u */\n", *typeformat_offset); + return write_pointer_only_tfs(file, var->attrs, type->type, + !last_ptr(type) ? 0x10 : 0, + offset, typeformat_offset); +} + +static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, + const char *name, int write_ptr, unsigned int *tfsoff) +{ + int retmask = 0; + + if (is_user_type(type)) + { + write_user_tfs(file, type, tfsoff); + } + else if (is_ptr(type)) + { + type_t *ref = type->ref; + + if (ref->type == RPC_FC_IP + || (ref->type == 0 + && is_attr(attrs, ATTR_IIDIS))) + { + write_ip_tfs(file, attrs, type, tfsoff); + } + else + { + if (!processed(ref) && !is_base_type(ref->type)) + retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff); + + if (write_ptr) + write_pointer_tfs(file, type, tfsoff); + + retmask |= 1; + } + } + else if (last_array(type) && is_attr(attrs, ATTR_STRING)) + { + write_string_tfs(file, attrs, type, name, tfsoff, FALSE); + } + else if (type->declarray && is_conformant_array(type)) + ; /* conformant arrays and strings are handled specially */ + else if (is_array(type)) + { + write_array_tfs(file, attrs, type, name, tfsoff); + if (is_conformant_array(type)) + retmask |= 1; + } + else if (is_struct(type->type)) + { + if (!processed(type)) + write_struct_tfs(file, type, name, tfsoff); + } + else if (is_union(type->type)) + { + if (!processed(type)) + write_union_tfs(file, type, tfsoff); + } + else if (!is_base_type(type->type)) + error("write_embedded_types: unknown embedded type for %s (0x%x)\n", + name, type->type); + + return retmask; +} + +static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred) +{ + const var_t *var; + const ifref_t *iface; + unsigned int typeformat_offset = 2; + + if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry ) + { + if (!pred(iface->iface)) + continue; + + if (iface->iface->funcs) + { + const func_t *func; + LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry ) + { + if (is_local(func->def->attrs)) continue; + + current_func = func; + if (func->args) + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + update_tfsoff( + var->type, + write_typeformatstring_var( + file, 2, func, var->type, var, + &typeformat_offset), + file); + } + } + } + + return typeformat_offset + 1; +} + + +void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred) +{ + int indent = 0; + + print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); + print_file(file, indent, "{\n"); + indent++; + print_file(file, indent, "0,\n"); + print_file(file, indent, "{\n"); + indent++; + print_file(file, indent, "NdrFcShort(0x0),\n"); + + set_all_tfswrite(TRUE); + process_tfs(file, ifaces, pred); + + print_file(file, indent, "0x0\n"); + indent--; + print_file(file, indent, "}\n"); + indent--; + print_file(file, indent, "};\n"); + print_file(file, indent, "\n"); +} + +static unsigned int get_required_buffer_size_type( + const type_t *type, const char *name, unsigned int *alignment) +{ + *alignment = 0; + if (is_user_type(type)) + { + const char *uname; + const type_t *utype = get_user_type(type, &uname); + return get_required_buffer_size_type(utype, uname, alignment); + } + else + { + switch (type->type) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_USMALL: + case RPC_FC_SMALL: + *alignment = 4; + return 1; + + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + case RPC_FC_ENUM16: + *alignment = 4; + return 2; + + case RPC_FC_ULONG: + case RPC_FC_LONG: + case RPC_FC_ENUM32: + case RPC_FC_FLOAT: + case RPC_FC_ERROR_STATUS_T: + *alignment = 4; + return 4; + + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + *alignment = 8; + return 8; + + case RPC_FC_IGNORE: + case RPC_FC_BIND_PRIMITIVE: + return 0; + + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + { + size_t size = 0; + const var_t *field; + if (!type->fields) return 0; + LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) + { + unsigned int alignment; + size += get_required_buffer_size_type(field->type, field->name, + &alignment); + } + return size; + } + + case RPC_FC_RP: + return + is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT + ? get_required_buffer_size_type( type->ref, name, alignment ) + : 0; + + case RPC_FC_SMFARRAY: + case RPC_FC_LGFARRAY: + return type->dim * get_required_buffer_size_type(type->ref, name, alignment); + + default: + return 0; + } + } +} + +static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass) +{ + int in_attr = is_attr(var->attrs, ATTR_IN); + int out_attr = is_attr(var->attrs, ATTR_OUT); + const type_t *t; + + if (!in_attr && !out_attr) + in_attr = 1; + + *alignment = 0; + + for (t = var->type; is_ptr(t); t = t->ref) + if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) + { + *alignment = 4; + return 20; + } + + if (pass == PASS_OUT) + { + if (out_attr && is_ptr(var->type)) + { + type_t *type = var->type; + + if (type->type == RPC_FC_STRUCT) + { + const var_t *field; + unsigned int size = 36; + + if (!type->fields) return size; + LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) + { + unsigned int align; + size += get_required_buffer_size_type( + field->type, field->name, &align); + } + return size; + } + } + return 0; + } + else + { + if ((!out_attr || in_attr) && !var->type->size_is + && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray) + { + if (is_ptr(var->type)) + { + type_t *type = var->type; + + if (is_base_type(type->type)) + { + return 25; + } + else if (type->type == RPC_FC_STRUCT) + { + unsigned int size = 36; + const var_t *field; + + if (!type->fields) return size; + LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) + { + unsigned int align; + size += get_required_buffer_size_type( + field->type, field->name, &align); + } + return size; + } + } + } + + return get_required_buffer_size_type(var->type, var->name, alignment); + } +} + +static unsigned int get_function_buffer_size( const func_t *func, enum pass pass ) +{ + const var_t *var; + unsigned int total_size = 0, alignment; + + if (func->args) + { + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + { + total_size += get_required_buffer_size(var, &alignment, pass); + total_size += alignment; + } + } + + if (pass == PASS_OUT && !is_void(func->def->type)) + { + total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN); + total_size += alignment; + } + return total_size; +} + +static void print_phase_function(FILE *file, int indent, const char *type, + enum remoting_phase phase, + const var_t *var, unsigned int type_offset) +{ + const char *function; + switch (phase) + { + case PHASE_BUFFERSIZE: + function = "BufferSize"; + break; + case PHASE_MARSHAL: + function = "Marshall"; + break; + case PHASE_UNMARSHAL: + function = "Unmarshall"; + break; + case PHASE_FREE: + function = "Free"; + break; + default: + assert(0); + return; + } + + print_file(file, indent, "Ndr%s%s(\n", type, function); + indent++; + print_file(file, indent, "&_StubMsg,\n"); + print_file(file, indent, "%s%s%s%s,\n", + (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)", + (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "", + (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "", + var->name); + print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n", + type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");"); + if (phase == PHASE_UNMARSHAL) + print_file(file, indent, "0);\n"); + indent--; +} + +void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, + enum pass pass, const var_t *var, + const char *varname) +{ + type_t *type = var->type; + unsigned int size; + unsigned int alignment = 0; + unsigned char rtype; + + /* no work to do for other phases, buffer sizing is done elsewhere */ + if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL) + return; + + rtype = is_ptr(type) ? type->ref->type : type->type; + + switch (rtype) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + size = 1; + alignment = 1; + break; + + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + case RPC_FC_ENUM16: + size = 2; + alignment = 2; + break; + + case RPC_FC_ULONG: + case RPC_FC_LONG: + case RPC_FC_ENUM32: + case RPC_FC_FLOAT: + case RPC_FC_ERROR_STATUS_T: + size = 4; + alignment = 4; + break; + + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + size = 8; + alignment = 8; + break; + + case RPC_FC_IGNORE: + case RPC_FC_BIND_PRIMITIVE: + /* no marshalling needed */ + return; + + default: + error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype); + size = 0; + } + + if (phase == PHASE_MARSHAL) + print_file(file, indent, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1); + print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n", + alignment - 1, alignment - 1); + + if (phase == PHASE_MARSHAL) + { + print_file(file, indent, "*("); + write_type_decl(file, is_ptr(type) ? type->ref : type, NULL); + if (is_ptr(type)) + fprintf(file, " *)_StubMsg.Buffer = *"); + else + fprintf(file, " *)_StubMsg.Buffer = "); + fprintf(file, "%s", varname); + fprintf(file, ";\n"); + } + else if (phase == PHASE_UNMARSHAL) + { + print_file(file, indent, "if (_StubMsg.Buffer + sizeof("); + write_type_decl(file, is_ptr(type) ? type->ref : type, NULL); + fprintf(file, ") > _StubMsg.BufferEnd)\n"); + print_file(file, indent, "{\n"); + print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); + print_file(file, indent, "}\n"); + if (pass == PASS_IN || pass == PASS_RETURN) + print_file(file, indent, ""); + else + print_file(file, indent, "*"); + fprintf(file, "%s", varname); + if (pass == PASS_IN && is_ptr(type)) + fprintf(file, " = ("); + else + fprintf(file, " = *("); + write_type_decl(file, is_ptr(type) ? type->ref : type, NULL); + fprintf(file, " *)_StubMsg.Buffer;\n"); + } + + print_file(file, indent, "_StubMsg.Buffer += sizeof("); + write_type_decl(file, var->type, NULL); + fprintf(file, ");\n"); +} + +/* returns whether the MaxCount, Offset or ActualCount members need to be + * filled in for the specified phase */ +static inline int is_size_needed_for_phase(enum remoting_phase phase) +{ + return (phase != PHASE_UNMARSHAL); +} + +expr_t *get_size_is_expr(const type_t *t, const char *name) +{ + expr_t *x = NULL; + + for ( ; is_ptr(t) || is_array(t); t = t->ref) + if (t->size_is) + { + if (!x) + x = t->size_is; + else + error("%s: multidimensional conformant" + " arrays not supported at the top level\n", + name); + } + + return x; +} + +static void write_remoting_arg(FILE *file, int indent, const func_t *func, + enum pass pass, enum remoting_phase phase, + const var_t *var) +{ + int in_attr, out_attr, pointer_type; + const type_t *type = var->type; + unsigned char rtype; + size_t start_offset = type->typestring_offset; + + pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE); + if (!pointer_type) + pointer_type = RPC_FC_RP; + + in_attr = is_attr(var->attrs, ATTR_IN); + out_attr = is_attr(var->attrs, ATTR_OUT); + if (!in_attr && !out_attr) + in_attr = 1; + + if (phase != PHASE_FREE) + switch (pass) + { + case PASS_IN: + if (!in_attr) return; + break; + case PASS_OUT: + if (!out_attr) return; + break; + case PASS_RETURN: + break; + } + + rtype = type->type; + + if (is_context_handle(type)) + { + if (phase == PHASE_MARSHAL) + { + if (pass == PASS_IN) + { + print_file(file, indent, "NdrClientContextMarshall(\n"); + print_file(file, indent + 1, "&_StubMsg,\n"); + print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name); + print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0"); + } + else + { + print_file(file, indent, "NdrServerContextMarshall(\n"); + print_file(file, indent + 1, "&_StubMsg,\n"); + print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name); + print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type)); + } + } + else if (phase == PHASE_UNMARSHAL) + { + if (pass == PASS_OUT) + { + print_file(file, indent, "NdrClientContextUnmarshall(\n"); + print_file(file, indent + 1, "&_StubMsg,\n"); + print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name); + print_file(file, indent + 1, "_Handle);\n"); + } + else + print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name); + } + } + else if (is_user_type(var->type)) + { + print_phase_function(file, indent, "UserMarshal", phase, var, start_offset); + } + else if (is_string_type(var->attrs, var->type)) + { + if (is_array(type) && !is_conformant_array(type)) + print_phase_function(file, indent, "NonConformantString", phase, var, start_offset); + else + { + if (type->size_is && is_size_needed_for_phase(phase)) + { + print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)"); + write_expr(file, type->size_is, 1); + fprintf(file, ";\n"); + } + + if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP)) + print_phase_function(file, indent, "Pointer", phase, var, start_offset); + else + print_phase_function(file, indent, "ConformantString", phase, var, + start_offset + (type->size_is ? 4 : 2)); + } + } + else if (is_array(type)) + { + unsigned char tc = type->type; + const char *array_type = "FixedArray"; + + /* We already have the size_is expression since it's at the + top level, but do checks for multidimensional conformant + arrays. When we handle them, we'll need to extend this + function to return a list, and then we'll actually use + the return value. */ + get_size_is_expr(type, var->name); + + if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY) + { + if (is_size_needed_for_phase(phase)) + { + print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */ + print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)"); + write_expr(file, type->length_is, 1); + fprintf(file, ";\n\n"); + } + array_type = "VaryingArray"; + } + else if (tc == RPC_FC_CARRAY) + { + if (is_size_needed_for_phase(phase)) + { + print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)"); + write_expr(file, type->size_is, 1); + fprintf(file, ";\n\n"); + } + array_type = "ConformantArray"; + } + else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY) + { + if (is_size_needed_for_phase(phase)) + { + if (type->size_is) + { + print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)"); + write_expr(file, type->size_is, 1); + fprintf(file, ";\n"); + } + if (type->length_is) + { + print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */ + print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)"); + write_expr(file, type->length_is, 1); + fprintf(file, ";\n\n"); + } + } + array_type = (tc == RPC_FC_BOGUS_ARRAY + ? "ComplexArray" + : "ConformantVaryingArray"); + } + + if (pointer_type != RPC_FC_RP) array_type = "Pointer"; + print_phase_function(file, indent, array_type, phase, var, start_offset); + if (phase == PHASE_FREE && type->declarray && pointer_type == RPC_FC_RP) + { + /* these are all unmarshalled by pointing into the buffer on the + * server side */ + if (type->type == RPC_FC_BOGUS_ARRAY || + type->type == RPC_FC_CVARRAY || + (type->type == RPC_FC_SMVARRAY && type->type == RPC_FC_LGVARRAY && in_attr) || + (type->type == RPC_FC_CARRAY && type->type == RPC_FC_CARRAY && !in_attr)) + { + print_file(file, indent, "if (%s)\n", var->name); + indent++; + print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name); + } + } + } + else if (!is_ptr(var->type) && is_base_type(rtype)) + { + if (phase != PHASE_FREE) + print_phase_basetype(file, indent, phase, pass, var, var->name); + } + else if (!is_ptr(var->type)) + { + switch (rtype) + { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset); + break; + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset); + break; + case RPC_FC_CVSTRUCT: + print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset); + break; + case RPC_FC_BOGUS_STRUCT: + print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset); + break; + case RPC_FC_RP: + if (is_base_type( var->type->ref->type )) + { + print_phase_basetype(file, indent, phase, pass, var, var->name); + } + else if (var->type->ref->type == RPC_FC_STRUCT) + { + if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE) + print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4); + } + else + { + expr_t *iid; + if ((iid = get_attrp( var->attrs, ATTR_IIDIS ))) + { + print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " ); + write_expr( file, iid, 1 ); + fprintf( file, ";\n\n" ); + } + print_phase_function(file, indent, "Pointer", phase, var, start_offset); + } + break; + default: + error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype); + } + } + else + { + if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype)) + { + if (phase != PHASE_FREE) + print_phase_basetype(file, indent, phase, pass, var, var->name); + } + else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT)) + { + if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE) + print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4); + } + else + { + expr_t *iid; + expr_t *sx = get_size_is_expr(type, var->name); + + if ((iid = get_attrp( var->attrs, ATTR_IIDIS ))) + { + print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " ); + write_expr( file, iid, 1 ); + fprintf( file, ";\n\n" ); + } + else if (sx) + { + print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) "); + write_expr(file, sx, 1); + fprintf(file, ";\n\n"); + } + if (var->type->ref->type == RPC_FC_IP) + print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset); + else + print_phase_function(file, indent, "Pointer", phase, var, start_offset); + } + } + fprintf(file, "\n"); +} + +void write_remoting_arguments(FILE *file, int indent, const func_t *func, + enum pass pass, enum remoting_phase phase) +{ + if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN) + { + unsigned int size = get_function_buffer_size( func, pass ); + print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size); + } + + if (pass == PASS_RETURN) + { + var_t var; + var = *func->def; + var.name = xstrdup( "_RetVal" ); + write_remoting_arg( file, indent, func, pass, phase, &var ); + free( var.name ); + } + else + { + const var_t *var; + if (!func->args) + return; + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + write_remoting_arg( file, indent, func, pass, phase, var ); + } +} + + +size_t get_size_procformatstring_var(const var_t *var) +{ + return write_procformatstring_var(NULL, 0, var, FALSE); +} + + +size_t get_size_procformatstring_func(const func_t *func) +{ + const var_t *var; + size_t size = 0; + + /* argument list size */ + if (func->args) + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + size += get_size_procformatstring_var(var); + + /* return value size */ + if (is_void(func->def->type)) + size += 2; /* FC_END and FC_PAD */ + else + size += get_size_procformatstring_var(func->def); + + return size; +} + +size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred) +{ + const ifref_t *iface; + size_t size = 1; + const func_t *func; + + if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry ) + { + if (!pred(iface->iface)) + continue; + + if (iface->iface->funcs) + LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry ) + if (!is_local(func->def->attrs)) + size += get_size_procformatstring_func( func ); + } + return size; +} + +size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred) +{ + set_all_tfswrite(FALSE); + return process_tfs(NULL, ifaces, pred); +} + +static void write_struct_expr(FILE *h, const expr_t *e, int brackets, + const var_list_t *fields, const char *structvar) +{ + switch (e->type) { + case EXPR_VOID: + break; + case EXPR_NUM: + fprintf(h, "%lu", e->u.lval); + break; + case EXPR_HEXNUM: + fprintf(h, "0x%lx", e->u.lval); + break; + case EXPR_DOUBLE: + fprintf(h, "%#.15g", e->u.dval); + break; + case EXPR_TRUEFALSE: + if (e->u.lval == 0) + fprintf(h, "FALSE"); + else + fprintf(h, "TRUE"); + break; + case EXPR_IDENTIFIER: + { + const var_t *field; + LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) + if (!strcmp(e->u.sval, field->name)) + { + fprintf(h, "%s->%s", structvar, e->u.sval); + break; + } + + if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval); + break; + } + case EXPR_NEG: + fprintf(h, "-"); + write_struct_expr(h, e->ref, 1, fields, structvar); + break; + case EXPR_NOT: + fprintf(h, "~"); + write_struct_expr(h, e->ref, 1, fields, structvar); + break; + case EXPR_PPTR: + fprintf(h, "*"); + write_struct_expr(h, e->ref, 1, fields, structvar); + break; + case EXPR_CAST: + fprintf(h, "("); + write_type_decl(h, e->u.tref, NULL); + fprintf(h, ")"); + write_struct_expr(h, e->ref, 1, fields, structvar); + break; + case EXPR_SIZEOF: + fprintf(h, "sizeof("); + write_type_decl(h, e->u.tref, NULL); + fprintf(h, ")"); + break; + case EXPR_SHL: + case EXPR_SHR: + case EXPR_MUL: + case EXPR_DIV: + case EXPR_ADD: + case EXPR_SUB: + case EXPR_AND: + case EXPR_OR: + if (brackets) fprintf(h, "("); + write_struct_expr(h, e->ref, 1, fields, structvar); + switch (e->type) { + case EXPR_SHL: fprintf(h, " << "); break; + case EXPR_SHR: fprintf(h, " >> "); break; + case EXPR_MUL: fprintf(h, " * "); break; + case EXPR_DIV: fprintf(h, " / "); break; + case EXPR_ADD: fprintf(h, " + "); break; + case EXPR_SUB: fprintf(h, " - "); break; + case EXPR_AND: fprintf(h, " & "); break; + case EXPR_OR: fprintf(h, " | "); break; + default: break; + } + write_struct_expr(h, e->u.ext, 1, fields, structvar); + if (brackets) fprintf(h, ")"); + break; + case EXPR_COND: + if (brackets) fprintf(h, "("); + write_struct_expr(h, e->ref, 1, fields, structvar); + fprintf(h, " ? "); + write_struct_expr(h, e->u.ext, 1, fields, structvar); + fprintf(h, " : "); + write_struct_expr(h, e->ext2, 1, fields, structvar); + if (brackets) fprintf(h, ")"); + break; + case EXPR_ADDRESSOF: + fprintf(h, "&"); + write_struct_expr(h, e->ref, 1, fields, structvar); + break; + } +} + + +void declare_stub_args( FILE *file, int indent, const func_t *func ) +{ + int in_attr, out_attr; + int i = 0; + const var_t *def = func->def; + const var_t *var; + + /* declare return value '_RetVal' */ + if (!is_void(def->type)) + { + print_file(file, indent, ""); + write_type_decl_left(file, def->type); + fprintf(file, " _RetVal;\n"); + } + + if (!func->args) + return; + + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + { + int is_string = is_attr(var->attrs, ATTR_STRING); + + in_attr = is_attr(var->attrs, ATTR_IN); + out_attr = is_attr(var->attrs, ATTR_OUT); + if (!out_attr && !in_attr) + in_attr = 1; + + if (is_context_handle(var->type)) + print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); + else + { + if (!in_attr && !var->type->size_is && !is_string) + { + print_file(file, indent, ""); + write_type_decl(file, var->type->declarray ? var->type : var->type->ref, + "_W%u", i++); + fprintf(file, ";\n"); + } + + print_file(file, indent, ""); + write_type_decl_left(file, var->type); + fprintf(file, " "); + if (var->type->declarray) { + fprintf(file, "( *"); + write_name(file, var); + fprintf(file, " )"); + } else + write_name(file, var); + write_type_right(file, var->type, FALSE); + fprintf(file, ";\n"); + + if (decl_indirect(var->type)) + print_file(file, indent, "void *_p_%s = &%s;\n", + var->name, var->name); + } + } +} + + +void assign_stub_out_args( FILE *file, int indent, const func_t *func ) +{ + int in_attr, out_attr; + int i = 0, sep = 0; + const var_t *var; + + if (!func->args) + return; + + LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) + { + int is_string = is_attr(var->attrs, ATTR_STRING); + in_attr = is_attr(var->attrs, ATTR_IN); + out_attr = is_attr(var->attrs, ATTR_OUT); + if (!out_attr && !in_attr) + in_attr = 1; + + if (!in_attr) + { + print_file(file, indent, ""); + write_name(file, var); + + if (is_context_handle(var->type)) + { + fprintf(file, " = NdrContextHandleInitialize(\n"); + print_file(file, indent + 1, "&_StubMsg,\n"); + print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", + var->type->typestring_offset); + } + else if (var->type->size_is) + { + unsigned int size, align = 0; + type_t *type = var->type; + + fprintf(file, " = NdrAllocate(&_StubMsg, "); + for ( ; type->size_is ; type = type->ref) + { + write_expr(file, type->size_is, TRUE); + fprintf(file, " * "); + } + size = type_memsize(type, &align); + fprintf(file, "%u);\n", size); + } + else if (!is_string) + { + fprintf(file, " = &_W%u;\n", i); + if (is_ptr(var->type) && !last_ptr(var->type)) + print_file(file, indent, "_W%u = 0;\n", i); + i++; + } + + sep = 1; + } + } + if (sep) + fprintf(file, "\n"); +} + + +int write_expr_eval_routines(FILE *file, const char *iface) +{ + static const char *var_name = "pS"; + int result = 0; + struct expr_eval_routine *eval; + unsigned short callback_offset = 0; + + LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) + { + const char *name = eval->structure->name; + const var_list_t *fields = eval->structure->fields; + result = 1; + + print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n", + iface, name, callback_offset); + print_file(file, 0, "{\n"); + print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n", + name, var_name, name, eval->baseoff); + print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ + print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)"); + write_struct_expr(file, eval->expr, 1, fields, var_name); + fprintf(file, ";\n"); + print_file(file, 0, "}\n\n"); + callback_offset++; + } + return result; +} + +void write_expr_eval_routine_list(FILE *file, const char *iface) +{ + struct expr_eval_routine *eval; + struct expr_eval_routine *cursor; + unsigned short callback_offset = 0; + + fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n"); + fprintf(file, "{\n"); + + LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry) + { + const char *name = eval->structure->name; + print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset); + callback_offset++; + list_remove(&eval->entry); + free(eval); + } + + fprintf(file, "};\n\n"); +} + +void write_user_quad_list(FILE *file) +{ + user_type_t *ut; + + if (list_empty(&user_type_list)) + return; + + fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n"); + fprintf(file, "{\n"); + LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) + { + const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ","; + print_file(file, 1, "{\n"); + print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name); + print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name); + print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name); + print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name); + print_file(file, 1, "}%s\n", sep); + } + fprintf(file, "};\n\n"); +} + +void write_endpoints( FILE *f, const char *prefix, const str_list_t *list ) +{ + const struct str_list_entry_t *endpoint; + const char *p; + + /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */ + print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix ); + LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry ) + { + print_file( f, 1, "{ (const unsigned char *)\"" ); + for (p = endpoint->str; *p && *p != ':'; p++) + { + if (*p == '"' || *p == '\\') fputc( '\\', f ); + fputc( *p, f ); + } + if (!*p) goto error; + if (p[1] != '[') goto error; + + fprintf( f, "\", (const unsigned char *)\"" ); + for (p += 2; *p && *p != ']'; p++) + { + if (*p == '"' || *p == '\\') fputc( '\\', f ); + fputc( *p, f ); + } + if (*p != ']') goto error; + fprintf( f, "\" },\n" ); + } + print_file( f, 0, "};\n\n" ); + return; + +error: + error("Invalid endpoint syntax '%s'\n", endpoint->str); +} diff --git a/reactos/tools/widl_20080105/typegen.h b/reactos/tools/widl_20080105/typegen.h new file mode 100644 index 00000000000..c9a5148290f --- /dev/null +++ b/reactos/tools/widl_20080105/typegen.h @@ -0,0 +1,62 @@ +/* + * Format String Generator for IDL Compiler + * + * Copyright 2005-2006 Eric Kohl + * Copyright 2005 Robert Shearman + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +enum pass +{ + PASS_IN, + PASS_OUT, + PASS_RETURN +}; + +enum remoting_phase +{ + PHASE_BUFFERSIZE, + PHASE_MARSHAL, + PHASE_UNMARSHAL, + PHASE_FREE +}; + +typedef int (*type_pred_t)(const type_t *); + +void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred); +void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred); +void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred); +void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, enum pass pass, const var_t *var, const char *varname); +void write_remoting_arguments(FILE *file, int indent, const func_t *func, enum pass pass, enum remoting_phase phase); +size_t get_size_procformatstring_var(const var_t *var); +size_t get_size_procformatstring_func(const func_t *func); +size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred); +size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred); +void assign_stub_out_args( FILE *file, int indent, const func_t *func ); +void declare_stub_args( FILE *file, int indent, const func_t *func ); +int write_expr_eval_routines(FILE *file, const char *iface); +void write_expr_eval_routine_list(FILE *file, const char *iface); +void write_user_quad_list(FILE *file); +void write_endpoints( FILE *f, const char *prefix, const str_list_t *list ); +size_t type_memsize(const type_t *t, unsigned int *align); +int decl_indirect(const type_t *t); +void write_parameters_init(FILE *file, int indent, const func_t *func); +void print(FILE *file, int indent, const char *format, va_list ap); +int get_padding(const var_list_t *fields); +int is_user_type(const type_t *t); +expr_t *get_size_is_expr(const type_t *t, const char *name); diff --git a/reactos/tools/widl_20080105/typelib.c b/reactos/tools/widl_20080105/typelib.c new file mode 100644 index 00000000000..7130e506d77 --- /dev/null +++ b/reactos/tools/widl_20080105/typelib.c @@ -0,0 +1,403 @@ +/* + * IDL Compiler + * + * Copyright 2004 Ove Kaaven + * Copyright 2006 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" +#include "wine/wpp.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "header.h" +#include "typelib.h" +#include "widltypes.h" +#include "typelib_struct.h" + +int in_typelib = 0; + +static typelib_t *typelib; + +type_t *duptype(type_t *t, int dupname) +{ + type_t *d = alloc_type(); + + *d = *t; + if (dupname && t->name) + d->name = xstrdup(t->name); + + d->orig = t; + return d; +} + +type_t *alias(type_t *t, const char *name) +{ + type_t *a = duptype(t, 0); + + a->name = xstrdup(name); + a->kind = TKIND_ALIAS; + a->attrs = NULL; + a->declarray = FALSE; + + return a; +} + +int is_ptr(const type_t *t) +{ + unsigned char c = t->type; + return c == RPC_FC_RP + || c == RPC_FC_UP + || c == RPC_FC_FP + || c == RPC_FC_OP; +} + +int is_array(const type_t *t) +{ + switch (t->type) + { + case RPC_FC_SMFARRAY: + case RPC_FC_LGFARRAY: + case RPC_FC_SMVARRAY: + case RPC_FC_LGVARRAY: + case RPC_FC_CARRAY: + case RPC_FC_CVARRAY: + case RPC_FC_BOGUS_ARRAY: + return TRUE; + default: + return FALSE; + } +} + +/* List of oleauto types that should be recognized by name. + * (most of) these seem to be intrinsic types in mktyplib. */ + +static const struct oatype { + const char *kw; + unsigned short vt; +} oatypes[] = { + {"BSTR", VT_BSTR}, + {"CURRENCY", VT_CY}, + {"DATE", VT_DATE}, + {"DECIMAL", VT_DECIMAL}, + {"HRESULT", VT_HRESULT}, + {"LPSTR", VT_LPSTR}, + {"LPWSTR", VT_LPWSTR}, + {"SCODE", VT_ERROR}, + {"VARIANT", VT_VARIANT}, + {"VARIANT_BOOL", VT_BOOL} +}; +#define NTYPES (sizeof(oatypes)/sizeof(oatypes[0])) +#define KWP(p) ((const struct oatype *)(p)) + +static int kw_cmp_func(const void *s1, const void *s2) +{ + return strcmp(KWP(s1)->kw, KWP(s2)->kw); +} + +static unsigned short builtin_vt(const type_t *t) +{ + const char *kw = t->name; + struct oatype key; + const struct oatype *kwp; + key.kw = kw; +#ifdef KW_BSEARCH + kwp = bsearch(&key, oatypes, NTYPES, sizeof(oatypes[0]), kw_cmp_func); +#else + { + unsigned int i; + for (kwp=NULL, i=0; i < NTYPES; i++) + if (!kw_cmp_func(&key, &oatypes[i])) { + kwp = &oatypes[i]; + break; + } + } +#endif + if (kwp) { + return kwp->vt; + } + if (is_string_type (t->attrs, t)) + switch (t->ref->type) + { + case RPC_FC_CHAR: return VT_LPSTR; + case RPC_FC_WCHAR: return VT_LPWSTR; + default: break; + } + return 0; +} + +static int match(const char*n, const char*m) +{ + if (!n) return 0; + return !strcmp(n, m); +} + +unsigned short get_type_vt(type_t *t) +{ + unsigned short vt; + + chat("get_type_vt: %p type->name %s\n", t, t->name); + if (t->name) { + vt = builtin_vt(t); + if (vt) return vt; + } + + if (t->kind == TKIND_ALIAS && t->attrs) + return VT_USERDEFINED; + + switch (t->type) { + case RPC_FC_BYTE: + case RPC_FC_USMALL: + return VT_UI1; + case RPC_FC_CHAR: + case RPC_FC_SMALL: + return VT_I1; + case RPC_FC_WCHAR: + return VT_I2; /* mktyplib seems to parse wchar_t as short */ + case RPC_FC_SHORT: + return VT_I2; + case RPC_FC_USHORT: + return VT_UI2; + case RPC_FC_LONG: + if (match(t->name, "int")) return VT_INT; + return VT_I4; + case RPC_FC_ULONG: + if (match(t->name, "int")) return VT_UINT; + return VT_UI4; + case RPC_FC_HYPER: + if (t->sign < 0) return VT_UI8; + if (match(t->name, "MIDL_uhyper")) return VT_UI8; + return VT_I8; + case RPC_FC_FLOAT: + return VT_R4; + case RPC_FC_DOUBLE: + return VT_R8; + case RPC_FC_RP: + case RPC_FC_UP: + case RPC_FC_OP: + case RPC_FC_FP: + case RPC_FC_CARRAY: + case RPC_FC_CVARRAY: + if(t->ref) + { + if (match(t->ref->name, "SAFEARRAY")) + return VT_SAFEARRAY; + return VT_PTR; + } + + error("get_type_vt: unknown-deref-type: %d\n", t->ref->type); + break; + case RPC_FC_IP: + if(match(t->name, "IUnknown")) + return VT_UNKNOWN; + if(match(t->name, "IDispatch")) + return VT_DISPATCH; + return VT_USERDEFINED; + + case RPC_FC_ENUM16: + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_BOGUS_STRUCT: + return VT_USERDEFINED; + case 0: + return t->kind == TKIND_PRIMITIVE ? VT_VOID : VT_USERDEFINED; + default: + error("get_type_vt: unknown type: 0x%02x\n", t->type); + } + return 0; +} + +void start_typelib(char *name, attr_list_t *attrs) +{ + in_typelib++; + if (!do_typelib) return; + + typelib = xmalloc(sizeof(*typelib)); + typelib->name = xstrdup(name); + typelib->filename = xstrdup(typelib_name); + typelib->attrs = attrs; + list_init( &typelib->entries ); + list_init( &typelib->importlibs ); + + if (is_attr(attrs, ATTR_POINTERDEFAULT)) + pointer_default = get_attrv(attrs, ATTR_POINTERDEFAULT); +} + +void end_typelib(void) +{ + in_typelib--; + if (!typelib) return; + + create_msft_typelib(typelib); + pointer_default = RPC_FC_UP; + return; +} + +void add_typelib_entry(type_t *t) +{ + typelib_entry_t *entry; + if (!typelib) return; + + chat("add kind %i: %s\n", t->kind, t->name); + entry = xmalloc(sizeof(*entry)); + entry->type = t; + list_add_tail( &typelib->entries, &entry->entry ); +} + +static void tlb_read(int fd, void *buf, int count) +{ + if(read(fd, buf, count) < count) + error("error while reading importlib.\n"); +} + +static void tlb_lseek(int fd, off_t offset) +{ + if(lseek(fd, offset, SEEK_SET) == -1) + error("lseek failed\n"); +} + +static void msft_read_guid(int fd, MSFT_SegDir *segdir, int offset, GUID *guid) +{ + tlb_lseek(fd, segdir->pGuidTab.offset+offset); + tlb_read(fd, guid, sizeof(GUID)); +} + +static void read_msft_importlib(importlib_t *importlib, int fd) +{ + MSFT_Header header; + MSFT_SegDir segdir; + int *typeinfo_offs; + int i; + + importlib->allocated = 0; + + tlb_lseek(fd, 0); + tlb_read(fd, &header, sizeof(header)); + + importlib->version = header.version; + + typeinfo_offs = xmalloc(header.nrtypeinfos*sizeof(INT)); + tlb_read(fd, typeinfo_offs, header.nrtypeinfos*sizeof(INT)); + tlb_read(fd, &segdir, sizeof(segdir)); + + msft_read_guid(fd, &segdir, header.posguid, &importlib->guid); + + importlib->ntypeinfos = header.nrtypeinfos; + importlib->importinfos = xmalloc(importlib->ntypeinfos*sizeof(importinfo_t)); + + for(i=0; i < importlib->ntypeinfos; i++) { + MSFT_TypeInfoBase base; + MSFT_NameIntro nameintro; + int len; + + tlb_lseek(fd, sizeof(MSFT_Header) + header.nrtypeinfos*sizeof(INT) + sizeof(MSFT_SegDir) + + typeinfo_offs[i]); + tlb_read(fd, &base, sizeof(base)); + + importlib->importinfos[i].importlib = importlib; + importlib->importinfos[i].flags = (base.typekind&0xf)<<24; + importlib->importinfos[i].offset = -1; + importlib->importinfos[i].id = i; + + if(base.posguid != -1) { + importlib->importinfos[i].flags |= MSFT_IMPINFO_OFFSET_IS_GUID; + msft_read_guid(fd, &segdir, base.posguid, &importlib->importinfos[i].guid); + } + else memset( &importlib->importinfos[i].guid, 0, sizeof(importlib->importinfos[i].guid)); + + tlb_lseek(fd, segdir.pNametab.offset + base.NameOffset); + tlb_read(fd, &nameintro, sizeof(nameintro)); + + len = nameintro.namelen & 0xff; + + importlib->importinfos[i].name = xmalloc(len+1); + tlb_read(fd, importlib->importinfos[i].name, len); + importlib->importinfos[i].name[len] = 0; + } + + free(typeinfo_offs); +} + +static void read_importlib(importlib_t *importlib) +{ + int fd; + INT magic; + char *file_name; + + file_name = wpp_find_include(importlib->name, NULL); + if(file_name) { + fd = open(file_name, O_RDONLY); + free(file_name); + }else { + fd = open(importlib->name, O_RDONLY); + } + + if(fd < 0) + error("Could not open importlib %s.\n", importlib->name); + + tlb_read(fd, &magic, sizeof(magic)); + + switch(magic) { + case MSFT_MAGIC: + read_msft_importlib(importlib, fd); + break; + default: + error("Wrong or unsupported typelib magic %x\n", magic); + }; + + close(fd); +} + +void add_importlib(const char *name) +{ + importlib_t *importlib; + + if(!typelib) return; + + LIST_FOR_EACH_ENTRY( importlib, &typelib->importlibs, importlib_t, entry ) + if(!strcmp(name, importlib->name)) + return; + + chat("add_importlib: %s\n", name); + + importlib = xmalloc(sizeof(*importlib)); + memset( importlib, 0, sizeof(*importlib) ); + importlib->name = xstrdup(name); + + read_importlib(importlib); + list_add_head( &typelib->importlibs, &importlib->entry ); +} diff --git a/reactos/tools/widl_20080105/typelib.h b/reactos/tools/widl_20080105/typelib.h new file mode 100644 index 00000000000..b17387dfc39 --- /dev/null +++ b/reactos/tools/widl_20080105/typelib.h @@ -0,0 +1,87 @@ +/* + * IDL Compiler + * + * Copyright 2004 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WIDL_TYPELIB_H +#define __WIDL_TYPELIB_H + +extern int in_typelib; +extern void start_typelib(char *name, attr_list_t *attrs); +extern void end_typelib(void); +extern void add_typelib_entry(type_t *t); +extern void add_importlib(const char *name); + +/* Copied from wtypes.h. Not included directly because that would create a + * circular dependency (after all, wtypes.h is generated by widl...) */ + +enum VARENUM { + VT_EMPTY = 0, + VT_NULL = 1, + VT_I2 = 2, + VT_I4 = 3, + VT_R4 = 4, + VT_R8 = 5, + VT_CY = 6, + VT_DATE = 7, + VT_BSTR = 8, + VT_DISPATCH = 9, + VT_ERROR = 10, + VT_BOOL = 11, + VT_VARIANT = 12, + VT_UNKNOWN = 13, + VT_DECIMAL = 14, + VT_I1 = 16, + VT_UI1 = 17, + VT_UI2 = 18, + VT_UI4 = 19, + VT_I8 = 20, + VT_UI8 = 21, + VT_INT = 22, + VT_UINT = 23, + VT_VOID = 24, + VT_HRESULT = 25, + VT_PTR = 26, + VT_SAFEARRAY = 27, + VT_CARRAY = 28, + VT_USERDEFINED = 29, + VT_LPSTR = 30, + VT_LPWSTR = 31, + VT_RECORD = 36, + VT_FILETIME = 64, + VT_BLOB = 65, + VT_STREAM = 66, + VT_STORAGE = 67, + VT_STREAMED_OBJECT = 68, + VT_STORED_OBJECT = 69, + VT_BLOB_OBJECT = 70, + VT_CF = 71, + VT_CLSID = 72, + VT_BSTR_BLOB = 0xfff, + VT_VECTOR = 0x1000, + VT_ARRAY = 0x2000, + VT_BYREF = 0x4000, + VT_RESERVED = 0x8000, + VT_ILLEGAL = 0xffff, + VT_ILLEGALMASKED = 0xfff, + VT_TYPEMASK = 0xfff +}; +extern unsigned short get_type_vt(type_t *t); + +extern int create_msft_typelib(typelib_t *typelib); +#endif diff --git a/reactos/tools/widl_20080105/typelib_struct.h b/reactos/tools/widl_20080105/typelib_struct.h new file mode 100644 index 00000000000..e16387c8dcd --- /dev/null +++ b/reactos/tools/widl_20080105/typelib_struct.h @@ -0,0 +1,605 @@ +/* + * typelib_struct.h internal wine data structures + * used to decode typelib's + * + * Copyright 1999 Rein KLazes + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef _WIDL_TYPELIB_STRUCT_H +#define _WIDL_TYPELIB_STRUCT_H + +#define HELPDLLFLAG (0x0100) +#define DO_NOT_SEEK (-1) + +#define MSFT_HREFTYPE_INTHISFILE(href) (!((href) & 3)) +#define MSFT_HREFTYPE_INDEX(href) ((href) /sizeof(MSFT_TypeInfoBase)) + +/*-------------------------FILE STRUCTURES-----------------------------------*/ + +/* There are two known file formats, those created with ICreateTypeLib + * have the signature "SLTG" as their first four bytes, while those created + * with ICreateTypeLib2 have "MSFT". + */ + +#define MSFT_MAGIC 0x5446534d + +/***************************************************** + * MSFT typelibs + * + * These are TypeLibs created with ICreateTypeLib2 + * + */ + +/* + * structure of the typelib type2 header + * it is at the beginning of a type lib file + * + */ +typedef struct tagMSFT_Header { +/*0x00*/INT magic1; /* 0x5446534D "MSFT" */ + INT magic2; /* 0x00010002 version nr? */ + INT posguid; /* position of libid in guid table */ + /* (should be, else -1) */ + INT lcid; /* locale id */ +/*0x10*/INT lcid2; + INT varflags; /* (largely) unknown flags */ + /* the lower nibble is syskind */ + /* 0x40 always seems to be set */ + /* 0x10 set with a helpfile defined */ + /* 0x100 set with a helpstringdll defined - in this + case the offset to the name in the stringtable + appears right after this struct, before the + typeinfo offsets */ + INT version; /* set with SetVersion() */ + INT flags; /* set with SetFlags() */ +/*0x20*/INT nrtypeinfos; /* number of typeinfo's (till so far) */ + INT helpstring; /* position of help string in stringtable */ + INT helpstringcontext; + INT helpcontext; +/*0x30*/INT nametablecount; /* number of names in name table */ + INT nametablechars; /* nr of characters in name table */ + INT NameOffset; /* offset of name in name table */ + INT helpfile; /* position of helpfile in stringtable */ +/*0x40*/INT CustomDataOffset; /* if -1 no custom data, else it is offset */ + /* in customer data/guid offset table */ + INT res44; /* unknown always: 0x20 (guid hash size?) */ + INT res48; /* unknown always: 0x80 (name hash size?) */ + INT dispatchpos; /* HREFTYPE to IDispatch, or -1 if no IDispatch */ +/*0x50*/INT nimpinfos; /* number of impinfos */ +} MSFT_Header; + +/* segments in the type lib file have a structure like this: */ +typedef struct tagMSFT_pSeg { + INT offset; /* absolute offset in file */ + INT length; /* length of segment */ + INT res08; /* unknown always -1 */ + INT res0c; /* unknown always 0x0f in the header */ + /* 0x03 in the typeinfo_data */ +} MSFT_pSeg; + +/* layout of the main segment directory */ +typedef struct tagMSFT_SegDir { +/*1*/MSFT_pSeg pTypeInfoTab; /* each type info get an entry of 0x64 bytes */ + /* (25 ints) */ +/*2*/MSFT_pSeg pImpInfo; /* table with info for imported types */ +/*3*/MSFT_pSeg pImpFiles; /* import libaries */ +/*4*/MSFT_pSeg pRefTab; /* References table */ +/*5*/MSFT_pSeg pLibtab; /* always exists, alway same size (0x80) */ + /* hash table w offsets to guid????? */ +/*6*/MSFT_pSeg pGuidTab; /* all guids are stored here together with */ + /* offset in some table???? */ +/*7*/MSFT_pSeg res07; /* always created, alway same size (0x200) */ + /* purpose largely unknown */ +/*8*/MSFT_pSeg pNametab; /* name tables */ +/*9*/MSFT_pSeg pStringtab; /* string table */ +/*A*/MSFT_pSeg pTypdescTab; /* table with type descriptors */ +/*B*/MSFT_pSeg pArrayDescriptions; +/*C*/MSFT_pSeg pCustData; /* data table, used for custom data and default */ + /* parameter values */ +/*D*/MSFT_pSeg pCDGuids; /* table with offsets for the guids and into */ + /* the customer data table */ +/*E*/MSFT_pSeg res0e; /* unknown */ +/*F*/MSFT_pSeg res0f; /* unknown */ +} MSFT_SegDir; + + +/* base type info data */ +typedef struct tagMSFT_TypeInfoBase { +/*000*/ INT typekind; /* it is the TKIND_xxx */ + /* some byte alignment stuf */ + INT memoffset; /* points past the file, if no elements */ + INT res2; /* zero if no element, N*0x40 */ + INT res3; /* -1 if no lement, (N-1)*0x38 */ +/*010*/ INT res4; /* always? 3 */ + INT res5; /* always? zero */ + INT cElement; /* counts elements, HI=cVars, LO=cFuncs */ + INT res7; /* always? zero */ +/*020*/ INT res8; /* always? zero */ + INT res9; /* always? zero */ + INT resA; /* always? zero */ + INT posguid; /* position in guid table */ +/*030*/ INT flags; /* Typeflags */ + INT NameOffset; /* offset in name table */ + INT version; /* element version */ + INT docstringoffs; /* offset of docstring in string tab */ +/*040*/ INT helpstringcontext; /* */ + INT helpcontext; /* */ + INT oCustData; /* offset in customer data table */ +#ifdef WORDS_BIGENDIAN + INT16 cbSizeVft; /* virtual table size, including inherits */ + INT16 cImplTypes; /* nr of implemented interfaces */ +#else + INT16 cImplTypes; /* nr of implemented interfaces */ + INT16 cbSizeVft; /* virtual table size, including inherits */ +#endif +/*050*/ INT size; /* size in bytes, at least for structures */ + /* FIXME: name of this field */ + INT datatype1; /* position in type description table */ + /* or in base interfaces */ + /* if coclass: offset in reftable */ + /* if interface: reference to inherited if */ + INT datatype2; /* for interfaces: hiword is num of inherited funcs */ + /* loword is num of inherited interfaces */ + INT res18; /* always? 0 */ +/*060*/ INT res19; /* always? -1 */ +} MSFT_TypeInfoBase; + +/* layout of an entry with information on imported types */ +typedef struct tagMSFT_ImpInfo { + INT flags; /* bits 0 - 15: count */ + /* bit 16: if set oGuid is an offset to Guid */ + /* if clear oGuid is a typeinfo index in the specified typelib */ + /* bits 24 - 31: TKIND of reference */ + INT oImpFile; /* offset in the Import File table */ + INT oGuid; /* offset in Guid table or typeinfo index (see bit 16 of flags) */ +} MSFT_ImpInfo; + +#define MSFT_IMPINFO_OFFSET_IS_GUID 0x00010000 + +/* function description data */ +typedef struct { +/* INT recsize; record size including some xtra stuff */ + INT DataType; /* data type of the member, eg return of function */ + INT Flags; /* something to do with attribute flags (LOWORD) */ +#ifdef WORDS_BIGENDIAN + INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */ + INT16 VtableOffset; /* offset in vtable */ +#else + INT16 VtableOffset; /* offset in vtable */ + INT16 funcdescsize; /* size of reconstituted FUNCDESC and related structs */ +#endif + INT FKCCIC; /* bit string with the following */ + /* meaning (bit 0 is the lsb): */ + /* bits 0 - 2: FUNCKIND */ + /* bits 3 - 6: INVOKEKIND */ + /* bit 7: custom data present */ + /* bits 8 - 11: CALLCONV */ + /* bit 12: parameters have default values */ + /* bit 13: oEntry is numeric */ + /* bit 14: has retval param */ + /* bits 16 - 31: index of next function with same id */ +#ifdef WORDS_BIGENDIAN + INT16 nroargs; /* nr of optional arguments */ + INT16 nrargs; /* number of arguments (including optional ????) */ +#else + INT16 nrargs; /* number of arguments (including optional ????) */ + INT16 nroargs; /* nr of optional arguments */ +#endif + /* optional attribute fields, the number of them is variable */ + INT OptAttr[1]; +/* +0* INT helpcontext; +1* INT oHelpString; +2* INT oEntry; // either offset in string table or numeric as it is (see bit 13 of FKCCIC) // +3* INT res9; // unknown (-1) // +4* INT resA; // unknown (-1) // +5* INT HelpStringContext; + // these are controlled by a bit set in the FKCCIC field // +6* INT oCustData; // custom data for function // +7* INT oArgCustData[1]; // custom data per argument // +*/ +} MSFT_FuncRecord; + +/* after this may follow an array with default value pointers if the + * appropriate bit in the FKCCIC field has been set: + * INT oDefautlValue[nrargs]; + */ + + /* Parameter info one per argument*/ +typedef struct { + INT DataType; + INT oName; + INT Flags; + } MSFT_ParameterInfo; + +/* Variable description data */ +typedef struct { +/* INT recsize; // record size including some xtra stuff */ + INT DataType; /* data type of the variable */ + INT Flags; /* VarFlags (LOWORD) */ +#ifdef WORDS_BIGENDIAN + INT16 vardescsize; /* size of reconstituted VARDESC and related structs */ + INT16 VarKind; /* VarKind */ +#else + INT16 VarKind; /* VarKind */ + INT16 vardescsize; /* size of reconstituted VARDESC and related structs */ +#endif + INT OffsValue; /* value of the variable or the offset */ + /* in the data structure */ + /* optional attribute fields, the number of them is variable */ + /* controlled by record length */ + INT HelpContext; + INT oHelpString; + INT res9; /* unknown (-1) */ + INT oCustData; /* custom data for variable */ + INT HelpStringContext; + +} MSFT_VarRecord; + +/* Structure of the reference data */ +typedef struct { + INT reftype; /* either offset in type info table, then it's */ + /* a multiple of 64 */ + /* or offset in the external reference table */ + /* with an offset of 1 */ + INT flags; + INT oCustData; /* custom data */ + INT onext; /* next offset, -1 if last */ +} MSFT_RefRecord; + +/* this is how a guid is stored */ +typedef struct { + GUID guid; + INT hreftype; /* -2 for the typelib guid, typeinfo offset + for typeinfo guid, low two bits are 01 if + this is an imported typeinfo, low two bits + are 10 if this is an imported typelib (used + by imported typeinfos) */ + INT next_hash; /* offset to next guid in the hash bucket */ +} MSFT_GuidEntry; +/* some data preceding entries in the name table */ +typedef struct { + INT hreftype; /* is -1 if name is for neither a typeinfo, + a variable, or a function (that is, name + is for a typelib or a function parameter). + otherwise is the offset of the first + typeinfo that this name refers to (either + to the typeinfo itself or to a member of + the typeinfo */ + INT next_hash; /* offset to next name in the hash bucket */ + INT namelen; /* only lower 8 bits are valid */ + /* 0x1000 if name is only used once as a variable name */ + /* 0x2000 if name is a variable in an enumeration */ + /* 0x3800 if name is typeinfo name */ + /* upper 16 bits are hash code */ +} MSFT_NameIntro; +/* the custom data table directory has entries like this */ +typedef struct { + INT GuidOffset; + INT DataOffset; + INT next; /* next offset in the table, -1 if it's the last */ +} MSFT_CDGuid; + + +/*********************************************************** + * + * SLTG typelibs. + * + * These are created with ICreateTypeLib + * + */ + +#include "pshpack1.h" + +typedef struct { +/*00*/ DWORD SLTG_magic; /* 0x47544c53 == "SLTG" */ +/*04*/ WORD nrOfFileBlks; /* no of SLTG_BlkEntry's + 1 */ +/*06*/ WORD res06; /* ?? always 9 */ +/*08*/ WORD res08; /* some kind of len/offset ?? */ +/*0a*/ WORD first_blk; /* 1 based index into blk entries that + corresponds to first block in file */ +/*0c*/ DWORD res0c; /* always 0x000204ff */ +/*10*/ DWORD res10; /* always 0x00000000 */ +/*14*/ DWORD res14; /* always 0x000000c0 */ +/*18*/ DWORD res18; /* always 0x46000000 */ +/*1c*/ DWORD res1c; /* always 0x00000044 */ +/*20*/ DWORD res20; /* always 0xffff0000 */ +} SLTG_Header; + +/* This gets followed by a list of block entries */ +typedef struct { +/*00*/ DWORD len; +/*04*/ WORD index_string; /* offs from start of SLTG_Magic to index string */ +/*06*/ WORD next; +} SLTG_BlkEntry; + +/* The order of the blocks in the file is given by starting at Block + entry firt_blk and stepping through using the next pointer */ + +/* These then get followed by this magic */ +typedef struct { +/*00*/ BYTE res00; /* always 0x01 */ +/*01*/ CHAR CompObj_magic[8]; /* always "CompObj" */ +/*09*/ CHAR dir_magic[4]; /* always "dir" */ +} SLTG_Magic; + +#define SLTG_COMPOBJ_MAGIC "CompObj" +#define SLTG_DIR_MAGIC "dir" + +/* Next we have SLTG_Header.nrOfFileBlks - 2 of Index strings. These +are presumably unique to within the file and look something like +"AAAAAAAAAA" with the first character incremented from 'A' to ensure +uniqueness. I guess successive chars increment when we need to wrap +the first one. */ + +typedef struct { +/*00*/ CHAR string[11]; +} SLTG_Index; + + +/* This is followed by SLTG_pad9 */ +typedef struct { +/*00*/ CHAR pad[9]; /* 9 '\0's */ +} SLTG_Pad9; + + +/* Now we have the noOfFileBlks - 1 worth of blocks. The length of +each block is given by its entry in SLTG_BlkEntry. */ + +/* type SLTG_NAME in rather like a BSTR except that the length in +bytes is given by the first WORD and the string contains 8bit chars */ + +typedef WORD SLTG_Name; + +/* The main library block looks like this. This one seems to come last */ + +typedef struct { +/*00*/ WORD magic; /* 0x51cc */ +/*02*/ WORD res02; /* 0x0003, 0x0004 */ +/*04*/ WORD name; /* offset to name in name table */ +/*06*/ SLTG_Name res06; /* maybe this is just WORD == 0xffff */ + SLTG_Name helpstring; + SLTG_Name helpfile; + DWORD helpcontext; + WORD syskind; /* == 1 for win32, 0 for win16 */ + WORD lcid; /* == 0x409, 0x809 etc */ + DWORD res12; /* == 0 */ + WORD libflags; /* LIBFLAG_* */ + WORD maj_vers; + WORD min_vers; + GUID uuid; +} SLTG_LibBlk; + +#define SLTG_LIBBLK_MAGIC 0x51cc + +/* we then get 0x40 bytes worth of 0xffff or small numbers followed by + nrOfFileBlks - 2 of these */ +typedef struct { + WORD small_no; + SLTG_Name index_name; /* This refers to a name in the directory */ + SLTG_Name other_name; /* Another one of these weird names */ + WORD res1a; /* 0xffff */ + WORD name_offs; /* offset to name in name table */ + WORD more_bytes; /* if this is non-zero we get this many + bytes before the next element, which seem + to reference the docstring of the type ? */ + WORD res20; /* 0xffff */ + DWORD helpcontext; + WORD res26; /* 0xffff */ + GUID uuid; +} SLTG_OtherTypeInfo; + +/* Next we get WORD 0x0003 followed by a DWORD which if we add to +0x216 gives the offset to the name table from the start of the LibBlk +struct */ + +typedef struct { +/*00*/ WORD magic; /* 0x0501 */ +/*02*/ DWORD href_table; /* if not 0xffffffff, then byte offset from + beginning of struct to href table */ +/*06*/ DWORD res06; /* 0xffffffff */ +/*0a*/ DWORD elem_table; /* offset to members */ +/*0e*/ DWORD res0e; /* 0xffffffff */ +/*12*/ WORD major_version; /* major version number */ +/*14*/ WORD minor_version; /* minor version number */ +/*16*/ DWORD res16; /* 0xfffe0000 */ +/*1a*/ BYTE typeflags1;/* 0x02 | top 5 bits hold l5sbs of TYPEFLAGS */ +/*1b*/ BYTE typeflags2;/* TYPEFLAGS >> 5 */ +/*1c*/ BYTE typeflags3;/* 0x02*/ +/*1d*/ BYTE typekind; /* 0x03 == TKIND_INTERFACE etc. */ +/*1e*/ DWORD res1e; /* 0x00000000 or 0xffffffff */ +} SLTG_TypeInfoHeader; + +#define SLTG_TIHEADER_MAGIC 0x0501 + +typedef struct { +/*00*/ WORD cFuncs; +/*02*/ WORD cVars; +/*04*/ WORD cImplTypes; +/*06*/ WORD res06; +/*08*/ WORD res08; +/*0a*/ WORD res0a; +/*0c*/ WORD res0c; +/*0e*/ WORD res0e; +/*10*/ WORD res10; +/*12*/ WORD res12; +/*14*/ WORD tdescalias_vt; /* for TKIND_ALIAS */ +/*16*/ WORD res16; +/*18*/ WORD res18; +/*1a*/ WORD res1a; +/*1c*/ WORD res1c; +/*1e*/ WORD res1e; +/*20*/ WORD cbSizeInstance; +/*22*/ WORD cbAlignment; +/*24*/ WORD res24; +/*26*/ WORD res26; +/*28*/ WORD cbSizeVft; +/*2a*/ WORD res2a; +/*2c*/ WORD res2c; +/*2e*/ WORD res2e; +/*30*/ WORD res30; +/*32*/ WORD res32; +/*34*/ WORD res34; +} SLTG_TypeInfoTail; + +typedef struct { +/*00*/ WORD res00; /* 0x0001 sometimes 0x0003 ?? */ +/*02*/ WORD res02; /* 0xffff */ +/*04*/ BYTE res04; /* 0x01 */ +/*05*/ DWORD cbExtra; /* No of bytes that follow */ +} SLTG_MemberHeader; + +typedef struct { +/*00*/ WORD magic; /* 0x120a */ +/*02*/ WORD next; /* offset in bytes to next block from start of block + group, 0xffff if last item */ +/*04*/ WORD name; /* offset to name within name table */ +/*06*/ WORD value; /* offset to value from start of block group */ +/*08*/ WORD res08; /* 0x56 */ +/*0a*/ DWORD memid; /* memid */ +/*0e*/ WORD helpcontext;/* 0xfffe == no context, 0x0001 == stored in EnumInfo struct, else offset + to value from start of block group */ +/*10*/ WORD helpstring;/* offset from start of block group to string offset */ +} SLTG_EnumItem; + +#define SLTG_ENUMITEM_MAGIC 0x120a + +typedef struct { +/*00*/ WORD vt; /* vartype, 0xffff marks end. */ +/*02*/ WORD res02; /* ?, 0xffff marks end */ +} SLTG_AliasItem; + +#define SLTG_ALIASITEM_MAGIC 0x001d + + +typedef struct { + BYTE magic; /* 0x4c or 0x6c */ + BYTE inv; /* high nibble is INVOKE_KIND, low nibble = 2 */ + WORD next; /* byte offset from beginning of group to next fn */ + WORD name; /* Offset within name table to name */ + DWORD dispid; /* dispid */ + WORD helpcontext; /* helpcontext (again 1 is special) */ + WORD helpstring;/* helpstring offset to offset */ + WORD arg_off; /* offset to args from start of block */ + BYTE nacc; /* lowest 3bits are CALLCONV, rest are no of args */ + BYTE retnextopt;/* if 0x80 bit set ret type follows else next WORD + is offset to ret type. No of optional args is + middle 6 bits */ + WORD rettype; /* return type VT_?? or offset to ret type */ + WORD vtblpos; /* position in vtbl? */ + WORD funcflags; /* present if magic == 0x6c */ +/* Param list starts, repeat next two as required */ +#if 0 + WORD name; /* offset to 2nd letter of name */ + WORD+ type; /* VT_ of param */ +#endif +} SLTG_Function; + +#define SLTG_FUNCTION_MAGIC 0x4c +#define SLTG_FUNCTION_WITH_FLAGS_MAGIC 0x6c + +typedef struct { +/*00*/ BYTE magic; /* 0xdf */ +/*01*/ BYTE res01; /* 0x00 */ +/*02*/ DWORD res02; /* 0xffffffff */ +/*06*/ DWORD res06; /* 0xffffffff */ +/*0a*/ DWORD res0a; /* 0xffffffff */ +/*0e*/ DWORD res0e; /* 0xffffffff */ +/*12*/ DWORD res12; /* 0xffffffff */ +/*16*/ DWORD res16; /* 0xffffffff */ +/*1a*/ DWORD res1a; /* 0xffffffff */ +/*1e*/ DWORD res1e; /* 0xffffffff */ +/*22*/ DWORD res22; /* 0xffffffff */ +/*26*/ DWORD res26; /* 0xffffffff */ +/*2a*/ DWORD res2a; /* 0xffffffff */ +/*2e*/ DWORD res2e; /* 0xffffffff */ +/*32*/ DWORD res32; /* 0xffffffff */ +/*36*/ DWORD res36; /* 0xffffffff */ +/*3a*/ DWORD res3a; /* 0xffffffff */ +/*3e*/ DWORD res3e; /* 0xffffffff */ +/*42*/ WORD res42; /* 0xffff */ +/*44*/ DWORD number; /* this is 8 times the number of refs */ +/*48*/ /* Now we have number bytes (8 for each ref) of SLTG_UnknownRefInfo */ + +/*50*/ WORD res50; /* 0xffff */ +/*52*/ BYTE res52; /* 0x01 */ +/*53*/ DWORD res53; /* 0x00000000 */ +/*57*/ SLTG_Name names[1]; + /* Now we have number/8 SLTG_Names (first WORD is no of bytes in the ascii + * string). Strings look like "*\Rxxxx*#n". If xxxx == ffff then the + * ref refers to the nth type listed in this library (0 based). Else + * the xxxx (which maybe fewer than 4 digits) is the offset into the name + * table to a string "*\G{}#1.0#0#C:\WINNT\System32\stdole32.tlb#" + * The guid is the typelib guid; the ref again refers to the nth type of + * the imported typelib. + */ + +/*xx*/ BYTE resxx; /* 0xdf */ + +} SLTG_RefInfo; + +#define SLTG_REF_MAGIC 0xdf + +typedef struct { + WORD res00; /* 0x0001 */ + BYTE res02; /* 0x02 */ + BYTE res03; /* 0x40 if internal ref, 0x00 if external ? */ + WORD res04; /* 0xffff */ + WORD res06; /* 0x0000, 0x0013 or 0xffff ?? */ +} SLTG_UnknownRefInfo; + +typedef struct { + WORD res00; /* 0x004a */ + WORD next; /* byte offs to next interface */ + WORD res04; /* 0xffff */ + BYTE impltypeflags; /* IMPLTYPEFLAG_* */ + BYTE res07; /* 0x80 */ + WORD res08; /* 0x0012, 0x0028 ?? */ + WORD ref; /* number in ref table ? */ + WORD res0c; /* 0x4000 */ + WORD res0e; /* 0xfffe */ + WORD res10; /* 0xffff */ + WORD res12; /* 0x001d */ + WORD pos_in_table; /* 0x0, 0x4, ? */ +} SLTG_ImplInfo; + +#define SLTG_IMPL_MAGIC 0x004a + +typedef struct { + BYTE magic; /* 0x0a */ + BYTE typepos; + WORD next; + WORD name; + WORD byte_offs; /* pos in struct */ + WORD type; /* if typepos == 0x02 this is the type, else offset to type */ + DWORD memid; + WORD helpcontext; /* ?? */ + WORD helpstring; /* ?? */ +} SLTG_RecordItem; + +#define SLTG_RECORD_MAGIC 0x0a + + +/* CARRAYs look like this +WORD type == VT_CARRAY +WORD offset from start of block to SAFEARRAY +WORD typeofarray +*/ + +#include "poppack.h" + +/*---------------------------END--------------------------------------------*/ +#endif diff --git a/reactos/tools/widl_20080105/utils.c b/reactos/tools/widl_20080105/utils.c new file mode 100644 index 00000000000..e77361ce339 --- /dev/null +++ b/reactos/tools/widl_20080105/utils.c @@ -0,0 +1,218 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#include + +#include "widl.h" +#include "utils.h" +#include "parser.h" + +static const int want_near_indication = 0; + +static void make_print(char *str) +{ + while(*str) + { + if(!isprint(*str)) + *str = ' '; + str++; + } +} + +static void generic_msg(const char *s, const char *t, const char *n, va_list ap) +{ + fprintf(stderr, "%s:%d: %s: ", input_name ? input_name : "stdin", line_number, t); + vfprintf(stderr, s, ap); + + if (want_near_indication) + { + char *cpy; + if(n) + { + cpy = xstrdup(n); + make_print(cpy); + fprintf(stderr, " near '%s'", cpy); + free(cpy); + } + } +} + + +/* yyerror: yacc assumes this is not newline terminated. */ +int parser_error(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Error", parser_text, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); + return 1; +} + +void error_loc(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Error", parser_text, ap); + va_end(ap); + exit(1); +} + +int parser_warning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + generic_msg(s, "Warning", parser_text, ap); + va_end(ap); + return 0; +} + +void error(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "error: "); + vfprintf(stderr, s, ap); + va_end(ap); + exit(2); +} + +void warning(const char *s, ...) +{ + va_list ap; + va_start(ap, s); + fprintf(stderr, "warning: "); + vfprintf(stderr, s, ap); + va_end(ap); +} + +void chat(const char *s, ...) +{ + if(debuglevel & DEBUGLEVEL_CHAT) + { + va_list ap; + va_start(ap, s); + fprintf(stderr, "chat: "); + vfprintf(stderr, s, ap); + 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 = xmalloc(namelen +4 +1); + strcpy(base, name); + if(!strcasecmp(name + namelen-extlen, ext)) + { + base[namelen - extlen] = '\0'; + } + return base; +} + +size_t widl_getline(char **linep, size_t *lenp, FILE *fp) +{ + char *line = *linep; + size_t len = *lenp; + size_t n = 0; + + if (!line) + { + len = 64; + line = xmalloc(len); + } + + while (fgets(&line[n], len - n, fp)) + { + n += strlen(&line[n]); + if (line[n - 1] == '\n') + break; + else if (n == len - 1) + { + len *= 2; + line = xrealloc(line, len); + } + } + + *linep = line; + *lenp = len; + return n; +} + +void *xmalloc(size_t size) +{ + void *res; + + assert(size > 0); + res = malloc(size); + if(res == NULL) + { + error("Virtual memory exhausted.\n"); + } + memset(res, 0x55, 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 = xmalloc(strlen(str)+1); + return strcpy(s, str); +} diff --git a/reactos/tools/widl_20080105/utils.h b/reactos/tools/widl_20080105/utils.h new file mode 100644 index 00000000000..7d6ce5c5f30 --- /dev/null +++ b/reactos/tools/widl_20080105/utils.h @@ -0,0 +1,55 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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); + +#ifndef __GNUC__ +#define __attribute__(X) +#endif + +int parser_error(const char *s, ...) __attribute__((format (printf, 1, 2))); +int parser_warning(const char *s, ...) __attribute__((format (printf, 1, 2))); +void error_loc(const char *s, ...) __attribute__((format (printf, 1, 2))); +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); +size_t widl_getline(char **linep, size_t *lenp, FILE *fp); + +UUID *parse_uuid(const char *u); +int is_valid_uuid(const char *s); + +/* typelibs expect the minor version to be stored in the higher bits and + * major to be stored in the lower bits */ +#define MAKEVERSION(major, minor) ((((minor) & 0xffff) << 16) | ((major) & 0xffff)) +#define MAJORVERSION(version) ((version) & 0xffff) +#define MINORVERSION(version) (((version) >> 16) & 0xffff) + +#endif diff --git a/reactos/tools/widl_20080105/widl.c b/reactos/tools/widl_20080105/widl.c new file mode 100644 index 00000000000..79456942609 --- /dev/null +++ b/reactos/tools/widl_20080105/widl.c @@ -0,0 +1,653 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include +#include +#include +#include +#ifdef HAVE_GETOPT_H +# include +#endif + +#include "widl.h" +#include "utils.h" +#include "parser.h" +#include "wine/wpp.h" +#include "header.h" + +/* future options to reserve characters for: */ +/* a = alignment of structures */ +/* A = ACF input filename */ +/* J = do not search standard include path */ +/* O = generate interpreted stubs */ +/* w = select win16/win32 output (?) */ + +static const char usage[] = +"Usage: widl [options...] infile.idl\n" +" or: widl [options...] --dlldata-only name1 [name2...]\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" +" --dlldata=file Name of the dlldata file (default is dlldata.c)\n" +" -E Preprocess only\n" +" -h Generate headers\n" +" -H file Name of header file (default is infile.h)\n" +" -I path Set include search dir to path (multiple -I allowed)\n" +" --local-stubs=file Write empty stubs for call_as/local methods to file\n" +" -N Do not preprocess input\n" +" --oldnames Use old naming conventions\n" +" -p Generate proxy\n" +" -P file Name of proxy file (default is infile_p.c)\n" +" --prefix-all=p Prefix names of client stubs / server functions with 'p'\n" +" --prefix-client=p Prefix names of client stubs with 'p'\n" +" --prefix-server=p Prefix names of server functions with 'p'\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" +" -u Generate interface identifiers file\n" +" -U file Name of interface identifiers file (default is infile_i.c)\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" +; + +static const char version_string[] = "Wine IDL Compiler version " PACKAGE_VERSION "\n" + "Copyright 2002 Ove Kaaven\n"; + +int win32 = 1; +int debuglevel = DEBUGLEVEL_NONE; +int parser_debug, yy_flex_debug; + +int pedantic = 0; +int do_everything = 1; +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 do_idfile = 0; +int do_dlldata = 0; +int no_preprocess = 0; +int old_names = 0; + +char *input_name; +char *header_name; +char *local_stubs_name; +char *header_token; +char *typelib_name; +char *dlldata_name; +char *proxy_name; +char *proxy_token; +char *client_name; +char *client_token; +char *server_name; +char *server_token; +char *idfile_name; +char *idfile_token; +char *temp_name; +const char *prefix_client = ""; +const char *prefix_server = ""; + +int line_number = 1; + +FILE *header; +FILE *local_stubs; +FILE *proxy; +FILE *idfile; + +time_t now; + +enum { + OLDNAMES_OPTION = CHAR_MAX + 1, + DLLDATA_OPTION, + DLLDATA_ONLY_OPTION, + LOCAL_STUBS_OPTION, + PREFIX_ALL_OPTION, + PREFIX_CLIENT_OPTION, + PREFIX_SERVER_OPTION +}; + +static const char short_options[] = + "cC:d:D:EhH:I:NpP:sS:tT:uU:VW"; +static const struct option long_options[] = { + { "dlldata", required_argument, 0, DLLDATA_OPTION }, + { "dlldata-only", no_argument, 0, DLLDATA_ONLY_OPTION }, + { "local-stubs", required_argument, 0, LOCAL_STUBS_OPTION }, + { "oldnames", no_argument, 0, OLDNAMES_OPTION }, + { "prefix-all", required_argument, 0, PREFIX_ALL_OPTION }, + { "prefix-client", required_argument, 0, PREFIX_CLIENT_OPTION }, + { "prefix-server", required_argument, 0, PREFIX_SERVER_OPTION }, + { 0, 0, 0, 0 } +}; + +static void rm_tempfile(void); + +static char *make_token(const char *name) +{ + char *token; + char *slash; + int i; + + slash = strrchr(name, '/'); + if (slash) name = slash + 1; + + token = xstrdup(name); + for (i=0; token[i]; i++) { + if (!isalnum(token[i])) token[i] = '_'; + else token[i] = toupper(token[i]); + } + return token; +} + +/* duplicate a basename into a valid C token */ +static char *dup_basename_token(const char *name, const char *ext) +{ + char *p, *ret = dup_basename( name, ext ); + /* map invalid characters to '_' */ + for (p = ret; *p; p++) if (!isalnum(*p)) *p = '_'; + return ret; +} + +/* clean things up when aborting on a signal */ +static void exit_on_signal( int sig ) +{ + exit(1); /* this will call the atexit functions */ +} + +static void set_everything(int x) +{ + do_header = x; + do_typelib = x; + do_proxies = x; + do_client = x; + do_server = x; + do_idfile = x; + do_dlldata = x; +} + +static void start_cplusplus_guard(FILE *fp) +{ + fprintf(fp, "#ifdef __cplusplus\n"); + fprintf(fp, "extern \"C\" {\n"); + fprintf(fp, "#endif\n\n"); +} + +static void end_cplusplus_guard(FILE *fp) +{ + fprintf(fp, "#ifdef __cplusplus\n"); + fprintf(fp, "}\n"); + fprintf(fp, "#endif\n\n"); +} + +typedef struct +{ + char *filename; + struct list link; +} filename_node_t; + +static void add_filename_node(struct list *list, const char *name) +{ + filename_node_t *node = xmalloc(sizeof *node); + node->filename = dup_basename( name, ".idl" ); + list_add_tail(list, &node->link); +} + +static void free_filename_nodes(struct list *list) +{ + filename_node_t *node, *next; + LIST_FOR_EACH_ENTRY_SAFE(node, next, list, filename_node_t, link) { + list_remove(&node->link); + free(node->filename); + free(node); + } +} + +static void write_dlldata_list(struct list *filenames) +{ + FILE *dlldata; + filename_node_t *node; + + dlldata = fopen(dlldata_name, "w"); + if (!dlldata) + error("couldn't open %s: %s\n", dlldata_name, strerror(errno)); + + fprintf(dlldata, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION); + fprintf(dlldata, "- Do not edit ***/\n\n"); + fprintf(dlldata, "#include \n"); + fprintf(dlldata, "#include \n\n"); + start_cplusplus_guard(dlldata); + + LIST_FOR_EACH_ENTRY(node, filenames, filename_node_t, link) + fprintf(dlldata, "EXTERN_PROXY_FILE(%s)\n", node->filename); + + fprintf(dlldata, "\nPROXYFILE_LIST_START\n"); + fprintf(dlldata, "/* Start of list */\n"); + LIST_FOR_EACH_ENTRY(node, filenames, filename_node_t, link) + fprintf(dlldata, " REFERENCE_PROXY_FILE(%s),\n", node->filename); + fprintf(dlldata, "/* End of list */\n"); + fprintf(dlldata, "PROXYFILE_LIST_END\n\n"); + + fprintf(dlldata, "DLLDATA_ROUTINES(aProxyFileList, GET_DLL_CLSID)\n\n"); + end_cplusplus_guard(dlldata); + fclose(dlldata); +} + +static char *eat_space(char *s) +{ + while (isspace((unsigned char) *s)) + ++s; + return s; +} + +void write_dlldata(ifref_list_t *ifaces) +{ + struct list filenames = LIST_INIT(filenames); + filename_node_t *node; + FILE *dlldata; + + if (!do_dlldata || !need_proxy_file(ifaces)) + return; + + dlldata = fopen(dlldata_name, "r"); + if (dlldata) { + static char marker[] = "REFERENCE_PROXY_FILE"; + char *line = NULL; + size_t len = 0; + + while (widl_getline(&line, &len, dlldata)) { + char *start, *end; + start = eat_space(line); + if (strncmp(start, marker, sizeof marker - 1) == 0) { + start = eat_space(start + sizeof marker - 1); + if (*start != '(') + continue; + end = start = eat_space(start + 1); + while (*end && *end != ')') + ++end; + if (*end != ')') + continue; + while (isspace((unsigned char) end[-1])) + --end; + *end = '\0'; + if (start < end) + add_filename_node(&filenames, start); + } + } + + if (ferror(dlldata)) + error("couldn't read from %s: %s\n", dlldata_name, strerror(errno)); + + free(line); + fclose(dlldata); + } + + LIST_FOR_EACH_ENTRY(node, &filenames, filename_node_t, link) + if (strcmp(proxy_token, node->filename) == 0) { + /* We're already in the list, no need to regenerate this file. */ + free_filename_nodes(&filenames); + return; + } + + add_filename_node(&filenames, proxy_token); + write_dlldata_list(&filenames); + free_filename_nodes(&filenames); +} + +int main(int argc,char *argv[]) +{ + extern char* optarg; + extern int optind; + int optc; + int ret = 0; + int opti = 0; + + signal( SIGTERM, exit_on_signal ); + signal( SIGINT, exit_on_signal ); +#ifdef SIGHUP + signal( SIGHUP, exit_on_signal ); +#endif + + now = time(NULL); + + while((optc = getopt_long(argc, argv, short_options, long_options, &opti)) != EOF) { + switch(optc) { + case DLLDATA_OPTION: + dlldata_name = xstrdup(optarg); + break; + case DLLDATA_ONLY_OPTION: + do_everything = 0; + do_dlldata = 1; + break; + case LOCAL_STUBS_OPTION: + do_everything = 0; + local_stubs_name = xstrdup(optarg); + break; + case OLDNAMES_OPTION: + old_names = 1; + break; + case PREFIX_ALL_OPTION: + prefix_client = xstrdup(optarg); + prefix_server = xstrdup(optarg); + break; + case PREFIX_CLIENT_OPTION: + prefix_client = xstrdup(optarg); + break; + case PREFIX_SERVER_OPTION: + prefix_server = xstrdup(optarg); + break; + case 'c': + do_everything = 0; + do_client = 1; + break; + case 'C': + client_name = xstrdup(optarg); + break; + case 'd': + debuglevel = strtol(optarg, NULL, 0); + break; + case 'D': + wpp_add_cmdline_define(optarg); + break; + case 'E': + do_everything = 0; + preprocess_only = 1; + break; + case 'h': + do_everything = 0; + do_header = 1; + break; + case 'H': + header_name = xstrdup(optarg); + break; + case 'I': + wpp_add_include_path(optarg); + break; + case 'N': + no_preprocess = 1; + break; + case 'p': + do_everything = 0; + do_proxies = 1; + break; + case 'P': + proxy_name = xstrdup(optarg); + break; + case 's': + do_everything = 0; + do_server = 1; + break; + case 'S': + server_name = xstrdup(optarg); + break; + case 't': + do_everything = 0; + do_typelib = 1; + break; + case 'T': + typelib_name = xstrdup(optarg); + break; + case 'u': + do_everything = 0; + do_idfile = 1; + break; + case 'U': + idfile_name = xstrdup(optarg); + break; + case 'V': + printf("%s", version_string); + return 0; + case 'W': + pedantic = 1; + break; + default: + fprintf(stderr, "%s", usage); + return 1; + } + } + + if(do_everything) { + set_everything(TRUE); + } + + if (!dlldata_name && do_dlldata) + dlldata_name = xstrdup("dlldata.c"); + + if(optind < argc) { + if (do_dlldata && !do_everything) { + struct list filenames = LIST_INIT(filenames); + for ( ; optind < argc; ++optind) + add_filename_node(&filenames, argv[optind]); + + write_dlldata_list(&filenames); + free_filename_nodes(&filenames); + return 0; + } + else if (optind != argc - 1) { + fprintf(stderr, "%s", usage); + return 1; + } + else + input_name = xstrdup(argv[optind]); + } + else { + fprintf(stderr, "%s", usage); + return 1; + } + + if(debuglevel) + { + setbuf(stdout,0); + setbuf(stderr,0); + } + + parser_debug = 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 (!typelib_name && do_typelib) { + typelib_name = dup_basename(input_name, ".idl"); + strcat(typelib_name, ".tlb"); + } + + if (!proxy_name && do_proxies) { + proxy_name = dup_basename(input_name, ".idl"); + strcat(proxy_name, "_p.c"); + } + + if (!client_name && do_client) { + client_name = dup_basename(input_name, ".idl"); + strcat(client_name, "_c.c"); + } + + if (!server_name && do_server) { + server_name = dup_basename(input_name, ".idl"); + strcat(server_name, "_s.c"); + } + + if (!idfile_name && do_idfile) { + idfile_name = dup_basename(input_name, ".idl"); + strcat(idfile_name, "_i.c"); + } + + if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c"); + if (do_client) client_token = dup_basename_token(client_name,"_c.c"); + if (do_server) server_token = dup_basename_token(server_name,"_s.c"); + + wpp_add_cmdline_define("__WIDL__"); + + atexit(rm_tempfile); + if (!no_preprocess) + { + chat("Starting preprocess\n"); + + if (!preprocess_only) + { + ret = wpp_parse_temp( input_name, header_name, &temp_name ); + } + else + { + ret = wpp_parse( input_name, stdout ); + } + + if(ret) exit(1); + if(preprocess_only) exit(0); + if(!(parser_in = fopen(temp_name, "r"))) { + fprintf(stderr, "Could not open %s for input\n", temp_name); + return 1; + } + } + else { + if(!(parser_in = fopen(input_name, "r"))) { + fprintf(stderr, "Could not open %s for input\n", input_name); + return 1; + } + } + + if(do_header) { + header_token = make_token(header_name); + + if(!(header = fopen(header_name, "w"))) { + fprintf(stderr, "Could not open %s for output\n", header_name); + return 1; + } + fprintf(header, "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); + fprintf(header, "#include \n" ); + fprintf(header, "#include \n\n" ); + fprintf(header, "#ifndef __WIDL_%s\n", header_token); + fprintf(header, "#define __WIDL_%s\n", header_token); + start_cplusplus_guard(header); + } + + if (local_stubs_name) { + local_stubs = fopen(local_stubs_name, "w"); + if (!local_stubs) { + fprintf(stderr, "Could not open %s for output\n", local_stubs_name); + return 1; + } + fprintf(local_stubs, "/* call_as/local stubs for %s */\n\n", input_name); + fprintf(local_stubs, "#include \n"); + fprintf(local_stubs, "#include \"%s\"\n\n", header_name); + } + + if (do_idfile) { + idfile_token = make_token(idfile_name); + + idfile = fopen(idfile_name, "w"); + if (! idfile) { + fprintf(stderr, "Could not open %s for output\n", idfile_name); + return 1; + } + + fprintf(idfile, "/*** Autogenerated by WIDL %s ", PACKAGE_VERSION); + fprintf(idfile, "from %s - Do not edit ***/\n\n", input_name); + fprintf(idfile, "#include \n"); + fprintf(idfile, "#include \n\n"); + fprintf(idfile, "#include \n\n"); + start_cplusplus_guard(idfile); + } + + init_types(); + ret = parser_parse(); + + if(do_header) { + fprintf(header, "/* Begin additional prototypes for all interfaces */\n"); + fprintf(header, "\n"); + write_user_types(); + write_context_handle_rundowns(); + fprintf(header, "\n"); + fprintf(header, "/* End additional prototypes */\n"); + fprintf(header, "\n"); + end_cplusplus_guard(header); + fprintf(header, "#endif /* __WIDL_%s */\n", header_token); + fclose(header); + } + + if (local_stubs) { + fclose(local_stubs); + } + + if (do_idfile) { + fprintf(idfile, "\n"); + end_cplusplus_guard(idfile); + + fclose(idfile); + } + + fclose(parser_in); + + if(ret) { + exit(1); + } + + /* Everything has been done successfully, don't delete any files. */ + set_everything(FALSE); + local_stubs_name = NULL; + + return 0; +} + +static void rm_tempfile(void) +{ + abort_import(); + if(temp_name) + unlink(temp_name); + if (do_header) + unlink(header_name); + if (local_stubs_name) + unlink(local_stubs_name); + if (do_client) + unlink(client_name); + if (do_server) + unlink(server_name); + if (do_idfile) + unlink(idfile_name); + if (do_proxies) + unlink(proxy_name); + if (do_typelib) + unlink(typelib_name); +} diff --git a/reactos/tools/widl_20080105/widl.h b/reactos/tools/widl_20080105/widl.h new file mode 100644 index 00000000000..924b67a3d88 --- /dev/null +++ b/reactos/tools/widl_20080105/widl.h @@ -0,0 +1,76 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WIDL_WIDL_H +#define __WIDL_WIDL_H + +#include "widltypes.h" + +#include + +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 int do_everything; +extern int do_header; +extern int do_typelib; +extern int do_proxies; +extern int do_client; +extern int do_server; +extern int do_idfile; +extern int do_dlldata; +extern int old_names; + +extern char *input_name; +extern char *header_name; +extern char *local_stubs_name; +extern char *typelib_name; +extern char *dlldata_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 const char *prefix_client; +extern const char *prefix_server; +extern time_t now; + +extern int line_number; +extern int char_number; + +extern FILE* header; +extern FILE* local_stubs; +extern FILE* idfile; + +extern void write_proxies(ifref_list_t *ifaces); +extern void write_client(ifref_list_t *ifaces); +extern void write_server(ifref_list_t *ifaces); +extern void write_dlldata(ifref_list_t *ifaces); + +#endif diff --git a/reactos/tools/widl_20080105/widl.mak b/reactos/tools/widl_20080105/widl.mak new file mode 100644 index 00000000000..de6813ac536 --- /dev/null +++ b/reactos/tools/widl_20080105/widl.mak @@ -0,0 +1,131 @@ +WIDL_BASE = $(TOOLS_BASE)$(SEP)widl +WIDL_BASE_ = $(WIDL_BASE)$(SEP) +WIDL_INT = $(INTERMEDIATE_)$(WIDL_BASE) +WIDL_INT_ = $(WIDL_INT)$(SEP) +WIDL_OUT = $(OUTPUT_)$(WIDL_BASE) +WIDL_OUT_ = $(WIDL_OUT)$(SEP) + +$(WIDL_INT): | $(TOOLS_INT) + $(ECHO_MKDIR) + ${mkdir} $@ + +ifneq ($(INTERMEDIATE),$(OUTPUT)) +$(WIDL_OUT): | $(TOOLS_OUT) + $(ECHO_MKDIR) + ${mkdir} $@ +endif + +WIDL_PORT_BASE = $(WIDL_BASE)$(SEP)port +WIDL_PORT_BASE_ = $(WIDL_PORT_BASE)$(SEP) +WIDL_PORT_INT = $(INTERMEDIATE_)$(WIDL_PORT_BASE) +WIDL_PORT_INT_ = $(WIDL_PORT_INT)$(SEP) +WIDL_PORT_OUT = $(OUTPUT_)$(WIDL_PORT_BASE) +WIDL_PORT_OUT_ = $(WIDL_PORT_OUT)$(SEP) + +$(WIDL_PORT_INT): | $(WIDL_INT) + $(ECHO_MKDIR) + ${mkdir} $@ + +ifneq ($(INTERMEDIATE),$(OUTPUT)) +$(WIDL_PORT_OUT): | $(WIDL_OUT) + $(ECHO_MKDIR) + ${mkdir} $@ +endif + +WIDL_TARGET = \ + $(WIDL_OUT_)widl$(EXEPOSTFIX) + +WIDL_DEPENDS = $(BUILDNO_H) + +WIDL_SOURCES = $(addprefix $(WIDL_BASE_), \ + client.c \ + hash.c \ + header.c \ + proxy.c \ + server.c \ + typegen.c \ + typelib.c \ + utils.c \ + widl.c \ + write_msft.c \ + parser.yy.c \ + parser.tab.c \ + port$(SEP)mkstemps.c \ + ) + +WIDL_OBJECTS = \ + $(addprefix $(INTERMEDIATE_), $(WIDL_SOURCES:.c=.o)) + +WIDL_HOST_CFLAGS = $(TOOLS_CFLAGS) \ + -DINT16=SHORT -D__USE_W32API -DYYDEBUG=1 -D__REACTOS__=1 \ + -I$(WIDL_BASE) -I$(WPP_BASE) \ + -Iinclude/reactos/wine -Iinclude/reactos -Iinclude -Iinclude/psdk \ + -I$(INTERMEDIATE_)include + +WIDL_HOST_LFLAGS = $(TOOLS_LFLAGS) + +WIDL_LIBS = $(WPP_TARGET) + +.PHONY: widl +widl: $(WIDL_TARGET) + +$(WIDL_TARGET): $(WIDL_OBJECTS) $(WIDL_LIBS) | $(WIDL_OUT) + $(ECHO_LD) + ${host_gcc} $(WIDL_OBJECTS) $(WIDL_LIBS) $(WIDL_HOST_LFLAGS) -o $@ + +$(WIDL_INT_)client.o: $(WIDL_BASE_)client.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)hash.o: $(WIDL_BASE_)hash.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)header.o: $(WIDL_BASE_)header.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)proxy.o: $(WIDL_BASE_)proxy.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)server.o: $(WIDL_BASE_)server.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)typegen.o: $(WIDL_BASE_)typegen.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)typelib.o: $(WIDL_BASE_)typelib.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)utils.o: $(WIDL_BASE_)utils.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)widl.o: $(WIDL_BASE_)widl.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)write_msft.o: $(WIDL_BASE_)write_msft.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)parser.yy.o: $(WIDL_BASE_)parser.yy.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_INT_)parser.tab.o: $(WIDL_BASE_)parser.tab.c $(WIDL_DEPENDS) | $(WIDL_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +$(WIDL_PORT_INT_)mkstemps.o: $(WIDL_PORT_BASE_)mkstemps.c $(WIDL_DEPENDS) | $(WIDL_PORT_INT) + $(ECHO_CC) + ${host_gcc} $(WIDL_HOST_CFLAGS) -c $< -o $@ + +.PHONY: widl_clean +widl_clean: + -@$(rm) $(WIDL_TARGET) $(WIDL_OBJECTS) 2>$(NUL) +clean: widl_clean diff --git a/reactos/tools/widl_20080105/widltypes.h b/reactos/tools/widl_20080105/widltypes.h new file mode 100644 index 00000000000..6930f711719 --- /dev/null +++ b/reactos/tools/widl_20080105/widltypes.h @@ -0,0 +1,330 @@ +/* + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WIDL_WIDLTYPES_H +#define __WIDL_WIDLTYPES_H + +#include +#include "guiddef.h" +#include "wine/rpcfc.h" +#include "wine/list.h" + +#ifndef UUID_DEFINED +#define UUID_DEFINED +typedef GUID UUID; +#endif + +#define TRUE 1 +#define FALSE 0 + +typedef struct _attr_t attr_t; +typedef struct _expr_t expr_t; +typedef struct _type_t type_t; +typedef struct _typeref_t typeref_t; +typedef struct _var_t var_t; +typedef struct _pident_t pident_t; +typedef struct _func_t func_t; +typedef struct _ifref_t ifref_t; +typedef struct _typelib_entry_t typelib_entry_t; +typedef struct _importlib_t importlib_t; +typedef struct _importinfo_t importinfo_t; +typedef struct _typelib_t typelib_t; +typedef struct _user_type_t user_type_t; +typedef struct _user_type_t context_handle_t; + +typedef struct list attr_list_t; +typedef struct list str_list_t; +typedef struct list func_list_t; +typedef struct list expr_list_t; +typedef struct list var_list_t; +typedef struct list pident_list_t; +typedef struct list ifref_list_t; +typedef struct list array_dims_t; +typedef struct list user_type_list_t; +typedef struct list context_handle_list_t; + +enum attr_type +{ + ATTR_AGGREGATABLE, + ATTR_APPOBJECT, + ATTR_ASYNC, + ATTR_AUTO_HANDLE, + ATTR_BINDABLE, + ATTR_CALLAS, + ATTR_CASE, + ATTR_CONTEXTHANDLE, + ATTR_CONTROL, + ATTR_DEFAULT, + ATTR_DEFAULTCOLLELEM, + ATTR_DEFAULTVALUE_EXPR, + ATTR_DEFAULTVALUE_STRING, + ATTR_DEFAULTVTABLE, + ATTR_DISPINTERFACE, + ATTR_DISPLAYBIND, + ATTR_DLLNAME, + ATTR_DUAL, + ATTR_ENDPOINT, + ATTR_ENTRY_ORDINAL, + ATTR_ENTRY_STRING, + ATTR_EXPLICIT_HANDLE, + ATTR_HANDLE, + ATTR_HELPCONTEXT, + ATTR_HELPFILE, + ATTR_HELPSTRING, + ATTR_HELPSTRINGCONTEXT, + ATTR_HELPSTRINGDLL, + ATTR_HIDDEN, + ATTR_ID, + ATTR_IDEMPOTENT, + ATTR_IIDIS, + ATTR_IMMEDIATEBIND, + ATTR_IMPLICIT_HANDLE, + ATTR_IN, + ATTR_INPUTSYNC, + ATTR_LENGTHIS, + ATTR_LOCAL, + ATTR_NONBROWSABLE, + ATTR_NONCREATABLE, + ATTR_NONEXTENSIBLE, + ATTR_OBJECT, + ATTR_ODL, + ATTR_OLEAUTOMATION, + ATTR_OPTIONAL, + ATTR_OUT, + ATTR_POINTERDEFAULT, + ATTR_POINTERTYPE, + ATTR_PROPGET, + ATTR_PROPPUT, + ATTR_PROPPUTREF, + ATTR_PUBLIC, + ATTR_RANGE, + ATTR_READONLY, + ATTR_REQUESTEDIT, + ATTR_RESTRICTED, + ATTR_RETVAL, + ATTR_SIZEIS, + ATTR_SOURCE, + ATTR_STRING, + ATTR_SWITCHIS, + ATTR_SWITCHTYPE, + ATTR_TRANSMITAS, + ATTR_UUID, + ATTR_V1ENUM, + ATTR_VARARG, + ATTR_VERSION, + ATTR_WIREMARSHAL +}; + +enum expr_type +{ + EXPR_VOID, + EXPR_NUM, + EXPR_HEXNUM, + EXPR_DOUBLE, + EXPR_IDENTIFIER, + EXPR_NEG, + EXPR_NOT, + EXPR_PPTR, + EXPR_CAST, + EXPR_SIZEOF, + EXPR_SHL, + EXPR_SHR, + EXPR_MUL, + EXPR_DIV, + EXPR_ADD, + EXPR_SUB, + EXPR_AND, + EXPR_OR, + EXPR_COND, + EXPR_TRUEFALSE, + EXPR_ADDRESSOF, +}; + +enum type_kind +{ + TKIND_PRIMITIVE = -1, + TKIND_ENUM, + TKIND_RECORD, + TKIND_MODULE, + TKIND_INTERFACE, + TKIND_DISPATCH, + TKIND_COCLASS, + TKIND_ALIAS, + TKIND_UNION, + TKIND_MAX +}; + +struct str_list_entry_t +{ + char *str; + struct list entry; +}; + +struct _attr_t { + enum attr_type type; + union { + unsigned long ival; + void *pval; + } u; + /* parser-internal */ + struct list entry; +}; + +struct _expr_t { + enum expr_type type; + const expr_t *ref; + union { + long lval; + double dval; + const char *sval; + const expr_t *ext; + type_t *tref; + } u; + const expr_t *ext2; + int is_const; + long cval; + /* parser-internal */ + struct list entry; +}; + +struct _type_t { + const char *name; + enum type_kind kind; + unsigned char type; + struct _type_t *ref; + const attr_list_t *attrs; + func_list_t *funcs; /* interfaces and modules */ + var_list_t *fields; /* interfaces, structures and enumerations */ + ifref_list_t *ifaces; /* coclasses */ + unsigned long dim; /* array dimension */ + expr_t *size_is, *length_is; + type_t *orig; /* dup'd types */ + unsigned int typestring_offset; + unsigned int ptrdesc; /* used for complex structs */ + int typelib_idx; + unsigned int declarray : 1; /* if declared as an array */ + unsigned int ignore : 1; + unsigned int is_const : 1; + unsigned int defined : 1; + unsigned int written : 1; + unsigned int user_types_registered : 1; + unsigned int tfswrite : 1; /* if the type needs to be written to the TFS */ + int sign : 2; +}; + +struct _var_t { + char *name; + type_t *type; + var_list_t *args; /* for function pointers */ + attr_list_t *attrs; + expr_t *eval; + + /* parser-internal */ + struct list entry; +}; + +struct _pident_t { + var_t *var; + int ptr_level; + + /* parser-internal */ + struct list entry; +}; + +struct _func_t { + var_t *def; + var_list_t *args; + int ignore, idx; + + /* parser-internal */ + struct list entry; +}; + +struct _ifref_t { + type_t *iface; + attr_list_t *attrs; + + /* parser-internal */ + struct list entry; +}; + +struct _typelib_entry_t { + type_t *type; + struct list entry; +}; + +struct _importinfo_t { + int offset; + GUID guid; + int flags; + int id; + + char *name; + + importlib_t *importlib; +}; + +struct _importlib_t { + char *name; + + int version; + GUID guid; + + importinfo_t *importinfos; + int ntypeinfos; + + int allocated; + + struct list entry; +}; + +struct _typelib_t { + char *name; + char *filename; + attr_list_t *attrs; + struct list entries; + struct list importlibs; +}; + +struct _user_type_t { + struct list entry; + const char *name; +}; + +extern unsigned char pointer_default; + +extern user_type_list_t user_type_list; +void check_for_user_types_and_context_handles(const var_list_t *list); + +void init_types(void); +type_t *alloc_type(void); +void set_all_tfswrite(int val); + +type_t *duptype(type_t *t, int dupname); +type_t *alias(type_t *t, const char *name); + +int is_ptr(const type_t *t); +int is_array(const type_t *t); +int is_var_ptr(const var_t *v); +int cant_be_null(const var_t *v); +int is_struct(unsigned char tc); +int is_union(unsigned char tc); + +#endif diff --git a/reactos/tools/widl_20080105/write_msft.c b/reactos/tools/widl_20080105/write_msft.c new file mode 100644 index 00000000000..f5ea2f7f27b --- /dev/null +++ b/reactos/tools/widl_20080105/write_msft.c @@ -0,0 +1,2533 @@ +/* + * Typelib v2 (MSFT) generation + * + * Copyright 2004 Alastair Bridgewater + * 2004, 2005 Huw Davies + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * -------------------------------------------------------------------------------------- + * Known problems: + * + * Badly incomplete. + * + * Only works on little-endian systems. + * + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include +#include +#include +#include + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "winerror.h" +#include "windef.h" +#include "winbase.h" +#include "winnls.h" + +#include "widltypes.h" +#include "typelib.h" +#include "typelib_struct.h" +#include "utils.h" +#include "header.h" +#include "hash.h" + +enum MSFT_segment_index { + MSFT_SEG_TYPEINFO = 0, /* type information */ + MSFT_SEG_IMPORTINFO, /* import information */ + MSFT_SEG_IMPORTFILES, /* import filenames */ + MSFT_SEG_REFERENCES, /* references (?) */ + MSFT_SEG_GUIDHASH, /* hash table for guids? */ + MSFT_SEG_GUID, /* guid storage */ + MSFT_SEG_NAMEHASH, /* hash table for names */ + MSFT_SEG_NAME, /* name storage */ + MSFT_SEG_STRING, /* string storage */ + MSFT_SEG_TYPEDESC, /* type descriptions */ + MSFT_SEG_ARRAYDESC, /* array descriptions */ + MSFT_SEG_CUSTDATA, /* custom data */ + MSFT_SEG_CUSTDATAGUID, /* custom data guids */ + MSFT_SEG_UNKNOWN, /* ??? */ + MSFT_SEG_UNKNOWN2, /* ??? */ + MSFT_SEG_MAX /* total number of segments */ +}; + +typedef struct tagMSFT_ImpFile { + int guid; + LCID lcid; + int version; + char filename[0]; /* preceded by two bytes of encoded (length << 2) + flags in the low two bits. */ +} MSFT_ImpFile; + +typedef struct _msft_typelib_t +{ + typelib_t *typelib; + MSFT_Header typelib_header; + MSFT_pSeg typelib_segdir[MSFT_SEG_MAX]; + char *typelib_segment_data[MSFT_SEG_MAX]; + int typelib_segment_block_length[MSFT_SEG_MAX]; + + INT typelib_typeinfo_offsets[0x200]; /* Hope that's enough. */ + + INT *typelib_namehash_segment; + INT *typelib_guidhash_segment; + + INT help_string_dll_offset; + + struct _msft_typeinfo_t *typeinfos; + struct _msft_typeinfo_t *last_typeinfo; +} msft_typelib_t; + +typedef struct _msft_typeinfo_t +{ + msft_typelib_t *typelib; + MSFT_TypeInfoBase *typeinfo; + + int typekind; + + unsigned int var_data_allocated; + int *var_data; + + unsigned int func_data_allocated; + int *func_data; + + int vars_allocated; + int *var_indices; + int *var_names; + int *var_offsets; + + int funcs_allocated; + int *func_indices; + int *func_names; + int *func_offsets; + + int datawidth; + + struct _msft_typeinfo_t *next_typeinfo; +} msft_typeinfo_t; + + + +/*================== Internal functions ===================================*/ + +/**************************************************************************** + * ctl2_init_header + * + * Initializes the type library header of a new typelib. + */ +static void ctl2_init_header( + msft_typelib_t *typelib) /* [I] The typelib to initialize. */ +{ + typelib->typelib_header.magic1 = 0x5446534d; + typelib->typelib_header.magic2 = 0x00010002; + typelib->typelib_header.posguid = -1; + typelib->typelib_header.lcid = 0x0409; /* or do we use the current one? */ + typelib->typelib_header.lcid2 = 0x0; + typelib->typelib_header.varflags = 0x40; + typelib->typelib_header.version = 0; + typelib->typelib_header.flags = 0; + typelib->typelib_header.nrtypeinfos = 0; + typelib->typelib_header.helpstring = -1; + typelib->typelib_header.helpstringcontext = 0; + typelib->typelib_header.helpcontext = 0; + typelib->typelib_header.nametablecount = 0; + typelib->typelib_header.nametablechars = 0; + typelib->typelib_header.NameOffset = -1; + typelib->typelib_header.helpfile = -1; + typelib->typelib_header.CustomDataOffset = -1; + typelib->typelib_header.res44 = 0x20; + typelib->typelib_header.res48 = 0x80; + typelib->typelib_header.dispatchpos = -1; + typelib->typelib_header.nimpinfos = 0; +} + +/**************************************************************************** + * ctl2_init_segdir + * + * Initializes the segment directory of a new typelib. + */ +static void ctl2_init_segdir( + msft_typelib_t *typelib) /* [I] The typelib to initialize. */ +{ + int i; + MSFT_pSeg *segdir; + + segdir = &typelib->typelib_segdir[MSFT_SEG_TYPEINFO]; + + for (i = 0; i < 15; i++) { + segdir[i].offset = -1; + segdir[i].length = 0; + segdir[i].res08 = -1; + segdir[i].res0c = 0x0f; + } +} + +/**************************************************************************** + * ctl2_hash_guid + * + * Generates a hash key from a GUID. + * + * RETURNS + * + * The hash key for the GUID. + */ +static int ctl2_hash_guid( + REFGUID guid) /* [I] The guid to hash. */ +{ + int hash; + int i; + + hash = 0; + for (i = 0; i < 8; i ++) { + hash ^= ((const short *)guid)[i]; + } + + return hash & 0x1f; +} + +/**************************************************************************** + * ctl2_find_guid + * + * Locates a guid in a type library. + * + * RETURNS + * + * The offset into the GUID segment of the guid, or -1 if not found. + */ +static int ctl2_find_guid( + msft_typelib_t *typelib, /* [I] The typelib to operate against. */ + int hash_key, /* [I] The hash key for the guid. */ + REFGUID guid) /* [I] The guid to find. */ +{ + int offset; + MSFT_GuidEntry *guidentry; + + offset = typelib->typelib_guidhash_segment[hash_key]; + while (offset != -1) { + guidentry = (MSFT_GuidEntry *)&typelib->typelib_segment_data[MSFT_SEG_GUID][offset]; + + if (!memcmp(guidentry, guid, sizeof(GUID))) return offset; + + offset = guidentry->next_hash; + } + + return offset; +} + +/**************************************************************************** + * ctl2_find_name + * + * Locates a name in a type library. + * + * RETURNS + * + * The offset into the NAME segment of the name, or -1 if not found. + * + * NOTES + * + * The name must be encoded as with ctl2_encode_name(). + */ +static int ctl2_find_name( + msft_typelib_t *typelib, /* [I] The typelib to operate against. */ + char *name) /* [I] The encoded name to find. */ +{ + int offset; + int *namestruct; + + offset = typelib->typelib_namehash_segment[name[2] & 0x7f]; + while (offset != -1) { + namestruct = (int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][offset]; + + if (!((namestruct[2] ^ *((int *)name)) & 0xffff00ff)) { + /* hash codes and lengths match, final test */ + if (!strncasecmp(name+4, (void *)(namestruct+3), name[0])) break; + } + + /* move to next item in hash bucket */ + offset = namestruct[1]; + } + + return offset; +} + +/**************************************************************************** + * ctl2_encode_name + * + * Encodes a name string to a form suitable for storing into a type library + * or comparing to a name stored in a type library. + * + * RETURNS + * + * The length of the encoded name, including padding and length+hash fields. + * + * NOTES + * + * Will throw an exception if name or result are NULL. Is not multithread + * safe in the slightest. + */ +static int ctl2_encode_name( + msft_typelib_t *typelib, /* [I] The typelib to operate against (used for LCID only). */ + const char *name, /* [I] The name string to encode. */ + char **result) /* [O] A pointer to a pointer to receive the encoded name. */ +{ + int length; + static char converted_name[0x104]; + int offset; + int value; + + length = strlen(name); + memcpy(converted_name + 4, name, length); + converted_name[0] = length & 0xff; + + converted_name[length + 4] = 0; + + converted_name[1] = 0x00; + + value = lhash_val_of_name_sys(typelib->typelib_header.varflags & 0x0f, typelib->typelib_header.lcid, converted_name + 4); + + converted_name[2] = value; + converted_name[3] = value >> 8; + + for (offset = (4 - length) & 3; offset; offset--) converted_name[length + offset + 3] = 0x57; + + *result = converted_name; + + return (length + 7) & ~3; +} + +/**************************************************************************** + * ctl2_encode_string + * + * Encodes a string to a form suitable for storing into a type library or + * comparing to a string stored in a type library. + * + * RETURNS + * + * The length of the encoded string, including padding and length fields. + * + * NOTES + * + * Will throw an exception if string or result are NULL. Is not multithread + * safe in the slightest. + */ +static int ctl2_encode_string( + const char *string, /* [I] The string to encode. */ + char **result) /* [O] A pointer to a pointer to receive the encoded string. */ +{ + int length; + static char converted_string[0x104]; + int offset; + + length = strlen(string); + memcpy(converted_string + 2, string, length); + converted_string[0] = length & 0xff; + converted_string[1] = (length >> 8) & 0xff; + + if(length < 3) { /* strings of this length are padded with up to 8 bytes incl the 2 byte length */ + for(offset = 0; offset < 4; offset++) + converted_string[length + offset + 2] = 0x57; + length += 4; + } + for (offset = (4 - (length + 2)) & 3; offset; offset--) converted_string[length + offset + 1] = 0x57; + + *result = converted_string; + + return (length + 5) & ~3; +} + +/**************************************************************************** + * ctl2_alloc_segment + * + * Allocates memory from a segment in a type library. + * + * RETURNS + * + * Success: The offset within the segment of the new data area. + * + * BUGS + * + * Does not (yet) handle the case where the allocated segment memory needs to grow. + */ +static int ctl2_alloc_segment( + msft_typelib_t *typelib, /* [I] The type library in which to allocate. */ + enum MSFT_segment_index segment, /* [I] The segment in which to allocate. */ + int size, /* [I] The amount to allocate. */ + int block_size) /* [I] Initial allocation block size, or 0 for default. */ +{ + int offset; + + if(!typelib->typelib_segment_data[segment]) { + if (!block_size) block_size = 0x2000; + + typelib->typelib_segment_block_length[segment] = block_size; + typelib->typelib_segment_data[segment] = xmalloc(block_size); + if (!typelib->typelib_segment_data[segment]) return -1; + memset(typelib->typelib_segment_data[segment], 0x57, block_size); + } + + while ((typelib->typelib_segdir[segment].length + size) > typelib->typelib_segment_block_length[segment]) { + char *block; + + block_size = typelib->typelib_segment_block_length[segment]; + block = xrealloc(typelib->typelib_segment_data[segment], block_size << 1); + + if (segment == MSFT_SEG_TYPEINFO) { + /* TypeInfos have a direct pointer to their memory space, so we have to fix them up. */ + msft_typeinfo_t *typeinfo; + + for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) { + typeinfo->typeinfo = (void *)&block[((char *)typeinfo->typeinfo) - typelib->typelib_segment_data[segment]]; + } + } + + memset(block + block_size, 0x57, block_size); + typelib->typelib_segment_block_length[segment] = block_size << 1; + typelib->typelib_segment_data[segment] = block; + } + + offset = typelib->typelib_segdir[segment].length; + typelib->typelib_segdir[segment].length += size; + + return offset; +} + +/**************************************************************************** + * ctl2_alloc_typeinfo + * + * Allocates and initializes a typeinfo structure in a type library. + * + * RETURNS + * + * Success: The offset of the new typeinfo. + * Failure: -1 (this is invariably an out of memory condition). + */ +static int ctl2_alloc_typeinfo( + msft_typelib_t *typelib, /* [I] The type library to allocate in. */ + int nameoffset) /* [I] The offset of the name for this typeinfo. */ +{ + int offset; + MSFT_TypeInfoBase *typeinfo; + + offset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEINFO, sizeof(MSFT_TypeInfoBase), 0); + + typelib->typelib_typeinfo_offsets[typelib->typelib_header.nrtypeinfos++] = offset; + + typeinfo = (void *)(typelib->typelib_segment_data[MSFT_SEG_TYPEINFO] + offset); + + typeinfo->typekind = (typelib->typelib_header.nrtypeinfos - 1) << 16; + typeinfo->memoffset = -1; /* should be EOF if no elements */ + typeinfo->res2 = 0; + typeinfo->res3 = -1; + typeinfo->res4 = 3; + typeinfo->res5 = 0; + typeinfo->cElement = 0; + typeinfo->res7 = 0; + typeinfo->res8 = 0; + typeinfo->res9 = 0; + typeinfo->resA = 0; + typeinfo->posguid = -1; + typeinfo->flags = 0; + typeinfo->NameOffset = nameoffset; + typeinfo->version = 0; + typeinfo->docstringoffs = -1; + typeinfo->helpstringcontext = 0; + typeinfo->helpcontext = 0; + typeinfo->oCustData = -1; + typeinfo->cbSizeVft = 0; + typeinfo->cImplTypes = 0; + typeinfo->size = 0; + typeinfo->datatype1 = -1; + typeinfo->datatype2 = 0; + typeinfo->res18 = 0; + typeinfo->res19 = -1; + + return offset; +} + +/**************************************************************************** + * ctl2_alloc_guid + * + * Allocates and initializes a GUID structure in a type library. Also updates + * the GUID hash table as needed. + * + * RETURNS + * + * Success: The offset of the new GUID. + */ +static int ctl2_alloc_guid( + msft_typelib_t *typelib, /* [I] The type library to allocate in. */ + MSFT_GuidEntry *guid) /* [I] The GUID to store. */ +{ + int offset; + MSFT_GuidEntry *guid_space; + int hash_key; + + hash_key = ctl2_hash_guid(&guid->guid); + + offset = ctl2_find_guid(typelib, hash_key, &guid->guid); + if (offset != -1) return offset; + + offset = ctl2_alloc_segment(typelib, MSFT_SEG_GUID, sizeof(MSFT_GuidEntry), 0); + + guid_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_GUID] + offset); + *guid_space = *guid; + + guid_space->next_hash = typelib->typelib_guidhash_segment[hash_key]; + typelib->typelib_guidhash_segment[hash_key] = offset; + + return offset; +} + +/**************************************************************************** + * ctl2_alloc_name + * + * Allocates and initializes a name within a type library. Also updates the + * name hash table as needed. + * + * RETURNS + * + * Success: The offset within the segment of the new name. + * Failure: -1 (this is invariably an out of memory condition). + */ +static int ctl2_alloc_name( + msft_typelib_t *typelib, /* [I] The type library to allocate in. */ + const char *name) /* [I] The name to store. */ +{ + int length; + int offset; + MSFT_NameIntro *name_space; + char *encoded_name; + + length = ctl2_encode_name(typelib, name, &encoded_name); + + offset = ctl2_find_name(typelib, encoded_name); + if (offset != -1) return offset; + + offset = ctl2_alloc_segment(typelib, MSFT_SEG_NAME, length + 8, 0); + + name_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_NAME] + offset); + name_space->hreftype = -1; + name_space->next_hash = -1; + memcpy(&name_space->namelen, encoded_name, length); + + if (typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] != -1) + name_space->next_hash = typelib->typelib_namehash_segment[encoded_name[2] & 0x7f]; + + typelib->typelib_namehash_segment[encoded_name[2] & 0x7f] = offset; + + typelib->typelib_header.nametablecount += 1; + typelib->typelib_header.nametablechars += *encoded_name; + + return offset; +} + +/**************************************************************************** + * ctl2_alloc_string + * + * Allocates and initializes a string in a type library. + * + * RETURNS + * + * Success: The offset within the segment of the new string. + * Failure: -1 (this is invariably an out of memory condition). + */ +static int ctl2_alloc_string( + msft_typelib_t *typelib, /* [I] The type library to allocate in. */ + const char *string) /* [I] The string to store. */ +{ + int length; + int offset; + char *string_space; + char *encoded_string; + + length = ctl2_encode_string(string, &encoded_string); + + for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_STRING].length; + offset += ((((typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 1] << 8) & 0xff) + | (typelib->typelib_segment_data[MSFT_SEG_STRING][offset + 0] & 0xff)) + 5) & ~3) { + if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_STRING] + offset, length)) return offset; + } + + offset = ctl2_alloc_segment(typelib, MSFT_SEG_STRING, length, 0); + + string_space = typelib->typelib_segment_data[MSFT_SEG_STRING] + offset; + memcpy(string_space, encoded_string, length); + + return offset; +} + +/**************************************************************************** + * alloc_msft_importinfo + * + * Allocates and initializes an import information structure in a type library. + * + * RETURNS + * + * Success: The offset of the new importinfo. + * Failure: -1 (this is invariably an out of memory condition). + */ +static int alloc_msft_importinfo( + msft_typelib_t *typelib, /* [I] The type library to allocate in. */ + MSFT_ImpInfo *impinfo) /* [I] The import information to store. */ +{ + int offset; + MSFT_ImpInfo *impinfo_space; + + for (offset = 0; + offset < typelib->typelib_segdir[MSFT_SEG_IMPORTINFO].length; + offset += sizeof(MSFT_ImpInfo)) { + if (!memcmp(&(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO][offset]), + impinfo, sizeof(MSFT_ImpInfo))) { + return offset; + } + } + + impinfo->flags |= typelib->typelib_header.nimpinfos++; + + offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTINFO, sizeof(MSFT_ImpInfo), 0); + + impinfo_space = (void *)(typelib->typelib_segment_data[MSFT_SEG_IMPORTINFO] + offset); + *impinfo_space = *impinfo; + + return offset; +} + +/**************************************************************************** + * alloc_importfile + * + * Allocates and initializes an import file definition in a type library. + * + * RETURNS + * + * Success: The offset of the new importinfo. + * Failure: -1 (this is invariably an out of memory condition). + */ +static int alloc_importfile( + msft_typelib_t *typelib, /* [I] The type library to allocate in. */ + int guidoffset, /* [I] The offset to the GUID for the imported library. */ + int major_version, /* [I] The major version number of the imported library. */ + int minor_version, /* [I] The minor version number of the imported library. */ + const char *filename) /* [I] The filename of the imported library. */ +{ + int length; + int offset; + MSFT_ImpFile *importfile; + char *encoded_string; + + length = ctl2_encode_string(filename, &encoded_string); + + encoded_string[0] <<= 2; + encoded_string[0] |= 1; + + for (offset = 0; offset < typelib->typelib_segdir[MSFT_SEG_IMPORTFILES].length; + offset += ((((typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xd] << 8) & 0xff) + | (typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset + 0xc] & 0xff)) >> 2) + 0xc) { + if (!memcmp(encoded_string, typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES] + offset + 0xc, length)) return offset; + } + + offset = ctl2_alloc_segment(typelib, MSFT_SEG_IMPORTFILES, length + 0xc, 0); + + importfile = (MSFT_ImpFile *)&typelib->typelib_segment_data[MSFT_SEG_IMPORTFILES][offset]; + importfile->guid = guidoffset; + importfile->lcid = typelib->typelib_header.lcid2; + importfile->version = major_version | (minor_version << 16); + memcpy(&importfile->filename, encoded_string, length); + + return offset; +} + +static void alloc_importinfo(msft_typelib_t *typelib, importinfo_t *importinfo) +{ + importlib_t *importlib = importinfo->importlib; + + chat("alloc_importinfo: %s\n", importinfo->name); + + if(!importlib->allocated) { + MSFT_GuidEntry guid; + int guid_idx; + + chat("allocating importlib %s\n", importlib->name); + + importlib->allocated = -1; + + memcpy(&guid.guid, &importlib->guid, sizeof(GUID)); + guid.hreftype = 2; + + guid_idx = ctl2_alloc_guid(typelib, &guid); + + alloc_importfile(typelib, guid_idx, importlib->version&0xffff, + importlib->version>>16, importlib->name); + } + + if(importinfo->offset == -1 || !(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID)) { + MSFT_ImpInfo impinfo; + + impinfo.flags = importinfo->flags; + impinfo.oImpFile = 0; + + if(importinfo->flags & MSFT_IMPINFO_OFFSET_IS_GUID) { + MSFT_GuidEntry guid; + + guid.hreftype = 0; + memcpy(&guid.guid, &importinfo->guid, sizeof(GUID)); + + impinfo.oGuid = ctl2_alloc_guid(typelib, &guid); + + importinfo->offset = alloc_msft_importinfo(typelib, &impinfo); + + typelib->typelib_segment_data[MSFT_SEG_GUID][impinfo.oGuid+sizeof(GUID)] + = importinfo->offset+1; + + if(!strcmp(importinfo->name, "IDispatch")) + typelib->typelib_header.dispatchpos = importinfo->offset+1; + }else { + impinfo.oGuid = importinfo->id; + importinfo->offset = alloc_msft_importinfo(typelib, &impinfo); + } + } +} + +static importinfo_t *find_importinfo(msft_typelib_t *typelib, const char *name) +{ + importlib_t *importlib; + int i; + + chat("search importlib %s\n", name); + + if(!name) + return NULL; + + LIST_FOR_EACH_ENTRY( importlib, &typelib->typelib->importlibs, importlib_t, entry ) + { + for(i=0; i < importlib->ntypeinfos; i++) { + if(!strcmp(name, importlib->importinfos[i].name)) { + chat("Found %s in importlib.\n", name); + return importlib->importinfos+i; + } + } + } + + return NULL; +} + +static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure); +static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface); +static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration); +static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls); +static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface); + + +/**************************************************************************** + * encode_type + * + * Encodes a type, storing information in the TYPEDESC and ARRAYDESC + * segments as needed. + * + * RETURNS + * + * Success: 0. + * Failure: -1. + */ +static int encode_type( + msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */ + int vt, /* [I] vt to encode */ + type_t *type, /* [I] type */ + int *encoded_type, /* [O] The encoded type description. */ + int *width, /* [O] The width of the type, or NULL. */ + int *alignment, /* [O] The alignment of the type, or NULL. */ + int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */ +{ + int default_type; + int scratch; + int typeoffset; + int *typedata; + int target_type; + int child_size = 0; + + chat("encode_type vt %d type %p\n", vt, type); + + default_type = 0x80000000 | (vt << 16) | vt; + if (!width) width = &scratch; + if (!alignment) alignment = &scratch; + if (!decoded_size) decoded_size = &scratch; + + + switch (vt) { + case VT_I1: + case VT_UI1: + *encoded_type = default_type; + *width = 1; + *alignment = 1; + break; + + case VT_INT: + *encoded_type = 0x80000000 | (VT_I4 << 16) | VT_INT; + if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) { + *width = 2; + *alignment = 2; + } else { + *width = 4; + *alignment = 4; + } + break; + + case VT_UINT: + *encoded_type = 0x80000000 | (VT_UI4 << 16) | VT_UINT; + if ((typelib->typelib_header.varflags & 0x0f) == SYS_WIN16) { + *width = 2; + *alignment = 2; + } else { + *width = 4; + *alignment = 4; + } + break; + + case VT_UI2: + case VT_I2: + case VT_BOOL: + *encoded_type = default_type; + *width = 2; + *alignment = 2; + break; + + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_ERROR: + case VT_BSTR: + case VT_HRESULT: + *encoded_type = default_type; + *width = 4; + *alignment = 4; + break; + + case VT_R8: + case VT_I8: + case VT_UI8: + *encoded_type = default_type; + *width = 8; + *alignment = 8; + break; + + case VT_CY: + case VT_DATE: + *encoded_type = default_type; + *width = 8; + *alignment = 8; + break; + + case VT_VOID: + *encoded_type = 0x80000000 | (VT_EMPTY << 16) | vt; + *width = 0; + *alignment = 1; + break; + + case VT_UNKNOWN: + case VT_DISPATCH: + *encoded_type = default_type; + *width = 4; + *alignment = 4; + break; + + case VT_VARIANT: + *encoded_type = default_type; + break; + + case VT_LPSTR: + case VT_LPWSTR: + *encoded_type = 0xfffe0000 | vt; + *width = 4; + *alignment = 4; + break; + + case VT_PTR: + { + int next_vt; + for(next_vt = 0; type->ref; type = type->ref) { + next_vt = get_type_vt(type->ref); + if (next_vt != 0) + break; + } + /* if no type found then it must be void */ + if (next_vt == 0) + next_vt = VT_VOID; + + encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size); + if(type->ref && (type->ref->type == RPC_FC_IP)) { + chat("encode_type: skipping ptr\n"); + *encoded_type = target_type; + *width = 4; + *alignment = 4; + *decoded_size = child_size; + break; + } + + for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break; + } + + if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { + int mix_field; + + if (target_type & 0x80000000) { + mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF; + } else { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; + mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; + } + + typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + + typedata[0] = (mix_field << 16) | VT_PTR; + typedata[1] = target_type; + } + + *encoded_type = typeoffset; + + *width = 4; + *alignment = 4; + *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; + break; + } + + + case VT_SAFEARRAY: + { + int next_vt; + + /* skip over SAFEARRAY type straight to element type */ + type = type->ref; + + for(next_vt = 0; type->ref; type = type->ref) { + next_vt = get_type_vt(type->ref); + if (next_vt != 0) + break; + } + + encode_type(typelib, next_vt, type->ref, &target_type, NULL, NULL, &child_size); + + for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break; + } + + if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { + int mix_field; + + if (target_type & 0x80000000) { + mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY; + } else { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; + mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; + } + + typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + + typedata[0] = (mix_field << 16) | VT_SAFEARRAY; + typedata[1] = target_type; + } + + *encoded_type = typeoffset; + + *width = 4; + *alignment = 4; + *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; + break; + } + + + case VT_USERDEFINED: + { + int typeinfo_offset; + + /* typedef'd types without attributes aren't included in the typelib */ + while (type->typelib_idx < 0 && type->kind == TKIND_ALIAS && ! type->attrs) + type = type->orig; + + chat("encode_type: VT_USERDEFINED - type %p name = %s type->type %d idx %d\n", type, + type->name, type->type, type->typelib_idx); + + if(type->typelib_idx == -1) { + chat("encode_type: trying to ref not added type\n"); + switch(type->type) { + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_BOGUS_STRUCT: + add_structure_typeinfo(typelib, type); + break; + case RPC_FC_IP: + add_interface_typeinfo(typelib, type); + break; + case RPC_FC_ENUM16: + add_enum_typeinfo(typelib, type); + break; + case 0: + if (type->kind == TKIND_COCLASS) + add_coclass_typeinfo(typelib, type); + else if (type->kind == TKIND_DISPATCH) + add_dispinterface_typeinfo(typelib, type); + else + error("encode_type: VT_USERDEFINED - can't yet add typedef's on the fly\n"); + break; + default: + error("encode_type: VT_USERDEFINED - unhandled type %d\n", type->type); + } + } + + typeinfo_offset = typelib->typelib_typeinfo_offsets[type->typelib_idx]; + for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == typeinfo_offset)) break; + } + + if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { + typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + + typedata[0] = (0x7fff << 16) | VT_USERDEFINED; + typedata[1] = typeinfo_offset; + } + + *encoded_type = typeoffset; + *width = 0; + *alignment = 1; + + if(type->type == RPC_FC_IP) { + for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + if ((typedata[0] == ((0x7fff << 16) | VT_PTR)) && (typedata[1] == *encoded_type)) break; + } + if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { + typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + + typedata[0] = (0x7fff << 16) | VT_PTR; + typedata[1] = *encoded_type; + } + *encoded_type = typeoffset; + *width = 4; + *alignment = 4; + *decoded_size += 8; + } + break; + } + + default: + error("encode_type: unrecognized type %d.\n", vt); + *encoded_type = default_type; + *width = 0; + *alignment = 1; + break; + } + + return 0; +} + +static void dump_type(type_t *t) +{ + chat("dump_type: %p name %s type %d ref %p attrs %p\n", t, t->name, t->type, t->ref, t->attrs); + if(t->ref) dump_type(t->ref); +} + +static int encode_var( + msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */ + type_t *type, /* [I] The type description to encode. */ + var_t *var, /* [I] The var to encode. */ + int *encoded_type, /* [O] The encoded type description. */ + int *width, /* [O] The width of the type, or NULL. */ + int *alignment, /* [O] The alignment of the type, or NULL. */ + int *decoded_size) /* [O] The total size of the unencoded TYPEDESCs, including nested descs. */ +{ + int typeoffset; + int *typedata; + int target_type; + int child_size; + int vt; + int scratch; + + if (!width) width = &scratch; + if (!alignment) alignment = &scratch; + if (!decoded_size) decoded_size = &scratch; + *decoded_size = 0; + + chat("encode_var: var %p type %p type->name %s type->ref %p\n", + var, type, type->name ? type->name : "NULL", type->ref); + + if (type->declarray) { + int num_dims, elements = 1, arrayoffset; + type_t *atype; + int *arraydata; + + num_dims = 0; + for (atype = type; atype->declarray; atype = atype->ref) + ++num_dims; + + chat("array with %d dimensions\n", num_dims); + encode_var(typelib, atype, var, &target_type, width, alignment, NULL); + arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0); + arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset]; + + arraydata[0] = target_type; + arraydata[1] = num_dims; + arraydata[1] |= ((num_dims * 2 * sizeof(long)) << 16); + + arraydata += 2; + for (atype = type; atype->declarray; atype = atype->ref) + { + arraydata[0] = atype->dim; + arraydata[1] = 0; + arraydata += 2; + elements *= atype->dim; + } + + typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + + typedata[0] = (0x7ffe << 16) | VT_CARRAY; + typedata[1] = arrayoffset; + + *encoded_type = typeoffset; + *width = *width * elements; + *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/; + return 0; + } + + vt = get_type_vt(type); + if (vt == VT_PTR) { + int skip_ptr = encode_var(typelib, type->ref, var, &target_type, NULL, NULL, &child_size); + + if(skip_ptr == 2) { + chat("encode_var: skipping ptr\n"); + *encoded_type = target_type; + *decoded_size = child_size; + *width = 4; + *alignment = 4; + return 0; + } + + for (typeoffset = 0; typeoffset < typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break; + } + + if (typeoffset == typelib->typelib_segdir[MSFT_SEG_TYPEDESC].length) { + int mix_field; + + if (target_type & 0x80000000) { + mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF; + } else { + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type]; + mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe; + } + + typeoffset = ctl2_alloc_segment(typelib, MSFT_SEG_TYPEDESC, 8, 0); + typedata = (void *)&typelib->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset]; + + typedata[0] = (mix_field << 16) | VT_PTR; + typedata[1] = target_type; + } + + *encoded_type = typeoffset; + + *width = 4; + *alignment = 4; + *decoded_size = 8 /*sizeof(TYPEDESC)*/ + child_size; + return 0; + } + + dump_type(type); + + encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size); + if(type->type == RPC_FC_IP) return 2; + return 0; +} + +static unsigned long get_ulong_val(unsigned long val, int vt) +{ + switch(vt) { + case VT_I2: + case VT_BOOL: + case VT_UI2: + return val & 0xffff; + case VT_I1: + case VT_UI1: + return val & 0xff; + } + + return val; +} + +static void write_value(msft_typelib_t* typelib, int *out, int vt, void *value) +{ + switch(vt) { + case VT_I2: + case VT_I4: + case VT_R4: + case VT_BOOL: + case VT_I1: + case VT_UI1: + case VT_UI2: + case VT_UI4: + case VT_INT: + case VT_UINT: + case VT_HRESULT: + case VT_PTR: + { + const unsigned long lv = get_ulong_val(*(unsigned long*)value, vt); + if((lv & 0x3ffffff) == lv) { + *out = 0x80000000; + *out |= vt << 26; + *out |= lv; + } else { + int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, 8, 0); + *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt; + memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2], value, 4); + *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6]) = 0x5757; + *out = offset; + } + return; + } + case VT_BSTR: + { + char *s = (char *) value; + int len = strlen(s), seg_len = (len + 6 + 3) & ~0x3; + int offset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATA, seg_len, 0); + *((unsigned short *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = vt; + *((unsigned int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = len; + memcpy(&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], value, len); + len += 6; + while(len < seg_len) { + *((char *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+len]) = 0x57; + len++; + } + *out = offset; + return; + } + + default: + warning("can't write value of type %d yet\n", vt); + } + return; +} + +static HRESULT set_custdata(msft_typelib_t *typelib, REFGUID guid, + int vt, void *value, int *offset) +{ + MSFT_GuidEntry guidentry; + int guidoffset; + int custoffset; + int *custdata; + int data_out; + + guidentry.guid = *guid; + + guidentry.hreftype = -1; + guidentry.next_hash = -1; + + guidoffset = ctl2_alloc_guid(typelib, &guidentry); + write_value(typelib, &data_out, vt, value); + + custoffset = ctl2_alloc_segment(typelib, MSFT_SEG_CUSTDATAGUID, 12, 0); + + custdata = (int *)&typelib->typelib_segment_data[MSFT_SEG_CUSTDATAGUID][custoffset]; + custdata[0] = guidoffset; + custdata[1] = data_out; + custdata[2] = *offset; + *offset = custoffset; + + return S_OK; +} + +static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int index) +{ + int offset, name_offset; + int *typedata, typedata_size; + int i, id, next_idx; + int decoded_size, extra_attr = 0; + int num_params = 0, num_optional = 0, num_defaults = 0; + var_t *arg; + char *namedata; + const attr_t *attr; + unsigned int funcflags = 0, callconv = 4 /* CC_STDCALL */; + unsigned int funckind, invokekind = 1 /* INVOKE_FUNC */; + int help_context = 0, help_string_context = 0, help_string_offset = -1; + int entry = -1, entry_is_ord = 0; + + chat("add_func_desc(%p,%d)\n", typeinfo, index); + + id = ((0x6000 | (typeinfo->typeinfo->datatype2 & 0xffff)) << 16) | index; + + switch(typeinfo->typekind) { + case TKIND_DISPATCH: + funckind = 0x4; /* FUNC_DISPATCH */ + break; + case TKIND_MODULE: + funckind = 0x3; /* FUNC_STATIC */ + break; + default: + funckind = 0x1; /* FUNC_PUREVIRTUAL */ + break; + } + + if (is_local( func->def->attrs )) { + chat("add_func_desc: skipping local function\n"); + return S_FALSE; + } + + if (func->args) + LIST_FOR_EACH_ENTRY( arg, func->args, var_t, entry ) + { + num_params++; + if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { + if(attr->type == ATTR_DEFAULTVALUE_EXPR || attr->type == ATTR_DEFAULTVALUE_STRING) + num_defaults++; + else if(attr->type == ATTR_OPTIONAL) + num_optional++; + } + } + + chat("add_func_desc: num of params %d\n", num_params); + + name_offset = ctl2_alloc_name(typeinfo->typelib, func->def->name); + + if (func->def->attrs) LIST_FOR_EACH_ENTRY( attr, func->def->attrs, const attr_t, entry ) { + expr_t *expr = attr->u.pval; + switch(attr->type) { + case ATTR_BINDABLE: + funcflags |= 0x4; /* FUNCFLAG_BINDABLE */ + break; + case ATTR_DISPLAYBIND: + funcflags |= 0x10; /* FUNCFLAG_DISPLAYBIND */ + break; + case ATTR_ENTRY_ORDINAL: + extra_attr = max(extra_attr, 3); + entry = expr->cval; + entry_is_ord = 1; + break; + case ATTR_ENTRY_STRING: + extra_attr = max(extra_attr, 3); + entry = ctl2_alloc_string(typeinfo->typelib, attr->u.pval); + break; + case ATTR_HELPCONTEXT: + extra_attr = max(extra_attr, 1); + help_context = expr->u.lval; + break; + case ATTR_HELPSTRING: + extra_attr = max(extra_attr, 2); + help_string_offset = ctl2_alloc_string(typeinfo->typelib, attr->u.pval); + break; + case ATTR_HELPSTRINGCONTEXT: + extra_attr = max(extra_attr, 6); + help_string_context = expr->u.lval; + break; + case ATTR_HIDDEN: + funcflags |= 0x40; /* FUNCFLAG_FHIDDEN */ + break; + case ATTR_ID: + id = expr->cval; + break; + case ATTR_NONBROWSABLE: + funcflags |= 0x400; /* FUNCFLAG_NONBROWSABLE */ + break; + case ATTR_OUT: + break; + case ATTR_PROPGET: + invokekind = 0x2; /* INVOKE_PROPERTYGET */ + break; + case ATTR_PROPPUT: + invokekind = 0x4; /* INVOKE_PROPERTYPUT */ + break; + case ATTR_PROPPUTREF: + invokekind = 0x8; /* INVOKE_PROPERTYPUTREF */ + break; + case ATTR_RESTRICTED: + funcflags |= 0x1; /* FUNCFLAG_FRESTRICTED */ + break; + case ATTR_VARARG: + if (num_optional || num_defaults) + warning("add_func_desc: ignoring vararg in function with optional or defaultvalue params\n"); + else + num_optional = -1; + break; + default: + warning("add_func_desc: ignoring attr %d\n", attr->type); + break; + } + } + + /* allocate type data space for us */ + typedata_size = 0x18 + extra_attr * sizeof(int) + (num_params * (num_defaults ? 16 : 12)); + + if (!typeinfo->func_data) { + typeinfo->func_data = xmalloc(0x100); + typeinfo->func_data_allocated = 0x100; + typeinfo->func_data[0] = 0; + } + + if(typeinfo->func_data[0] + typedata_size + sizeof(int) > typeinfo->func_data_allocated) { + typeinfo->func_data_allocated = max(typeinfo->func_data_allocated * 2, + typeinfo->func_data[0] + typedata_size + sizeof(int)); + typeinfo->func_data = xrealloc(typeinfo->func_data, typeinfo->func_data_allocated); + } + + offset = typeinfo->func_data[0]; + typeinfo->func_data[0] += typedata_size; + typedata = typeinfo->func_data + (offset >> 2) + 1; + + + /* find func with the same name - if it exists use its id */ + for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) { + if(name_offset == typeinfo->func_names[i]) { + id = typeinfo->func_indices[i]; + break; + } + } + + /* find the first func with the same id and link via the hiword of typedata[4] */ + next_idx = index; + for(i = 0; i < (typeinfo->typeinfo->cElement & 0xffff); i++) { + if(id == typeinfo->func_indices[i]) { + next_idx = typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] >> 16; + typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] &= 0xffff; + typeinfo->func_data[(typeinfo->func_offsets[i] >> 2) + 1 + 4] |= (index << 16); + break; + } + } + + /* fill out the basic type information */ + typedata[0] = typedata_size | (index << 16); + encode_var(typeinfo->typelib, func->def->type, func->def, &typedata[1], NULL, NULL, &decoded_size); + typedata[2] = funcflags; + typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft; + typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind; + if(num_defaults) typedata[4] |= 0x1000; + if(entry_is_ord) typedata[4] |= 0x2000; + typedata[5] = (num_optional << 16) | num_params; + + /* NOTE: High word of typedata[3] is total size of FUNCDESC + size of all ELEMDESCs for params + TYPEDESCs for pointer params and return types. */ + /* That is, total memory allocation required to reconstitute the FUNCDESC in its entirety. */ + typedata[3] += (16 /*sizeof(ELEMDESC)*/ * num_params) << 16; + typedata[3] += (24 /*sizeof(PARAMDESCEX)*/ * num_defaults) << 16; + + switch(extra_attr) { + case 6: typedata[11] = help_string_context; + case 5: typedata[10] = -1; + case 4: typedata[9] = -1; + case 3: typedata[8] = entry; + case 2: typedata[7] = help_string_offset; + case 1: typedata[6] = help_context; + case 0: + break; + default: + warning("unknown number of optional attrs\n"); + } + + if (func->args) + { + i = 0; + LIST_FOR_EACH_ENTRY( arg, func->args, var_t, entry ) + { + const attr_t *attr; + int paramflags = 0; + int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; + int *defaultdata = num_defaults ? typedata + 6 + extra_attr + i : NULL; + + if(defaultdata) *defaultdata = -1; + + encode_var(typeinfo->typelib, arg->type, arg, paramdata, NULL, NULL, &decoded_size); + if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { + switch(attr->type) { + case ATTR_DEFAULTVALUE_EXPR: + { + int vt; + expr_t *expr = (expr_t *)attr->u.pval; + if (arg->type->type == RPC_FC_ENUM16) + vt = VT_INT; + else + vt = get_type_vt(arg->type); + paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ + chat("default value %ld\n", expr->cval); + write_value(typeinfo->typelib, defaultdata, vt, &expr->cval); + break; + } + case ATTR_DEFAULTVALUE_STRING: + { + char *s = (char *)attr->u.pval; + int vt; + if (arg->type->type == RPC_FC_ENUM16) + vt = VT_INT; + else + vt = get_type_vt(arg->type); + paramflags |= 0x30; /* PARAMFLAG_FHASDEFAULT | PARAMFLAG_FOPT */ + chat("default value '%s'\n", s); + write_value(typeinfo->typelib, defaultdata, vt, s); + break; + } + case ATTR_IN: + paramflags |= 0x01; /* PARAMFLAG_FIN */ + break; + case ATTR_OPTIONAL: + paramflags |= 0x10; /* PARAMFLAG_FOPT */ + break; + case ATTR_OUT: + paramflags |= 0x02; /* PARAMFLAG_FOUT */ + break; + case ATTR_RETVAL: + paramflags |= 0x08; /* PARAMFLAG_FRETVAL */ + typedata[4] |= 0x4000; + break; + default: + chat("unhandled param attr %d\n", attr->type); + break; + } + } + paramdata[1] = -1; + paramdata[2] = paramflags; + typedata[3] += decoded_size << 16; + i++; + } + } + + if(typeinfo->funcs_allocated == 0) { + typeinfo->funcs_allocated = 10; + typeinfo->func_indices = xmalloc(typeinfo->funcs_allocated * sizeof(int)); + typeinfo->func_names = xmalloc(typeinfo->funcs_allocated * sizeof(int)); + typeinfo->func_offsets = xmalloc(typeinfo->funcs_allocated * sizeof(int)); + } + if(typeinfo->funcs_allocated == (typeinfo->typeinfo->cElement & 0xffff)) { + typeinfo->funcs_allocated *= 2; + typeinfo->func_indices = xrealloc(typeinfo->func_indices, typeinfo->funcs_allocated * sizeof(int)); + typeinfo->func_names = xrealloc(typeinfo->func_names, typeinfo->funcs_allocated * sizeof(int)); + typeinfo->func_offsets = xrealloc(typeinfo->func_offsets, typeinfo->funcs_allocated * sizeof(int)); + } + + /* update the index data */ + typeinfo->func_indices[typeinfo->typeinfo->cElement & 0xffff] = id; + typeinfo->func_offsets[typeinfo->typeinfo->cElement & 0xffff] = offset; + typeinfo->func_names[typeinfo->typeinfo->cElement & 0xffff] = name_offset; + + /* ??? */ + if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x20; + typeinfo->typeinfo->res2 <<= 1; + /* ??? */ + if (index < 2) typeinfo->typeinfo->res2 += num_params << 4; + + if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0; + typeinfo->typeinfo->res3 += 0x38 + num_params * 0x10; + if(num_defaults) typeinfo->typeinfo->res3 += num_params * 0x4; + + /* adjust size of VTBL */ + if(funckind != 0x3 /* FUNC_STATIC */) + typeinfo->typeinfo->cbSizeVft += 4; + + /* Increment the number of function elements */ + typeinfo->typeinfo->cElement += 1; + + namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + name_offset; + if (*((INT *)namedata) == -1) { + *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; + if(typeinfo->typekind == TKIND_MODULE) + namedata[9] |= 0x10; + } else + namedata[9] &= ~0x10; + + if(typeinfo->typekind == TKIND_MODULE) + namedata[9] |= 0x20; + + if (func->args) + { + i = 0; + LIST_FOR_EACH_ENTRY( arg, func->args, var_t, entry ) + { + /* don't give the last arg of a [propput*] func a name */ + if(i != num_params - 1 || (invokekind != 0x4 /* INVOKE_PROPERTYPUT */ && invokekind != 0x8 /* INVOKE_PROPERTYPUTREF */)) + { + int *paramdata = typedata + 6 + extra_attr + (num_defaults ? num_params : 0) + i * 3; + offset = ctl2_alloc_name(typeinfo->typelib, arg->name); + paramdata[1] = offset; + } + i++; + } + } + return S_OK; +} + +static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) +{ + int offset, id; + unsigned int typedata_size; + INT *typedata; + int var_datawidth; + int var_alignment; + int var_type_size, var_kind = 0 /* VAR_PERINSTANCE */; + int alignment; + int varflags = 0; + const attr_t *attr; + char *namedata; + int var_num = (typeinfo->typeinfo->cElement >> 16) & 0xffff; + + chat("add_var_desc(%d, %s)\n", index, var->name); + + id = 0x40000000 + index; + + if (var->attrs) LIST_FOR_EACH_ENTRY( attr, var->attrs, const attr_t, entry ) { + expr_t *expr = attr->u.pval; + switch(attr->type) { + case ATTR_HIDDEN: + varflags |= 0x40; /* VARFLAG_FHIDDEN */ + break; + case ATTR_ID: + id = expr->cval; + break; + case ATTR_READONLY: + varflags |= 0x01; /* VARFLAG_FREADONLY */ + break; + case ATTR_RESTRICTED: + varflags |= 0x80; /* VARFLAG_FRESTRICTED */ + break; + case ATTR_SOURCE: + varflags |= 0x02; /* VARFLAG_FSOURCE */ + break; + default: + warning("AddVarDesc: unhandled attr type %d\n", attr->type); + break; + } + } + + /* allocate type data space for us */ + typedata_size = 0x14; + + if (!typeinfo->var_data) { + typeinfo->var_data = xmalloc(0x100); + typeinfo->var_data_allocated = 0x100; + typeinfo->var_data[0] = 0; + } + + if(typeinfo->var_data[0] + typedata_size + sizeof(int) > typeinfo->var_data_allocated) { + typeinfo->var_data_allocated = max(typeinfo->var_data_allocated * 2, + typeinfo->var_data[0] + typedata_size + sizeof(int)); + typeinfo->var_data = xrealloc(typeinfo->var_data, typeinfo->var_data_allocated); + } + + offset = typeinfo->var_data[0]; + typeinfo->var_data[0] += typedata_size; + typedata = typeinfo->var_data + (offset >> 2) + 1; + + /* fill out the basic type information */ + typedata[0] = typedata_size | (index << 16); + typedata[2] = varflags; + typedata[3] = (36 /*sizeof(VARDESC)*/ << 16) | 0; + + if(typeinfo->vars_allocated == 0) { + typeinfo->vars_allocated = 10; + typeinfo->var_indices = xmalloc(typeinfo->vars_allocated * sizeof(int)); + typeinfo->var_names = xmalloc(typeinfo->vars_allocated * sizeof(int)); + typeinfo->var_offsets = xmalloc(typeinfo->vars_allocated * sizeof(int)); + } + if(typeinfo->vars_allocated == var_num) { + typeinfo->vars_allocated *= 2; + typeinfo->var_indices = xrealloc(typeinfo->var_indices, typeinfo->vars_allocated * sizeof(int)); + typeinfo->var_names = xrealloc(typeinfo->var_names, typeinfo->vars_allocated * sizeof(int)); + typeinfo->var_offsets = xrealloc(typeinfo->var_offsets, typeinfo->vars_allocated * sizeof(int)); + } + /* update the index data */ + typeinfo->var_indices[var_num] = id; + typeinfo->var_names[var_num] = -1; + typeinfo->var_offsets[var_num] = offset; + + /* figure out type widths and whatnot */ + encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_datawidth, + &var_alignment, &var_type_size); + + /* pad out starting position to data width */ + typeinfo->datawidth += var_alignment - 1; + typeinfo->datawidth &= ~(var_alignment - 1); + + switch(typeinfo->typekind) { + case TKIND_ENUM: + write_value(typeinfo->typelib, &typedata[4], VT_I4, &var->eval->cval); + var_kind = 2; /* VAR_CONST */ + var_type_size += 16; /* sizeof(VARIANT) */ + typeinfo->datawidth = var_datawidth; + break; + case TKIND_RECORD: + typedata[4] = typeinfo->datawidth; + typeinfo->datawidth += var_datawidth; + break; + case TKIND_DISPATCH: + var_kind = 3; /* VAR_DISPATCH */ + typeinfo->datawidth = 4; + var_alignment = 4; + break; + default: + error("add_var_desc: unhandled type kind %d\n", typeinfo->typekind); + break; + } + + /* add type description size to total required allocation */ + typedata[3] += var_type_size << 16 | var_kind; + + /* fix type alignment */ + alignment = (typeinfo->typeinfo->typekind >> 11) & 0x1f; + if (alignment < var_alignment) { + alignment = var_alignment; + typeinfo->typeinfo->typekind &= ~0xffc0; + typeinfo->typeinfo->typekind |= alignment << 11 | alignment << 6; + } + + /* ??? */ + if (!typeinfo->typeinfo->res2) typeinfo->typeinfo->res2 = 0x1a; + if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) { + typeinfo->typeinfo->res2 <<= 1; + } + + /* ??? */ + if (typeinfo->typeinfo->res3 == -1) typeinfo->typeinfo->res3 = 0; + typeinfo->typeinfo->res3 += 0x2c; + + /* increment the number of variable elements */ + typeinfo->typeinfo->cElement += 0x10000; + + /* pad data width to alignment */ + typeinfo->typeinfo->size = (typeinfo->datawidth + (alignment - 1)) & ~(alignment - 1); + + offset = ctl2_alloc_name(typeinfo->typelib, var->name); + if (offset == -1) return E_OUTOFMEMORY; + + namedata = typeinfo->typelib->typelib_segment_data[MSFT_SEG_NAME] + offset; + if (*((INT *)namedata) == -1) { + *((INT *)namedata) = typeinfo->typelib->typelib_typeinfo_offsets[typeinfo->typeinfo->typekind >> 16]; + if(typeinfo->typekind != TKIND_DISPATCH) + namedata[9] |= 0x10; + } else + namedata[9] &= ~0x10; + + if (typeinfo->typekind == TKIND_ENUM) { + namedata[9] |= 0x20; + } + typeinfo->var_names[var_num] = offset; + + return S_OK; +} + +static HRESULT add_impl_type(msft_typeinfo_t *typeinfo, type_t *ref, importinfo_t *importinfo) +{ + if(importinfo) { + alloc_importinfo(typeinfo->typelib, importinfo); + typeinfo->typeinfo->datatype1 = importinfo->offset+1; + }else { + if(ref->typelib_idx == -1) + add_interface_typeinfo(typeinfo->typelib, ref); + if(ref->typelib_idx == -1) + error("add_impl_type: unable to add inherited interface\n"); + + typeinfo->typeinfo->datatype1 = typeinfo->typelib->typelib_typeinfo_offsets[ref->typelib_idx]; + } + + typeinfo->typeinfo->cImplTypes++; + return S_OK; +} + +static msft_typeinfo_t *create_msft_typeinfo(msft_typelib_t *typelib, enum type_kind kind, + const char *name, const attr_list_t *attrs) +{ + const attr_t *attr; + msft_typeinfo_t *msft_typeinfo; + int nameoffset; + int typeinfo_offset; + MSFT_TypeInfoBase *typeinfo; + MSFT_GuidEntry guidentry; + + chat("create_msft_typeinfo: name %s kind %d\n", name, kind); + + msft_typeinfo = xmalloc(sizeof(*msft_typeinfo)); + memset( msft_typeinfo, 0, sizeof(*msft_typeinfo) ); + + msft_typeinfo->typelib = typelib; + + nameoffset = ctl2_alloc_name(typelib, name); + typeinfo_offset = ctl2_alloc_typeinfo(typelib, nameoffset); + typeinfo = (MSFT_TypeInfoBase *)&typelib->typelib_segment_data[MSFT_SEG_TYPEINFO][typeinfo_offset]; + + typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset + 9] = 0x38; + *((int *)&typelib->typelib_segment_data[MSFT_SEG_NAME][nameoffset]) = typeinfo_offset; + + msft_typeinfo->typekind = kind; + msft_typeinfo->typeinfo = typeinfo; + + typeinfo->typekind |= kind | 0x20; + + if(kind == TKIND_COCLASS) + typeinfo->flags |= 0x2; /* TYPEFLAG_FCANCREATE */ + + if (attrs) LIST_FOR_EACH_ENTRY( attr, attrs, const attr_t, entry ) { + switch(attr->type) { + case ATTR_AGGREGATABLE: + if (kind == TKIND_COCLASS) + typeinfo->flags |= 0x400; /* TYPEFLAG_FAGGREGATABLE */ + break; + + case ATTR_APPOBJECT: + if (kind == TKIND_COCLASS) + typeinfo->flags |= 0x1; /* TYPEFLAG_FAPPOBJECT */ + break; + + case ATTR_CONTROL: + if (kind == TKIND_COCLASS) + typeinfo->flags |= 0x20; /* TYPEFLAG_FCONTROL */ + break; + + case ATTR_DISPINTERFACE: + break; + + case ATTR_DLLNAME: + { + int offset = ctl2_alloc_string(typelib, attr->u.pval); + typeinfo->datatype1 = offset; + break; + } + + case ATTR_DUAL: + /* FIXME: check interface is compatible */ + typeinfo->typekind = (typeinfo->typekind & ~0xff) | 0x34; + typeinfo->flags |= 0x140; /* TYPEFLAG_FDUAL | TYPEFLAG_FOLEAUTOMATION */ + break; + + case ATTR_HELPCONTEXT: + { + expr_t *expr = (expr_t*)attr->u.pval; + typeinfo->helpcontext = expr->cval; + break; + } + case ATTR_HELPSTRING: + { + int offset = ctl2_alloc_string(typelib, attr->u.pval); + if (offset == -1) break; + typeinfo->docstringoffs = offset; + break; + } + case ATTR_HELPSTRINGCONTEXT: + { + expr_t *expr = (expr_t*)attr->u.pval; + typeinfo->helpstringcontext = expr->cval; + break; + } + case ATTR_HIDDEN: + typeinfo->flags |= 0x10; /* TYPEFLAG_FHIDDEN */ + break; + + case ATTR_NONCREATABLE: + typeinfo->flags &= ~0x2; /* TYPEFLAG_FCANCREATE */ + break; + + case ATTR_NONEXTENSIBLE: + typeinfo->flags |= 0x80; /* TYPEFLAG_FNONEXTENSIBLE */ + break; + + case ATTR_OBJECT: + break; + + case ATTR_ODL: + break; + + case ATTR_OLEAUTOMATION: + typeinfo->flags |= 0x100; /* TYPEFLAG_FOLEAUTOMATION */ + break; + + case ATTR_PUBLIC: + break; + + case ATTR_RESTRICTED: + typeinfo->flags |= 0x200; /* TYPEFLAG_FRESTRICTED */ + break; + + case ATTR_UUID: + guidentry.guid = *(GUID*)attr->u.pval; + guidentry.hreftype = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16]; + guidentry.next_hash = -1; + typeinfo->posguid = ctl2_alloc_guid(typelib, &guidentry); +#if 0 + if (IsEqualIID(guid, &IID_IDispatch)) { + typelib->typelib_header.dispatchpos = typelib->typelib_typeinfo_offsets[typeinfo->typekind >> 16]; + } +#endif + break; + + case ATTR_VERSION: + typeinfo->version = attr->u.ival; + break; + + default: + warning("create_msft_typeinfo: ignoring attr %d\n", attr->type); + break; + } + } + + if (typelib->last_typeinfo) typelib->last_typeinfo->next_typeinfo = msft_typeinfo; + typelib->last_typeinfo = msft_typeinfo; + if (!typelib->typeinfos) typelib->typeinfos = msft_typeinfo; + + + return msft_typeinfo; +} + +static void add_dispatch(msft_typelib_t *typelib) +{ + int guid_offset, impfile_offset; + MSFT_GuidEntry guidentry; + MSFT_ImpInfo impinfo; + GUID stdole = {0x00020430,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; + GUID iid_idispatch = {0x00020400,0x0000,0x0000,{0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; + + if(typelib->typelib_header.dispatchpos != -1) return; + + guidentry.guid = stdole; + guidentry.hreftype = 2; + guidentry.next_hash = -1; + guid_offset = ctl2_alloc_guid(typelib, &guidentry); + impfile_offset = alloc_importfile(typelib, guid_offset, 2, 0, "stdole2.tlb"); + + guidentry.guid = iid_idispatch; + guidentry.hreftype = 1; + guidentry.next_hash = -1; + impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID; + impinfo.oImpFile = impfile_offset; + impinfo.oGuid = ctl2_alloc_guid(typelib, &guidentry); + typelib->typelib_header.dispatchpos = alloc_msft_importinfo(typelib, &impinfo) | 0x01; +} + +static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinterface) +{ + int idx = 0; + const func_t *func; + var_t *var; + msft_typeinfo_t *msft_typeinfo; + + if (-1 < dispinterface->typelib_idx) + return; + + dispinterface->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_DISPATCH, dispinterface->name, + dispinterface->attrs); + + msft_typeinfo->typeinfo->size = 4; + msft_typeinfo->typeinfo->typekind |= 0x2100; + + msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */ + add_dispatch(typelib); + msft_typeinfo->typeinfo->cImplTypes = 1; + + /* count the no of funcs, as the variable indices come after the funcs */ + if (dispinterface->funcs) + LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) idx++; + + if (dispinterface->fields) + LIST_FOR_EACH_ENTRY( var, dispinterface->fields, var_t, entry ) + add_var_desc(msft_typeinfo, idx++, var); + + if (dispinterface->funcs) + { + idx = 0; + LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) + if(add_func_desc(msft_typeinfo, func, idx) == S_OK) + idx++; + } +} + +static void add_interface_typeinfo(msft_typelib_t *typelib, type_t *interface) +{ + int idx = 0; + const func_t *func; + type_t *ref; + msft_typeinfo_t *msft_typeinfo; + importinfo_t *ref_importinfo = NULL; + int num_parents = 0, num_funcs = 0; + const type_t *derived; + + if (-1 < interface->typelib_idx) + return; + + if (is_attr(interface->attrs, ATTR_DISPINTERFACE)) + return add_dispinterface_typeinfo(typelib, interface); + + /* midl adds the parent interface first, unless the parent itself + has no parent (i.e. it stops before IUnknown). */ + + if(interface->ref) { + ref_importinfo = find_importinfo(typelib, interface->ref->name); + + if(!ref_importinfo && interface->ref->ref && interface->ref->typelib_idx == -1) + add_interface_typeinfo(typelib, interface->ref); + } + + interface->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_INTERFACE, interface->name, interface->attrs); + msft_typeinfo->typeinfo->size = 4; + msft_typeinfo->typeinfo->typekind |= 0x2200; + + for (derived = interface->ref; derived; derived = derived->ref) + if (derived->name && !strcmp(derived->name, "IDispatch")) + msft_typeinfo->typeinfo->flags |= 0x1000; /* TYPEFLAG_FDISPATCHABLE */ + + /* can't be dual if it doesn't derive from IDispatch */ + if (!(msft_typeinfo->typeinfo->flags & 0x1000)) /* TYPEFLAG_FDISPATCHABLE */ + msft_typeinfo->typeinfo->flags &= ~0x40; /* TYPEFLAG_FDUAL */ + + if(interface->ref) + add_impl_type(msft_typeinfo, interface->ref, ref_importinfo); + + /* count the number of inherited interfaces and non-local functions */ + for(ref = interface->ref; ref; ref = ref->ref) { + num_parents++; + if (ref->funcs) + LIST_FOR_EACH_ENTRY( func, ref->funcs, const func_t, entry ) + if (!is_local(func->def->attrs)) num_funcs++; + } + msft_typeinfo->typeinfo->datatype2 = num_funcs << 16 | num_parents; + msft_typeinfo->typeinfo->cbSizeVft = num_funcs * 4; + + if (interface->funcs) + LIST_FOR_EACH_ENTRY( func, interface->funcs, const func_t, entry ) + if(add_func_desc(msft_typeinfo, func, idx) == S_OK) + idx++; +} + +static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure) +{ + int idx = 0; + var_t *cur; + msft_typeinfo_t *msft_typeinfo; + + if (-1 < structure->typelib_idx) + return; + + structure->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs); + msft_typeinfo->typeinfo->size = 0; + + if (structure->fields) + LIST_FOR_EACH_ENTRY( cur, structure->fields, var_t, entry ) + add_var_desc(msft_typeinfo, idx++, cur); +} + +static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration) +{ + int idx = 0; + var_t *cur; + msft_typeinfo_t *msft_typeinfo; + + enumeration->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs); + msft_typeinfo->typeinfo->size = 0; + + if (enumeration->fields) + LIST_FOR_EACH_ENTRY( cur, enumeration->fields, var_t, entry ) + add_var_desc(msft_typeinfo, idx++, cur); +} + +static void add_typedef_typeinfo(msft_typelib_t *typelib, type_t *tdef) +{ + msft_typeinfo_t *msft_typeinfo; + int alignment; + + if (-1 < tdef->typelib_idx) + return; + + tdef->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ALIAS, tdef->name, tdef->attrs); + encode_type(typelib, get_type_vt(tdef->orig), tdef->orig, &msft_typeinfo->typeinfo->datatype1, &msft_typeinfo->typeinfo->size, + &alignment, &msft_typeinfo->typeinfo->datatype2); + msft_typeinfo->typeinfo->typekind |= (alignment << 11 | alignment << 6); +} + +static void add_coclass_typeinfo(msft_typelib_t *typelib, type_t *cls) +{ + msft_typeinfo_t *msft_typeinfo; + ifref_t *iref; + int num_ifaces = 0, offset, i; + MSFT_RefRecord *ref, *first = NULL, *first_source = NULL; + int have_default = 0, have_default_source = 0; + const attr_t *attr; + + if (-1 < cls->typelib_idx) + return; + + cls->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_COCLASS, cls->name, cls->attrs); + + if (cls->ifaces) LIST_FOR_EACH_ENTRY( iref, cls->ifaces, ifref_t, entry ) num_ifaces++; + + offset = msft_typeinfo->typeinfo->datatype1 = ctl2_alloc_segment(typelib, MSFT_SEG_REFERENCES, + num_ifaces * sizeof(*ref), 0); + + i = 0; + if (cls->ifaces) LIST_FOR_EACH_ENTRY( iref, cls->ifaces, ifref_t, entry ) { + if(iref->iface->typelib_idx == -1) + add_interface_typeinfo(typelib, iref->iface); + ref = (MSFT_RefRecord*) (typelib->typelib_segment_data[MSFT_SEG_REFERENCES] + offset + i * sizeof(*ref)); + ref->reftype = typelib->typelib_typeinfo_offsets[iref->iface->typelib_idx]; + ref->flags = 0; + ref->oCustData = -1; + ref->onext = -1; + if(i < num_ifaces - 1) + ref->onext = offset + (i + 1) * sizeof(*ref); + + if (iref->attrs) LIST_FOR_EACH_ENTRY( attr, iref->attrs, const attr_t, entry ) { + switch(attr->type) { + case ATTR_DEFAULT: + ref->flags |= 0x1; /* IMPLTYPEFLAG_FDEFAULT */ + break; + case ATTR_RESTRICTED: + ref->flags |= 0x4; /* IMPLTYPEFLAG_FRESTRICTED */ + break; + case ATTR_SOURCE: + ref->flags |= 0x2; /* IMPLTYPEFLAG_FSOURCE */ + break; + default: + warning("add_coclass_typeinfo: unhandled attr %d\n", attr->type); + } + } + if(ref->flags & 0x1) { /* IMPLTYPEFLAG_FDEFAULT */ + if(ref->flags & 0x2) /* IMPLTYPEFLAG_SOURCE */ + have_default_source = 1; + else + have_default = 1; + } + + /* If the interface is non-restricted and we haven't already had one then + remember it so that we can use it as a default later */ + if((ref->flags & 0x4) == 0) { /* IMPLTYPEFLAG_FRESTRICTED */ + if(ref->flags & 0x2) { /* IMPLTYPEFLAG_FSOURCE */ + if(!first_source) + first_source = ref; + } + else if(!first) + first = ref; + } + i++; + } + + /* If we haven't had a default interface, then set the default flags on the + first ones */ + if(!have_default && first) + first->flags |= 0x1; + if(!have_default_source && first_source) + first_source->flags |= 0x1; + + msft_typeinfo->typeinfo->cImplTypes = num_ifaces; + msft_typeinfo->typeinfo->size = 4; + msft_typeinfo->typeinfo->typekind |= 0x2200; +} + +static void add_module_typeinfo(msft_typelib_t *typelib, type_t *module) +{ + int idx = 0; + const func_t *func; + msft_typeinfo_t *msft_typeinfo; + + if (-1 < module->typelib_idx) + return; + + module->typelib_idx = typelib->typelib_header.nrtypeinfos; + msft_typeinfo = create_msft_typeinfo(typelib, TKIND_MODULE, module->name, module->attrs); + msft_typeinfo->typeinfo->typekind |= 0x0a00; + + if (module->funcs) + LIST_FOR_EACH_ENTRY( func, module->funcs, const func_t, entry ) + if(add_func_desc(msft_typeinfo, func, idx) == S_OK) + idx++; + + msft_typeinfo->typeinfo->size = idx; +} + +static void add_entry(msft_typelib_t *typelib, typelib_entry_t *entry) +{ + switch(entry->type->kind) { + case TKIND_INTERFACE: + case TKIND_DISPATCH: + add_interface_typeinfo(typelib, entry->type); + break; + + case TKIND_RECORD: + add_structure_typeinfo(typelib, entry->type); + break; + + case TKIND_ENUM: + add_enum_typeinfo(typelib, entry->type); + break; + + case TKIND_ALIAS: + add_typedef_typeinfo(typelib, entry->type); + break; + + case TKIND_COCLASS: + add_coclass_typeinfo(typelib, entry->type); + break; + + case TKIND_MODULE: + add_module_typeinfo(typelib, entry->type); + break; + + default: + error("add_entry: unhandled type %d\n", entry->type->kind); + break; + } +} + +static void set_name(msft_typelib_t *typelib) +{ + int offset; + + offset = ctl2_alloc_name(typelib, typelib->typelib->name); + if (offset == -1) return; + typelib->typelib_header.NameOffset = offset; + return; +} + +static void set_version(msft_typelib_t *typelib) +{ + typelib->typelib_header.version = get_attrv( typelib->typelib->attrs, ATTR_VERSION ); +} + +static void set_guid(msft_typelib_t *typelib) +{ + MSFT_GuidEntry guidentry; + int offset; + void *ptr; + GUID guid = {0,0,0,{0,0,0,0,0,0}}; + + guidentry.guid = guid; + guidentry.hreftype = -2; + guidentry.next_hash = -1; + + ptr = get_attrp( typelib->typelib->attrs, ATTR_UUID ); + if (ptr) guidentry.guid = *(GUID *)ptr; + + offset = ctl2_alloc_guid(typelib, &guidentry); + typelib->typelib_header.posguid = offset; + + return; +} + +static void set_doc_string(msft_typelib_t *typelib) +{ + char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRING ); + + if (str) + { + int offset = ctl2_alloc_string(typelib, str); + if (offset != -1) typelib->typelib_header.helpstring = offset; + } +} + +static void set_help_file_name(msft_typelib_t *typelib) +{ + char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPFILE ); + + if (str) + { + int offset = ctl2_alloc_string(typelib, str); + if (offset != -1) + { + typelib->typelib_header.helpfile = offset; + typelib->typelib_header.varflags |= 0x10; + } + } +} + +static void set_help_context(msft_typelib_t *typelib) +{ + const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPCONTEXT ); + if (expr) typelib->typelib_header.helpcontext = expr->cval; +} + +static void set_help_string_dll(msft_typelib_t *typelib) +{ + char *str = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGDLL ); + + if (str) + { + int offset = ctl2_alloc_string(typelib, str); + if (offset != -1) + { + typelib->help_string_dll_offset = offset; + typelib->typelib_header.varflags |= 0x100; + } + } +} + +static void set_help_string_context(msft_typelib_t *typelib) +{ + const expr_t *expr = get_attrp( typelib->typelib->attrs, ATTR_HELPSTRINGCONTEXT ); + if (expr) typelib->typelib_header.helpstringcontext = expr->cval; +} + +static void set_lcid(msft_typelib_t *typelib) +{ + typelib->typelib_header.lcid2 = 0x0; + return; +} + +static void set_lib_flags(msft_typelib_t *typelib) +{ + const attr_t *attr; + + typelib->typelib_header.flags = 0; + if (!typelib->typelib->attrs) return; + LIST_FOR_EACH_ENTRY( attr, typelib->typelib->attrs, const attr_t, entry ) + { + switch(attr->type) { + case ATTR_CONTROL: + typelib->typelib_header.flags |= 0x02; /* LIBFLAG_FCONTROL */ + break; + case ATTR_HIDDEN: + typelib->typelib_header.flags |= 0x04; /* LIBFLAG_FHIDDEN */ + break; + case ATTR_RESTRICTED: + typelib->typelib_header.flags |= 0x01; /* LIBFLAG_FRESTRICTED */ + break; + default: + break; + } + } + return; +} + +static int ctl2_write_chunk(int fd, void *segment, int length) +{ + if (write(fd, segment, length) != length) { + close(fd); + return 0; + } + return -1; +} + +static int ctl2_write_segment(msft_typelib_t *typelib, int fd, int segment) +{ + if (write(fd, typelib->typelib_segment_data[segment], typelib->typelib_segdir[segment].length) + != typelib->typelib_segdir[segment].length) { + close(fd); + return 0; + } + + return -1; +} + +static void ctl2_finalize_typeinfos(msft_typelib_t *typelib, int filesize) +{ + msft_typeinfo_t *typeinfo; + + for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) { + typeinfo->typeinfo->memoffset = filesize; + if (typeinfo->func_data) + filesize += typeinfo->func_data[0] + ((typeinfo->typeinfo->cElement & 0xffff) * 12); + if (typeinfo->var_data) + filesize += typeinfo->var_data[0] + (((typeinfo->typeinfo->cElement >> 16) & 0xffff) * 12); + if (typeinfo->func_data || typeinfo->var_data) + filesize += 4; + } +} + +static int ctl2_finalize_segment(msft_typelib_t *typelib, int filepos, int segment) +{ + if (typelib->typelib_segdir[segment].length) { + typelib->typelib_segdir[segment].offset = filepos; + } else { + typelib->typelib_segdir[segment].offset = -1; + } + + return typelib->typelib_segdir[segment].length; +} + + +static void ctl2_write_typeinfos(msft_typelib_t *typelib, int fd) +{ + msft_typeinfo_t *typeinfo; + int typedata_size; + + for (typeinfo = typelib->typeinfos; typeinfo; typeinfo = typeinfo->next_typeinfo) { + if (!typeinfo->func_data && !typeinfo->var_data) continue; + typedata_size = 0; + if (typeinfo->func_data) + typedata_size = typeinfo->func_data[0]; + if (typeinfo->var_data) + typedata_size += typeinfo->var_data[0]; + ctl2_write_chunk(fd, &typedata_size, sizeof(int)); + if (typeinfo->func_data) + ctl2_write_chunk(fd, typeinfo->func_data + 1, typeinfo->func_data[0]); + if (typeinfo->var_data) + ctl2_write_chunk(fd, typeinfo->var_data + 1, typeinfo->var_data[0]); + if (typeinfo->func_indices) + ctl2_write_chunk(fd, typeinfo->func_indices, (typeinfo->typeinfo->cElement & 0xffff) * 4); + if (typeinfo->var_indices) + ctl2_write_chunk(fd, typeinfo->var_indices, (typeinfo->typeinfo->cElement >> 16) * 4); + if (typeinfo->func_names) + ctl2_write_chunk(fd, typeinfo->func_names, (typeinfo->typeinfo->cElement & 0xffff) * 4); + if (typeinfo->var_names) + ctl2_write_chunk(fd, typeinfo->var_names, (typeinfo->typeinfo->cElement >> 16) * 4); + if (typeinfo->func_offsets) + ctl2_write_chunk(fd, typeinfo->func_offsets, (typeinfo->typeinfo->cElement & 0xffff) * 4); + if (typeinfo->var_offsets) { + int add = 0, i, offset; + if(typeinfo->func_data) + add = typeinfo->func_data[0]; + for(i = 0; i < (typeinfo->typeinfo->cElement >> 16); i++) { + offset = typeinfo->var_offsets[i]; + offset += add; + ctl2_write_chunk(fd, &offset, 4); + } + } + } +} + +static int save_all_changes(msft_typelib_t *typelib) +{ + int retval; + int filepos; + int fd; + + chat("save_all_changes(%p)\n", typelib); + + retval = TYPE_E_IOERROR; + + fd = creat(typelib->typelib->filename, 0666); + if (fd == -1) return retval; + + filepos = sizeof(MSFT_Header) + sizeof(MSFT_SegDir); + if(typelib->typelib_header.varflags & 0x100) filepos += 4; /* helpstringdll */ + filepos += typelib->typelib_header.nrtypeinfos * 4; + + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEINFO); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUIDHASH); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_GUID); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_REFERENCES); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTINFO); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_IMPORTFILES); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAMEHASH); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_NAME); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_STRING); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_TYPEDESC); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_ARRAYDESC); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATA); + filepos += ctl2_finalize_segment(typelib, filepos, MSFT_SEG_CUSTDATAGUID); + + ctl2_finalize_typeinfos(typelib, filepos); + + if (!ctl2_write_chunk(fd, &typelib->typelib_header, sizeof(typelib->typelib_header))) return retval; + if(typelib->typelib_header.varflags & 0x100) + if (!ctl2_write_chunk(fd, &typelib->help_string_dll_offset, sizeof(typelib->help_string_dll_offset))) + return retval; + + if (!ctl2_write_chunk(fd, typelib->typelib_typeinfo_offsets, typelib->typelib_header.nrtypeinfos * 4)) return retval; + if (!ctl2_write_chunk(fd, &typelib->typelib_segdir, sizeof(typelib->typelib_segdir))) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEINFO )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUIDHASH )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_GUID )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_REFERENCES )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTINFO )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_IMPORTFILES )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAMEHASH )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_NAME )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_STRING )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_TYPEDESC )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_ARRAYDESC )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATA )) return retval; + if (!ctl2_write_segment(typelib, fd, MSFT_SEG_CUSTDATAGUID)) return retval; + + ctl2_write_typeinfos(typelib, fd); + + if (close(fd) == -1) return retval; + + retval = S_OK; + return retval; +} + +int create_msft_typelib(typelib_t *typelib) +{ + msft_typelib_t *msft; + int failed = 0; + typelib_entry_t *entry; + time_t cur_time; + char *time_override; + unsigned int version = 5 << 24 | 1 << 16 | 164; /* 5.01.0164 */ + GUID midl_time_guid = {0xde77ba63,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; + GUID midl_version_guid = {0xde77ba64,0x517c,0x11d1,{0xa2,0xda,0x00,0x00,0xf8,0x77,0x3c,0xe9}}; + + msft = xmalloc(sizeof(*msft)); + memset(msft, 0, sizeof(*msft)); + msft->typelib = typelib; + + ctl2_init_header(msft); + ctl2_init_segdir(msft); + + msft->typelib_header.varflags |= SYS_WIN32; + + /* + * The following two calls return an offset or -1 if out of memory. We + * specifically need an offset of 0, however, so... + */ + if (ctl2_alloc_segment(msft, MSFT_SEG_GUIDHASH, 0x80, 0x80)) { failed = 1; } + if (ctl2_alloc_segment(msft, MSFT_SEG_NAMEHASH, 0x200, 0x200)) { failed = 1; } + + if(failed) + { + free(msft); + return 0; + } + + msft->typelib_guidhash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_GUIDHASH]; + msft->typelib_namehash_segment = (int *)msft->typelib_segment_data[MSFT_SEG_NAMEHASH]; + + memset(msft->typelib_guidhash_segment, 0xff, 0x80); + memset(msft->typelib_namehash_segment, 0xff, 0x200); + + set_lib_flags(msft); + set_lcid(msft); + set_help_file_name(msft); + set_doc_string(msft); + set_guid(msft); + set_version(msft); + set_name(msft); + set_help_context(msft); + set_help_string_dll(msft); + set_help_string_context(msft); + + /* midl adds two sets of custom data to the library: the current unix time + and midl's version number */ + time_override = getenv( "WIDL_TIME_OVERRIDE"); + cur_time = time_override ? atol( time_override) : time(NULL); + set_custdata(msft, &midl_time_guid, VT_UI4, &cur_time, &msft->typelib_header.CustomDataOffset); + set_custdata(msft, &midl_version_guid, VT_UI4, &version, &msft->typelib_header.CustomDataOffset); + + LIST_FOR_EACH_ENTRY( entry, &typelib->entries, typelib_entry_t, entry ) + add_entry(msft, entry); + + save_all_changes(msft); + free(msft); + return 1; +}