widl: Take array dimensions into account when computing buffer size.
[wine/multimedia.git] / tools / widl / typegen.c
blob938764fe3a16c2e41e47e18de49b4c06860cf291
1 /*
2 * Format String Generator for IDL Compiler
4 * Copyright 2005-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 array_dims_t *array, unsigned int *align);
63 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
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 case EXPR_TRUEFALSE:
77 return a->u.lval - b->u.lval;
78 case EXPR_IDENTIFIER:
79 return strcmp(a->u.sval, b->u.sval);
80 case EXPR_COND:
81 ret = compare_expr(a->ref, b->ref);
82 if (ret != 0)
83 return ret;
84 ret = compare_expr(a->u.ext, b->u.ext);
85 if (ret != 0)
86 return ret;
87 return compare_expr(a->ext2, b->ext2);
88 case EXPR_OR:
89 case EXPR_AND:
90 case EXPR_ADD:
91 case EXPR_SUB:
92 case EXPR_MUL:
93 case EXPR_DIV:
94 case EXPR_SHL:
95 case EXPR_SHR:
96 ret = compare_expr(a->ref, b->ref);
97 if (ret != 0)
98 return ret;
99 return compare_expr(a->u.ext, b->u.ext);
100 case EXPR_NOT:
101 case EXPR_NEG:
102 case EXPR_PPTR:
103 case EXPR_CAST:
104 case EXPR_SIZEOF:
105 return compare_expr(a->ref, b->ref);
106 case EXPR_VOID:
107 return 0;
109 return -1;
112 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
113 do { \
114 if (file) \
115 fprintf(file, "/* %2u */\n", typestring_offset); \
116 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
118 while (0)
120 static int print_file(FILE *file, int indent, const char *format, ...)
122 va_list va;
123 int i, r;
125 if (!file) return 0;
127 va_start(va, format);
128 for (i = 0; i < indent; i++)
129 fprintf(file, " ");
130 r = vfprintf(file, format, va);
131 va_end(va);
132 return r;
135 static void write_formatdesc(FILE *f, int indent, const char *str)
137 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
138 print_file(f, indent, "{\n");
139 print_file(f, indent + 1, "short Pad;\n");
140 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
141 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
142 print_file(f, indent, "\n");
145 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, int for_objects)
147 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
148 get_size_typeformatstring(ifaces, for_objects));
150 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
151 get_size_procformatstring(ifaces, for_objects));
153 fprintf(f, "\n");
154 write_formatdesc(f, indent, "TYPE");
155 write_formatdesc(f, indent, "PROC");
156 fprintf(f, "\n");
157 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
158 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
159 print_file(f, indent, "\n");
162 static int is_user_derived(const var_t *v)
164 const type_t *type = v->type;
166 if (v->attrs && is_attr( v->attrs, ATTR_WIREMARSHAL )) return 1;
168 while (type)
170 if (type->attrs && is_attr( type->attrs, ATTR_WIREMARSHAL )) return 1;
171 type = type->ref;
173 return 0;
176 static inline int is_base_type(unsigned char type)
178 switch (type)
180 case RPC_FC_BYTE:
181 case RPC_FC_CHAR:
182 case RPC_FC_USMALL:
183 case RPC_FC_SMALL:
184 case RPC_FC_WCHAR:
185 case RPC_FC_USHORT:
186 case RPC_FC_SHORT:
187 case RPC_FC_ULONG:
188 case RPC_FC_LONG:
189 case RPC_FC_HYPER:
190 case RPC_FC_IGNORE:
191 case RPC_FC_FLOAT:
192 case RPC_FC_DOUBLE:
193 case RPC_FC_ENUM16:
194 case RPC_FC_ENUM32:
195 case RPC_FC_ERROR_STATUS_T:
196 case RPC_FC_BIND_PRIMITIVE:
197 return TRUE;
199 default:
200 return FALSE;
204 static size_t write_procformatstring_var(FILE *file, int indent,
205 const var_t *var, int is_return, unsigned int *type_offset)
207 size_t size;
208 int ptr_level = var->ptr_level;
209 const type_t *type = var->type;
211 int is_in = is_attr(var->attrs, ATTR_IN);
212 int is_out = is_attr(var->attrs, ATTR_OUT);
214 if (!is_in && !is_out) is_in = TRUE;
216 if (ptr_level == 0 && !var->array && is_base_type(type->type))
218 if (is_return)
219 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
220 else
221 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
223 switch(type->type)
225 #define CASE_BASETYPE(fctype) \
226 case RPC_##fctype: \
227 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
228 size = 2; /* includes param type prefix */ \
229 break
231 CASE_BASETYPE(FC_BYTE);
232 CASE_BASETYPE(FC_CHAR);
233 CASE_BASETYPE(FC_WCHAR);
234 CASE_BASETYPE(FC_USHORT);
235 CASE_BASETYPE(FC_SHORT);
236 CASE_BASETYPE(FC_ULONG);
237 CASE_BASETYPE(FC_LONG);
238 CASE_BASETYPE(FC_HYPER);
239 CASE_BASETYPE(FC_IGNORE);
240 CASE_BASETYPE(FC_USMALL);
241 CASE_BASETYPE(FC_SMALL);
242 CASE_BASETYPE(FC_FLOAT);
243 CASE_BASETYPE(FC_DOUBLE);
244 CASE_BASETYPE(FC_ERROR_STATUS_T);
245 #undef CASE_BASETYPE
247 case RPC_FC_BIND_PRIMITIVE:
248 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
249 size = 2; /* includes param type prefix */
250 break;
252 default:
253 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
254 size = 0;
257 else
259 if (is_return)
260 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
261 else if (is_in && is_out)
262 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
263 else if (is_out)
264 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
265 else
266 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
268 print_file(file, indent, "0x01,\n");
269 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
270 size = 4; /* includes param type prefix */
272 *type_offset += get_size_typeformatstring_var(var);
273 return size;
276 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
278 const ifref_t *iface;
279 int indent = 0;
280 const var_t *var;
281 unsigned int type_offset = 2;
283 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
284 print_file(file, indent, "{\n");
285 indent++;
286 print_file(file, indent, "0,\n");
287 print_file(file, indent, "{\n");
288 indent++;
290 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
292 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
293 continue;
295 if (iface->iface->funcs)
297 const func_t *func;
298 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
300 if (is_local(func->def->attrs)) continue;
301 /* emit argument data */
302 if (func->args)
304 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
305 write_procformatstring_var(file, indent, var, FALSE, &type_offset);
308 /* emit return value data */
309 var = func->def;
310 if (is_void(var->type, NULL))
312 print_file(file, indent, "0x5b, /* FC_END */\n");
313 print_file(file, indent, "0x5c, /* FC_PAD */\n");
315 else
316 write_procformatstring_var(file, indent, var, TRUE,
317 &type_offset);
322 print_file(file, indent, "0x0\n");
323 indent--;
324 print_file(file, indent, "}\n");
325 indent--;
326 print_file(file, indent, "};\n");
327 print_file(file, indent, "\n");
330 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
332 switch (type->type)
334 #define CASE_BASETYPE(fctype) \
335 case RPC_##fctype: \
336 print_file(file, 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
337 *typestring_offset += 1; \
338 return 1;
340 CASE_BASETYPE(FC_BYTE);
341 CASE_BASETYPE(FC_CHAR);
342 CASE_BASETYPE(FC_SMALL);
343 CASE_BASETYPE(FC_USMALL);
344 CASE_BASETYPE(FC_WCHAR);
345 CASE_BASETYPE(FC_SHORT);
346 CASE_BASETYPE(FC_USHORT);
347 CASE_BASETYPE(FC_LONG);
348 CASE_BASETYPE(FC_ULONG);
349 CASE_BASETYPE(FC_FLOAT);
350 CASE_BASETYPE(FC_HYPER);
351 CASE_BASETYPE(FC_DOUBLE);
352 CASE_BASETYPE(FC_ENUM16);
353 CASE_BASETYPE(FC_ENUM32);
354 CASE_BASETYPE(FC_IGNORE);
355 CASE_BASETYPE(FC_ERROR_STATUS_T);
356 #undef CASE_BASETYPE
358 return 0;
361 /* write conformance / variance descriptor */
362 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr)
364 unsigned char operator_type = 0;
365 const char *operator_string = "no operators";
366 const expr_t *subexpr = expr;
367 unsigned char correlation_type;
369 if (!file) return 4; /* optimisation for sizing pass */
371 if (expr->is_const)
373 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
374 error("write_conf_or_var_desc: constant value %ld is greater than "
375 "the maximum constant size of %d\n", expr->cval,
376 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
378 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
379 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
380 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
381 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
383 return 4;
386 switch (subexpr->type)
388 case EXPR_PPTR:
389 subexpr = subexpr->ref;
390 operator_type = RPC_FC_DEREFERENCE;
391 operator_string = "FC_DEREFERENCE";
392 break;
393 case EXPR_DIV:
394 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
396 subexpr = subexpr->ref;
397 operator_type = RPC_FC_DIV_2;
398 operator_string = "FC_DIV_2";
400 break;
401 case EXPR_MUL:
402 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
404 subexpr = subexpr->ref;
405 operator_type = RPC_FC_MULT_2;
406 operator_string = "FC_MULT_2";
408 break;
409 case EXPR_SUB:
410 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
412 subexpr = subexpr->ref;
413 operator_type = RPC_FC_SUB_1;
414 operator_string = "FC_SUB_1";
416 break;
417 case EXPR_ADD:
418 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
420 subexpr = subexpr->ref;
421 operator_type = RPC_FC_ADD_1;
422 operator_string = "FC_ADD_1";
424 break;
425 default:
426 break;
429 if (subexpr->type == EXPR_IDENTIFIER)
431 const type_t *correlation_variable = NULL;
432 unsigned char correlation_variable_type;
433 unsigned char param_type = 0;
434 const char *param_type_string = NULL;
435 size_t offset;
437 if (structure)
439 const var_t *var;
441 offset = 0;
442 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
444 unsigned int align = 0;
445 offset -= type_memsize(var->type, var->ptr_level, var->array, &align);
446 /* FIXME: take alignment into account */
447 if (!strcmp(var->name, subexpr->u.sval))
449 correlation_variable = var->type;
450 break;
453 if (!correlation_variable)
454 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
455 subexpr->u.sval);
457 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
459 else
461 const var_t *var;
463 offset = 0;
464 if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
466 if (!strcmp(var->name, subexpr->u.sval))
468 correlation_variable = var->type;
469 break;
471 /* FIXME: not all stack variables are sizeof(void *) */
472 offset += sizeof(void *);
474 if (!correlation_variable)
475 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
476 subexpr->u.sval);
478 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
481 correlation_variable_type = correlation_variable->type;
483 switch (correlation_variable_type)
485 case RPC_FC_CHAR:
486 case RPC_FC_SMALL:
487 param_type = RPC_FC_SMALL;
488 param_type_string = "FC_SMALL";
489 break;
490 case RPC_FC_BYTE:
491 case RPC_FC_USMALL:
492 param_type = RPC_FC_USMALL;
493 param_type_string = "FC_USMALL";
494 break;
495 case RPC_FC_WCHAR:
496 case RPC_FC_SHORT:
497 param_type = RPC_FC_SHORT;
498 param_type_string = "FC_SHORT";
499 break;
500 case RPC_FC_USHORT:
501 param_type = RPC_FC_USHORT;
502 param_type_string = "FC_USHORT";
503 break;
504 case RPC_FC_LONG:
505 param_type = RPC_FC_LONG;
506 param_type_string = "FC_LONG";
507 break;
508 case RPC_FC_ULONG:
509 param_type = RPC_FC_ULONG;
510 param_type_string = "FC_ULONG";
511 break;
512 default:
513 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
514 correlation_variable_type);
517 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
518 correlation_type | param_type,
519 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
520 param_type_string);
521 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
522 print_file(file, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
523 offset,
524 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
525 offset);
527 else
529 unsigned int callback_offset = 0;
531 if (structure)
533 struct expr_eval_routine *eval;
534 int found = 0;
536 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
538 if (!strcmp(eval->structure->name, structure->name) &&
539 !compare_expr(eval->expr, expr))
541 found = 1;
542 break;
544 callback_offset++;
547 if (!found)
549 unsigned int align = 0;
550 eval = xmalloc(sizeof(*eval));
551 eval->structure = structure;
552 eval->structure_size = fields_memsize(structure->fields, &align);
553 eval->expr = expr;
554 list_add_tail(&expr_eval_routines, &eval->entry);
557 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
559 else
561 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
562 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
565 if (callback_offset > USHRT_MAX)
566 error("Maximum number of callback routines reached\n");
568 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
569 correlation_type,
570 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
571 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
572 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
574 return 4;
577 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
579 size_t size = 0;
580 const var_t *v;
582 if (!fields) return 0;
583 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
584 size += type_memsize(v->type, v->ptr_level, v->array, align);
586 return size;
589 static size_t get_array_size( const array_dims_t *array )
591 size_t size = 1;
592 const expr_t *dim;
594 if (!array) return 0;
596 LIST_FOR_EACH_ENTRY( dim, array, expr_t, entry )
598 if (!dim->is_const) return 0;
599 size *= dim->cval;
602 return size;
605 static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *array, unsigned int *align)
607 size_t size = 0;
609 if (ptr_level)
611 size = sizeof(void *);
612 if (size > *align) *align = size;
614 else switch (t->type)
616 case RPC_FC_BYTE:
617 case RPC_FC_CHAR:
618 case RPC_FC_USMALL:
619 case RPC_FC_SMALL:
620 size = 1;
621 if (size > *align) *align = size;
622 break;
623 case RPC_FC_WCHAR:
624 case RPC_FC_USHORT:
625 case RPC_FC_SHORT:
626 case RPC_FC_ENUM16:
627 size = 2;
628 if (size > *align) *align = size;
629 break;
630 case RPC_FC_ULONG:
631 case RPC_FC_LONG:
632 case RPC_FC_ERROR_STATUS_T:
633 case RPC_FC_ENUM32:
634 case RPC_FC_FLOAT:
635 size = 4;
636 if (size > *align) *align = size;
637 break;
638 case RPC_FC_HYPER:
639 case RPC_FC_DOUBLE:
640 size = 8;
641 if (size > *align) *align = size;
642 break;
643 case RPC_FC_STRUCT:
644 case RPC_FC_CVSTRUCT:
645 case RPC_FC_CPSTRUCT:
646 case RPC_FC_CSTRUCT:
647 case RPC_FC_PSTRUCT:
648 case RPC_FC_BOGUS_STRUCT:
649 case RPC_FC_ENCAPSULATED_UNION:
650 case RPC_FC_NON_ENCAPSULATED_UNION:
651 size = fields_memsize(t->fields, align);
652 break;
653 default:
654 error("type_memsize: Unknown type %d\n", t->type);
655 size = 0;
658 if (array) size *= get_array_size( array );
659 return size;
662 static int write_pointers(FILE *file, const attr_list_t *attrs,
663 const type_t *type, int ptr_level,
664 const array_dims_t *array, int level,
665 unsigned int *typestring_offset)
667 int pointers_written = 0;
668 const var_t *v;
670 /* don't generate a pointer for first-level arrays since we want to
671 * descend into them to write their pointers, not stop here */
672 if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array))
674 return write_pointers(file, NULL, type, 0, NULL, level + 1, typestring_offset);
677 if (ptr_level != 0)
679 /* FIXME: only general algorithm implemented, not the actual writing */
680 error("write_pointers: Writing type format string for pointer is unimplemented\n");
681 return 1;
684 switch (type->type)
686 /* note: don't descend into complex structures or unions since these
687 * will always be generated as a separate type */
688 case RPC_FC_STRUCT:
689 case RPC_FC_CVSTRUCT:
690 case RPC_FC_CPSTRUCT:
691 case RPC_FC_CSTRUCT:
692 case RPC_FC_PSTRUCT:
693 if (!type->fields) break;
694 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
695 pointers_written += write_pointers(file, v->attrs, v->type,
696 v->ptr_level, v->array,
697 level + 1,
698 typestring_offset);
700 break;
702 default:
703 /* nothing to do */
704 break;
707 return pointers_written;
710 static size_t write_pointer_description(FILE *file, const attr_list_t *attrs,
711 const type_t *type, int ptr_level,
712 const array_dims_t *array, int level,
713 size_t typestring_offset)
715 size_t size = 0;
716 const var_t *v;
718 /* don't generate a pointer for first-level arrays since we want to
719 * descend into them to write their pointers, not stop here */
720 if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array))
722 return write_pointer_description(file, NULL, type, 0, NULL,
723 level + 1, typestring_offset);
726 if (ptr_level != 0)
728 /* FIXME: only general algorithm implemented, not the actual writing */
729 error("write_pointer_description: Writing pointer description is unimplemented\n");
730 return 0;
733 /* FIXME: search through all refs for pointers too */
735 switch (type->type)
737 /* note: don't descend into complex structures or unions since these
738 * will always be generated as a separate type */
739 case RPC_FC_STRUCT:
740 case RPC_FC_CVSTRUCT:
741 case RPC_FC_CPSTRUCT:
742 case RPC_FC_CSTRUCT:
743 case RPC_FC_PSTRUCT:
744 if (!type->fields) break;
745 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
746 size += write_pointer_description(file, v->attrs, v->type,
747 v->ptr_level, v->array,
748 level + 1,
749 typestring_offset);
751 break;
753 default:
754 /* nothing to do */
755 break;
758 return size;
761 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
762 const type_t *type, const array_dims_t *array,
763 const char *name, unsigned int *typestring_offset)
765 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
766 int has_size = size_is && (size_is->type != EXPR_VOID);
767 size_t start_offset = *typestring_offset;
768 unsigned char flags = 0;
769 int pointer_type;
770 unsigned char rtype;
772 if (is_ptr(type))
774 pointer_type = type->type;
775 type = type->ref;
777 else
778 pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
780 if (!pointer_type)
781 pointer_type = RPC_FC_RP;
783 if (!get_attrp(attrs, ATTR_SIZEIS))
784 flags |= RPC_FC_P_SIMPLEPOINTER;
786 rtype = type->type;
788 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
790 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
791 return start_offset;
794 print_file(file, 2,"0x%x, 0x%x, /* %s%s */\n",
795 pointer_type, flags,
796 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"),
797 (flags & RPC_FC_P_SIMPLEPOINTER) ? " [simple_pointer]" : "");
798 *typestring_offset += 2;
800 if (!(flags & RPC_FC_P_SIMPLEPOINTER))
802 print_file(file, 2, "NdrFcShort(0x2),\n");
803 *typestring_offset += 2;
806 if (array && !is_conformant_array(array))
808 /* FIXME: multi-dimensional array */
809 const expr_t *dim = LIST_ENTRY( list_head( array ), expr_t, entry );
810 if (dim->cval > USHRT_MAX)
811 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
812 name, USHRT_MAX, dim->cval - USHRT_MAX);
814 if (rtype == RPC_FC_CHAR)
815 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
816 else
817 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
818 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
819 *typestring_offset += 2;
821 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", dim->cval, dim->cval);
822 *typestring_offset += 2;
824 return start_offset;
826 else if (has_size)
828 if (rtype == RPC_FC_CHAR)
829 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
830 else
831 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
832 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
833 *typestring_offset += 2;
835 *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, size_is);
837 return start_offset;
839 else
841 if (rtype == RPC_FC_CHAR)
842 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
843 else
844 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
845 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
846 *typestring_offset += 2;
848 return start_offset;
852 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs,
853 const type_t *type, const array_dims_t *array,
854 const char *name, unsigned int *typestring_offset)
856 const expr_t *length_is = get_attrp(attrs, ATTR_LENGTHIS);
857 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
858 int has_length = length_is && (length_is->type != EXPR_VOID);
859 int has_size = (size_is && (size_is->type != EXPR_VOID)) || is_conformant_array(array);
860 size_t start_offset;
861 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
862 if (!pointer_type)
863 pointer_type = RPC_FC_RP;
865 print_file(file, 2, "0x%x, 0x00, /* %s */\n",
866 pointer_type,
867 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
868 print_file(file, 2, "NdrFcShort(0x2),\n");
869 *typestring_offset += 4;
871 if (array && list_count(array) > 1) /* multi-dimensional array */
873 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name);
874 return 0;
876 else
878 const expr_t *dim = array ? LIST_ENTRY( list_head( array ), expr_t, entry ) : NULL;
879 size_t pointer_start_offset = *typestring_offset;
880 int has_pointer = 0;
882 if (write_pointers(file, attrs, type, 0, array, 0, typestring_offset) > 0)
883 has_pointer = 1;
885 start_offset = *typestring_offset;
887 if (!has_length && !has_size)
889 /* fixed array */
890 unsigned int align = 0;
891 size_t size = type_memsize(type, 0, array, &align);
892 if (size < USHRT_MAX)
894 WRITE_FCTYPE(file, FC_SMFARRAY, *typestring_offset);
895 /* alignment */
896 print_file(file, 2, "0x%02x,\n", align - 1);
897 /* size */
898 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", size, size);
899 *typestring_offset += 4;
901 else
903 WRITE_FCTYPE(file, FC_LGFARRAY, *typestring_offset);
904 /* alignment */
905 print_file(file, 2, "0x%02x,\n", align - 1);
906 /* size */
907 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", size, size);
908 *typestring_offset += 6;
911 if (has_pointer)
913 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
914 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
915 *typestring_offset += 2;
916 *typestring_offset = write_pointer_description(file, attrs,
917 type, 0, array, 0, pointer_start_offset);
918 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
919 *typestring_offset += 1;
922 if (!write_base_type( file, type, typestring_offset ))
924 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
925 *typestring_offset += 1;
927 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
928 *typestring_offset += 1;
930 return start_offset;
932 else if (has_length && !has_size)
934 /* varying array */
935 unsigned int align = 0;
936 size_t element_size = type_memsize(type, 0, NULL, &align);
937 size_t elements = dim->cval;
938 size_t total_size = element_size * elements;
940 if (total_size < USHRT_MAX)
942 WRITE_FCTYPE(file, FC_SMVARRAY, *typestring_offset);
943 /* alignment */
944 print_file(file, 2, "0x%02x,\n", align - 1);
945 /* total size */
946 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", total_size, total_size);
947 /* number of elements */
948 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", elements, elements);
949 *typestring_offset += 6;
951 else
953 WRITE_FCTYPE(file, FC_LGVARRAY, *typestring_offset);
954 /* alignment */
955 print_file(file, 2, "0x%02x,\n", align - 1);
956 /* total size */
957 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", total_size, total_size);
958 /* number of elements */
959 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", elements, elements);
960 *typestring_offset += 10;
962 /* element size */
963 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
964 *typestring_offset += 2;
966 *typestring_offset += write_conf_or_var_desc(file, current_func,
967 current_structure,
968 length_is);
970 if (has_pointer)
972 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
973 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
974 *typestring_offset += 2;
975 *typestring_offset += write_pointer_description(file, attrs,
976 type, 0, array, 0, pointer_start_offset);
977 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
978 *typestring_offset += 1;
981 if (!write_base_type( file, type, typestring_offset ))
983 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
984 *typestring_offset += 1;
986 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
987 *typestring_offset += 1;
989 return start_offset;
991 else if (!has_length && has_size)
993 /* conformant array */
994 unsigned int align = 0;
995 size_t element_size = type_memsize(type, 0, NULL, &align);
997 WRITE_FCTYPE(file, FC_CARRAY, *typestring_offset);
998 /* alignment */
999 print_file(file, 2, "0x%02x,\n", align - 1);
1000 /* element size */
1001 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
1002 *typestring_offset += 4;
1004 *typestring_offset += write_conf_or_var_desc(file, current_func,
1005 current_structure,
1006 size_is ? size_is : dim);
1008 if (has_pointer)
1010 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1011 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1012 *typestring_offset += 2;
1013 *typestring_offset += write_pointer_description(file, attrs,
1014 type, 0, array, 0, pointer_start_offset);
1015 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1016 *typestring_offset += 1;
1019 if (!write_base_type( file, type, typestring_offset ))
1021 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
1022 *typestring_offset += 1;
1024 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1025 *typestring_offset += 1;
1027 return start_offset;
1029 else
1031 /* conformant varying array */
1032 unsigned int align = 0;
1033 size_t element_size = type_memsize(type, 0, NULL, &align);
1035 WRITE_FCTYPE(file, FC_CVARRAY, *typestring_offset);
1036 /* alignment */
1037 print_file(file, 2, "0x%02x,\n", align - 1);
1038 /* element size */
1039 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
1040 *typestring_offset += 4;
1042 *typestring_offset += write_conf_or_var_desc(file, current_func,
1043 current_structure,
1044 size_is ? size_is : dim);
1045 *typestring_offset += write_conf_or_var_desc(file, current_func,
1046 current_structure,
1047 length_is);
1049 if (has_pointer)
1051 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1052 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1053 *typestring_offset += 2;
1054 *typestring_offset += write_pointer_description(file, attrs,
1055 type, 0, array, 0, pointer_start_offset);
1056 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1057 *typestring_offset += 1;
1060 if (!write_base_type( file, type, typestring_offset ))
1062 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
1063 *typestring_offset += 1;
1065 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1066 *typestring_offset += 1;
1068 return start_offset;
1073 static const var_t *find_array_or_string_in_struct(const type_t *type)
1075 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1077 if (is_array_type(last_field->attrs, last_field->ptr_level, last_field->array))
1078 return last_field;
1080 assert((last_field->type->type == RPC_FC_CSTRUCT) ||
1081 (last_field->type->type == RPC_FC_CPSTRUCT) ||
1082 (last_field->type->type == RPC_FC_CVSTRUCT));
1084 return find_array_or_string_in_struct(last_field->type);
1087 static void write_struct_members(FILE *file, const type_t *type, unsigned int *typestring_offset)
1089 const var_t *field;
1091 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1093 unsigned char rtype = field->type->type;
1095 if (field->array)
1096 write_array_tfs( file, field->attrs, field->type, field->array,
1097 field->name, typestring_offset );
1098 else if (!write_base_type( file, field->type, typestring_offset ))
1099 error("Unsupported member type 0x%x\n", rtype);
1102 if (!(*typestring_offset % 2))
1104 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1105 *typestring_offset += 1;
1108 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1109 *typestring_offset += 1;
1112 static size_t write_struct_tfs(FILE *file, const type_t *type,
1113 const char *name, unsigned int *typestring_offset)
1115 unsigned int total_size;
1116 const var_t *array;
1117 size_t start_offset;
1118 size_t array_offset;
1119 size_t pointer_offset;
1120 unsigned int align = 0;
1122 switch (type->type)
1124 case RPC_FC_STRUCT:
1125 case RPC_FC_PSTRUCT:
1126 total_size = type_memsize(type, 0, NULL, &align);
1128 if (total_size > USHRT_MAX)
1129 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1130 name, USHRT_MAX, total_size - USHRT_MAX);
1132 if (type->type == RPC_FC_PSTRUCT)
1134 pointer_offset = *typestring_offset;
1135 write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset);
1137 else pointer_offset = 0; /* silence warning */
1139 start_offset = *typestring_offset;
1140 if (type->type == RPC_FC_STRUCT)
1141 WRITE_FCTYPE(file, FC_STRUCT, *typestring_offset);
1142 else
1143 WRITE_FCTYPE(file, FC_PSTRUCT, *typestring_offset);
1144 /* alignment */
1145 print_file(file, 2, "0x%02x,\n", align - 1);
1146 /* total size */
1147 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1148 *typestring_offset += 4;
1150 if (type->type == RPC_FC_PSTRUCT)
1152 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1153 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1154 *typestring_offset += 2;
1155 *typestring_offset += write_pointer_description(file, NULL,
1156 type, 0, NULL, 0, pointer_offset);
1157 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1158 *typestring_offset += 1;
1161 /* member layout */
1162 write_struct_members(file, type, typestring_offset);
1163 return start_offset;
1164 case RPC_FC_CSTRUCT:
1165 case RPC_FC_CPSTRUCT:
1166 total_size = type_memsize(type, 0, NULL, &align);
1168 if (total_size > USHRT_MAX)
1169 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1170 name, USHRT_MAX, total_size - USHRT_MAX);
1172 array = find_array_or_string_in_struct(type);
1173 current_structure = type;
1174 array_offset = write_array_tfs(file, array->attrs, array->type,
1175 array->array, array->name,
1176 typestring_offset);
1177 current_structure = NULL;
1179 if (type->type == RPC_FC_CPSTRUCT)
1181 pointer_offset = *typestring_offset;
1182 write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset);
1184 else pointer_offset = 0; /* silence warning */
1186 start_offset = *typestring_offset;
1187 if (type->type == RPC_FC_CSTRUCT)
1188 WRITE_FCTYPE(file, FC_CSTRUCT, *typestring_offset);
1189 else
1190 WRITE_FCTYPE(file, FC_CPSTRUCT, *typestring_offset);
1191 /* alignment */
1192 print_file(file, 2, "0x%02x,\n", align - 1);
1193 /* total size */
1194 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1195 *typestring_offset += 4;
1196 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1197 array_offset - *typestring_offset,
1198 array_offset - *typestring_offset,
1199 array_offset);
1200 *typestring_offset += 2;
1202 if (type->type == RPC_FC_CPSTRUCT)
1204 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1205 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1206 *typestring_offset += 2;
1207 *typestring_offset += write_pointer_description(file, NULL,
1208 type, 0, NULL, 0, pointer_offset);
1209 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1210 *typestring_offset += 1;
1213 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1214 *typestring_offset += 1;
1216 return start_offset;
1217 case RPC_FC_CVSTRUCT:
1218 total_size = type_memsize(type, 0, NULL, &align);
1220 if (total_size > USHRT_MAX)
1221 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1222 name, USHRT_MAX, total_size - USHRT_MAX);
1224 array = find_array_or_string_in_struct(type);
1225 current_structure = type;
1226 if (is_attr(array->attrs, ATTR_STRING))
1227 array_offset = write_string_tfs(file, array->attrs, array->type,
1228 array->array, array->name,
1229 typestring_offset);
1230 else
1231 array_offset = write_array_tfs(file, array->attrs, array->type,
1232 array->array, array->name,
1233 typestring_offset);
1234 current_structure = NULL;
1236 pointer_offset = *typestring_offset;
1237 if (!write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset))
1238 pointer_offset = 0;
1240 start_offset = *typestring_offset;
1241 WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset);
1242 /* alignment */
1243 print_file(file, 2, "0x%02x,\n", align - 1);
1244 /* total size */
1245 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1246 *typestring_offset += 4;
1247 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1248 array_offset - *typestring_offset,
1249 array_offset - *typestring_offset,
1250 array_offset);
1251 *typestring_offset += 2;
1253 if (pointer_offset != 0)
1255 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1256 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1257 *typestring_offset += 2;
1258 *typestring_offset += write_pointer_description(file, NULL,
1259 type, 0, NULL, 0, pointer_offset);
1260 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1261 *typestring_offset += 1;
1264 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1265 *typestring_offset += 1;
1267 return start_offset;
1268 default:
1269 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
1270 return *typestring_offset;
1274 static void write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1275 unsigned char flags, size_t offset,
1276 unsigned int *typeformat_offset)
1278 int in_attr, out_attr;
1279 in_attr = is_attr(attrs, ATTR_IN);
1280 out_attr = is_attr(attrs, ATTR_OUT);
1281 if (!in_attr && !out_attr) in_attr = 1;
1283 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1284 flags |= 0x04;
1286 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1287 pointer_type,
1288 flags,
1289 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
1290 if (file)
1292 if (flags & 0x04)
1293 fprintf(file, " [allocated_on_stack]");
1294 if (flags & 0x10)
1295 fprintf(file, " [pointer_deref]");
1296 fprintf(file, " */\n");
1299 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", offset, offset);
1300 *typeformat_offset += 4;
1303 static size_t write_union_tfs(FILE *file, const attr_list_t *attrs,
1304 const type_t *type, const char *name,
1305 unsigned int *typeformat_offset)
1307 error("write_union_tfs: Unimplemented\n");
1308 return *typeformat_offset;
1311 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs,
1312 const char *name, unsigned int *typeformat_offset)
1314 size_t i;
1315 size_t start_offset = *typeformat_offset;
1316 const UUID *uuid = get_attrp(attrs, ATTR_UUID);
1318 if (! uuid)
1319 error("%s: interface %s missing UUID\n", __FUNCTION__, name);
1321 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1322 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1323 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1324 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1325 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1326 for (i = 0; i < 8; ++i)
1327 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1329 if (file)
1330 fprintf(file, "\n");
1332 *typeformat_offset += 18;
1333 return start_offset;
1336 static int get_ptr_attr(const type_t *t, int def_type)
1338 while (TRUE)
1340 int ptr_attr = get_attrv(t->attrs, ATTR_POINTERTYPE);
1341 if (ptr_attr)
1342 return ptr_attr;
1343 if (t->kind != TKIND_ALIAS)
1344 return def_type;
1345 t = t->orig;
1349 static size_t write_typeformatstring_var(FILE *file, int indent,
1350 const var_t *var, unsigned int *typeformat_offset)
1352 const type_t *type = var->type;
1353 int var_ptrs = var->ptr_level, type_ptrs = 0;
1354 int is_str = is_attr(var->attrs, ATTR_STRING);
1356 chat("write_typeformatstring_var: %s\n", var->name);
1358 while (TRUE)
1360 is_str = is_str || is_attr(type->attrs, ATTR_STRING);
1361 if (type->kind == TKIND_ALIAS)
1362 type = type->orig;
1363 else if (is_ptr(type))
1365 ++type_ptrs;
1366 type = type->ref;
1368 else
1370 type = var->type;
1371 break;
1375 while (TRUE)
1377 int ptr_level = var_ptrs + type_ptrs;
1378 int pointer_type = 0;
1380 chat("write_typeformatstring: type->type = 0x%x, type->name = %s, ptr_level = %d\n", type->type, type->name, ptr_level);
1382 /* var attrs only effect the rightmost pointer */
1383 if ((0 < var->ptr_level && var_ptrs == var->ptr_level)
1384 || (var->ptr_level == 0 && type == var->type))
1386 int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE);
1387 if (pointer_attr)
1389 if (! ptr_level)
1390 error("'%s': pointer attribute applied to non-pointer type",
1391 var->name);
1392 pointer_type = pointer_attr;
1394 else
1395 pointer_type = RPC_FC_RP;
1397 else /* pointers below other pointers default to unique */
1398 pointer_type = var_ptrs ? RPC_FC_UP : get_ptr_attr(type, RPC_FC_UP);
1400 if (is_str && ptr_level + (var->array != NULL) == 1)
1401 return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
1403 if (is_array_type(var->attrs, ptr_level, var->array))
1404 return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
1406 if (ptr_level == 0)
1408 /* basic types don't need a type format string */
1409 if (is_base_type(type->type))
1410 return 0;
1412 switch (type->type)
1414 case RPC_FC_STRUCT:
1415 case RPC_FC_PSTRUCT:
1416 case RPC_FC_CSTRUCT:
1417 case RPC_FC_CPSTRUCT:
1418 case RPC_FC_CVSTRUCT:
1419 case RPC_FC_BOGUS_STRUCT:
1420 return write_struct_tfs(file, type, var->name, typeformat_offset);
1421 case RPC_FC_ENCAPSULATED_UNION:
1422 case RPC_FC_NON_ENCAPSULATED_UNION:
1423 return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset);
1424 case RPC_FC_IGNORE:
1425 case RPC_FC_BIND_PRIMITIVE:
1426 /* nothing to do */
1427 return 0;
1428 default:
1429 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
1432 else if (ptr_level == 1)
1434 size_t start_offset = *typeformat_offset;
1435 int in_attr = is_attr(var->attrs, ATTR_IN);
1436 int out_attr = is_attr(var->attrs, ATTR_OUT);
1437 const type_t *base = is_ptr(type) ? type->ref : type;
1439 if (base->type == RPC_FC_IP)
1441 return write_ip_tfs(file, base->attrs, base->name, typeformat_offset);
1444 /* special case for pointers to base types */
1445 switch (base->type)
1447 #define CASE_BASETYPE(fctype) \
1448 case RPC_##fctype: \
1449 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n", \
1450 pointer_type, \
1451 (!in_attr && out_attr) ? 0x0C : 0x08, \
1452 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"), \
1453 (!in_attr && out_attr) ? "[allocated_on_stack] " : ""); \
1454 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
1455 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
1456 *typeformat_offset += 4; \
1457 return start_offset
1458 CASE_BASETYPE(FC_BYTE);
1459 CASE_BASETYPE(FC_CHAR);
1460 CASE_BASETYPE(FC_SMALL);
1461 CASE_BASETYPE(FC_USMALL);
1462 CASE_BASETYPE(FC_WCHAR);
1463 CASE_BASETYPE(FC_SHORT);
1464 CASE_BASETYPE(FC_USHORT);
1465 CASE_BASETYPE(FC_LONG);
1466 CASE_BASETYPE(FC_ULONG);
1467 CASE_BASETYPE(FC_FLOAT);
1468 CASE_BASETYPE(FC_HYPER);
1469 CASE_BASETYPE(FC_DOUBLE);
1470 CASE_BASETYPE(FC_ENUM16);
1471 CASE_BASETYPE(FC_ENUM32);
1472 CASE_BASETYPE(FC_IGNORE);
1473 CASE_BASETYPE(FC_ERROR_STATUS_T);
1474 default:
1475 break;
1479 assert(ptr_level > 0);
1481 if (file)
1482 fprintf(file, "/* %2u */\n", *typeformat_offset);
1483 write_pointer_only_tfs(file, var->attrs, pointer_type,
1484 1 < ptr_level ? 0x10 : 0,
1485 2, typeformat_offset);
1487 if (var_ptrs)
1488 --var_ptrs;
1489 else
1491 --type_ptrs;
1492 type = type->ref;
1498 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
1500 int indent = 0;
1501 const var_t *var;
1502 unsigned int typeformat_offset;
1503 const ifref_t *iface;
1505 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1506 print_file(file, indent, "{\n");
1507 indent++;
1508 print_file(file, indent, "0,\n");
1509 print_file(file, indent, "{\n");
1510 indent++;
1511 print_file(file, indent, "NdrFcShort(0x0),\n");
1512 typeformat_offset = 2;
1514 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
1516 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
1517 continue;
1519 if (iface->iface->funcs)
1521 const func_t *func;
1522 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
1524 if (is_local(func->def->attrs)) continue;
1525 current_func = func;
1526 if (func->args)
1527 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1528 write_typeformatstring_var(file, indent, var,
1529 &typeformat_offset);
1534 print_file(file, indent, "0x0\n");
1535 indent--;
1536 print_file(file, indent, "}\n");
1537 indent--;
1538 print_file(file, indent, "};\n");
1539 print_file(file, indent, "\n");
1542 static unsigned int get_required_buffer_size_type(
1543 const type_t *type, int ptr_level, const array_dims_t *array,
1544 const char *name, unsigned int *alignment)
1546 size_t size = 0;
1548 *alignment = 0;
1549 if (ptr_level == 0)
1551 switch (type->type)
1553 case RPC_FC_BYTE:
1554 case RPC_FC_CHAR:
1555 case RPC_FC_USMALL:
1556 case RPC_FC_SMALL:
1557 *alignment = 4;
1558 size = 1;
1559 break;
1561 case RPC_FC_WCHAR:
1562 case RPC_FC_USHORT:
1563 case RPC_FC_SHORT:
1564 *alignment = 4;
1565 size = 2;
1566 break;
1568 case RPC_FC_ULONG:
1569 case RPC_FC_LONG:
1570 case RPC_FC_FLOAT:
1571 case RPC_FC_ERROR_STATUS_T:
1572 *alignment = 4;
1573 size = 4;
1574 break;
1576 case RPC_FC_HYPER:
1577 case RPC_FC_DOUBLE:
1578 *alignment = 8;
1579 size = 8;
1580 break;
1582 case RPC_FC_IGNORE:
1583 case RPC_FC_BIND_PRIMITIVE:
1584 return 0;
1586 case RPC_FC_STRUCT:
1588 const var_t *field;
1589 if (!type->fields) return 0;
1590 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1592 unsigned int alignment;
1593 size += get_required_buffer_size_type(
1594 field->type, field->ptr_level, field->array, field->name,
1595 &alignment);
1597 break;
1600 case RPC_FC_RP:
1601 if (is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT)
1602 size = get_required_buffer_size_type( type->ref, 0, NULL, name, alignment );
1603 break;
1605 default:
1606 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1607 return 0;
1609 if (array) size *= get_array_size( array );
1611 return size;
1614 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
1616 expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1617 int has_size = (size_is && (size_is->type != EXPR_VOID));
1618 int in_attr = is_attr(var->attrs, ATTR_IN);
1619 int out_attr = is_attr(var->attrs, ATTR_OUT);
1621 if (!in_attr && !out_attr)
1622 in_attr = 1;
1624 *alignment = 0;
1626 if (pass == PASS_OUT)
1628 if (out_attr && var->ptr_level > 0)
1630 type_t *type = var->type;
1632 if (type->type == RPC_FC_STRUCT)
1634 const var_t *field;
1635 unsigned int size = 36;
1637 if (!type->fields) return size;
1638 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1640 unsigned int align;
1641 size += get_required_buffer_size_type(
1642 field->type, field->ptr_level, field->array, field->name,
1643 &align);
1645 return size;
1648 return 0;
1650 else
1652 if ((!out_attr || in_attr) && !has_size && !is_attr(var->attrs, ATTR_STRING) && !var->array)
1654 if (var->ptr_level > 0)
1656 type_t *type = var->type;
1658 if (is_base_type(type->type))
1660 return 25;
1662 else if (type->type == RPC_FC_STRUCT)
1664 unsigned int size = 36;
1665 const var_t *field;
1667 if (!type->fields) return size;
1668 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1670 unsigned int align;
1671 size += get_required_buffer_size_type(
1672 field->type, field->ptr_level, field->array, field->name,
1673 &align);
1675 return size;
1680 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
1684 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
1686 const var_t *var;
1687 unsigned int total_size = 0, alignment;
1689 if (func->args)
1691 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1693 total_size += get_required_buffer_size(var, &alignment, pass);
1694 total_size += alignment;
1698 if (pass == PASS_OUT && !is_void(func->def->type, NULL))
1700 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
1701 total_size += alignment;
1703 return total_size;
1706 static void print_phase_function(FILE *file, int indent, const char *type,
1707 enum remoting_phase phase,
1708 const char *varname, unsigned int type_offset)
1710 const char *function;
1711 switch (phase)
1713 case PHASE_BUFFERSIZE:
1714 function = "BufferSize";
1715 break;
1716 case PHASE_MARSHAL:
1717 function = "Marshall";
1718 break;
1719 case PHASE_UNMARSHAL:
1720 function = "Unmarshall";
1721 break;
1722 case PHASE_FREE:
1723 function = "Free";
1724 break;
1725 default:
1726 assert(0);
1727 return;
1730 print_file(file, indent, "Ndr%s%s(\n", type, function);
1731 indent++;
1732 print_file(file, indent, "&_StubMsg,\n");
1733 print_file(file, indent, "%s%s,\n",
1734 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)&" : "(unsigned char *)",
1735 varname);
1736 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
1737 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
1738 if (phase == PHASE_UNMARSHAL)
1739 print_file(file, indent, "0);\n");
1740 indent--;
1743 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
1744 enum pass pass, const var_t *var,
1745 const char *varname)
1747 const type_t *type = var->type;
1748 unsigned int size;
1749 unsigned int alignment = 0;
1750 unsigned char rtype;
1752 /* no work to do for other phases, buffer sizing is done elsewhere */
1753 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
1754 return;
1756 rtype = type->type;
1758 switch (rtype)
1760 case RPC_FC_BYTE:
1761 case RPC_FC_CHAR:
1762 case RPC_FC_SMALL:
1763 case RPC_FC_USMALL:
1764 size = 1;
1765 alignment = 1;
1766 break;
1768 case RPC_FC_WCHAR:
1769 case RPC_FC_USHORT:
1770 case RPC_FC_SHORT:
1771 size = 2;
1772 alignment = 2;
1773 break;
1775 case RPC_FC_ULONG:
1776 case RPC_FC_LONG:
1777 case RPC_FC_FLOAT:
1778 case RPC_FC_ERROR_STATUS_T:
1779 size = 4;
1780 alignment = 4;
1781 break;
1783 case RPC_FC_HYPER:
1784 case RPC_FC_DOUBLE:
1785 size = 8;
1786 alignment = 8;
1787 break;
1789 case RPC_FC_IGNORE:
1790 case RPC_FC_BIND_PRIMITIVE:
1791 /* no marshalling needed */
1792 return;
1794 default:
1795 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
1796 size = 0;
1799 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
1800 alignment - 1, alignment - 1);
1802 if (phase == PHASE_MARSHAL)
1804 print_file(file, indent, "*(");
1805 write_type(file, var->type, NULL, var->tname);
1806 if (var->ptr_level)
1807 fprintf(file, " *)_StubMsg.Buffer = *");
1808 else
1809 fprintf(file, " *)_StubMsg.Buffer = ");
1810 fprintf(file, varname);
1811 fprintf(file, ";\n");
1813 else if (phase == PHASE_UNMARSHAL)
1815 if (pass == PASS_IN || pass == PASS_RETURN)
1816 print_file(file, indent, "");
1817 else
1818 print_file(file, indent, "*");
1819 fprintf(file, varname);
1820 if (pass == PASS_IN && var->ptr_level)
1821 fprintf(file, " = (");
1822 else
1823 fprintf(file, " = *(");
1824 write_type(file, var->type, NULL, var->tname);
1825 fprintf(file, " *)_StubMsg.Buffer;\n");
1828 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1829 write_type(file, var->type, NULL, var->tname);
1830 fprintf(file, ");\n");
1833 /* returns whether the MaxCount, Offset or ActualCount members need to be
1834 * filled in for the specified phase */
1835 static inline int is_size_needed_for_phase(enum remoting_phase phase)
1837 return (phase != PHASE_UNMARSHAL);
1840 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
1841 unsigned int *type_offset, enum pass pass,
1842 enum remoting_phase phase)
1844 const expr_t *length_is;
1845 const expr_t *size_is;
1846 int in_attr, out_attr, has_length, has_size, pointer_type;
1847 const var_t *var;
1849 if (!func->args)
1850 return;
1852 if (phase == PHASE_BUFFERSIZE)
1854 unsigned int size = get_function_buffer_size( func, pass );
1855 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
1858 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1860 const type_t *type = var->type;
1861 unsigned char rtype;
1863 length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1864 size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1865 has_length = length_is && (length_is->type != EXPR_VOID);
1866 has_size = (size_is && (size_is->type != EXPR_VOID)) || (var->array && is_conformant_array(var->array));
1868 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
1869 if (!pointer_type)
1870 pointer_type = RPC_FC_RP;
1872 in_attr = is_attr(var->attrs, ATTR_IN);
1873 out_attr = is_attr(var->attrs, ATTR_OUT);
1874 if (!in_attr && !out_attr)
1875 in_attr = 1;
1877 switch (pass)
1879 case PASS_IN:
1880 if (!in_attr) goto next;
1881 break;
1882 case PASS_OUT:
1883 if (!out_attr) goto next;
1884 break;
1885 case PASS_RETURN:
1886 break;
1889 rtype = type->type;
1891 if (is_user_derived( var ))
1893 print_phase_function(file, indent, "UserMarshal", phase, var->name, *type_offset);
1895 else if (is_string_type(var->attrs, var->ptr_level, var->array))
1897 if (var->array && !is_conformant_array(var->array))
1898 print_phase_function(file, indent, "NonConformantString", phase, var->name, *type_offset);
1899 else
1901 if (size_is && is_size_needed_for_phase(phase))
1903 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1904 write_expr(file, size_is, 1);
1905 fprintf(file, ";\n");
1908 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
1909 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
1910 else
1911 print_phase_function(file, indent, "ConformantString", phase, var->name,
1912 *type_offset + (has_size ? 4 : 2));
1915 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1917 const char *array_type;
1919 if (var->array && list_count(var->array) > 1) /* multi-dimensional array */
1920 array_type = "ComplexArray";
1921 else
1923 const expr_t *dim = LIST_ENTRY( list_head( var->array ), expr_t, entry );
1924 if (!has_length && !has_size)
1925 array_type = "FixedArray";
1926 else if (has_length && !has_size)
1928 if (is_size_needed_for_phase(phase))
1930 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1931 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1932 write_expr(file, length_is, 1);
1933 fprintf(file, ";\n\n");
1935 array_type = "VaryingArray";
1937 else if (!has_length && has_size)
1939 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
1941 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1942 write_expr(file, size_is ? size_is : dim, 1);
1943 fprintf(file, ";\n\n");
1945 array_type = "ConformantArray";
1947 else
1949 if (is_size_needed_for_phase(phase))
1951 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1952 write_expr(file, size_is ? size_is : dim, 1);
1953 fprintf(file, ";\n");
1954 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1955 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1956 write_expr(file, length_is, 1);
1957 fprintf(file, ";\n\n");
1959 array_type = "ConformantVaryingArray";
1963 if (!in_attr && phase == PHASE_FREE)
1965 print_file(file, indent, "if (%s)\n", var->name);
1966 indent++;
1967 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
1969 else if (phase != PHASE_FREE)
1971 if (pointer_type == RPC_FC_UP)
1972 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
1973 else
1974 print_phase_function(file, indent, array_type, phase, var->name, *type_offset + 4);
1977 else if (var->ptr_level == 0 && is_base_type(rtype))
1979 print_phase_basetype(file, indent, phase, pass, var, var->name);
1981 else if (var->ptr_level == 0)
1983 switch (rtype)
1985 case RPC_FC_STRUCT:
1986 print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset);
1987 break;
1988 case RPC_FC_CSTRUCT:
1989 case RPC_FC_CPSTRUCT:
1990 print_phase_function(file, indent, "ConformantStruct", phase, var->name, *type_offset);
1991 break;
1992 case RPC_FC_CVSTRUCT:
1993 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var->name, *type_offset);
1994 break;
1995 case RPC_FC_BOGUS_STRUCT:
1996 print_phase_function(file, indent, "ComplexStruct", phase, var->name, *type_offset);
1997 break;
1998 case RPC_FC_RP:
1999 if (is_base_type( var->type->ref->type ))
2001 print_phase_basetype(file, indent, phase, pass, var, var->name);
2003 else if (var->type->ref->type == RPC_FC_STRUCT)
2005 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2006 print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset + 4);
2008 else
2010 const var_t *iid;
2011 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2012 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2013 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
2015 break;
2016 default:
2017 error("write_remoting_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
2018 var->name, rtype, var->ptr_level);
2021 else
2023 if ((var->ptr_level == 1) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2025 print_phase_basetype(file, indent, phase, pass, var, var->name);
2027 else if ((var->ptr_level == 1) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2029 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2030 print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset + 4);
2032 else
2034 const var_t *iid;
2035 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2036 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2037 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
2040 fprintf(file, "\n");
2041 next:
2042 *type_offset += get_size_typeformatstring_var(var);
2047 size_t get_size_procformatstring_var(const var_t *var)
2049 unsigned int type_offset = 2;
2050 return write_procformatstring_var(NULL, 0, var, FALSE, &type_offset);
2054 size_t get_size_procformatstring_func(const func_t *func)
2056 const var_t *var;
2057 size_t size = 0;
2059 /* argument list size */
2060 if (func->args)
2061 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2062 size += get_size_procformatstring_var(var);
2064 /* return value size */
2065 if (is_void(func->def->type, NULL))
2066 size += 2; /* FC_END and FC_PAD */
2067 else
2068 size += get_size_procformatstring_var(func->def);
2070 return size;
2073 size_t get_size_typeformatstring_var(const var_t *var)
2075 unsigned int type_offset = 0;
2076 write_typeformatstring_var(NULL, 0, var, &type_offset);
2077 return type_offset;
2080 size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects)
2082 const ifref_t *iface;
2083 size_t size = 1;
2084 const func_t *func;
2086 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2088 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2089 continue;
2091 if (iface->iface->funcs)
2092 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2093 if (!is_local(func->def->attrs))
2094 size += get_size_procformatstring_func( func );
2096 return size;
2099 size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects)
2101 const ifref_t *iface;
2102 size_t size = 3;
2103 const func_t *func;
2104 const var_t *var;
2106 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2108 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2109 continue;
2111 if (iface->iface->funcs)
2113 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2115 if (is_local(func->def->attrs)) continue;
2116 /* argument list size */
2117 if (func->args)
2118 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2119 size += get_size_typeformatstring_var(var);
2123 return size;
2126 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2127 const var_list_t *fields, const char *structvar)
2129 switch (e->type) {
2130 case EXPR_VOID:
2131 break;
2132 case EXPR_NUM:
2133 fprintf(h, "%ld", e->u.lval);
2134 break;
2135 case EXPR_HEXNUM:
2136 fprintf(h, "0x%lx", e->u.lval);
2137 break;
2138 case EXPR_TRUEFALSE:
2139 if (e->u.lval == 0)
2140 fprintf(h, "FALSE");
2141 else
2142 fprintf(h, "TRUE");
2143 break;
2144 case EXPR_IDENTIFIER:
2146 const var_t *field;
2147 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2148 if (!strcmp(e->u.sval, field->name))
2150 fprintf(h, "%s->%s", structvar, e->u.sval);
2151 break;
2154 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2155 break;
2157 case EXPR_NEG:
2158 fprintf(h, "-");
2159 write_struct_expr(h, e->ref, 1, fields, structvar);
2160 break;
2161 case EXPR_NOT:
2162 fprintf(h, "~");
2163 write_struct_expr(h, e->ref, 1, fields, structvar);
2164 break;
2165 case EXPR_PPTR:
2166 fprintf(h, "*");
2167 write_struct_expr(h, e->ref, 1, fields, structvar);
2168 break;
2169 case EXPR_CAST:
2170 fprintf(h, "(");
2171 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
2172 fprintf(h, ")");
2173 write_struct_expr(h, e->ref, 1, fields, structvar);
2174 break;
2175 case EXPR_SIZEOF:
2176 fprintf(h, "sizeof(");
2177 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
2178 fprintf(h, ")");
2179 break;
2180 case EXPR_SHL:
2181 case EXPR_SHR:
2182 case EXPR_MUL:
2183 case EXPR_DIV:
2184 case EXPR_ADD:
2185 case EXPR_SUB:
2186 case EXPR_AND:
2187 case EXPR_OR:
2188 if (brackets) fprintf(h, "(");
2189 write_struct_expr(h, e->ref, 1, fields, structvar);
2190 switch (e->type) {
2191 case EXPR_SHL: fprintf(h, " << "); break;
2192 case EXPR_SHR: fprintf(h, " >> "); break;
2193 case EXPR_MUL: fprintf(h, " * "); break;
2194 case EXPR_DIV: fprintf(h, " / "); break;
2195 case EXPR_ADD: fprintf(h, " + "); break;
2196 case EXPR_SUB: fprintf(h, " - "); break;
2197 case EXPR_AND: fprintf(h, " & "); break;
2198 case EXPR_OR: fprintf(h, " | "); break;
2199 default: break;
2201 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2202 if (brackets) fprintf(h, ")");
2203 break;
2204 case EXPR_COND:
2205 if (brackets) fprintf(h, "(");
2206 write_struct_expr(h, e->ref, 1, fields, structvar);
2207 fprintf(h, " ? ");
2208 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2209 fprintf(h, " : ");
2210 write_struct_expr(h, e->ext2, 1, fields, structvar);
2211 if (brackets) fprintf(h, ")");
2212 break;
2217 void declare_stub_args( FILE *file, int indent, const func_t *func )
2219 int in_attr, out_attr;
2220 int i = 0;
2221 const var_t *def = func->def;
2222 const var_t *var;
2224 /* declare return value '_RetVal' */
2225 if (!is_void(def->type, NULL))
2227 print_file(file, indent, "");
2228 write_type(file, def->type, def, def->tname);
2229 fprintf(file, " _RetVal;\n");
2232 if (!func->args)
2233 return;
2235 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2237 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
2238 int has_size = size_is && (size_is->type != EXPR_VOID);
2239 int is_string = is_attr(var->attrs, ATTR_STRING);
2241 in_attr = is_attr(var->attrs, ATTR_IN);
2242 out_attr = is_attr(var->attrs, ATTR_OUT);
2243 if (!out_attr && !in_attr)
2244 in_attr = 1;
2246 if (!in_attr && !has_size && !is_string)
2248 int indirection;
2249 print_file(file, indent, "");
2250 write_type(file, var->type, NULL, var->tname);
2251 for (indirection = 0; indirection < var->ptr_level - 1; indirection++)
2252 fprintf(file, "*");
2253 fprintf(file, " _W%u;\n", i++);
2256 print_file(file, indent, "");
2257 write_type(file, var->type, var, var->tname);
2258 fprintf(file, " ");
2259 write_name(file, var);
2260 write_array(file, var->array, 0);
2261 fprintf(file, ";\n");
2266 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
2268 int in_attr, out_attr;
2269 int i = 0, sep = 0;
2270 const var_t *var;
2271 const expr_t *size_is;
2272 int has_size;
2274 if (!func->args)
2275 return;
2277 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2279 int is_string = is_attr(var->attrs, ATTR_STRING);
2280 size_is = get_attrp(var->attrs, ATTR_SIZEIS);
2281 has_size = size_is && (size_is->type != EXPR_VOID);
2282 in_attr = is_attr(var->attrs, ATTR_IN);
2283 out_attr = is_attr(var->attrs, ATTR_OUT);
2284 if (!out_attr && !in_attr)
2285 in_attr = 1;
2287 if (!in_attr)
2289 print_file(file, indent, "");
2290 write_name(file, var);
2292 if (has_size)
2294 unsigned int size, align = 0;
2295 type_t *type = var->type;
2297 fprintf(file, " = NdrAllocate(&_StubMsg, ");
2298 write_expr(file, size_is, 1);
2299 size = type_memsize(type, 0, NULL, &align);
2300 fprintf(file, " * %u);\n", size);
2302 else if (!is_string)
2304 fprintf(file, " = &_W%u;\n", i);
2305 if (var->ptr_level > 1)
2306 print_file(file, indent, "_W%u = 0;\n", i);
2307 i++;
2310 sep = 1;
2313 if (sep)
2314 fprintf(file, "\n");
2318 int write_expr_eval_routines(FILE *file, const char *iface)
2320 int result = 0;
2321 struct expr_eval_routine *eval;
2322 unsigned short callback_offset = 0;
2324 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
2326 int indent = 0;
2327 result = 1;
2328 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2329 iface, eval->structure->name, callback_offset);
2330 print_file(file, indent, "{\n");
2331 indent++;
2332 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
2333 eval->structure->name, eval->structure->name, eval->structure_size);
2334 fprintf(file, "\n");
2335 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
2336 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
2337 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
2338 fprintf(file, ";\n");
2339 indent--;
2340 print_file(file, indent, "}\n\n");
2341 callback_offset++;
2343 return result;
2346 void write_expr_eval_routine_list(FILE *file, const char *iface)
2348 struct expr_eval_routine *eval;
2349 struct expr_eval_routine *cursor;
2350 unsigned short callback_offset = 0;
2352 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2353 fprintf(file, "{\n");
2355 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
2357 print_file(file, 1, "%s_%sExprEval_%04u,\n",
2358 iface, eval->structure->name, callback_offset);
2360 callback_offset++;
2361 list_remove(&eval->entry);
2362 free(eval);
2365 fprintf(file, "};\n\n");