widl: Improve the current type offset passing.
[wine/multimedia.git] / tools / widl / typegen.c
blob8649252f9afb5417b4e9eb77c337a9a790d1be44
1 /*
2 * Format String Generator for IDL Compiler
4 * Copyright 2005 Eric Kohl
5 * Copyright 2005-2006 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"
41 #include "wine/list.h"
43 #include "widl.h"
44 #include "typegen.h"
46 static const func_t *current_func;
47 static const type_t *current_structure;
49 /* name of the structure variable for structure callbacks */
50 #define STRUCT_EXPR_EVAL_VAR "pS"
52 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
54 struct expr_eval_routine
56 struct list entry;
57 const type_t *structure;
58 size_t structure_size;
59 const expr_t *expr;
62 static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array);
63 static size_t fields_memsize(const var_t *v);
65 static int compare_expr(const expr_t *a, const expr_t *b)
67 int ret;
69 if (a->type != b->type)
70 return a->type - b->type;
72 switch (a->type)
74 case EXPR_NUM:
75 case EXPR_HEXNUM:
76 return a->u.lval - b->u.lval;
77 case EXPR_IDENTIFIER:
78 return strcmp(a->u.sval, b->u.sval);
79 case EXPR_COND:
80 ret = compare_expr(a->ref, b->ref);
81 if (ret != 0)
82 return ret;
83 ret = compare_expr(a->u.ext, b->u.ext);
84 if (ret != 0)
85 return ret;
86 return compare_expr(a->ext2, b->ext2);
87 case EXPR_OR:
88 case EXPR_AND:
89 case EXPR_ADD:
90 case EXPR_SUB:
91 case EXPR_MUL:
92 case EXPR_DIV:
93 case EXPR_SHL:
94 case EXPR_SHR:
95 ret = compare_expr(a->ref, b->ref);
96 if (ret != 0)
97 return ret;
98 return compare_expr(a->u.ext, b->u.ext);
99 case EXPR_NOT:
100 case EXPR_NEG:
101 case EXPR_PPTR:
102 case EXPR_CAST:
103 case EXPR_SIZEOF:
104 return compare_expr(a->ref, b->ref);
105 case EXPR_VOID:
106 return 0;
108 return -1;
111 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
112 do { \
113 if (file) \
114 fprintf(file, "/* %2u */\n", typestring_offset); \
115 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
117 while (0)
119 static int print_file(FILE *file, int indent, const char *format, ...)
121 va_list va;
122 int i, r;
124 if (!file) return 0;
126 va_start(va, format);
127 for (i = 0; i < indent; i++)
128 fprintf(file, " ");
129 r = vfprintf(file, format, va);
130 va_end(va);
131 return r;
134 static inline int type_has_ref(const type_t *type)
136 return (type->type == 0 && type->ref);
139 static inline int is_base_type(unsigned char type)
141 switch (type)
143 case RPC_FC_BYTE:
144 case RPC_FC_CHAR:
145 case RPC_FC_USMALL:
146 case RPC_FC_SMALL:
147 case RPC_FC_WCHAR:
148 case RPC_FC_USHORT:
149 case RPC_FC_SHORT:
150 case RPC_FC_ULONG:
151 case RPC_FC_LONG:
152 case RPC_FC_HYPER:
153 case RPC_FC_IGNORE:
154 case RPC_FC_FLOAT:
155 case RPC_FC_DOUBLE:
156 case RPC_FC_ENUM16:
157 case RPC_FC_ENUM32:
158 case RPC_FC_ERROR_STATUS_T:
159 return TRUE;
161 default:
162 return FALSE;
166 static size_t write_procformatstring_var(FILE *file, int indent,
167 const var_t *var, int is_return, unsigned int *type_offset)
169 size_t size;
170 int ptr_level = var->ptr_level;
171 const type_t *type = var->type;
173 int is_in = is_attr(var->attrs, ATTR_IN);
174 int is_out = is_attr(var->attrs, ATTR_OUT);
176 if (!is_in && !is_out) is_in = TRUE;
178 if (ptr_level == 0 && type_has_ref(type))
179 type = type->ref;
181 if (ptr_level == 0 && !var->array && is_base_type(type->type))
183 if (is_return)
184 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
185 else
186 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
188 switch(type->type)
190 #define CASE_BASETYPE(fctype) \
191 case RPC_##fctype: \
192 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
193 size = 2; /* includes param type prefix */ \
194 break
196 CASE_BASETYPE(FC_BYTE);
197 CASE_BASETYPE(FC_CHAR);
198 CASE_BASETYPE(FC_WCHAR);
199 CASE_BASETYPE(FC_USHORT);
200 CASE_BASETYPE(FC_SHORT);
201 CASE_BASETYPE(FC_ULONG);
202 CASE_BASETYPE(FC_LONG);
203 CASE_BASETYPE(FC_HYPER);
204 CASE_BASETYPE(FC_IGNORE);
205 CASE_BASETYPE(FC_USMALL);
206 CASE_BASETYPE(FC_SMALL);
207 CASE_BASETYPE(FC_FLOAT);
208 CASE_BASETYPE(FC_DOUBLE);
209 CASE_BASETYPE(FC_ERROR_STATUS_T);
210 #undef CASE_BASETYPE
211 default:
212 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
213 size = 0;
216 else
218 if (is_return)
219 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
220 else if (is_in && is_out)
221 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
222 else if (is_out)
223 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
224 else
225 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
227 print_file(file, indent, "0x01,\n");
228 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
229 size = 4; /* includes param type prefix */
231 *type_offset += get_size_typeformatstring_var(var);
232 return size;
235 void write_procformatstring(FILE *file, type_t *iface)
237 int indent = 0;
238 var_t *var;
239 unsigned int type_offset = 2;
241 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
242 print_file(file, indent, "{\n");
243 indent++;
244 print_file(file, indent, "0,\n");
245 print_file(file, indent, "{\n");
246 indent++;
248 if (iface->funcs)
250 func_t *func = iface->funcs;
251 while (NEXT_LINK(func)) func = NEXT_LINK(func);
252 for (; func; func = PREV_LINK(func))
254 /* emit argument data */
255 if (func->args)
257 var = func->args;
258 while (NEXT_LINK(var)) var = NEXT_LINK(var);
259 while (var)
261 write_procformatstring_var(file, indent, var, FALSE,
262 &type_offset);
264 var = PREV_LINK(var);
268 /* emit return value data */
269 var = func->def;
270 if (is_void(var->type, NULL))
272 print_file(file, indent, "0x5b, /* FC_END */\n");
273 print_file(file, indent, "0x5c, /* FC_PAD */\n");
275 else
276 write_procformatstring_var(file, indent, var, TRUE,
277 &type_offset);
281 print_file(file, indent, "0x0\n");
282 indent--;
283 print_file(file, indent, "}\n");
284 indent--;
285 print_file(file, indent, "};\n");
286 print_file(file, indent, "\n");
289 /* write conformance / variance descriptor */
290 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr)
292 unsigned char operator_type = 0;
293 const char *operator_string = "no operators";
294 const expr_t *subexpr = expr;
295 unsigned char correlation_type;
297 if (!file) return 4; /* optimisation for sizing pass */
299 if (expr->is_const)
301 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
302 error("write_conf_or_var_desc: constant value %ld is greater than "
303 "the maximum constant size of %d\n", expr->cval,
304 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
306 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
307 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
308 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
309 print_file(file, 2, "NdrShort(0x%x),\n", expr->cval & USHRT_MAX);
311 return 4;
314 switch (subexpr->type)
316 case EXPR_PPTR:
317 subexpr = subexpr->ref;
318 operator_type = RPC_FC_DEREFERENCE;
319 operator_string = "FC_DEREFERENCE";
320 break;
321 case EXPR_DIV:
322 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
324 subexpr = subexpr->ref;
325 operator_type = RPC_FC_DIV_2;
326 operator_string = "FC_DIV_2";
328 break;
329 case EXPR_MUL:
330 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
332 subexpr = subexpr->ref;
333 operator_type = RPC_FC_MULT_2;
334 operator_string = "FC_MULT_2";
336 break;
337 case EXPR_SUB:
338 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
340 subexpr = subexpr->ref;
341 operator_type = RPC_FC_SUB_1;
342 operator_string = "FC_SUB_1";
344 break;
345 case EXPR_ADD:
346 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
348 subexpr = subexpr->ref;
349 operator_type = RPC_FC_ADD_1;
350 operator_string = "FC_ADD_1";
352 break;
353 default:
354 break;
357 if (subexpr->type == EXPR_IDENTIFIER)
359 const type_t *correlation_variable = NULL;
360 unsigned char param_type = 0;
361 const char *param_type_string = NULL;
362 size_t offset;
364 if (structure)
366 const var_t *var;
368 for (offset = 0, var = structure->fields; var; var = NEXT_LINK(var))
370 offset -= type_memsize(var->type, var->ptr_level, var->array);
371 if (!strcmp(var->name, subexpr->u.sval))
373 correlation_variable = var->type;
374 break;
377 if (!correlation_variable)
378 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
379 subexpr->u.sval);
381 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
383 else
385 const var_t *var = func->args;
387 while (NEXT_LINK(var)) var = NEXT_LINK(var);
388 /* FIXME: not all stack variables are sizeof(void *) */
389 for (offset = 0; var; offset += sizeof(void *), var = PREV_LINK(var))
391 if (!strcmp(var->name, subexpr->u.sval))
393 correlation_variable = var->type;
394 break;
397 if (!correlation_variable)
398 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
399 subexpr->u.sval);
401 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
404 while (type_has_ref(correlation_variable))
405 correlation_variable = correlation_variable->ref;
407 switch (correlation_variable->type)
409 case RPC_FC_CHAR:
410 case RPC_FC_SMALL:
411 param_type = RPC_FC_SMALL;
412 param_type_string = "FC_SMALL";
413 break;
414 case RPC_FC_BYTE:
415 case RPC_FC_USMALL:
416 param_type = RPC_FC_USMALL;
417 param_type_string = "FC_USMALL";
418 break;
419 case RPC_FC_WCHAR:
420 case RPC_FC_SHORT:
421 param_type = RPC_FC_SHORT;
422 param_type_string = "FC_SHORT";
423 break;
424 case RPC_FC_USHORT:
425 param_type = RPC_FC_USHORT;
426 param_type_string = "FC_USHORT";
427 break;
428 case RPC_FC_LONG:
429 param_type = RPC_FC_LONG;
430 param_type_string = "FC_LONG";
431 break;
432 case RPC_FC_ULONG:
433 param_type = RPC_FC_ULONG;
434 param_type_string = "FC_ULONG";
435 break;
436 default:
437 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
438 correlation_variable->type);
441 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
442 correlation_type | param_type,
443 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
444 param_type_string);
445 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
446 print_file(file, 2, "NdrShort(0x%x), /* %soffset = %d */\n",
447 offset,
448 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
449 offset);
451 else
453 unsigned int callback_offset = 0;
455 if (structure)
457 struct expr_eval_routine *eval;
458 int found = 0;
460 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
462 if (!strcmp(eval->structure->name, structure->name) &&
463 !compare_expr(eval->expr, expr))
465 found = 1;
466 break;
468 callback_offset++;
471 if (!found)
473 eval = xmalloc(sizeof(*eval));
474 eval->structure = structure;
475 eval->structure_size = fields_memsize(structure->fields);
476 eval->expr = expr;
477 list_add_tail(&expr_eval_routines, &eval->entry);
480 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
482 else
484 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
485 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
488 if (callback_offset > USHRT_MAX)
489 error("Maximum number of callback routines reached\n");
491 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
492 correlation_type,
493 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
494 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
495 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", callback_offset, callback_offset);
497 return 4;
500 static size_t fields_memsize(const var_t *v)
502 size_t size = 0;
503 const var_t *first = v;
504 if (!v) return 0;
505 while (NEXT_LINK(v)) v = NEXT_LINK(v);
506 while (v) {
507 size += type_memsize(v->type, v->ptr_level, v->array);
508 if (v == first) break;
509 v = PREV_LINK(v);
511 return size;
514 static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array)
516 size_t size = 0;
518 if (ptr_level)
519 return sizeof(void *);
521 switch (t->type)
523 case RPC_FC_BYTE:
524 case RPC_FC_CHAR:
525 case RPC_FC_USMALL:
526 case RPC_FC_SMALL:
527 size = 1;
528 break;
529 case RPC_FC_WCHAR:
530 case RPC_FC_USHORT:
531 case RPC_FC_SHORT:
532 case RPC_FC_ENUM16:
533 size = 2;
534 break;
535 case RPC_FC_ULONG:
536 case RPC_FC_LONG:
537 case RPC_FC_ERROR_STATUS_T:
538 case RPC_FC_ENUM32:
539 case RPC_FC_FLOAT:
540 size = 4;
541 break;
542 case RPC_FC_HYPER:
543 case RPC_FC_DOUBLE:
544 size = 8;
545 break;
546 case RPC_FC_STRUCT:
547 case RPC_FC_CVSTRUCT:
548 case RPC_FC_CPSTRUCT:
549 case RPC_FC_CSTRUCT:
550 case RPC_FC_PSTRUCT:
551 case RPC_FC_BOGUS_STRUCT:
552 case RPC_FC_ENCAPSULATED_UNION:
553 case RPC_FC_NON_ENCAPSULATED_UNION:
554 size = fields_memsize(t->fields);
555 break;
556 default:
557 error("type_memsize: Unknown type %d", t->type);
558 size = 0;
561 if (array)
563 if (array->is_const)
564 size *= array->cval;
565 else
566 size = 0;
569 return size;
572 static size_t write_string_tfs(FILE *file, const attr_t *attrs,
573 const type_t *type, const expr_t *array,
574 const char *name, size_t *typestring_offset)
576 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
577 int has_size = size_is && (size_is->type != EXPR_VOID);
578 size_t start_offset = *typestring_offset;
580 if ((type->type != RPC_FC_CHAR) && (type->type != RPC_FC_WCHAR))
582 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", type->type, name);
583 return start_offset;
586 if (array && array->is_const)
588 if (array->cval > USHRT_MAX)
589 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
590 name, USHRT_MAX, array->cval - USHRT_MAX);
592 if (type->type == RPC_FC_CHAR)
593 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
594 else
595 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
596 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
597 *typestring_offset += 2;
599 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", array->cval, array->cval);
600 *typestring_offset += 2;
602 return start_offset;
604 else if (has_size)
606 if (type->type == RPC_FC_CHAR)
607 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
608 else
609 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
610 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
611 *typestring_offset += 2;
613 *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, size_is);
615 return start_offset;
617 else
619 if (type->type == RPC_FC_CHAR)
620 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
621 else
622 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
623 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
624 *typestring_offset += 2;
626 return start_offset;
630 static size_t write_array_tfs(FILE *file, const attr_t *attrs,
631 const type_t *type, const expr_t *array,
632 const char *name, size_t *typestring_offset)
634 const expr_t *length_is = get_attrp(attrs, ATTR_LENGTHIS);
635 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
636 int has_length = length_is && (length_is->type != EXPR_VOID);
637 int has_size = size_is && (size_is->type != EXPR_VOID) && !array->is_const;
638 size_t start_offset = *typestring_offset;
640 /* FIXME: need to analyse type for pointers */
642 if (NEXT_LINK(array)) /* multi-dimensional array */
644 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name);
645 return 0;
647 else
649 if (!has_length && !has_size)
651 /* fixed array */
652 size_t size = type_memsize(type, 0, array);
653 if (size < USHRT_MAX)
655 WRITE_FCTYPE(file, FC_SMFARRAY, *typestring_offset);
656 /* alignment */
657 print_file(file, 2, "0x%x, /* 0 */\n", 0);
658 /* size */
659 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", size, size);
660 *typestring_offset += 4;
662 else
664 WRITE_FCTYPE(file, FC_LGFARRAY, *typestring_offset);
665 /* alignment */
666 print_file(file, 2, "0x%x, /* 0 */\n", 0);
667 /* size */
668 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", size, size);
669 *typestring_offset += 6;
672 /* FIXME: write out pointer descriptor if necessary */
674 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
675 print_file(file, 2, "FC_END,\n");
676 *typestring_offset += 2;
678 return start_offset;
680 else if (has_length && !has_size)
682 /* varying array */
683 size_t element_size = type_memsize(type, 0, NULL);
684 size_t elements = array->cval;
685 size_t total_size = element_size * elements;
687 if (total_size < USHRT_MAX)
689 WRITE_FCTYPE(file, FC_SMVARRAY, *typestring_offset);
690 /* alignment */
691 print_file(file, 2, "0x%x, /* 0 */\n", 0);
692 /* total size */
693 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", total_size, total_size);
694 /* number of elements */
695 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", elements, elements);
696 *typestring_offset += 6;
698 else
700 WRITE_FCTYPE(file, FC_LGVARRAY, *typestring_offset);
701 /* alignment */
702 print_file(file, 2, "0x%x, /* 0 */\n", 0);
703 /* total size */
704 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", total_size, total_size);
705 /* number of elements */
706 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", elements, elements);
707 *typestring_offset += 10;
709 /* element size */
710 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
711 *typestring_offset += 2;
713 *typestring_offset += write_conf_or_var_desc(file, current_func,
714 current_structure,
715 length_is);
717 /* FIXME: write out pointer descriptor if necessary */
719 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
720 print_file(file, 2, "FC_END,\n");
721 *typestring_offset += 2;
723 return start_offset;
725 else if (!has_length && has_size)
727 /* conformant array */
728 size_t element_size = type_memsize(type, 0, NULL);
730 WRITE_FCTYPE(file, FC_CARRAY, *typestring_offset);
731 /* alignment */
732 print_file(file, 2, "0x%x, /* 0 */\n", 0);
733 /* element size */
734 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
735 *typestring_offset += 4;
737 *typestring_offset += write_conf_or_var_desc(file, current_func,
738 current_structure, size_is);
740 /* FIXME: write out pointer descriptor if necessary */
742 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
743 print_file(file, 2, "FC_END,\n");
744 *typestring_offset += 2;
746 return start_offset;
748 else
750 /* conformant varying array */
751 size_t element_size = type_memsize(type, 0, NULL);
753 WRITE_FCTYPE(file, FC_CVARRAY, *typestring_offset);
754 /* alignment */
755 print_file(file, 2, "0x%x, /* 0 */\n", 0);
756 /* element size */
757 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
758 *typestring_offset += 4;
760 *typestring_offset += write_conf_or_var_desc(file, current_func,
761 current_structure, size_is);
762 *typestring_offset += write_conf_or_var_desc(file, current_func,
763 current_structure,
764 length_is);
766 /* FIXME: write out pointer descriptor if necessary */
768 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
769 print_file(file, 2, "FC_END,\n");
770 *typestring_offset += 2;
772 return start_offset;
777 static const var_t *find_array_or_string_in_struct(const type_t *type)
779 /* last field is the first in the fields linked list */
780 const var_t *last_field = type->fields;
781 if (is_array_type(last_field->attrs, last_field->ptr_level, last_field->array))
782 return last_field;
784 assert((last_field->type->type == RPC_FC_CSTRUCT) ||
785 (last_field->type->type == RPC_FC_CPSTRUCT) ||
786 (last_field->type->type == RPC_FC_CVSTRUCT));
788 return find_array_or_string_in_struct(last_field->type);
791 static size_t write_struct_tfs(FILE *file, const type_t *type,
792 const char *name, size_t *typestring_offset)
794 size_t total_size;
795 const var_t *array;
796 size_t start_offset;
798 switch (type->type)
800 case RPC_FC_STRUCT:
801 total_size = type_memsize(type, 0, NULL);
803 if (total_size > USHRT_MAX)
804 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
805 name, USHRT_MAX, total_size - USHRT_MAX);
807 start_offset = *typestring_offset;
808 WRITE_FCTYPE(file, FC_STRUCT, *typestring_offset);
809 /* alignment */
810 print_file(file, 2, "0x0,\n");
811 /* total size */
812 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
813 *typestring_offset += 4;
815 /* member layout */
816 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
817 print_file(file, 2, "FC_END,\n");
819 *typestring_offset += 2;
820 return start_offset;
821 case RPC_FC_CSTRUCT:
822 total_size = type_memsize(type, 0, NULL);
824 if (total_size > USHRT_MAX)
825 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
826 name, USHRT_MAX, total_size - USHRT_MAX);
828 start_offset = *typestring_offset;
829 WRITE_FCTYPE(file, FC_CSTRUCT, *typestring_offset);
830 /* alignment */
831 print_file(file, 2, "0x0,\n");
832 /* total size */
833 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
834 *typestring_offset += 4;
835 /* FIXME: a fixed offset won't work when pointer layout is present */
836 print_file(file, 2, "NdrShort(0x3), /* 3 */\n");
837 *typestring_offset += 2;
838 print_file(file, 2, "FC_END,\n");
839 *typestring_offset += 1;
841 array = find_array_or_string_in_struct(type);
842 current_structure = type;
843 write_array_tfs(file, array->attrs, array->type,
844 array->array, array->name,
845 typestring_offset);
846 current_structure = NULL;
848 return start_offset;
849 case RPC_FC_CVSTRUCT:
850 total_size = type_memsize(type, 0, NULL);
852 if (total_size > USHRT_MAX)
853 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
854 name, USHRT_MAX, total_size - USHRT_MAX);
856 start_offset = *typestring_offset;
857 WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset);
858 /* alignment */
859 print_file(file, 2, "0x0,\n");
860 /* total size */
861 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
862 *typestring_offset += 4;
863 /* FIXME: a fixed offset won't work when pointer layout is present */
864 print_file(file, 2, "NdrShort(0x3), /* 3 */\n");
865 *typestring_offset += 2;
866 print_file(file, 2, "FC_END,\n");
867 *typestring_offset += 1;
869 array = find_array_or_string_in_struct(type);
870 current_structure = type;
871 if (is_attr(array->attrs, ATTR_STRING))
872 write_string_tfs(file, array->attrs, array->type,
873 array->array, array->name,
874 typestring_offset);
875 else
876 write_array_tfs(file, array->attrs, array->type,
877 array->array, array->name,
878 typestring_offset);
879 current_structure = NULL;
881 return start_offset;
882 default:
883 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
884 return *typestring_offset;
888 static size_t write_union_tfs(FILE *file, const attr_t *attrs,
889 const type_t *type, const char *name,
890 size_t *typeformat_offset)
892 error("write_union_tfs: Unimplemented\n");
893 return *typeformat_offset;
896 static size_t write_typeformatstring_var(FILE *file, int indent,
897 const var_t *var, size_t *typeformat_offset)
899 const type_t *type = var->type;
900 int ptr_level = var->ptr_level;
902 while (TRUE)
904 int pointer_type;
906 if (is_string_type(var->attrs, ptr_level, var->array))
907 return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
909 if (is_array_type(var->attrs, ptr_level, var->array))
910 return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
912 if (ptr_level == 0)
914 /* follow reference if the type has one */
915 if (type_has_ref(type))
917 type = type->ref;
918 /* FIXME: get new ptr_level from type */
919 continue;
922 /* basic types don't need a type format string */
923 if (is_base_type(type->type))
924 return 0;
926 switch (type->type)
928 case RPC_FC_STRUCT:
929 case RPC_FC_PSTRUCT:
930 case RPC_FC_CSTRUCT:
931 case RPC_FC_CPSTRUCT:
932 case RPC_FC_CVSTRUCT:
933 case RPC_FC_BOGUS_STRUCT:
934 return write_struct_tfs(file, type, var->name, typeformat_offset);
935 case RPC_FC_ENCAPSULATED_UNION:
936 case RPC_FC_NON_ENCAPSULATED_UNION:
937 return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset);
938 case RPC_FC_IGNORE:
939 case RPC_FC_BIND_PRIMITIVE:
940 /* nothing to do */
941 return 0;
942 default:
943 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
946 else if (ptr_level == 1 && !type_has_ref(type))
948 size_t start_offset = *typeformat_offset;
949 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
950 if (!pointer_type) pointer_type = RPC_FC_RP;
952 /* special case for pointers to base types */
953 switch (type->type)
955 #define CASE_BASETYPE(fctype) \
956 case RPC_##fctype: \
957 print_file(file, indent, "0x%x, 0x08, /* %s [simple_pointer] */\n", \
958 pointer_type, \
959 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP")); \
960 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
961 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
962 *typeformat_offset += 4; \
963 return start_offset
964 CASE_BASETYPE(FC_BYTE);
965 CASE_BASETYPE(FC_CHAR);
966 CASE_BASETYPE(FC_SMALL);
967 CASE_BASETYPE(FC_USMALL);
968 CASE_BASETYPE(FC_WCHAR);
969 CASE_BASETYPE(FC_SHORT);
970 CASE_BASETYPE(FC_USHORT);
971 CASE_BASETYPE(FC_LONG);
972 CASE_BASETYPE(FC_ULONG);
973 CASE_BASETYPE(FC_FLOAT);
974 CASE_BASETYPE(FC_HYPER);
975 CASE_BASETYPE(FC_DOUBLE);
976 CASE_BASETYPE(FC_ENUM16);
977 CASE_BASETYPE(FC_ENUM32);
978 CASE_BASETYPE(FC_IGNORE);
979 CASE_BASETYPE(FC_ERROR_STATUS_T);
980 default:
981 break;
985 assert(ptr_level > 0);
987 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
988 if (!pointer_type) pointer_type = RPC_FC_RP;
990 print_file(file, indent, "0x%x, 0x00, /* %s */\n",
991 pointer_type,
992 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
993 print_file(file, indent, "NdrShort(0x2), /* 2 */\n");
994 *typeformat_offset += 4;
996 ptr_level--;
1001 void write_typeformatstring(FILE *file, type_t *iface)
1003 int indent = 0;
1004 var_t *var;
1005 size_t typeformat_offset;
1007 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1008 print_file(file, indent, "{\n");
1009 indent++;
1010 print_file(file, indent, "0,\n");
1011 print_file(file, indent, "{\n");
1012 indent++;
1013 print_file(file, indent, "NdrFcShort(0x0),\n");
1014 typeformat_offset = 2;
1016 if (iface->funcs)
1018 func_t *func = iface->funcs;
1019 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1020 for (; func; func = PREV_LINK(func))
1022 current_func = func;
1023 if (func->args)
1025 var = func->args;
1026 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1027 while (var)
1029 write_typeformatstring_var(file, indent, var,
1030 &typeformat_offset);
1031 var = PREV_LINK(var);
1037 print_file(file, indent, "0x0\n");
1038 indent--;
1039 print_file(file, indent, "}\n");
1040 indent--;
1041 print_file(file, indent, "};\n");
1042 print_file(file, indent, "\n");
1045 static unsigned int get_required_buffer_size_type(
1046 const type_t *type, int ptr_level, const expr_t *array,
1047 const char *name, unsigned int *alignment)
1049 *alignment = 0;
1050 if (ptr_level == 0 && !array && !type_has_ref(type))
1052 switch (type->type)
1054 case RPC_FC_BYTE:
1055 case RPC_FC_CHAR:
1056 case RPC_FC_USMALL:
1057 case RPC_FC_SMALL:
1058 return 1;
1060 case RPC_FC_WCHAR:
1061 case RPC_FC_USHORT:
1062 case RPC_FC_SHORT:
1063 *alignment = 2;
1064 return 2;
1066 case RPC_FC_ULONG:
1067 case RPC_FC_LONG:
1068 case RPC_FC_FLOAT:
1069 case RPC_FC_ERROR_STATUS_T:
1070 *alignment = 4;
1071 return 4;
1073 case RPC_FC_HYPER:
1074 case RPC_FC_DOUBLE:
1075 *alignment = 8;
1076 return 8;
1078 case RPC_FC_IGNORE:
1079 case RPC_FC_BIND_PRIMITIVE:
1080 return 0;
1082 case RPC_FC_STRUCT:
1084 size_t size = 0;
1085 const var_t *field;
1086 for (field = type->fields; field; field = NEXT_LINK(field))
1088 unsigned int alignment;
1089 size += get_required_buffer_size_type(
1090 field->type, field->ptr_level, field->array, field->name,
1091 &alignment);
1093 return size;
1096 default:
1097 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1098 return 0;
1101 if (ptr_level == 0 && type_has_ref(type))
1102 return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
1103 return 0;
1106 unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
1108 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
1111 void marshall_arguments(FILE *file, int indent, func_t *func,
1112 unsigned int *type_offset, enum pass pass)
1114 unsigned int last_size = 0;
1115 var_t *var;
1117 if (!func->args)
1118 return;
1120 var = func->args;
1121 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1122 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
1124 int in_attr = is_attr(var->attrs, ATTR_IN);
1125 int out_attr = is_attr(var->attrs, ATTR_OUT);
1127 if (!in_attr && !out_attr)
1128 in_attr = 1;
1130 switch (pass)
1132 case PASS_IN:
1133 if (!in_attr)
1134 continue;
1135 break;
1136 case PASS_OUT:
1137 if (!out_attr)
1138 continue;
1139 break;
1140 case PASS_RETURN:
1141 break;
1144 if (is_string_type(var->attrs, var->ptr_level, var->array))
1146 if (var->array && var->array->is_const)
1147 print_file(file, indent,
1148 "NdrNonConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1149 var->name, *type_offset);
1150 else
1151 print_file(file, indent,
1152 "NdrConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1153 var->name, *type_offset);
1154 last_size = 1;
1156 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1158 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1159 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1160 const char *array_type;
1161 int has_length = length_is && (length_is->type != EXPR_VOID);
1162 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
1164 if (NEXT_LINK(var->array)) /* multi-dimensional array */
1165 array_type = "ComplexArray";
1166 else
1168 if (!has_length && !has_size)
1169 array_type = "FixedArray";
1170 else if (has_length && !has_size)
1172 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1173 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1174 write_expr(file, length_is, 1);
1175 fprintf(file, ";\n\n");
1176 array_type = "VaryingArray";
1178 else if (!has_length && has_size)
1180 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1181 write_expr(file, size_is ? size_is : var->array, 1);
1182 fprintf(file, ";\n\n");
1183 array_type = "ConformantArray";
1185 else
1187 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1188 write_expr(file, size_is ? size_is : var->array, 1);
1189 fprintf(file, ";\n");
1190 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1191 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1192 write_expr(file, length_is, 1);
1193 fprintf(file, ";\n\n");
1194 array_type = "ConformantVaryingArray";
1198 print_file(file, indent,
1199 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1200 array_type, var->name, *type_offset);
1201 last_size = 1;
1203 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1205 unsigned int size;
1206 unsigned int alignment = 0;
1207 switch (var->type->type)
1209 case RPC_FC_BYTE:
1210 case RPC_FC_CHAR:
1211 case RPC_FC_SMALL:
1212 case RPC_FC_USMALL:
1213 size = 1;
1214 alignment = 0;
1215 break;
1217 case RPC_FC_WCHAR:
1218 case RPC_FC_USHORT:
1219 case RPC_FC_SHORT:
1220 size = 2;
1221 if (last_size != 0 && last_size < 2)
1222 alignment = (2 - last_size);
1223 break;
1225 case RPC_FC_ULONG:
1226 case RPC_FC_LONG:
1227 case RPC_FC_FLOAT:
1228 case RPC_FC_ERROR_STATUS_T:
1229 size = 4;
1230 if (last_size != 0 && last_size < 4)
1231 alignment = (4 - last_size);
1232 break;
1234 case RPC_FC_HYPER:
1235 case RPC_FC_DOUBLE:
1236 size = 8;
1237 if (last_size != 0 && last_size < 4)
1238 alignment = (4 - last_size);
1239 break;
1241 default:
1242 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1243 size = 0;
1246 if (alignment != 0)
1247 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
1249 print_file(file, indent, "*(");
1250 write_type(file, var->type, var, var->tname);
1251 fprintf(file, " *)_StubMsg.Buffer = ");
1252 write_name(file, var);
1253 fprintf(file, ";\n");
1254 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1255 write_type(file, var->type, var, var->tname);
1256 fprintf(file, ");\n");
1258 last_size = size;
1260 else if (var->ptr_level == 0)
1262 const char *ndrtype;
1264 switch (var->type->type)
1266 case RPC_FC_STRUCT:
1267 ndrtype = "SimpleStruct";
1268 break;
1269 case RPC_FC_CSTRUCT:
1270 case RPC_FC_CPSTRUCT:
1271 ndrtype = "ConformantStruct";
1272 break;
1273 case RPC_FC_CVSTRUCT:
1274 ndrtype = "ConformantVaryingStruct";
1275 break;
1276 case RPC_FC_BOGUS_STRUCT:
1277 ndrtype = "ComplexStruct";
1278 break;
1279 case RPC_FC_IGNORE:
1280 case RPC_FC_BIND_PRIMITIVE:
1281 /* no marshalling needed */
1282 continue;
1283 default:
1284 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1285 var->name, var->type->type, var->ptr_level);
1286 ndrtype = NULL;
1289 print_file(file, indent,
1290 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1291 ndrtype, var->name, *type_offset);
1292 last_size = 1;
1294 else
1296 print_file(file, indent,
1297 "NdrPointerMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1298 var->name, *type_offset);
1299 last_size = 1;
1301 fprintf(file, "\n");
1305 void unmarshall_arguments(FILE *file, int indent, func_t *func,
1306 unsigned int *type_offset, enum pass pass)
1308 unsigned int last_size = 0;
1309 var_t *var;
1311 if (!func->args)
1312 return;
1314 var = func->args;
1315 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1316 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
1318 int in_attr = is_attr(var->attrs, ATTR_IN);
1319 int out_attr = is_attr(var->attrs, ATTR_OUT);
1321 if (!in_attr && !out_attr)
1322 in_attr = 1;
1324 switch (pass)
1326 case PASS_IN:
1327 if (!in_attr)
1328 continue;
1329 break;
1330 case PASS_OUT:
1331 if (!out_attr)
1332 continue;
1333 break;
1334 case PASS_RETURN:
1335 break;
1338 if (is_string_type(var->attrs, var->ptr_level, var->array))
1340 if (var->array && var->array->is_const)
1341 print_file(file, indent,
1342 "NdrNonConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1343 var->name, *type_offset);
1344 else
1345 print_file(file, indent,
1346 "NdrConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1347 var->name, *type_offset);
1348 last_size = 1;
1350 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1352 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1353 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1354 const char *array_type;
1355 int has_length = length_is && (length_is->type != EXPR_VOID);
1356 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
1358 if (NEXT_LINK(var->array)) /* multi-dimensional array */
1359 array_type = "ComplexArray";
1360 else
1362 if (!has_length && !has_size)
1363 array_type = "FixedArray";
1364 else if (has_length && !has_size)
1365 array_type = "VaryingArray";
1366 else if (!has_length && has_size)
1367 array_type = "ConformantArray";
1368 else
1369 array_type = "ConformantVaryingArray";
1372 print_file(file, indent,
1373 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1374 array_type, var->name, *type_offset);
1375 last_size = 1;
1377 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1379 unsigned int size;
1380 unsigned int alignment = 0;
1382 switch (var->type->type)
1384 case RPC_FC_BYTE:
1385 case RPC_FC_CHAR:
1386 case RPC_FC_SMALL:
1387 case RPC_FC_USMALL:
1388 size = 1;
1389 alignment = 0;
1390 break;
1392 case RPC_FC_WCHAR:
1393 case RPC_FC_USHORT:
1394 case RPC_FC_SHORT:
1395 size = 2;
1396 if (last_size != 0 && last_size < 2)
1397 alignment = (2 - last_size);
1398 break;
1400 case RPC_FC_ULONG:
1401 case RPC_FC_LONG:
1402 case RPC_FC_FLOAT:
1403 case RPC_FC_ERROR_STATUS_T:
1404 size = 4;
1405 if (last_size != 0 && last_size < 4)
1406 alignment = (4 - last_size);
1407 break;
1409 case RPC_FC_HYPER:
1410 case RPC_FC_DOUBLE:
1411 size = 8;
1412 if (last_size != 0 && last_size < 4)
1413 alignment = (4 - last_size);
1414 break;
1416 default:
1417 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1418 size = 0;
1421 if (alignment != 0)
1422 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
1424 print_file(file, indent, "");
1425 write_name(file, var);
1426 fprintf(file, " = *(");
1427 write_type(file, var->type, var, var->tname);
1428 fprintf(file, " *)_StubMsg.Buffer;\n");
1429 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1430 write_type(file, var->type, var, var->tname);
1431 fprintf(file, ");\n");
1433 last_size = size;
1435 else if (var->ptr_level == 0)
1437 const char *ndrtype;
1439 switch (var->type->type)
1441 case RPC_FC_STRUCT:
1442 ndrtype = "SimpleStruct";
1443 break;
1444 case RPC_FC_CSTRUCT:
1445 case RPC_FC_CPSTRUCT:
1446 ndrtype = "ConformantStruct";
1447 break;
1448 case RPC_FC_CVSTRUCT:
1449 ndrtype = "ConformantVaryingStruct";
1450 break;
1451 case RPC_FC_BOGUS_STRUCT:
1452 ndrtype = "ComplexStruct";
1453 break;
1454 case RPC_FC_IGNORE:
1455 case RPC_FC_BIND_PRIMITIVE:
1456 /* no unmarshalling needed */
1457 continue;
1458 default:
1459 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1460 var->name, var->type->type, var->ptr_level);
1461 ndrtype = NULL;
1464 print_file(file, indent,
1465 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1466 ndrtype, var->name, *type_offset);
1467 last_size = 1;
1469 else
1471 print_file(file, indent,
1472 "NdrPointerUnmarshall(&_StubMsg, (unsigned char **)&%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1473 var->name, *type_offset);
1474 last_size = 1;
1476 fprintf(file, "\n");
1481 size_t get_size_procformatstring_var(const var_t *var)
1483 unsigned int type_offset = 2;
1484 return write_procformatstring_var(NULL, 0, var, FALSE, &type_offset);
1488 size_t get_size_typeformatstring_var(const var_t *var)
1490 unsigned int type_offset = 0;
1491 write_typeformatstring_var(NULL, 0, var, &type_offset);
1492 return type_offset;
1495 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
1496 const var_t *fields, const char *structvar)
1498 switch (e->type) {
1499 case EXPR_VOID:
1500 break;
1501 case EXPR_NUM:
1502 fprintf(h, "%ld", e->u.lval);
1503 break;
1504 case EXPR_HEXNUM:
1505 fprintf(h, "0x%lx", e->u.lval);
1506 break;
1507 case EXPR_IDENTIFIER:
1509 const var_t *field;
1510 for (field = fields; field; field = NEXT_LINK(field))
1512 if (!strcmp(e->u.sval, field->name))
1514 fprintf(h, "%s->%s", structvar, e->u.sval);
1515 break;
1518 if (!field) error("no field found for identifier %s\n", e->u.sval);
1519 break;
1521 case EXPR_NEG:
1522 fprintf(h, "-");
1523 write_struct_expr(h, e->ref, 1, fields, structvar);
1524 break;
1525 case EXPR_NOT:
1526 fprintf(h, "~");
1527 write_struct_expr(h, e->ref, 1, fields, structvar);
1528 break;
1529 case EXPR_PPTR:
1530 fprintf(h, "*");
1531 write_struct_expr(h, e->ref, 1, fields, structvar);
1532 break;
1533 case EXPR_CAST:
1534 fprintf(h, "(");
1535 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
1536 fprintf(h, ")");
1537 write_struct_expr(h, e->ref, 1, fields, structvar);
1538 break;
1539 case EXPR_SIZEOF:
1540 fprintf(h, "sizeof(");
1541 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
1542 fprintf(h, ")");
1543 break;
1544 case EXPR_SHL:
1545 case EXPR_SHR:
1546 case EXPR_MUL:
1547 case EXPR_DIV:
1548 case EXPR_ADD:
1549 case EXPR_SUB:
1550 case EXPR_AND:
1551 case EXPR_OR:
1552 if (brackets) fprintf(h, "(");
1553 write_struct_expr(h, e->ref, 1, fields, structvar);
1554 switch (e->type) {
1555 case EXPR_SHL: fprintf(h, " << "); break;
1556 case EXPR_SHR: fprintf(h, " >> "); break;
1557 case EXPR_MUL: fprintf(h, " * "); break;
1558 case EXPR_DIV: fprintf(h, " / "); break;
1559 case EXPR_ADD: fprintf(h, " + "); break;
1560 case EXPR_SUB: fprintf(h, " - "); break;
1561 case EXPR_AND: fprintf(h, " & "); break;
1562 case EXPR_OR: fprintf(h, " | "); break;
1563 default: break;
1565 write_struct_expr(h, e->u.ext, 1, fields, structvar);
1566 if (brackets) fprintf(h, ")");
1567 break;
1568 case EXPR_COND:
1569 if (brackets) fprintf(h, "(");
1570 write_struct_expr(h, e->ref, 1, fields, structvar);
1571 fprintf(h, " ? ");
1572 write_struct_expr(h, e->u.ext, 1, fields, structvar);
1573 fprintf(h, " : ");
1574 write_struct_expr(h, e->ext2, 1, fields, structvar);
1575 if (brackets) fprintf(h, ")");
1576 break;
1580 int write_expr_eval_routines(FILE *file, const char *iface)
1582 int result = 0;
1583 struct expr_eval_routine *eval;
1584 unsigned short callback_offset = 0;
1586 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
1588 int indent = 0;
1589 result = 1;
1590 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
1591 iface, eval->structure->name, callback_offset);
1592 print_file(file, indent, "{\n");
1593 indent++;
1594 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
1595 eval->structure->name, eval->structure->name, eval->structure_size);
1596 fprintf(file, "\n");
1597 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
1598 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
1599 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
1600 fprintf(file, ";\n");
1601 indent--;
1602 print_file(file, indent, "}\n\n");
1603 callback_offset++;
1605 return result;
1608 void write_expr_eval_routine_list(FILE *file, const char *iface)
1610 struct expr_eval_routine *eval;
1611 struct expr_eval_routine *cursor;
1612 unsigned short callback_offset = 0;
1614 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
1615 fprintf(file, "{\n");
1617 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
1619 print_file(file, 1, "%s_%sExprEval_%04u,\n",
1620 iface, eval->structure->name, callback_offset);
1622 callback_offset++;
1623 list_remove(&eval->entry);
1624 free(eval);
1627 fprintf(file, "};\n\n");