widl: Detect conformant arrays of user types correctly.
[wine/testsucceed.git] / tools / widl / typegen.c
blob2245524cc5642995216d04e5eba0e9f19896df2a
1 /*
2 * Format String Generator for IDL Compiler
4 * Copyright 2005-2006 Eric Kohl
5 * Copyright 2005-2006 Robert Shearman
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <string.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <signal.h>
34 #include <limits.h>
36 #include "widl.h"
37 #include "utils.h"
38 #include "parser.h"
39 #include "header.h"
40 #include "windef.h"
41 #include "wine/list.h"
43 #include "widl.h"
44 #include "typegen.h"
46 static const func_t *current_func;
47 static const type_t *current_structure;
49 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
50 struct expr_eval_routine
52 struct list entry;
53 const type_t *structure;
54 unsigned int baseoff;
55 const expr_t *expr;
58 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
59 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
60 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
61 const char *name, int write_ptr, unsigned int *tfsoff);
62 static const var_t *find_array_or_string_in_struct(const type_t *type);
64 const char *string_of_type(unsigned char type)
66 switch (type)
68 case RPC_FC_BYTE: return "FC_BYTE";
69 case RPC_FC_CHAR: return "FC_CHAR";
70 case RPC_FC_SMALL: return "FC_SMALL";
71 case RPC_FC_USMALL: return "FC_USMALL";
72 case RPC_FC_WCHAR: return "FC_WCHAR";
73 case RPC_FC_SHORT: return "FC_SHORT";
74 case RPC_FC_USHORT: return "FC_USHORT";
75 case RPC_FC_LONG: return "FC_LONG";
76 case RPC_FC_ULONG: return "FC_ULONG";
77 case RPC_FC_FLOAT: return "FC_FLOAT";
78 case RPC_FC_HYPER: return "FC_HYPER";
79 case RPC_FC_DOUBLE: return "FC_DOUBLE";
80 case RPC_FC_ENUM16: return "FC_ENUM16";
81 case RPC_FC_ENUM32: return "FC_ENUM32";
82 case RPC_FC_IGNORE: return "FC_IGNORE";
83 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
84 case RPC_FC_RP: return "FC_RP";
85 case RPC_FC_UP: return "FC_UP";
86 case RPC_FC_OP: return "FC_OP";
87 case RPC_FC_FP: return "FC_FP";
88 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
89 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
90 case RPC_FC_STRUCT: return "FC_STRUCT";
91 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
92 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
93 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
94 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
95 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
96 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
97 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
98 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
99 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
100 case RPC_FC_CARRAY: return "FC_CARRAY";
101 case RPC_FC_CVARRAY: return "FC_CVARRAY";
102 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
103 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
104 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
105 case RPC_FC_POINTER: return "FC_POINTER";
106 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
107 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
108 case RPC_FC_CSTRING: return "FC_CSTRING";
109 case RPC_FC_WSTRING: return "FC_WSTRING";
110 default:
111 error("string_of_type: unknown type 0x%02x\n", type);
112 return NULL;
116 int is_struct(unsigned char type)
118 switch (type)
120 case RPC_FC_STRUCT:
121 case RPC_FC_PSTRUCT:
122 case RPC_FC_CSTRUCT:
123 case RPC_FC_CPSTRUCT:
124 case RPC_FC_CVSTRUCT:
125 case RPC_FC_BOGUS_STRUCT:
126 return 1;
127 default:
128 return 0;
132 static int is_non_complex_struct(const type_t *type)
134 switch (type->type)
136 case RPC_FC_STRUCT:
137 case RPC_FC_PSTRUCT:
138 case RPC_FC_CSTRUCT:
139 case RPC_FC_CPSTRUCT:
140 case RPC_FC_CVSTRUCT:
141 return 1;
142 default:
143 return 0;
147 int is_union(unsigned char type)
149 switch (type)
151 case RPC_FC_ENCAPSULATED_UNION:
152 case RPC_FC_NON_ENCAPSULATED_UNION:
153 return 1;
154 default:
155 return 0;
159 static unsigned short user_type_offset(const char *name)
161 user_type_t *ut;
162 unsigned short off = 0;
163 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
165 if (strcmp(name, ut->name) == 0)
166 return off;
167 ++off;
169 error("user_type_offset: couldn't find type (%s)\n", name);
170 return 0;
173 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
175 type->typestring_offset = offset;
176 if (file) type->tfswrite = FALSE;
179 static void guard_rec(type_t *type)
181 /* types that contain references to themselves (like a linked list),
182 need to be shielded from infinite recursion when writing embedded
183 types */
184 if (type->typestring_offset)
185 type->tfswrite = FALSE;
186 else
187 type->typestring_offset = 1;
190 static type_t *get_user_type(const type_t *t, const char **pname)
192 for (;;)
194 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
195 if (ut)
197 if (pname)
198 *pname = t->name;
199 return ut;
202 if (t->kind == TKIND_ALIAS)
203 t = t->orig;
204 else
205 return 0;
209 int is_user_type(const type_t *t)
211 return get_user_type(t, NULL) != NULL;
214 static int is_embedded_complex(const type_t *type)
216 unsigned char tc = type->type;
217 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
218 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
221 static const char *get_context_handle_type_name(const type_t *type)
223 const type_t *t;
224 for (t = type; is_ptr(t); t = t->ref)
225 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
226 return t->name;
227 assert(0);
228 return NULL;
231 static int compare_expr(const expr_t *a, const expr_t *b)
233 int ret;
235 if (a->type != b->type)
236 return a->type - b->type;
238 switch (a->type)
240 case EXPR_NUM:
241 case EXPR_HEXNUM:
242 case EXPR_TRUEFALSE:
243 return a->u.lval - b->u.lval;
244 case EXPR_DOUBLE:
245 return a->u.dval - b->u.dval;
246 case EXPR_IDENTIFIER:
247 return strcmp(a->u.sval, b->u.sval);
248 case EXPR_COND:
249 ret = compare_expr(a->ref, b->ref);
250 if (ret != 0)
251 return ret;
252 ret = compare_expr(a->u.ext, b->u.ext);
253 if (ret != 0)
254 return ret;
255 return compare_expr(a->ext2, b->ext2);
256 case EXPR_OR:
257 case EXPR_AND:
258 case EXPR_ADD:
259 case EXPR_SUB:
260 case EXPR_MUL:
261 case EXPR_DIV:
262 case EXPR_SHL:
263 case EXPR_SHR:
264 ret = compare_expr(a->ref, b->ref);
265 if (ret != 0)
266 return ret;
267 return compare_expr(a->u.ext, b->u.ext);
268 case EXPR_NOT:
269 case EXPR_NEG:
270 case EXPR_PPTR:
271 case EXPR_CAST:
272 case EXPR_SIZEOF:
273 return compare_expr(a->ref, b->ref);
274 case EXPR_VOID:
275 return 0;
277 return -1;
280 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
281 do { \
282 if (file) \
283 fprintf(file, "/* %2u */\n", typestring_offset); \
284 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
286 while (0)
288 static void print_file(FILE *file, int indent, const char *format, ...)
290 va_list va;
291 va_start(va, format);
292 print(file, indent, format, va);
293 va_end(va);
296 void print(FILE *file, int indent, const char *format, va_list va)
298 if (file)
300 if (format[0] != '\n')
301 while (0 < indent--)
302 fprintf(file, " ");
303 vfprintf(file, format, va);
307 void write_parameters_init(FILE *file, int indent, const func_t *func)
309 const var_t *var;
311 if (!func->args)
312 return;
314 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
316 const type_t *t = var->type;
317 const char *n = var->name;
318 if (decl_indirect(t))
319 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
320 else if (is_ptr(t) || is_array(t))
321 print_file(file, indent, "%s = 0;\n", n);
324 fprintf(file, "\n");
327 static void write_formatdesc(FILE *f, int indent, const char *str)
329 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
330 print_file(f, indent, "{\n");
331 print_file(f, indent + 1, "short Pad;\n");
332 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
333 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
334 print_file(f, indent, "\n");
337 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
339 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
340 get_size_typeformatstring(ifaces, pred));
342 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
343 get_size_procformatstring(ifaces, pred));
345 fprintf(f, "\n");
346 write_formatdesc(f, indent, "TYPE");
347 write_formatdesc(f, indent, "PROC");
348 fprintf(f, "\n");
349 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
350 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
351 print_file(f, indent, "\n");
354 static inline int is_base_type(unsigned char type)
356 switch (type)
358 case RPC_FC_BYTE:
359 case RPC_FC_CHAR:
360 case RPC_FC_USMALL:
361 case RPC_FC_SMALL:
362 case RPC_FC_WCHAR:
363 case RPC_FC_USHORT:
364 case RPC_FC_SHORT:
365 case RPC_FC_ULONG:
366 case RPC_FC_LONG:
367 case RPC_FC_HYPER:
368 case RPC_FC_IGNORE:
369 case RPC_FC_FLOAT:
370 case RPC_FC_DOUBLE:
371 case RPC_FC_ENUM16:
372 case RPC_FC_ENUM32:
373 case RPC_FC_ERROR_STATUS_T:
374 case RPC_FC_BIND_PRIMITIVE:
375 return TRUE;
377 default:
378 return FALSE;
382 int decl_indirect(const type_t *t)
384 return is_user_type(t)
385 || (!is_base_type(t->type)
386 && !is_ptr(t)
387 && !is_array(t));
390 static size_t write_procformatstring_var(FILE *file, int indent,
391 const var_t *var, int is_return)
393 size_t size;
394 const type_t *type = var->type;
396 int is_in = is_attr(var->attrs, ATTR_IN);
397 int is_out = is_attr(var->attrs, ATTR_OUT);
399 if (!is_in && !is_out) is_in = TRUE;
401 if (!type->declarray && is_base_type(type->type))
403 if (is_return)
404 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
405 else
406 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
408 if (type->type == RPC_FC_BIND_PRIMITIVE)
410 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
411 size = 2; /* includes param type prefix */
413 else if (is_base_type(type->type))
415 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
416 size = 2; /* includes param type prefix */
418 else
420 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
421 size = 0;
424 else
426 if (is_return)
427 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
428 else if (is_in && is_out)
429 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
430 else if (is_out)
431 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
432 else
433 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
435 print_file(file, indent, "0x01,\n");
436 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
437 size = 4; /* includes param type prefix */
439 return size;
442 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
444 const ifref_t *iface;
445 int indent = 0;
446 const var_t *var;
448 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
449 print_file(file, indent, "{\n");
450 indent++;
451 print_file(file, indent, "0,\n");
452 print_file(file, indent, "{\n");
453 indent++;
455 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
457 if (!pred(iface->iface))
458 continue;
460 if (iface->iface->funcs)
462 const func_t *func;
463 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
465 if (is_local(func->def->attrs)) continue;
466 /* emit argument data */
467 if (func->args)
469 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
470 write_procformatstring_var(file, indent, var, FALSE);
473 /* emit return value data */
474 var = func->def;
475 if (is_void(var->type))
477 print_file(file, indent, "0x5b, /* FC_END */\n");
478 print_file(file, indent, "0x5c, /* FC_PAD */\n");
480 else
481 write_procformatstring_var(file, indent, var, TRUE);
486 print_file(file, indent, "0x0\n");
487 indent--;
488 print_file(file, indent, "}\n");
489 indent--;
490 print_file(file, indent, "};\n");
491 print_file(file, indent, "\n");
494 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
496 if (is_base_type(type->type))
498 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
499 *typestring_offset += 1;
500 return 1;
503 return 0;
506 /* write conformance / variance descriptor */
507 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
508 unsigned int baseoff, const type_t *type,
509 const expr_t *expr)
511 unsigned char operator_type = 0;
512 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
513 const char *conftype_string = "";
514 const char *operator_string = "no operators";
515 const expr_t *subexpr;
517 if (!expr)
519 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
520 return 4;
523 if (!structure)
525 /* Top-level conformance calculations are done inline. */
526 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
527 RPC_FC_TOP_LEVEL_CONFORMANCE);
528 print_file (file, 2, "0x0,\n");
529 print_file (file, 2, "NdrFcShort(0x0),\n");
530 return 4;
533 if (expr->is_const)
535 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
536 error("write_conf_or_var_desc: constant value %ld is greater than "
537 "the maximum constant size of %d\n", expr->cval,
538 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
540 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
541 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
542 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
543 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
545 return 4;
548 if (is_ptr(type) || (is_array(type) && !type->declarray))
550 conftype = RPC_FC_POINTER_CONFORMANCE;
551 conftype_string = "field pointer, ";
554 subexpr = expr;
555 switch (subexpr->type)
557 case EXPR_PPTR:
558 subexpr = subexpr->ref;
559 operator_type = RPC_FC_DEREFERENCE;
560 operator_string = "FC_DEREFERENCE";
561 break;
562 case EXPR_DIV:
563 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
565 subexpr = subexpr->ref;
566 operator_type = RPC_FC_DIV_2;
567 operator_string = "FC_DIV_2";
569 break;
570 case EXPR_MUL:
571 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
573 subexpr = subexpr->ref;
574 operator_type = RPC_FC_MULT_2;
575 operator_string = "FC_MULT_2";
577 break;
578 case EXPR_SUB:
579 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
581 subexpr = subexpr->ref;
582 operator_type = RPC_FC_SUB_1;
583 operator_string = "FC_SUB_1";
585 break;
586 case EXPR_ADD:
587 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
589 subexpr = subexpr->ref;
590 operator_type = RPC_FC_ADD_1;
591 operator_string = "FC_ADD_1";
593 break;
594 default:
595 break;
598 if (subexpr->type == EXPR_IDENTIFIER)
600 const type_t *correlation_variable = NULL;
601 unsigned char correlation_variable_type;
602 unsigned char param_type = 0;
603 size_t offset = 0;
604 const var_t *var;
606 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
608 unsigned int align = 0;
609 /* FIXME: take alignment into account */
610 if (var->name && !strcmp(var->name, subexpr->u.sval))
612 correlation_variable = var->type;
613 break;
615 offset += type_memsize(var->type, &align);
617 if (!correlation_variable)
618 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
619 subexpr->u.sval);
621 offset -= baseoff;
622 correlation_variable_type = correlation_variable->type;
624 switch (correlation_variable_type)
626 case RPC_FC_CHAR:
627 case RPC_FC_SMALL:
628 param_type = RPC_FC_SMALL;
629 break;
630 case RPC_FC_BYTE:
631 case RPC_FC_USMALL:
632 param_type = RPC_FC_USMALL;
633 break;
634 case RPC_FC_WCHAR:
635 case RPC_FC_SHORT:
636 case RPC_FC_ENUM16:
637 param_type = RPC_FC_SHORT;
638 break;
639 case RPC_FC_USHORT:
640 param_type = RPC_FC_USHORT;
641 break;
642 case RPC_FC_LONG:
643 case RPC_FC_ENUM32:
644 param_type = RPC_FC_LONG;
645 break;
646 case RPC_FC_ULONG:
647 param_type = RPC_FC_ULONG;
648 break;
649 case RPC_FC_RP:
650 case RPC_FC_UP:
651 case RPC_FC_OP:
652 case RPC_FC_FP:
653 if (sizeof(void *) == 4) /* FIXME */
654 param_type = RPC_FC_LONG;
655 else
656 param_type = RPC_FC_HYPER;
657 break;
658 default:
659 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
660 correlation_variable_type);
663 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
664 conftype | param_type, conftype_string, string_of_type(param_type));
665 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
666 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
667 offset, offset);
669 else
671 unsigned int callback_offset = 0;
672 struct expr_eval_routine *eval;
673 int found = 0;
675 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
677 if (!strcmp (eval->structure->name, structure->name)
678 && !compare_expr (eval->expr, expr))
680 found = 1;
681 break;
683 callback_offset++;
686 if (!found)
688 eval = xmalloc (sizeof(*eval));
689 eval->structure = structure;
690 eval->baseoff = baseoff;
691 eval->expr = expr;
692 list_add_tail (&expr_eval_routines, &eval->entry);
695 if (callback_offset > USHRT_MAX)
696 error("Maximum number of callback routines reached\n");
698 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
699 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
700 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
702 return 4;
705 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
707 int have_align = FALSE;
708 size_t size = 0;
709 const var_t *v;
711 if (!fields) return 0;
712 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
714 unsigned int falign = 0;
715 size_t fsize = type_memsize(v->type, &falign);
716 if (!have_align)
718 *align = falign;
719 have_align = TRUE;
721 size = (size + (falign - 1)) & ~(falign - 1);
722 size += fsize;
725 size = (size + (*align - 1)) & ~(*align - 1);
726 return size;
729 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
731 size_t size, maxs = 0;
732 unsigned int align = *pmaxa;
733 const var_t *v;
735 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
737 /* we could have an empty default field with NULL type */
738 if (v->type)
740 size = type_memsize(v->type, &align);
741 if (maxs < size) maxs = size;
742 if (*pmaxa < align) *pmaxa = align;
746 return maxs;
749 int get_padding(const var_list_t *fields)
751 unsigned short offset = 0;
752 int salign = -1;
753 const var_t *f;
755 if (!fields)
756 return 0;
758 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
760 type_t *ft = f->type;
761 unsigned int align = 0;
762 size_t size = type_memsize(ft, &align);
763 if (salign == -1)
764 salign = align;
765 offset = (offset + (align - 1)) & ~(align - 1);
766 offset += size;
769 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
772 size_t type_memsize(const type_t *t, unsigned int *align)
774 size_t size = 0;
776 if (t->declarray && is_conformant_array(t))
778 type_memsize(t->ref, align);
779 size = 0;
781 else if (is_ptr(t) || is_conformant_array(t))
783 size = sizeof(void *);
784 if (size > *align) *align = size;
786 else switch (t->type)
788 case RPC_FC_BYTE:
789 case RPC_FC_CHAR:
790 case RPC_FC_USMALL:
791 case RPC_FC_SMALL:
792 size = 1;
793 if (size > *align) *align = size;
794 break;
795 case RPC_FC_WCHAR:
796 case RPC_FC_USHORT:
797 case RPC_FC_SHORT:
798 case RPC_FC_ENUM16:
799 size = 2;
800 if (size > *align) *align = size;
801 break;
802 case RPC_FC_ULONG:
803 case RPC_FC_LONG:
804 case RPC_FC_ERROR_STATUS_T:
805 case RPC_FC_ENUM32:
806 case RPC_FC_FLOAT:
807 size = 4;
808 if (size > *align) *align = size;
809 break;
810 case RPC_FC_HYPER:
811 case RPC_FC_DOUBLE:
812 size = 8;
813 if (size > *align) *align = size;
814 break;
815 case RPC_FC_STRUCT:
816 case RPC_FC_CVSTRUCT:
817 case RPC_FC_CPSTRUCT:
818 case RPC_FC_CSTRUCT:
819 case RPC_FC_PSTRUCT:
820 case RPC_FC_BOGUS_STRUCT:
821 size = fields_memsize(t->fields, align);
822 break;
823 case RPC_FC_ENCAPSULATED_UNION:
824 case RPC_FC_NON_ENCAPSULATED_UNION:
825 size = union_memsize(t->fields, align);
826 break;
827 case RPC_FC_SMFARRAY:
828 case RPC_FC_LGFARRAY:
829 case RPC_FC_SMVARRAY:
830 case RPC_FC_LGVARRAY:
831 case RPC_FC_BOGUS_ARRAY:
832 size = t->dim * type_memsize(t->ref, align);
833 break;
834 default:
835 error("type_memsize: Unknown type %d\n", t->type);
836 size = 0;
839 return size;
842 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
844 short absoff = type->ref->typestring_offset;
845 short reloff = absoff - (offset + 2);
846 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
848 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
849 type->type, ptr_attr, string_of_type(type->type));
850 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
851 reloff, reloff, absoff);
852 return 4;
855 static unsigned char conf_string_type_of_char_type(unsigned char t)
857 switch (t)
859 case RPC_FC_BYTE:
860 case RPC_FC_CHAR:
861 return RPC_FC_C_CSTRING;
862 case RPC_FC_WCHAR:
863 return RPC_FC_C_WSTRING;
866 error("string_type_of_char_type: unrecognized type %d", t);
867 return 0;
870 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
872 unsigned char fc
873 = is_string_type(type->attrs, type)
874 ? conf_string_type_of_char_type(type->ref->type)
875 : type->ref->type;
876 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
877 type->type, string_of_type(type->type));
878 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
879 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
880 return 4;
883 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
885 print_file(file, 0, "/* %u (", tfsoff);
886 write_type_decl(file, t, NULL);
887 print_file(file, 0, ") */\n");
890 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
892 unsigned int offset = *typestring_offset;
894 print_start_tfs_comment(file, type, offset);
895 update_tfsoff(type, offset, file);
897 if (type->ref->typestring_offset)
898 *typestring_offset += write_nonsimple_pointer(file, type, offset);
899 else if (is_base_type(type->ref->type))
900 *typestring_offset += write_simple_pointer(file, type);
902 return offset;
905 static int processed(const type_t *type)
907 return type->typestring_offset && !type->tfswrite;
910 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
912 unsigned int start, absoff, flags;
913 unsigned int align = 0, ualign = 0;
914 const char *name;
915 type_t *utype = get_user_type(type, &name);
916 size_t usize = type_memsize(utype, &ualign);
917 size_t size = type_memsize(type, &align);
918 unsigned short funoff = user_type_offset(name);
919 short reloff;
921 guard_rec(type);
923 if (is_base_type(utype->type))
925 absoff = *tfsoff;
926 print_start_tfs_comment(file, utype, absoff);
927 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
928 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
929 *tfsoff += 2;
931 else
933 if (!processed(utype))
934 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
935 absoff = utype->typestring_offset;
938 if (utype->type == RPC_FC_RP)
939 flags = 0x40;
940 else if (utype->type == RPC_FC_UP)
941 flags = 0x80;
942 else
943 flags = 0;
945 start = *tfsoff;
946 update_tfsoff(type, start, file);
947 print_start_tfs_comment(file, type, start);
948 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
949 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
950 flags | (align - 1), align - 1, flags);
951 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
952 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
953 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
954 *tfsoff += 8;
955 reloff = absoff - *tfsoff;
956 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
957 *tfsoff += 2;
960 static void write_member_type(FILE *file, const type_t *cont,
961 const attr_list_t *attrs, const type_t *type,
962 unsigned int *corroff, unsigned int *tfsoff)
964 if (is_embedded_complex(type) && !is_conformant_array(type))
966 size_t absoff;
967 short reloff;
969 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
971 absoff = *corroff;
972 *corroff += 8;
974 else
976 absoff = type->typestring_offset;
978 reloff = absoff - (*tfsoff + 2);
980 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
981 /* FIXME: actually compute necessary padding */
982 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
983 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
984 reloff, reloff, absoff);
985 *tfsoff += 4;
987 else if (is_ptr(type) || is_conformant_array(type))
989 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
990 ? RPC_FC_POINTER
991 : RPC_FC_LONG);
992 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
993 *tfsoff += 1;
995 else if (!write_base_type(file, type, tfsoff))
996 error("Unsupported member type 0x%x\n", type->type);
999 static void write_end(FILE *file, unsigned int *tfsoff)
1001 if (*tfsoff % 2 == 0)
1003 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1004 *tfsoff += 1;
1006 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1007 *tfsoff += 1;
1010 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1012 unsigned int offset = 0;
1013 var_list_t *fs = type->fields;
1014 var_t *f;
1016 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1018 unsigned int align = 0;
1019 type_t *ft = f->type;
1020 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1022 unsigned int absoff = ft->typestring_offset;
1023 short reloff = absoff - (*tfsoff + 6);
1024 print_file(file, 0, "/* %d */\n", *tfsoff);
1025 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1026 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1027 write_conf_or_var_desc(file, current_structure, offset, ft,
1028 get_attrp(f->attrs, ATTR_SWITCHIS));
1029 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1030 reloff, reloff, absoff);
1031 *tfsoff += 8;
1034 /* FIXME: take alignment into account */
1035 offset += type_memsize(ft, &align);
1039 static int write_no_repeat_pointer_descriptions(
1040 FILE *file, type_t *type,
1041 size_t *offset_in_memory, size_t *offset_in_buffer,
1042 unsigned int *typestring_offset)
1044 int written = 0;
1045 unsigned int align;
1047 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1049 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1050 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1052 /* pointer instance */
1053 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1054 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1055 *typestring_offset += 6;
1057 if (is_ptr(type))
1058 write_pointer_tfs(file, type, typestring_offset);
1059 else
1061 unsigned absoff = type->typestring_offset;
1062 short reloff = absoff - (*typestring_offset + 2);
1063 /* FIXME: get pointer attributes from field */
1064 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1065 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1066 reloff, reloff, absoff);
1067 *typestring_offset += 4;
1070 align = 0;
1071 *offset_in_memory += type_memsize(type, &align);
1072 /* FIXME: is there a case where these two are different? */
1073 align = 0;
1074 *offset_in_buffer += type_memsize(type, &align);
1076 return 1;
1079 if (is_non_complex_struct(type))
1081 const var_t *v;
1082 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1083 written += write_no_repeat_pointer_descriptions(
1084 file, v->type,
1085 offset_in_memory, offset_in_buffer, typestring_offset);
1087 else
1089 align = 0;
1090 *offset_in_memory += type_memsize(type, &align);
1091 /* FIXME: is there a case where these two are different? */
1092 align = 0;
1093 *offset_in_buffer += type_memsize(type, &align);
1096 return written;
1099 static int write_pointer_description_offsets(
1100 FILE *file, const attr_list_t *attrs, type_t *type,
1101 size_t *offset_in_memory, size_t *offset_in_buffer,
1102 unsigned int *typestring_offset)
1104 int written = 0;
1105 unsigned int align;
1107 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1109 if (offset_in_memory && offset_in_buffer)
1111 /* pointer instance */
1112 /* FIXME: sometimes from end of structure, sometimes from beginning */
1113 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1114 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1116 align = 0;
1117 *offset_in_memory += type_memsize(type, &align);
1118 /* FIXME: is there a case where these two are different? */
1119 align = 0;
1120 *offset_in_buffer += type_memsize(type, &align);
1122 *typestring_offset += 4;
1124 if (processed(type->ref) || is_base_type(type->ref->type))
1125 write_pointer_tfs(file, type, typestring_offset);
1126 else
1127 error("write_pointer_description_offsets: type format string unknown\n");
1129 return 1;
1132 if (is_array(type))
1134 return write_pointer_description_offsets(
1135 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1136 typestring_offset);
1138 else if (is_non_complex_struct(type))
1140 /* otherwise search for interesting fields to parse */
1141 const var_t *v;
1142 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1144 written += write_pointer_description_offsets(
1145 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1146 typestring_offset);
1149 else
1151 align = 0;
1152 if (offset_in_memory)
1153 *offset_in_memory += type_memsize(type, &align);
1154 /* FIXME: is there a case where these two are different? */
1155 align = 0;
1156 if (offset_in_buffer)
1157 *offset_in_buffer += type_memsize(type, &align);
1160 return written;
1163 /* Note: if file is NULL return value is number of pointers to write, else
1164 * it is the number of type format characters written */
1165 static int write_fixed_array_pointer_descriptions(
1166 FILE *file, const attr_list_t *attrs, type_t *type,
1167 size_t *offset_in_memory, size_t *offset_in_buffer,
1168 unsigned int *typestring_offset)
1170 unsigned int align;
1171 int pointer_count = 0;
1173 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1175 unsigned int temp = 0;
1176 /* unfortunately, this needs to be done in two passes to avoid
1177 * writing out redundant FC_FIXED_REPEAT descriptions */
1178 pointer_count = write_pointer_description_offsets(
1179 NULL, attrs, type->ref, NULL, NULL, &temp);
1180 if (pointer_count > 0)
1182 unsigned int increment_size;
1183 size_t offset_of_array_pointer_mem = 0;
1184 size_t offset_of_array_pointer_buf = 0;
1186 align = 0;
1187 increment_size = type_memsize(type->ref, &align);
1189 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1190 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1191 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1192 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1193 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1194 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1195 *typestring_offset += 10;
1197 pointer_count = write_pointer_description_offsets(
1198 file, attrs, type, &offset_of_array_pointer_mem,
1199 &offset_of_array_pointer_buf, typestring_offset);
1202 else if (is_struct(type->type))
1204 const var_t *v;
1205 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1207 pointer_count += write_fixed_array_pointer_descriptions(
1208 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1209 typestring_offset);
1212 else
1214 align = 0;
1215 if (offset_in_memory)
1216 *offset_in_memory += type_memsize(type, &align);
1217 /* FIXME: is there a case where these two are different? */
1218 align = 0;
1219 if (offset_in_buffer)
1220 *offset_in_buffer += type_memsize(type, &align);
1223 return pointer_count;
1226 /* Note: if file is NULL return value is number of pointers to write, else
1227 * it is the number of type format characters written */
1228 static int write_conformant_array_pointer_descriptions(
1229 FILE *file, const attr_list_t *attrs, type_t *type,
1230 size_t offset_in_memory, unsigned int *typestring_offset)
1232 unsigned int align;
1233 int pointer_count = 0;
1235 if (is_conformant_array(type) && !type->length_is)
1237 unsigned int temp = 0;
1238 /* unfortunately, this needs to be done in two passes to avoid
1239 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1240 pointer_count = write_pointer_description_offsets(
1241 NULL, attrs, type->ref, NULL, NULL, &temp);
1242 if (pointer_count > 0)
1244 unsigned int increment_size;
1245 size_t offset_of_array_pointer_mem = offset_in_memory;
1246 size_t offset_of_array_pointer_buf = offset_in_memory;
1248 align = 0;
1249 increment_size = type_memsize(type->ref, &align);
1251 if (increment_size > USHRT_MAX)
1252 error("array size of %u bytes is too large\n", increment_size);
1254 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1255 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1256 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1257 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1258 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1259 *typestring_offset += 8;
1261 pointer_count = write_pointer_description_offsets(
1262 file, attrs, type->ref, &offset_of_array_pointer_mem,
1263 &offset_of_array_pointer_buf, typestring_offset);
1267 return pointer_count;
1270 /* Note: if file is NULL return value is number of pointers to write, else
1271 * it is the number of type format characters written */
1272 static int write_varying_array_pointer_descriptions(
1273 FILE *file, const attr_list_t *attrs, type_t *type,
1274 size_t *offset_in_memory, size_t *offset_in_buffer,
1275 unsigned int *typestring_offset)
1277 unsigned int align;
1278 int pointer_count = 0;
1280 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1282 if (is_array(type) && type->length_is)
1284 unsigned int temp = 0;
1285 /* unfortunately, this needs to be done in two passes to avoid
1286 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1287 pointer_count = write_pointer_description_offsets(
1288 NULL, attrs, type->ref, NULL, NULL, &temp);
1289 if (pointer_count > 0)
1291 unsigned int increment_size;
1292 size_t offset_of_array_pointer_mem = 0;
1293 size_t offset_of_array_pointer_buf = 0;
1295 align = 0;
1296 increment_size = type_memsize(type->ref, &align);
1298 if (increment_size > USHRT_MAX)
1299 error("array size of %u bytes is too large\n", increment_size);
1301 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1302 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1303 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1304 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1305 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1306 *typestring_offset += 8;
1308 pointer_count = write_pointer_description_offsets(
1309 file, attrs, type, &offset_of_array_pointer_mem,
1310 &offset_of_array_pointer_buf, typestring_offset);
1313 else if (is_struct(type->type))
1315 const var_t *v;
1316 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1318 pointer_count += write_varying_array_pointer_descriptions(
1319 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1320 typestring_offset);
1323 else
1325 align = 0;
1326 if (offset_in_memory)
1327 *offset_in_memory += type_memsize(type, &align);
1328 /* FIXME: is there a case where these two are different? */
1329 align = 0;
1330 if (offset_in_buffer)
1331 *offset_in_buffer += type_memsize(type, &align);
1334 return pointer_count;
1337 static void write_pointer_description(FILE *file, type_t *type,
1338 unsigned int *typestring_offset)
1340 size_t offset_in_buffer;
1341 size_t offset_in_memory;
1343 /* pass 1: search for single instance of a pointer (i.e. don't descend
1344 * into arrays) */
1345 if (!is_array(type))
1347 offset_in_memory = 0;
1348 offset_in_buffer = 0;
1349 write_no_repeat_pointer_descriptions(
1350 file, type,
1351 &offset_in_memory, &offset_in_buffer, typestring_offset);
1354 /* pass 2: search for pointers in fixed arrays */
1355 offset_in_memory = 0;
1356 offset_in_buffer = 0;
1357 write_fixed_array_pointer_descriptions(
1358 file, NULL, type,
1359 &offset_in_memory, &offset_in_buffer, typestring_offset);
1361 /* pass 3: search for pointers in conformant only arrays (but don't descend
1362 * into conformant varying or varying arrays) */
1363 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1364 write_conformant_array_pointer_descriptions(
1365 file, NULL, type, 0, typestring_offset);
1366 else if (type->type == RPC_FC_CPSTRUCT)
1368 unsigned int align = 0;
1369 type_t *carray = find_array_or_string_in_struct(type)->type;
1370 write_conformant_array_pointer_descriptions(
1371 file, NULL, carray,
1372 type_memsize(type, &align),
1373 typestring_offset);
1376 /* pass 4: search for pointers in varying arrays */
1377 offset_in_memory = 0;
1378 offset_in_buffer = 0;
1379 write_varying_array_pointer_descriptions(
1380 file, NULL, type,
1381 &offset_in_memory, &offset_in_buffer, typestring_offset);
1384 static int is_declptr(const type_t *t)
1386 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1389 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1390 type_t *type,
1391 const char *name, unsigned int *typestring_offset)
1393 size_t start_offset = *typestring_offset;
1394 unsigned char rtype;
1396 update_tfsoff(type, start_offset, file);
1398 if (is_declptr(type))
1400 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1401 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1402 if (!pointer_type)
1403 pointer_type = RPC_FC_RP;
1404 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1405 pointer_type, flag, string_of_type(pointer_type),
1406 flag ? " [simple_pointer]" : "");
1407 *typestring_offset += 2;
1408 if (!flag)
1410 print_file(file, 2, "NdrFcShort(0x2),\n");
1411 *typestring_offset += 2;
1413 rtype = type->ref->type;
1415 else
1416 rtype = type->ref->type;
1418 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1420 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1421 return start_offset;
1424 if (type->declarray && !is_conformant_array(type))
1426 /* FIXME: multi-dimensional array */
1427 if (0xffffuL < type->dim)
1428 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1429 name, 0xffffu, type->dim - 0xffffu);
1431 if (rtype == RPC_FC_CHAR)
1432 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1433 else
1434 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1435 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1436 *typestring_offset += 2;
1438 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1439 *typestring_offset += 2;
1441 return start_offset;
1443 else if (type->size_is)
1445 unsigned int align = 0;
1447 if (rtype == RPC_FC_CHAR)
1448 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1449 else
1450 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1451 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1452 *typestring_offset += 2;
1454 *typestring_offset += write_conf_or_var_desc(
1455 file, current_structure,
1456 (type->declarray && current_structure
1457 ? type_memsize(current_structure, &align)
1458 : 0),
1459 type, type->size_is);
1461 return start_offset;
1463 else
1465 if (rtype == RPC_FC_WCHAR)
1466 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1467 else
1468 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1469 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1470 *typestring_offset += 2;
1472 return start_offset;
1476 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1477 const char *name, unsigned int *typestring_offset)
1479 const expr_t *length_is = type->length_is;
1480 const expr_t *size_is = type->size_is;
1481 unsigned int align = 0;
1482 size_t size;
1483 size_t start_offset;
1484 int has_pointer;
1485 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1486 unsigned int baseoff
1487 = type->declarray && current_structure
1488 ? type_memsize(current_structure, &align)
1489 : 0;
1491 if (!pointer_type)
1492 pointer_type = RPC_FC_RP;
1494 has_pointer = FALSE;
1495 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1496 has_pointer = TRUE;
1498 align = 0;
1499 size = type_memsize(type, &align);
1500 if (size == 0) /* conformant array */
1501 size = type_memsize(type->ref, &align);
1503 start_offset = *typestring_offset;
1504 update_tfsoff(type, start_offset, file);
1505 print_start_tfs_comment(file, type, start_offset);
1506 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1507 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1508 *typestring_offset += 2;
1510 align = 0;
1511 if (type->type != RPC_FC_BOGUS_ARRAY)
1513 unsigned char tc = type->type;
1515 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1517 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1518 *typestring_offset += 4;
1520 else
1522 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1523 *typestring_offset += 2;
1526 if (is_conformant_array(type))
1527 *typestring_offset
1528 += write_conf_or_var_desc(file, current_structure, baseoff,
1529 type, size_is);
1531 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1533 unsigned int elalign = 0;
1534 size_t elsize = type_memsize(type->ref, &elalign);
1536 if (type->type == RPC_FC_LGVARRAY)
1538 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1539 *typestring_offset += 4;
1541 else
1543 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1544 *typestring_offset += 2;
1547 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1548 *typestring_offset += 2;
1551 if (length_is)
1552 *typestring_offset
1553 += write_conf_or_var_desc(file, current_structure, baseoff,
1554 type, length_is);
1556 if (has_pointer && (!type->declarray || !current_structure))
1558 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1559 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1560 *typestring_offset += 2;
1561 write_pointer_description(file, type, typestring_offset);
1562 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1563 *typestring_offset += 1;
1566 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1567 write_end(file, typestring_offset);
1569 else
1571 unsigned int dim = size_is ? 0 : type->dim;
1572 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1573 *typestring_offset += 2;
1574 *typestring_offset
1575 += write_conf_or_var_desc(file, current_structure, baseoff,
1576 type, size_is);
1577 *typestring_offset
1578 += write_conf_or_var_desc(file, current_structure, baseoff,
1579 type, length_is);
1580 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1581 write_end(file, typestring_offset);
1584 return start_offset;
1587 static const var_t *find_array_or_string_in_struct(const type_t *type)
1589 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1590 const type_t *ft = last_field->type;
1592 if (ft->declarray && is_conformant_array(ft))
1593 return last_field;
1595 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1596 return find_array_or_string_in_struct(last_field->type);
1597 else
1598 return NULL;
1601 static void write_struct_members(FILE *file, const type_t *type,
1602 unsigned int *corroff, unsigned int *typestring_offset)
1604 const var_t *field;
1605 unsigned short offset = 0;
1606 int salign = -1;
1607 int padding;
1609 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1611 type_t *ft = field->type;
1612 if (!ft->declarray || !is_conformant_array(ft))
1614 unsigned int align = 0;
1615 size_t size = type_memsize(ft, &align);
1616 if (salign == -1)
1617 salign = align;
1618 if ((align - 1) & offset)
1620 unsigned char fc = 0;
1621 switch (align)
1623 case 4:
1624 fc = RPC_FC_ALIGNM4;
1625 break;
1626 case 8:
1627 fc = RPC_FC_ALIGNM8;
1628 break;
1629 default:
1630 error("write_struct_members: cannot align type %d\n", ft->type);
1632 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1633 offset = (offset + (align - 1)) & ~(align - 1);
1634 *typestring_offset += 1;
1636 write_member_type(file, type, field->attrs, field->type, corroff,
1637 typestring_offset);
1638 offset += size;
1642 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1643 if (padding)
1645 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1646 RPC_FC_STRUCTPAD1 + padding - 1,
1647 padding);
1648 *typestring_offset += 1;
1651 write_end(file, typestring_offset);
1654 static size_t write_struct_tfs(FILE *file, type_t *type,
1655 const char *name, unsigned int *tfsoff)
1657 const type_t *save_current_structure = current_structure;
1658 unsigned int total_size;
1659 const var_t *array;
1660 size_t start_offset;
1661 size_t array_offset;
1662 int has_pointers = 0;
1663 unsigned int align = 0;
1664 unsigned int corroff;
1665 var_t *f;
1667 guard_rec(type);
1668 current_structure = type;
1670 total_size = type_memsize(type, &align);
1671 if (total_size > USHRT_MAX)
1672 error("structure size for %s exceeds %d bytes by %d bytes\n",
1673 name, USHRT_MAX, total_size - USHRT_MAX);
1675 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1676 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1677 FALSE, tfsoff);
1679 array = find_array_or_string_in_struct(type);
1680 if (array && !processed(array->type))
1681 array_offset
1682 = is_attr(array->attrs, ATTR_STRING)
1683 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1684 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1686 corroff = *tfsoff;
1687 write_descriptors(file, type, tfsoff);
1689 start_offset = *tfsoff;
1690 update_tfsoff(type, start_offset, file);
1691 print_start_tfs_comment(file, type, start_offset);
1692 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1693 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1694 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1695 *tfsoff += 4;
1697 if (array)
1699 unsigned int absoff = array->type->typestring_offset;
1700 short reloff = absoff - *tfsoff;
1701 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1702 reloff, reloff, absoff);
1703 *tfsoff += 2;
1705 else if (type->type == RPC_FC_BOGUS_STRUCT)
1707 print_file(file, 2, "NdrFcShort(0x0),\n");
1708 *tfsoff += 2;
1711 if (type->type == RPC_FC_BOGUS_STRUCT)
1713 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1714 nothing is written to file yet. On the actual writing pass,
1715 this will have been updated. */
1716 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1717 short reloff = absoff - *tfsoff;
1718 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1719 reloff, reloff, absoff);
1720 *tfsoff += 2;
1722 else if ((type->type == RPC_FC_PSTRUCT) ||
1723 (type->type == RPC_FC_CPSTRUCT) ||
1724 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1726 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1727 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1728 *tfsoff += 2;
1729 write_pointer_description(file, type, tfsoff);
1730 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1731 *tfsoff += 1;
1734 write_struct_members(file, type, &corroff, tfsoff);
1736 if (type->type == RPC_FC_BOGUS_STRUCT)
1738 const var_list_t *fs = type->fields;
1739 const var_t *f;
1741 type->ptrdesc = *tfsoff;
1742 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1744 type_t *ft = f->type;
1745 if (is_ptr(ft))
1746 write_pointer_tfs(file, ft, tfsoff);
1747 else if (!ft->declarray && is_conformant_array(ft))
1749 unsigned int absoff = ft->typestring_offset;
1750 short reloff = absoff - (*tfsoff + 2);
1751 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1752 /* FIXME: We need to store pointer attributes for arrays
1753 so we don't lose pointer_default info. */
1754 if (ptr_type == 0)
1755 ptr_type = RPC_FC_UP;
1756 print_file(file, 0, "/* %d */\n", *tfsoff);
1757 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1758 string_of_type(ptr_type));
1759 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1760 reloff, reloff, absoff);
1761 *tfsoff += 4;
1764 if (type->ptrdesc == *tfsoff)
1765 type->ptrdesc = 0;
1768 current_structure = save_current_structure;
1769 return start_offset;
1772 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1773 unsigned char flags, size_t offset,
1774 unsigned int *typeformat_offset)
1776 size_t start_offset = *typeformat_offset;
1777 short reloff = offset - (*typeformat_offset + 2);
1778 int in_attr, out_attr;
1779 in_attr = is_attr(attrs, ATTR_IN);
1780 out_attr = is_attr(attrs, ATTR_OUT);
1781 if (!in_attr && !out_attr) in_attr = 1;
1783 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1784 flags |= 0x04;
1786 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1787 pointer_type,
1788 flags,
1789 string_of_type(pointer_type));
1790 if (file)
1792 if (flags & 0x04)
1793 fprintf(file, " [allocated_on_stack]");
1794 if (flags & 0x10)
1795 fprintf(file, " [pointer_deref]");
1796 fprintf(file, " */\n");
1799 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1800 *typeformat_offset += 4;
1802 return start_offset;
1805 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1807 if (t == NULL)
1809 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1811 else if (is_base_type(t->type))
1813 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1814 t->type, string_of_type(t->type));
1816 else if (t->typestring_offset)
1818 short reloff = t->typestring_offset - *tfsoff;
1819 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1820 reloff, reloff, t->typestring_offset);
1822 else
1823 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1825 *tfsoff += 2;
1828 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1830 unsigned int align = 0;
1831 unsigned int start_offset;
1832 size_t size = type_memsize(type, &align);
1833 var_list_t *fields;
1834 size_t nbranch = 0;
1835 type_t *deftype = NULL;
1836 short nodeftype = 0xffff;
1837 var_t *f;
1839 guard_rec(type);
1841 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1843 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1844 fields = uv->type->fields;
1846 else
1847 fields = type->fields;
1849 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1851 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1852 if (cases)
1853 nbranch += list_count(cases);
1854 if (f->type)
1855 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1858 start_offset = *tfsoff;
1859 update_tfsoff(type, start_offset, file);
1860 print_start_tfs_comment(file, type, start_offset);
1861 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1863 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1864 const type_t *st = sv->type;
1866 switch (st->type)
1868 case RPC_FC_CHAR:
1869 case RPC_FC_SMALL:
1870 case RPC_FC_USMALL:
1871 case RPC_FC_SHORT:
1872 case RPC_FC_USHORT:
1873 case RPC_FC_LONG:
1874 case RPC_FC_ULONG:
1875 case RPC_FC_ENUM16:
1876 case RPC_FC_ENUM32:
1877 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1878 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1879 0x40 | st->type, string_of_type(st->type));
1880 *tfsoff += 2;
1881 break;
1882 default:
1883 error("union switch type must be an integer, char, or enum\n");
1886 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1887 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1888 *tfsoff += 4;
1890 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1892 type_t *ft = f->type;
1893 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1894 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1895 expr_t *c;
1897 if (cases == NULL && !deflt)
1898 error("union field %s with neither case nor default attribute\n", f->name);
1900 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1902 /* MIDL doesn't check for duplicate cases, even though that seems
1903 like a reasonable thing to do, it just dumps them to the TFS
1904 like we're going to do here. */
1905 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1906 *tfsoff += 4;
1907 write_branch_type(file, ft, tfsoff);
1910 /* MIDL allows multiple default branches, even though that seems
1911 illogical, it just chooses the last one, which is what we will
1912 do. */
1913 if (deflt)
1915 deftype = ft;
1916 nodeftype = 0;
1920 if (deftype)
1922 write_branch_type(file, deftype, tfsoff);
1924 else
1926 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1927 *tfsoff += 2;
1930 return start_offset;
1933 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1934 unsigned int *typeformat_offset)
1936 size_t i;
1937 size_t start_offset = *typeformat_offset;
1938 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1940 if (iid)
1942 expr_t expr;
1944 expr.type = EXPR_IDENTIFIER;
1945 expr.ref = NULL;
1946 expr.u.sval = iid->name;
1947 expr.is_const = FALSE;
1948 print_file(file, 2, "0x2f, /* FC_IP */\n");
1949 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1950 *typeformat_offset
1951 += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
1953 else
1955 const type_t *base = is_ptr(type) ? type->ref : type;
1956 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1958 if (! uuid)
1959 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1961 update_tfsoff(type, start_offset, file);
1962 print_start_tfs_comment(file, type, start_offset);
1963 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1964 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1965 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1966 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1967 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1968 for (i = 0; i < 8; ++i)
1969 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1971 if (file)
1972 fprintf(file, "\n");
1974 *typeformat_offset += 18;
1976 return start_offset;
1979 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
1980 const var_t *var,
1981 unsigned int *typeformat_offset)
1983 size_t start_offset = *typeformat_offset;
1984 unsigned char flags = 0x08 /* strict */;
1986 if (is_ptr(type))
1988 flags |= 0x80;
1989 if (type->type != RPC_FC_RP)
1990 flags |= 0x01;
1992 if (is_attr(var->attrs, ATTR_IN))
1993 flags |= 0x40;
1994 if (is_attr(var->attrs, ATTR_OUT))
1995 flags |= 0x20;
1997 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
1998 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
1999 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2000 print_file(file, 0, "can't be null, ");
2001 if (flags & 0x02)
2002 print_file(file, 0, "serialize, ");
2003 if (flags & 0x04)
2004 print_file(file, 0, "no serialize, ");
2005 if (flags & 0x08)
2006 print_file(file, 0, "strict, ");
2007 if ((flags & 0x21) == 0x20)
2008 print_file(file, 0, "out, ");
2009 if ((flags & 0x21) == 0x21)
2010 print_file(file, 0, "return, ");
2011 if (flags & 0x40)
2012 print_file(file, 0, "in, ");
2013 if (flags & 0x80)
2014 print_file(file, 0, "via ptr, ");
2015 print_file(file, 0, "*/\n");
2016 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2017 print_file(file, 2, "0, /* FIXME: param num */\n");
2018 *typeformat_offset += 4;
2020 return start_offset;
2023 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2024 type_t *type, const var_t *var,
2025 unsigned int *typeformat_offset)
2027 size_t offset;
2029 if (is_context_handle(type))
2030 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2032 if (is_user_type(type))
2034 write_user_tfs(file, type, typeformat_offset);
2035 return type->typestring_offset;
2038 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2039 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
2041 if (is_array(type))
2043 int ptr_type;
2044 size_t off;
2045 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2046 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2047 if (ptr_type && ptr_type != RPC_FC_RP)
2049 unsigned int absoff = type->typestring_offset;
2050 short reloff = absoff - (*typeformat_offset + 2);
2051 off = *typeformat_offset;
2052 print_file(file, 0, "/* %d */\n", off);
2053 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2054 string_of_type(ptr_type));
2055 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2056 reloff, reloff, absoff);
2057 *typeformat_offset += 4;
2059 return off;
2062 if (!is_ptr(type))
2064 /* basic types don't need a type format string */
2065 if (is_base_type(type->type))
2066 return 0;
2068 switch (type->type)
2070 case RPC_FC_STRUCT:
2071 case RPC_FC_PSTRUCT:
2072 case RPC_FC_CSTRUCT:
2073 case RPC_FC_CPSTRUCT:
2074 case RPC_FC_CVSTRUCT:
2075 case RPC_FC_BOGUS_STRUCT:
2076 return write_struct_tfs(file, type, var->name, typeformat_offset);
2077 case RPC_FC_ENCAPSULATED_UNION:
2078 case RPC_FC_NON_ENCAPSULATED_UNION:
2079 return write_union_tfs(file, type, typeformat_offset);
2080 case RPC_FC_IGNORE:
2081 case RPC_FC_BIND_PRIMITIVE:
2082 /* nothing to do */
2083 return 0;
2084 default:
2085 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2088 else if (last_ptr(type))
2090 size_t start_offset = *typeformat_offset;
2091 int in_attr = is_attr(var->attrs, ATTR_IN);
2092 int out_attr = is_attr(var->attrs, ATTR_OUT);
2093 const type_t *base = type->ref;
2095 if (base->type == RPC_FC_IP)
2097 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2100 /* special case for pointers to base types */
2101 if (is_base_type(base->type))
2103 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2104 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2105 string_of_type(type->type),
2106 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2107 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2108 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2109 *typeformat_offset += 4;
2110 return start_offset;
2114 assert(is_ptr(type));
2116 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2117 if (file)
2118 fprintf(file, "/* %2u */\n", *typeformat_offset);
2119 return write_pointer_only_tfs(file, var->attrs, type->type,
2120 !last_ptr(type) ? 0x10 : 0,
2121 offset, typeformat_offset);
2124 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2125 const char *name, int write_ptr, unsigned int *tfsoff)
2127 int retmask = 0;
2129 if (is_user_type(type))
2131 write_user_tfs(file, type, tfsoff);
2133 else if (is_ptr(type))
2135 type_t *ref = type->ref;
2137 if (ref->type == RPC_FC_IP)
2139 write_ip_tfs(file, attrs, type, tfsoff);
2141 else
2143 if (!processed(ref) && !is_base_type(ref->type))
2144 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2146 if (write_ptr)
2147 write_pointer_tfs(file, type, tfsoff);
2149 retmask |= 1;
2152 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2154 write_string_tfs(file, attrs, type, name, tfsoff);
2156 else if (type->declarray && is_conformant_array(type))
2157 ; /* conformant arrays and strings are handled specially */
2158 else if (is_array(type))
2160 write_array_tfs(file, attrs, type, name, tfsoff);
2161 if (is_conformant_array(type))
2162 retmask |= 1;
2164 else if (is_struct(type->type))
2166 if (!processed(type))
2167 write_struct_tfs(file, type, name, tfsoff);
2169 else if (is_union(type->type))
2171 if (!processed(type))
2172 write_union_tfs(file, type, tfsoff);
2174 else if (!is_base_type(type->type))
2175 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2176 name, type->type);
2178 return retmask;
2181 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2183 const var_t *var;
2184 const ifref_t *iface;
2185 unsigned int typeformat_offset = 2;
2187 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2189 if (!pred(iface->iface))
2190 continue;
2192 if (iface->iface->funcs)
2194 const func_t *func;
2195 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2197 if (is_local(func->def->attrs)) continue;
2199 current_func = func;
2200 if (func->args)
2201 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2202 update_tfsoff(
2203 var->type,
2204 write_typeformatstring_var(
2205 file, 2, func, var->type, var,
2206 &typeformat_offset),
2207 file);
2212 return typeformat_offset + 1;
2216 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2218 int indent = 0;
2220 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2221 print_file(file, indent, "{\n");
2222 indent++;
2223 print_file(file, indent, "0,\n");
2224 print_file(file, indent, "{\n");
2225 indent++;
2226 print_file(file, indent, "NdrFcShort(0x0),\n");
2228 set_all_tfswrite(TRUE);
2229 process_tfs(file, ifaces, pred);
2231 print_file(file, indent, "0x0\n");
2232 indent--;
2233 print_file(file, indent, "}\n");
2234 indent--;
2235 print_file(file, indent, "};\n");
2236 print_file(file, indent, "\n");
2239 static unsigned int get_required_buffer_size_type(
2240 const type_t *type, const char *name, unsigned int *alignment)
2242 *alignment = 0;
2243 if (is_user_type(type))
2245 const char *uname;
2246 const type_t *utype = get_user_type(type, &uname);
2247 return get_required_buffer_size_type(utype, uname, alignment);
2249 else
2251 switch (type->type)
2253 case RPC_FC_BYTE:
2254 case RPC_FC_CHAR:
2255 case RPC_FC_USMALL:
2256 case RPC_FC_SMALL:
2257 *alignment = 4;
2258 return 1;
2260 case RPC_FC_WCHAR:
2261 case RPC_FC_USHORT:
2262 case RPC_FC_SHORT:
2263 case RPC_FC_ENUM16:
2264 *alignment = 4;
2265 return 2;
2267 case RPC_FC_ULONG:
2268 case RPC_FC_LONG:
2269 case RPC_FC_ENUM32:
2270 case RPC_FC_FLOAT:
2271 case RPC_FC_ERROR_STATUS_T:
2272 *alignment = 4;
2273 return 4;
2275 case RPC_FC_HYPER:
2276 case RPC_FC_DOUBLE:
2277 *alignment = 8;
2278 return 8;
2280 case RPC_FC_IGNORE:
2281 case RPC_FC_BIND_PRIMITIVE:
2282 return 0;
2284 case RPC_FC_STRUCT:
2285 case RPC_FC_PSTRUCT:
2287 size_t size = 0;
2288 const var_t *field;
2289 if (!type->fields) return 0;
2290 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2292 unsigned int alignment;
2293 size += get_required_buffer_size_type(field->type, field->name,
2294 &alignment);
2296 return size;
2299 case RPC_FC_RP:
2300 return
2301 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2302 ? get_required_buffer_size_type( type->ref, name, alignment )
2303 : 0;
2305 case RPC_FC_SMFARRAY:
2306 case RPC_FC_LGFARRAY:
2307 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2309 default:
2310 return 0;
2315 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2317 int in_attr = is_attr(var->attrs, ATTR_IN);
2318 int out_attr = is_attr(var->attrs, ATTR_OUT);
2319 const type_t *t;
2321 if (!in_attr && !out_attr)
2322 in_attr = 1;
2324 *alignment = 0;
2326 for (t = var->type; is_ptr(t); t = t->ref)
2327 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2329 *alignment = 4;
2330 return 20;
2333 if (pass == PASS_OUT)
2335 if (out_attr && is_ptr(var->type))
2337 type_t *type = var->type;
2339 if (type->type == RPC_FC_STRUCT)
2341 const var_t *field;
2342 unsigned int size = 36;
2344 if (!type->fields) return size;
2345 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2347 unsigned int align;
2348 size += get_required_buffer_size_type(
2349 field->type, field->name, &align);
2351 return size;
2354 return 0;
2356 else
2358 if ((!out_attr || in_attr) && !var->type->size_is
2359 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2361 if (is_ptr(var->type))
2363 type_t *type = var->type;
2365 if (is_base_type(type->type))
2367 return 25;
2369 else if (type->type == RPC_FC_STRUCT)
2371 unsigned int size = 36;
2372 const var_t *field;
2374 if (!type->fields) return size;
2375 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2377 unsigned int align;
2378 size += get_required_buffer_size_type(
2379 field->type, field->name, &align);
2381 return size;
2386 return get_required_buffer_size_type(var->type, var->name, alignment);
2390 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2392 const var_t *var;
2393 unsigned int total_size = 0, alignment;
2395 if (func->args)
2397 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2399 total_size += get_required_buffer_size(var, &alignment, pass);
2400 total_size += alignment;
2404 if (pass == PASS_OUT && !is_void(func->def->type))
2406 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2407 total_size += alignment;
2409 return total_size;
2412 static void print_phase_function(FILE *file, int indent, const char *type,
2413 enum remoting_phase phase,
2414 const var_t *var, unsigned int type_offset)
2416 const char *function;
2417 switch (phase)
2419 case PHASE_BUFFERSIZE:
2420 function = "BufferSize";
2421 break;
2422 case PHASE_MARSHAL:
2423 function = "Marshall";
2424 break;
2425 case PHASE_UNMARSHAL:
2426 function = "Unmarshall";
2427 break;
2428 case PHASE_FREE:
2429 function = "Free";
2430 break;
2431 default:
2432 assert(0);
2433 return;
2436 print_file(file, indent, "Ndr%s%s(\n", type, function);
2437 indent++;
2438 print_file(file, indent, "&_StubMsg,\n");
2439 print_file(file, indent, "%s%s%s%s,\n",
2440 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2441 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2442 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2443 var->name);
2444 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2445 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2446 if (phase == PHASE_UNMARSHAL)
2447 print_file(file, indent, "0);\n");
2448 indent--;
2451 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2452 enum pass pass, const var_t *var,
2453 const char *varname)
2455 type_t *type = var->type;
2456 unsigned int size;
2457 unsigned int alignment = 0;
2458 unsigned char rtype;
2460 /* no work to do for other phases, buffer sizing is done elsewhere */
2461 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2462 return;
2464 rtype = is_ptr(type) ? type->ref->type : type->type;
2466 switch (rtype)
2468 case RPC_FC_BYTE:
2469 case RPC_FC_CHAR:
2470 case RPC_FC_SMALL:
2471 case RPC_FC_USMALL:
2472 size = 1;
2473 alignment = 1;
2474 break;
2476 case RPC_FC_WCHAR:
2477 case RPC_FC_USHORT:
2478 case RPC_FC_SHORT:
2479 case RPC_FC_ENUM16:
2480 size = 2;
2481 alignment = 2;
2482 break;
2484 case RPC_FC_ULONG:
2485 case RPC_FC_LONG:
2486 case RPC_FC_ENUM32:
2487 case RPC_FC_FLOAT:
2488 case RPC_FC_ERROR_STATUS_T:
2489 size = 4;
2490 alignment = 4;
2491 break;
2493 case RPC_FC_HYPER:
2494 case RPC_FC_DOUBLE:
2495 size = 8;
2496 alignment = 8;
2497 break;
2499 case RPC_FC_IGNORE:
2500 case RPC_FC_BIND_PRIMITIVE:
2501 /* no marshalling needed */
2502 return;
2504 default:
2505 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2506 size = 0;
2509 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2510 alignment - 1, alignment - 1);
2512 if (phase == PHASE_MARSHAL)
2514 print_file(file, indent, "*(");
2515 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2516 if (is_ptr(type))
2517 fprintf(file, " *)_StubMsg.Buffer = *");
2518 else
2519 fprintf(file, " *)_StubMsg.Buffer = ");
2520 fprintf(file, "%s", varname);
2521 fprintf(file, ";\n");
2523 else if (phase == PHASE_UNMARSHAL)
2525 if (pass == PASS_IN || pass == PASS_RETURN)
2526 print_file(file, indent, "");
2527 else
2528 print_file(file, indent, "*");
2529 fprintf(file, "%s", varname);
2530 if (pass == PASS_IN && is_ptr(type))
2531 fprintf(file, " = (");
2532 else
2533 fprintf(file, " = *(");
2534 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2535 fprintf(file, " *)_StubMsg.Buffer;\n");
2538 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2539 write_type_decl(file, var->type, NULL);
2540 fprintf(file, ");\n");
2543 /* returns whether the MaxCount, Offset or ActualCount members need to be
2544 * filled in for the specified phase */
2545 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2547 return (phase != PHASE_UNMARSHAL);
2550 static int needs_freeing(const attr_list_t *attrs, const type_t *t, int out)
2552 return
2553 (is_user_type(t)
2554 || (is_ptr(t)
2555 && (t->ref->type == RPC_FC_IP
2556 || is_ptr(t->ref))))
2557 || (out && (is_string_type(attrs, t)
2558 || is_array(t)));
2561 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2562 enum pass pass, enum remoting_phase phase)
2564 int in_attr, out_attr, pointer_type;
2565 const var_t *var;
2567 if (!func->args)
2568 return;
2570 if (phase == PHASE_BUFFERSIZE)
2572 unsigned int size = get_function_buffer_size( func, pass );
2573 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2576 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2578 const type_t *type = var->type;
2579 unsigned char rtype;
2580 size_t start_offset = type->typestring_offset;
2582 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2583 if (!pointer_type)
2584 pointer_type = RPC_FC_RP;
2586 in_attr = is_attr(var->attrs, ATTR_IN);
2587 out_attr = is_attr(var->attrs, ATTR_OUT);
2588 if (!in_attr && !out_attr)
2589 in_attr = 1;
2591 if (phase == PHASE_FREE)
2593 if (!needs_freeing(var->attrs, type, out_attr))
2594 continue;
2596 else
2597 switch (pass)
2599 case PASS_IN:
2600 if (!in_attr) continue;
2601 break;
2602 case PASS_OUT:
2603 if (!out_attr) continue;
2604 break;
2605 case PASS_RETURN:
2606 break;
2609 rtype = type->type;
2611 if (is_context_handle(type))
2613 if (phase == PHASE_MARSHAL)
2615 if (pass == PASS_IN)
2617 print_file(file, indent, "NdrClientContextMarshall(\n");
2618 print_file(file, indent + 1, "&_StubMsg,\n");
2619 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2620 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2622 else
2624 print_file(file, indent, "NdrServerContextMarshall(\n");
2625 print_file(file, indent + 1, "&_StubMsg,\n");
2626 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2627 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2630 else if (phase == PHASE_UNMARSHAL)
2632 if (pass == PASS_OUT)
2634 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2635 print_file(file, indent + 1, "&_StubMsg,\n");
2636 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2637 print_file(file, indent + 1, "_Handle);\n");
2639 else
2640 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2643 else if (is_user_type(var->type))
2645 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2647 else if (is_string_type(var->attrs, var->type))
2649 if (is_array(type) && !is_conformant_array(type))
2650 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2651 else
2653 if (type->size_is && is_size_needed_for_phase(phase))
2655 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2656 write_expr(file, type->size_is, 1);
2657 fprintf(file, ";\n");
2660 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2661 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2662 else
2663 print_phase_function(file, indent, "ConformantString", phase, var,
2664 start_offset + (type->size_is ? 4 : 2));
2667 else if (is_array(type))
2669 unsigned char tc = type->type;
2670 const char *array_type = "FixedArray";
2672 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2674 if (is_size_needed_for_phase(phase))
2676 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2677 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2678 write_expr(file, type->length_is, 1);
2679 fprintf(file, ";\n\n");
2681 array_type = "VaryingArray";
2683 else if (tc == RPC_FC_CARRAY)
2685 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2687 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2688 write_expr(file, type->size_is, 1);
2689 fprintf(file, ";\n\n");
2691 array_type = "ConformantArray";
2693 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2695 if (is_size_needed_for_phase(phase))
2697 if (type->size_is)
2699 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2700 write_expr(file, type->size_is, 1);
2701 fprintf(file, ";\n");
2703 if (type->length_is)
2705 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2706 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2707 write_expr(file, type->length_is, 1);
2708 fprintf(file, ";\n\n");
2711 array_type = (tc == RPC_FC_BOGUS_ARRAY
2712 ? "ComplexArray"
2713 : "ConformantVaryingArray");
2716 if (!in_attr && phase == PHASE_FREE)
2718 print_file(file, indent, "if (%s)\n", var->name);
2719 indent++;
2720 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2722 else if (phase != PHASE_FREE)
2724 const char *t = pointer_type == RPC_FC_RP ? array_type : "Pointer";
2725 print_phase_function(file, indent, t, phase, var, start_offset);
2728 else if (!is_ptr(var->type) && is_base_type(rtype))
2730 print_phase_basetype(file, indent, phase, pass, var, var->name);
2732 else if (!is_ptr(var->type))
2734 switch (rtype)
2736 case RPC_FC_STRUCT:
2737 case RPC_FC_PSTRUCT:
2738 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2739 break;
2740 case RPC_FC_CSTRUCT:
2741 case RPC_FC_CPSTRUCT:
2742 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2743 break;
2744 case RPC_FC_CVSTRUCT:
2745 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2746 break;
2747 case RPC_FC_BOGUS_STRUCT:
2748 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2749 break;
2750 case RPC_FC_RP:
2751 if (is_base_type( var->type->ref->type ))
2753 print_phase_basetype(file, indent, phase, pass, var, var->name);
2755 else if (var->type->ref->type == RPC_FC_STRUCT)
2757 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2758 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2760 else
2762 const var_t *iid;
2763 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2764 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2765 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2767 break;
2768 default:
2769 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2772 else
2774 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2776 print_phase_basetype(file, indent, phase, pass, var, var->name);
2778 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2780 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2781 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2783 else
2785 const var_t *iid;
2786 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2787 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2788 if (var->type->ref->type == RPC_FC_IP)
2789 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2790 else
2791 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2794 fprintf(file, "\n");
2799 size_t get_size_procformatstring_var(const var_t *var)
2801 return write_procformatstring_var(NULL, 0, var, FALSE);
2805 size_t get_size_procformatstring_func(const func_t *func)
2807 const var_t *var;
2808 size_t size = 0;
2810 /* argument list size */
2811 if (func->args)
2812 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2813 size += get_size_procformatstring_var(var);
2815 /* return value size */
2816 if (is_void(func->def->type))
2817 size += 2; /* FC_END and FC_PAD */
2818 else
2819 size += get_size_procformatstring_var(func->def);
2821 return size;
2824 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2826 const ifref_t *iface;
2827 size_t size = 1;
2828 const func_t *func;
2830 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2832 if (!pred(iface->iface))
2833 continue;
2835 if (iface->iface->funcs)
2836 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2837 if (!is_local(func->def->attrs))
2838 size += get_size_procformatstring_func( func );
2840 return size;
2843 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2845 set_all_tfswrite(FALSE);
2846 return process_tfs(NULL, ifaces, pred);
2849 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2850 const var_list_t *fields, const char *structvar)
2852 switch (e->type) {
2853 case EXPR_VOID:
2854 break;
2855 case EXPR_NUM:
2856 fprintf(h, "%lu", e->u.lval);
2857 break;
2858 case EXPR_HEXNUM:
2859 fprintf(h, "0x%lx", e->u.lval);
2860 break;
2861 case EXPR_DOUBLE:
2862 fprintf(h, "%#.15g", e->u.dval);
2863 break;
2864 case EXPR_TRUEFALSE:
2865 if (e->u.lval == 0)
2866 fprintf(h, "FALSE");
2867 else
2868 fprintf(h, "TRUE");
2869 break;
2870 case EXPR_IDENTIFIER:
2872 const var_t *field;
2873 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2874 if (!strcmp(e->u.sval, field->name))
2876 fprintf(h, "%s->%s", structvar, e->u.sval);
2877 break;
2880 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2881 break;
2883 case EXPR_NEG:
2884 fprintf(h, "-");
2885 write_struct_expr(h, e->ref, 1, fields, structvar);
2886 break;
2887 case EXPR_NOT:
2888 fprintf(h, "~");
2889 write_struct_expr(h, e->ref, 1, fields, structvar);
2890 break;
2891 case EXPR_PPTR:
2892 fprintf(h, "*");
2893 write_struct_expr(h, e->ref, 1, fields, structvar);
2894 break;
2895 case EXPR_CAST:
2896 fprintf(h, "(");
2897 write_type_decl(h, e->u.tref, NULL);
2898 fprintf(h, ")");
2899 write_struct_expr(h, e->ref, 1, fields, structvar);
2900 break;
2901 case EXPR_SIZEOF:
2902 fprintf(h, "sizeof(");
2903 write_type_decl(h, e->u.tref, NULL);
2904 fprintf(h, ")");
2905 break;
2906 case EXPR_SHL:
2907 case EXPR_SHR:
2908 case EXPR_MUL:
2909 case EXPR_DIV:
2910 case EXPR_ADD:
2911 case EXPR_SUB:
2912 case EXPR_AND:
2913 case EXPR_OR:
2914 if (brackets) fprintf(h, "(");
2915 write_struct_expr(h, e->ref, 1, fields, structvar);
2916 switch (e->type) {
2917 case EXPR_SHL: fprintf(h, " << "); break;
2918 case EXPR_SHR: fprintf(h, " >> "); break;
2919 case EXPR_MUL: fprintf(h, " * "); break;
2920 case EXPR_DIV: fprintf(h, " / "); break;
2921 case EXPR_ADD: fprintf(h, " + "); break;
2922 case EXPR_SUB: fprintf(h, " - "); break;
2923 case EXPR_AND: fprintf(h, " & "); break;
2924 case EXPR_OR: fprintf(h, " | "); break;
2925 default: break;
2927 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2928 if (brackets) fprintf(h, ")");
2929 break;
2930 case EXPR_COND:
2931 if (brackets) fprintf(h, "(");
2932 write_struct_expr(h, e->ref, 1, fields, structvar);
2933 fprintf(h, " ? ");
2934 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2935 fprintf(h, " : ");
2936 write_struct_expr(h, e->ext2, 1, fields, structvar);
2937 if (brackets) fprintf(h, ")");
2938 break;
2943 void declare_stub_args( FILE *file, int indent, const func_t *func )
2945 int in_attr, out_attr;
2946 int i = 0;
2947 const var_t *def = func->def;
2948 const var_t *var;
2950 /* declare return value '_RetVal' */
2951 if (!is_void(def->type))
2953 print_file(file, indent, "");
2954 write_type_decl_left(file, def->type);
2955 fprintf(file, " _RetVal;\n");
2958 if (!func->args)
2959 return;
2961 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2963 int is_string = is_attr(var->attrs, ATTR_STRING);
2965 in_attr = is_attr(var->attrs, ATTR_IN);
2966 out_attr = is_attr(var->attrs, ATTR_OUT);
2967 if (!out_attr && !in_attr)
2968 in_attr = 1;
2970 if (is_context_handle(var->type))
2971 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
2972 else
2974 if (!in_attr && !var->type->size_is && !is_string)
2976 print_file(file, indent, "");
2977 write_type_decl(file, var->type->ref, "_W%u", i++);
2978 fprintf(file, ";\n");
2981 print_file(file, indent, "");
2982 write_type_decl_left(file, var->type);
2983 fprintf(file, " ");
2984 if (var->type->declarray) {
2985 fprintf(file, "( *");
2986 write_name(file, var);
2987 fprintf(file, " )");
2988 } else
2989 write_name(file, var);
2990 write_type_right(file, var->type, FALSE);
2991 fprintf(file, ";\n");
2993 if (decl_indirect(var->type))
2994 print_file(file, indent, "void *_p_%s = &%s;\n",
2995 var->name, var->name);
3001 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3003 int in_attr, out_attr;
3004 int i = 0, sep = 0;
3005 const var_t *var;
3007 if (!func->args)
3008 return;
3010 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3012 int is_string = is_attr(var->attrs, ATTR_STRING);
3013 in_attr = is_attr(var->attrs, ATTR_IN);
3014 out_attr = is_attr(var->attrs, ATTR_OUT);
3015 if (!out_attr && !in_attr)
3016 in_attr = 1;
3018 if (!in_attr)
3020 print_file(file, indent, "");
3021 write_name(file, var);
3023 if (var->type->size_is)
3025 unsigned int size, align = 0;
3026 type_t *type = var->type;
3028 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3029 for ( ; type->size_is ; type = type->ref)
3031 write_expr(file, type->size_is, TRUE);
3032 fprintf(file, " * ");
3034 size = type_memsize(type, &align);
3035 fprintf(file, "%u);\n", size);
3037 else if (!is_string)
3039 fprintf(file, " = &_W%u;\n", i);
3040 if (is_ptr(var->type) && !last_ptr(var->type))
3041 print_file(file, indent, "_W%u = 0;\n", i);
3042 i++;
3045 sep = 1;
3048 if (sep)
3049 fprintf(file, "\n");
3053 int write_expr_eval_routines(FILE *file, const char *iface)
3055 static const char *var_name = "pS";
3056 int result = 0;
3057 struct expr_eval_routine *eval;
3058 unsigned short callback_offset = 0;
3060 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3062 const char *name = eval->structure->name;
3063 const var_list_t *fields = eval->structure->fields;
3064 result = 1;
3066 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3067 iface, name, callback_offset);
3068 print_file(file, 0, "{\n");
3069 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3070 name, var_name, name, eval->baseoff);
3071 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3072 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3073 write_struct_expr(file, eval->expr, 1, fields, var_name);
3074 fprintf(file, ";\n");
3075 print_file(file, 0, "}\n\n");
3076 callback_offset++;
3078 return result;
3081 void write_expr_eval_routine_list(FILE *file, const char *iface)
3083 struct expr_eval_routine *eval;
3084 struct expr_eval_routine *cursor;
3085 unsigned short callback_offset = 0;
3087 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3088 fprintf(file, "{\n");
3090 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3092 const char *name = eval->structure->name;
3093 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3094 callback_offset++;
3095 list_remove(&eval->entry);
3096 free(eval);
3099 fprintf(file, "};\n\n");
3102 void write_user_quad_list(FILE *file)
3104 user_type_t *ut;
3106 if (list_empty(&user_type_list))
3107 return;
3109 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3110 fprintf(file, "{\n");
3111 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3113 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3114 print_file(file, 1, "{\n");
3115 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3116 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3117 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3118 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3119 print_file(file, 1, "}%s\n", sep);
3121 fprintf(file, "};\n\n");
3124 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3126 const struct str_list_entry_t *endpoint;
3127 const char *p;
3129 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3130 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3131 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3133 print_file( f, 1, "{ (const unsigned char *)\"" );
3134 for (p = endpoint->str; *p && *p != ':'; p++)
3136 if (*p == '"' || *p == '\\') fputc( '\\', f );
3137 fputc( *p, f );
3139 if (!*p) goto error;
3140 if (p[1] != '[') goto error;
3142 fprintf( f, "\", (const unsigned char *)\"" );
3143 for (p += 2; *p && *p != ']'; p++)
3145 if (*p == '"' || *p == '\\') fputc( '\\', f );
3146 fputc( *p, f );
3148 if (*p != ']') goto error;
3149 fprintf( f, "\" },\n" );
3151 print_file( f, 0, "};\n\n" );
3152 return;
3154 error:
3155 error("Invalid endpoint syntax '%s'\n", endpoint->str);