wined3d: Vertex declaration recording state.
[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, "\n");
310
311         last_size = size;
312
313         var = PREV_LINK(var);
314     }
315 }
316
317 void unmarshall_arguments(FILE *file, int indent, func_t *func)
318 {
319     unsigned int alignment;
320     unsigned int size;
321     unsigned int last_size = 0;
322     var_t *var;
323
324     if (!func->args)
325         return;
326
327     var = func->args;
328     while (NEXT_LINK(var)) var = NEXT_LINK(var);
329     while (var)
330     {
331         alignment = 0;
332         switch (var->type->type)
333         {
334         case RPC_FC_BYTE:
335         case RPC_FC_CHAR:
336         case RPC_FC_SMALL:
337         case RPC_FC_USMALL:
338             size = 1;
339             alignment = 0;
340             break;
341
342         case RPC_FC_WCHAR:
343         case RPC_FC_USHORT:
344         case RPC_FC_SHORT:
345             size = 2;
346             if (last_size != 0 && last_size < 2)
347                 alignment = (2 - last_size);
348             break;
349
350         case RPC_FC_ULONG:
351         case RPC_FC_LONG:
352         case RPC_FC_FLOAT:
353         case RPC_FC_ERROR_STATUS_T:
354             size = 4;
355             if (last_size != 0 && last_size < 4)
356                 alignment = (4 - last_size);
357             break;
358
359         case RPC_FC_HYPER:
360         case RPC_FC_DOUBLE:
361             size = 8;
362             if (last_size != 0 && last_size < 4)
363                 alignment = (4 - last_size);
364             break;
365
366         default:
367             size = 0;
368             error("Unknown/unsupported type: %s (0x%02x)\n", var->name, var->type->type);
369         }
370
371         if (alignment != 0)
372             print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
373
374         print_file(file, indent, "");
375         write_name(file, var);
376         fprintf(file, " = *((");
377         write_type(file, var->type, var, var->tname);
378         fprintf(file, " *)_StubMsg.Buffer)++;\n");
379         fprintf(file, "\n");
380
381         last_size = size;
382
383         var = PREV_LINK(var);
384     }
385 }