winemenubuilder: Provide depth to the menus created.
[wine] / tools / widl / typegen.c
1 /*
2  * Format String Generator for IDL Compiler
3  *
4  * Copyright 2005 Eric Kohl
5  * Copyright 2005 Robert Shearman
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <string.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <signal.h>
34
35 #include "widl.h"
36 #include "utils.h"
37 #include "parser.h"
38 #include "header.h"
39 #include "windef.h"
40
41 #include "widl.h"
42 #include "typegen.h"
43
44 static int print_file(FILE *file, int indent, const char *format, ...)
45 {
46     va_list va;
47     int i, r;
48
49     va_start(va, format);
50     for (i = 0; i < indent; i++)
51         fprintf(file, "    ");
52     r = vfprintf(file, format, va);
53     va_end(va);
54     return r;
55 }
56
57 static void write_procformatstring_var(FILE *file, int indent, var_t *var)
58 {
59     switch(var->type->type)
60     {
61 #define CASE_BASETYPE(fctype) \
62     case RPC_##fctype: \
63         print_file(file, indent, "0x%02x,    /* " #fctype " */\n", var->type->type); \
64         break
65
66     CASE_BASETYPE(FC_BYTE);
67     CASE_BASETYPE(FC_CHAR);
68     CASE_BASETYPE(FC_WCHAR);
69     CASE_BASETYPE(FC_USHORT);
70     CASE_BASETYPE(FC_SHORT);
71     CASE_BASETYPE(FC_ULONG);
72     CASE_BASETYPE(FC_LONG);
73     CASE_BASETYPE(FC_HYPER);
74     CASE_BASETYPE(FC_IGNORE);
75     CASE_BASETYPE(FC_USMALL);
76     CASE_BASETYPE(FC_SMALL);
77     CASE_BASETYPE(FC_FLOAT);
78     CASE_BASETYPE(FC_DOUBLE);
79     CASE_BASETYPE(FC_ERROR_STATUS_T);
80 #undef CASE_BASETYPE
81     default:
82         error("Unknown/unsupported type: %s (0x%02x)\n", var->name, var->type->type);
83     }
84 }
85
86 void write_procformatstring(FILE *file, type_t *iface)
87 {
88     int indent = 0;
89     func_t *func = iface->funcs;
90     var_t *var;
91
92     print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
93     print_file(file, indent, "{\n");
94     indent++;
95     print_file(file, indent, "0,\n");
96     print_file(file, indent, "{\n");
97     indent++;
98
99     while (NEXT_LINK(func)) func = NEXT_LINK(func);
100     while (func)
101     {
102         /* emit argument data */
103         if (func->args)
104         {
105             var = func->args;
106             while (NEXT_LINK(var)) var = NEXT_LINK(var);
107             while (var)
108             {
109                 print_file(file, indent, "0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
110                 write_procformatstring_var(file, indent, var);
111                 var = PREV_LINK(var);
112             }
113         }
114
115         /* emit return value data */
116         var = func->def;
117         if (is_void(var->type, NULL))
118         {
119             print_file(file, indent, "0x5b,    /* FC_END */\n");
120             print_file(file, indent, "0x5c,    /* FC_PAD */\n");
121         }
122         else
123         {
124             print_file(file, indent, "0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
125             write_procformatstring_var(file, indent, var);
126         }
127
128         func = PREV_LINK(func);
129     }
130
131     print_file(file, indent, "0x0\n");
132     indent--;
133     print_file(file, indent, "}\n");
134     indent--;
135     print_file(file, indent, "};\n");
136     print_file(file, indent, "\n");
137 }
138
139
140 static void write_typeformatstring_var(FILE *file, int indent, var_t *var)
141 {
142     int ptr_level = var->ptr_level;
143
144     /* basic types don't need a type format string */
145     if (ptr_level == 0)
146         return;
147
148     if (ptr_level == 1)
149     {
150         switch (var->type->type)
151         {
152 #define CASE_BASETYPE(fctype) \
153         case RPC_##fctype: \
154             print_file(file, indent, "0x11, 0x08,    /* FC_RP [simple_pointer] */\n"); \
155             print_file(file, indent, "0x%02x,    /* " #fctype " */\n", var->type->type); \
156             print_file(file, indent, "0x5c,          /* FC_PAD */\n"); \
157             break
158         CASE_BASETYPE(FC_BYTE);
159         CASE_BASETYPE(FC_CHAR);
160         CASE_BASETYPE(FC_SMALL);
161         CASE_BASETYPE(FC_USMALL);
162         CASE_BASETYPE(FC_WCHAR);
163         CASE_BASETYPE(FC_SHORT);
164         CASE_BASETYPE(FC_USHORT);
165         CASE_BASETYPE(FC_LONG);
166         CASE_BASETYPE(FC_ULONG);
167         CASE_BASETYPE(FC_FLOAT);
168         CASE_BASETYPE(FC_HYPER);
169         CASE_BASETYPE(FC_DOUBLE);
170         CASE_BASETYPE(FC_ENUM16);
171         CASE_BASETYPE(FC_ENUM32);
172         CASE_BASETYPE(FC_IGNORE);
173         CASE_BASETYPE(FC_ERROR_STATUS_T);
174         default:
175             error("write_typeformatstring_var: Unknown/unsupported type: %s (0x%02x)\n", var->name, var->type->type);
176         }
177     }
178 }
179
180 void write_typeformatstring(FILE *file, type_t *iface)
181 {
182     int indent = 0;
183     func_t *func = iface->funcs;
184     var_t *var;
185
186     print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
187     print_file(file, indent, "{\n");
188     indent++;
189     print_file(file, indent, "0,\n");
190     print_file(file, indent, "{\n");
191     indent++;
192     print_file(file, indent, "NdrFcShort(0x0),\n");
193
194     while (NEXT_LINK(func)) func = NEXT_LINK(func);
195     while (func)
196     {
197         if (func->args)
198         {
199             var = func->args;
200             while (NEXT_LINK(var)) var = NEXT_LINK(var);
201             while (var)
202             {
203                 write_typeformatstring_var(file, indent, var);
204                 var = PREV_LINK(var);
205             }
206         }
207         func = PREV_LINK(func);
208     }
209
210     print_file(file, indent, "0x0\n");
211     indent--;
212     print_file(file, indent, "}\n");
213     indent--;
214     print_file(file, indent, "};\n");
215     print_file(file, indent, "\n");
216 }
217
218
219 unsigned int get_required_buffer_size(type_t *type)
220 {
221     switch(type->type)
222     {
223         case RPC_FC_BYTE:
224         case RPC_FC_CHAR:
225         case RPC_FC_WCHAR:
226         case RPC_FC_USHORT:
227         case RPC_FC_SHORT:
228         case RPC_FC_USMALL:
229         case RPC_FC_SMALL:
230         case RPC_FC_ULONG:
231         case RPC_FC_LONG:
232         case RPC_FC_FLOAT:
233         case RPC_FC_IGNORE:
234         case RPC_FC_ERROR_STATUS_T:
235             return 4;
236
237         case RPC_FC_HYPER:
238         case RPC_FC_DOUBLE:
239             return 8;
240
241         default:
242             error("Unknown/unsupported type: %s (0x%02x)\n", type->name, type->type);
243             return 0;
244     }
245 }
246
247 void marshall_arguments(FILE *file, int indent, func_t *func)
248 {
249     unsigned int alignment;
250     unsigned int size;
251     unsigned int last_size = 0;
252     var_t *var;
253
254     if (!func->args)
255         return;
256
257     var = func->args;
258     while (NEXT_LINK(var)) var = NEXT_LINK(var);
259     while (var)
260     {
261         alignment = 0;
262         switch (var->type->type)
263         {
264         case RPC_FC_BYTE:
265         case RPC_FC_CHAR:
266         case RPC_FC_SMALL:
267         case RPC_FC_USMALL:
268             size = 1;
269             alignment = 0;
270             break;
271
272         case RPC_FC_WCHAR:
273         case RPC_FC_USHORT:
274         case RPC_FC_SHORT:
275             size = 2;
276             if (last_size != 0 && last_size < 2)
277                 alignment = (2 - last_size);
278             break;
279
280         case RPC_FC_ULONG:
281         case RPC_FC_LONG:
282         case RPC_FC_FLOAT:
283         case RPC_FC_ERROR_STATUS_T:
284             size = 4;
285             if (last_size != 0 && last_size < 4)
286                 alignment = (4 - last_size);
287             break;
288
289         case RPC_FC_HYPER:
290         case RPC_FC_DOUBLE:
291             size = 8;
292             if (last_size != 0 && last_size < 4)
293                 alignment = (4 - last_size);
294             break;
295
296         default:
297             size = 0;
298             error("Unknown/unsupported type: %s (0x%02x)\n", var->name, var->type->type);
299         }
300
301         if (alignment != 0)
302             print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
303
304         print_file(file, indent, "*(");
305         write_type(file, var->type, var, var->tname);
306         fprintf(file, " *)_StubMsg.Buffer = ");
307         write_name(file, var);
308         fprintf(file, ";\n");
309         fprintf(file, "_StubMsg.Buffer += sizeof(");
310         write_type(file, var->type, var, var->tname);
311         fprintf(file, ");\n");
312         fprintf(file, "\n");
313
314         last_size = size;
315
316         var = PREV_LINK(var);
317     }
318 }
319
320 void unmarshall_arguments(FILE *file, int indent, func_t *func)
321 {
322     unsigned int alignment;
323     unsigned int size;
324     unsigned int last_size = 0;
325     var_t *var;
326
327     if (!func->args)
328         return;
329
330     var = func->args;
331     while (NEXT_LINK(var)) var = NEXT_LINK(var);
332     while (var)
333     {
334         alignment = 0;
335         switch (var->type->type)
336         {
337         case RPC_FC_BYTE:
338         case RPC_FC_CHAR:
339         case RPC_FC_SMALL:
340         case RPC_FC_USMALL:
341             size = 1;
342             alignment = 0;
343             break;
344
345         case RPC_FC_WCHAR:
346         case RPC_FC_USHORT:
347         case RPC_FC_SHORT:
348             size = 2;
349             if (last_size != 0 && last_size < 2)
350                 alignment = (2 - last_size);
351             break;
352
353         case RPC_FC_ULONG:
354         case RPC_FC_LONG:
355         case RPC_FC_FLOAT:
356         case RPC_FC_ERROR_STATUS_T:
357             size = 4;
358             if (last_size != 0 && last_size < 4)
359                 alignment = (4 - last_size);
360             break;
361
362         case RPC_FC_HYPER:
363         case RPC_FC_DOUBLE:
364             size = 8;
365             if (last_size != 0 && last_size < 4)
366                 alignment = (4 - last_size);
367             break;
368
369         default:
370             size = 0;
371             error("Unknown/unsupported type: %s (0x%02x)\n", var->name, var->type->type);
372         }
373
374         if (alignment != 0)
375             print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
376
377         print_file(file, indent, "");
378         write_name(file, var);
379         fprintf(file, " = *(");
380         write_type(file, var->type, var, var->tname);
381         fprintf(file, " *)_StubMsg.Buffer;\n");
382         fprintf(file, "_StubMsg.Buffer += sizeof(");
383         write_type(file, var->type, var, var->tname);
384         fprintf(file, ");\n");
385         fprintf(file, "\n");
386
387         last_size = size;
388
389         var = PREV_LINK(var);
390     }
391 }