quartz: Prepare mpeg splitter code for seeking by making most splitter parsing locked.
[wine/hacks.git] / tools / widl / typegen.c
blob2b0a624daeb7c494bacf94f16b75cdbd98353e1b
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 <limits.h>
35 #include "widl.h"
36 #include "utils.h"
37 #include "parser.h"
38 #include "header.h"
39 #include "wine/list.h"
41 #include "typegen.h"
43 static const func_t *current_func;
44 static const type_t *current_structure;
45 static const ifref_t *current_iface;
47 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
48 struct expr_eval_routine
50 struct list entry;
51 const type_t *structure;
52 unsigned int baseoff;
53 const expr_t *expr;
56 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
57 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
58 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
59 const char *name, int write_ptr, unsigned int *tfsoff);
60 static const var_t *find_array_or_string_in_struct(const type_t *type);
61 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
62 type_t *type,
63 const char *name, unsigned int *typestring_offset);
65 const char *string_of_type(unsigned char type)
67 switch (type)
69 case RPC_FC_BYTE: return "FC_BYTE";
70 case RPC_FC_CHAR: return "FC_CHAR";
71 case RPC_FC_SMALL: return "FC_SMALL";
72 case RPC_FC_USMALL: return "FC_USMALL";
73 case RPC_FC_WCHAR: return "FC_WCHAR";
74 case RPC_FC_SHORT: return "FC_SHORT";
75 case RPC_FC_USHORT: return "FC_USHORT";
76 case RPC_FC_LONG: return "FC_LONG";
77 case RPC_FC_ULONG: return "FC_ULONG";
78 case RPC_FC_FLOAT: return "FC_FLOAT";
79 case RPC_FC_HYPER: return "FC_HYPER";
80 case RPC_FC_DOUBLE: return "FC_DOUBLE";
81 case RPC_FC_ENUM16: return "FC_ENUM16";
82 case RPC_FC_ENUM32: return "FC_ENUM32";
83 case RPC_FC_IGNORE: return "FC_IGNORE";
84 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
85 case RPC_FC_RP: return "FC_RP";
86 case RPC_FC_UP: return "FC_UP";
87 case RPC_FC_OP: return "FC_OP";
88 case RPC_FC_FP: return "FC_FP";
89 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
90 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
91 case RPC_FC_STRUCT: return "FC_STRUCT";
92 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
93 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
94 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
95 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
96 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
97 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
98 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
99 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
100 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
101 case RPC_FC_CARRAY: return "FC_CARRAY";
102 case RPC_FC_CVARRAY: return "FC_CVARRAY";
103 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
104 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
105 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
106 case RPC_FC_POINTER: return "FC_POINTER";
107 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
108 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
109 case RPC_FC_CSTRING: return "FC_CSTRING";
110 case RPC_FC_WSTRING: return "FC_WSTRING";
111 default:
112 error("string_of_type: unknown type 0x%02x\n", type);
113 return NULL;
117 int is_struct(unsigned char type)
119 switch (type)
121 case RPC_FC_STRUCT:
122 case RPC_FC_PSTRUCT:
123 case RPC_FC_CSTRUCT:
124 case RPC_FC_CPSTRUCT:
125 case RPC_FC_CVSTRUCT:
126 case RPC_FC_BOGUS_STRUCT:
127 return 1;
128 default:
129 return 0;
133 static int is_non_complex_struct(const type_t *type)
135 switch (type->type)
137 case RPC_FC_STRUCT:
138 case RPC_FC_PSTRUCT:
139 case RPC_FC_CSTRUCT:
140 case RPC_FC_CPSTRUCT:
141 case RPC_FC_CVSTRUCT:
142 return 1;
143 default:
144 return 0;
148 int is_union(unsigned char type)
150 switch (type)
152 case RPC_FC_ENCAPSULATED_UNION:
153 case RPC_FC_NON_ENCAPSULATED_UNION:
154 return 1;
155 default:
156 return 0;
160 static int type_has_pointers(const type_t *type)
162 if (is_user_type(type))
163 return FALSE;
164 else if (is_ptr(type))
165 return TRUE;
166 else if (is_array(type))
167 return type_has_pointers(type->ref);
168 else if (is_struct(type->type))
170 const var_t *field;
171 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
173 if (type_has_pointers(field->type))
174 return TRUE;
177 else if (is_union(type->type))
179 var_list_t *fields;
180 const var_t *field;
181 if (type->type == RPC_FC_ENCAPSULATED_UNION)
183 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
184 fields = uv->type->fields;
186 else
187 fields = type->fields;
188 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
190 if (field->type && type_has_pointers(field->type))
191 return TRUE;
195 return FALSE;
198 static int type_has_full_pointer(const type_t *type)
200 if (is_user_type(type))
201 return FALSE;
202 else if (type->type == RPC_FC_FP)
203 return TRUE;
204 else if (is_ptr(type))
205 return FALSE;
206 else if (is_array(type))
207 return type_has_full_pointer(type->ref);
208 else if (is_struct(type->type))
210 const var_t *field;
211 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
213 if (type_has_full_pointer(field->type))
214 return TRUE;
217 else if (is_union(type->type))
219 var_list_t *fields;
220 const var_t *field;
221 if (type->type == RPC_FC_ENCAPSULATED_UNION)
223 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
224 fields = uv->type->fields;
226 else
227 fields = type->fields;
228 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
230 if (field->type && type_has_full_pointer(field->type))
231 return TRUE;
235 return FALSE;
238 static unsigned short user_type_offset(const char *name)
240 user_type_t *ut;
241 unsigned short off = 0;
242 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
244 if (strcmp(name, ut->name) == 0)
245 return off;
246 ++off;
248 error("user_type_offset: couldn't find type (%s)\n", name);
249 return 0;
252 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
254 type->typestring_offset = offset;
255 if (file) type->tfswrite = FALSE;
258 static void guard_rec(type_t *type)
260 /* types that contain references to themselves (like a linked list),
261 need to be shielded from infinite recursion when writing embedded
262 types */
263 if (type->typestring_offset)
264 type->tfswrite = FALSE;
265 else
266 type->typestring_offset = 1;
269 static type_t *get_user_type(const type_t *t, const char **pname)
271 for (;;)
273 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
274 if (ut)
276 if (pname)
277 *pname = t->name;
278 return ut;
281 if (t->kind == TKIND_ALIAS)
282 t = t->orig;
283 else
284 return 0;
288 int is_user_type(const type_t *t)
290 return get_user_type(t, NULL) != NULL;
293 static int is_embedded_complex(const type_t *type)
295 unsigned char tc = type->type;
296 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
297 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
300 static const char *get_context_handle_type_name(const type_t *type)
302 const type_t *t;
303 for (t = type; is_ptr(t); t = t->ref)
304 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
305 return t->name;
306 assert(0);
307 return NULL;
310 /* This is actually fairly involved to implement precisely, due to the
311 effects attributes may have and things like that. Right now this is
312 only used for optimization, so just check for a very small set of
313 criteria that guarantee the types are equivalent; assume every thing
314 else is different. */
315 static int compare_type(const type_t *a, const type_t *b)
317 if (a == b
318 || (a->name
319 && b->name
320 && strcmp(a->name, b->name) == 0))
321 return 0;
322 /* Ordering doesn't need to be implemented yet. */
323 return 1;
326 static int compare_expr(const expr_t *a, const expr_t *b)
328 int ret;
330 if (a->type != b->type)
331 return a->type - b->type;
333 switch (a->type)
335 case EXPR_NUM:
336 case EXPR_HEXNUM:
337 case EXPR_TRUEFALSE:
338 return a->u.lval - b->u.lval;
339 case EXPR_DOUBLE:
340 return a->u.dval - b->u.dval;
341 case EXPR_IDENTIFIER:
342 return strcmp(a->u.sval, b->u.sval);
343 case EXPR_COND:
344 ret = compare_expr(a->ref, b->ref);
345 if (ret != 0)
346 return ret;
347 ret = compare_expr(a->u.ext, b->u.ext);
348 if (ret != 0)
349 return ret;
350 return compare_expr(a->ext2, b->ext2);
351 case EXPR_OR:
352 case EXPR_AND:
353 case EXPR_ADD:
354 case EXPR_SUB:
355 case EXPR_MUL:
356 case EXPR_DIV:
357 case EXPR_SHL:
358 case EXPR_SHR:
359 ret = compare_expr(a->ref, b->ref);
360 if (ret != 0)
361 return ret;
362 return compare_expr(a->u.ext, b->u.ext);
363 case EXPR_CAST:
364 ret = compare_type(a->u.tref, b->u.tref);
365 if (ret != 0)
366 return ret;
367 /* Fall through. */
368 case EXPR_NOT:
369 case EXPR_NEG:
370 case EXPR_PPTR:
371 case EXPR_ADDRESSOF:
372 return compare_expr(a->ref, b->ref);
373 case EXPR_SIZEOF:
374 return compare_type(a->u.tref, b->u.tref);
375 case EXPR_VOID:
376 return 0;
378 return -1;
381 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
382 do { \
383 if (file) \
384 fprintf(file, "/* %2u */\n", typestring_offset); \
385 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
387 while (0)
389 static void print_file(FILE *file, int indent, const char *format, ...)
391 va_list va;
392 va_start(va, format);
393 print(file, indent, format, va);
394 va_end(va);
397 void print(FILE *file, int indent, const char *format, va_list va)
399 if (file)
401 if (format[0] != '\n')
402 while (0 < indent--)
403 fprintf(file, " ");
404 vfprintf(file, format, va);
409 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n)
411 if (decl_indirect(t))
412 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof(%s));\n", n, n);
413 else if (is_ptr(t) || is_array(t))
414 print_file(file, indent, "%s = 0;\n", n);
417 void write_parameters_init(FILE *file, int indent, const func_t *func)
419 const var_t *var;
421 if (!is_void(func->def->type))
422 write_var_init(file, indent, func->def->type, "_RetVal");
424 if (!func->args)
425 return;
427 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
428 write_var_init(file, indent, var->type, var->name);
430 fprintf(file, "\n");
433 static void write_formatdesc(FILE *f, int indent, const char *str)
435 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
436 print_file(f, indent, "{\n");
437 print_file(f, indent + 1, "short Pad;\n");
438 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
439 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
440 print_file(f, indent, "\n");
443 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
445 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
446 get_size_typeformatstring(ifaces, pred));
448 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
449 get_size_procformatstring(ifaces, pred));
451 fprintf(f, "\n");
452 write_formatdesc(f, indent, "TYPE");
453 write_formatdesc(f, indent, "PROC");
454 fprintf(f, "\n");
455 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
456 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
457 print_file(f, indent, "\n");
460 static inline int is_base_type(unsigned char type)
462 switch (type)
464 case RPC_FC_BYTE:
465 case RPC_FC_CHAR:
466 case RPC_FC_USMALL:
467 case RPC_FC_SMALL:
468 case RPC_FC_WCHAR:
469 case RPC_FC_USHORT:
470 case RPC_FC_SHORT:
471 case RPC_FC_ULONG:
472 case RPC_FC_LONG:
473 case RPC_FC_HYPER:
474 case RPC_FC_IGNORE:
475 case RPC_FC_FLOAT:
476 case RPC_FC_DOUBLE:
477 case RPC_FC_ENUM16:
478 case RPC_FC_ENUM32:
479 case RPC_FC_ERROR_STATUS_T:
480 case RPC_FC_BIND_PRIMITIVE:
481 return TRUE;
483 default:
484 return FALSE;
488 int decl_indirect(const type_t *t)
490 return is_user_type(t)
491 || (!is_base_type(t->type)
492 && !is_ptr(t)
493 && !is_array(t));
496 static size_t write_procformatstring_var(FILE *file, int indent,
497 const var_t *var, int is_return)
499 size_t size;
500 const type_t *type = var->type;
502 int is_in = is_attr(var->attrs, ATTR_IN);
503 int is_out = is_attr(var->attrs, ATTR_OUT);
505 if (!is_in && !is_out) is_in = TRUE;
507 if (!type->declarray && is_base_type(type->type))
509 if (is_return)
510 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
511 else
512 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
514 if (type->type == RPC_FC_BIND_PRIMITIVE)
516 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
517 size = 2; /* includes param type prefix */
519 else if (is_base_type(type->type))
521 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
522 size = 2; /* includes param type prefix */
524 else
526 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
527 size = 0;
530 else
532 if (is_return)
533 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
534 else if (is_in && is_out)
535 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
536 else if (is_out)
537 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
538 else
539 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
541 print_file(file, indent, "0x01,\n");
542 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
543 size = 4; /* includes param type prefix */
545 return size;
548 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
550 const ifref_t *iface;
551 int indent = 0;
552 const var_t *var;
554 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
555 print_file(file, indent, "{\n");
556 indent++;
557 print_file(file, indent, "0,\n");
558 print_file(file, indent, "{\n");
559 indent++;
561 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
563 if (!pred(iface->iface))
564 continue;
566 if (iface->iface->funcs)
568 const func_t *func;
569 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
571 if (is_local(func->def->attrs)) continue;
572 /* emit argument data */
573 if (func->args)
575 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
576 write_procformatstring_var(file, indent, var, FALSE);
579 /* emit return value data */
580 var = func->def;
581 if (is_void(var->type))
583 print_file(file, indent, "0x5b, /* FC_END */\n");
584 print_file(file, indent, "0x5c, /* FC_PAD */\n");
586 else
587 write_procformatstring_var(file, indent, var, TRUE);
592 print_file(file, indent, "0x0\n");
593 indent--;
594 print_file(file, indent, "}\n");
595 indent--;
596 print_file(file, indent, "};\n");
597 print_file(file, indent, "\n");
600 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
602 if (is_base_type(type->type))
604 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
605 *typestring_offset += 1;
606 return 1;
609 return 0;
612 /* write conformance / variance descriptor */
613 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
614 unsigned int baseoff, const type_t *type,
615 const expr_t *expr)
617 unsigned char operator_type = 0;
618 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
619 const char *conftype_string = "";
620 const char *operator_string = "no operators";
621 const expr_t *subexpr;
623 if (!expr)
625 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
626 return 4;
629 if (!structure)
631 /* Top-level conformance calculations are done inline. */
632 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
633 RPC_FC_TOP_LEVEL_CONFORMANCE);
634 print_file (file, 2, "0x0,\n");
635 print_file (file, 2, "NdrFcShort(0x0),\n");
636 return 4;
639 if (expr->is_const)
641 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
642 error("write_conf_or_var_desc: constant value %ld is greater than "
643 "the maximum constant size of %d\n", expr->cval,
644 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
646 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
647 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
648 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
649 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
651 return 4;
654 if (is_ptr(type) || (is_array(type) && !type->declarray))
656 conftype = RPC_FC_POINTER_CONFORMANCE;
657 conftype_string = "field pointer, ";
660 subexpr = expr;
661 switch (subexpr->type)
663 case EXPR_PPTR:
664 subexpr = subexpr->ref;
665 operator_type = RPC_FC_DEREFERENCE;
666 operator_string = "FC_DEREFERENCE";
667 break;
668 case EXPR_DIV:
669 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
671 subexpr = subexpr->ref;
672 operator_type = RPC_FC_DIV_2;
673 operator_string = "FC_DIV_2";
675 break;
676 case EXPR_MUL:
677 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
679 subexpr = subexpr->ref;
680 operator_type = RPC_FC_MULT_2;
681 operator_string = "FC_MULT_2";
683 break;
684 case EXPR_SUB:
685 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
687 subexpr = subexpr->ref;
688 operator_type = RPC_FC_SUB_1;
689 operator_string = "FC_SUB_1";
691 break;
692 case EXPR_ADD:
693 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
695 subexpr = subexpr->ref;
696 operator_type = RPC_FC_ADD_1;
697 operator_string = "FC_ADD_1";
699 break;
700 default:
701 break;
704 if (subexpr->type == EXPR_IDENTIFIER)
706 const type_t *correlation_variable = NULL;
707 unsigned char correlation_variable_type;
708 unsigned char param_type = 0;
709 size_t offset = 0;
710 const var_t *var;
712 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
714 unsigned int align = 0;
715 /* FIXME: take alignment into account */
716 if (var->name && !strcmp(var->name, subexpr->u.sval))
718 correlation_variable = var->type;
719 break;
721 offset += type_memsize(var->type, &align);
723 if (!correlation_variable)
724 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
725 subexpr->u.sval);
727 offset -= baseoff;
728 correlation_variable_type = correlation_variable->type;
730 switch (correlation_variable_type)
732 case RPC_FC_CHAR:
733 case RPC_FC_SMALL:
734 param_type = RPC_FC_SMALL;
735 break;
736 case RPC_FC_BYTE:
737 case RPC_FC_USMALL:
738 param_type = RPC_FC_USMALL;
739 break;
740 case RPC_FC_WCHAR:
741 case RPC_FC_SHORT:
742 case RPC_FC_ENUM16:
743 param_type = RPC_FC_SHORT;
744 break;
745 case RPC_FC_USHORT:
746 param_type = RPC_FC_USHORT;
747 break;
748 case RPC_FC_LONG:
749 case RPC_FC_ENUM32:
750 param_type = RPC_FC_LONG;
751 break;
752 case RPC_FC_ULONG:
753 param_type = RPC_FC_ULONG;
754 break;
755 case RPC_FC_RP:
756 case RPC_FC_UP:
757 case RPC_FC_OP:
758 case RPC_FC_FP:
759 if (sizeof(void *) == 4) /* FIXME */
760 param_type = RPC_FC_LONG;
761 else
762 param_type = RPC_FC_HYPER;
763 break;
764 default:
765 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
766 correlation_variable_type);
769 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
770 conftype | param_type, conftype_string, string_of_type(param_type));
771 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
772 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
773 offset, offset);
775 else
777 unsigned int callback_offset = 0;
778 struct expr_eval_routine *eval;
779 int found = 0;
781 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
783 if (!strcmp (eval->structure->name, structure->name)
784 && !compare_expr (eval->expr, expr))
786 found = 1;
787 break;
789 callback_offset++;
792 if (!found)
794 eval = xmalloc (sizeof(*eval));
795 eval->structure = structure;
796 eval->baseoff = baseoff;
797 eval->expr = expr;
798 list_add_tail (&expr_eval_routines, &eval->entry);
801 if (callback_offset > USHRT_MAX)
802 error("Maximum number of callback routines reached\n");
804 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
805 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
806 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
808 return 4;
811 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
813 int have_align = FALSE;
814 size_t size = 0;
815 const var_t *v;
817 if (!fields) return 0;
818 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
820 unsigned int falign = 0;
821 size_t fsize = type_memsize(v->type, &falign);
822 if (!have_align)
824 *align = falign;
825 have_align = TRUE;
827 size = (size + (falign - 1)) & ~(falign - 1);
828 size += fsize;
831 size = (size + (*align - 1)) & ~(*align - 1);
832 return size;
835 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
837 size_t size, maxs = 0;
838 unsigned int align = *pmaxa;
839 const var_t *v;
841 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
843 /* we could have an empty default field with NULL type */
844 if (v->type)
846 size = type_memsize(v->type, &align);
847 if (maxs < size) maxs = size;
848 if (*pmaxa < align) *pmaxa = align;
852 return maxs;
855 int get_padding(const var_list_t *fields)
857 unsigned short offset = 0;
858 int salign = -1;
859 const var_t *f;
861 if (!fields)
862 return 0;
864 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
866 type_t *ft = f->type;
867 unsigned int align = 0;
868 size_t size = type_memsize(ft, &align);
869 if (salign == -1)
870 salign = align;
871 offset = (offset + (align - 1)) & ~(align - 1);
872 offset += size;
875 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
878 size_t type_memsize(const type_t *t, unsigned int *align)
880 size_t size = 0;
882 if (t->declarray && is_conformant_array(t))
884 type_memsize(t->ref, align);
885 size = 0;
887 else if (is_ptr(t) || is_conformant_array(t))
889 size = sizeof(void *);
890 if (size > *align) *align = size;
892 else switch (t->type)
894 case RPC_FC_BYTE:
895 case RPC_FC_CHAR:
896 case RPC_FC_USMALL:
897 case RPC_FC_SMALL:
898 size = 1;
899 if (size > *align) *align = size;
900 break;
901 case RPC_FC_WCHAR:
902 case RPC_FC_USHORT:
903 case RPC_FC_SHORT:
904 case RPC_FC_ENUM16:
905 size = 2;
906 if (size > *align) *align = size;
907 break;
908 case RPC_FC_ULONG:
909 case RPC_FC_LONG:
910 case RPC_FC_ERROR_STATUS_T:
911 case RPC_FC_ENUM32:
912 case RPC_FC_FLOAT:
913 size = 4;
914 if (size > *align) *align = size;
915 break;
916 case RPC_FC_HYPER:
917 case RPC_FC_DOUBLE:
918 size = 8;
919 if (size > *align) *align = size;
920 break;
921 case RPC_FC_STRUCT:
922 case RPC_FC_CVSTRUCT:
923 case RPC_FC_CPSTRUCT:
924 case RPC_FC_CSTRUCT:
925 case RPC_FC_PSTRUCT:
926 case RPC_FC_BOGUS_STRUCT:
927 size = fields_memsize(t->fields, align);
928 break;
929 case RPC_FC_ENCAPSULATED_UNION:
930 case RPC_FC_NON_ENCAPSULATED_UNION:
931 size = union_memsize(t->fields, align);
932 break;
933 case RPC_FC_SMFARRAY:
934 case RPC_FC_LGFARRAY:
935 case RPC_FC_SMVARRAY:
936 case RPC_FC_LGVARRAY:
937 case RPC_FC_BOGUS_ARRAY:
938 size = t->dim * type_memsize(t->ref, align);
939 break;
940 default:
941 error("type_memsize: Unknown type %d\n", t->type);
942 size = 0;
945 return size;
948 int is_full_pointer_function(const func_t *func)
950 const var_t *var;
951 if (type_has_full_pointer(func->def->type))
952 return TRUE;
953 if (!func->args)
954 return FALSE;
955 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
956 if (type_has_full_pointer( var->type ))
957 return TRUE;
958 return FALSE;
961 void write_full_pointer_init(FILE *file, int indent, const func_t *func, int is_server)
963 print_file(file, indent, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
964 is_server ? "XLAT_SERVER" : "XLAT_CLIENT");
965 fprintf(file, "\n");
968 void write_full_pointer_free(FILE *file, int indent, const func_t *func)
970 print_file(file, indent, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
971 fprintf(file, "\n");
974 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
976 short absoff = type->ref->typestring_offset;
977 short reloff = absoff - (offset + 2);
978 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
980 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
981 type->type, ptr_attr, string_of_type(type->type));
982 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
983 reloff, reloff, absoff);
984 return 4;
987 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
989 unsigned char fc = type->ref->type;
990 /* for historical reasons, write_simple_pointer also handled string types,
991 * but no longer does. catch bad uses of the function with this check */
992 if (is_string_type(type->attrs, type))
993 error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
994 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
995 type->type, string_of_type(type->type));
996 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
997 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
998 return 4;
1001 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
1003 print_file(file, 0, "/* %u (", tfsoff);
1004 write_type_decl(file, t, NULL);
1005 print_file(file, 0, ") */\n");
1008 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
1010 unsigned int offset = *typestring_offset;
1012 print_start_tfs_comment(file, type, offset);
1013 update_tfsoff(type, offset, file);
1015 if (type->ref->typestring_offset)
1016 *typestring_offset += write_nonsimple_pointer(file, type, offset);
1017 else if (is_base_type(type->ref->type))
1018 *typestring_offset += write_simple_pointer(file, type);
1020 return offset;
1023 static int processed(const type_t *type)
1025 return type->typestring_offset && !type->tfswrite;
1028 static int user_type_has_variable_size(const type_t *t)
1030 if (is_ptr(t))
1031 return TRUE;
1032 else
1033 switch (t->type)
1035 case RPC_FC_PSTRUCT:
1036 case RPC_FC_CSTRUCT:
1037 case RPC_FC_CPSTRUCT:
1038 case RPC_FC_CVSTRUCT:
1039 return TRUE;
1041 /* Note: Since this only applies to user types, we can't have a conformant
1042 array here, and strings should get filed under pointer in this case. */
1043 return FALSE;
1046 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1048 unsigned int start, absoff, flags;
1049 unsigned int align = 0, ualign = 0;
1050 const char *name;
1051 type_t *utype = get_user_type(type, &name);
1052 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
1053 size_t size = type_memsize(type, &align);
1054 unsigned short funoff = user_type_offset(name);
1055 short reloff;
1057 guard_rec(type);
1059 if (is_base_type(utype->type))
1061 absoff = *tfsoff;
1062 print_start_tfs_comment(file, utype, absoff);
1063 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
1064 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1065 *tfsoff += 2;
1067 else
1069 if (!processed(utype))
1070 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
1071 absoff = utype->typestring_offset;
1074 if (utype->type == RPC_FC_RP)
1075 flags = 0x40;
1076 else if (utype->type == RPC_FC_UP)
1077 flags = 0x80;
1078 else
1079 flags = 0;
1081 start = *tfsoff;
1082 update_tfsoff(type, start, file);
1083 print_start_tfs_comment(file, type, start);
1084 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
1085 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1086 flags | (align - 1), align - 1, flags);
1087 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
1088 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
1089 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
1090 *tfsoff += 8;
1091 reloff = absoff - *tfsoff;
1092 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
1093 *tfsoff += 2;
1096 static void write_member_type(FILE *file, const type_t *cont,
1097 const attr_list_t *attrs, const type_t *type,
1098 unsigned int *corroff, unsigned int *tfsoff)
1100 if (is_embedded_complex(type) && !is_conformant_array(type))
1102 size_t absoff;
1103 short reloff;
1105 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1107 absoff = *corroff;
1108 *corroff += 8;
1110 else
1112 absoff = type->typestring_offset;
1114 reloff = absoff - (*tfsoff + 2);
1116 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1117 /* FIXME: actually compute necessary padding */
1118 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1119 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1120 reloff, reloff, absoff);
1121 *tfsoff += 4;
1123 else if (is_ptr(type) || is_conformant_array(type))
1125 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1126 ? RPC_FC_POINTER
1127 : RPC_FC_LONG);
1128 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1129 *tfsoff += 1;
1131 else if (!write_base_type(file, type, tfsoff))
1132 error("Unsupported member type 0x%x\n", type->type);
1135 static void write_end(FILE *file, unsigned int *tfsoff)
1137 if (*tfsoff % 2 == 0)
1139 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1140 *tfsoff += 1;
1142 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1143 *tfsoff += 1;
1146 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1148 unsigned int offset = 0;
1149 var_list_t *fs = type->fields;
1150 var_t *f;
1152 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1154 unsigned int align = 0;
1155 type_t *ft = f->type;
1156 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1158 unsigned int absoff = ft->typestring_offset;
1159 short reloff = absoff - (*tfsoff + 6);
1160 print_file(file, 0, "/* %d */\n", *tfsoff);
1161 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1162 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1163 write_conf_or_var_desc(file, current_structure, offset, ft,
1164 get_attrp(f->attrs, ATTR_SWITCHIS));
1165 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1166 reloff, reloff, absoff);
1167 *tfsoff += 8;
1170 /* FIXME: take alignment into account */
1171 offset += type_memsize(ft, &align);
1175 static int write_no_repeat_pointer_descriptions(
1176 FILE *file, type_t *type,
1177 size_t *offset_in_memory, size_t *offset_in_buffer,
1178 unsigned int *typestring_offset)
1180 int written = 0;
1181 unsigned int align;
1183 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1185 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1186 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1188 /* pointer instance */
1189 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1190 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1191 *typestring_offset += 6;
1193 if (is_ptr(type))
1195 if (is_string_type(type->attrs, type))
1196 write_string_tfs(file, NULL, type, NULL, typestring_offset);
1197 else
1198 write_pointer_tfs(file, type, typestring_offset);
1200 else
1202 unsigned absoff = type->typestring_offset;
1203 short reloff = absoff - (*typestring_offset + 2);
1204 /* FIXME: get pointer attributes from field */
1205 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1206 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1207 reloff, reloff, absoff);
1208 *typestring_offset += 4;
1211 align = 0;
1212 *offset_in_memory += type_memsize(type, &align);
1213 /* FIXME: is there a case where these two are different? */
1214 align = 0;
1215 *offset_in_buffer += type_memsize(type, &align);
1217 return 1;
1220 if (is_non_complex_struct(type))
1222 const var_t *v;
1223 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1224 written += write_no_repeat_pointer_descriptions(
1225 file, v->type,
1226 offset_in_memory, offset_in_buffer, typestring_offset);
1228 else
1230 align = 0;
1231 *offset_in_memory += type_memsize(type, &align);
1232 /* FIXME: is there a case where these two are different? */
1233 align = 0;
1234 *offset_in_buffer += type_memsize(type, &align);
1237 return written;
1240 static int write_pointer_description_offsets(
1241 FILE *file, const attr_list_t *attrs, type_t *type,
1242 size_t *offset_in_memory, size_t *offset_in_buffer,
1243 unsigned int *typestring_offset)
1245 int written = 0;
1246 unsigned int align;
1248 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1250 if (offset_in_memory && offset_in_buffer)
1252 /* pointer instance */
1253 /* FIXME: sometimes from end of structure, sometimes from beginning */
1254 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1255 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1257 align = 0;
1258 *offset_in_memory += type_memsize(type, &align);
1259 /* FIXME: is there a case where these two are different? */
1260 align = 0;
1261 *offset_in_buffer += type_memsize(type, &align);
1263 *typestring_offset += 4;
1265 if (is_string_type(attrs, type))
1266 write_string_tfs(file, NULL, type, NULL, typestring_offset);
1267 else if (processed(type->ref) || is_base_type(type->ref->type))
1268 write_pointer_tfs(file, type, typestring_offset);
1269 else
1270 error("write_pointer_description_offsets: type format string unknown\n");
1272 return 1;
1275 if (is_array(type))
1277 return write_pointer_description_offsets(
1278 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1279 typestring_offset);
1281 else if (is_non_complex_struct(type))
1283 /* otherwise search for interesting fields to parse */
1284 const var_t *v;
1285 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1287 written += write_pointer_description_offsets(
1288 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1289 typestring_offset);
1292 else
1294 align = 0;
1295 if (offset_in_memory)
1296 *offset_in_memory += type_memsize(type, &align);
1297 /* FIXME: is there a case where these two are different? */
1298 align = 0;
1299 if (offset_in_buffer)
1300 *offset_in_buffer += type_memsize(type, &align);
1303 return written;
1306 /* Note: if file is NULL return value is number of pointers to write, else
1307 * it is the number of type format characters written */
1308 static int write_fixed_array_pointer_descriptions(
1309 FILE *file, const attr_list_t *attrs, type_t *type,
1310 size_t *offset_in_memory, size_t *offset_in_buffer,
1311 unsigned int *typestring_offset)
1313 unsigned int align;
1314 int pointer_count = 0;
1316 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1318 unsigned int temp = 0;
1319 /* unfortunately, this needs to be done in two passes to avoid
1320 * writing out redundant FC_FIXED_REPEAT descriptions */
1321 pointer_count = write_pointer_description_offsets(
1322 NULL, attrs, type->ref, NULL, NULL, &temp);
1323 if (pointer_count > 0)
1325 unsigned int increment_size;
1326 size_t offset_of_array_pointer_mem = 0;
1327 size_t offset_of_array_pointer_buf = 0;
1329 align = 0;
1330 increment_size = type_memsize(type->ref, &align);
1332 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1333 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1334 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1335 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1336 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1337 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1338 *typestring_offset += 10;
1340 pointer_count = write_pointer_description_offsets(
1341 file, attrs, type, &offset_of_array_pointer_mem,
1342 &offset_of_array_pointer_buf, typestring_offset);
1345 else if (is_struct(type->type))
1347 const var_t *v;
1348 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1350 pointer_count += write_fixed_array_pointer_descriptions(
1351 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1352 typestring_offset);
1355 else
1357 align = 0;
1358 if (offset_in_memory)
1359 *offset_in_memory += type_memsize(type, &align);
1360 /* FIXME: is there a case where these two are different? */
1361 align = 0;
1362 if (offset_in_buffer)
1363 *offset_in_buffer += type_memsize(type, &align);
1366 return pointer_count;
1369 /* Note: if file is NULL return value is number of pointers to write, else
1370 * it is the number of type format characters written */
1371 static int write_conformant_array_pointer_descriptions(
1372 FILE *file, const attr_list_t *attrs, type_t *type,
1373 size_t offset_in_memory, unsigned int *typestring_offset)
1375 unsigned int align;
1376 int pointer_count = 0;
1378 if (is_conformant_array(type) && !type->length_is)
1380 unsigned int temp = 0;
1381 /* unfortunately, this needs to be done in two passes to avoid
1382 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1383 pointer_count = write_pointer_description_offsets(
1384 NULL, attrs, type->ref, NULL, NULL, &temp);
1385 if (pointer_count > 0)
1387 unsigned int increment_size;
1388 size_t offset_of_array_pointer_mem = offset_in_memory;
1389 size_t offset_of_array_pointer_buf = offset_in_memory;
1391 align = 0;
1392 increment_size = type_memsize(type->ref, &align);
1394 if (increment_size > USHRT_MAX)
1395 error("array size of %u bytes is too large\n", increment_size);
1397 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1398 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1399 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1400 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1401 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1402 *typestring_offset += 8;
1404 pointer_count = write_pointer_description_offsets(
1405 file, attrs, type->ref, &offset_of_array_pointer_mem,
1406 &offset_of_array_pointer_buf, typestring_offset);
1410 return pointer_count;
1413 /* Note: if file is NULL return value is number of pointers to write, else
1414 * it is the number of type format characters written */
1415 static int write_varying_array_pointer_descriptions(
1416 FILE *file, const attr_list_t *attrs, type_t *type,
1417 size_t *offset_in_memory, size_t *offset_in_buffer,
1418 unsigned int *typestring_offset)
1420 unsigned int align;
1421 int pointer_count = 0;
1423 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1425 if (is_array(type) && type->length_is)
1427 unsigned int temp = 0;
1428 /* unfortunately, this needs to be done in two passes to avoid
1429 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1430 pointer_count = write_pointer_description_offsets(
1431 NULL, attrs, type->ref, NULL, NULL, &temp);
1432 if (pointer_count > 0)
1434 unsigned int increment_size;
1435 size_t offset_of_array_pointer_mem = 0;
1436 size_t offset_of_array_pointer_buf = 0;
1438 align = 0;
1439 increment_size = type_memsize(type->ref, &align);
1441 if (increment_size > USHRT_MAX)
1442 error("array size of %u bytes is too large\n", increment_size);
1444 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1445 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1446 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1447 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1448 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1449 *typestring_offset += 8;
1451 pointer_count = write_pointer_description_offsets(
1452 file, attrs, type, &offset_of_array_pointer_mem,
1453 &offset_of_array_pointer_buf, typestring_offset);
1456 else if (is_struct(type->type))
1458 const var_t *v;
1459 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1461 pointer_count += write_varying_array_pointer_descriptions(
1462 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1463 typestring_offset);
1466 else
1468 align = 0;
1469 if (offset_in_memory)
1470 *offset_in_memory += type_memsize(type, &align);
1471 /* FIXME: is there a case where these two are different? */
1472 align = 0;
1473 if (offset_in_buffer)
1474 *offset_in_buffer += type_memsize(type, &align);
1477 return pointer_count;
1480 static void write_pointer_description(FILE *file, type_t *type,
1481 unsigned int *typestring_offset)
1483 size_t offset_in_buffer;
1484 size_t offset_in_memory;
1486 /* pass 1: search for single instance of a pointer (i.e. don't descend
1487 * into arrays) */
1488 if (!is_array(type))
1490 offset_in_memory = 0;
1491 offset_in_buffer = 0;
1492 write_no_repeat_pointer_descriptions(
1493 file, type,
1494 &offset_in_memory, &offset_in_buffer, typestring_offset);
1497 /* pass 2: search for pointers in fixed arrays */
1498 offset_in_memory = 0;
1499 offset_in_buffer = 0;
1500 write_fixed_array_pointer_descriptions(
1501 file, NULL, type,
1502 &offset_in_memory, &offset_in_buffer, typestring_offset);
1504 /* pass 3: search for pointers in conformant only arrays (but don't descend
1505 * into conformant varying or varying arrays) */
1506 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1507 write_conformant_array_pointer_descriptions(
1508 file, NULL, type, 0, typestring_offset);
1509 else if (type->type == RPC_FC_CPSTRUCT)
1511 unsigned int align = 0;
1512 type_t *carray = find_array_or_string_in_struct(type)->type;
1513 write_conformant_array_pointer_descriptions(
1514 file, NULL, carray,
1515 type_memsize(type, &align),
1516 typestring_offset);
1519 /* pass 4: search for pointers in varying arrays */
1520 offset_in_memory = 0;
1521 offset_in_buffer = 0;
1522 write_varying_array_pointer_descriptions(
1523 file, NULL, type,
1524 &offset_in_memory, &offset_in_buffer, typestring_offset);
1527 int is_declptr(const type_t *t)
1529 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1532 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1533 type_t *type,
1534 const char *name, unsigned int *typestring_offset)
1536 size_t start_offset;
1537 unsigned char rtype;
1539 if (is_declptr(type))
1541 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1542 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1543 if (!pointer_type)
1544 pointer_type = RPC_FC_RP;
1545 print_start_tfs_comment(file, type, *typestring_offset);
1546 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1547 pointer_type, flag, string_of_type(pointer_type),
1548 flag ? " [simple_pointer]" : "");
1549 *typestring_offset += 2;
1550 if (!flag)
1552 print_file(file, 2, "NdrFcShort(0x2),\n");
1553 *typestring_offset += 2;
1557 start_offset = *typestring_offset;
1558 update_tfsoff(type, start_offset, file);
1560 rtype = type->ref->type;
1562 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1564 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1565 return start_offset;
1568 if (type->declarray && !is_conformant_array(type))
1570 /* FIXME: multi-dimensional array */
1571 if (0xffffuL < type->dim)
1572 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1573 name, 0xffffu, type->dim - 0xffffu);
1575 if (rtype == RPC_FC_CHAR)
1576 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1577 else
1578 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1579 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1580 *typestring_offset += 2;
1582 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1583 *typestring_offset += 2;
1585 return start_offset;
1587 else if (type->size_is)
1589 unsigned int align = 0;
1591 if (rtype == RPC_FC_CHAR)
1592 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1593 else
1594 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1595 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1596 *typestring_offset += 2;
1598 *typestring_offset += write_conf_or_var_desc(
1599 file, current_structure,
1600 (type->declarray && current_structure
1601 ? type_memsize(current_structure, &align)
1602 : 0),
1603 type, type->size_is);
1605 return start_offset;
1607 else
1609 if (rtype == RPC_FC_WCHAR)
1610 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1611 else
1612 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1613 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1614 *typestring_offset += 2;
1616 return start_offset;
1620 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1621 const char *name, unsigned int *typestring_offset)
1623 const expr_t *length_is = type->length_is;
1624 const expr_t *size_is = type->size_is;
1625 unsigned int align = 0;
1626 size_t size;
1627 size_t start_offset;
1628 int has_pointer;
1629 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1630 unsigned int baseoff
1631 = type->declarray && current_structure
1632 ? type_memsize(current_structure, &align)
1633 : 0;
1635 if (!pointer_type)
1636 pointer_type = RPC_FC_RP;
1638 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1639 has_pointer = TRUE;
1640 else
1641 has_pointer = type_has_pointers(type->ref);
1643 align = 0;
1644 size = type_memsize((is_conformant_array(type) ? type->ref : type), &align);
1646 start_offset = *typestring_offset;
1647 update_tfsoff(type, start_offset, file);
1648 print_start_tfs_comment(file, type, start_offset);
1649 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1650 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1651 *typestring_offset += 2;
1653 align = 0;
1654 if (type->type != RPC_FC_BOGUS_ARRAY)
1656 unsigned char tc = type->type;
1658 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1660 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1661 *typestring_offset += 4;
1663 else
1665 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1666 *typestring_offset += 2;
1669 if (is_conformant_array(type))
1670 *typestring_offset
1671 += write_conf_or_var_desc(file, current_structure, baseoff,
1672 type, size_is);
1674 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1676 unsigned int elalign = 0;
1677 size_t elsize = type_memsize(type->ref, &elalign);
1679 if (type->type == RPC_FC_LGVARRAY)
1681 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1682 *typestring_offset += 4;
1684 else
1686 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1687 *typestring_offset += 2;
1690 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1691 *typestring_offset += 2;
1694 if (length_is)
1695 *typestring_offset
1696 += write_conf_or_var_desc(file, current_structure, baseoff,
1697 type, length_is);
1699 if (has_pointer && (!type->declarray || !current_structure))
1701 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1702 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1703 *typestring_offset += 2;
1704 write_pointer_description(file, type, typestring_offset);
1705 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1706 *typestring_offset += 1;
1709 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1710 write_end(file, typestring_offset);
1712 else
1714 unsigned int dim = size_is ? 0 : type->dim;
1715 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1716 *typestring_offset += 2;
1717 *typestring_offset
1718 += write_conf_or_var_desc(file, current_structure, baseoff,
1719 type, size_is);
1720 *typestring_offset
1721 += write_conf_or_var_desc(file, current_structure, baseoff,
1722 type, length_is);
1723 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1724 write_end(file, typestring_offset);
1727 return start_offset;
1730 static const var_t *find_array_or_string_in_struct(const type_t *type)
1732 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1733 const type_t *ft = last_field->type;
1735 if (ft->declarray && is_conformant_array(ft))
1736 return last_field;
1738 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1739 return find_array_or_string_in_struct(last_field->type);
1740 else
1741 return NULL;
1744 static void write_struct_members(FILE *file, const type_t *type,
1745 unsigned int *corroff, unsigned int *typestring_offset)
1747 const var_t *field;
1748 unsigned short offset = 0;
1749 int salign = -1;
1750 int padding;
1752 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1754 type_t *ft = field->type;
1755 if (!ft->declarray || !is_conformant_array(ft))
1757 unsigned int align = 0;
1758 size_t size = type_memsize(ft, &align);
1759 if (salign == -1)
1760 salign = align;
1761 if ((align - 1) & offset)
1763 unsigned char fc = 0;
1764 switch (align)
1766 case 4:
1767 fc = RPC_FC_ALIGNM4;
1768 break;
1769 case 8:
1770 fc = RPC_FC_ALIGNM8;
1771 break;
1772 default:
1773 error("write_struct_members: cannot align type %d\n", ft->type);
1775 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1776 offset = (offset + (align - 1)) & ~(align - 1);
1777 *typestring_offset += 1;
1779 write_member_type(file, type, field->attrs, field->type, corroff,
1780 typestring_offset);
1781 offset += size;
1785 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1786 if (padding)
1788 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1789 RPC_FC_STRUCTPAD1 + padding - 1,
1790 padding);
1791 *typestring_offset += 1;
1794 write_end(file, typestring_offset);
1797 static size_t write_struct_tfs(FILE *file, type_t *type,
1798 const char *name, unsigned int *tfsoff)
1800 const type_t *save_current_structure = current_structure;
1801 unsigned int total_size;
1802 const var_t *array;
1803 size_t start_offset;
1804 size_t array_offset;
1805 int has_pointers = 0;
1806 unsigned int align = 0;
1807 unsigned int corroff;
1808 var_t *f;
1810 guard_rec(type);
1811 current_structure = type;
1813 total_size = type_memsize(type, &align);
1814 if (total_size > USHRT_MAX)
1815 error("structure size for %s exceeds %d bytes by %d bytes\n",
1816 name, USHRT_MAX, total_size - USHRT_MAX);
1818 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1819 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1820 FALSE, tfsoff);
1821 if (!has_pointers) has_pointers = type_has_pointers(type);
1823 array = find_array_or_string_in_struct(type);
1824 if (array && !processed(array->type))
1825 array_offset
1826 = is_attr(array->attrs, ATTR_STRING)
1827 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1828 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1830 corroff = *tfsoff;
1831 write_descriptors(file, type, tfsoff);
1833 start_offset = *tfsoff;
1834 update_tfsoff(type, start_offset, file);
1835 print_start_tfs_comment(file, type, start_offset);
1836 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1837 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1838 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1839 *tfsoff += 4;
1841 if (array)
1843 unsigned int absoff = array->type->typestring_offset;
1844 short reloff = absoff - *tfsoff;
1845 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1846 reloff, reloff, absoff);
1847 *tfsoff += 2;
1849 else if (type->type == RPC_FC_BOGUS_STRUCT)
1851 print_file(file, 2, "NdrFcShort(0x0),\n");
1852 *tfsoff += 2;
1855 if (type->type == RPC_FC_BOGUS_STRUCT)
1857 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1858 nothing is written to file yet. On the actual writing pass,
1859 this will have been updated. */
1860 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1861 short reloff = absoff - *tfsoff;
1862 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1863 reloff, reloff, absoff);
1864 *tfsoff += 2;
1866 else if ((type->type == RPC_FC_PSTRUCT) ||
1867 (type->type == RPC_FC_CPSTRUCT) ||
1868 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1870 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1871 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1872 *tfsoff += 2;
1873 write_pointer_description(file, type, tfsoff);
1874 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1875 *tfsoff += 1;
1878 write_struct_members(file, type, &corroff, tfsoff);
1880 if (type->type == RPC_FC_BOGUS_STRUCT)
1882 const var_list_t *fs = type->fields;
1883 const var_t *f;
1885 type->ptrdesc = *tfsoff;
1886 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1888 type_t *ft = f->type;
1889 if (is_ptr(ft))
1891 if (is_string_type(f->attrs, ft))
1892 write_string_tfs(file, f->attrs, ft, f->name, tfsoff);
1893 else
1894 write_pointer_tfs(file, ft, tfsoff);
1896 else if (!ft->declarray && is_conformant_array(ft))
1898 unsigned int absoff = ft->typestring_offset;
1899 short reloff = absoff - (*tfsoff + 2);
1900 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1901 /* FIXME: We need to store pointer attributes for arrays
1902 so we don't lose pointer_default info. */
1903 if (ptr_type == 0)
1904 ptr_type = RPC_FC_UP;
1905 print_file(file, 0, "/* %d */\n", *tfsoff);
1906 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1907 string_of_type(ptr_type));
1908 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1909 reloff, reloff, absoff);
1910 *tfsoff += 4;
1913 if (type->ptrdesc == *tfsoff)
1914 type->ptrdesc = 0;
1917 current_structure = save_current_structure;
1918 return start_offset;
1921 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1922 unsigned char flags, size_t offset,
1923 unsigned int *typeformat_offset)
1925 size_t start_offset = *typeformat_offset;
1926 short reloff = offset - (*typeformat_offset + 2);
1927 int in_attr, out_attr;
1928 in_attr = is_attr(attrs, ATTR_IN);
1929 out_attr = is_attr(attrs, ATTR_OUT);
1930 if (!in_attr && !out_attr) in_attr = 1;
1932 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1933 flags |= 0x04;
1935 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1936 pointer_type,
1937 flags,
1938 string_of_type(pointer_type));
1939 if (file)
1941 if (flags & 0x04)
1942 fprintf(file, " [allocated_on_stack]");
1943 if (flags & 0x10)
1944 fprintf(file, " [pointer_deref]");
1945 fprintf(file, " */\n");
1948 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1949 *typeformat_offset += 4;
1951 return start_offset;
1954 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1956 if (t == NULL)
1958 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1960 else if (is_base_type(t->type))
1962 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1963 t->type, string_of_type(t->type));
1965 else if (t->typestring_offset)
1967 short reloff = t->typestring_offset - *tfsoff;
1968 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1969 reloff, reloff, t->typestring_offset);
1971 else
1972 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1974 *tfsoff += 2;
1977 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1979 unsigned int align = 0;
1980 unsigned int start_offset;
1981 size_t size = type_memsize(type, &align);
1982 var_list_t *fields;
1983 size_t nbranch = 0;
1984 type_t *deftype = NULL;
1985 short nodeftype = 0xffff;
1986 var_t *f;
1988 guard_rec(type);
1990 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1992 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1993 fields = uv->type->fields;
1995 else
1996 fields = type->fields;
1998 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
2000 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
2001 if (cases)
2002 nbranch += list_count(cases);
2003 if (f->type)
2004 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
2007 start_offset = *tfsoff;
2008 update_tfsoff(type, start_offset, file);
2009 print_start_tfs_comment(file, type, start_offset);
2010 if (type->type == RPC_FC_ENCAPSULATED_UNION)
2012 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
2013 const type_t *st = sv->type;
2015 switch (st->type)
2017 case RPC_FC_CHAR:
2018 case RPC_FC_SMALL:
2019 case RPC_FC_USMALL:
2020 case RPC_FC_SHORT:
2021 case RPC_FC_USHORT:
2022 case RPC_FC_LONG:
2023 case RPC_FC_ULONG:
2024 case RPC_FC_ENUM16:
2025 case RPC_FC_ENUM32:
2026 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
2027 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
2028 0x40 | st->type, string_of_type(st->type));
2029 *tfsoff += 2;
2030 break;
2031 default:
2032 error("union switch type must be an integer, char, or enum\n");
2035 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
2036 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
2037 *tfsoff += 4;
2039 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
2041 type_t *ft = f->type;
2042 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
2043 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
2044 expr_t *c;
2046 if (cases == NULL && !deflt)
2047 error("union field %s with neither case nor default attribute\n", f->name);
2049 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
2051 /* MIDL doesn't check for duplicate cases, even though that seems
2052 like a reasonable thing to do, it just dumps them to the TFS
2053 like we're going to do here. */
2054 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
2055 *tfsoff += 4;
2056 write_branch_type(file, ft, tfsoff);
2059 /* MIDL allows multiple default branches, even though that seems
2060 illogical, it just chooses the last one, which is what we will
2061 do. */
2062 if (deflt)
2064 deftype = ft;
2065 nodeftype = 0;
2069 if (deftype)
2071 write_branch_type(file, deftype, tfsoff);
2073 else
2075 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
2076 *tfsoff += 2;
2079 return start_offset;
2082 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2083 unsigned int *typeformat_offset)
2085 size_t i;
2086 size_t start_offset = *typeformat_offset;
2087 expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
2089 if (iid)
2091 print_file(file, 2, "0x2f, /* FC_IP */\n");
2092 print_file(file, 2, "0x5c, /* FC_PAD */\n");
2093 *typeformat_offset
2094 += write_conf_or_var_desc(file, NULL, 0, type, iid) + 2;
2096 else
2098 const type_t *base = is_ptr(type) ? type->ref : type;
2099 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
2101 if (! uuid)
2102 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
2104 update_tfsoff(type, start_offset, file);
2105 print_start_tfs_comment(file, type, start_offset);
2106 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2107 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2108 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2109 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2110 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2111 for (i = 0; i < 8; ++i)
2112 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2114 if (file)
2115 fprintf(file, "\n");
2117 *typeformat_offset += 18;
2119 return start_offset;
2122 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2123 const var_t *var,
2124 unsigned int *typeformat_offset)
2126 size_t start_offset = *typeformat_offset;
2127 unsigned char flags = 0;
2129 if (is_attr(current_iface->attrs, ATTR_STRICTCONTEXTHANDLE))
2130 flags |= NDR_STRICT_CONTEXT_HANDLE;
2132 if (is_ptr(type))
2133 flags |= 0x80;
2134 if (is_attr(var->attrs, ATTR_IN))
2136 flags |= 0x40;
2137 if (!is_attr(var->attrs, ATTR_OUT))
2138 flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
2140 if (is_attr(var->attrs, ATTR_OUT))
2141 flags |= 0x20;
2143 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2144 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2145 /* return and can't be null values overlap */
2146 if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
2147 print_file(file, 0, "can't be null, ");
2148 if (flags & NDR_CONTEXT_HANDLE_SERIALIZE)
2149 print_file(file, 0, "serialize, ");
2150 if (flags & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
2151 print_file(file, 0, "no serialize, ");
2152 if (flags & NDR_STRICT_CONTEXT_HANDLE)
2153 print_file(file, 0, "strict, ");
2154 if ((flags & 0x21) == 0x20)
2155 print_file(file, 0, "out, ");
2156 if ((flags & 0x21) == 0x21)
2157 print_file(file, 0, "return, ");
2158 if (flags & 0x40)
2159 print_file(file, 0, "in, ");
2160 if (flags & 0x80)
2161 print_file(file, 0, "via ptr, ");
2162 print_file(file, 0, "*/\n");
2163 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2164 print_file(file, 2, "0, /* FIXME: param num */\n");
2165 *typeformat_offset += 4;
2167 return start_offset;
2170 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2171 type_t *type, const var_t *var,
2172 unsigned int *typeformat_offset)
2174 size_t offset;
2176 if (is_context_handle(type))
2177 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2179 if (is_user_type(type))
2181 write_user_tfs(file, type, typeformat_offset);
2182 return type->typestring_offset;
2185 if (is_string_type(var->attrs, type))
2186 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
2188 if (is_array(type))
2190 int ptr_type;
2191 size_t off;
2192 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2193 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2194 /* Top level pointers to conformant arrays may be handled specially
2195 since we can bypass the pointer, but if the array is buried
2196 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2197 always need to write the pointer. */
2198 if (!ptr_type && var->type != type)
2199 /* FIXME: This should use pointer_default, but the information
2200 isn't kept around for arrays. */
2201 ptr_type = RPC_FC_UP;
2202 if (ptr_type && ptr_type != RPC_FC_RP)
2204 unsigned int absoff = type->typestring_offset;
2205 short reloff = absoff - (*typeformat_offset + 2);
2206 off = *typeformat_offset;
2207 print_file(file, 0, "/* %d */\n", off);
2208 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2209 string_of_type(ptr_type));
2210 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2211 reloff, reloff, absoff);
2212 *typeformat_offset += 4;
2214 return off;
2217 if (!is_ptr(type))
2219 /* basic types don't need a type format string */
2220 if (is_base_type(type->type))
2221 return 0;
2223 switch (type->type)
2225 case RPC_FC_STRUCT:
2226 case RPC_FC_PSTRUCT:
2227 case RPC_FC_CSTRUCT:
2228 case RPC_FC_CPSTRUCT:
2229 case RPC_FC_CVSTRUCT:
2230 case RPC_FC_BOGUS_STRUCT:
2231 return write_struct_tfs(file, type, var->name, typeformat_offset);
2232 case RPC_FC_ENCAPSULATED_UNION:
2233 case RPC_FC_NON_ENCAPSULATED_UNION:
2234 return write_union_tfs(file, type, typeformat_offset);
2235 case RPC_FC_IGNORE:
2236 case RPC_FC_BIND_PRIMITIVE:
2237 /* nothing to do */
2238 return 0;
2239 default:
2240 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2243 else if (last_ptr(type))
2245 size_t start_offset = *typeformat_offset;
2246 int in_attr = is_attr(var->attrs, ATTR_IN);
2247 int out_attr = is_attr(var->attrs, ATTR_OUT);
2248 const type_t *base = type->ref;
2250 if (base->type == RPC_FC_IP
2251 || (base->type == 0
2252 && is_attr(var->attrs, ATTR_IIDIS)))
2254 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2257 /* special case for pointers to base types */
2258 if (is_base_type(base->type))
2260 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2261 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2262 string_of_type(type->type),
2263 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2264 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2265 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2266 *typeformat_offset += 4;
2267 return start_offset;
2271 assert(is_ptr(type));
2273 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2274 if (file)
2275 fprintf(file, "/* %2u */\n", *typeformat_offset);
2276 return write_pointer_only_tfs(file, var->attrs, type->type,
2277 !last_ptr(type) ? 0x10 : 0,
2278 offset, typeformat_offset);
2281 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2282 const char *name, int write_ptr, unsigned int *tfsoff)
2284 int retmask = 0;
2286 if (is_user_type(type))
2288 write_user_tfs(file, type, tfsoff);
2290 else if (is_string_type(attrs, type))
2292 write_string_tfs(file, attrs, type, name, tfsoff);
2294 else if (is_ptr(type))
2296 type_t *ref = type->ref;
2298 if (ref->type == RPC_FC_IP
2299 || (ref->type == 0
2300 && is_attr(attrs, ATTR_IIDIS)))
2302 write_ip_tfs(file, attrs, type, tfsoff);
2304 else
2306 if (!processed(ref) && !is_base_type(ref->type))
2307 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2309 if (write_ptr)
2310 write_pointer_tfs(file, type, tfsoff);
2312 retmask |= 1;
2315 else if (type->declarray && is_conformant_array(type))
2316 ; /* conformant arrays and strings are handled specially */
2317 else if (is_array(type))
2319 write_array_tfs(file, attrs, type, name, tfsoff);
2320 if (is_conformant_array(type))
2321 retmask |= 1;
2323 else if (is_struct(type->type))
2325 if (!processed(type))
2326 write_struct_tfs(file, type, name, tfsoff);
2328 else if (is_union(type->type))
2330 if (!processed(type))
2331 write_union_tfs(file, type, tfsoff);
2333 else if (!is_base_type(type->type))
2334 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2335 name, type->type);
2337 return retmask;
2340 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2342 const var_t *var;
2343 const ifref_t *iface;
2344 unsigned int typeformat_offset = 2;
2346 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2348 if (!pred(iface->iface))
2349 continue;
2351 if (iface->iface->funcs)
2353 const func_t *func;
2354 current_iface = iface;
2355 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2357 if (is_local(func->def->attrs)) continue;
2359 if (!is_void(func->def->type))
2360 update_tfsoff(func->def->type,
2361 write_typeformatstring_var(
2362 file, 2, NULL, func->def->type,
2363 func->def, &typeformat_offset),
2364 file);
2366 current_func = func;
2367 if (func->args)
2368 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2369 update_tfsoff(
2370 var->type,
2371 write_typeformatstring_var(
2372 file, 2, func, var->type, var,
2373 &typeformat_offset),
2374 file);
2379 return typeformat_offset + 1;
2383 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2385 int indent = 0;
2387 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2388 print_file(file, indent, "{\n");
2389 indent++;
2390 print_file(file, indent, "0,\n");
2391 print_file(file, indent, "{\n");
2392 indent++;
2393 print_file(file, indent, "NdrFcShort(0x0),\n");
2395 set_all_tfswrite(TRUE);
2396 process_tfs(file, ifaces, pred);
2398 print_file(file, indent, "0x0\n");
2399 indent--;
2400 print_file(file, indent, "}\n");
2401 indent--;
2402 print_file(file, indent, "};\n");
2403 print_file(file, indent, "\n");
2406 static unsigned int get_required_buffer_size_type(
2407 const type_t *type, const char *name, unsigned int *alignment)
2409 *alignment = 0;
2410 if (is_user_type(type))
2412 const char *uname;
2413 const type_t *utype = get_user_type(type, &uname);
2414 return get_required_buffer_size_type(utype, uname, alignment);
2416 else
2418 switch (type->type)
2420 case RPC_FC_BYTE:
2421 case RPC_FC_CHAR:
2422 case RPC_FC_USMALL:
2423 case RPC_FC_SMALL:
2424 *alignment = 4;
2425 return 1;
2427 case RPC_FC_WCHAR:
2428 case RPC_FC_USHORT:
2429 case RPC_FC_SHORT:
2430 case RPC_FC_ENUM16:
2431 *alignment = 4;
2432 return 2;
2434 case RPC_FC_ULONG:
2435 case RPC_FC_LONG:
2436 case RPC_FC_ENUM32:
2437 case RPC_FC_FLOAT:
2438 case RPC_FC_ERROR_STATUS_T:
2439 *alignment = 4;
2440 return 4;
2442 case RPC_FC_HYPER:
2443 case RPC_FC_DOUBLE:
2444 *alignment = 8;
2445 return 8;
2447 case RPC_FC_IGNORE:
2448 case RPC_FC_BIND_PRIMITIVE:
2449 return 0;
2451 case RPC_FC_STRUCT:
2452 case RPC_FC_PSTRUCT:
2454 size_t size = 0;
2455 const var_t *field;
2456 if (!type->fields) return 0;
2457 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2459 unsigned int alignment;
2460 size += get_required_buffer_size_type(field->type, field->name,
2461 &alignment);
2463 return size;
2466 case RPC_FC_RP:
2467 return
2468 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2469 ? get_required_buffer_size_type( type->ref, name, alignment )
2470 : 0;
2472 case RPC_FC_SMFARRAY:
2473 case RPC_FC_LGFARRAY:
2474 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2476 default:
2477 return 0;
2482 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2484 int in_attr = is_attr(var->attrs, ATTR_IN);
2485 int out_attr = is_attr(var->attrs, ATTR_OUT);
2486 const type_t *t;
2488 if (!in_attr && !out_attr)
2489 in_attr = 1;
2491 *alignment = 0;
2493 for (t = var->type; is_ptr(t); t = t->ref)
2494 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2496 *alignment = 4;
2497 return 20;
2500 if (pass == PASS_OUT)
2502 if (out_attr && is_ptr(var->type))
2504 type_t *type = var->type;
2506 if (type->type == RPC_FC_STRUCT)
2508 const var_t *field;
2509 unsigned int size = 36;
2511 if (!type->fields) return size;
2512 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2514 unsigned int align;
2515 size += get_required_buffer_size_type(
2516 field->type, field->name, &align);
2518 return size;
2521 return 0;
2523 else
2525 if ((!out_attr || in_attr) && !var->type->size_is
2526 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2528 if (is_ptr(var->type))
2530 type_t *type = var->type;
2532 if (is_base_type(type->type))
2534 return 25;
2536 else if (type->type == RPC_FC_STRUCT)
2538 unsigned int size = 36;
2539 const var_t *field;
2541 if (!type->fields) return size;
2542 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2544 unsigned int align;
2545 size += get_required_buffer_size_type(
2546 field->type, field->name, &align);
2548 return size;
2553 return get_required_buffer_size_type(var->type, var->name, alignment);
2557 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2559 const var_t *var;
2560 unsigned int total_size = 0, alignment;
2562 if (func->args)
2564 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2566 total_size += get_required_buffer_size(var, &alignment, pass);
2567 total_size += alignment;
2571 if (pass == PASS_OUT && !is_void(func->def->type))
2573 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2574 total_size += alignment;
2576 return total_size;
2579 static void print_phase_function(FILE *file, int indent, const char *type,
2580 enum remoting_phase phase,
2581 const var_t *var, unsigned int type_offset)
2583 const char *function;
2584 switch (phase)
2586 case PHASE_BUFFERSIZE:
2587 function = "BufferSize";
2588 break;
2589 case PHASE_MARSHAL:
2590 function = "Marshall";
2591 break;
2592 case PHASE_UNMARSHAL:
2593 function = "Unmarshall";
2594 break;
2595 case PHASE_FREE:
2596 function = "Free";
2597 break;
2598 default:
2599 assert(0);
2600 return;
2603 print_file(file, indent, "Ndr%s%s(\n", type, function);
2604 indent++;
2605 print_file(file, indent, "&_StubMsg,\n");
2606 print_file(file, indent, "%s%s%s%s,\n",
2607 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2608 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2609 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2610 var->name);
2611 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2612 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2613 if (phase == PHASE_UNMARSHAL)
2614 print_file(file, indent, "0);\n");
2615 indent--;
2618 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2619 enum pass pass, const var_t *var,
2620 const char *varname)
2622 type_t *type = var->type;
2623 unsigned int size;
2624 unsigned int alignment = 0;
2625 unsigned char rtype;
2627 /* no work to do for other phases, buffer sizing is done elsewhere */
2628 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2629 return;
2631 rtype = is_ptr(type) ? type->ref->type : type->type;
2633 switch (rtype)
2635 case RPC_FC_BYTE:
2636 case RPC_FC_CHAR:
2637 case RPC_FC_SMALL:
2638 case RPC_FC_USMALL:
2639 size = 1;
2640 alignment = 1;
2641 break;
2643 case RPC_FC_WCHAR:
2644 case RPC_FC_USHORT:
2645 case RPC_FC_SHORT:
2646 case RPC_FC_ENUM16:
2647 size = 2;
2648 alignment = 2;
2649 break;
2651 case RPC_FC_ULONG:
2652 case RPC_FC_LONG:
2653 case RPC_FC_ENUM32:
2654 case RPC_FC_FLOAT:
2655 case RPC_FC_ERROR_STATUS_T:
2656 size = 4;
2657 alignment = 4;
2658 break;
2660 case RPC_FC_HYPER:
2661 case RPC_FC_DOUBLE:
2662 size = 8;
2663 alignment = 8;
2664 break;
2666 case RPC_FC_IGNORE:
2667 case RPC_FC_BIND_PRIMITIVE:
2668 /* no marshalling needed */
2669 return;
2671 default:
2672 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2673 size = 0;
2676 if (phase == PHASE_MARSHAL)
2677 print_file(file, indent, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
2678 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2679 alignment - 1, alignment - 1);
2681 if (phase == PHASE_MARSHAL)
2683 print_file(file, indent, "*(");
2684 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2685 if (is_ptr(type))
2686 fprintf(file, " *)_StubMsg.Buffer = *");
2687 else
2688 fprintf(file, " *)_StubMsg.Buffer = ");
2689 fprintf(file, "%s", varname);
2690 fprintf(file, ";\n");
2692 else if (phase == PHASE_UNMARSHAL)
2694 print_file(file, indent, "if (_StubMsg.Buffer + sizeof(");
2695 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2696 fprintf(file, ") > _StubMsg.BufferEnd)\n");
2697 print_file(file, indent, "{\n");
2698 print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2699 print_file(file, indent, "}\n");
2700 if (pass == PASS_IN || pass == PASS_RETURN)
2701 print_file(file, indent, "");
2702 else
2703 print_file(file, indent, "*");
2704 fprintf(file, "%s", varname);
2705 if (pass == PASS_IN && is_ptr(type))
2706 fprintf(file, " = (");
2707 else
2708 fprintf(file, " = *(");
2709 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2710 fprintf(file, " *)_StubMsg.Buffer;\n");
2713 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2714 write_type_decl(file, var->type, NULL);
2715 fprintf(file, ");\n");
2718 /* returns whether the MaxCount, Offset or ActualCount members need to be
2719 * filled in for the specified phase */
2720 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2722 return (phase != PHASE_UNMARSHAL);
2725 expr_t *get_size_is_expr(const type_t *t, const char *name)
2727 expr_t *x = NULL;
2729 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2730 if (t->size_is)
2732 if (!x)
2733 x = t->size_is;
2734 else
2735 error("%s: multidimensional conformant"
2736 " arrays not supported at the top level\n",
2737 name);
2740 return x;
2743 static void write_remoting_arg(FILE *file, int indent, const func_t *func,
2744 enum pass pass, enum remoting_phase phase,
2745 const var_t *var)
2747 int in_attr, out_attr, pointer_type;
2748 const type_t *type = var->type;
2749 unsigned char rtype;
2750 size_t start_offset = type->typestring_offset;
2752 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2753 if (!pointer_type)
2754 pointer_type = RPC_FC_RP;
2756 in_attr = is_attr(var->attrs, ATTR_IN);
2757 out_attr = is_attr(var->attrs, ATTR_OUT);
2758 if (!in_attr && !out_attr)
2759 in_attr = 1;
2761 if (phase != PHASE_FREE)
2762 switch (pass)
2764 case PASS_IN:
2765 if (!in_attr) return;
2766 break;
2767 case PASS_OUT:
2768 if (!out_attr) return;
2769 break;
2770 case PASS_RETURN:
2771 break;
2774 rtype = type->type;
2776 if (is_context_handle(type))
2778 if (phase == PHASE_MARSHAL)
2780 if (pass == PASS_IN)
2782 /* if the context_handle attribute appears in the chain of types
2783 * without pointers being followed, then the context handle must
2784 * be direct, otherwise it is a pointer */
2785 int is_ch_ptr = is_aliaschain_attr(type, ATTR_CONTEXTHANDLE) ? FALSE : TRUE;
2786 print_file(file, indent, "NdrClientContextMarshall(\n");
2787 print_file(file, indent + 1, "&_StubMsg,\n");
2788 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ch_ptr ? "*" : "", var->name);
2789 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2791 else
2793 print_file(file, indent, "NdrServerContextNewMarshall(\n");
2794 print_file(file, indent + 1, "&_StubMsg,\n");
2795 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2796 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type));
2797 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
2800 else if (phase == PHASE_UNMARSHAL)
2802 if (pass == PASS_OUT)
2804 if (!in_attr)
2805 print_file(file, indent, "*%s = 0;\n", var->name);
2806 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2807 print_file(file, indent + 1, "&_StubMsg,\n");
2808 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2809 print_file(file, indent + 1, "_Handle);\n");
2811 else
2813 print_file(file, indent, "%s = NdrServerContextNewUnmarshall(\n", var->name);
2814 print_file(file, indent + 1, "&_StubMsg,\n");
2815 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
2819 else if (is_user_type(var->type))
2821 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2823 else if (is_string_type(var->attrs, var->type))
2825 if (is_array(type) && !is_conformant_array(type))
2826 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2827 else
2829 if (type->size_is && is_size_needed_for_phase(phase))
2831 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2832 write_expr(file, type->size_is, 1);
2833 fprintf(file, ";\n");
2836 if (phase == PHASE_FREE || pass == PASS_RETURN || pointer_type == RPC_FC_UP)
2837 print_phase_function(file, indent, "Pointer", phase, var,
2838 start_offset - (type->size_is ? 4 : 2));
2839 else
2840 print_phase_function(file, indent, "ConformantString", phase, var,
2841 start_offset);
2844 else if (is_array(type))
2846 unsigned char tc = type->type;
2847 const char *array_type = "FixedArray";
2849 /* We already have the size_is expression since it's at the
2850 top level, but do checks for multidimensional conformant
2851 arrays. When we handle them, we'll need to extend this
2852 function to return a list, and then we'll actually use
2853 the return value. */
2854 get_size_is_expr(type, var->name);
2856 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2858 if (is_size_needed_for_phase(phase))
2860 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2861 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2862 write_expr(file, type->length_is, 1);
2863 fprintf(file, ";\n\n");
2865 array_type = "VaryingArray";
2867 else if (tc == RPC_FC_CARRAY)
2869 if (is_size_needed_for_phase(phase))
2871 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2872 write_expr(file, type->size_is, 1);
2873 fprintf(file, ";\n\n");
2875 array_type = "ConformantArray";
2877 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2879 if (is_size_needed_for_phase(phase))
2881 if (type->size_is)
2883 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2884 write_expr(file, type->size_is, 1);
2885 fprintf(file, ";\n");
2887 if (type->length_is)
2889 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2890 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2891 write_expr(file, type->length_is, 1);
2892 fprintf(file, ";\n\n");
2895 array_type = (tc == RPC_FC_BOGUS_ARRAY
2896 ? "ComplexArray"
2897 : "ConformantVaryingArray");
2900 if (pointer_type != RPC_FC_RP) array_type = "Pointer";
2901 print_phase_function(file, indent, array_type, phase, var, start_offset);
2902 if (phase == PHASE_FREE && pointer_type == RPC_FC_RP)
2904 /* these are all unmarshalled by allocating memory */
2905 if (type->type == RPC_FC_BOGUS_ARRAY ||
2906 type->type == RPC_FC_CVARRAY ||
2907 ((type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY) && in_attr) ||
2908 (type->type == RPC_FC_CARRAY && !in_attr))
2910 print_file(file, indent, "if (%s)\n", var->name);
2911 indent++;
2912 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2916 else if (!is_ptr(var->type) && is_base_type(rtype))
2918 if (phase != PHASE_FREE)
2919 print_phase_basetype(file, indent, phase, pass, var, var->name);
2921 else if (!is_ptr(var->type))
2923 switch (rtype)
2925 case RPC_FC_STRUCT:
2926 case RPC_FC_PSTRUCT:
2927 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2928 break;
2929 case RPC_FC_CSTRUCT:
2930 case RPC_FC_CPSTRUCT:
2931 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2932 break;
2933 case RPC_FC_CVSTRUCT:
2934 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2935 break;
2936 case RPC_FC_BOGUS_STRUCT:
2937 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2938 break;
2939 case RPC_FC_RP:
2940 if (is_base_type( var->type->ref->type ))
2942 print_phase_basetype(file, indent, phase, pass, var, var->name);
2944 else if (var->type->ref->type == RPC_FC_STRUCT)
2946 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2947 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2949 else
2951 expr_t *iid;
2952 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2954 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2955 write_expr( file, iid, 1 );
2956 fprintf( file, ";\n\n" );
2958 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2960 break;
2961 default:
2962 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2965 else
2967 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2969 if (phase != PHASE_FREE)
2970 print_phase_basetype(file, indent, phase, pass, var, var->name);
2972 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2974 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2975 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2977 else
2979 expr_t *iid;
2980 expr_t *sx = get_size_is_expr(type, var->name);
2982 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2984 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2985 write_expr( file, iid, 1 );
2986 fprintf( file, ";\n\n" );
2988 else if (sx)
2990 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2991 write_expr(file, sx, 1);
2992 fprintf(file, ";\n\n");
2994 if (var->type->ref->type == RPC_FC_IP)
2995 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2996 else
2997 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
3000 fprintf(file, "\n");
3003 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
3004 enum pass pass, enum remoting_phase phase)
3006 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN)
3008 unsigned int size = get_function_buffer_size( func, pass );
3009 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
3012 if (pass == PASS_RETURN)
3014 var_t var;
3015 var = *func->def;
3016 var.name = xstrdup( "_RetVal" );
3017 write_remoting_arg( file, indent, func, pass, phase, &var );
3018 free( var.name );
3020 else
3022 const var_t *var;
3023 if (!func->args)
3024 return;
3025 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3026 write_remoting_arg( file, indent, func, pass, phase, var );
3031 size_t get_size_procformatstring_var(const var_t *var)
3033 return write_procformatstring_var(NULL, 0, var, FALSE);
3037 size_t get_size_procformatstring_func(const func_t *func)
3039 const var_t *var;
3040 size_t size = 0;
3042 /* argument list size */
3043 if (func->args)
3044 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3045 size += get_size_procformatstring_var(var);
3047 /* return value size */
3048 if (is_void(func->def->type))
3049 size += 2; /* FC_END and FC_PAD */
3050 else
3051 size += get_size_procformatstring_var(func->def);
3053 return size;
3056 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
3058 const ifref_t *iface;
3059 size_t size = 1;
3060 const func_t *func;
3062 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
3064 if (!pred(iface->iface))
3065 continue;
3067 if (iface->iface->funcs)
3068 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
3069 if (!is_local(func->def->attrs))
3070 size += get_size_procformatstring_func( func );
3072 return size;
3075 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
3077 set_all_tfswrite(FALSE);
3078 return process_tfs(NULL, ifaces, pred);
3081 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
3082 const var_list_t *fields, const char *structvar)
3084 switch (e->type) {
3085 case EXPR_VOID:
3086 break;
3087 case EXPR_NUM:
3088 fprintf(h, "%lu", e->u.lval);
3089 break;
3090 case EXPR_HEXNUM:
3091 fprintf(h, "0x%lx", e->u.lval);
3092 break;
3093 case EXPR_DOUBLE:
3094 fprintf(h, "%#.15g", e->u.dval);
3095 break;
3096 case EXPR_TRUEFALSE:
3097 if (e->u.lval == 0)
3098 fprintf(h, "FALSE");
3099 else
3100 fprintf(h, "TRUE");
3101 break;
3102 case EXPR_IDENTIFIER:
3104 const var_t *field;
3105 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3106 if (!strcmp(e->u.sval, field->name))
3108 fprintf(h, "%s->%s", structvar, e->u.sval);
3109 break;
3112 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
3113 break;
3115 case EXPR_NEG:
3116 fprintf(h, "-");
3117 write_struct_expr(h, e->ref, 1, fields, structvar);
3118 break;
3119 case EXPR_NOT:
3120 fprintf(h, "~");
3121 write_struct_expr(h, e->ref, 1, fields, structvar);
3122 break;
3123 case EXPR_PPTR:
3124 fprintf(h, "*");
3125 write_struct_expr(h, e->ref, 1, fields, structvar);
3126 break;
3127 case EXPR_CAST:
3128 fprintf(h, "(");
3129 write_type_decl(h, e->u.tref, NULL);
3130 fprintf(h, ")");
3131 write_struct_expr(h, e->ref, 1, fields, structvar);
3132 break;
3133 case EXPR_SIZEOF:
3134 fprintf(h, "sizeof(");
3135 write_type_decl(h, e->u.tref, NULL);
3136 fprintf(h, ")");
3137 break;
3138 case EXPR_SHL:
3139 case EXPR_SHR:
3140 case EXPR_MUL:
3141 case EXPR_DIV:
3142 case EXPR_ADD:
3143 case EXPR_SUB:
3144 case EXPR_AND:
3145 case EXPR_OR:
3146 if (brackets) fprintf(h, "(");
3147 write_struct_expr(h, e->ref, 1, fields, structvar);
3148 switch (e->type) {
3149 case EXPR_SHL: fprintf(h, " << "); break;
3150 case EXPR_SHR: fprintf(h, " >> "); break;
3151 case EXPR_MUL: fprintf(h, " * "); break;
3152 case EXPR_DIV: fprintf(h, " / "); break;
3153 case EXPR_ADD: fprintf(h, " + "); break;
3154 case EXPR_SUB: fprintf(h, " - "); break;
3155 case EXPR_AND: fprintf(h, " & "); break;
3156 case EXPR_OR: fprintf(h, " | "); break;
3157 default: break;
3159 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3160 if (brackets) fprintf(h, ")");
3161 break;
3162 case EXPR_COND:
3163 if (brackets) fprintf(h, "(");
3164 write_struct_expr(h, e->ref, 1, fields, structvar);
3165 fprintf(h, " ? ");
3166 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3167 fprintf(h, " : ");
3168 write_struct_expr(h, e->ext2, 1, fields, structvar);
3169 if (brackets) fprintf(h, ")");
3170 break;
3171 case EXPR_ADDRESSOF:
3172 fprintf(h, "&");
3173 write_struct_expr(h, e->ref, 1, fields, structvar);
3174 break;
3179 void declare_stub_args( FILE *file, int indent, const func_t *func )
3181 int in_attr, out_attr;
3182 int i = 0;
3183 const var_t *def = func->def;
3184 const var_t *var;
3186 /* declare return value '_RetVal' */
3187 if (!is_void(def->type))
3189 print_file(file, indent, "");
3190 write_type_decl_left(file, def->type);
3191 fprintf(file, " _RetVal;\n");
3194 if (!func->args)
3195 return;
3197 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3199 int is_string = is_attr(var->attrs, ATTR_STRING);
3201 in_attr = is_attr(var->attrs, ATTR_IN);
3202 out_attr = is_attr(var->attrs, ATTR_OUT);
3203 if (!out_attr && !in_attr)
3204 in_attr = 1;
3206 if (is_context_handle(var->type))
3207 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3208 else
3210 if (!in_attr && !var->type->size_is && !is_string)
3212 print_file(file, indent, "");
3213 write_type_decl(file, var->type->declarray ? var->type : var->type->ref,
3214 "_W%u", i++);
3215 fprintf(file, ";\n");
3218 print_file(file, indent, "");
3219 write_type_decl_left(file, var->type);
3220 fprintf(file, " ");
3221 if (var->type->declarray) {
3222 fprintf(file, "( *");
3223 write_name(file, var);
3224 fprintf(file, " )");
3225 } else
3226 write_name(file, var);
3227 write_type_right(file, var->type, FALSE);
3228 fprintf(file, ";\n");
3230 if (decl_indirect(var->type))
3231 print_file(file, indent, "void *_p_%s = &%s;\n",
3232 var->name, var->name);
3238 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3240 int in_attr, out_attr;
3241 int i = 0, sep = 0;
3242 const var_t *var;
3244 if (!func->args)
3245 return;
3247 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3249 int is_string = is_attr(var->attrs, ATTR_STRING);
3250 in_attr = is_attr(var->attrs, ATTR_IN);
3251 out_attr = is_attr(var->attrs, ATTR_OUT);
3252 if (!out_attr && !in_attr)
3253 in_attr = 1;
3255 if (!in_attr)
3257 print_file(file, indent, "");
3258 write_name(file, var);
3260 if (is_context_handle(var->type))
3262 fprintf(file, " = NdrContextHandleInitialize(\n");
3263 print_file(file, indent + 1, "&_StubMsg,\n");
3264 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3265 var->type->typestring_offset);
3267 else if (var->type->size_is)
3269 unsigned int size, align = 0;
3270 type_t *type = var->type;
3272 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3273 for ( ; type->size_is ; type = type->ref)
3275 write_expr(file, type->size_is, TRUE);
3276 fprintf(file, " * ");
3278 size = type_memsize(type, &align);
3279 fprintf(file, "%u);\n", size);
3281 else if (!is_string)
3283 fprintf(file, " = &_W%u;\n", i);
3284 if (is_ptr(var->type) && !last_ptr(var->type))
3285 print_file(file, indent, "_W%u = 0;\n", i);
3286 i++;
3289 sep = 1;
3292 if (sep)
3293 fprintf(file, "\n");
3297 int write_expr_eval_routines(FILE *file, const char *iface)
3299 static const char *var_name = "pS";
3300 int result = 0;
3301 struct expr_eval_routine *eval;
3302 unsigned short callback_offset = 0;
3304 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3306 const char *name = eval->structure->name;
3307 const var_list_t *fields = eval->structure->fields;
3308 result = 1;
3310 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3311 iface, name, callback_offset);
3312 print_file(file, 0, "{\n");
3313 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3314 name, var_name, name, eval->baseoff);
3315 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3316 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3317 write_struct_expr(file, eval->expr, 1, fields, var_name);
3318 fprintf(file, ";\n");
3319 print_file(file, 0, "}\n\n");
3320 callback_offset++;
3322 return result;
3325 void write_expr_eval_routine_list(FILE *file, const char *iface)
3327 struct expr_eval_routine *eval;
3328 struct expr_eval_routine *cursor;
3329 unsigned short callback_offset = 0;
3331 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3332 fprintf(file, "{\n");
3334 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3336 const char *name = eval->structure->name;
3337 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3338 callback_offset++;
3339 list_remove(&eval->entry);
3340 free(eval);
3343 fprintf(file, "};\n\n");
3346 void write_user_quad_list(FILE *file)
3348 user_type_t *ut;
3350 if (list_empty(&user_type_list))
3351 return;
3353 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3354 fprintf(file, "{\n");
3355 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3357 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3358 print_file(file, 1, "{\n");
3359 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3360 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3361 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3362 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3363 print_file(file, 1, "}%s\n", sep);
3365 fprintf(file, "};\n\n");
3368 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3370 const struct str_list_entry_t *endpoint;
3371 const char *p;
3373 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3374 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3375 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3377 print_file( f, 1, "{ (const unsigned char *)\"" );
3378 for (p = endpoint->str; *p && *p != ':'; p++)
3380 if (*p == '"' || *p == '\\') fputc( '\\', f );
3381 fputc( *p, f );
3383 if (!*p) goto error;
3384 if (p[1] != '[') goto error;
3386 fprintf( f, "\", (const unsigned char *)\"" );
3387 for (p += 2; *p && *p != ']'; p++)
3389 if (*p == '"' || *p == '\\') fputc( '\\', f );
3390 fputc( *p, f );
3392 if (*p != ']') goto error;
3393 fprintf( f, "\" },\n" );
3395 print_file( f, 0, "};\n\n" );
3396 return;
3398 error:
3399 error("Invalid endpoint syntax '%s'\n", endpoint->str);