Alexandre Julliard | 7d4ee77 | 2002-07-16 03:20:45 +0000 | [diff] [blame] | 1 | /* |
| 2 | * IDL Compiler |
| 3 | * |
| 4 | * Copyright 2002 Ove Kaaven |
| 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 19 | */ |
| 20 | |
| 21 | #include "config.h" |
| 22 | |
| 23 | #include <stdio.h> |
| 24 | #include <stdlib.h> |
Dmitry Timoshkov | c63d980 | 2002-08-17 18:28:43 +0000 | [diff] [blame] | 25 | #ifdef HAVE_UNISTD_H |
| 26 | # include <unistd.h> |
| 27 | #endif |
Alexandre Julliard | 7d4ee77 | 2002-07-16 03:20:45 +0000 | [diff] [blame] | 28 | #include <string.h> |
| 29 | #include <assert.h> |
| 30 | #include <ctype.h> |
| 31 | #include <signal.h> |
| 32 | |
| 33 | #include "widl.h" |
| 34 | #include "utils.h" |
| 35 | #include "parser.h" |
| 36 | #include "header.h" |
Alexandre Julliard | 7d4ee77 | 2002-07-16 03:20:45 +0000 | [diff] [blame] | 37 | |
| 38 | /* FIXME: support generation of stubless proxies */ |
| 39 | |
| 40 | static void write_stubdesc(void) |
| 41 | { |
| 42 | fprintf(proxy, "const MIDL_STUB_DESC Object_StubDesc = {\n"); |
| 43 | fprintf(proxy, " 0,\n"); |
| 44 | fprintf(proxy, " NdrOleAllocate,\n"); |
| 45 | fprintf(proxy, " NdrOleFree,\n"); |
| 46 | fprintf(proxy, " {0}, 0, 0, 0, 0,\n"); |
| 47 | fprintf(proxy, " 0 /* __MIDL_TypeFormatString.Format */\n"); |
| 48 | fprintf(proxy, "};\n"); |
| 49 | fprintf(proxy, "\n"); |
| 50 | } |
| 51 | |
| 52 | static void init_proxy(void) |
| 53 | { |
| 54 | if (proxy) return; |
| 55 | proxy = fopen(proxy_name, "w"); |
| 56 | fprintf(proxy, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION); |
| 57 | fprintf(proxy, "#include \"rpcproxy.h\"\n"); |
| 58 | fprintf(proxy, "#include \"%s\"\n", header_name); |
| 59 | fprintf(proxy, "\n"); |
| 60 | write_stubdesc(); |
| 61 | } |
| 62 | |
| 63 | static void gen_proxy(type_t *iface, func_t *cur, int idx) |
| 64 | { |
| 65 | var_t *def = cur->def; |
| 66 | int has_ret = !is_void(def->type, def); |
| 67 | |
| 68 | write_type(proxy, def->type, def, def->tname); |
| 69 | fprintf(proxy, " CALLBACK %s_", iface->name); |
| 70 | write_name(proxy, def); |
| 71 | fprintf(proxy, "_Proxy(\n"); |
| 72 | write_method_args(proxy, cur->args, iface->name); |
| 73 | fprintf(proxy, ")\n"); |
| 74 | fprintf(proxy, "{\n"); |
| 75 | /* local variables */ |
| 76 | if (has_ret) { |
| 77 | fprintf(proxy, " "); |
| 78 | write_type(proxy, def->type, def, def->tname); |
| 79 | fprintf(proxy, " _Ret;\n"); |
| 80 | } |
| 81 | fprintf(proxy, " RPC_MESSAGE _Msg;\n"); |
| 82 | fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n"); |
| 83 | fprintf(proxy, "\n"); |
| 84 | |
| 85 | /* FIXME: trace */ |
| 86 | /* FIXME: clear output vars? */ |
| 87 | |
| 88 | fprintf(proxy, " NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx); |
| 89 | |
| 90 | /* FIXME: size buffer */ |
| 91 | |
| 92 | fprintf(proxy, " NdrProxyGetBuffer(This, &_StubMsg);\n"); |
| 93 | |
| 94 | /* FIXME: marshall */ |
| 95 | |
| 96 | fprintf(proxy, " NdrProxySendReceive(This, &_StubMsg);\n"); |
| 97 | |
| 98 | /* FIXME: unmarshall */ |
| 99 | |
| 100 | fprintf(proxy, " NdrProxyFreeBuffer(This, &_StubMsg);\n"); |
| 101 | |
| 102 | if (has_ret) { |
| 103 | fprintf(proxy, " return _Ret;\n"); |
| 104 | } |
| 105 | fprintf(proxy, "}\n"); |
| 106 | fprintf(proxy, "\n"); |
| 107 | } |
| 108 | |
| 109 | static void gen_stub(type_t *iface, func_t *cur, char *cas) |
| 110 | { |
| 111 | var_t *def = cur->def; |
| 112 | var_t *arg; |
| 113 | int has_ret = !is_void(def->type, def); |
| 114 | |
| 115 | fprintf(proxy, "void __RPC_STUB %s_", iface->name); |
| 116 | write_name(proxy, def); |
| 117 | fprintf(proxy, "_Stub(\n"); |
| 118 | fprintf(proxy, " IRpcStubBuffer* This,\n"); |
| 119 | fprintf(proxy, " IRpcChannelBuffer* pRpcChannelBuffer,\n"); |
| 120 | fprintf(proxy, " PRPC_MESSAGE pRpcMessage,\n"); |
| 121 | fprintf(proxy, " DWORD* pdwStubPhase)\n"); |
| 122 | fprintf(proxy, "{\n"); |
| 123 | /* local variables */ |
| 124 | if (has_ret) { |
| 125 | fprintf(proxy, " "); |
| 126 | write_type(proxy, def->type, def, def->tname); |
| 127 | fprintf(proxy, " _Ret;\n"); |
| 128 | } |
| 129 | fprintf(proxy, " %s* _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name); |
| 130 | fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n"); |
| 131 | arg = cur->args; |
| 132 | while (arg) { |
| 133 | fprintf(proxy, " "); |
| 134 | write_type(proxy, arg->type, arg, arg->tname); |
| 135 | fprintf(proxy, " "); |
| 136 | write_name(proxy, arg); |
| 137 | fprintf(proxy, ";\n"); |
| 138 | arg = NEXT_LINK(arg); |
| 139 | } |
| 140 | fprintf(proxy, "\n"); |
| 141 | |
| 142 | /* FIXME: trace */ |
| 143 | /* FIXME: clear output vars? */ |
| 144 | |
| 145 | fprintf(proxy, " NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n"); |
| 146 | |
| 147 | /* FIXME: unmarshall */ |
| 148 | |
| 149 | fprintf(proxy, " *pdwStubPhase = STUB_CALL_SERVER;\n"); |
| 150 | fprintf(proxy, " "); |
| 151 | if (has_ret) fprintf(proxy, "_Ret = "); |
| 152 | fprintf(proxy, "%s_", iface->name); |
| 153 | if (cas) fprintf(proxy, "%s_Stub", cas); |
| 154 | else write_name(proxy, def); |
| 155 | fprintf(proxy, "(_This"); |
| 156 | arg = cur->args; |
| 157 | if (arg) { |
| 158 | while (NEXT_LINK(arg)) arg = NEXT_LINK(arg); |
| 159 | while (arg) { |
| 160 | fprintf(proxy, ", "); |
| 161 | write_name(proxy, arg); |
| 162 | arg = PREV_LINK(arg); |
| 163 | } |
| 164 | } |
| 165 | fprintf(proxy, ");\n"); |
| 166 | fprintf(proxy, " *pdwStubPhase = STUB_MARSHAL;\n"); |
| 167 | |
| 168 | /* FIXME: size buffer */ |
| 169 | |
| 170 | fprintf(proxy, " NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n"); |
| 171 | |
| 172 | /* FIXME: marshall */ |
| 173 | |
| 174 | fprintf(proxy, "}\n"); |
| 175 | fprintf(proxy, "\n"); |
| 176 | } |
| 177 | |
| 178 | static int write_proxy_methods(type_t *iface) |
| 179 | { |
| 180 | func_t *cur = iface->funcs; |
| 181 | int i = 0; |
| 182 | while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); |
| 183 | |
| 184 | if (iface->ref) i = write_proxy_methods(iface->ref); |
| 185 | while (cur) { |
| 186 | var_t *def = cur->def; |
| 187 | if (!is_callas(def->attrs)) { |
| 188 | if (i) fprintf(proxy, ",\n "); |
| 189 | fprintf(proxy, "%s_", iface->name); |
| 190 | write_name(proxy, def); |
| 191 | fprintf(proxy, "_Proxy"); |
| 192 | i++; |
| 193 | } |
| 194 | cur = PREV_LINK(cur); |
| 195 | } |
| 196 | return i; |
| 197 | } |
| 198 | |
| 199 | static int write_stub_methods(type_t *iface) |
| 200 | { |
| 201 | func_t *cur = iface->funcs; |
| 202 | int i = 0; |
| 203 | while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); |
| 204 | |
| 205 | if (iface->ref) i = write_stub_methods(iface->ref); |
| 206 | else return i; /* skip IUnknown */ |
| 207 | while (cur) { |
| 208 | var_t *def = cur->def; |
| 209 | if (!is_local(def->attrs)) { |
| 210 | if (i) fprintf(proxy, ",\n"); |
| 211 | fprintf(proxy, " %s_", iface->name); |
| 212 | write_name(proxy, def); |
| 213 | fprintf(proxy, "_Stub"); |
| 214 | i++; |
| 215 | } |
| 216 | cur = PREV_LINK(cur); |
| 217 | } |
| 218 | return i; |
| 219 | } |
| 220 | |
| 221 | typedef struct _if_list if_list; |
| 222 | struct _if_list { |
| 223 | type_t *iface; |
| 224 | DECL_LINK(if_list) |
| 225 | }; |
| 226 | |
| 227 | if_list *if_first; |
| 228 | |
| 229 | void write_proxy(type_t *iface) |
| 230 | { |
| 231 | int midx = -1, stubs; |
| 232 | func_t *cur = iface->funcs; |
| 233 | if_list *if_cur; |
| 234 | |
| 235 | if (!cur) { |
| 236 | yywarning("%s has no methods", iface->name); |
| 237 | return; |
| 238 | } |
| 239 | |
| 240 | while (NEXT_LINK(cur)) cur = NEXT_LINK(cur); |
| 241 | |
| 242 | /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */ |
| 243 | |
| 244 | init_proxy(); |
| 245 | |
| 246 | if_cur = xmalloc(sizeof(if_list)); |
| 247 | if_cur->iface = iface; |
| 248 | INIT_LINK(if_cur); |
| 249 | LINK(if_cur, if_first); |
| 250 | if_first = if_cur; |
| 251 | |
| 252 | fprintf(proxy, "/*****************************************************************************\n"); |
| 253 | fprintf(proxy, " * %s interface\n", iface->name); |
| 254 | fprintf(proxy, " */\n"); |
| 255 | while (cur) { |
| 256 | var_t *def = cur->def; |
| 257 | if (!is_local(def->attrs)) { |
| 258 | var_t *cas = is_callas(def->attrs); |
| 259 | char *cname = cas ? cas->name : NULL; |
| 260 | int idx = cur->idx; |
| 261 | if (cname) { |
| 262 | func_t *m = iface->funcs; |
| 263 | while (m && strcmp(get_name(m->def), cname)) |
| 264 | m = NEXT_LINK(m); |
| 265 | idx = m->idx; |
| 266 | } |
| 267 | gen_proxy(iface, cur, idx); |
| 268 | gen_stub(iface, cur, cname); |
| 269 | if (midx == -1) midx = idx; |
| 270 | else if (midx != idx) yyerror("method index mismatch in write_proxy"); |
| 271 | midx++; |
| 272 | } |
| 273 | cur = PREV_LINK(cur); |
| 274 | } |
| 275 | |
| 276 | /* proxy vtable */ |
| 277 | fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name); |
| 278 | fprintf(proxy, " {&IID_%s},\n", iface->name); |
| 279 | fprintf(proxy, " {"); |
| 280 | write_proxy_methods(iface); |
| 281 | fprintf(proxy, "}\n"); |
| 282 | fprintf(proxy, "};\n"); |
| 283 | fprintf(proxy, "\n"); |
| 284 | |
| 285 | /* stub vtable */ |
| 286 | fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name); |
| 287 | stubs = write_stub_methods(iface); |
| 288 | fprintf(proxy, "\n"); |
| 289 | fprintf(proxy, "};\n"); |
| 290 | fprintf(proxy, "\n"); |
| 291 | fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name); |
| 292 | fprintf(proxy, " {&IID_%s,\n", iface->name); |
| 293 | fprintf(proxy, " 0,\n"); |
| 294 | fprintf(proxy, " %d,\n", stubs+3); |
| 295 | fprintf(proxy, " &%s_table[-3]},\n", iface->name); |
| 296 | fprintf(proxy, " {CStdStubBuffer_METHODS}\n"); |
| 297 | fprintf(proxy, "};\n"); |
| 298 | fprintf(proxy, "\n"); |
| 299 | } |
| 300 | |
| 301 | void finish_proxy(void) |
| 302 | { |
| 303 | if_list *lcur = if_first; |
| 304 | if_list *cur; |
| 305 | int c; |
| 306 | |
| 307 | if (!lcur) return; |
| 308 | while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur); |
| 309 | |
| 310 | fprintf(proxy, "const CInterfaceProxyVtbl* _XXX_ProxyVtblList[] = {\n"); |
| 311 | cur = lcur; |
| 312 | while (cur) { |
| 313 | fprintf(proxy, " (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name); |
| 314 | cur = PREV_LINK(cur); |
| 315 | } |
| 316 | fprintf(proxy, " 0\n"); |
| 317 | fprintf(proxy, "};\n"); |
| 318 | fprintf(proxy, "\n"); |
| 319 | |
| 320 | fprintf(proxy, "const CInterfaceStubVtbl* _XXX_StubVtblList[] = {\n"); |
| 321 | cur = lcur; |
| 322 | while (cur) { |
| 323 | fprintf(proxy, " (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name); |
| 324 | cur = PREV_LINK(cur); |
| 325 | } |
| 326 | fprintf(proxy, " 0\n"); |
| 327 | fprintf(proxy, "};\n"); |
| 328 | fprintf(proxy, "\n"); |
| 329 | |
| 330 | fprintf(proxy, "const PCInterfaceName _XXX_InterfaceNamesList[] = {\n"); |
| 331 | cur = lcur; |
| 332 | while (cur) { |
| 333 | fprintf(proxy, " \"%s\",\n", cur->iface->name); |
| 334 | cur = PREV_LINK(cur); |
| 335 | } |
| 336 | fprintf(proxy, " 0\n"); |
| 337 | fprintf(proxy, "};\n"); |
| 338 | fprintf(proxy, "\n"); |
| 339 | |
| 340 | fprintf(proxy, "#define _XXX_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n"); |
| 341 | fprintf(proxy, "\n"); |
| 342 | fprintf(proxy, "int __stdcall _XXX_IID_Lookup(const IID* pIID, int* pIndex)\n"); |
| 343 | fprintf(proxy, "{\n"); |
| 344 | cur = lcur; |
| 345 | c = 0; |
| 346 | while (cur) { |
| 347 | fprintf(proxy, " if (!_XXX_CHECK_IID(%d)) {\n", c); |
| 348 | fprintf(proxy, " *pIndex = %d\n", c); |
| 349 | fprintf(proxy, " return 1;\n"); |
| 350 | fprintf(proxy, " }\n"); |
| 351 | cur = PREV_LINK(cur); |
| 352 | c++; |
| 353 | } |
| 354 | fprintf(proxy, " return 0;\n"); |
| 355 | fprintf(proxy, "}\n"); |
| 356 | fprintf(proxy, "\n"); |
| 357 | |
| 358 | fprintf(proxy, "const ExtendedProxyFileInfo XXX_ProxyFileInfo = {\n"); |
| 359 | fprintf(proxy, " (PCInterfaceProxyVtblList*)&_XXX_ProxyVtblList,\n"); |
| 360 | fprintf(proxy, " (PCInterfaceStubVtblList*)&_XXX_StubVtblList,\n"); |
| 361 | fprintf(proxy, " (const PCInterfaceName*)&_XXX_InterfaceNamesList,\n"); |
| 362 | fprintf(proxy, " 0,\n"); |
| 363 | fprintf(proxy, " &_XXX_IID_Lookup,\n"); |
| 364 | fprintf(proxy, " %d,\n", c); |
| 365 | fprintf(proxy, " 1\n"); |
| 366 | fprintf(proxy, "};\n"); |
| 367 | |
| 368 | fclose(proxy); |
| 369 | } |