cabinet: FCICreate: Initialize oldCCAB.
[wine.git] / tools / widl / typegen.c
blob2cb8dc9bcdcabb8a831f73c8cf4029b8401cbcee
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 /* This is actually fairly involved to implement precisely, due to the
232 effects attributes may have and things like that. Right now this is
233 only used for optimization, so just check for a very small set of
234 criteria that guarantee the types are equivalent; assume every thing
235 else is different. */
236 static int compare_type(const type_t *a, const type_t *b)
238 if (a == b
239 || (a->name
240 && b->name
241 && strcmp(a->name, b->name) == 0))
242 return 0;
243 /* Ordering doesn't need to be implemented yet. */
244 return 1;
247 static int compare_expr(const expr_t *a, const expr_t *b)
249 int ret;
251 if (a->type != b->type)
252 return a->type - b->type;
254 switch (a->type)
256 case EXPR_NUM:
257 case EXPR_HEXNUM:
258 case EXPR_TRUEFALSE:
259 return a->u.lval - b->u.lval;
260 case EXPR_DOUBLE:
261 return a->u.dval - b->u.dval;
262 case EXPR_IDENTIFIER:
263 return strcmp(a->u.sval, b->u.sval);
264 case EXPR_COND:
265 ret = compare_expr(a->ref, b->ref);
266 if (ret != 0)
267 return ret;
268 ret = compare_expr(a->u.ext, b->u.ext);
269 if (ret != 0)
270 return ret;
271 return compare_expr(a->ext2, b->ext2);
272 case EXPR_OR:
273 case EXPR_AND:
274 case EXPR_ADD:
275 case EXPR_SUB:
276 case EXPR_MUL:
277 case EXPR_DIV:
278 case EXPR_SHL:
279 case EXPR_SHR:
280 ret = compare_expr(a->ref, b->ref);
281 if (ret != 0)
282 return ret;
283 return compare_expr(a->u.ext, b->u.ext);
284 case EXPR_CAST:
285 ret = compare_type(a->u.tref, b->u.tref);
286 if (ret != 0)
287 return ret;
288 /* Fall through. */
289 case EXPR_NOT:
290 case EXPR_NEG:
291 case EXPR_PPTR:
292 return compare_expr(a->ref, b->ref);
293 case EXPR_SIZEOF:
294 return compare_type(a->u.tref, b->u.tref);
295 case EXPR_VOID:
296 return 0;
298 return -1;
301 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
302 do { \
303 if (file) \
304 fprintf(file, "/* %2u */\n", typestring_offset); \
305 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
307 while (0)
309 static void print_file(FILE *file, int indent, const char *format, ...)
311 va_list va;
312 va_start(va, format);
313 print(file, indent, format, va);
314 va_end(va);
317 void print(FILE *file, int indent, const char *format, va_list va)
319 if (file)
321 if (format[0] != '\n')
322 while (0 < indent--)
323 fprintf(file, " ");
324 vfprintf(file, format, va);
328 void write_parameters_init(FILE *file, int indent, const func_t *func)
330 const var_t *var;
332 if (!func->args)
333 return;
335 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
337 const type_t *t = var->type;
338 const char *n = var->name;
339 if (decl_indirect(t))
340 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
341 else if (is_ptr(t) || is_array(t))
342 print_file(file, indent, "%s = 0;\n", n);
345 fprintf(file, "\n");
348 static void write_formatdesc(FILE *f, int indent, const char *str)
350 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
351 print_file(f, indent, "{\n");
352 print_file(f, indent + 1, "short Pad;\n");
353 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
354 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
355 print_file(f, indent, "\n");
358 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
360 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
361 get_size_typeformatstring(ifaces, pred));
363 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
364 get_size_procformatstring(ifaces, pred));
366 fprintf(f, "\n");
367 write_formatdesc(f, indent, "TYPE");
368 write_formatdesc(f, indent, "PROC");
369 fprintf(f, "\n");
370 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
371 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
372 print_file(f, indent, "\n");
375 static inline int is_base_type(unsigned char type)
377 switch (type)
379 case RPC_FC_BYTE:
380 case RPC_FC_CHAR:
381 case RPC_FC_USMALL:
382 case RPC_FC_SMALL:
383 case RPC_FC_WCHAR:
384 case RPC_FC_USHORT:
385 case RPC_FC_SHORT:
386 case RPC_FC_ULONG:
387 case RPC_FC_LONG:
388 case RPC_FC_HYPER:
389 case RPC_FC_IGNORE:
390 case RPC_FC_FLOAT:
391 case RPC_FC_DOUBLE:
392 case RPC_FC_ENUM16:
393 case RPC_FC_ENUM32:
394 case RPC_FC_ERROR_STATUS_T:
395 case RPC_FC_BIND_PRIMITIVE:
396 return TRUE;
398 default:
399 return FALSE;
403 int decl_indirect(const type_t *t)
405 return is_user_type(t)
406 || (!is_base_type(t->type)
407 && !is_ptr(t)
408 && !is_array(t));
411 static size_t write_procformatstring_var(FILE *file, int indent,
412 const var_t *var, int is_return)
414 size_t size;
415 const type_t *type = var->type;
417 int is_in = is_attr(var->attrs, ATTR_IN);
418 int is_out = is_attr(var->attrs, ATTR_OUT);
420 if (!is_in && !is_out) is_in = TRUE;
422 if (!type->declarray && is_base_type(type->type))
424 if (is_return)
425 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
426 else
427 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
429 if (type->type == RPC_FC_BIND_PRIMITIVE)
431 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
432 size = 2; /* includes param type prefix */
434 else if (is_base_type(type->type))
436 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
437 size = 2; /* includes param type prefix */
439 else
441 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
442 size = 0;
445 else
447 if (is_return)
448 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
449 else if (is_in && is_out)
450 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
451 else if (is_out)
452 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
453 else
454 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
456 print_file(file, indent, "0x01,\n");
457 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
458 size = 4; /* includes param type prefix */
460 return size;
463 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
465 const ifref_t *iface;
466 int indent = 0;
467 const var_t *var;
469 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
470 print_file(file, indent, "{\n");
471 indent++;
472 print_file(file, indent, "0,\n");
473 print_file(file, indent, "{\n");
474 indent++;
476 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
478 if (!pred(iface->iface))
479 continue;
481 if (iface->iface->funcs)
483 const func_t *func;
484 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
486 if (is_local(func->def->attrs)) continue;
487 /* emit argument data */
488 if (func->args)
490 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
491 write_procformatstring_var(file, indent, var, FALSE);
494 /* emit return value data */
495 var = func->def;
496 if (is_void(var->type))
498 print_file(file, indent, "0x5b, /* FC_END */\n");
499 print_file(file, indent, "0x5c, /* FC_PAD */\n");
501 else
502 write_procformatstring_var(file, indent, var, TRUE);
507 print_file(file, indent, "0x0\n");
508 indent--;
509 print_file(file, indent, "}\n");
510 indent--;
511 print_file(file, indent, "};\n");
512 print_file(file, indent, "\n");
515 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
517 if (is_base_type(type->type))
519 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
520 *typestring_offset += 1;
521 return 1;
524 return 0;
527 /* write conformance / variance descriptor */
528 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
529 unsigned int baseoff, const type_t *type,
530 const expr_t *expr)
532 unsigned char operator_type = 0;
533 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
534 const char *conftype_string = "";
535 const char *operator_string = "no operators";
536 const expr_t *subexpr;
538 if (!expr)
540 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
541 return 4;
544 if (!structure)
546 /* Top-level conformance calculations are done inline. */
547 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
548 RPC_FC_TOP_LEVEL_CONFORMANCE);
549 print_file (file, 2, "0x0,\n");
550 print_file (file, 2, "NdrFcShort(0x0),\n");
551 return 4;
554 if (expr->is_const)
556 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
557 error("write_conf_or_var_desc: constant value %ld is greater than "
558 "the maximum constant size of %d\n", expr->cval,
559 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
561 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
562 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
563 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
564 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
566 return 4;
569 if (is_ptr(type) || (is_array(type) && !type->declarray))
571 conftype = RPC_FC_POINTER_CONFORMANCE;
572 conftype_string = "field pointer, ";
575 subexpr = expr;
576 switch (subexpr->type)
578 case EXPR_PPTR:
579 subexpr = subexpr->ref;
580 operator_type = RPC_FC_DEREFERENCE;
581 operator_string = "FC_DEREFERENCE";
582 break;
583 case EXPR_DIV:
584 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
586 subexpr = subexpr->ref;
587 operator_type = RPC_FC_DIV_2;
588 operator_string = "FC_DIV_2";
590 break;
591 case EXPR_MUL:
592 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
594 subexpr = subexpr->ref;
595 operator_type = RPC_FC_MULT_2;
596 operator_string = "FC_MULT_2";
598 break;
599 case EXPR_SUB:
600 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
602 subexpr = subexpr->ref;
603 operator_type = RPC_FC_SUB_1;
604 operator_string = "FC_SUB_1";
606 break;
607 case EXPR_ADD:
608 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
610 subexpr = subexpr->ref;
611 operator_type = RPC_FC_ADD_1;
612 operator_string = "FC_ADD_1";
614 break;
615 default:
616 break;
619 if (subexpr->type == EXPR_IDENTIFIER)
621 const type_t *correlation_variable = NULL;
622 unsigned char correlation_variable_type;
623 unsigned char param_type = 0;
624 size_t offset = 0;
625 const var_t *var;
627 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
629 unsigned int align = 0;
630 /* FIXME: take alignment into account */
631 if (var->name && !strcmp(var->name, subexpr->u.sval))
633 correlation_variable = var->type;
634 break;
636 offset += type_memsize(var->type, &align);
638 if (!correlation_variable)
639 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
640 subexpr->u.sval);
642 offset -= baseoff;
643 correlation_variable_type = correlation_variable->type;
645 switch (correlation_variable_type)
647 case RPC_FC_CHAR:
648 case RPC_FC_SMALL:
649 param_type = RPC_FC_SMALL;
650 break;
651 case RPC_FC_BYTE:
652 case RPC_FC_USMALL:
653 param_type = RPC_FC_USMALL;
654 break;
655 case RPC_FC_WCHAR:
656 case RPC_FC_SHORT:
657 case RPC_FC_ENUM16:
658 param_type = RPC_FC_SHORT;
659 break;
660 case RPC_FC_USHORT:
661 param_type = RPC_FC_USHORT;
662 break;
663 case RPC_FC_LONG:
664 case RPC_FC_ENUM32:
665 param_type = RPC_FC_LONG;
666 break;
667 case RPC_FC_ULONG:
668 param_type = RPC_FC_ULONG;
669 break;
670 case RPC_FC_RP:
671 case RPC_FC_UP:
672 case RPC_FC_OP:
673 case RPC_FC_FP:
674 if (sizeof(void *) == 4) /* FIXME */
675 param_type = RPC_FC_LONG;
676 else
677 param_type = RPC_FC_HYPER;
678 break;
679 default:
680 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
681 correlation_variable_type);
684 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
685 conftype | param_type, conftype_string, string_of_type(param_type));
686 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
687 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
688 offset, offset);
690 else
692 unsigned int callback_offset = 0;
693 struct expr_eval_routine *eval;
694 int found = 0;
696 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
698 if (!strcmp (eval->structure->name, structure->name)
699 && !compare_expr (eval->expr, expr))
701 found = 1;
702 break;
704 callback_offset++;
707 if (!found)
709 eval = xmalloc (sizeof(*eval));
710 eval->structure = structure;
711 eval->baseoff = baseoff;
712 eval->expr = expr;
713 list_add_tail (&expr_eval_routines, &eval->entry);
716 if (callback_offset > USHRT_MAX)
717 error("Maximum number of callback routines reached\n");
719 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
720 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
721 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
723 return 4;
726 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
728 int have_align = FALSE;
729 size_t size = 0;
730 const var_t *v;
732 if (!fields) return 0;
733 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
735 unsigned int falign = 0;
736 size_t fsize = type_memsize(v->type, &falign);
737 if (!have_align)
739 *align = falign;
740 have_align = TRUE;
742 size = (size + (falign - 1)) & ~(falign - 1);
743 size += fsize;
746 size = (size + (*align - 1)) & ~(*align - 1);
747 return size;
750 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
752 size_t size, maxs = 0;
753 unsigned int align = *pmaxa;
754 const var_t *v;
756 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
758 /* we could have an empty default field with NULL type */
759 if (v->type)
761 size = type_memsize(v->type, &align);
762 if (maxs < size) maxs = size;
763 if (*pmaxa < align) *pmaxa = align;
767 return maxs;
770 int get_padding(const var_list_t *fields)
772 unsigned short offset = 0;
773 int salign = -1;
774 const var_t *f;
776 if (!fields)
777 return 0;
779 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
781 type_t *ft = f->type;
782 unsigned int align = 0;
783 size_t size = type_memsize(ft, &align);
784 if (salign == -1)
785 salign = align;
786 offset = (offset + (align - 1)) & ~(align - 1);
787 offset += size;
790 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
793 size_t type_memsize(const type_t *t, unsigned int *align)
795 size_t size = 0;
797 if (t->declarray && is_conformant_array(t))
799 type_memsize(t->ref, align);
800 size = 0;
802 else if (is_ptr(t) || is_conformant_array(t))
804 size = sizeof(void *);
805 if (size > *align) *align = size;
807 else switch (t->type)
809 case RPC_FC_BYTE:
810 case RPC_FC_CHAR:
811 case RPC_FC_USMALL:
812 case RPC_FC_SMALL:
813 size = 1;
814 if (size > *align) *align = size;
815 break;
816 case RPC_FC_WCHAR:
817 case RPC_FC_USHORT:
818 case RPC_FC_SHORT:
819 case RPC_FC_ENUM16:
820 size = 2;
821 if (size > *align) *align = size;
822 break;
823 case RPC_FC_ULONG:
824 case RPC_FC_LONG:
825 case RPC_FC_ERROR_STATUS_T:
826 case RPC_FC_ENUM32:
827 case RPC_FC_FLOAT:
828 size = 4;
829 if (size > *align) *align = size;
830 break;
831 case RPC_FC_HYPER:
832 case RPC_FC_DOUBLE:
833 size = 8;
834 if (size > *align) *align = size;
835 break;
836 case RPC_FC_STRUCT:
837 case RPC_FC_CVSTRUCT:
838 case RPC_FC_CPSTRUCT:
839 case RPC_FC_CSTRUCT:
840 case RPC_FC_PSTRUCT:
841 case RPC_FC_BOGUS_STRUCT:
842 size = fields_memsize(t->fields, align);
843 break;
844 case RPC_FC_ENCAPSULATED_UNION:
845 case RPC_FC_NON_ENCAPSULATED_UNION:
846 size = union_memsize(t->fields, align);
847 break;
848 case RPC_FC_SMFARRAY:
849 case RPC_FC_LGFARRAY:
850 case RPC_FC_SMVARRAY:
851 case RPC_FC_LGVARRAY:
852 case RPC_FC_BOGUS_ARRAY:
853 size = t->dim * type_memsize(t->ref, align);
854 break;
855 default:
856 error("type_memsize: Unknown type %d\n", t->type);
857 size = 0;
860 return size;
863 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
865 short absoff = type->ref->typestring_offset;
866 short reloff = absoff - (offset + 2);
867 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
869 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
870 type->type, ptr_attr, string_of_type(type->type));
871 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
872 reloff, reloff, absoff);
873 return 4;
876 static unsigned char conf_string_type_of_char_type(unsigned char t)
878 switch (t)
880 case RPC_FC_BYTE:
881 case RPC_FC_CHAR:
882 return RPC_FC_C_CSTRING;
883 case RPC_FC_WCHAR:
884 return RPC_FC_C_WSTRING;
887 error("string_type_of_char_type: unrecognized type %d\n", t);
888 return 0;
891 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
893 unsigned char fc
894 = is_string_type(type->attrs, type)
895 ? conf_string_type_of_char_type(type->ref->type)
896 : type->ref->type;
897 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
898 type->type, string_of_type(type->type));
899 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
900 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
901 return 4;
904 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
906 print_file(file, 0, "/* %u (", tfsoff);
907 write_type_decl(file, t, NULL);
908 print_file(file, 0, ") */\n");
911 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
913 unsigned int offset = *typestring_offset;
915 print_start_tfs_comment(file, type, offset);
916 update_tfsoff(type, offset, file);
918 if (type->ref->typestring_offset)
919 *typestring_offset += write_nonsimple_pointer(file, type, offset);
920 else if (is_base_type(type->ref->type))
921 *typestring_offset += write_simple_pointer(file, type);
923 return offset;
926 static int processed(const type_t *type)
928 return type->typestring_offset && !type->tfswrite;
931 static int user_type_has_variable_size(const type_t *t)
933 if (is_ptr(t))
934 return TRUE;
935 else
936 switch (t->type)
938 case RPC_FC_PSTRUCT:
939 case RPC_FC_CSTRUCT:
940 case RPC_FC_CPSTRUCT:
941 case RPC_FC_CVSTRUCT:
942 return TRUE;
944 /* Note: Since this only applies to user types, we can't have a conformant
945 array here, and strings should get filed under pointer in this case. */
946 return FALSE;
949 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
951 unsigned int start, absoff, flags;
952 unsigned int align = 0, ualign = 0;
953 const char *name;
954 type_t *utype = get_user_type(type, &name);
955 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
956 size_t size = type_memsize(type, &align);
957 unsigned short funoff = user_type_offset(name);
958 short reloff;
960 guard_rec(type);
962 if (is_base_type(utype->type))
964 absoff = *tfsoff;
965 print_start_tfs_comment(file, utype, absoff);
966 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
967 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
968 *tfsoff += 2;
970 else
972 if (!processed(utype))
973 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
974 absoff = utype->typestring_offset;
977 if (utype->type == RPC_FC_RP)
978 flags = 0x40;
979 else if (utype->type == RPC_FC_UP)
980 flags = 0x80;
981 else
982 flags = 0;
984 start = *tfsoff;
985 update_tfsoff(type, start, file);
986 print_start_tfs_comment(file, type, start);
987 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
988 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
989 flags | (align - 1), align - 1, flags);
990 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
991 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
992 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
993 *tfsoff += 8;
994 reloff = absoff - *tfsoff;
995 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
996 *tfsoff += 2;
999 static void write_member_type(FILE *file, const type_t *cont,
1000 const attr_list_t *attrs, const type_t *type,
1001 unsigned int *corroff, unsigned int *tfsoff)
1003 if (is_embedded_complex(type) && !is_conformant_array(type))
1005 size_t absoff;
1006 short reloff;
1008 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1010 absoff = *corroff;
1011 *corroff += 8;
1013 else
1015 absoff = type->typestring_offset;
1017 reloff = absoff - (*tfsoff + 2);
1019 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1020 /* FIXME: actually compute necessary padding */
1021 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1022 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1023 reloff, reloff, absoff);
1024 *tfsoff += 4;
1026 else if (is_ptr(type) || is_conformant_array(type))
1028 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1029 ? RPC_FC_POINTER
1030 : RPC_FC_LONG);
1031 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1032 *tfsoff += 1;
1034 else if (!write_base_type(file, type, tfsoff))
1035 error("Unsupported member type 0x%x\n", type->type);
1038 static void write_end(FILE *file, unsigned int *tfsoff)
1040 if (*tfsoff % 2 == 0)
1042 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1043 *tfsoff += 1;
1045 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1046 *tfsoff += 1;
1049 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1051 unsigned int offset = 0;
1052 var_list_t *fs = type->fields;
1053 var_t *f;
1055 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1057 unsigned int align = 0;
1058 type_t *ft = f->type;
1059 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1061 unsigned int absoff = ft->typestring_offset;
1062 short reloff = absoff - (*tfsoff + 6);
1063 print_file(file, 0, "/* %d */\n", *tfsoff);
1064 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1065 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1066 write_conf_or_var_desc(file, current_structure, offset, ft,
1067 get_attrp(f->attrs, ATTR_SWITCHIS));
1068 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1069 reloff, reloff, absoff);
1070 *tfsoff += 8;
1073 /* FIXME: take alignment into account */
1074 offset += type_memsize(ft, &align);
1078 static int write_no_repeat_pointer_descriptions(
1079 FILE *file, type_t *type,
1080 size_t *offset_in_memory, size_t *offset_in_buffer,
1081 unsigned int *typestring_offset)
1083 int written = 0;
1084 unsigned int align;
1086 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1088 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1089 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1091 /* pointer instance */
1092 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1093 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1094 *typestring_offset += 6;
1096 if (is_ptr(type))
1097 write_pointer_tfs(file, type, typestring_offset);
1098 else
1100 unsigned absoff = type->typestring_offset;
1101 short reloff = absoff - (*typestring_offset + 2);
1102 /* FIXME: get pointer attributes from field */
1103 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1104 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1105 reloff, reloff, absoff);
1106 *typestring_offset += 4;
1109 align = 0;
1110 *offset_in_memory += type_memsize(type, &align);
1111 /* FIXME: is there a case where these two are different? */
1112 align = 0;
1113 *offset_in_buffer += type_memsize(type, &align);
1115 return 1;
1118 if (is_non_complex_struct(type))
1120 const var_t *v;
1121 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1122 written += write_no_repeat_pointer_descriptions(
1123 file, v->type,
1124 offset_in_memory, offset_in_buffer, typestring_offset);
1126 else
1128 align = 0;
1129 *offset_in_memory += type_memsize(type, &align);
1130 /* FIXME: is there a case where these two are different? */
1131 align = 0;
1132 *offset_in_buffer += type_memsize(type, &align);
1135 return written;
1138 static int write_pointer_description_offsets(
1139 FILE *file, const attr_list_t *attrs, type_t *type,
1140 size_t *offset_in_memory, size_t *offset_in_buffer,
1141 unsigned int *typestring_offset)
1143 int written = 0;
1144 unsigned int align;
1146 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1148 if (offset_in_memory && offset_in_buffer)
1150 /* pointer instance */
1151 /* FIXME: sometimes from end of structure, sometimes from beginning */
1152 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1153 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1155 align = 0;
1156 *offset_in_memory += type_memsize(type, &align);
1157 /* FIXME: is there a case where these two are different? */
1158 align = 0;
1159 *offset_in_buffer += type_memsize(type, &align);
1161 *typestring_offset += 4;
1163 if (processed(type->ref) || is_base_type(type->ref->type))
1164 write_pointer_tfs(file, type, typestring_offset);
1165 else
1166 error("write_pointer_description_offsets: type format string unknown\n");
1168 return 1;
1171 if (is_array(type))
1173 return write_pointer_description_offsets(
1174 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1175 typestring_offset);
1177 else if (is_non_complex_struct(type))
1179 /* otherwise search for interesting fields to parse */
1180 const var_t *v;
1181 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1183 written += write_pointer_description_offsets(
1184 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1185 typestring_offset);
1188 else
1190 align = 0;
1191 if (offset_in_memory)
1192 *offset_in_memory += type_memsize(type, &align);
1193 /* FIXME: is there a case where these two are different? */
1194 align = 0;
1195 if (offset_in_buffer)
1196 *offset_in_buffer += type_memsize(type, &align);
1199 return written;
1202 /* Note: if file is NULL return value is number of pointers to write, else
1203 * it is the number of type format characters written */
1204 static int write_fixed_array_pointer_descriptions(
1205 FILE *file, const attr_list_t *attrs, type_t *type,
1206 size_t *offset_in_memory, size_t *offset_in_buffer,
1207 unsigned int *typestring_offset)
1209 unsigned int align;
1210 int pointer_count = 0;
1212 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1214 unsigned int temp = 0;
1215 /* unfortunately, this needs to be done in two passes to avoid
1216 * writing out redundant FC_FIXED_REPEAT descriptions */
1217 pointer_count = write_pointer_description_offsets(
1218 NULL, attrs, type->ref, NULL, NULL, &temp);
1219 if (pointer_count > 0)
1221 unsigned int increment_size;
1222 size_t offset_of_array_pointer_mem = 0;
1223 size_t offset_of_array_pointer_buf = 0;
1225 align = 0;
1226 increment_size = type_memsize(type->ref, &align);
1228 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1229 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1230 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1231 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1232 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1233 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1234 *typestring_offset += 10;
1236 pointer_count = write_pointer_description_offsets(
1237 file, attrs, type, &offset_of_array_pointer_mem,
1238 &offset_of_array_pointer_buf, typestring_offset);
1241 else if (is_struct(type->type))
1243 const var_t *v;
1244 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1246 pointer_count += write_fixed_array_pointer_descriptions(
1247 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1248 typestring_offset);
1251 else
1253 align = 0;
1254 if (offset_in_memory)
1255 *offset_in_memory += type_memsize(type, &align);
1256 /* FIXME: is there a case where these two are different? */
1257 align = 0;
1258 if (offset_in_buffer)
1259 *offset_in_buffer += type_memsize(type, &align);
1262 return pointer_count;
1265 /* Note: if file is NULL return value is number of pointers to write, else
1266 * it is the number of type format characters written */
1267 static int write_conformant_array_pointer_descriptions(
1268 FILE *file, const attr_list_t *attrs, type_t *type,
1269 size_t offset_in_memory, unsigned int *typestring_offset)
1271 unsigned int align;
1272 int pointer_count = 0;
1274 if (is_conformant_array(type) && !type->length_is)
1276 unsigned int temp = 0;
1277 /* unfortunately, this needs to be done in two passes to avoid
1278 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1279 pointer_count = write_pointer_description_offsets(
1280 NULL, attrs, type->ref, NULL, NULL, &temp);
1281 if (pointer_count > 0)
1283 unsigned int increment_size;
1284 size_t offset_of_array_pointer_mem = offset_in_memory;
1285 size_t offset_of_array_pointer_buf = offset_in_memory;
1287 align = 0;
1288 increment_size = type_memsize(type->ref, &align);
1290 if (increment_size > USHRT_MAX)
1291 error("array size of %u bytes is too large\n", increment_size);
1293 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1294 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1295 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1296 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1297 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1298 *typestring_offset += 8;
1300 pointer_count = write_pointer_description_offsets(
1301 file, attrs, type->ref, &offset_of_array_pointer_mem,
1302 &offset_of_array_pointer_buf, typestring_offset);
1306 return pointer_count;
1309 /* Note: if file is NULL return value is number of pointers to write, else
1310 * it is the number of type format characters written */
1311 static int write_varying_array_pointer_descriptions(
1312 FILE *file, const attr_list_t *attrs, type_t *type,
1313 size_t *offset_in_memory, size_t *offset_in_buffer,
1314 unsigned int *typestring_offset)
1316 unsigned int align;
1317 int pointer_count = 0;
1319 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1321 if (is_array(type) && type->length_is)
1323 unsigned int temp = 0;
1324 /* unfortunately, this needs to be done in two passes to avoid
1325 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1326 pointer_count = write_pointer_description_offsets(
1327 NULL, attrs, type->ref, NULL, NULL, &temp);
1328 if (pointer_count > 0)
1330 unsigned int increment_size;
1331 size_t offset_of_array_pointer_mem = 0;
1332 size_t offset_of_array_pointer_buf = 0;
1334 align = 0;
1335 increment_size = type_memsize(type->ref, &align);
1337 if (increment_size > USHRT_MAX)
1338 error("array size of %u bytes is too large\n", increment_size);
1340 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1341 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1342 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1343 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1344 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1345 *typestring_offset += 8;
1347 pointer_count = write_pointer_description_offsets(
1348 file, attrs, type, &offset_of_array_pointer_mem,
1349 &offset_of_array_pointer_buf, typestring_offset);
1352 else if (is_struct(type->type))
1354 const var_t *v;
1355 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1357 pointer_count += write_varying_array_pointer_descriptions(
1358 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1359 typestring_offset);
1362 else
1364 align = 0;
1365 if (offset_in_memory)
1366 *offset_in_memory += type_memsize(type, &align);
1367 /* FIXME: is there a case where these two are different? */
1368 align = 0;
1369 if (offset_in_buffer)
1370 *offset_in_buffer += type_memsize(type, &align);
1373 return pointer_count;
1376 static void write_pointer_description(FILE *file, type_t *type,
1377 unsigned int *typestring_offset)
1379 size_t offset_in_buffer;
1380 size_t offset_in_memory;
1382 /* pass 1: search for single instance of a pointer (i.e. don't descend
1383 * into arrays) */
1384 if (!is_array(type))
1386 offset_in_memory = 0;
1387 offset_in_buffer = 0;
1388 write_no_repeat_pointer_descriptions(
1389 file, type,
1390 &offset_in_memory, &offset_in_buffer, typestring_offset);
1393 /* pass 2: search for pointers in fixed arrays */
1394 offset_in_memory = 0;
1395 offset_in_buffer = 0;
1396 write_fixed_array_pointer_descriptions(
1397 file, NULL, type,
1398 &offset_in_memory, &offset_in_buffer, typestring_offset);
1400 /* pass 3: search for pointers in conformant only arrays (but don't descend
1401 * into conformant varying or varying arrays) */
1402 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1403 write_conformant_array_pointer_descriptions(
1404 file, NULL, type, 0, typestring_offset);
1405 else if (type->type == RPC_FC_CPSTRUCT)
1407 unsigned int align = 0;
1408 type_t *carray = find_array_or_string_in_struct(type)->type;
1409 write_conformant_array_pointer_descriptions(
1410 file, NULL, carray,
1411 type_memsize(type, &align),
1412 typestring_offset);
1415 /* pass 4: search for pointers in varying arrays */
1416 offset_in_memory = 0;
1417 offset_in_buffer = 0;
1418 write_varying_array_pointer_descriptions(
1419 file, NULL, type,
1420 &offset_in_memory, &offset_in_buffer, typestring_offset);
1423 int is_declptr(const type_t *t)
1425 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1428 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1429 type_t *type,
1430 const char *name, unsigned int *typestring_offset)
1432 size_t start_offset = *typestring_offset;
1433 unsigned char rtype;
1435 update_tfsoff(type, start_offset, file);
1437 if (is_declptr(type))
1439 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1440 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1441 if (!pointer_type)
1442 pointer_type = RPC_FC_RP;
1443 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1444 pointer_type, flag, string_of_type(pointer_type),
1445 flag ? " [simple_pointer]" : "");
1446 *typestring_offset += 2;
1447 if (!flag)
1449 print_file(file, 2, "NdrFcShort(0x2),\n");
1450 *typestring_offset += 2;
1452 rtype = type->ref->type;
1454 else
1455 rtype = type->ref->type;
1457 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1459 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1460 return start_offset;
1463 if (type->declarray && !is_conformant_array(type))
1465 /* FIXME: multi-dimensional array */
1466 if (0xffffuL < type->dim)
1467 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1468 name, 0xffffu, type->dim - 0xffffu);
1470 if (rtype == RPC_FC_CHAR)
1471 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1472 else
1473 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1474 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1475 *typestring_offset += 2;
1477 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1478 *typestring_offset += 2;
1480 return start_offset;
1482 else if (type->size_is)
1484 unsigned int align = 0;
1486 if (rtype == RPC_FC_CHAR)
1487 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1488 else
1489 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1490 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1491 *typestring_offset += 2;
1493 *typestring_offset += write_conf_or_var_desc(
1494 file, current_structure,
1495 (type->declarray && current_structure
1496 ? type_memsize(current_structure, &align)
1497 : 0),
1498 type, type->size_is);
1500 return start_offset;
1502 else
1504 if (rtype == RPC_FC_WCHAR)
1505 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1506 else
1507 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1508 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1509 *typestring_offset += 2;
1511 return start_offset;
1515 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1516 const char *name, unsigned int *typestring_offset)
1518 const expr_t *length_is = type->length_is;
1519 const expr_t *size_is = type->size_is;
1520 unsigned int align = 0;
1521 size_t size;
1522 size_t start_offset;
1523 int has_pointer;
1524 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1525 unsigned int baseoff
1526 = type->declarray && current_structure
1527 ? type_memsize(current_structure, &align)
1528 : 0;
1530 if (!pointer_type)
1531 pointer_type = RPC_FC_RP;
1533 has_pointer = FALSE;
1534 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1535 has_pointer = TRUE;
1537 align = 0;
1538 size = type_memsize(type, &align);
1539 if (size == 0) /* conformant array */
1540 size = type_memsize(type->ref, &align);
1542 start_offset = *typestring_offset;
1543 update_tfsoff(type, start_offset, file);
1544 print_start_tfs_comment(file, type, start_offset);
1545 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1546 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1547 *typestring_offset += 2;
1549 align = 0;
1550 if (type->type != RPC_FC_BOGUS_ARRAY)
1552 unsigned char tc = type->type;
1554 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1556 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1557 *typestring_offset += 4;
1559 else
1561 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1562 *typestring_offset += 2;
1565 if (is_conformant_array(type))
1566 *typestring_offset
1567 += write_conf_or_var_desc(file, current_structure, baseoff,
1568 type, size_is);
1570 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1572 unsigned int elalign = 0;
1573 size_t elsize = type_memsize(type->ref, &elalign);
1575 if (type->type == RPC_FC_LGVARRAY)
1577 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1578 *typestring_offset += 4;
1580 else
1582 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1583 *typestring_offset += 2;
1586 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1587 *typestring_offset += 2;
1590 if (length_is)
1591 *typestring_offset
1592 += write_conf_or_var_desc(file, current_structure, baseoff,
1593 type, length_is);
1595 if (has_pointer && (!type->declarray || !current_structure))
1597 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1598 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1599 *typestring_offset += 2;
1600 write_pointer_description(file, type, typestring_offset);
1601 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1602 *typestring_offset += 1;
1605 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1606 write_end(file, typestring_offset);
1608 else
1610 unsigned int dim = size_is ? 0 : type->dim;
1611 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1612 *typestring_offset += 2;
1613 *typestring_offset
1614 += write_conf_or_var_desc(file, current_structure, baseoff,
1615 type, size_is);
1616 *typestring_offset
1617 += write_conf_or_var_desc(file, current_structure, baseoff,
1618 type, length_is);
1619 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1620 write_end(file, typestring_offset);
1623 return start_offset;
1626 static const var_t *find_array_or_string_in_struct(const type_t *type)
1628 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1629 const type_t *ft = last_field->type;
1631 if (ft->declarray && is_conformant_array(ft))
1632 return last_field;
1634 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1635 return find_array_or_string_in_struct(last_field->type);
1636 else
1637 return NULL;
1640 static void write_struct_members(FILE *file, const type_t *type,
1641 unsigned int *corroff, unsigned int *typestring_offset)
1643 const var_t *field;
1644 unsigned short offset = 0;
1645 int salign = -1;
1646 int padding;
1648 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1650 type_t *ft = field->type;
1651 if (!ft->declarray || !is_conformant_array(ft))
1653 unsigned int align = 0;
1654 size_t size = type_memsize(ft, &align);
1655 if (salign == -1)
1656 salign = align;
1657 if ((align - 1) & offset)
1659 unsigned char fc = 0;
1660 switch (align)
1662 case 4:
1663 fc = RPC_FC_ALIGNM4;
1664 break;
1665 case 8:
1666 fc = RPC_FC_ALIGNM8;
1667 break;
1668 default:
1669 error("write_struct_members: cannot align type %d\n", ft->type);
1671 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1672 offset = (offset + (align - 1)) & ~(align - 1);
1673 *typestring_offset += 1;
1675 write_member_type(file, type, field->attrs, field->type, corroff,
1676 typestring_offset);
1677 offset += size;
1681 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1682 if (padding)
1684 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1685 RPC_FC_STRUCTPAD1 + padding - 1,
1686 padding);
1687 *typestring_offset += 1;
1690 write_end(file, typestring_offset);
1693 static size_t write_struct_tfs(FILE *file, type_t *type,
1694 const char *name, unsigned int *tfsoff)
1696 const type_t *save_current_structure = current_structure;
1697 unsigned int total_size;
1698 const var_t *array;
1699 size_t start_offset;
1700 size_t array_offset;
1701 int has_pointers = 0;
1702 unsigned int align = 0;
1703 unsigned int corroff;
1704 var_t *f;
1706 guard_rec(type);
1707 current_structure = type;
1709 total_size = type_memsize(type, &align);
1710 if (total_size > USHRT_MAX)
1711 error("structure size for %s exceeds %d bytes by %d bytes\n",
1712 name, USHRT_MAX, total_size - USHRT_MAX);
1714 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1715 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1716 FALSE, tfsoff);
1718 array = find_array_or_string_in_struct(type);
1719 if (array && !processed(array->type))
1720 array_offset
1721 = is_attr(array->attrs, ATTR_STRING)
1722 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1723 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1725 corroff = *tfsoff;
1726 write_descriptors(file, type, tfsoff);
1728 start_offset = *tfsoff;
1729 update_tfsoff(type, start_offset, file);
1730 print_start_tfs_comment(file, type, start_offset);
1731 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1732 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1733 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1734 *tfsoff += 4;
1736 if (array)
1738 unsigned int absoff = array->type->typestring_offset;
1739 short reloff = absoff - *tfsoff;
1740 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1741 reloff, reloff, absoff);
1742 *tfsoff += 2;
1744 else if (type->type == RPC_FC_BOGUS_STRUCT)
1746 print_file(file, 2, "NdrFcShort(0x0),\n");
1747 *tfsoff += 2;
1750 if (type->type == RPC_FC_BOGUS_STRUCT)
1752 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1753 nothing is written to file yet. On the actual writing pass,
1754 this will have been updated. */
1755 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1756 short reloff = absoff - *tfsoff;
1757 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1758 reloff, reloff, absoff);
1759 *tfsoff += 2;
1761 else if ((type->type == RPC_FC_PSTRUCT) ||
1762 (type->type == RPC_FC_CPSTRUCT) ||
1763 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1765 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1766 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1767 *tfsoff += 2;
1768 write_pointer_description(file, type, tfsoff);
1769 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1770 *tfsoff += 1;
1773 write_struct_members(file, type, &corroff, tfsoff);
1775 if (type->type == RPC_FC_BOGUS_STRUCT)
1777 const var_list_t *fs = type->fields;
1778 const var_t *f;
1780 type->ptrdesc = *tfsoff;
1781 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1783 type_t *ft = f->type;
1784 if (is_ptr(ft))
1785 write_pointer_tfs(file, ft, tfsoff);
1786 else if (!ft->declarray && is_conformant_array(ft))
1788 unsigned int absoff = ft->typestring_offset;
1789 short reloff = absoff - (*tfsoff + 2);
1790 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1791 /* FIXME: We need to store pointer attributes for arrays
1792 so we don't lose pointer_default info. */
1793 if (ptr_type == 0)
1794 ptr_type = RPC_FC_UP;
1795 print_file(file, 0, "/* %d */\n", *tfsoff);
1796 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1797 string_of_type(ptr_type));
1798 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1799 reloff, reloff, absoff);
1800 *tfsoff += 4;
1803 if (type->ptrdesc == *tfsoff)
1804 type->ptrdesc = 0;
1807 current_structure = save_current_structure;
1808 return start_offset;
1811 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1812 unsigned char flags, size_t offset,
1813 unsigned int *typeformat_offset)
1815 size_t start_offset = *typeformat_offset;
1816 short reloff = offset - (*typeformat_offset + 2);
1817 int in_attr, out_attr;
1818 in_attr = is_attr(attrs, ATTR_IN);
1819 out_attr = is_attr(attrs, ATTR_OUT);
1820 if (!in_attr && !out_attr) in_attr = 1;
1822 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1823 flags |= 0x04;
1825 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1826 pointer_type,
1827 flags,
1828 string_of_type(pointer_type));
1829 if (file)
1831 if (flags & 0x04)
1832 fprintf(file, " [allocated_on_stack]");
1833 if (flags & 0x10)
1834 fprintf(file, " [pointer_deref]");
1835 fprintf(file, " */\n");
1838 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1839 *typeformat_offset += 4;
1841 return start_offset;
1844 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1846 if (t == NULL)
1848 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1850 else if (is_base_type(t->type))
1852 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1853 t->type, string_of_type(t->type));
1855 else if (t->typestring_offset)
1857 short reloff = t->typestring_offset - *tfsoff;
1858 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1859 reloff, reloff, t->typestring_offset);
1861 else
1862 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1864 *tfsoff += 2;
1867 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1869 unsigned int align = 0;
1870 unsigned int start_offset;
1871 size_t size = type_memsize(type, &align);
1872 var_list_t *fields;
1873 size_t nbranch = 0;
1874 type_t *deftype = NULL;
1875 short nodeftype = 0xffff;
1876 var_t *f;
1878 guard_rec(type);
1880 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1882 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1883 fields = uv->type->fields;
1885 else
1886 fields = type->fields;
1888 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1890 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1891 if (cases)
1892 nbranch += list_count(cases);
1893 if (f->type)
1894 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1897 start_offset = *tfsoff;
1898 update_tfsoff(type, start_offset, file);
1899 print_start_tfs_comment(file, type, start_offset);
1900 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1902 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1903 const type_t *st = sv->type;
1905 switch (st->type)
1907 case RPC_FC_CHAR:
1908 case RPC_FC_SMALL:
1909 case RPC_FC_USMALL:
1910 case RPC_FC_SHORT:
1911 case RPC_FC_USHORT:
1912 case RPC_FC_LONG:
1913 case RPC_FC_ULONG:
1914 case RPC_FC_ENUM16:
1915 case RPC_FC_ENUM32:
1916 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1917 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1918 0x40 | st->type, string_of_type(st->type));
1919 *tfsoff += 2;
1920 break;
1921 default:
1922 error("union switch type must be an integer, char, or enum\n");
1925 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1926 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1927 *tfsoff += 4;
1929 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1931 type_t *ft = f->type;
1932 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1933 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1934 expr_t *c;
1936 if (cases == NULL && !deflt)
1937 error("union field %s with neither case nor default attribute\n", f->name);
1939 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1941 /* MIDL doesn't check for duplicate cases, even though that seems
1942 like a reasonable thing to do, it just dumps them to the TFS
1943 like we're going to do here. */
1944 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1945 *tfsoff += 4;
1946 write_branch_type(file, ft, tfsoff);
1949 /* MIDL allows multiple default branches, even though that seems
1950 illogical, it just chooses the last one, which is what we will
1951 do. */
1952 if (deflt)
1954 deftype = ft;
1955 nodeftype = 0;
1959 if (deftype)
1961 write_branch_type(file, deftype, tfsoff);
1963 else
1965 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1966 *tfsoff += 2;
1969 return start_offset;
1972 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1973 unsigned int *typeformat_offset)
1975 size_t i;
1976 size_t start_offset = *typeformat_offset;
1977 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1979 if (iid)
1981 expr_t expr;
1983 expr.type = EXPR_IDENTIFIER;
1984 expr.ref = NULL;
1985 expr.u.sval = iid->name;
1986 expr.is_const = FALSE;
1987 print_file(file, 2, "0x2f, /* FC_IP */\n");
1988 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1989 *typeformat_offset
1990 += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
1992 else
1994 const type_t *base = is_ptr(type) ? type->ref : type;
1995 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1997 if (! uuid)
1998 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
2000 update_tfsoff(type, start_offset, file);
2001 print_start_tfs_comment(file, type, start_offset);
2002 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2003 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2004 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2005 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2006 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2007 for (i = 0; i < 8; ++i)
2008 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2010 if (file)
2011 fprintf(file, "\n");
2013 *typeformat_offset += 18;
2015 return start_offset;
2018 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2019 const var_t *var,
2020 unsigned int *typeformat_offset)
2022 size_t start_offset = *typeformat_offset;
2023 unsigned char flags = 0x08 /* strict */;
2025 if (is_ptr(type))
2027 flags |= 0x80;
2028 if (type->type != RPC_FC_RP)
2029 flags |= 0x01;
2031 if (is_attr(var->attrs, ATTR_IN))
2032 flags |= 0x40;
2033 if (is_attr(var->attrs, ATTR_OUT))
2034 flags |= 0x20;
2036 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2037 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2038 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2039 print_file(file, 0, "can't be null, ");
2040 if (flags & 0x02)
2041 print_file(file, 0, "serialize, ");
2042 if (flags & 0x04)
2043 print_file(file, 0, "no serialize, ");
2044 if (flags & 0x08)
2045 print_file(file, 0, "strict, ");
2046 if ((flags & 0x21) == 0x20)
2047 print_file(file, 0, "out, ");
2048 if ((flags & 0x21) == 0x21)
2049 print_file(file, 0, "return, ");
2050 if (flags & 0x40)
2051 print_file(file, 0, "in, ");
2052 if (flags & 0x80)
2053 print_file(file, 0, "via ptr, ");
2054 print_file(file, 0, "*/\n");
2055 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2056 print_file(file, 2, "0, /* FIXME: param num */\n");
2057 *typeformat_offset += 4;
2059 return start_offset;
2062 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2063 type_t *type, const var_t *var,
2064 unsigned int *typeformat_offset)
2066 size_t offset;
2068 if (is_context_handle(type))
2069 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2071 if (is_user_type(type))
2073 write_user_tfs(file, type, typeformat_offset);
2074 return type->typestring_offset;
2077 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2078 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
2080 if (is_array(type))
2082 int ptr_type;
2083 size_t off;
2084 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2085 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2086 /* Top level pointers to conformant arrays may be handled specially
2087 since we can bypass the pointer, but if the array is burried
2088 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2089 always need to write the pointer. */
2090 if (!ptr_type && var->type != type)
2091 /* FIXME: This should use pointer_default, but the information
2092 isn't kept around for arrays. */
2093 ptr_type = RPC_FC_UP;
2094 if (ptr_type && ptr_type != RPC_FC_RP)
2096 unsigned int absoff = type->typestring_offset;
2097 short reloff = absoff - (*typeformat_offset + 2);
2098 off = *typeformat_offset;
2099 print_file(file, 0, "/* %d */\n", off);
2100 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2101 string_of_type(ptr_type));
2102 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2103 reloff, reloff, absoff);
2104 *typeformat_offset += 4;
2106 return off;
2109 if (!is_ptr(type))
2111 /* basic types don't need a type format string */
2112 if (is_base_type(type->type))
2113 return 0;
2115 switch (type->type)
2117 case RPC_FC_STRUCT:
2118 case RPC_FC_PSTRUCT:
2119 case RPC_FC_CSTRUCT:
2120 case RPC_FC_CPSTRUCT:
2121 case RPC_FC_CVSTRUCT:
2122 case RPC_FC_BOGUS_STRUCT:
2123 return write_struct_tfs(file, type, var->name, typeformat_offset);
2124 case RPC_FC_ENCAPSULATED_UNION:
2125 case RPC_FC_NON_ENCAPSULATED_UNION:
2126 return write_union_tfs(file, type, typeformat_offset);
2127 case RPC_FC_IGNORE:
2128 case RPC_FC_BIND_PRIMITIVE:
2129 /* nothing to do */
2130 return 0;
2131 default:
2132 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2135 else if (last_ptr(type))
2137 size_t start_offset = *typeformat_offset;
2138 int in_attr = is_attr(var->attrs, ATTR_IN);
2139 int out_attr = is_attr(var->attrs, ATTR_OUT);
2140 const type_t *base = type->ref;
2142 if (base->type == RPC_FC_IP
2143 || (base->type == 0
2144 && is_attr(var->attrs, ATTR_IIDIS)))
2146 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2149 /* special case for pointers to base types */
2150 if (is_base_type(base->type))
2152 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2153 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2154 string_of_type(type->type),
2155 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2156 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2157 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2158 *typeformat_offset += 4;
2159 return start_offset;
2163 assert(is_ptr(type));
2165 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2166 if (file)
2167 fprintf(file, "/* %2u */\n", *typeformat_offset);
2168 return write_pointer_only_tfs(file, var->attrs, type->type,
2169 !last_ptr(type) ? 0x10 : 0,
2170 offset, typeformat_offset);
2173 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2174 const char *name, int write_ptr, unsigned int *tfsoff)
2176 int retmask = 0;
2178 if (is_user_type(type))
2180 write_user_tfs(file, type, tfsoff);
2182 else if (is_ptr(type))
2184 type_t *ref = type->ref;
2186 if (ref->type == RPC_FC_IP
2187 || (ref->type == 0
2188 && is_attr(attrs, ATTR_IIDIS)))
2190 write_ip_tfs(file, attrs, type, tfsoff);
2192 else
2194 if (!processed(ref) && !is_base_type(ref->type))
2195 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2197 if (write_ptr)
2198 write_pointer_tfs(file, type, tfsoff);
2200 retmask |= 1;
2203 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2205 write_string_tfs(file, attrs, type, name, tfsoff);
2207 else if (type->declarray && is_conformant_array(type))
2208 ; /* conformant arrays and strings are handled specially */
2209 else if (is_array(type))
2211 write_array_tfs(file, attrs, type, name, tfsoff);
2212 if (is_conformant_array(type))
2213 retmask |= 1;
2215 else if (is_struct(type->type))
2217 if (!processed(type))
2218 write_struct_tfs(file, type, name, tfsoff);
2220 else if (is_union(type->type))
2222 if (!processed(type))
2223 write_union_tfs(file, type, tfsoff);
2225 else if (!is_base_type(type->type))
2226 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2227 name, type->type);
2229 return retmask;
2232 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2234 const var_t *var;
2235 const ifref_t *iface;
2236 unsigned int typeformat_offset = 2;
2238 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2240 if (!pred(iface->iface))
2241 continue;
2243 if (iface->iface->funcs)
2245 const func_t *func;
2246 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2248 if (is_local(func->def->attrs)) continue;
2250 current_func = func;
2251 if (func->args)
2252 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2253 update_tfsoff(
2254 var->type,
2255 write_typeformatstring_var(
2256 file, 2, func, var->type, var,
2257 &typeformat_offset),
2258 file);
2263 return typeformat_offset + 1;
2267 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2269 int indent = 0;
2271 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2272 print_file(file, indent, "{\n");
2273 indent++;
2274 print_file(file, indent, "0,\n");
2275 print_file(file, indent, "{\n");
2276 indent++;
2277 print_file(file, indent, "NdrFcShort(0x0),\n");
2279 set_all_tfswrite(TRUE);
2280 process_tfs(file, ifaces, pred);
2282 print_file(file, indent, "0x0\n");
2283 indent--;
2284 print_file(file, indent, "}\n");
2285 indent--;
2286 print_file(file, indent, "};\n");
2287 print_file(file, indent, "\n");
2290 static unsigned int get_required_buffer_size_type(
2291 const type_t *type, const char *name, unsigned int *alignment)
2293 *alignment = 0;
2294 if (is_user_type(type))
2296 const char *uname;
2297 const type_t *utype = get_user_type(type, &uname);
2298 return get_required_buffer_size_type(utype, uname, alignment);
2300 else
2302 switch (type->type)
2304 case RPC_FC_BYTE:
2305 case RPC_FC_CHAR:
2306 case RPC_FC_USMALL:
2307 case RPC_FC_SMALL:
2308 *alignment = 4;
2309 return 1;
2311 case RPC_FC_WCHAR:
2312 case RPC_FC_USHORT:
2313 case RPC_FC_SHORT:
2314 case RPC_FC_ENUM16:
2315 *alignment = 4;
2316 return 2;
2318 case RPC_FC_ULONG:
2319 case RPC_FC_LONG:
2320 case RPC_FC_ENUM32:
2321 case RPC_FC_FLOAT:
2322 case RPC_FC_ERROR_STATUS_T:
2323 *alignment = 4;
2324 return 4;
2326 case RPC_FC_HYPER:
2327 case RPC_FC_DOUBLE:
2328 *alignment = 8;
2329 return 8;
2331 case RPC_FC_IGNORE:
2332 case RPC_FC_BIND_PRIMITIVE:
2333 return 0;
2335 case RPC_FC_STRUCT:
2336 case RPC_FC_PSTRUCT:
2338 size_t size = 0;
2339 const var_t *field;
2340 if (!type->fields) return 0;
2341 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2343 unsigned int alignment;
2344 size += get_required_buffer_size_type(field->type, field->name,
2345 &alignment);
2347 return size;
2350 case RPC_FC_RP:
2351 return
2352 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2353 ? get_required_buffer_size_type( type->ref, name, alignment )
2354 : 0;
2356 case RPC_FC_SMFARRAY:
2357 case RPC_FC_LGFARRAY:
2358 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2360 default:
2361 return 0;
2366 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2368 int in_attr = is_attr(var->attrs, ATTR_IN);
2369 int out_attr = is_attr(var->attrs, ATTR_OUT);
2370 const type_t *t;
2372 if (!in_attr && !out_attr)
2373 in_attr = 1;
2375 *alignment = 0;
2377 for (t = var->type; is_ptr(t); t = t->ref)
2378 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2380 *alignment = 4;
2381 return 20;
2384 if (pass == PASS_OUT)
2386 if (out_attr && is_ptr(var->type))
2388 type_t *type = var->type;
2390 if (type->type == RPC_FC_STRUCT)
2392 const var_t *field;
2393 unsigned int size = 36;
2395 if (!type->fields) return size;
2396 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2398 unsigned int align;
2399 size += get_required_buffer_size_type(
2400 field->type, field->name, &align);
2402 return size;
2405 return 0;
2407 else
2409 if ((!out_attr || in_attr) && !var->type->size_is
2410 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2412 if (is_ptr(var->type))
2414 type_t *type = var->type;
2416 if (is_base_type(type->type))
2418 return 25;
2420 else if (type->type == RPC_FC_STRUCT)
2422 unsigned int size = 36;
2423 const var_t *field;
2425 if (!type->fields) return size;
2426 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2428 unsigned int align;
2429 size += get_required_buffer_size_type(
2430 field->type, field->name, &align);
2432 return size;
2437 return get_required_buffer_size_type(var->type, var->name, alignment);
2441 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2443 const var_t *var;
2444 unsigned int total_size = 0, alignment;
2446 if (func->args)
2448 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2450 total_size += get_required_buffer_size(var, &alignment, pass);
2451 total_size += alignment;
2455 if (pass == PASS_OUT && !is_void(func->def->type))
2457 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2458 total_size += alignment;
2460 return total_size;
2463 static void print_phase_function(FILE *file, int indent, const char *type,
2464 enum remoting_phase phase,
2465 const var_t *var, unsigned int type_offset)
2467 const char *function;
2468 switch (phase)
2470 case PHASE_BUFFERSIZE:
2471 function = "BufferSize";
2472 break;
2473 case PHASE_MARSHAL:
2474 function = "Marshall";
2475 break;
2476 case PHASE_UNMARSHAL:
2477 function = "Unmarshall";
2478 break;
2479 case PHASE_FREE:
2480 function = "Free";
2481 break;
2482 default:
2483 assert(0);
2484 return;
2487 print_file(file, indent, "Ndr%s%s(\n", type, function);
2488 indent++;
2489 print_file(file, indent, "&_StubMsg,\n");
2490 print_file(file, indent, "%s%s%s%s,\n",
2491 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2492 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2493 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2494 var->name);
2495 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2496 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2497 if (phase == PHASE_UNMARSHAL)
2498 print_file(file, indent, "0);\n");
2499 indent--;
2502 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2503 enum pass pass, const var_t *var,
2504 const char *varname)
2506 type_t *type = var->type;
2507 unsigned int size;
2508 unsigned int alignment = 0;
2509 unsigned char rtype;
2511 /* no work to do for other phases, buffer sizing is done elsewhere */
2512 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2513 return;
2515 rtype = is_ptr(type) ? type->ref->type : type->type;
2517 switch (rtype)
2519 case RPC_FC_BYTE:
2520 case RPC_FC_CHAR:
2521 case RPC_FC_SMALL:
2522 case RPC_FC_USMALL:
2523 size = 1;
2524 alignment = 1;
2525 break;
2527 case RPC_FC_WCHAR:
2528 case RPC_FC_USHORT:
2529 case RPC_FC_SHORT:
2530 case RPC_FC_ENUM16:
2531 size = 2;
2532 alignment = 2;
2533 break;
2535 case RPC_FC_ULONG:
2536 case RPC_FC_LONG:
2537 case RPC_FC_ENUM32:
2538 case RPC_FC_FLOAT:
2539 case RPC_FC_ERROR_STATUS_T:
2540 size = 4;
2541 alignment = 4;
2542 break;
2544 case RPC_FC_HYPER:
2545 case RPC_FC_DOUBLE:
2546 size = 8;
2547 alignment = 8;
2548 break;
2550 case RPC_FC_IGNORE:
2551 case RPC_FC_BIND_PRIMITIVE:
2552 /* no marshalling needed */
2553 return;
2555 default:
2556 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2557 size = 0;
2560 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2561 alignment - 1, alignment - 1);
2563 if (phase == PHASE_MARSHAL)
2565 print_file(file, indent, "*(");
2566 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2567 if (is_ptr(type))
2568 fprintf(file, " *)_StubMsg.Buffer = *");
2569 else
2570 fprintf(file, " *)_StubMsg.Buffer = ");
2571 fprintf(file, "%s", varname);
2572 fprintf(file, ";\n");
2574 else if (phase == PHASE_UNMARSHAL)
2576 if (pass == PASS_IN || pass == PASS_RETURN)
2577 print_file(file, indent, "");
2578 else
2579 print_file(file, indent, "*");
2580 fprintf(file, "%s", varname);
2581 if (pass == PASS_IN && is_ptr(type))
2582 fprintf(file, " = (");
2583 else
2584 fprintf(file, " = *(");
2585 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2586 fprintf(file, " *)_StubMsg.Buffer;\n");
2589 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2590 write_type_decl(file, var->type, NULL);
2591 fprintf(file, ");\n");
2594 /* returns whether the MaxCount, Offset or ActualCount members need to be
2595 * filled in for the specified phase */
2596 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2598 return (phase != PHASE_UNMARSHAL);
2601 static int needs_freeing(const attr_list_t *attrs, const type_t *t, int out)
2603 return
2604 (is_user_type(t)
2605 || (is_ptr(t)
2606 && (t->ref->type == RPC_FC_IP
2607 || is_ptr(t->ref))))
2608 || (out && (is_string_type(attrs, t)
2609 || is_array(t)));
2612 expr_t *get_size_is_expr(const type_t *t, const char *name)
2614 expr_t *x = NULL;
2616 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2617 if (t->size_is)
2619 if (!x)
2620 x = t->size_is;
2621 else
2622 error("%s: multidimensional conformant"
2623 " arrays not supported at the top level\n",
2624 name);
2627 return x;
2630 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2631 enum pass pass, enum remoting_phase phase)
2633 int in_attr, out_attr, pointer_type;
2634 const var_t *var;
2636 if (!func->args)
2637 return;
2639 if (phase == PHASE_BUFFERSIZE)
2641 unsigned int size = get_function_buffer_size( func, pass );
2642 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2645 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2647 const type_t *type = var->type;
2648 unsigned char rtype;
2649 size_t start_offset = type->typestring_offset;
2651 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2652 if (!pointer_type)
2653 pointer_type = RPC_FC_RP;
2655 in_attr = is_attr(var->attrs, ATTR_IN);
2656 out_attr = is_attr(var->attrs, ATTR_OUT);
2657 if (!in_attr && !out_attr)
2658 in_attr = 1;
2660 if (phase == PHASE_FREE)
2662 if (!needs_freeing(var->attrs, type, out_attr))
2663 continue;
2665 else
2666 switch (pass)
2668 case PASS_IN:
2669 if (!in_attr) continue;
2670 break;
2671 case PASS_OUT:
2672 if (!out_attr) continue;
2673 break;
2674 case PASS_RETURN:
2675 break;
2678 rtype = type->type;
2680 if (is_context_handle(type))
2682 if (phase == PHASE_MARSHAL)
2684 if (pass == PASS_IN)
2686 print_file(file, indent, "NdrClientContextMarshall(\n");
2687 print_file(file, indent + 1, "&_StubMsg,\n");
2688 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2689 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2691 else
2693 print_file(file, indent, "NdrServerContextMarshall(\n");
2694 print_file(file, indent + 1, "&_StubMsg,\n");
2695 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2696 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2699 else if (phase == PHASE_UNMARSHAL)
2701 if (pass == PASS_OUT)
2703 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2704 print_file(file, indent + 1, "&_StubMsg,\n");
2705 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2706 print_file(file, indent + 1, "_Handle);\n");
2708 else
2709 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2712 else if (is_user_type(var->type))
2714 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2716 else if (is_string_type(var->attrs, var->type))
2718 if (is_array(type) && !is_conformant_array(type))
2719 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2720 else
2722 if (type->size_is && is_size_needed_for_phase(phase))
2724 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2725 write_expr(file, type->size_is, 1);
2726 fprintf(file, ";\n");
2729 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2730 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2731 else
2732 print_phase_function(file, indent, "ConformantString", phase, var,
2733 start_offset + (type->size_is ? 4 : 2));
2736 else if (is_array(type))
2738 unsigned char tc = type->type;
2739 const char *array_type = "FixedArray";
2741 /* We already have the size_is expression since it's at the
2742 top level, but do checks for multidimensional conformant
2743 arrays. When we handle them, we'll need to extend this
2744 function to return a list, and then we'll actually use
2745 the return value. */
2746 get_size_is_expr(type, var->name);
2748 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2750 if (is_size_needed_for_phase(phase))
2752 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2753 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2754 write_expr(file, type->length_is, 1);
2755 fprintf(file, ";\n\n");
2757 array_type = "VaryingArray";
2759 else if (tc == RPC_FC_CARRAY)
2761 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2763 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2764 write_expr(file, type->size_is, 1);
2765 fprintf(file, ";\n\n");
2767 array_type = "ConformantArray";
2769 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2771 if (is_size_needed_for_phase(phase))
2773 if (type->size_is)
2775 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2776 write_expr(file, type->size_is, 1);
2777 fprintf(file, ";\n");
2779 if (type->length_is)
2781 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2782 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2783 write_expr(file, type->length_is, 1);
2784 fprintf(file, ";\n\n");
2787 array_type = (tc == RPC_FC_BOGUS_ARRAY
2788 ? "ComplexArray"
2789 : "ConformantVaryingArray");
2792 if (!in_attr && phase == PHASE_FREE)
2794 print_file(file, indent, "if (%s)\n", var->name);
2795 indent++;
2796 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2798 else if (phase != PHASE_FREE)
2800 const char *t = pointer_type == RPC_FC_RP ? array_type : "Pointer";
2801 print_phase_function(file, indent, t, phase, var, start_offset);
2804 else if (!is_ptr(var->type) && is_base_type(rtype))
2806 print_phase_basetype(file, indent, phase, pass, var, var->name);
2808 else if (!is_ptr(var->type))
2810 switch (rtype)
2812 case RPC_FC_STRUCT:
2813 case RPC_FC_PSTRUCT:
2814 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2815 break;
2816 case RPC_FC_CSTRUCT:
2817 case RPC_FC_CPSTRUCT:
2818 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2819 break;
2820 case RPC_FC_CVSTRUCT:
2821 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2822 break;
2823 case RPC_FC_BOGUS_STRUCT:
2824 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2825 break;
2826 case RPC_FC_RP:
2827 if (is_base_type( var->type->ref->type ))
2829 print_phase_basetype(file, indent, phase, pass, var, var->name);
2831 else if (var->type->ref->type == RPC_FC_STRUCT)
2833 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2834 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2836 else
2838 const var_t *iid;
2839 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2840 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2841 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2843 break;
2844 default:
2845 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2848 else
2850 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2852 print_phase_basetype(file, indent, phase, pass, var, var->name);
2854 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2856 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2857 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2859 else
2861 const var_t *iid;
2862 expr_t *sx = get_size_is_expr(type, var->name);
2864 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2865 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2866 else if (sx)
2868 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2869 write_expr(file, sx, 1);
2870 fprintf(file, ";\n\n");
2872 if (var->type->ref->type == RPC_FC_IP)
2873 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2874 else
2875 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2878 fprintf(file, "\n");
2883 size_t get_size_procformatstring_var(const var_t *var)
2885 return write_procformatstring_var(NULL, 0, var, FALSE);
2889 size_t get_size_procformatstring_func(const func_t *func)
2891 const var_t *var;
2892 size_t size = 0;
2894 /* argument list size */
2895 if (func->args)
2896 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2897 size += get_size_procformatstring_var(var);
2899 /* return value size */
2900 if (is_void(func->def->type))
2901 size += 2; /* FC_END and FC_PAD */
2902 else
2903 size += get_size_procformatstring_var(func->def);
2905 return size;
2908 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2910 const ifref_t *iface;
2911 size_t size = 1;
2912 const func_t *func;
2914 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2916 if (!pred(iface->iface))
2917 continue;
2919 if (iface->iface->funcs)
2920 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2921 if (!is_local(func->def->attrs))
2922 size += get_size_procformatstring_func( func );
2924 return size;
2927 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2929 set_all_tfswrite(FALSE);
2930 return process_tfs(NULL, ifaces, pred);
2933 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2934 const var_list_t *fields, const char *structvar)
2936 switch (e->type) {
2937 case EXPR_VOID:
2938 break;
2939 case EXPR_NUM:
2940 fprintf(h, "%lu", e->u.lval);
2941 break;
2942 case EXPR_HEXNUM:
2943 fprintf(h, "0x%lx", e->u.lval);
2944 break;
2945 case EXPR_DOUBLE:
2946 fprintf(h, "%#.15g", e->u.dval);
2947 break;
2948 case EXPR_TRUEFALSE:
2949 if (e->u.lval == 0)
2950 fprintf(h, "FALSE");
2951 else
2952 fprintf(h, "TRUE");
2953 break;
2954 case EXPR_IDENTIFIER:
2956 const var_t *field;
2957 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2958 if (!strcmp(e->u.sval, field->name))
2960 fprintf(h, "%s->%s", structvar, e->u.sval);
2961 break;
2964 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2965 break;
2967 case EXPR_NEG:
2968 fprintf(h, "-");
2969 write_struct_expr(h, e->ref, 1, fields, structvar);
2970 break;
2971 case EXPR_NOT:
2972 fprintf(h, "~");
2973 write_struct_expr(h, e->ref, 1, fields, structvar);
2974 break;
2975 case EXPR_PPTR:
2976 fprintf(h, "*");
2977 write_struct_expr(h, e->ref, 1, fields, structvar);
2978 break;
2979 case EXPR_CAST:
2980 fprintf(h, "(");
2981 write_type_decl(h, e->u.tref, NULL);
2982 fprintf(h, ")");
2983 write_struct_expr(h, e->ref, 1, fields, structvar);
2984 break;
2985 case EXPR_SIZEOF:
2986 fprintf(h, "sizeof(");
2987 write_type_decl(h, e->u.tref, NULL);
2988 fprintf(h, ")");
2989 break;
2990 case EXPR_SHL:
2991 case EXPR_SHR:
2992 case EXPR_MUL:
2993 case EXPR_DIV:
2994 case EXPR_ADD:
2995 case EXPR_SUB:
2996 case EXPR_AND:
2997 case EXPR_OR:
2998 if (brackets) fprintf(h, "(");
2999 write_struct_expr(h, e->ref, 1, fields, structvar);
3000 switch (e->type) {
3001 case EXPR_SHL: fprintf(h, " << "); break;
3002 case EXPR_SHR: fprintf(h, " >> "); break;
3003 case EXPR_MUL: fprintf(h, " * "); break;
3004 case EXPR_DIV: fprintf(h, " / "); break;
3005 case EXPR_ADD: fprintf(h, " + "); break;
3006 case EXPR_SUB: fprintf(h, " - "); break;
3007 case EXPR_AND: fprintf(h, " & "); break;
3008 case EXPR_OR: fprintf(h, " | "); break;
3009 default: break;
3011 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3012 if (brackets) fprintf(h, ")");
3013 break;
3014 case EXPR_COND:
3015 if (brackets) fprintf(h, "(");
3016 write_struct_expr(h, e->ref, 1, fields, structvar);
3017 fprintf(h, " ? ");
3018 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3019 fprintf(h, " : ");
3020 write_struct_expr(h, e->ext2, 1, fields, structvar);
3021 if (brackets) fprintf(h, ")");
3022 break;
3027 void declare_stub_args( FILE *file, int indent, const func_t *func )
3029 int in_attr, out_attr;
3030 int i = 0;
3031 const var_t *def = func->def;
3032 const var_t *var;
3034 /* declare return value '_RetVal' */
3035 if (!is_void(def->type))
3037 print_file(file, indent, "");
3038 write_type_decl_left(file, def->type);
3039 fprintf(file, " _RetVal;\n");
3042 if (!func->args)
3043 return;
3045 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3047 int is_string = is_attr(var->attrs, ATTR_STRING);
3049 in_attr = is_attr(var->attrs, ATTR_IN);
3050 out_attr = is_attr(var->attrs, ATTR_OUT);
3051 if (!out_attr && !in_attr)
3052 in_attr = 1;
3054 if (is_context_handle(var->type))
3055 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3056 else
3058 if (!in_attr && !var->type->size_is && !is_string)
3060 print_file(file, indent, "");
3061 write_type_decl(file, var->type->ref, "_W%u", i++);
3062 fprintf(file, ";\n");
3065 print_file(file, indent, "");
3066 write_type_decl_left(file, var->type);
3067 fprintf(file, " ");
3068 if (var->type->declarray) {
3069 fprintf(file, "( *");
3070 write_name(file, var);
3071 fprintf(file, " )");
3072 } else
3073 write_name(file, var);
3074 write_type_right(file, var->type, FALSE);
3075 fprintf(file, ";\n");
3077 if (decl_indirect(var->type))
3078 print_file(file, indent, "void *_p_%s = &%s;\n",
3079 var->name, var->name);
3085 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3087 int in_attr, out_attr;
3088 int i = 0, sep = 0;
3089 const var_t *var;
3091 if (!func->args)
3092 return;
3094 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3096 int is_string = is_attr(var->attrs, ATTR_STRING);
3097 in_attr = is_attr(var->attrs, ATTR_IN);
3098 out_attr = is_attr(var->attrs, ATTR_OUT);
3099 if (!out_attr && !in_attr)
3100 in_attr = 1;
3102 if (!in_attr)
3104 print_file(file, indent, "");
3105 write_name(file, var);
3107 if (var->type->size_is)
3109 unsigned int size, align = 0;
3110 type_t *type = var->type;
3112 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3113 for ( ; type->size_is ; type = type->ref)
3115 write_expr(file, type->size_is, TRUE);
3116 fprintf(file, " * ");
3118 size = type_memsize(type, &align);
3119 fprintf(file, "%u);\n", size);
3121 else if (!is_string)
3123 fprintf(file, " = &_W%u;\n", i);
3124 if (is_ptr(var->type) && !last_ptr(var->type))
3125 print_file(file, indent, "_W%u = 0;\n", i);
3126 i++;
3129 sep = 1;
3132 if (sep)
3133 fprintf(file, "\n");
3137 int write_expr_eval_routines(FILE *file, const char *iface)
3139 static const char *var_name = "pS";
3140 int result = 0;
3141 struct expr_eval_routine *eval;
3142 unsigned short callback_offset = 0;
3144 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3146 const char *name = eval->structure->name;
3147 const var_list_t *fields = eval->structure->fields;
3148 result = 1;
3150 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3151 iface, name, callback_offset);
3152 print_file(file, 0, "{\n");
3153 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3154 name, var_name, name, eval->baseoff);
3155 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3156 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3157 write_struct_expr(file, eval->expr, 1, fields, var_name);
3158 fprintf(file, ";\n");
3159 print_file(file, 0, "}\n\n");
3160 callback_offset++;
3162 return result;
3165 void write_expr_eval_routine_list(FILE *file, const char *iface)
3167 struct expr_eval_routine *eval;
3168 struct expr_eval_routine *cursor;
3169 unsigned short callback_offset = 0;
3171 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3172 fprintf(file, "{\n");
3174 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3176 const char *name = eval->structure->name;
3177 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3178 callback_offset++;
3179 list_remove(&eval->entry);
3180 free(eval);
3183 fprintf(file, "};\n\n");
3186 void write_user_quad_list(FILE *file)
3188 user_type_t *ut;
3190 if (list_empty(&user_type_list))
3191 return;
3193 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3194 fprintf(file, "{\n");
3195 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3197 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3198 print_file(file, 1, "{\n");
3199 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3200 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3201 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3202 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3203 print_file(file, 1, "}%s\n", sep);
3205 fprintf(file, "};\n\n");
3208 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3210 const struct str_list_entry_t *endpoint;
3211 const char *p;
3213 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3214 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3215 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3217 print_file( f, 1, "{ (const unsigned char *)\"" );
3218 for (p = endpoint->str; *p && *p != ':'; p++)
3220 if (*p == '"' || *p == '\\') fputc( '\\', f );
3221 fputc( *p, f );
3223 if (!*p) goto error;
3224 if (p[1] != '[') goto error;
3226 fprintf( f, "\", (const unsigned char *)\"" );
3227 for (p += 2; *p && *p != ']'; p++)
3229 if (*p == '"' || *p == '\\') fputc( '\\', f );
3230 fputc( *p, f );
3232 if (*p != ']') goto error;
3233 fprintf( f, "\" },\n" );
3235 print_file( f, 0, "};\n\n" );
3236 return;
3238 error:
3239 error("Invalid endpoint syntax '%s'\n", endpoint->str);