/* * IDL Compiler * * Copyright 2002 Ove Kaaven * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include #include #include #include "widl.h" #include "utils.h" #include "parser.h" #include "header.h" #include "y.tab.h" /* FIXME: support generation of stubless proxies */ static void write_stubdesc(void) { fprintf(proxy, "const MIDL_STUB_DESC Object_StubDesc = {\n"); fprintf(proxy, " 0,\n"); fprintf(proxy, " NdrOleAllocate,\n"); fprintf(proxy, " NdrOleFree,\n"); fprintf(proxy, " {0}, 0, 0, 0, 0,\n"); fprintf(proxy, " 0 /* __MIDL_TypeFormatString.Format */\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); } static void init_proxy(void) { if (proxy) return; proxy = fopen(proxy_name, "w"); fprintf(proxy, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION); fprintf(proxy, "#include \"rpcproxy.h\"\n"); fprintf(proxy, "#include \"%s\"\n", header_name); fprintf(proxy, "\n"); write_stubdesc(); } static void gen_proxy(type_t *iface, func_t *cur, int idx) { var_t *def = cur->def; int has_ret = !is_void(def->type, def); write_type(proxy, def->type, def, def->tname); fprintf(proxy, " CALLBACK %s_", iface->name); write_name(proxy, def); fprintf(proxy, "_Proxy(\n"); write_method_args(proxy, cur->args, iface->name); fprintf(proxy, ")\n"); fprintf(proxy, "{\n"); /* local variables */ if (has_ret) { fprintf(proxy, " "); write_type(proxy, def->type, def, def->tname); fprintf(proxy, " _Ret;\n"); } fprintf(proxy, " RPC_MESSAGE _Msg;\n"); fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n"); fprintf(proxy, "\n"); /* FIXME: trace */ /* FIXME: clear output vars? */ fprintf(proxy, " NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx); /* FIXME: size buffer */ fprintf(proxy, " NdrProxyGetBuffer(This, &_StubMsg);\n"); /* FIXME: marshall */ fprintf(proxy, " NdrProxySendReceive(This, &_StubMsg);\n"); /* FIXME: unmarshall */ fprintf(proxy, " NdrProxyFreeBuffer(This, &_StubMsg);\n"); if (has_ret) { fprintf(proxy, " return _Ret;\n"); } fprintf(proxy, "}\n"); fprintf(proxy, "\n"); } static void gen_stub(type_t *iface, func_t *cur, char *cas) { var_t *def = cur->def; var_t *arg; int has_ret = !is_void(def->type, def); fprintf(proxy, "void __RPC_STUB %s_", iface->name); write_name(proxy, def); fprintf(proxy, "_Stub(\n"); fprintf(proxy, " IRpcStubBuffer* This,\n"); fprintf(proxy, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); fprintf(proxy, " PRPC_MESSAGE pRpcMessage,\n"); fprintf(proxy, " DWORD* pdwStubPhase)\n"); fprintf(proxy, "{\n"); /* local variables */ if (has_ret) { fprintf(proxy, " "); write_type(proxy, def->type, def, def->tname); fprintf(proxy, " _Ret;\n"); } fprintf(proxy, " %s* _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name); fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n"); arg = cur->args; while (arg) { fprintf(proxy, " "); write_type(proxy, arg->type, arg, arg->tname); fprintf(proxy, " "); write_name(proxy, arg); fprintf(proxy, ";\n"); arg = NEXT_LINK(arg); } fprintf(proxy, "\n"); /* FIXME: trace */ /* FIXME: clear output vars? */ fprintf(proxy, " NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n"); /* FIXME: unmarshall */ fprintf(proxy, " *pdwStubPhase = STUB_CALL_SERVER;\n"); fprintf(proxy, " "); if (has_ret) fprintf(proxy, "_Ret = "); fprintf(proxy, "%s_", iface->name); if (cas) fprintf(proxy, "%s_Stub", cas); else write_name(proxy, def); fprintf(proxy, "(_This"); arg = cur->args; if (arg) { while (NEXT_LINK(arg)) arg = NEXT_LINK(arg); while (arg) { fprintf(proxy, ", "); write_name(proxy, arg); arg = PREV_LINK(arg); } } fprintf(proxy, ");\n"); fprintf(proxy, " *pdwStubPhase = STUB_MARSHAL;\n"); /* FIXME: size buffer */ fprintf(proxy, " NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n"); /* FIXME: marshall */ fprintf(proxy, "}\n"); fprintf(proxy, "\n"); } static int write_proxy_methods(type_t *iface) { func_t *cur = iface->funcs; int i = 0; while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); if (iface->ref) i = write_proxy_methods(iface->ref); while (cur) { var_t *def = cur->def; if (!is_callas(def->attrs)) { if (i) fprintf(proxy, ",\n "); fprintf(proxy, "%s_", iface->name); write_name(proxy, def); fprintf(proxy, "_Proxy"); i++; } cur = PREV_LINK(cur); } return i; } static int write_stub_methods(type_t *iface) { func_t *cur = iface->funcs; int i = 0; while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); if (iface->ref) i = write_stub_methods(iface->ref); else return i; /* skip IUnknown */ while (cur) { var_t *def = cur->def; if (!is_local(def->attrs)) { if (i) fprintf(proxy, ",\n"); fprintf(proxy, " %s_", iface->name); write_name(proxy, def); fprintf(proxy, "_Stub"); i++; } cur = PREV_LINK(cur); } return i; } typedef struct _if_list if_list; struct _if_list { type_t *iface; DECL_LINK(if_list) }; if_list *if_first; void write_proxy(type_t *iface) { int midx = -1, stubs; func_t *cur = iface->funcs; if_list *if_cur; if (!cur) { yywarning("%s has no methods", iface->name); return; } while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */ init_proxy(); if_cur = xmalloc(sizeof(if_list)); if_cur->iface = iface; INIT_LINK(if_cur); LINK(if_cur, if_first); if_first = if_cur; fprintf(proxy, "/*****************************************************************************\n"); fprintf(proxy, " * %s interface\n", iface->name); fprintf(proxy, " */\n"); while (cur) { var_t *def = cur->def; if (!is_local(def->attrs)) { var_t *cas = is_callas(def->attrs); char *cname = cas ? cas->name : NULL; int idx = cur->idx; if (cname) { func_t *m = iface->funcs; while (m && strcmp(get_name(m->def), cname)) m = NEXT_LINK(m); idx = m->idx; } gen_proxy(iface, cur, idx); gen_stub(iface, cur, cname); if (midx == -1) midx = idx; else if (midx != idx) yyerror("method index mismatch in write_proxy"); midx++; } cur = PREV_LINK(cur); } /* proxy vtable */ fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name); fprintf(proxy, " {&IID_%s},\n", iface->name); fprintf(proxy, " {"); write_proxy_methods(iface); fprintf(proxy, "}\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); /* stub vtable */ fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name); stubs = write_stub_methods(iface); fprintf(proxy, "\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name); fprintf(proxy, " {&IID_%s,\n", iface->name); fprintf(proxy, " 0,\n"); fprintf(proxy, " %d,\n", stubs+3); fprintf(proxy, " &%s_table[-3]},\n", iface->name); fprintf(proxy, " {CStdStubBuffer_METHODS}\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); } void finish_proxy(void) { if_list *lcur = if_first; if_list *cur; int c; if (!lcur) return; while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur); fprintf(proxy, "const CInterfaceProxyVtbl* _XXX_ProxyVtblList[] = {\n"); cur = lcur; while (cur) { fprintf(proxy, " (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name); cur = PREV_LINK(cur); } fprintf(proxy, " 0\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); fprintf(proxy, "const CInterfaceStubVtbl* _XXX_StubVtblList[] = {\n"); cur = lcur; while (cur) { fprintf(proxy, " (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name); cur = PREV_LINK(cur); } fprintf(proxy, " 0\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); fprintf(proxy, "const PCInterfaceName _XXX_InterfaceNamesList[] = {\n"); cur = lcur; while (cur) { fprintf(proxy, " \"%s\",\n", cur->iface->name); cur = PREV_LINK(cur); } fprintf(proxy, " 0\n"); fprintf(proxy, "};\n"); fprintf(proxy, "\n"); fprintf(proxy, "#define _XXX_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n"); fprintf(proxy, "\n"); fprintf(proxy, "int __stdcall _XXX_IID_Lookup(const IID* pIID, int* pIndex)\n"); fprintf(proxy, "{\n"); cur = lcur; c = 0; while (cur) { fprintf(proxy, " if (!_XXX_CHECK_IID(%d)) {\n", c); fprintf(proxy, " *pIndex = %d\n", c); fprintf(proxy, " return 1;\n"); fprintf(proxy, " }\n"); cur = PREV_LINK(cur); c++; } fprintf(proxy, " return 0;\n"); fprintf(proxy, "}\n"); fprintf(proxy, "\n"); fprintf(proxy, "const ExtendedProxyFileInfo XXX_ProxyFileInfo = {\n"); fprintf(proxy, " (PCInterfaceProxyVtblList*)&_XXX_ProxyVtblList,\n"); fprintf(proxy, " (PCInterfaceStubVtblList*)&_XXX_StubVtblList,\n"); fprintf(proxy, " (const PCInterfaceName*)&_XXX_InterfaceNamesList,\n"); fprintf(proxy, " 0,\n"); fprintf(proxy, " &_XXX_IID_Lookup,\n"); fprintf(proxy, " %d,\n", c); fprintf(proxy, " 1\n"); fprintf(proxy, "};\n"); fclose(proxy); }