push f98ef5dce4886db1f9801e7c454145e1b633b4ff
[wine/hacks.git] / tools / widl / typegen.c
blobdee5ad8ec0352f019f64c7f8f958d324dd847711
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 "wine/list.h"
42 #include "typegen.h"
44 static const func_t *current_func;
45 static const type_t *current_structure;
47 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
48 struct expr_eval_routine
50 struct list entry;
51 const type_t *structure;
52 unsigned int baseoff;
53 const expr_t *expr;
56 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
57 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
58 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
59 const char *name, int write_ptr, unsigned int *tfsoff);
60 static const var_t *find_array_or_string_in_struct(const type_t *type);
62 const char *string_of_type(unsigned char type)
64 switch (type)
66 case RPC_FC_BYTE: return "FC_BYTE";
67 case RPC_FC_CHAR: return "FC_CHAR";
68 case RPC_FC_SMALL: return "FC_SMALL";
69 case RPC_FC_USMALL: return "FC_USMALL";
70 case RPC_FC_WCHAR: return "FC_WCHAR";
71 case RPC_FC_SHORT: return "FC_SHORT";
72 case RPC_FC_USHORT: return "FC_USHORT";
73 case RPC_FC_LONG: return "FC_LONG";
74 case RPC_FC_ULONG: return "FC_ULONG";
75 case RPC_FC_FLOAT: return "FC_FLOAT";
76 case RPC_FC_HYPER: return "FC_HYPER";
77 case RPC_FC_DOUBLE: return "FC_DOUBLE";
78 case RPC_FC_ENUM16: return "FC_ENUM16";
79 case RPC_FC_ENUM32: return "FC_ENUM32";
80 case RPC_FC_IGNORE: return "FC_IGNORE";
81 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
82 case RPC_FC_RP: return "FC_RP";
83 case RPC_FC_UP: return "FC_UP";
84 case RPC_FC_OP: return "FC_OP";
85 case RPC_FC_FP: return "FC_FP";
86 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
87 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
88 case RPC_FC_STRUCT: return "FC_STRUCT";
89 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
90 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
91 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
92 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
93 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
94 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
95 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
96 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
97 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
98 case RPC_FC_CARRAY: return "FC_CARRAY";
99 case RPC_FC_CVARRAY: return "FC_CVARRAY";
100 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
101 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
102 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
103 case RPC_FC_POINTER: return "FC_POINTER";
104 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
105 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
106 case RPC_FC_CSTRING: return "FC_CSTRING";
107 case RPC_FC_WSTRING: return "FC_WSTRING";
108 default:
109 error("string_of_type: unknown type 0x%02x\n", type);
110 return NULL;
114 int is_struct(unsigned char type)
116 switch (type)
118 case RPC_FC_STRUCT:
119 case RPC_FC_PSTRUCT:
120 case RPC_FC_CSTRUCT:
121 case RPC_FC_CPSTRUCT:
122 case RPC_FC_CVSTRUCT:
123 case RPC_FC_BOGUS_STRUCT:
124 return 1;
125 default:
126 return 0;
130 static int is_non_complex_struct(const type_t *type)
132 switch (type->type)
134 case RPC_FC_STRUCT:
135 case RPC_FC_PSTRUCT:
136 case RPC_FC_CSTRUCT:
137 case RPC_FC_CPSTRUCT:
138 case RPC_FC_CVSTRUCT:
139 return 1;
140 default:
141 return 0;
145 int is_union(unsigned char type)
147 switch (type)
149 case RPC_FC_ENCAPSULATED_UNION:
150 case RPC_FC_NON_ENCAPSULATED_UNION:
151 return 1;
152 default:
153 return 0;
157 static int type_has_pointers(const type_t *type)
159 if (is_user_type(type))
160 return FALSE;
161 else if (is_ptr(type))
162 return TRUE;
163 else if (is_array(type))
164 return type_has_pointers(type->ref);
165 else if (is_struct(type->type))
167 const var_t *field;
168 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
170 if (type_has_pointers(field->type))
171 return TRUE;
174 else if (is_union(type->type))
176 var_list_t *fields;
177 const var_t *field;
178 if (type->type == RPC_FC_ENCAPSULATED_UNION)
180 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
181 fields = uv->type->fields;
183 else
184 fields = type->fields;
185 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
187 if (field->type && type_has_pointers(field->type))
188 return TRUE;
192 return FALSE;
195 static unsigned short user_type_offset(const char *name)
197 user_type_t *ut;
198 unsigned short off = 0;
199 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
201 if (strcmp(name, ut->name) == 0)
202 return off;
203 ++off;
205 error("user_type_offset: couldn't find type (%s)\n", name);
206 return 0;
209 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
211 type->typestring_offset = offset;
212 if (file) type->tfswrite = FALSE;
215 static void guard_rec(type_t *type)
217 /* types that contain references to themselves (like a linked list),
218 need to be shielded from infinite recursion when writing embedded
219 types */
220 if (type->typestring_offset)
221 type->tfswrite = FALSE;
222 else
223 type->typestring_offset = 1;
226 static type_t *get_user_type(const type_t *t, const char **pname)
228 for (;;)
230 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
231 if (ut)
233 if (pname)
234 *pname = t->name;
235 return ut;
238 if (t->kind == TKIND_ALIAS)
239 t = t->orig;
240 else
241 return 0;
245 int is_user_type(const type_t *t)
247 return get_user_type(t, NULL) != NULL;
250 static int is_embedded_complex(const type_t *type)
252 unsigned char tc = type->type;
253 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
254 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
257 static const char *get_context_handle_type_name(const type_t *type)
259 const type_t *t;
260 for (t = type; is_ptr(t); t = t->ref)
261 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
262 return t->name;
263 assert(0);
264 return NULL;
267 /* This is actually fairly involved to implement precisely, due to the
268 effects attributes may have and things like that. Right now this is
269 only used for optimization, so just check for a very small set of
270 criteria that guarantee the types are equivalent; assume every thing
271 else is different. */
272 static int compare_type(const type_t *a, const type_t *b)
274 if (a == b
275 || (a->name
276 && b->name
277 && strcmp(a->name, b->name) == 0))
278 return 0;
279 /* Ordering doesn't need to be implemented yet. */
280 return 1;
283 static int compare_expr(const expr_t *a, const expr_t *b)
285 int ret;
287 if (a->type != b->type)
288 return a->type - b->type;
290 switch (a->type)
292 case EXPR_NUM:
293 case EXPR_HEXNUM:
294 case EXPR_TRUEFALSE:
295 return a->u.lval - b->u.lval;
296 case EXPR_DOUBLE:
297 return a->u.dval - b->u.dval;
298 case EXPR_IDENTIFIER:
299 return strcmp(a->u.sval, b->u.sval);
300 case EXPR_COND:
301 ret = compare_expr(a->ref, b->ref);
302 if (ret != 0)
303 return ret;
304 ret = compare_expr(a->u.ext, b->u.ext);
305 if (ret != 0)
306 return ret;
307 return compare_expr(a->ext2, b->ext2);
308 case EXPR_OR:
309 case EXPR_AND:
310 case EXPR_ADD:
311 case EXPR_SUB:
312 case EXPR_MUL:
313 case EXPR_DIV:
314 case EXPR_SHL:
315 case EXPR_SHR:
316 ret = compare_expr(a->ref, b->ref);
317 if (ret != 0)
318 return ret;
319 return compare_expr(a->u.ext, b->u.ext);
320 case EXPR_CAST:
321 ret = compare_type(a->u.tref, b->u.tref);
322 if (ret != 0)
323 return ret;
324 /* Fall through. */
325 case EXPR_NOT:
326 case EXPR_NEG:
327 case EXPR_PPTR:
328 case EXPR_ADDRESSOF:
329 return compare_expr(a->ref, b->ref);
330 case EXPR_SIZEOF:
331 return compare_type(a->u.tref, b->u.tref);
332 case EXPR_VOID:
333 return 0;
335 return -1;
338 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
339 do { \
340 if (file) \
341 fprintf(file, "/* %2u */\n", typestring_offset); \
342 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
344 while (0)
346 static void print_file(FILE *file, int indent, const char *format, ...)
348 va_list va;
349 va_start(va, format);
350 print(file, indent, format, va);
351 va_end(va);
354 void print(FILE *file, int indent, const char *format, va_list va)
356 if (file)
358 if (format[0] != '\n')
359 while (0 < indent--)
360 fprintf(file, " ");
361 vfprintf(file, format, va);
366 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n)
368 if (decl_indirect(t))
369 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof(%s));\n", n, n);
370 else if (is_ptr(t) || is_array(t))
371 print_file(file, indent, "%s = 0;\n", n);
374 void write_parameters_init(FILE *file, int indent, const func_t *func)
376 const var_t *var;
378 if (!is_void(func->def->type))
379 write_var_init(file, indent, func->def->type, "_RetVal");
381 if (!func->args)
382 return;
384 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
385 write_var_init(file, indent, var->type, var->name);
387 fprintf(file, "\n");
390 static void write_formatdesc(FILE *f, int indent, const char *str)
392 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
393 print_file(f, indent, "{\n");
394 print_file(f, indent + 1, "short Pad;\n");
395 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
396 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
397 print_file(f, indent, "\n");
400 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
402 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
403 get_size_typeformatstring(ifaces, pred));
405 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
406 get_size_procformatstring(ifaces, pred));
408 fprintf(f, "\n");
409 write_formatdesc(f, indent, "TYPE");
410 write_formatdesc(f, indent, "PROC");
411 fprintf(f, "\n");
412 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
413 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
414 print_file(f, indent, "\n");
417 static inline int is_base_type(unsigned char type)
419 switch (type)
421 case RPC_FC_BYTE:
422 case RPC_FC_CHAR:
423 case RPC_FC_USMALL:
424 case RPC_FC_SMALL:
425 case RPC_FC_WCHAR:
426 case RPC_FC_USHORT:
427 case RPC_FC_SHORT:
428 case RPC_FC_ULONG:
429 case RPC_FC_LONG:
430 case RPC_FC_HYPER:
431 case RPC_FC_IGNORE:
432 case RPC_FC_FLOAT:
433 case RPC_FC_DOUBLE:
434 case RPC_FC_ENUM16:
435 case RPC_FC_ENUM32:
436 case RPC_FC_ERROR_STATUS_T:
437 case RPC_FC_BIND_PRIMITIVE:
438 return TRUE;
440 default:
441 return FALSE;
445 int decl_indirect(const type_t *t)
447 return is_user_type(t)
448 || (!is_base_type(t->type)
449 && !is_ptr(t)
450 && !is_array(t));
453 static size_t write_procformatstring_var(FILE *file, int indent,
454 const var_t *var, int is_return)
456 size_t size;
457 const type_t *type = var->type;
459 int is_in = is_attr(var->attrs, ATTR_IN);
460 int is_out = is_attr(var->attrs, ATTR_OUT);
462 if (!is_in && !is_out) is_in = TRUE;
464 if (!type->declarray && is_base_type(type->type))
466 if (is_return)
467 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
468 else
469 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
471 if (type->type == RPC_FC_BIND_PRIMITIVE)
473 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
474 size = 2; /* includes param type prefix */
476 else if (is_base_type(type->type))
478 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
479 size = 2; /* includes param type prefix */
481 else
483 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
484 size = 0;
487 else
489 if (is_return)
490 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
491 else if (is_in && is_out)
492 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
493 else if (is_out)
494 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
495 else
496 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
498 print_file(file, indent, "0x01,\n");
499 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
500 size = 4; /* includes param type prefix */
502 return size;
505 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
507 const ifref_t *iface;
508 int indent = 0;
509 const var_t *var;
511 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
512 print_file(file, indent, "{\n");
513 indent++;
514 print_file(file, indent, "0,\n");
515 print_file(file, indent, "{\n");
516 indent++;
518 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
520 if (!pred(iface->iface))
521 continue;
523 if (iface->iface->funcs)
525 const func_t *func;
526 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
528 if (is_local(func->def->attrs)) continue;
529 /* emit argument data */
530 if (func->args)
532 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
533 write_procformatstring_var(file, indent, var, FALSE);
536 /* emit return value data */
537 var = func->def;
538 if (is_void(var->type))
540 print_file(file, indent, "0x5b, /* FC_END */\n");
541 print_file(file, indent, "0x5c, /* FC_PAD */\n");
543 else
544 write_procformatstring_var(file, indent, var, TRUE);
549 print_file(file, indent, "0x0\n");
550 indent--;
551 print_file(file, indent, "}\n");
552 indent--;
553 print_file(file, indent, "};\n");
554 print_file(file, indent, "\n");
557 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
559 if (is_base_type(type->type))
561 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
562 *typestring_offset += 1;
563 return 1;
566 return 0;
569 /* write conformance / variance descriptor */
570 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
571 unsigned int baseoff, const type_t *type,
572 const expr_t *expr)
574 unsigned char operator_type = 0;
575 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
576 const char *conftype_string = "";
577 const char *operator_string = "no operators";
578 const expr_t *subexpr;
580 if (!expr)
582 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
583 return 4;
586 if (!structure)
588 /* Top-level conformance calculations are done inline. */
589 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
590 RPC_FC_TOP_LEVEL_CONFORMANCE);
591 print_file (file, 2, "0x0,\n");
592 print_file (file, 2, "NdrFcShort(0x0),\n");
593 return 4;
596 if (expr->is_const)
598 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
599 error("write_conf_or_var_desc: constant value %ld is greater than "
600 "the maximum constant size of %d\n", expr->cval,
601 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
603 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
604 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
605 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
606 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
608 return 4;
611 if (is_ptr(type) || (is_array(type) && !type->declarray))
613 conftype = RPC_FC_POINTER_CONFORMANCE;
614 conftype_string = "field pointer, ";
617 subexpr = expr;
618 switch (subexpr->type)
620 case EXPR_PPTR:
621 subexpr = subexpr->ref;
622 operator_type = RPC_FC_DEREFERENCE;
623 operator_string = "FC_DEREFERENCE";
624 break;
625 case EXPR_DIV:
626 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
628 subexpr = subexpr->ref;
629 operator_type = RPC_FC_DIV_2;
630 operator_string = "FC_DIV_2";
632 break;
633 case EXPR_MUL:
634 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
636 subexpr = subexpr->ref;
637 operator_type = RPC_FC_MULT_2;
638 operator_string = "FC_MULT_2";
640 break;
641 case EXPR_SUB:
642 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
644 subexpr = subexpr->ref;
645 operator_type = RPC_FC_SUB_1;
646 operator_string = "FC_SUB_1";
648 break;
649 case EXPR_ADD:
650 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
652 subexpr = subexpr->ref;
653 operator_type = RPC_FC_ADD_1;
654 operator_string = "FC_ADD_1";
656 break;
657 default:
658 break;
661 if (subexpr->type == EXPR_IDENTIFIER)
663 const type_t *correlation_variable = NULL;
664 unsigned char correlation_variable_type;
665 unsigned char param_type = 0;
666 size_t offset = 0;
667 const var_t *var;
669 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
671 unsigned int align = 0;
672 /* FIXME: take alignment into account */
673 if (var->name && !strcmp(var->name, subexpr->u.sval))
675 correlation_variable = var->type;
676 break;
678 offset += type_memsize(var->type, &align);
680 if (!correlation_variable)
681 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
682 subexpr->u.sval);
684 offset -= baseoff;
685 correlation_variable_type = correlation_variable->type;
687 switch (correlation_variable_type)
689 case RPC_FC_CHAR:
690 case RPC_FC_SMALL:
691 param_type = RPC_FC_SMALL;
692 break;
693 case RPC_FC_BYTE:
694 case RPC_FC_USMALL:
695 param_type = RPC_FC_USMALL;
696 break;
697 case RPC_FC_WCHAR:
698 case RPC_FC_SHORT:
699 case RPC_FC_ENUM16:
700 param_type = RPC_FC_SHORT;
701 break;
702 case RPC_FC_USHORT:
703 param_type = RPC_FC_USHORT;
704 break;
705 case RPC_FC_LONG:
706 case RPC_FC_ENUM32:
707 param_type = RPC_FC_LONG;
708 break;
709 case RPC_FC_ULONG:
710 param_type = RPC_FC_ULONG;
711 break;
712 case RPC_FC_RP:
713 case RPC_FC_UP:
714 case RPC_FC_OP:
715 case RPC_FC_FP:
716 if (sizeof(void *) == 4) /* FIXME */
717 param_type = RPC_FC_LONG;
718 else
719 param_type = RPC_FC_HYPER;
720 break;
721 default:
722 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
723 correlation_variable_type);
726 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
727 conftype | param_type, conftype_string, string_of_type(param_type));
728 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
729 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
730 offset, offset);
732 else
734 unsigned int callback_offset = 0;
735 struct expr_eval_routine *eval;
736 int found = 0;
738 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
740 if (!strcmp (eval->structure->name, structure->name)
741 && !compare_expr (eval->expr, expr))
743 found = 1;
744 break;
746 callback_offset++;
749 if (!found)
751 eval = xmalloc (sizeof(*eval));
752 eval->structure = structure;
753 eval->baseoff = baseoff;
754 eval->expr = expr;
755 list_add_tail (&expr_eval_routines, &eval->entry);
758 if (callback_offset > USHRT_MAX)
759 error("Maximum number of callback routines reached\n");
761 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
762 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
763 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
765 return 4;
768 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
770 int have_align = FALSE;
771 size_t size = 0;
772 const var_t *v;
774 if (!fields) return 0;
775 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
777 unsigned int falign = 0;
778 size_t fsize = type_memsize(v->type, &falign);
779 if (!have_align)
781 *align = falign;
782 have_align = TRUE;
784 size = (size + (falign - 1)) & ~(falign - 1);
785 size += fsize;
788 size = (size + (*align - 1)) & ~(*align - 1);
789 return size;
792 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
794 size_t size, maxs = 0;
795 unsigned int align = *pmaxa;
796 const var_t *v;
798 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
800 /* we could have an empty default field with NULL type */
801 if (v->type)
803 size = type_memsize(v->type, &align);
804 if (maxs < size) maxs = size;
805 if (*pmaxa < align) *pmaxa = align;
809 return maxs;
812 int get_padding(const var_list_t *fields)
814 unsigned short offset = 0;
815 int salign = -1;
816 const var_t *f;
818 if (!fields)
819 return 0;
821 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
823 type_t *ft = f->type;
824 unsigned int align = 0;
825 size_t size = type_memsize(ft, &align);
826 if (salign == -1)
827 salign = align;
828 offset = (offset + (align - 1)) & ~(align - 1);
829 offset += size;
832 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
835 size_t type_memsize(const type_t *t, unsigned int *align)
837 size_t size = 0;
839 if (t->declarray && is_conformant_array(t))
841 type_memsize(t->ref, align);
842 size = 0;
844 else if (is_ptr(t) || is_conformant_array(t))
846 size = sizeof(void *);
847 if (size > *align) *align = size;
849 else switch (t->type)
851 case RPC_FC_BYTE:
852 case RPC_FC_CHAR:
853 case RPC_FC_USMALL:
854 case RPC_FC_SMALL:
855 size = 1;
856 if (size > *align) *align = size;
857 break;
858 case RPC_FC_WCHAR:
859 case RPC_FC_USHORT:
860 case RPC_FC_SHORT:
861 case RPC_FC_ENUM16:
862 size = 2;
863 if (size > *align) *align = size;
864 break;
865 case RPC_FC_ULONG:
866 case RPC_FC_LONG:
867 case RPC_FC_ERROR_STATUS_T:
868 case RPC_FC_ENUM32:
869 case RPC_FC_FLOAT:
870 size = 4;
871 if (size > *align) *align = size;
872 break;
873 case RPC_FC_HYPER:
874 case RPC_FC_DOUBLE:
875 size = 8;
876 if (size > *align) *align = size;
877 break;
878 case RPC_FC_STRUCT:
879 case RPC_FC_CVSTRUCT:
880 case RPC_FC_CPSTRUCT:
881 case RPC_FC_CSTRUCT:
882 case RPC_FC_PSTRUCT:
883 case RPC_FC_BOGUS_STRUCT:
884 size = fields_memsize(t->fields, align);
885 break;
886 case RPC_FC_ENCAPSULATED_UNION:
887 case RPC_FC_NON_ENCAPSULATED_UNION:
888 size = union_memsize(t->fields, align);
889 break;
890 case RPC_FC_SMFARRAY:
891 case RPC_FC_LGFARRAY:
892 case RPC_FC_SMVARRAY:
893 case RPC_FC_LGVARRAY:
894 case RPC_FC_BOGUS_ARRAY:
895 size = t->dim * type_memsize(t->ref, align);
896 break;
897 default:
898 error("type_memsize: Unknown type %d\n", t->type);
899 size = 0;
902 return size;
905 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
907 short absoff = type->ref->typestring_offset;
908 short reloff = absoff - (offset + 2);
909 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
911 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
912 type->type, ptr_attr, string_of_type(type->type));
913 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
914 reloff, reloff, absoff);
915 return 4;
918 static unsigned char conf_string_type_of_char_type(unsigned char t)
920 switch (t)
922 case RPC_FC_BYTE:
923 case RPC_FC_CHAR:
924 return RPC_FC_C_CSTRING;
925 case RPC_FC_WCHAR:
926 return RPC_FC_C_WSTRING;
929 error("string_type_of_char_type: unrecognized type %d\n", t);
930 return 0;
933 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
935 unsigned char fc
936 = is_string_type(type->attrs, type)
937 ? conf_string_type_of_char_type(type->ref->type)
938 : type->ref->type;
939 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
940 type->type, string_of_type(type->type));
941 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
942 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
943 return 4;
946 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
948 print_file(file, 0, "/* %u (", tfsoff);
949 write_type_decl(file, t, NULL);
950 print_file(file, 0, ") */\n");
953 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
955 unsigned int offset = *typestring_offset;
957 print_start_tfs_comment(file, type, offset);
958 update_tfsoff(type, offset, file);
960 if (type->ref->typestring_offset)
961 *typestring_offset += write_nonsimple_pointer(file, type, offset);
962 else if (is_base_type(type->ref->type))
963 *typestring_offset += write_simple_pointer(file, type);
965 return offset;
968 static int processed(const type_t *type)
970 return type->typestring_offset && !type->tfswrite;
973 static int user_type_has_variable_size(const type_t *t)
975 if (is_ptr(t))
976 return TRUE;
977 else
978 switch (t->type)
980 case RPC_FC_PSTRUCT:
981 case RPC_FC_CSTRUCT:
982 case RPC_FC_CPSTRUCT:
983 case RPC_FC_CVSTRUCT:
984 return TRUE;
986 /* Note: Since this only applies to user types, we can't have a conformant
987 array here, and strings should get filed under pointer in this case. */
988 return FALSE;
991 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
993 unsigned int start, absoff, flags;
994 unsigned int align = 0, ualign = 0;
995 const char *name;
996 type_t *utype = get_user_type(type, &name);
997 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
998 size_t size = type_memsize(type, &align);
999 unsigned short funoff = user_type_offset(name);
1000 short reloff;
1002 guard_rec(type);
1004 if (is_base_type(utype->type))
1006 absoff = *tfsoff;
1007 print_start_tfs_comment(file, utype, absoff);
1008 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
1009 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1010 *tfsoff += 2;
1012 else
1014 if (!processed(utype))
1015 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
1016 absoff = utype->typestring_offset;
1019 if (utype->type == RPC_FC_RP)
1020 flags = 0x40;
1021 else if (utype->type == RPC_FC_UP)
1022 flags = 0x80;
1023 else
1024 flags = 0;
1026 start = *tfsoff;
1027 update_tfsoff(type, start, file);
1028 print_start_tfs_comment(file, type, start);
1029 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
1030 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1031 flags | (align - 1), align - 1, flags);
1032 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
1033 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
1034 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
1035 *tfsoff += 8;
1036 reloff = absoff - *tfsoff;
1037 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
1038 *tfsoff += 2;
1041 static void write_member_type(FILE *file, const type_t *cont,
1042 const attr_list_t *attrs, const type_t *type,
1043 unsigned int *corroff, unsigned int *tfsoff)
1045 if (is_embedded_complex(type) && !is_conformant_array(type))
1047 size_t absoff;
1048 short reloff;
1050 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1052 absoff = *corroff;
1053 *corroff += 8;
1055 else
1057 absoff = type->typestring_offset;
1059 reloff = absoff - (*tfsoff + 2);
1061 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1062 /* FIXME: actually compute necessary padding */
1063 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1064 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1065 reloff, reloff, absoff);
1066 *tfsoff += 4;
1068 else if (is_ptr(type) || is_conformant_array(type))
1070 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1071 ? RPC_FC_POINTER
1072 : RPC_FC_LONG);
1073 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1074 *tfsoff += 1;
1076 else if (!write_base_type(file, type, tfsoff))
1077 error("Unsupported member type 0x%x\n", type->type);
1080 static void write_end(FILE *file, unsigned int *tfsoff)
1082 if (*tfsoff % 2 == 0)
1084 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1085 *tfsoff += 1;
1087 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1088 *tfsoff += 1;
1091 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1093 unsigned int offset = 0;
1094 var_list_t *fs = type->fields;
1095 var_t *f;
1097 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1099 unsigned int align = 0;
1100 type_t *ft = f->type;
1101 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1103 unsigned int absoff = ft->typestring_offset;
1104 short reloff = absoff - (*tfsoff + 6);
1105 print_file(file, 0, "/* %d */\n", *tfsoff);
1106 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1107 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1108 write_conf_or_var_desc(file, current_structure, offset, ft,
1109 get_attrp(f->attrs, ATTR_SWITCHIS));
1110 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1111 reloff, reloff, absoff);
1112 *tfsoff += 8;
1115 /* FIXME: take alignment into account */
1116 offset += type_memsize(ft, &align);
1120 static int write_no_repeat_pointer_descriptions(
1121 FILE *file, type_t *type,
1122 size_t *offset_in_memory, size_t *offset_in_buffer,
1123 unsigned int *typestring_offset)
1125 int written = 0;
1126 unsigned int align;
1128 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1130 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1131 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1133 /* pointer instance */
1134 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1135 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1136 *typestring_offset += 6;
1138 if (is_ptr(type))
1139 write_pointer_tfs(file, type, typestring_offset);
1140 else
1142 unsigned absoff = type->typestring_offset;
1143 short reloff = absoff - (*typestring_offset + 2);
1144 /* FIXME: get pointer attributes from field */
1145 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1146 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1147 reloff, reloff, absoff);
1148 *typestring_offset += 4;
1151 align = 0;
1152 *offset_in_memory += type_memsize(type, &align);
1153 /* FIXME: is there a case where these two are different? */
1154 align = 0;
1155 *offset_in_buffer += type_memsize(type, &align);
1157 return 1;
1160 if (is_non_complex_struct(type))
1162 const var_t *v;
1163 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1164 written += write_no_repeat_pointer_descriptions(
1165 file, v->type,
1166 offset_in_memory, offset_in_buffer, typestring_offset);
1168 else
1170 align = 0;
1171 *offset_in_memory += type_memsize(type, &align);
1172 /* FIXME: is there a case where these two are different? */
1173 align = 0;
1174 *offset_in_buffer += type_memsize(type, &align);
1177 return written;
1180 static int write_pointer_description_offsets(
1181 FILE *file, const attr_list_t *attrs, type_t *type,
1182 size_t *offset_in_memory, size_t *offset_in_buffer,
1183 unsigned int *typestring_offset)
1185 int written = 0;
1186 unsigned int align;
1188 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1190 if (offset_in_memory && offset_in_buffer)
1192 /* pointer instance */
1193 /* FIXME: sometimes from end of structure, sometimes from beginning */
1194 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1195 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1197 align = 0;
1198 *offset_in_memory += type_memsize(type, &align);
1199 /* FIXME: is there a case where these two are different? */
1200 align = 0;
1201 *offset_in_buffer += type_memsize(type, &align);
1203 *typestring_offset += 4;
1205 if (processed(type->ref) || is_base_type(type->ref->type))
1206 write_pointer_tfs(file, type, typestring_offset);
1207 else
1208 error("write_pointer_description_offsets: type format string unknown\n");
1210 return 1;
1213 if (is_array(type))
1215 return write_pointer_description_offsets(
1216 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1217 typestring_offset);
1219 else if (is_non_complex_struct(type))
1221 /* otherwise search for interesting fields to parse */
1222 const var_t *v;
1223 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1225 written += write_pointer_description_offsets(
1226 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1227 typestring_offset);
1230 else
1232 align = 0;
1233 if (offset_in_memory)
1234 *offset_in_memory += type_memsize(type, &align);
1235 /* FIXME: is there a case where these two are different? */
1236 align = 0;
1237 if (offset_in_buffer)
1238 *offset_in_buffer += type_memsize(type, &align);
1241 return written;
1244 /* Note: if file is NULL return value is number of pointers to write, else
1245 * it is the number of type format characters written */
1246 static int write_fixed_array_pointer_descriptions(
1247 FILE *file, const attr_list_t *attrs, type_t *type,
1248 size_t *offset_in_memory, size_t *offset_in_buffer,
1249 unsigned int *typestring_offset)
1251 unsigned int align;
1252 int pointer_count = 0;
1254 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1256 unsigned int temp = 0;
1257 /* unfortunately, this needs to be done in two passes to avoid
1258 * writing out redundant FC_FIXED_REPEAT descriptions */
1259 pointer_count = write_pointer_description_offsets(
1260 NULL, attrs, type->ref, NULL, NULL, &temp);
1261 if (pointer_count > 0)
1263 unsigned int increment_size;
1264 size_t offset_of_array_pointer_mem = 0;
1265 size_t offset_of_array_pointer_buf = 0;
1267 align = 0;
1268 increment_size = type_memsize(type->ref, &align);
1270 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1271 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1272 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1273 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1274 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1275 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1276 *typestring_offset += 10;
1278 pointer_count = write_pointer_description_offsets(
1279 file, attrs, type, &offset_of_array_pointer_mem,
1280 &offset_of_array_pointer_buf, typestring_offset);
1283 else if (is_struct(type->type))
1285 const var_t *v;
1286 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1288 pointer_count += write_fixed_array_pointer_descriptions(
1289 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1290 typestring_offset);
1293 else
1295 align = 0;
1296 if (offset_in_memory)
1297 *offset_in_memory += type_memsize(type, &align);
1298 /* FIXME: is there a case where these two are different? */
1299 align = 0;
1300 if (offset_in_buffer)
1301 *offset_in_buffer += type_memsize(type, &align);
1304 return pointer_count;
1307 /* Note: if file is NULL return value is number of pointers to write, else
1308 * it is the number of type format characters written */
1309 static int write_conformant_array_pointer_descriptions(
1310 FILE *file, const attr_list_t *attrs, type_t *type,
1311 size_t offset_in_memory, unsigned int *typestring_offset)
1313 unsigned int align;
1314 int pointer_count = 0;
1316 if (is_conformant_array(type) && !type->length_is)
1318 unsigned int temp = 0;
1319 /* unfortunately, this needs to be done in two passes to avoid
1320 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1321 pointer_count = write_pointer_description_offsets(
1322 NULL, attrs, type->ref, NULL, NULL, &temp);
1323 if (pointer_count > 0)
1325 unsigned int increment_size;
1326 size_t offset_of_array_pointer_mem = offset_in_memory;
1327 size_t offset_of_array_pointer_buf = offset_in_memory;
1329 align = 0;
1330 increment_size = type_memsize(type->ref, &align);
1332 if (increment_size > USHRT_MAX)
1333 error("array size of %u bytes is too large\n", increment_size);
1335 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1336 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1337 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1338 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1339 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1340 *typestring_offset += 8;
1342 pointer_count = write_pointer_description_offsets(
1343 file, attrs, type->ref, &offset_of_array_pointer_mem,
1344 &offset_of_array_pointer_buf, typestring_offset);
1348 return pointer_count;
1351 /* Note: if file is NULL return value is number of pointers to write, else
1352 * it is the number of type format characters written */
1353 static int write_varying_array_pointer_descriptions(
1354 FILE *file, const attr_list_t *attrs, type_t *type,
1355 size_t *offset_in_memory, size_t *offset_in_buffer,
1356 unsigned int *typestring_offset)
1358 unsigned int align;
1359 int pointer_count = 0;
1361 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1363 if (is_array(type) && type->length_is)
1365 unsigned int temp = 0;
1366 /* unfortunately, this needs to be done in two passes to avoid
1367 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1368 pointer_count = write_pointer_description_offsets(
1369 NULL, attrs, type->ref, NULL, NULL, &temp);
1370 if (pointer_count > 0)
1372 unsigned int increment_size;
1373 size_t offset_of_array_pointer_mem = 0;
1374 size_t offset_of_array_pointer_buf = 0;
1376 align = 0;
1377 increment_size = type_memsize(type->ref, &align);
1379 if (increment_size > USHRT_MAX)
1380 error("array size of %u bytes is too large\n", increment_size);
1382 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1383 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1384 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1385 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1386 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1387 *typestring_offset += 8;
1389 pointer_count = write_pointer_description_offsets(
1390 file, attrs, type, &offset_of_array_pointer_mem,
1391 &offset_of_array_pointer_buf, typestring_offset);
1394 else if (is_struct(type->type))
1396 const var_t *v;
1397 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1399 pointer_count += write_varying_array_pointer_descriptions(
1400 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1401 typestring_offset);
1404 else
1406 align = 0;
1407 if (offset_in_memory)
1408 *offset_in_memory += type_memsize(type, &align);
1409 /* FIXME: is there a case where these two are different? */
1410 align = 0;
1411 if (offset_in_buffer)
1412 *offset_in_buffer += type_memsize(type, &align);
1415 return pointer_count;
1418 static void write_pointer_description(FILE *file, type_t *type,
1419 unsigned int *typestring_offset)
1421 size_t offset_in_buffer;
1422 size_t offset_in_memory;
1424 /* pass 1: search for single instance of a pointer (i.e. don't descend
1425 * into arrays) */
1426 if (!is_array(type))
1428 offset_in_memory = 0;
1429 offset_in_buffer = 0;
1430 write_no_repeat_pointer_descriptions(
1431 file, type,
1432 &offset_in_memory, &offset_in_buffer, typestring_offset);
1435 /* pass 2: search for pointers in fixed arrays */
1436 offset_in_memory = 0;
1437 offset_in_buffer = 0;
1438 write_fixed_array_pointer_descriptions(
1439 file, NULL, type,
1440 &offset_in_memory, &offset_in_buffer, typestring_offset);
1442 /* pass 3: search for pointers in conformant only arrays (but don't descend
1443 * into conformant varying or varying arrays) */
1444 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1445 write_conformant_array_pointer_descriptions(
1446 file, NULL, type, 0, typestring_offset);
1447 else if (type->type == RPC_FC_CPSTRUCT)
1449 unsigned int align = 0;
1450 type_t *carray = find_array_or_string_in_struct(type)->type;
1451 write_conformant_array_pointer_descriptions(
1452 file, NULL, carray,
1453 type_memsize(type, &align),
1454 typestring_offset);
1457 /* pass 4: search for pointers in varying arrays */
1458 offset_in_memory = 0;
1459 offset_in_buffer = 0;
1460 write_varying_array_pointer_descriptions(
1461 file, NULL, type,
1462 &offset_in_memory, &offset_in_buffer, typestring_offset);
1465 int is_declptr(const type_t *t)
1467 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1470 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1471 type_t *type,
1472 const char *name, unsigned int *typestring_offset,
1473 int toplevel)
1475 size_t start_offset = *typestring_offset;
1476 unsigned char rtype;
1478 update_tfsoff(type, start_offset, file);
1480 if (toplevel && is_declptr(type))
1482 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1483 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1484 if (!pointer_type)
1485 pointer_type = RPC_FC_RP;
1486 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1487 pointer_type, flag, string_of_type(pointer_type),
1488 flag ? " [simple_pointer]" : "");
1489 *typestring_offset += 2;
1490 if (!flag)
1492 print_file(file, 2, "NdrFcShort(0x2),\n");
1493 *typestring_offset += 2;
1497 rtype = type->ref->type;
1499 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1501 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1502 return start_offset;
1505 if (type->declarray && !is_conformant_array(type))
1507 /* FIXME: multi-dimensional array */
1508 if (0xffffuL < type->dim)
1509 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1510 name, 0xffffu, type->dim - 0xffffu);
1512 if (rtype == RPC_FC_CHAR)
1513 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1514 else
1515 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1516 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1517 *typestring_offset += 2;
1519 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1520 *typestring_offset += 2;
1522 return start_offset;
1524 else if (type->size_is)
1526 unsigned int align = 0;
1528 if (rtype == RPC_FC_CHAR)
1529 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1530 else
1531 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1532 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1533 *typestring_offset += 2;
1535 *typestring_offset += write_conf_or_var_desc(
1536 file, current_structure,
1537 (type->declarray && current_structure
1538 ? type_memsize(current_structure, &align)
1539 : 0),
1540 type, type->size_is);
1542 return start_offset;
1544 else
1546 if (rtype == RPC_FC_WCHAR)
1547 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1548 else
1549 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1550 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1551 *typestring_offset += 2;
1553 return start_offset;
1557 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1558 const char *name, unsigned int *typestring_offset)
1560 const expr_t *length_is = type->length_is;
1561 const expr_t *size_is = type->size_is;
1562 unsigned int align = 0;
1563 size_t size;
1564 size_t start_offset;
1565 int has_pointer;
1566 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1567 unsigned int baseoff
1568 = type->declarray && current_structure
1569 ? type_memsize(current_structure, &align)
1570 : 0;
1572 if (!pointer_type)
1573 pointer_type = RPC_FC_RP;
1575 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1576 has_pointer = TRUE;
1577 else
1578 has_pointer = type_has_pointers(type->ref);
1580 align = 0;
1581 size = type_memsize((is_conformant_array(type) ? type->ref : type), &align);
1583 start_offset = *typestring_offset;
1584 update_tfsoff(type, start_offset, file);
1585 print_start_tfs_comment(file, type, start_offset);
1586 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1587 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1588 *typestring_offset += 2;
1590 align = 0;
1591 if (type->type != RPC_FC_BOGUS_ARRAY)
1593 unsigned char tc = type->type;
1595 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1597 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1598 *typestring_offset += 4;
1600 else
1602 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1603 *typestring_offset += 2;
1606 if (is_conformant_array(type))
1607 *typestring_offset
1608 += write_conf_or_var_desc(file, current_structure, baseoff,
1609 type, size_is);
1611 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1613 unsigned int elalign = 0;
1614 size_t elsize = type_memsize(type->ref, &elalign);
1616 if (type->type == RPC_FC_LGVARRAY)
1618 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1619 *typestring_offset += 4;
1621 else
1623 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1624 *typestring_offset += 2;
1627 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1628 *typestring_offset += 2;
1631 if (length_is)
1632 *typestring_offset
1633 += write_conf_or_var_desc(file, current_structure, baseoff,
1634 type, length_is);
1636 if (has_pointer && (!type->declarray || !current_structure))
1638 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1639 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1640 *typestring_offset += 2;
1641 write_pointer_description(file, type, typestring_offset);
1642 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1643 *typestring_offset += 1;
1646 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1647 write_end(file, typestring_offset);
1649 else
1651 unsigned int dim = size_is ? 0 : type->dim;
1652 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1653 *typestring_offset += 2;
1654 *typestring_offset
1655 += write_conf_or_var_desc(file, current_structure, baseoff,
1656 type, size_is);
1657 *typestring_offset
1658 += write_conf_or_var_desc(file, current_structure, baseoff,
1659 type, length_is);
1660 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1661 write_end(file, typestring_offset);
1664 return start_offset;
1667 static const var_t *find_array_or_string_in_struct(const type_t *type)
1669 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1670 const type_t *ft = last_field->type;
1672 if (ft->declarray && is_conformant_array(ft))
1673 return last_field;
1675 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1676 return find_array_or_string_in_struct(last_field->type);
1677 else
1678 return NULL;
1681 static void write_struct_members(FILE *file, const type_t *type,
1682 unsigned int *corroff, unsigned int *typestring_offset)
1684 const var_t *field;
1685 unsigned short offset = 0;
1686 int salign = -1;
1687 int padding;
1689 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1691 type_t *ft = field->type;
1692 if (!ft->declarray || !is_conformant_array(ft))
1694 unsigned int align = 0;
1695 size_t size = type_memsize(ft, &align);
1696 if (salign == -1)
1697 salign = align;
1698 if ((align - 1) & offset)
1700 unsigned char fc = 0;
1701 switch (align)
1703 case 4:
1704 fc = RPC_FC_ALIGNM4;
1705 break;
1706 case 8:
1707 fc = RPC_FC_ALIGNM8;
1708 break;
1709 default:
1710 error("write_struct_members: cannot align type %d\n", ft->type);
1712 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1713 offset = (offset + (align - 1)) & ~(align - 1);
1714 *typestring_offset += 1;
1716 write_member_type(file, type, field->attrs, field->type, corroff,
1717 typestring_offset);
1718 offset += size;
1722 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1723 if (padding)
1725 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1726 RPC_FC_STRUCTPAD1 + padding - 1,
1727 padding);
1728 *typestring_offset += 1;
1731 write_end(file, typestring_offset);
1734 static size_t write_struct_tfs(FILE *file, type_t *type,
1735 const char *name, unsigned int *tfsoff)
1737 const type_t *save_current_structure = current_structure;
1738 unsigned int total_size;
1739 const var_t *array;
1740 size_t start_offset;
1741 size_t array_offset;
1742 int has_pointers = 0;
1743 unsigned int align = 0;
1744 unsigned int corroff;
1745 var_t *f;
1747 guard_rec(type);
1748 current_structure = type;
1750 total_size = type_memsize(type, &align);
1751 if (total_size > USHRT_MAX)
1752 error("structure size for %s exceeds %d bytes by %d bytes\n",
1753 name, USHRT_MAX, total_size - USHRT_MAX);
1755 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1756 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1757 FALSE, tfsoff);
1758 if (!has_pointers) has_pointers = type_has_pointers(type);
1760 array = find_array_or_string_in_struct(type);
1761 if (array && !processed(array->type))
1762 array_offset
1763 = is_attr(array->attrs, ATTR_STRING)
1764 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff, FALSE)
1765 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1767 corroff = *tfsoff;
1768 write_descriptors(file, type, tfsoff);
1770 start_offset = *tfsoff;
1771 update_tfsoff(type, start_offset, file);
1772 print_start_tfs_comment(file, type, start_offset);
1773 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1774 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1775 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1776 *tfsoff += 4;
1778 if (array)
1780 unsigned int absoff = array->type->typestring_offset;
1781 short reloff = absoff - *tfsoff;
1782 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1783 reloff, reloff, absoff);
1784 *tfsoff += 2;
1786 else if (type->type == RPC_FC_BOGUS_STRUCT)
1788 print_file(file, 2, "NdrFcShort(0x0),\n");
1789 *tfsoff += 2;
1792 if (type->type == RPC_FC_BOGUS_STRUCT)
1794 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1795 nothing is written to file yet. On the actual writing pass,
1796 this will have been updated. */
1797 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1798 short reloff = absoff - *tfsoff;
1799 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1800 reloff, reloff, absoff);
1801 *tfsoff += 2;
1803 else if ((type->type == RPC_FC_PSTRUCT) ||
1804 (type->type == RPC_FC_CPSTRUCT) ||
1805 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1807 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1808 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1809 *tfsoff += 2;
1810 write_pointer_description(file, type, tfsoff);
1811 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1812 *tfsoff += 1;
1815 write_struct_members(file, type, &corroff, tfsoff);
1817 if (type->type == RPC_FC_BOGUS_STRUCT)
1819 const var_list_t *fs = type->fields;
1820 const var_t *f;
1822 type->ptrdesc = *tfsoff;
1823 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1825 type_t *ft = f->type;
1826 if (is_ptr(ft))
1827 write_pointer_tfs(file, ft, tfsoff);
1828 else if (!ft->declarray && is_conformant_array(ft))
1830 unsigned int absoff = ft->typestring_offset;
1831 short reloff = absoff - (*tfsoff + 2);
1832 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1833 /* FIXME: We need to store pointer attributes for arrays
1834 so we don't lose pointer_default info. */
1835 if (ptr_type == 0)
1836 ptr_type = RPC_FC_UP;
1837 print_file(file, 0, "/* %d */\n", *tfsoff);
1838 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1839 string_of_type(ptr_type));
1840 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1841 reloff, reloff, absoff);
1842 *tfsoff += 4;
1845 if (type->ptrdesc == *tfsoff)
1846 type->ptrdesc = 0;
1849 current_structure = save_current_structure;
1850 return start_offset;
1853 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1854 unsigned char flags, size_t offset,
1855 unsigned int *typeformat_offset)
1857 size_t start_offset = *typeformat_offset;
1858 short reloff = offset - (*typeformat_offset + 2);
1859 int in_attr, out_attr;
1860 in_attr = is_attr(attrs, ATTR_IN);
1861 out_attr = is_attr(attrs, ATTR_OUT);
1862 if (!in_attr && !out_attr) in_attr = 1;
1864 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1865 flags |= 0x04;
1867 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1868 pointer_type,
1869 flags,
1870 string_of_type(pointer_type));
1871 if (file)
1873 if (flags & 0x04)
1874 fprintf(file, " [allocated_on_stack]");
1875 if (flags & 0x10)
1876 fprintf(file, " [pointer_deref]");
1877 fprintf(file, " */\n");
1880 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1881 *typeformat_offset += 4;
1883 return start_offset;
1886 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1888 if (t == NULL)
1890 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1892 else if (is_base_type(t->type))
1894 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1895 t->type, string_of_type(t->type));
1897 else if (t->typestring_offset)
1899 short reloff = t->typestring_offset - *tfsoff;
1900 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1901 reloff, reloff, t->typestring_offset);
1903 else
1904 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1906 *tfsoff += 2;
1909 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1911 unsigned int align = 0;
1912 unsigned int start_offset;
1913 size_t size = type_memsize(type, &align);
1914 var_list_t *fields;
1915 size_t nbranch = 0;
1916 type_t *deftype = NULL;
1917 short nodeftype = 0xffff;
1918 var_t *f;
1920 guard_rec(type);
1922 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1924 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1925 fields = uv->type->fields;
1927 else
1928 fields = type->fields;
1930 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1932 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1933 if (cases)
1934 nbranch += list_count(cases);
1935 if (f->type)
1936 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1939 start_offset = *tfsoff;
1940 update_tfsoff(type, start_offset, file);
1941 print_start_tfs_comment(file, type, start_offset);
1942 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1944 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1945 const type_t *st = sv->type;
1947 switch (st->type)
1949 case RPC_FC_CHAR:
1950 case RPC_FC_SMALL:
1951 case RPC_FC_USMALL:
1952 case RPC_FC_SHORT:
1953 case RPC_FC_USHORT:
1954 case RPC_FC_LONG:
1955 case RPC_FC_ULONG:
1956 case RPC_FC_ENUM16:
1957 case RPC_FC_ENUM32:
1958 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1959 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1960 0x40 | st->type, string_of_type(st->type));
1961 *tfsoff += 2;
1962 break;
1963 default:
1964 error("union switch type must be an integer, char, or enum\n");
1967 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1968 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1969 *tfsoff += 4;
1971 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1973 type_t *ft = f->type;
1974 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1975 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1976 expr_t *c;
1978 if (cases == NULL && !deflt)
1979 error("union field %s with neither case nor default attribute\n", f->name);
1981 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1983 /* MIDL doesn't check for duplicate cases, even though that seems
1984 like a reasonable thing to do, it just dumps them to the TFS
1985 like we're going to do here. */
1986 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1987 *tfsoff += 4;
1988 write_branch_type(file, ft, tfsoff);
1991 /* MIDL allows multiple default branches, even though that seems
1992 illogical, it just chooses the last one, which is what we will
1993 do. */
1994 if (deflt)
1996 deftype = ft;
1997 nodeftype = 0;
2001 if (deftype)
2003 write_branch_type(file, deftype, tfsoff);
2005 else
2007 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
2008 *tfsoff += 2;
2011 return start_offset;
2014 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2015 unsigned int *typeformat_offset)
2017 size_t i;
2018 size_t start_offset = *typeformat_offset;
2019 expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
2021 if (iid)
2023 print_file(file, 2, "0x2f, /* FC_IP */\n");
2024 print_file(file, 2, "0x5c, /* FC_PAD */\n");
2025 *typeformat_offset
2026 += write_conf_or_var_desc(file, NULL, 0, type, iid) + 2;
2028 else
2030 const type_t *base = is_ptr(type) ? type->ref : type;
2031 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
2033 if (! uuid)
2034 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
2036 update_tfsoff(type, start_offset, file);
2037 print_start_tfs_comment(file, type, start_offset);
2038 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2039 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2040 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2041 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2042 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2043 for (i = 0; i < 8; ++i)
2044 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2046 if (file)
2047 fprintf(file, "\n");
2049 *typeformat_offset += 18;
2051 return start_offset;
2054 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2055 const var_t *var,
2056 unsigned int *typeformat_offset)
2058 size_t start_offset = *typeformat_offset;
2059 unsigned char flags = 0x08 /* strict */;
2061 if (is_ptr(type))
2063 flags |= 0x80;
2064 if (type->type != RPC_FC_RP)
2065 flags |= 0x01;
2067 if (is_attr(var->attrs, ATTR_IN))
2068 flags |= 0x40;
2069 if (is_attr(var->attrs, ATTR_OUT))
2070 flags |= 0x20;
2072 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2073 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2074 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2075 print_file(file, 0, "can't be null, ");
2076 if (flags & 0x02)
2077 print_file(file, 0, "serialize, ");
2078 if (flags & 0x04)
2079 print_file(file, 0, "no serialize, ");
2080 if (flags & 0x08)
2081 print_file(file, 0, "strict, ");
2082 if ((flags & 0x21) == 0x20)
2083 print_file(file, 0, "out, ");
2084 if ((flags & 0x21) == 0x21)
2085 print_file(file, 0, "return, ");
2086 if (flags & 0x40)
2087 print_file(file, 0, "in, ");
2088 if (flags & 0x80)
2089 print_file(file, 0, "via ptr, ");
2090 print_file(file, 0, "*/\n");
2091 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2092 print_file(file, 2, "0, /* FIXME: param num */\n");
2093 *typeformat_offset += 4;
2095 return start_offset;
2098 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2099 type_t *type, const var_t *var,
2100 unsigned int *typeformat_offset)
2102 size_t offset;
2104 if (is_context_handle(type))
2105 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2107 if (is_user_type(type))
2109 write_user_tfs(file, type, typeformat_offset);
2110 return type->typestring_offset;
2113 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2114 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset, TRUE);
2116 if (is_array(type))
2118 int ptr_type;
2119 size_t off;
2120 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2121 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2122 /* Top level pointers to conformant arrays may be handled specially
2123 since we can bypass the pointer, but if the array is burried
2124 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2125 always need to write the pointer. */
2126 if (!ptr_type && var->type != type)
2127 /* FIXME: This should use pointer_default, but the information
2128 isn't kept around for arrays. */
2129 ptr_type = RPC_FC_UP;
2130 if (ptr_type && ptr_type != RPC_FC_RP)
2132 unsigned int absoff = type->typestring_offset;
2133 short reloff = absoff - (*typeformat_offset + 2);
2134 off = *typeformat_offset;
2135 print_file(file, 0, "/* %d */\n", off);
2136 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2137 string_of_type(ptr_type));
2138 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2139 reloff, reloff, absoff);
2140 *typeformat_offset += 4;
2142 return off;
2145 if (!is_ptr(type))
2147 /* basic types don't need a type format string */
2148 if (is_base_type(type->type))
2149 return 0;
2151 switch (type->type)
2153 case RPC_FC_STRUCT:
2154 case RPC_FC_PSTRUCT:
2155 case RPC_FC_CSTRUCT:
2156 case RPC_FC_CPSTRUCT:
2157 case RPC_FC_CVSTRUCT:
2158 case RPC_FC_BOGUS_STRUCT:
2159 return write_struct_tfs(file, type, var->name, typeformat_offset);
2160 case RPC_FC_ENCAPSULATED_UNION:
2161 case RPC_FC_NON_ENCAPSULATED_UNION:
2162 return write_union_tfs(file, type, typeformat_offset);
2163 case RPC_FC_IGNORE:
2164 case RPC_FC_BIND_PRIMITIVE:
2165 /* nothing to do */
2166 return 0;
2167 default:
2168 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2171 else if (last_ptr(type))
2173 size_t start_offset = *typeformat_offset;
2174 int in_attr = is_attr(var->attrs, ATTR_IN);
2175 int out_attr = is_attr(var->attrs, ATTR_OUT);
2176 const type_t *base = type->ref;
2178 if (base->type == RPC_FC_IP
2179 || (base->type == 0
2180 && is_attr(var->attrs, ATTR_IIDIS)))
2182 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2185 /* special case for pointers to base types */
2186 if (is_base_type(base->type))
2188 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2189 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2190 string_of_type(type->type),
2191 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2192 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2193 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2194 *typeformat_offset += 4;
2195 return start_offset;
2199 assert(is_ptr(type));
2201 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2202 if (file)
2203 fprintf(file, "/* %2u */\n", *typeformat_offset);
2204 return write_pointer_only_tfs(file, var->attrs, type->type,
2205 !last_ptr(type) ? 0x10 : 0,
2206 offset, typeformat_offset);
2209 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2210 const char *name, int write_ptr, unsigned int *tfsoff)
2212 int retmask = 0;
2214 if (is_user_type(type))
2216 write_user_tfs(file, type, tfsoff);
2218 else if (is_ptr(type))
2220 type_t *ref = type->ref;
2222 if (ref->type == RPC_FC_IP
2223 || (ref->type == 0
2224 && is_attr(attrs, ATTR_IIDIS)))
2226 write_ip_tfs(file, attrs, type, tfsoff);
2228 else
2230 if (!processed(ref) && !is_base_type(ref->type))
2231 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2233 if (write_ptr)
2234 write_pointer_tfs(file, type, tfsoff);
2236 retmask |= 1;
2239 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2241 write_string_tfs(file, attrs, type, name, tfsoff, FALSE);
2243 else if (type->declarray && is_conformant_array(type))
2244 ; /* conformant arrays and strings are handled specially */
2245 else if (is_array(type))
2247 write_array_tfs(file, attrs, type, name, tfsoff);
2248 if (is_conformant_array(type))
2249 retmask |= 1;
2251 else if (is_struct(type->type))
2253 if (!processed(type))
2254 write_struct_tfs(file, type, name, tfsoff);
2256 else if (is_union(type->type))
2258 if (!processed(type))
2259 write_union_tfs(file, type, tfsoff);
2261 else if (!is_base_type(type->type))
2262 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2263 name, type->type);
2265 return retmask;
2268 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2270 const var_t *var;
2271 const ifref_t *iface;
2272 unsigned int typeformat_offset = 2;
2274 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2276 if (!pred(iface->iface))
2277 continue;
2279 if (iface->iface->funcs)
2281 const func_t *func;
2282 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2284 if (is_local(func->def->attrs)) continue;
2286 current_func = func;
2287 if (func->args)
2288 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2289 update_tfsoff(
2290 var->type,
2291 write_typeformatstring_var(
2292 file, 2, func, var->type, var,
2293 &typeformat_offset),
2294 file);
2299 return typeformat_offset + 1;
2303 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2305 int indent = 0;
2307 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2308 print_file(file, indent, "{\n");
2309 indent++;
2310 print_file(file, indent, "0,\n");
2311 print_file(file, indent, "{\n");
2312 indent++;
2313 print_file(file, indent, "NdrFcShort(0x0),\n");
2315 set_all_tfswrite(TRUE);
2316 process_tfs(file, ifaces, pred);
2318 print_file(file, indent, "0x0\n");
2319 indent--;
2320 print_file(file, indent, "}\n");
2321 indent--;
2322 print_file(file, indent, "};\n");
2323 print_file(file, indent, "\n");
2326 static unsigned int get_required_buffer_size_type(
2327 const type_t *type, const char *name, unsigned int *alignment)
2329 *alignment = 0;
2330 if (is_user_type(type))
2332 const char *uname;
2333 const type_t *utype = get_user_type(type, &uname);
2334 return get_required_buffer_size_type(utype, uname, alignment);
2336 else
2338 switch (type->type)
2340 case RPC_FC_BYTE:
2341 case RPC_FC_CHAR:
2342 case RPC_FC_USMALL:
2343 case RPC_FC_SMALL:
2344 *alignment = 4;
2345 return 1;
2347 case RPC_FC_WCHAR:
2348 case RPC_FC_USHORT:
2349 case RPC_FC_SHORT:
2350 case RPC_FC_ENUM16:
2351 *alignment = 4;
2352 return 2;
2354 case RPC_FC_ULONG:
2355 case RPC_FC_LONG:
2356 case RPC_FC_ENUM32:
2357 case RPC_FC_FLOAT:
2358 case RPC_FC_ERROR_STATUS_T:
2359 *alignment = 4;
2360 return 4;
2362 case RPC_FC_HYPER:
2363 case RPC_FC_DOUBLE:
2364 *alignment = 8;
2365 return 8;
2367 case RPC_FC_IGNORE:
2368 case RPC_FC_BIND_PRIMITIVE:
2369 return 0;
2371 case RPC_FC_STRUCT:
2372 case RPC_FC_PSTRUCT:
2374 size_t size = 0;
2375 const var_t *field;
2376 if (!type->fields) return 0;
2377 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2379 unsigned int alignment;
2380 size += get_required_buffer_size_type(field->type, field->name,
2381 &alignment);
2383 return size;
2386 case RPC_FC_RP:
2387 return
2388 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2389 ? get_required_buffer_size_type( type->ref, name, alignment )
2390 : 0;
2392 case RPC_FC_SMFARRAY:
2393 case RPC_FC_LGFARRAY:
2394 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2396 default:
2397 return 0;
2402 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2404 int in_attr = is_attr(var->attrs, ATTR_IN);
2405 int out_attr = is_attr(var->attrs, ATTR_OUT);
2406 const type_t *t;
2408 if (!in_attr && !out_attr)
2409 in_attr = 1;
2411 *alignment = 0;
2413 for (t = var->type; is_ptr(t); t = t->ref)
2414 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2416 *alignment = 4;
2417 return 20;
2420 if (pass == PASS_OUT)
2422 if (out_attr && is_ptr(var->type))
2424 type_t *type = var->type;
2426 if (type->type == RPC_FC_STRUCT)
2428 const var_t *field;
2429 unsigned int size = 36;
2431 if (!type->fields) return size;
2432 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2434 unsigned int align;
2435 size += get_required_buffer_size_type(
2436 field->type, field->name, &align);
2438 return size;
2441 return 0;
2443 else
2445 if ((!out_attr || in_attr) && !var->type->size_is
2446 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2448 if (is_ptr(var->type))
2450 type_t *type = var->type;
2452 if (is_base_type(type->type))
2454 return 25;
2456 else if (type->type == RPC_FC_STRUCT)
2458 unsigned int size = 36;
2459 const var_t *field;
2461 if (!type->fields) return size;
2462 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2464 unsigned int align;
2465 size += get_required_buffer_size_type(
2466 field->type, field->name, &align);
2468 return size;
2473 return get_required_buffer_size_type(var->type, var->name, alignment);
2477 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2479 const var_t *var;
2480 unsigned int total_size = 0, alignment;
2482 if (func->args)
2484 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2486 total_size += get_required_buffer_size(var, &alignment, pass);
2487 total_size += alignment;
2491 if (pass == PASS_OUT && !is_void(func->def->type))
2493 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2494 total_size += alignment;
2496 return total_size;
2499 static void print_phase_function(FILE *file, int indent, const char *type,
2500 enum remoting_phase phase,
2501 const var_t *var, unsigned int type_offset)
2503 const char *function;
2504 switch (phase)
2506 case PHASE_BUFFERSIZE:
2507 function = "BufferSize";
2508 break;
2509 case PHASE_MARSHAL:
2510 function = "Marshall";
2511 break;
2512 case PHASE_UNMARSHAL:
2513 function = "Unmarshall";
2514 break;
2515 case PHASE_FREE:
2516 function = "Free";
2517 break;
2518 default:
2519 assert(0);
2520 return;
2523 print_file(file, indent, "Ndr%s%s(\n", type, function);
2524 indent++;
2525 print_file(file, indent, "&_StubMsg,\n");
2526 print_file(file, indent, "%s%s%s%s,\n",
2527 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2528 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2529 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2530 var->name);
2531 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2532 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2533 if (phase == PHASE_UNMARSHAL)
2534 print_file(file, indent, "0);\n");
2535 indent--;
2538 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2539 enum pass pass, const var_t *var,
2540 const char *varname)
2542 type_t *type = var->type;
2543 unsigned int size;
2544 unsigned int alignment = 0;
2545 unsigned char rtype;
2547 /* no work to do for other phases, buffer sizing is done elsewhere */
2548 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2549 return;
2551 rtype = is_ptr(type) ? type->ref->type : type->type;
2553 switch (rtype)
2555 case RPC_FC_BYTE:
2556 case RPC_FC_CHAR:
2557 case RPC_FC_SMALL:
2558 case RPC_FC_USMALL:
2559 size = 1;
2560 alignment = 1;
2561 break;
2563 case RPC_FC_WCHAR:
2564 case RPC_FC_USHORT:
2565 case RPC_FC_SHORT:
2566 case RPC_FC_ENUM16:
2567 size = 2;
2568 alignment = 2;
2569 break;
2571 case RPC_FC_ULONG:
2572 case RPC_FC_LONG:
2573 case RPC_FC_ENUM32:
2574 case RPC_FC_FLOAT:
2575 case RPC_FC_ERROR_STATUS_T:
2576 size = 4;
2577 alignment = 4;
2578 break;
2580 case RPC_FC_HYPER:
2581 case RPC_FC_DOUBLE:
2582 size = 8;
2583 alignment = 8;
2584 break;
2586 case RPC_FC_IGNORE:
2587 case RPC_FC_BIND_PRIMITIVE:
2588 /* no marshalling needed */
2589 return;
2591 default:
2592 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2593 size = 0;
2596 if (phase == PHASE_MARSHAL)
2597 print_file(file, indent, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
2598 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2599 alignment - 1, alignment - 1);
2601 if (phase == PHASE_MARSHAL)
2603 print_file(file, indent, "*(");
2604 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2605 if (is_ptr(type))
2606 fprintf(file, " *)_StubMsg.Buffer = *");
2607 else
2608 fprintf(file, " *)_StubMsg.Buffer = ");
2609 fprintf(file, "%s", varname);
2610 fprintf(file, ";\n");
2612 else if (phase == PHASE_UNMARSHAL)
2614 if (pass == PASS_IN || pass == PASS_RETURN)
2615 print_file(file, indent, "");
2616 else
2617 print_file(file, indent, "*");
2618 fprintf(file, "%s", varname);
2619 if (pass == PASS_IN && is_ptr(type))
2620 fprintf(file, " = (");
2621 else
2622 fprintf(file, " = *(");
2623 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2624 fprintf(file, " *)_StubMsg.Buffer;\n");
2627 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2628 write_type_decl(file, var->type, NULL);
2629 fprintf(file, ");\n");
2632 /* returns whether the MaxCount, Offset or ActualCount members need to be
2633 * filled in for the specified phase */
2634 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2636 return (phase != PHASE_UNMARSHAL);
2639 expr_t *get_size_is_expr(const type_t *t, const char *name)
2641 expr_t *x = NULL;
2643 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2644 if (t->size_is)
2646 if (!x)
2647 x = t->size_is;
2648 else
2649 error("%s: multidimensional conformant"
2650 " arrays not supported at the top level\n",
2651 name);
2654 return x;
2657 static void write_remoting_arg(FILE *file, int indent, const func_t *func,
2658 enum pass pass, enum remoting_phase phase,
2659 const var_t *var)
2661 int in_attr, out_attr, pointer_type;
2662 const type_t *type = var->type;
2663 unsigned char rtype;
2664 size_t start_offset = type->typestring_offset;
2666 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2667 if (!pointer_type)
2668 pointer_type = RPC_FC_RP;
2670 in_attr = is_attr(var->attrs, ATTR_IN);
2671 out_attr = is_attr(var->attrs, ATTR_OUT);
2672 if (!in_attr && !out_attr)
2673 in_attr = 1;
2675 if (phase != PHASE_FREE)
2676 switch (pass)
2678 case PASS_IN:
2679 if (!in_attr) return;
2680 break;
2681 case PASS_OUT:
2682 if (!out_attr) return;
2683 break;
2684 case PASS_RETURN:
2685 break;
2688 rtype = type->type;
2690 if (is_context_handle(type))
2692 if (phase == PHASE_MARSHAL)
2694 if (pass == PASS_IN)
2696 print_file(file, indent, "NdrClientContextMarshall(\n");
2697 print_file(file, indent + 1, "&_StubMsg,\n");
2698 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2699 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2701 else
2703 print_file(file, indent, "NdrServerContextMarshall(\n");
2704 print_file(file, indent + 1, "&_StubMsg,\n");
2705 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2706 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2709 else if (phase == PHASE_UNMARSHAL)
2711 if (pass == PASS_OUT)
2713 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2714 print_file(file, indent + 1, "&_StubMsg,\n");
2715 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2716 print_file(file, indent + 1, "_Handle);\n");
2718 else
2719 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2722 else if (is_user_type(var->type))
2724 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2726 else if (is_string_type(var->attrs, var->type))
2728 if (is_array(type) && !is_conformant_array(type))
2729 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2730 else
2732 if (type->size_is && is_size_needed_for_phase(phase))
2734 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2735 write_expr(file, type->size_is, 1);
2736 fprintf(file, ";\n");
2739 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2740 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2741 else
2742 print_phase_function(file, indent, "ConformantString", phase, var,
2743 start_offset + (type->size_is ? 4 : 2));
2746 else if (is_array(type))
2748 unsigned char tc = type->type;
2749 const char *array_type = "FixedArray";
2751 /* We already have the size_is expression since it's at the
2752 top level, but do checks for multidimensional conformant
2753 arrays. When we handle them, we'll need to extend this
2754 function to return a list, and then we'll actually use
2755 the return value. */
2756 get_size_is_expr(type, var->name);
2758 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2760 if (is_size_needed_for_phase(phase))
2762 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2763 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2764 write_expr(file, type->length_is, 1);
2765 fprintf(file, ";\n\n");
2767 array_type = "VaryingArray";
2769 else if (tc == RPC_FC_CARRAY)
2771 if (is_size_needed_for_phase(phase))
2773 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2774 write_expr(file, type->size_is, 1);
2775 fprintf(file, ";\n\n");
2777 array_type = "ConformantArray";
2779 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2781 if (is_size_needed_for_phase(phase))
2783 if (type->size_is)
2785 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2786 write_expr(file, type->size_is, 1);
2787 fprintf(file, ";\n");
2789 if (type->length_is)
2791 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2792 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2793 write_expr(file, type->length_is, 1);
2794 fprintf(file, ";\n\n");
2797 array_type = (tc == RPC_FC_BOGUS_ARRAY
2798 ? "ComplexArray"
2799 : "ConformantVaryingArray");
2802 if (pointer_type != RPC_FC_RP) array_type = "Pointer";
2803 print_phase_function(file, indent, array_type, phase, var, start_offset);
2804 if (phase == PHASE_FREE && type->declarray && pointer_type == RPC_FC_RP)
2806 /* these are all unmarshalled by pointing into the buffer on the
2807 * server side */
2808 if (type->type == RPC_FC_BOGUS_ARRAY ||
2809 type->type == RPC_FC_CVARRAY ||
2810 (type->type == RPC_FC_SMVARRAY && type->type == RPC_FC_LGVARRAY && in_attr) ||
2811 (type->type == RPC_FC_CARRAY && type->type == RPC_FC_CARRAY && !in_attr))
2813 print_file(file, indent, "if (%s)\n", var->name);
2814 indent++;
2815 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2819 else if (!is_ptr(var->type) && is_base_type(rtype))
2821 if (phase != PHASE_FREE)
2822 print_phase_basetype(file, indent, phase, pass, var, var->name);
2824 else if (!is_ptr(var->type))
2826 switch (rtype)
2828 case RPC_FC_STRUCT:
2829 case RPC_FC_PSTRUCT:
2830 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2831 break;
2832 case RPC_FC_CSTRUCT:
2833 case RPC_FC_CPSTRUCT:
2834 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2835 break;
2836 case RPC_FC_CVSTRUCT:
2837 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2838 break;
2839 case RPC_FC_BOGUS_STRUCT:
2840 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2841 break;
2842 case RPC_FC_RP:
2843 if (is_base_type( var->type->ref->type ))
2845 print_phase_basetype(file, indent, phase, pass, var, var->name);
2847 else if (var->type->ref->type == RPC_FC_STRUCT)
2849 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2850 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2852 else
2854 expr_t *iid;
2855 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2857 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2858 write_expr( file, iid, 1 );
2859 fprintf( file, ";\n\n" );
2861 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2863 break;
2864 default:
2865 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2868 else
2870 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2872 if (phase != PHASE_FREE)
2873 print_phase_basetype(file, indent, phase, pass, var, var->name);
2875 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2877 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2878 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2880 else
2882 expr_t *iid;
2883 expr_t *sx = get_size_is_expr(type, var->name);
2885 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2887 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2888 write_expr( file, iid, 1 );
2889 fprintf( file, ";\n\n" );
2891 else if (sx)
2893 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2894 write_expr(file, sx, 1);
2895 fprintf(file, ";\n\n");
2897 if (var->type->ref->type == RPC_FC_IP)
2898 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2899 else
2900 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2903 fprintf(file, "\n");
2906 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2907 enum pass pass, enum remoting_phase phase)
2909 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN)
2911 unsigned int size = get_function_buffer_size( func, pass );
2912 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2915 if (pass == PASS_RETURN)
2917 var_t var;
2918 var = *func->def;
2919 var.name = xstrdup( "_RetVal" );
2920 write_remoting_arg( file, indent, func, pass, phase, &var );
2921 free( var.name );
2923 else
2925 const var_t *var;
2926 if (!func->args)
2927 return;
2928 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2929 write_remoting_arg( file, indent, func, pass, phase, var );
2934 size_t get_size_procformatstring_var(const var_t *var)
2936 return write_procformatstring_var(NULL, 0, var, FALSE);
2940 size_t get_size_procformatstring_func(const func_t *func)
2942 const var_t *var;
2943 size_t size = 0;
2945 /* argument list size */
2946 if (func->args)
2947 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2948 size += get_size_procformatstring_var(var);
2950 /* return value size */
2951 if (is_void(func->def->type))
2952 size += 2; /* FC_END and FC_PAD */
2953 else
2954 size += get_size_procformatstring_var(func->def);
2956 return size;
2959 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2961 const ifref_t *iface;
2962 size_t size = 1;
2963 const func_t *func;
2965 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2967 if (!pred(iface->iface))
2968 continue;
2970 if (iface->iface->funcs)
2971 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2972 if (!is_local(func->def->attrs))
2973 size += get_size_procformatstring_func( func );
2975 return size;
2978 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2980 set_all_tfswrite(FALSE);
2981 return process_tfs(NULL, ifaces, pred);
2984 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2985 const var_list_t *fields, const char *structvar)
2987 switch (e->type) {
2988 case EXPR_VOID:
2989 break;
2990 case EXPR_NUM:
2991 fprintf(h, "%lu", e->u.lval);
2992 break;
2993 case EXPR_HEXNUM:
2994 fprintf(h, "0x%lx", e->u.lval);
2995 break;
2996 case EXPR_DOUBLE:
2997 fprintf(h, "%#.15g", e->u.dval);
2998 break;
2999 case EXPR_TRUEFALSE:
3000 if (e->u.lval == 0)
3001 fprintf(h, "FALSE");
3002 else
3003 fprintf(h, "TRUE");
3004 break;
3005 case EXPR_IDENTIFIER:
3007 const var_t *field;
3008 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3009 if (!strcmp(e->u.sval, field->name))
3011 fprintf(h, "%s->%s", structvar, e->u.sval);
3012 break;
3015 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
3016 break;
3018 case EXPR_NEG:
3019 fprintf(h, "-");
3020 write_struct_expr(h, e->ref, 1, fields, structvar);
3021 break;
3022 case EXPR_NOT:
3023 fprintf(h, "~");
3024 write_struct_expr(h, e->ref, 1, fields, structvar);
3025 break;
3026 case EXPR_PPTR:
3027 fprintf(h, "*");
3028 write_struct_expr(h, e->ref, 1, fields, structvar);
3029 break;
3030 case EXPR_CAST:
3031 fprintf(h, "(");
3032 write_type_decl(h, e->u.tref, NULL);
3033 fprintf(h, ")");
3034 write_struct_expr(h, e->ref, 1, fields, structvar);
3035 break;
3036 case EXPR_SIZEOF:
3037 fprintf(h, "sizeof(");
3038 write_type_decl(h, e->u.tref, NULL);
3039 fprintf(h, ")");
3040 break;
3041 case EXPR_SHL:
3042 case EXPR_SHR:
3043 case EXPR_MUL:
3044 case EXPR_DIV:
3045 case EXPR_ADD:
3046 case EXPR_SUB:
3047 case EXPR_AND:
3048 case EXPR_OR:
3049 if (brackets) fprintf(h, "(");
3050 write_struct_expr(h, e->ref, 1, fields, structvar);
3051 switch (e->type) {
3052 case EXPR_SHL: fprintf(h, " << "); break;
3053 case EXPR_SHR: fprintf(h, " >> "); break;
3054 case EXPR_MUL: fprintf(h, " * "); break;
3055 case EXPR_DIV: fprintf(h, " / "); break;
3056 case EXPR_ADD: fprintf(h, " + "); break;
3057 case EXPR_SUB: fprintf(h, " - "); break;
3058 case EXPR_AND: fprintf(h, " & "); break;
3059 case EXPR_OR: fprintf(h, " | "); break;
3060 default: break;
3062 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3063 if (brackets) fprintf(h, ")");
3064 break;
3065 case EXPR_COND:
3066 if (brackets) fprintf(h, "(");
3067 write_struct_expr(h, e->ref, 1, fields, structvar);
3068 fprintf(h, " ? ");
3069 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3070 fprintf(h, " : ");
3071 write_struct_expr(h, e->ext2, 1, fields, structvar);
3072 if (brackets) fprintf(h, ")");
3073 break;
3074 case EXPR_ADDRESSOF:
3075 fprintf(h, "&");
3076 write_struct_expr(h, e->ref, 1, fields, structvar);
3077 break;
3082 void declare_stub_args( FILE *file, int indent, const func_t *func )
3084 int in_attr, out_attr;
3085 int i = 0;
3086 const var_t *def = func->def;
3087 const var_t *var;
3089 /* declare return value '_RetVal' */
3090 if (!is_void(def->type))
3092 print_file(file, indent, "");
3093 write_type_decl_left(file, def->type);
3094 fprintf(file, " _RetVal;\n");
3097 if (!func->args)
3098 return;
3100 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3102 int is_string = is_attr(var->attrs, ATTR_STRING);
3104 in_attr = is_attr(var->attrs, ATTR_IN);
3105 out_attr = is_attr(var->attrs, ATTR_OUT);
3106 if (!out_attr && !in_attr)
3107 in_attr = 1;
3109 if (is_context_handle(var->type))
3110 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3111 else
3113 if (!in_attr && !var->type->size_is && !is_string)
3115 print_file(file, indent, "");
3116 write_type_decl(file, var->type->declarray ? var->type : var->type->ref,
3117 "_W%u", i++);
3118 fprintf(file, ";\n");
3121 print_file(file, indent, "");
3122 write_type_decl_left(file, var->type);
3123 fprintf(file, " ");
3124 if (var->type->declarray) {
3125 fprintf(file, "( *");
3126 write_name(file, var);
3127 fprintf(file, " )");
3128 } else
3129 write_name(file, var);
3130 write_type_right(file, var->type, FALSE);
3131 fprintf(file, ";\n");
3133 if (decl_indirect(var->type))
3134 print_file(file, indent, "void *_p_%s = &%s;\n",
3135 var->name, var->name);
3141 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3143 int in_attr, out_attr;
3144 int i = 0, sep = 0;
3145 const var_t *var;
3147 if (!func->args)
3148 return;
3150 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3152 int is_string = is_attr(var->attrs, ATTR_STRING);
3153 in_attr = is_attr(var->attrs, ATTR_IN);
3154 out_attr = is_attr(var->attrs, ATTR_OUT);
3155 if (!out_attr && !in_attr)
3156 in_attr = 1;
3158 if (!in_attr)
3160 print_file(file, indent, "");
3161 write_name(file, var);
3163 if (is_context_handle(var->type))
3165 fprintf(file, " = NdrContextHandleInitialize(\n");
3166 print_file(file, indent + 1, "&_StubMsg,\n");
3167 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3168 var->type->typestring_offset);
3170 else if (var->type->size_is)
3172 unsigned int size, align = 0;
3173 type_t *type = var->type;
3175 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3176 for ( ; type->size_is ; type = type->ref)
3178 write_expr(file, type->size_is, TRUE);
3179 fprintf(file, " * ");
3181 size = type_memsize(type, &align);
3182 fprintf(file, "%u);\n", size);
3184 else if (!is_string)
3186 fprintf(file, " = &_W%u;\n", i);
3187 if (is_ptr(var->type) && !last_ptr(var->type))
3188 print_file(file, indent, "_W%u = 0;\n", i);
3189 i++;
3192 sep = 1;
3195 if (sep)
3196 fprintf(file, "\n");
3200 int write_expr_eval_routines(FILE *file, const char *iface)
3202 static const char *var_name = "pS";
3203 int result = 0;
3204 struct expr_eval_routine *eval;
3205 unsigned short callback_offset = 0;
3207 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3209 const char *name = eval->structure->name;
3210 const var_list_t *fields = eval->structure->fields;
3211 result = 1;
3213 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3214 iface, name, callback_offset);
3215 print_file(file, 0, "{\n");
3216 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3217 name, var_name, name, eval->baseoff);
3218 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3219 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3220 write_struct_expr(file, eval->expr, 1, fields, var_name);
3221 fprintf(file, ";\n");
3222 print_file(file, 0, "}\n\n");
3223 callback_offset++;
3225 return result;
3228 void write_expr_eval_routine_list(FILE *file, const char *iface)
3230 struct expr_eval_routine *eval;
3231 struct expr_eval_routine *cursor;
3232 unsigned short callback_offset = 0;
3234 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3235 fprintf(file, "{\n");
3237 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3239 const char *name = eval->structure->name;
3240 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3241 callback_offset++;
3242 list_remove(&eval->entry);
3243 free(eval);
3246 fprintf(file, "};\n\n");
3249 void write_user_quad_list(FILE *file)
3251 user_type_t *ut;
3253 if (list_empty(&user_type_list))
3254 return;
3256 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3257 fprintf(file, "{\n");
3258 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3260 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3261 print_file(file, 1, "{\n");
3262 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3263 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3264 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3265 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3266 print_file(file, 1, "}%s\n", sep);
3268 fprintf(file, "};\n\n");
3271 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3273 const struct str_list_entry_t *endpoint;
3274 const char *p;
3276 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3277 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3278 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3280 print_file( f, 1, "{ (const unsigned char *)\"" );
3281 for (p = endpoint->str; *p && *p != ':'; p++)
3283 if (*p == '"' || *p == '\\') fputc( '\\', f );
3284 fputc( *p, f );
3286 if (!*p) goto error;
3287 if (p[1] != '[') goto error;
3289 fprintf( f, "\", (const unsigned char *)\"" );
3290 for (p += 2; *p && *p != ']'; p++)
3292 if (*p == '"' || *p == '\\') fputc( '\\', f );
3293 fputc( *p, f );
3295 if (*p != ']') goto error;
3296 fprintf( f, "\" },\n" );
3298 print_file( f, 0, "};\n\n" );
3299 return;
3301 error:
3302 error("Invalid endpoint syntax '%s'\n", endpoint->str);