Suggest make uninstall in case the user tried make install.
[wine] / tools / widl / client.c
1 /*
2  * IDL Compiler
3  *
4  * Copyright 2005 Eric Kohl
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 #include "wine/port.h"
23  
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <ctype.h>
30 #include <signal.h>
31
32 #include "windef.h"
33
34 #include "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "header.h"
38
39 #include "widltypes.h"
40 #include "typelib.h"
41 #include "typelib_struct.h"
42
43 #define END_OF_LIST(list)       \
44   do {                          \
45     if (list) {                 \
46       while (NEXT_LINK(list))   \
47         list = NEXT_LINK(list); \
48     }                           \
49   } while(0)
50
51 static FILE* client;
52 static int indent = 0;
53
54 static int print_client( const char *format, ... )
55 {
56     va_list va;
57     int i, r;
58
59     va_start(va, format);
60     for (i = 0; i < indent; i++)
61         fprintf(client, "    ");
62     r = vfprintf(client, format, va);
63     va_end(va);
64     return r;
65 }
66
67
68 static void write_procformatstring(type_t *iface)
69 {
70     func_t *cur = iface->funcs;
71
72     print_client("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
73     print_client("{\n");
74     indent++;
75     print_client("0,\n");
76     print_client("{\n");
77     indent++;
78
79     while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
80     while (cur)
81     {
82         var_t *def = cur->def;
83
84         if (is_void(def->type, NULL))
85         {
86             print_client("0x5b,    /* FC_END */\n");
87             print_client("0x5c,    /* FC_PAD */\n");
88         }
89         else
90         {
91             print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
92             print_client("0x%02x,    /* <type> */\n", def->type->type);
93         }
94
95         cur = PREV_LINK(cur);
96     }
97
98     print_client("0x0\n");
99     indent--;
100     print_client("}\n");
101     indent--;
102     print_client("};\n");
103     print_client("\n");
104 }
105
106
107 static void write_typeformatstring(void)
108 {
109     print_client("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
110     print_client("{\n");
111     indent++;
112     print_client("0,\n");
113     print_client("{\n");
114     indent++;
115     print_client("NdrFcShort(0x0),\n");
116     print_client("0x0\n");
117     indent--;
118     print_client("}\n");
119     indent--;
120     print_client("};\n");
121     print_client("\n");
122 }
123
124
125 static void write_function_stubs(type_t *iface)
126 {
127     func_t *cur = iface->funcs;
128     char *handle_name = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
129     int method_count = 0;
130     unsigned int proc_offset = 0;
131
132     while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
133     while (cur)
134     {
135         var_t *def = cur->def;
136
137         write_type(client, def->type, def, def->tname);
138         fprintf(client, " ");
139         write_name(client, def);
140         fprintf(client, "(\n");
141         indent++;
142         if (cur->args)
143             write_args(client, cur->args, iface->name, 0, TRUE);
144         else
145             print_client("void");
146         fprintf(client, ")\n");
147         indent--;
148
149         /* write the functions body */
150         fprintf(client, "{\n");
151         indent++;
152
153         /* declare return value '_RetVal' */
154         if (!is_void(def->type, NULL))
155         {
156             print_client("");
157             write_type(client, def->type, def, def->tname);
158             fprintf(client, " _RetVal;\n");
159         }
160
161         if (handle_name)
162             print_client("RPC_BINDING_HANDLE _Handle = 0;\n");
163
164         print_client("RPC_MESSAGE _RpcMessage;\n");
165         print_client("MIDL_STUB_MESSAGE _StubMsg;\n");
166         fprintf(client, "\n");
167         print_client("RpcTryFinally\n");
168         print_client("{\n");
169         indent++;
170
171         print_client("NdrClientInitializeNew(\n");
172         indent++;
173         print_client("(PRPC_MESSAGE)&_RpcMessage,\n");
174         print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
175         print_client("(PMIDL_STUB_DESC)&%s_StubDesc,\n", iface->name);
176         print_client("%d);\n", method_count);
177         indent--;
178         fprintf(client, "\n");
179
180         if (handle_name)
181             print_client("_Handle = %s;\n", handle_name);
182
183         /* FIXME: marshal arguments */
184         print_client("_StubMsg.BufferLength = 0UL;\n");
185         /* print_client("NdrNsGetBuffer(\n"); */
186         print_client("NdrGetBuffer(\n");
187         indent++;
188         print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
189         print_client("_StubMsg.BufferLength,\n");
190         if (handle_name)
191             print_client("%_Handle);\n");
192         else
193             print_client("%s__MIDL_AutoBindHandle);\n", iface->name);
194         indent--;
195         fprintf(client, "\n");
196
197
198         /* send/recieve message */
199         /* print_client("NdrNsSendReceive(\n"); */
200         print_client("NdrSendReceive(\n");
201         indent++;
202         print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
203         print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer);\n");
204         /* print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer,\n"); */
205         /* print_client("(RPC_BINDING_HANDLE __RPC_FAR *) &%s__MIDL_AutoBindHandle);\n", iface->name); */
206         indent--;
207
208         /* unmarshal return value */
209         if (is_void(def->type, NULL))
210         {
211             proc_offset += 2;
212         }
213         else
214         {
215             fprintf(client, "\n");
216
217             print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
218             indent++;
219             print_client("NdrConvert(\n");
220             indent++;
221             print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
222             print_client("(PFORMAT_STRING)&__MIDL_ProcFormatString[%u]);\n", proc_offset);
223             indent -= 2;
224             fprintf(client, "\n");
225
226             print_client("_RetVal = *((");
227             write_type(client, def->type, def, def->tname);
228             fprintf(client, " __RPC_FAR *)_StubMsg.Buffer)++;\n");
229
230             /* FIXME: update proc_offset */
231             proc_offset += 2;
232         }
233
234         indent--;
235         print_client("}\n");
236         print_client("RpcFinally\n");
237         print_client("{\n");
238         indent++;
239
240
241         /* FIXME: emit client finally code */
242
243         print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n");
244
245         indent--;
246         print_client("}\n");
247         print_client("RpcEndFinally\n");
248
249
250         /* emit return code */
251         if (!is_void(def->type, NULL))
252         {
253             fprintf(client, "\n");
254             print_client("return _RetVal;\n");
255         }
256
257         indent--;
258         fprintf(client, "}\n");
259         fprintf(client, "\n");
260
261         method_count++;
262         cur = PREV_LINK(cur);
263     }
264 }
265
266
267 static void write_bindinghandledecl(type_t *iface)
268 {
269     print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n", iface->name);
270     fprintf(client, "\n");
271 }
272
273
274 static void write_stubdescdecl(type_t *iface)
275 {
276     print_client("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);
277     fprintf(client, "\n");
278 }
279
280
281 static void write_stubdescriptor(type_t *iface)
282 {
283     char *handle_name = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
284
285     print_client("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
286     print_client("{\n");
287     indent++;
288     print_client("(void __RPC_FAR *)& %s___RpcClientInterface,\n", iface->name);
289     print_client("MIDL_user_allocate,\n");
290     print_client("MIDL_user_free,\n");
291     if (handle_name)
292         print_client("&%s,\n", handle_name);
293     else
294         print_client("&%s__MIDL_AutoBindHandle,\n", iface->name);
295     print_client("0,\n");
296     print_client("0,\n");
297     print_client("0,\n");
298     print_client("0,\n");
299     print_client("__MIDL_TypeFormatString.Format,\n");
300     print_client("1, /* -error bounds_check flag */\n");
301     print_client("0x10001, /* Ndr library version */\n");
302     print_client("0,\n");
303     print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");
304     print_client("0,\n");
305     print_client("0,\n");
306     print_client("0,  /* notify & notify_flag routine table */\n");
307     print_client("1,  /* Flags */\n");
308     print_client("0,  /* Reserved3 */\n");
309     print_client("0,  /* Reserved4 */\n");
310     print_client("0   /* Reserved5 */\n");
311     indent--;
312     print_client("};\n");
313     fprintf(client, "\n");
314 }
315
316
317 static void write_clientinterfacedecl(type_t *iface)
318 {
319     unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
320     UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
321
322     print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name );
323     print_client("{\n");
324     indent++;
325     print_client("sizeof(RPC_CLIENT_INTERFACE),\n");
326     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",
327                  uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
328                  uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
329                  uuid->Data4[7], LOWORD(ver), HIWORD(ver));
330     print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
331     print_client("0,\n");
332     print_client("0,\n");
333     print_client("0,\n");
334     print_client("0,\n");
335     print_client("0,\n");
336     print_client("0,\n");
337     indent--;
338     print_client("};\n");
339     print_client("RPC_IF_HANDLE %s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
340                  iface->name, LOWORD(ver), HIWORD(ver), iface->name);
341     fprintf(client, "\n");
342 }
343
344
345 static void write_formatdesc( const char *str )
346 {
347     print_client("typedef struct _MIDL_%s_FORMAT_STRING\n", str );
348     print_client("{\n");
349     indent++;
350     print_client("short Pad;\n");
351     print_client("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
352     indent--;
353     print_client("} MIDL_%s_FORMAT_STRING;\n", str);
354     print_client("\n");
355 }
356
357
358 static void write_formatstringsdecl(type_t *iface)
359 {
360     func_t *cur;
361     int byte_count = 1;
362
363     print_client("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */
364
365     /* determine the proc format string size */
366     cur = iface->funcs;
367     while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
368     while (cur)
369     {
370         byte_count += 2; /* FIXME: determine real size */
371         cur = PREV_LINK(cur);
372     }
373     print_client("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count);
374
375     fprintf(client, "\n");
376     write_formatdesc("TYPE");
377     write_formatdesc("PROC");
378     fprintf(client, "\n");
379     print_client("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
380     print_client("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
381     print_client("\n");
382 }
383
384
385 static void write_implicithandledecl(type_t *iface)
386 {
387     char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
388
389     if (var)
390     {
391         fprintf(client, "handle_t %s;\n", var);
392         fprintf(client, "\n");
393     }
394 }
395
396
397 static void init_client(void)
398 {
399     if (client) return;
400     if (!(client = fopen(client_name, "w")))
401         error("Could not open %s for output\n", client_name);
402
403     print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name);
404     print_client("#include<string.h>\n");
405     print_client("#ifdef _ALPHA_\n");
406     print_client("#include<stdarg.h>\n");
407     print_client("#endif\n");
408     fprintf(client, "\n");
409     print_client("#include\"%s\"\n", header_name);
410     fprintf(client, "\n");
411 }
412
413
414 void write_client(ifref_t *ifaces)
415 {
416     ifref_t *lcur = ifaces;
417     char *file_id = client_token;
418     int c;
419
420     if (!do_client)
421         return;
422     if (!lcur)
423         return;
424     END_OF_LIST(lcur);
425
426     init_client();
427     if (!client)
428         return;
429
430     write_formatstringsdecl(lcur->iface);
431     write_implicithandledecl(lcur->iface);
432
433     write_clientinterfacedecl(lcur->iface);
434     write_stubdescdecl(lcur->iface);
435     write_bindinghandledecl(lcur->iface);
436
437     write_function_stubs(lcur->iface);
438     write_stubdescriptor(lcur->iface);
439
440     print_client("#if !defined(__RPC_WIN32__)\n");
441     print_client("#error  Invalid build platform for this stub.\n");
442     print_client("#endif\n");
443     fprintf(client, "\n");
444
445     write_procformatstring(lcur->iface);
446     write_typeformatstring();
447
448     fprintf(client, "\n");
449
450     fclose(client);
451 }