- add ZBuffer write support
[wine/multimedia.git] / tools / widl / proxy.c
blob0234b03f62b0eb95e742ab4599a225856c41330c
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 /* FIXME: support generation of stubless proxies */
40 static void write_stubdesc(void)
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");
52 static void init_proxy(void)
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();
63 static void gen_proxy(type_t *iface, func_t *cur, int idx)
65 var_t *def = cur->def;
66 int has_ret = !is_void(def->type, def);
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_args(proxy, cur->args, iface->name, 1, TRUE);
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");
81 fprintf(proxy, " RPC_MESSAGE _Msg;\n");
82 fprintf(proxy, " MIDL_STUB_MESSAGE _StubMsg;\n");
83 fprintf(proxy, "\n");
85 /* FIXME: trace */
86 /* FIXME: clear output vars? */
88 fprintf(proxy, " NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx);
90 /* FIXME: size buffer */
92 fprintf(proxy, " NdrProxyGetBuffer(This, &_StubMsg);\n");
94 /* FIXME: marshall */
96 fprintf(proxy, " NdrProxySendReceive(This, &_StubMsg);\n");
98 /* FIXME: unmarshall */
100 fprintf(proxy, " NdrProxyFreeBuffer(This, &_StubMsg);\n");
102 if (has_ret) {
103 fprintf(proxy, " return _Ret;\n");
105 fprintf(proxy, "}\n");
106 fprintf(proxy, "\n");
109 static void gen_stub(type_t *iface, func_t *cur, char *cas)
111 var_t *def = cur->def;
112 var_t *arg;
113 int has_ret = !is_void(def->type, def);
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");
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);
140 fprintf(proxy, "\n");
142 /* FIXME: trace */
143 /* FIXME: clear output vars? */
145 fprintf(proxy, " NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n");
147 /* FIXME: unmarshall */
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);
165 fprintf(proxy, ");\n");
166 fprintf(proxy, " *pdwStubPhase = STUB_MARSHAL;\n");
168 /* FIXME: size buffer */
170 fprintf(proxy, " NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n");
172 /* FIXME: marshall */
174 fprintf(proxy, "}\n");
175 fprintf(proxy, "\n");
178 static int write_proxy_methods(type_t *iface)
180 func_t *cur = iface->funcs;
181 int i = 0;
182 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
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++;
194 cur = PREV_LINK(cur);
196 return i;
199 static int write_stub_methods(type_t *iface)
201 func_t *cur = iface->funcs;
202 int i = 0;
203 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
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++;
216 cur = PREV_LINK(cur);
218 return i;
221 typedef struct _if_list if_list;
222 struct _if_list {
223 type_t *iface;
224 DECL_LINK(if_list)
227 if_list *if_first;
229 void write_proxy(type_t *iface)
231 int midx = -1, stubs;
232 func_t *cur = iface->funcs;
233 if_list *if_cur;
235 if (!cur) return;
236 if (header_only) return;
238 while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
240 /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */
242 init_proxy();
244 if_cur = xmalloc(sizeof(if_list));
245 if_cur->iface = iface;
246 INIT_LINK(if_cur);
247 LINK(if_cur, if_first);
248 if_first = if_cur;
250 fprintf(proxy, "/*****************************************************************************\n");
251 fprintf(proxy, " * %s interface\n", iface->name);
252 fprintf(proxy, " */\n");
253 while (cur) {
254 var_t *def = cur->def;
255 if (!is_local(def->attrs)) {
256 var_t *cas = is_callas(def->attrs);
257 char *cname = cas ? cas->name : NULL;
258 int idx = cur->idx;
259 if (cname) {
260 func_t *m = iface->funcs;
261 while (m && strcmp(get_name(m->def), cname))
262 m = NEXT_LINK(m);
263 idx = m->idx;
265 gen_proxy(iface, cur, idx);
266 gen_stub(iface, cur, cname);
267 if (midx == -1) midx = idx;
268 else if (midx != idx) yyerror("method index mismatch in write_proxy");
269 midx++;
271 cur = PREV_LINK(cur);
274 /* proxy vtable */
275 fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name);
276 fprintf(proxy, " {&IID_%s},\n", iface->name);
277 fprintf(proxy, " {");
278 write_proxy_methods(iface);
279 fprintf(proxy, "}\n");
280 fprintf(proxy, "};\n");
281 fprintf(proxy, "\n");
283 /* stub vtable */
284 fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name);
285 stubs = write_stub_methods(iface);
286 fprintf(proxy, "\n");
287 fprintf(proxy, "};\n");
288 fprintf(proxy, "\n");
289 fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name);
290 fprintf(proxy, " {&IID_%s,\n", iface->name);
291 fprintf(proxy, " 0,\n");
292 fprintf(proxy, " %d,\n", stubs+3);
293 fprintf(proxy, " &%s_table[-3]},\n", iface->name);
294 fprintf(proxy, " {CStdStubBuffer_METHODS}\n");
295 fprintf(proxy, "};\n");
296 fprintf(proxy, "\n");
299 void finish_proxy(void)
301 if_list *lcur = if_first;
302 if_list *cur;
303 char *file_id = proxy_token;
304 int c;
306 if (!lcur) return;
307 while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
309 fprintf(proxy, "const CInterfaceProxyVtbl* _%s_ProxyVtblList[] = {\n", file_id);
310 cur = lcur;
311 while (cur) {
312 fprintf(proxy, " (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name);
313 cur = PREV_LINK(cur);
315 fprintf(proxy, " 0\n");
316 fprintf(proxy, "};\n");
317 fprintf(proxy, "\n");
319 fprintf(proxy, "const CInterfaceStubVtbl* _%s_StubVtblList[] = {\n", file_id);
320 cur = lcur;
321 while (cur) {
322 fprintf(proxy, " (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name);
323 cur = PREV_LINK(cur);
325 fprintf(proxy, " 0\n");
326 fprintf(proxy, "};\n");
327 fprintf(proxy, "\n");
329 fprintf(proxy, "const PCInterfaceName _%s_InterfaceNamesList[] = {\n", file_id);
330 cur = lcur;
331 while (cur) {
332 fprintf(proxy, " \"%s\",\n", cur->iface->name);
333 cur = PREV_LINK(cur);
335 fprintf(proxy, " 0\n");
336 fprintf(proxy, "};\n");
337 fprintf(proxy, "\n");
339 fprintf(proxy, "#define _%s_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n", file_id);
340 fprintf(proxy, "\n");
341 fprintf(proxy, "int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id);
342 fprintf(proxy, "{\n");
343 cur = lcur;
344 c = 0;
345 while (cur) {
346 fprintf(proxy, " if (!_%s_CHECK_IID(%d)) {\n", file_id, c);
347 fprintf(proxy, " *pIndex = %d\n", c);
348 fprintf(proxy, " return 1;\n");
349 fprintf(proxy, " }\n");
350 cur = PREV_LINK(cur);
351 c++;
353 fprintf(proxy, " return 0;\n");
354 fprintf(proxy, "}\n");
355 fprintf(proxy, "\n");
357 fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo = {\n", file_id);
358 fprintf(proxy, " (PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id);
359 fprintf(proxy, " (PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id);
360 fprintf(proxy, " (const PCInterfaceName*)&_%s_InterfaceNamesList,\n", file_id);
361 fprintf(proxy, " 0,\n");
362 fprintf(proxy, " &_%s_IID_Lookup,\n", file_id);
363 fprintf(proxy, " %d,\n", c);
364 fprintf(proxy, " 1\n");
365 fprintf(proxy, "};\n");
367 fclose(proxy);