widl: Conformant arrays have a size of 0.
[wine/wine-gecko.git] / tools / widl / typegen.c
blob85c83c4bbf11f70259ac0ada1ad4cb0db903546b
1 /*
2 * Format String Generator for IDL Compiler
4 * Copyright 2005 Eric Kohl
5 * Copyright 2005 Robert Shearman
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.
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.
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
22 #include "config.h"
23 #include "wine/port.h"
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 #include <limits.h>
36 #include "widl.h"
37 #include "utils.h"
38 #include "parser.h"
39 #include "header.h"
40 #include "windef.h"
42 #include "widl.h"
43 #include "typegen.h"
45 static const func_t *current_func;
46 static const var_t *current_fields;
48 static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array);
50 static int print_file(FILE *file, int indent, const char *format, ...)
52 va_list va;
53 int i, r;
55 if (!file) return 0;
57 va_start(va, format);
58 for (i = 0; i < indent; i++)
59 fprintf(file, " ");
60 r = vfprintf(file, format, va);
61 va_end(va);
62 return r;
65 static inline int type_has_ref(const type_t *type)
67 return (type->type == 0 && type->ref);
70 static inline int is_base_type(unsigned char type)
72 switch (type)
74 case RPC_FC_BYTE:
75 case RPC_FC_CHAR:
76 case RPC_FC_USMALL:
77 case RPC_FC_SMALL:
78 case RPC_FC_WCHAR:
79 case RPC_FC_USHORT:
80 case RPC_FC_SHORT:
81 case RPC_FC_ULONG:
82 case RPC_FC_LONG:
83 case RPC_FC_HYPER:
84 case RPC_FC_IGNORE:
85 case RPC_FC_FLOAT:
86 case RPC_FC_DOUBLE:
87 case RPC_FC_ENUM16:
88 case RPC_FC_ENUM32:
89 case RPC_FC_ERROR_STATUS_T:
90 return TRUE;
92 default:
93 return FALSE;
97 static size_t write_procformatstring_var(FILE *file, int indent,
98 const var_t *var, int is_return, unsigned int *type_offset)
100 size_t size;
101 int ptr_level = var->ptr_level;
102 const type_t *type = var->type;
104 int is_in = is_attr(var->attrs, ATTR_IN);
105 int is_out = is_attr(var->attrs, ATTR_OUT);
107 if (!is_in && !is_out) is_in = TRUE;
109 if (ptr_level == 0 && type_has_ref(type))
110 type = type->ref;
112 if (ptr_level == 0 && !var->array && is_base_type(type->type))
114 if (is_return)
115 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
116 else
117 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
119 switch(type->type)
121 #define CASE_BASETYPE(fctype) \
122 case RPC_##fctype: \
123 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
124 size = 2; /* includes param type prefix */ \
125 break
127 CASE_BASETYPE(FC_BYTE);
128 CASE_BASETYPE(FC_CHAR);
129 CASE_BASETYPE(FC_WCHAR);
130 CASE_BASETYPE(FC_USHORT);
131 CASE_BASETYPE(FC_SHORT);
132 CASE_BASETYPE(FC_ULONG);
133 CASE_BASETYPE(FC_LONG);
134 CASE_BASETYPE(FC_HYPER);
135 CASE_BASETYPE(FC_IGNORE);
136 CASE_BASETYPE(FC_USMALL);
137 CASE_BASETYPE(FC_SMALL);
138 CASE_BASETYPE(FC_FLOAT);
139 CASE_BASETYPE(FC_DOUBLE);
140 CASE_BASETYPE(FC_ERROR_STATUS_T);
141 #undef CASE_BASETYPE
142 default:
143 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
144 size = 0;
147 else
149 if (is_return)
150 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
151 else if (is_in && is_out)
152 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
153 else if (is_out)
154 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
155 else
156 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
158 print_file(file, indent, "0x01,\n");
159 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
160 size = 4; /* includes param type prefix */
162 *type_offset += get_size_typeformatstring_var(var);
163 return size;
166 void write_procformatstring(FILE *file, type_t *iface)
168 int indent = 0;
169 var_t *var;
170 unsigned int type_offset = 2;
172 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
173 print_file(file, indent, "{\n");
174 indent++;
175 print_file(file, indent, "0,\n");
176 print_file(file, indent, "{\n");
177 indent++;
179 if (iface->funcs)
181 func_t *func = iface->funcs;
182 while (NEXT_LINK(func)) func = NEXT_LINK(func);
183 for (; func; func = PREV_LINK(func))
185 /* emit argument data */
186 if (func->args)
188 var = func->args;
189 while (NEXT_LINK(var)) var = NEXT_LINK(var);
190 while (var)
192 write_procformatstring_var(file, indent, var, FALSE,
193 &type_offset);
195 var = PREV_LINK(var);
199 /* emit return value data */
200 var = func->def;
201 if (is_void(var->type, NULL))
203 print_file(file, indent, "0x5b, /* FC_END */\n");
204 print_file(file, indent, "0x5c, /* FC_PAD */\n");
206 else
207 write_procformatstring_var(file, indent, var, TRUE,
208 &type_offset);
212 print_file(file, indent, "0x0\n");
213 indent--;
214 print_file(file, indent, "}\n");
215 indent--;
216 print_file(file, indent, "};\n");
217 print_file(file, indent, "\n");
220 /* write conformance / variance descriptor */
221 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const var_t *fields, const expr_t *expr)
223 unsigned char operator_type = 0;
224 const char *operator_string = "no operators";
225 const expr_t *subexpr = expr;
227 if (!file) return 4; /* optimisation for sizing pass */
229 switch (subexpr->type)
231 case EXPR_PPTR:
232 subexpr = subexpr->ref;
233 operator_type = RPC_FC_DEREFERENCE;
234 operator_string = "FC_DEREFERENCE";
235 break;
236 case EXPR_DIV:
237 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
239 subexpr = subexpr->ref;
240 operator_type = RPC_FC_DIV_2;
241 operator_string = "FC_DIV_2";
243 break;
244 case EXPR_MUL:
245 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
247 subexpr = subexpr->ref;
248 operator_type = RPC_FC_MULT_2;
249 operator_string = "FC_MULT_2";
251 break;
252 case EXPR_SUB:
253 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
255 subexpr = subexpr->ref;
256 operator_type = RPC_FC_SUB_1;
257 operator_string = "FC_SUB_1";
259 break;
260 case EXPR_ADD:
261 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
263 subexpr = subexpr->ref;
264 operator_type = RPC_FC_ADD_1;
265 operator_string = "FC_ADD_1";
267 break;
268 default:
269 break;
272 if (subexpr->type == EXPR_IDENTIFIER)
274 unsigned char correlation_type;
275 const type_t *correlation_variable = NULL;
276 unsigned char param_type = 0;
277 const char *param_type_string = NULL;
278 size_t offset;
280 if (fields)
282 const var_t *var;
284 for (offset = 0, var = fields; var; var = NEXT_LINK(var))
286 offset -= type_memsize(var->type, var->ptr_level, var->array);
287 if (!strcmp(var->name, subexpr->u.sval))
289 correlation_variable = var->type;
290 break;
293 if (!correlation_variable)
294 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
295 subexpr->u.sval);
297 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
299 else
301 const var_t *var = func->args;
303 while (NEXT_LINK(var)) var = NEXT_LINK(var);
304 /* FIXME: not all stack variables are sizeof(void *) */
305 for (offset = 0; var; offset += sizeof(void *), var = PREV_LINK(var))
307 if (!strcmp(var->name, subexpr->u.sval))
309 correlation_variable = var->type;
310 break;
313 if (!correlation_variable)
314 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
315 subexpr->u.sval);
317 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
320 while (type_has_ref(correlation_variable))
321 correlation_variable = correlation_variable->ref;
323 switch (correlation_variable->type)
325 case RPC_FC_CHAR:
326 case RPC_FC_SMALL:
327 param_type = RPC_FC_SMALL;
328 param_type_string = "FC_SMALL";
329 break;
330 case RPC_FC_BYTE:
331 case RPC_FC_USMALL:
332 param_type = RPC_FC_USMALL;
333 param_type_string = "FC_USMALL";
334 break;
335 case RPC_FC_WCHAR:
336 case RPC_FC_SHORT:
337 param_type = RPC_FC_SHORT;
338 param_type_string = "FC_SHORT";
339 break;
340 case RPC_FC_USHORT:
341 param_type = RPC_FC_USHORT;
342 param_type_string = "FC_USHORT";
343 break;
344 case RPC_FC_LONG:
345 param_type = RPC_FC_LONG;
346 param_type_string = "FC_LONG";
347 break;
348 case RPC_FC_ULONG:
349 param_type = RPC_FC_ULONG;
350 param_type_string = "FC_ULONG";
351 break;
352 default:
353 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
354 correlation_variable->type);
357 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
358 correlation_type | param_type,
359 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
360 param_type_string);
361 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
362 print_file(file, 2, "0x%x, /* %soffset = %d */\n",
363 offset,
364 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
365 offset);
367 else
368 error("write_conf_or_var_desc: expression type %d\n", subexpr->type);
369 return 4;
372 static size_t fields_memsize(const var_t *v)
374 size_t size = 0;
375 const var_t *first = v;
376 if (!v) return 0;
377 while (NEXT_LINK(v)) v = NEXT_LINK(v);
378 while (v) {
379 size += type_memsize(v->type, v->ptr_level, v->array);
380 if (v == first) break;
381 v = PREV_LINK(v);
383 return size;
386 static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array)
388 size_t size = 0;
390 if (ptr_level)
391 return sizeof(void *);
393 switch (t->type)
395 case RPC_FC_BYTE:
396 case RPC_FC_CHAR:
397 case RPC_FC_USMALL:
398 case RPC_FC_SMALL:
399 size = 1;
400 break;
401 case RPC_FC_WCHAR:
402 case RPC_FC_USHORT:
403 case RPC_FC_SHORT:
404 case RPC_FC_ENUM16:
405 size = 2;
406 break;
407 case RPC_FC_ULONG:
408 case RPC_FC_LONG:
409 case RPC_FC_ERROR_STATUS_T:
410 case RPC_FC_ENUM32:
411 case RPC_FC_FLOAT:
412 size = 4;
413 break;
414 case RPC_FC_HYPER:
415 case RPC_FC_DOUBLE:
416 size = 8;
417 break;
418 case RPC_FC_STRUCT:
419 case RPC_FC_CVSTRUCT:
420 case RPC_FC_CPSTRUCT:
421 case RPC_FC_CSTRUCT:
422 case RPC_FC_PSTRUCT:
423 case RPC_FC_BOGUS_STRUCT:
424 case RPC_FC_ENCAPSULATED_UNION:
425 case RPC_FC_NON_ENCAPSULATED_UNION:
426 size = fields_memsize(t->fields);
427 break;
428 default:
429 error("type_memsize: Unknown type %d", t->type);
430 size = 0;
433 if (array)
435 if (array->is_const)
436 size *= array->cval;
437 else
438 size = 0;
441 return size;
444 static size_t write_string_tfs(FILE *file, const attr_t *attrs,
445 const type_t *type, const expr_t *array,
446 const char *name)
448 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
449 int has_size = size_is && (size_is->type != EXPR_VOID);
451 if ((type->type != RPC_FC_CHAR) && (type->type != RPC_FC_WCHAR))
453 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", type->type, name);
454 return 0;
457 if (array && array->is_const)
459 size_t typestring_size;
461 if (array->cval > USHRT_MAX)
462 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
463 name, USHRT_MAX, array->cval - USHRT_MAX);
465 if (type->type == RPC_FC_CHAR)
466 print_file(file, 2, "0x%x, /* FC_CSTRING */\n", RPC_FC_C_CSTRING);
467 else
468 print_file(file, 2, "0x%x, /* FC_WSTRING */\n", RPC_FC_C_WSTRING);
469 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
470 typestring_size = 2;
472 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", array->cval, array->cval);
473 typestring_size += 2;
475 return typestring_size;
477 else if (has_size)
479 size_t typestring_size;
481 if (type->type == RPC_FC_CHAR)
482 print_file(file, 2, "0x%x, /* FC_C_CSTRING */\n", RPC_FC_C_CSTRING);
483 else
484 print_file(file, 2, "0x%x, /* FC_C_WSTRING */\n", RPC_FC_C_WSTRING);
485 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
486 typestring_size = 2;
488 typestring_size += write_conf_or_var_desc(file, current_func, NULL, size_is);
490 return typestring_size;
492 else
494 size_t typestring_size;
496 if (type->type == RPC_FC_CHAR)
497 print_file(file, 2, "0x%x, /* FC_C_CSTRING */\n", RPC_FC_C_CSTRING);
498 else
499 print_file(file, 2, "0x%x, /* FC_C_WSTRING */\n", RPC_FC_C_WSTRING);
500 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
501 typestring_size = 2;
503 return typestring_size;
507 static size_t write_array_tfs(FILE *file, const attr_t *attrs,
508 const type_t *type, const expr_t *array,
509 const char *name)
511 const expr_t *length_is = get_attrp(attrs, ATTR_LENGTHIS);
512 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
513 int has_length = length_is && (length_is->type != EXPR_VOID);
514 int has_size = size_is && (size_is->type != EXPR_VOID) && !array->is_const;
516 /* FIXME: need to analyse type for pointers */
518 if (NEXT_LINK(array)) /* multi-dimensional array */
520 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name);
521 return 0;
523 else
525 if (!has_length && !has_size)
527 /* fixed array */
528 size_t typestring_size;
529 size_t size = type_memsize(type, 0, array);
530 if (size < USHRT_MAX)
532 print_file(file, 2, "0x%x, /* FC_SMFARRAY */\n", RPC_FC_SMFARRAY);
533 /* alignment */
534 print_file(file, 2, "0x%x, /* 0 */\n", 0);
535 /* size */
536 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", size, size);
537 typestring_size = 4;
539 else
541 print_file(file, 2, "0x%x, /* FC_LGFARRAY */\n", RPC_FC_LGFARRAY);
542 /* alignment */
543 print_file(file, 2, "0x%x, /* 0 */\n", 0);
544 /* size */
545 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", size, size);
546 typestring_size = 6;
549 /* FIXME: write out pointer descriptor if necessary */
551 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
552 print_file(file, 2, "FC_END,\n");
553 typestring_size += 2;
555 return typestring_size;
557 else if (has_length && !has_size)
559 /* varying array */
560 size_t typestring_size;
561 size_t element_size = type_memsize(type, 0, NULL);
562 size_t elements = array->cval;
563 size_t total_size = element_size * elements;
565 if (total_size < USHRT_MAX)
567 print_file(file, 2, "0x%x, /* FC_SMVARRAY */\n", RPC_FC_SMVARRAY);
568 /* alignment */
569 print_file(file, 2, "0x%x, /* 0 */\n", 0);
570 /* total size */
571 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", total_size, total_size);
572 /* number of elements */
573 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", elements, elements);
574 typestring_size = 6;
576 else
578 print_file(file, 2, "0x%x, /* FC_LGVARRAY */\n", RPC_FC_LGVARRAY);
579 /* alignment */
580 print_file(file, 2, "0x%x, /* 0 */\n", 0);
581 /* total size */
582 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", total_size, total_size);
583 /* number of elements */
584 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", elements, elements);
585 typestring_size = 10;
587 /* element size */
588 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
589 typestring_size += 2;
591 typestring_size += write_conf_or_var_desc(file, current_func,
592 current_fields,
593 length_is);
595 /* FIXME: write out pointer descriptor if necessary */
597 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
598 print_file(file, 2, "FC_END,\n");
599 typestring_size += 2;
601 return typestring_size;
603 else if (!has_length && has_size)
605 /* conformant array */
606 size_t typestring_size;
607 size_t element_size = type_memsize(type, 0, NULL);
609 print_file(file, 2, "0x%x, /* FC_CARRAY */\n", RPC_FC_CARRAY);
610 /* alignment */
611 print_file(file, 2, "0x%x, /* 0 */\n", 0);
612 /* element size */
613 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
614 typestring_size = 4;
616 typestring_size += write_conf_or_var_desc(file, current_func,
617 current_fields, size_is);
619 /* FIXME: write out pointer descriptor if necessary */
621 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
622 print_file(file, 2, "FC_END,\n");
623 typestring_size += 2;
625 return typestring_size;
627 else
629 /* conformant varying array */
630 size_t typestring_size;
631 size_t element_size = type_memsize(type, 0, NULL);
633 print_file(file, 2, "0x%x, /* FC_CARRAY */\n", RPC_FC_CARRAY);
634 /* alignment */
635 print_file(file, 2, "0x%x, /* 0 */\n", 0);
636 /* element size */
637 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
638 typestring_size = 4;
640 typestring_size += write_conf_or_var_desc(file, current_func,
641 current_fields, size_is);
642 typestring_size += write_conf_or_var_desc(file, current_func,
643 current_fields,
644 length_is);
646 /* FIXME: write out pointer descriptor if necessary */
648 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
649 print_file(file, 2, "FC_END,\n");
650 typestring_size += 2;
652 return typestring_size;
657 static size_t write_struct_tfs(FILE *file, const type_t *type, const char *name)
659 size_t total_size;
660 size_t typestring_size;
661 switch (type->type)
663 case RPC_FC_STRUCT:
664 total_size = type_memsize(type, 0, NULL);
666 if (total_size > USHRT_MAX)
667 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
668 name, USHRT_MAX, total_size - USHRT_MAX);
670 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_STRUCT, "FC_STRUCT");
671 /* alignment */
672 print_file(file, 2, "0x0,\n");
673 /* total size */
674 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
675 typestring_size = 4;
677 /* member layout */
678 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
679 print_file(file, 2, "FC_END,\n");
681 typestring_size += 2;
682 return typestring_size;
683 default:
684 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
685 return 0;
689 static size_t write_union_tfs(FILE *file, const attr_t *attrs, const type_t *type, const char *name)
691 error("write_union_tfs: Unimplemented\n");
692 return 0;
695 static size_t write_typeformatstring_var(FILE *file, int indent,
696 const var_t *var)
698 const type_t *type = var->type;
699 int ptr_level = var->ptr_level;
701 while (TRUE)
703 int pointer_type;
704 size_t typeformat_size = 0;
706 if (is_string_type(var->attrs, ptr_level, var->array))
708 typeformat_size += write_string_tfs(file, var->attrs, type, var->array, var->name);
709 return typeformat_size;
712 if (is_array_type(var->attrs, ptr_level, var->array))
714 typeformat_size += write_array_tfs(file, var->attrs, type, var->array, var->name);
715 return typeformat_size;
718 if (ptr_level == 0)
720 /* follow reference if the type has one */
721 if (type_has_ref(type))
723 type = type->ref;
724 /* FIXME: get new ptr_level from type */
725 continue;
728 /* basic types don't need a type format string */
729 if (is_base_type(type->type))
730 return typeformat_size;
732 switch (type->type)
734 case RPC_FC_STRUCT:
735 case RPC_FC_PSTRUCT:
736 case RPC_FC_CSTRUCT:
737 case RPC_FC_CPSTRUCT:
738 case RPC_FC_CVSTRUCT:
739 case RPC_FC_BOGUS_STRUCT:
740 typeformat_size += write_struct_tfs(file, type, var->name);
741 return typeformat_size;
742 case RPC_FC_ENCAPSULATED_UNION:
743 case RPC_FC_NON_ENCAPSULATED_UNION:
744 typeformat_size += write_union_tfs(file, var->attrs, type, var->name);
745 return typeformat_size;
746 default:
747 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
750 else if (ptr_level == 1 && !type_has_ref(type))
752 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
753 if (!pointer_type) pointer_type = RPC_FC_RP;
755 /* special case for pointers to base types */
756 switch (type->type)
758 #define CASE_BASETYPE(fctype) \
759 case RPC_##fctype: \
760 print_file(file, indent, "0x%x, 0x08, /* %s [simple_pointer] */\n", \
761 pointer_type, \
762 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP")); \
763 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
764 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
765 typeformat_size += 4; \
766 return typeformat_size
767 CASE_BASETYPE(FC_BYTE);
768 CASE_BASETYPE(FC_CHAR);
769 CASE_BASETYPE(FC_SMALL);
770 CASE_BASETYPE(FC_USMALL);
771 CASE_BASETYPE(FC_WCHAR);
772 CASE_BASETYPE(FC_SHORT);
773 CASE_BASETYPE(FC_USHORT);
774 CASE_BASETYPE(FC_LONG);
775 CASE_BASETYPE(FC_ULONG);
776 CASE_BASETYPE(FC_FLOAT);
777 CASE_BASETYPE(FC_HYPER);
778 CASE_BASETYPE(FC_DOUBLE);
779 CASE_BASETYPE(FC_ENUM16);
780 CASE_BASETYPE(FC_ENUM32);
781 CASE_BASETYPE(FC_IGNORE);
782 CASE_BASETYPE(FC_ERROR_STATUS_T);
783 default:
784 break;
788 assert(ptr_level > 0);
790 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
791 if (!pointer_type) pointer_type = RPC_FC_RP;
793 print_file(file, indent, "0x%x, 0x00, /* %s */\n",
794 pointer_type,
795 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
796 print_file(file, indent, "NdrShort(0x2), /* 2 */\n");
798 ptr_level--;
803 void write_typeformatstring(FILE *file, type_t *iface)
805 int indent = 0;
806 var_t *var;
808 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
809 print_file(file, indent, "{\n");
810 indent++;
811 print_file(file, indent, "0,\n");
812 print_file(file, indent, "{\n");
813 indent++;
814 print_file(file, indent, "NdrFcShort(0x0),\n");
816 if (iface->funcs)
818 func_t *func = iface->funcs;
819 while (NEXT_LINK(func)) func = NEXT_LINK(func);
820 for (; func; func = PREV_LINK(func))
822 current_func = func;
823 if (func->args)
825 var = func->args;
826 while (NEXT_LINK(var)) var = NEXT_LINK(var);
827 while (var)
829 write_typeformatstring_var(file, indent, var);
830 var = PREV_LINK(var);
836 print_file(file, indent, "0x0\n");
837 indent--;
838 print_file(file, indent, "}\n");
839 indent--;
840 print_file(file, indent, "};\n");
841 print_file(file, indent, "\n");
844 static unsigned int get_required_buffer_size_type(
845 const type_t *type, int ptr_level, const expr_t *array,
846 const char *name, unsigned int *alignment)
848 *alignment = 0;
849 if (ptr_level == 0 && !array && !type_has_ref(type))
851 switch (type->type)
853 case RPC_FC_BYTE:
854 case RPC_FC_CHAR:
855 case RPC_FC_USMALL:
856 case RPC_FC_SMALL:
857 return 1;
859 case RPC_FC_WCHAR:
860 case RPC_FC_USHORT:
861 case RPC_FC_SHORT:
862 *alignment = 2;
863 return 2;
865 case RPC_FC_ULONG:
866 case RPC_FC_LONG:
867 case RPC_FC_FLOAT:
868 case RPC_FC_ERROR_STATUS_T:
869 *alignment = 4;
870 return 4;
872 case RPC_FC_HYPER:
873 case RPC_FC_DOUBLE:
874 *alignment = 8;
875 return 8;
877 case RPC_FC_STRUCT:
879 size_t size = 0;
880 const var_t *field;
881 for (field = type->fields; field; field = NEXT_LINK(field))
883 unsigned int alignment;
884 size += get_required_buffer_size_type(
885 field->type, field->ptr_level, field->array, field->name,
886 &alignment);
888 return size;
891 default:
892 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
893 return 0;
896 if (ptr_level == 0 && type_has_ref(type))
897 return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
898 return 0;
901 unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
903 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
906 void marshall_arguments(FILE *file, int indent, func_t *func,
907 unsigned int *type_offset, enum pass pass)
909 unsigned int last_size = 0;
910 var_t *var;
912 if (!func->args)
913 return;
915 var = func->args;
916 while (NEXT_LINK(var)) var = NEXT_LINK(var);
917 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
919 int in_attr = is_attr(var->attrs, ATTR_IN);
920 int out_attr = is_attr(var->attrs, ATTR_OUT);
922 if (!in_attr && !out_attr)
923 in_attr = 1;
925 switch (pass)
927 case PASS_IN:
928 if (!in_attr)
929 continue;
930 break;
931 case PASS_OUT:
932 if (!out_attr)
933 continue;
934 break;
935 case PASS_RETURN:
936 break;
939 if (is_string_type(var->attrs, var->ptr_level, var->array))
941 if (var->array && var->array->is_const)
942 print_file(file, indent,
943 "NdrNonConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
944 var->name, *type_offset);
945 else
946 print_file(file, indent,
947 "NdrConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
948 var->name, *type_offset);
949 last_size = 1;
951 else if (is_array_type(var->attrs, var->ptr_level, var->array))
953 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
954 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
955 const char *array_type;
956 int has_length = length_is && (length_is->type != EXPR_VOID);
957 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
959 if (NEXT_LINK(var->array)) /* multi-dimensional array */
960 array_type = "ComplexArray";
961 else
963 if (!has_length && !has_size)
964 array_type = "FixedArray";
965 else if (has_length && !has_size)
967 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
968 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
969 write_expr(file, length_is, 1);
970 fprintf(file, ";\n\n");
971 array_type = "VaryingArray";
973 else if (!has_length && has_size)
975 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
976 write_expr(file, size_is ? size_is : var->array, 1);
977 fprintf(file, ";\n\n");
978 array_type = "ConformantArray";
980 else
982 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
983 write_expr(file, size_is ? size_is : var->array, 1);
984 fprintf(file, ";\n");
985 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
986 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
987 write_expr(file, length_is, 1);
988 fprintf(file, ";\n\n");
989 array_type = "ConformantVaryingArray";
993 print_file(file, indent,
994 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
995 array_type, var->name, *type_offset);
996 last_size = 1;
998 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1000 unsigned int size;
1001 unsigned int alignment = 0;
1002 switch (var->type->type)
1004 case RPC_FC_BYTE:
1005 case RPC_FC_CHAR:
1006 case RPC_FC_SMALL:
1007 case RPC_FC_USMALL:
1008 size = 1;
1009 alignment = 0;
1010 break;
1012 case RPC_FC_WCHAR:
1013 case RPC_FC_USHORT:
1014 case RPC_FC_SHORT:
1015 size = 2;
1016 if (last_size != 0 && last_size < 2)
1017 alignment = (2 - last_size);
1018 break;
1020 case RPC_FC_ULONG:
1021 case RPC_FC_LONG:
1022 case RPC_FC_FLOAT:
1023 case RPC_FC_ERROR_STATUS_T:
1024 size = 4;
1025 if (last_size != 0 && last_size < 4)
1026 alignment = (4 - last_size);
1027 break;
1029 case RPC_FC_HYPER:
1030 case RPC_FC_DOUBLE:
1031 size = 8;
1032 if (last_size != 0 && last_size < 4)
1033 alignment = (4 - last_size);
1034 break;
1036 default:
1037 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1038 size = 0;
1041 if (alignment != 0)
1042 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
1044 print_file(file, indent, "*(");
1045 write_type(file, var->type, var, var->tname);
1046 fprintf(file, " *)_StubMsg.Buffer = ");
1047 write_name(file, var);
1048 fprintf(file, ";\n");
1049 fprintf(file, "_StubMsg.Buffer += sizeof(");
1050 write_type(file, var->type, var, var->tname);
1051 fprintf(file, ");\n");
1053 last_size = size;
1055 else if (var->ptr_level == 0)
1057 const char *ndrtype;
1059 switch (var->type->type)
1061 case RPC_FC_STRUCT:
1062 ndrtype = "SimpleStruct";
1063 break;
1064 case RPC_FC_CSTRUCT:
1065 case RPC_FC_CPSTRUCT:
1066 ndrtype = "ConformantStruct";
1067 break;
1068 case RPC_FC_CVSTRUCT:
1069 ndrtype = "ConformantVaryingStruct";
1070 break;
1071 case RPC_FC_BOGUS_STRUCT:
1072 ndrtype = "ComplexStruct";
1073 break;
1074 default:
1075 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1076 var->name, var->type->type, var->ptr_level);
1077 ndrtype = NULL;
1080 print_file(file, indent,
1081 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1082 ndrtype, var->name, *type_offset);
1083 last_size = 1;
1085 else
1087 print_file(file, indent,
1088 "NdrPointerMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1089 var->name, *type_offset);
1090 last_size = 1;
1092 fprintf(file, "\n");
1096 void unmarshall_arguments(FILE *file, int indent, func_t *func,
1097 unsigned int *type_offset, enum pass pass)
1099 unsigned int last_size = 0;
1100 var_t *var;
1102 if (!func->args)
1103 return;
1105 var = func->args;
1106 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1107 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
1109 int in_attr = is_attr(var->attrs, ATTR_IN);
1110 int out_attr = is_attr(var->attrs, ATTR_OUT);
1112 if (!in_attr && !out_attr)
1113 in_attr = 1;
1115 switch (pass)
1117 case PASS_IN:
1118 if (!in_attr)
1119 continue;
1120 break;
1121 case PASS_OUT:
1122 if (!out_attr)
1123 continue;
1124 break;
1125 case PASS_RETURN:
1126 break;
1129 if (is_string_type(var->attrs, var->ptr_level, var->array))
1131 if (var->array && var->array->is_const)
1132 print_file(file, indent,
1133 "NdrNonConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1134 var->name, *type_offset);
1135 else
1136 print_file(file, indent,
1137 "NdrConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1138 var->name, *type_offset);
1139 last_size = 1;
1141 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1143 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1144 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1145 const char *array_type;
1146 int has_length = length_is && (length_is->type != EXPR_VOID);
1147 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
1149 if (NEXT_LINK(var->array)) /* multi-dimensional array */
1150 array_type = "ComplexArray";
1151 else
1153 if (!has_length && !has_size)
1154 array_type = "FixedArray";
1155 else if (has_length && !has_size)
1156 array_type = "VaryingArray";
1157 else if (!has_length && has_size)
1158 array_type = "ConformantArray";
1159 else
1160 array_type = "ConformantVaryingArray";
1163 print_file(file, indent,
1164 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1165 array_type, var->name, *type_offset);
1166 last_size = 1;
1168 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1170 unsigned int size;
1171 unsigned int alignment = 0;
1173 switch (var->type->type)
1175 case RPC_FC_BYTE:
1176 case RPC_FC_CHAR:
1177 case RPC_FC_SMALL:
1178 case RPC_FC_USMALL:
1179 size = 1;
1180 alignment = 0;
1181 break;
1183 case RPC_FC_WCHAR:
1184 case RPC_FC_USHORT:
1185 case RPC_FC_SHORT:
1186 size = 2;
1187 if (last_size != 0 && last_size < 2)
1188 alignment = (2 - last_size);
1189 break;
1191 case RPC_FC_ULONG:
1192 case RPC_FC_LONG:
1193 case RPC_FC_FLOAT:
1194 case RPC_FC_ERROR_STATUS_T:
1195 size = 4;
1196 if (last_size != 0 && last_size < 4)
1197 alignment = (4 - last_size);
1198 break;
1200 case RPC_FC_HYPER:
1201 case RPC_FC_DOUBLE:
1202 size = 8;
1203 if (last_size != 0 && last_size < 4)
1204 alignment = (4 - last_size);
1205 break;
1207 default:
1208 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1209 size = 0;
1212 if (alignment != 0)
1213 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
1215 print_file(file, indent, "");
1216 write_name(file, var);
1217 fprintf(file, " = *(");
1218 write_type(file, var->type, var, var->tname);
1219 fprintf(file, " *)_StubMsg.Buffer;\n");
1220 fprintf(file, "_StubMsg.Buffer += sizeof(");
1221 write_type(file, var->type, var, var->tname);
1222 fprintf(file, ");\n");
1224 last_size = size;
1226 else if (var->ptr_level == 0)
1228 const char *ndrtype;
1230 switch (var->type->type)
1232 case RPC_FC_STRUCT:
1233 ndrtype = "SimpleStruct";
1234 break;
1235 case RPC_FC_CSTRUCT:
1236 case RPC_FC_CPSTRUCT:
1237 ndrtype = "ConformantStruct";
1238 break;
1239 case RPC_FC_CVSTRUCT:
1240 ndrtype = "ConformantVaryingStruct";
1241 break;
1242 case RPC_FC_BOGUS_STRUCT:
1243 ndrtype = "ComplexStruct";
1244 break;
1245 default:
1246 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1247 var->name, var->type->type, var->ptr_level);
1248 ndrtype = NULL;
1251 print_file(file, indent,
1252 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1253 ndrtype, var->name, *type_offset);
1254 last_size = 1;
1256 else
1258 print_file(file, indent,
1259 "NdrPointerUnmarshall(&_StubMsg, (unsigned char **)&%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1260 var->name, *type_offset);
1261 last_size = 1;
1263 fprintf(file, "\n");
1268 size_t get_size_procformatstring_var(const var_t *var)
1270 unsigned int type_offset = 2;
1271 return write_procformatstring_var(NULL, 0, var, FALSE, &type_offset);
1275 size_t get_size_typeformatstring_var(const var_t *var)
1277 return write_typeformatstring_var(NULL, 0, var);