Added rules to parse library, coclass, dispinterface, and module
[wine.git] / tools / widl / proxy.c
blob3badc74d6f65c9ae8f038bf7d6f69d8afa7f34af
1 /*
2 * IDL Compiler
4 * Copyright 2002 Ove Kaaven
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.
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.
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
21 #include "config.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <string.h>
29 #include <assert.h>
30 #include <ctype.h>
31 #include <signal.h>
33 #include "widl.h"
34 #include "utils.h"
35 #include "parser.h"
36 #include "header.h"
38 static FILE* proxy;
40 /* FIXME: support generation of stubless proxies */
42 static void write_stubdesc(void)
44 fprintf(proxy, "const MIDL_STUB_DESC Object_StubDesc = {\n");
45 fprintf(proxy, " 0,\n");
46 fprintf(proxy, " NdrOleAllocate,\n");
47 fprintf(proxy, " NdrOleFree,\n");
48 fprintf(proxy, " {0}, 0, 0, 0, 0,\n");
49 fprintf(proxy, " 0 /* __MIDL_TypeFormatString.Format */\n");
50 fprintf(proxy, "};\n");
51 fprintf(proxy, "\n");
54 static void init_proxy(void)
56 if (proxy) return;
57 proxy = fopen(proxy_name, "w");
58 fprintf(proxy, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION);
59 fprintf(proxy, "#include \"rpcproxy.h\"\n");
60 fprintf(proxy, "#include \"%s\"\n", header_name);
61 fprintf(proxy, "\n");
62 write_stubdesc();
65 static void gen_proxy(type_t *iface, func_t *cur, int idx)
67 var_t *def = cur->def;
68 int has_ret = !is_void(def->type, def);
70 write_type(proxy, def->type, def, def->tname);
71 fprintf(proxy, " CALLBACK %s_", iface->name);
72 write_name(proxy, def);
73 fprintf(proxy, "_Proxy(\n");
74 write_args(proxy, cur->args, iface->name, 1, TRUE);
75 fprintf(proxy, ")\n");
76 fprintf(proxy, "{\n");
77 /* local variables */
78 if (has_ret) {
79 fprintf(proxy, " ");
80 write_type(proxy, def->type, def, def->tname);
81 fprintf(proxy, " _Ret;\n");
83 fprintf(proxy, " RPC_MESSAGE _Msg;\n");
84 fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n");
85 fprintf(proxy, "\n");
87 /* FIXME: trace */
88 /* FIXME: clear output vars? */
90 fprintf(proxy, " NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx);
92 /* FIXME: size buffer */
94 fprintf(proxy, " NdrProxyGetBuffer(This, &_StubMsg);\n");
96 /* FIXME: marshall */
98 fprintf(proxy, " NdrProxySendReceive(This, &_StubMsg);\n");
100 /* FIXME: unmarshall */
102 fprintf(proxy, " NdrProxyFreeBuffer(This, &_StubMsg);\n");
104 if (has_ret) {
105 fprintf(proxy, " return _Ret;\n");
107 fprintf(proxy, "}\n");
108 fprintf(proxy, "\n");
111 static void gen_stub(type_t *iface, func_t *cur, char *cas)
113 var_t *def = cur->def;
114 var_t *arg;
115 int has_ret = !is_void(def->type, def);
117 fprintf(proxy, "void __RPC_STUB %s_", iface->name);
118 write_name(proxy, def);
119 fprintf(proxy, "_Stub(\n");
120 fprintf(proxy, " IRpcStubBuffer* This,\n");
121 fprintf(proxy, " IRpcChannelBuffer* pRpcChannelBuffer,\n");
122 fprintf(proxy, " PRPC_MESSAGE pRpcMessage,\n");
123 fprintf(proxy, " DWORD* pdwStubPhase)\n");
124 fprintf(proxy, "{\n");
125 /* local variables */
126 if (has_ret) {
127 fprintf(proxy, " ");
128 write_type(proxy, def->type, def, def->tname);
129 fprintf(proxy, " _Ret;\n");
131 fprintf(proxy, " %s* _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name);
132 fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n");
133 arg = cur->args;
134 while (arg) {
135 fprintf(proxy, " ");
136 write_type(proxy, arg->type, arg, arg->tname);
137 fprintf(proxy, " ");
138 write_name(proxy, arg);
139 fprintf(proxy, ";\n");
140 arg = NEXT_LINK(arg);
142 fprintf(proxy, "\n");
144 /* FIXME: trace */
145 /* FIXME: clear output vars? */
147 fprintf(proxy, " NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n");
149 /* FIXME: unmarshall */
151 fprintf(proxy, " *pdwStubPhase = STUB_CALL_SERVER;\n");
152 fprintf(proxy, " ");
153 if (has_ret) fprintf(proxy, "_Ret = ");
154 fprintf(proxy, "%s_", iface->name);
155 if (cas) fprintf(proxy, "%s_Stub", cas);
156 else write_name(proxy, def);
157 fprintf(proxy, "(_This");
158 arg = cur->args;
159 if (arg) {
160 while (NEXT_LINK(arg)) arg = NEXT_LINK(arg);
161 while (arg) {
162 fprintf(proxy, ", ");
163 write_name(proxy, arg);
164 arg = PREV_LINK(arg);
167 fprintf(proxy, ");\n");
168 fprintf(proxy, " *pdwStubPhase = STUB_MARSHAL;\n");
170 /* FIXME: size buffer */
172 fprintf(proxy, " NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n");
174 /* FIXME: marshall */
176 fprintf(proxy, "}\n");
177 fprintf(proxy, "\n");
180 static int write_proxy_methods(type_t *iface)
182 func_t *cur = iface->funcs;
183 int i = 0;
184 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
186 if (iface->ref) i = write_proxy_methods(iface->ref);
187 while (cur) {
188 var_t *def = cur->def;
189 if (!is_callas(def->attrs)) {
190 if (i) fprintf(proxy, ",\n ");
191 fprintf(proxy, "%s_", iface->name);
192 write_name(proxy, def);
193 fprintf(proxy, "_Proxy");
194 i++;
196 cur = PREV_LINK(cur);
198 return i;
201 static int write_stub_methods(type_t *iface)
203 func_t *cur = iface->funcs;
204 int i = 0;
205 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
207 if (iface->ref) i = write_stub_methods(iface->ref);
208 else return i; /* skip IUnknown */
209 while (cur) {
210 var_t *def = cur->def;
211 if (!is_local(def->attrs)) {
212 if (i) fprintf(proxy, ",\n");
213 fprintf(proxy, " %s_", iface->name);
214 write_name(proxy, def);
215 fprintf(proxy, "_Stub");
216 i++;
218 cur = PREV_LINK(cur);
220 return i;
223 static void write_proxy(type_t *iface)
225 int midx = -1, stubs;
226 func_t *cur = iface->funcs;
228 if (!cur) return;
229 if (!do_everything) return;
231 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
233 /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */
235 init_proxy();
237 fprintf(proxy, "/*****************************************************************************\n");
238 fprintf(proxy, " * %s interface\n", iface->name);
239 fprintf(proxy, " */\n");
240 while (cur) {
241 var_t *def = cur->def;
242 if (!is_local(def->attrs)) {
243 var_t *cas = is_callas(def->attrs);
244 char *cname = cas ? cas->name : NULL;
245 int idx = cur->idx;
246 if (cname) {
247 func_t *m = iface->funcs;
248 while (m && strcmp(get_name(m->def), cname))
249 m = NEXT_LINK(m);
250 idx = m->idx;
252 gen_proxy(iface, cur, idx);
253 gen_stub(iface, cur, cname);
254 if (midx == -1) midx = idx;
255 else if (midx != idx) yyerror("method index mismatch in write_proxy");
256 midx++;
258 cur = PREV_LINK(cur);
261 /* proxy vtable */
262 fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name);
263 fprintf(proxy, " {&IID_%s},\n", iface->name);
264 fprintf(proxy, " {");
265 write_proxy_methods(iface);
266 fprintf(proxy, "}\n");
267 fprintf(proxy, "};\n");
268 fprintf(proxy, "\n");
270 /* stub vtable */
271 fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name);
272 stubs = write_stub_methods(iface);
273 fprintf(proxy, "\n");
274 fprintf(proxy, "};\n");
275 fprintf(proxy, "\n");
276 fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name);
277 fprintf(proxy, " {&IID_%s,\n", iface->name);
278 fprintf(proxy, " 0,\n");
279 fprintf(proxy, " %d,\n", stubs+3);
280 fprintf(proxy, " &%s_table[-3]},\n", iface->name);
281 fprintf(proxy, " {CStdStubBuffer_METHODS}\n");
282 fprintf(proxy, "};\n");
283 fprintf(proxy, "\n");
286 void write_proxies(ifref_t *ifaces)
288 ifref_t *lcur = ifaces;
289 ifref_t *cur;
290 char *file_id = proxy_token;
291 int c;
293 if (!lcur) return;
294 while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
296 cur = lcur;
297 while (cur) {
298 if (is_object(cur->iface->attrs) && !is_local(cur->iface->attrs))
299 write_proxy(cur->iface);
300 cur = PREV_LINK(cur);
303 if (!proxy) return;
305 fprintf(proxy, "const CInterfaceProxyVtbl* _%s_ProxyVtblList[] = {\n", file_id);
306 cur = lcur;
307 while (cur) {
308 fprintf(proxy, " (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name);
309 cur = PREV_LINK(cur);
311 fprintf(proxy, " 0\n");
312 fprintf(proxy, "};\n");
313 fprintf(proxy, "\n");
315 fprintf(proxy, "const CInterfaceStubVtbl* _%s_StubVtblList[] = {\n", file_id);
316 cur = lcur;
317 while (cur) {
318 fprintf(proxy, " (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name);
319 cur = PREV_LINK(cur);
321 fprintf(proxy, " 0\n");
322 fprintf(proxy, "};\n");
323 fprintf(proxy, "\n");
325 fprintf(proxy, "const PCInterfaceName _%s_InterfaceNamesList[] = {\n", file_id);
326 cur = lcur;
327 while (cur) {
328 fprintf(proxy, " \"%s\",\n", cur->iface->name);
329 cur = PREV_LINK(cur);
331 fprintf(proxy, " 0\n");
332 fprintf(proxy, "};\n");
333 fprintf(proxy, "\n");
335 fprintf(proxy, "#define _%s_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n", file_id);
336 fprintf(proxy, "\n");
337 fprintf(proxy, "int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id);
338 fprintf(proxy, "{\n");
339 cur = lcur;
340 c = 0;
341 while (cur) {
342 fprintf(proxy, " if (!_%s_CHECK_IID(%d)) {\n", file_id, c);
343 fprintf(proxy, " *pIndex = %d\n", c);
344 fprintf(proxy, " return 1;\n");
345 fprintf(proxy, " }\n");
346 cur = PREV_LINK(cur);
347 c++;
349 fprintf(proxy, " return 0;\n");
350 fprintf(proxy, "}\n");
351 fprintf(proxy, "\n");
353 fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo = {\n", file_id);
354 fprintf(proxy, " (PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id);
355 fprintf(proxy, " (PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id);
356 fprintf(proxy, " (const PCInterfaceName*)&_%s_InterfaceNamesList,\n", file_id);
357 fprintf(proxy, " 0,\n");
358 fprintf(proxy, " &_%s_IID_Lookup,\n", file_id);
359 fprintf(proxy, " %d,\n", c);
360 fprintf(proxy, " 1\n");
361 fprintf(proxy, "};\n");
363 fclose(proxy);