msi: Fix the character count passed into RegSetValueExA in test_MsiQueryFeatureState.
[wine.git] / tools / widl / typegen.c
blobf3af93571b6bca135f7d3fa170cd36581f493fd2
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);
62 const char *string_of_type(unsigned char type)
64 switch (type)
66 case RPC_FC_BYTE: return "FC_BYTE";
67 case RPC_FC_CHAR: return "FC_CHAR";
68 case RPC_FC_SMALL: return "FC_SMALL";
69 case RPC_FC_USMALL: return "FC_USMALL";
70 case RPC_FC_WCHAR: return "FC_WCHAR";
71 case RPC_FC_SHORT: return "FC_SHORT";
72 case RPC_FC_USHORT: return "FC_USHORT";
73 case RPC_FC_LONG: return "FC_LONG";
74 case RPC_FC_ULONG: return "FC_ULONG";
75 case RPC_FC_FLOAT: return "FC_FLOAT";
76 case RPC_FC_HYPER: return "FC_HYPER";
77 case RPC_FC_DOUBLE: return "FC_DOUBLE";
78 case RPC_FC_ENUM16: return "FC_ENUM16";
79 case RPC_FC_ENUM32: return "FC_ENUM32";
80 case RPC_FC_IGNORE: return "FC_IGNORE";
81 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
82 case RPC_FC_RP: return "FC_RP";
83 case RPC_FC_UP: return "FC_UP";
84 case RPC_FC_OP: return "FC_OP";
85 case RPC_FC_FP: return "FC_FP";
86 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
87 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
88 case RPC_FC_STRUCT: return "FC_STRUCT";
89 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
90 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
91 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
92 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
93 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
94 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
95 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
96 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
97 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
98 case RPC_FC_CARRAY: return "FC_CARRAY";
99 case RPC_FC_CVARRAY: return "FC_CVARRAY";
100 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
101 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
102 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
103 case RPC_FC_POINTER: return "FC_POINTER";
104 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
105 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
106 case RPC_FC_CSTRING: return "FC_CSTRING";
107 case RPC_FC_WSTRING: return "FC_WSTRING";
108 default:
109 error("string_of_type: unknown type 0x%02x\n", type);
110 return NULL;
114 int is_struct(unsigned char type)
116 switch (type)
118 case RPC_FC_STRUCT:
119 case RPC_FC_PSTRUCT:
120 case RPC_FC_CSTRUCT:
121 case RPC_FC_CPSTRUCT:
122 case RPC_FC_CVSTRUCT:
123 case RPC_FC_BOGUS_STRUCT:
124 return 1;
125 default:
126 return 0;
130 static int is_non_complex_struct(const type_t *type)
132 switch (type->type)
134 case RPC_FC_STRUCT:
135 case RPC_FC_PSTRUCT:
136 case RPC_FC_CSTRUCT:
137 case RPC_FC_CPSTRUCT:
138 case RPC_FC_CVSTRUCT:
139 return 1;
140 default:
141 return 0;
145 int is_union(unsigned char type)
147 switch (type)
149 case RPC_FC_ENCAPSULATED_UNION:
150 case RPC_FC_NON_ENCAPSULATED_UNION:
151 return 1;
152 default:
153 return 0;
157 static int type_has_pointers(const type_t *type)
159 if (is_user_type(type))
160 return FALSE;
161 else if (is_ptr(type))
162 return TRUE;
163 else if (is_array(type))
164 return type_has_pointers(type->ref);
165 else if (is_struct(type->type))
167 const var_t *field;
168 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
170 if (type_has_pointers(field->type))
171 return TRUE;
174 else if (is_union(type->type))
176 var_list_t *fields;
177 const var_t *field;
178 if (type->type == RPC_FC_ENCAPSULATED_UNION)
180 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
181 fields = uv->type->fields;
183 else
184 fields = type->fields;
185 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
187 if (field->type && type_has_pointers(field->type))
188 return TRUE;
192 return FALSE;
195 static int type_has_full_pointer(const type_t *type)
197 if (is_user_type(type))
198 return FALSE;
199 else if (type->type == RPC_FC_FP)
200 return TRUE;
201 else if (is_ptr(type))
202 return FALSE;
203 else if (is_array(type))
204 return type_has_full_pointer(type->ref);
205 else if (is_struct(type->type))
207 const var_t *field;
208 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
210 if (type_has_full_pointer(field->type))
211 return TRUE;
214 else if (is_union(type->type))
216 var_list_t *fields;
217 const var_t *field;
218 if (type->type == RPC_FC_ENCAPSULATED_UNION)
220 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
221 fields = uv->type->fields;
223 else
224 fields = type->fields;
225 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
227 if (field->type && type_has_full_pointer(field->type))
228 return TRUE;
232 return FALSE;
235 static unsigned short user_type_offset(const char *name)
237 user_type_t *ut;
238 unsigned short off = 0;
239 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
241 if (strcmp(name, ut->name) == 0)
242 return off;
243 ++off;
245 error("user_type_offset: couldn't find type (%s)\n", name);
246 return 0;
249 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
251 type->typestring_offset = offset;
252 if (file) type->tfswrite = FALSE;
255 static void guard_rec(type_t *type)
257 /* types that contain references to themselves (like a linked list),
258 need to be shielded from infinite recursion when writing embedded
259 types */
260 if (type->typestring_offset)
261 type->tfswrite = FALSE;
262 else
263 type->typestring_offset = 1;
266 static type_t *get_user_type(const type_t *t, const char **pname)
268 for (;;)
270 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
271 if (ut)
273 if (pname)
274 *pname = t->name;
275 return ut;
278 if (t->kind == TKIND_ALIAS)
279 t = t->orig;
280 else
281 return 0;
285 int is_user_type(const type_t *t)
287 return get_user_type(t, NULL) != NULL;
290 static int is_embedded_complex(const type_t *type)
292 unsigned char tc = type->type;
293 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
294 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
297 static const char *get_context_handle_type_name(const type_t *type)
299 const type_t *t;
300 for (t = type; is_ptr(t); t = t->ref)
301 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
302 return t->name;
303 assert(0);
304 return NULL;
307 /* This is actually fairly involved to implement precisely, due to the
308 effects attributes may have and things like that. Right now this is
309 only used for optimization, so just check for a very small set of
310 criteria that guarantee the types are equivalent; assume every thing
311 else is different. */
312 static int compare_type(const type_t *a, const type_t *b)
314 if (a == b
315 || (a->name
316 && b->name
317 && strcmp(a->name, b->name) == 0))
318 return 0;
319 /* Ordering doesn't need to be implemented yet. */
320 return 1;
323 static int compare_expr(const expr_t *a, const expr_t *b)
325 int ret;
327 if (a->type != b->type)
328 return a->type - b->type;
330 switch (a->type)
332 case EXPR_NUM:
333 case EXPR_HEXNUM:
334 case EXPR_TRUEFALSE:
335 return a->u.lval - b->u.lval;
336 case EXPR_DOUBLE:
337 return a->u.dval - b->u.dval;
338 case EXPR_IDENTIFIER:
339 return strcmp(a->u.sval, b->u.sval);
340 case EXPR_COND:
341 ret = compare_expr(a->ref, b->ref);
342 if (ret != 0)
343 return ret;
344 ret = compare_expr(a->u.ext, b->u.ext);
345 if (ret != 0)
346 return ret;
347 return compare_expr(a->ext2, b->ext2);
348 case EXPR_OR:
349 case EXPR_AND:
350 case EXPR_ADD:
351 case EXPR_SUB:
352 case EXPR_MUL:
353 case EXPR_DIV:
354 case EXPR_SHL:
355 case EXPR_SHR:
356 ret = compare_expr(a->ref, b->ref);
357 if (ret != 0)
358 return ret;
359 return compare_expr(a->u.ext, b->u.ext);
360 case EXPR_CAST:
361 ret = compare_type(a->u.tref, b->u.tref);
362 if (ret != 0)
363 return ret;
364 /* Fall through. */
365 case EXPR_NOT:
366 case EXPR_NEG:
367 case EXPR_PPTR:
368 case EXPR_ADDRESSOF:
369 return compare_expr(a->ref, b->ref);
370 case EXPR_SIZEOF:
371 return compare_type(a->u.tref, b->u.tref);
372 case EXPR_VOID:
373 return 0;
375 return -1;
378 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
379 do { \
380 if (file) \
381 fprintf(file, "/* %2u */\n", typestring_offset); \
382 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
384 while (0)
386 static void print_file(FILE *file, int indent, const char *format, ...)
388 va_list va;
389 va_start(va, format);
390 print(file, indent, format, va);
391 va_end(va);
394 void print(FILE *file, int indent, const char *format, va_list va)
396 if (file)
398 if (format[0] != '\n')
399 while (0 < indent--)
400 fprintf(file, " ");
401 vfprintf(file, format, va);
406 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n)
408 if (decl_indirect(t))
409 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof(%s));\n", n, n);
410 else if (is_ptr(t) || is_array(t))
411 print_file(file, indent, "%s = 0;\n", n);
414 void write_parameters_init(FILE *file, int indent, const func_t *func)
416 const var_t *var;
418 if (!is_void(func->def->type))
419 write_var_init(file, indent, func->def->type, "_RetVal");
421 if (!func->args)
422 return;
424 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
425 write_var_init(file, indent, var->type, var->name);
427 fprintf(file, "\n");
430 static void write_formatdesc(FILE *f, int indent, const char *str)
432 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
433 print_file(f, indent, "{\n");
434 print_file(f, indent + 1, "short Pad;\n");
435 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
436 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
437 print_file(f, indent, "\n");
440 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
442 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
443 get_size_typeformatstring(ifaces, pred));
445 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
446 get_size_procformatstring(ifaces, pred));
448 fprintf(f, "\n");
449 write_formatdesc(f, indent, "TYPE");
450 write_formatdesc(f, indent, "PROC");
451 fprintf(f, "\n");
452 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
453 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
454 print_file(f, indent, "\n");
457 static inline int is_base_type(unsigned char type)
459 switch (type)
461 case RPC_FC_BYTE:
462 case RPC_FC_CHAR:
463 case RPC_FC_USMALL:
464 case RPC_FC_SMALL:
465 case RPC_FC_WCHAR:
466 case RPC_FC_USHORT:
467 case RPC_FC_SHORT:
468 case RPC_FC_ULONG:
469 case RPC_FC_LONG:
470 case RPC_FC_HYPER:
471 case RPC_FC_IGNORE:
472 case RPC_FC_FLOAT:
473 case RPC_FC_DOUBLE:
474 case RPC_FC_ENUM16:
475 case RPC_FC_ENUM32:
476 case RPC_FC_ERROR_STATUS_T:
477 case RPC_FC_BIND_PRIMITIVE:
478 return TRUE;
480 default:
481 return FALSE;
485 int decl_indirect(const type_t *t)
487 return is_user_type(t)
488 || (!is_base_type(t->type)
489 && !is_ptr(t)
490 && !is_array(t));
493 static size_t write_procformatstring_var(FILE *file, int indent,
494 const var_t *var, int is_return)
496 size_t size;
497 const type_t *type = var->type;
499 int is_in = is_attr(var->attrs, ATTR_IN);
500 int is_out = is_attr(var->attrs, ATTR_OUT);
502 if (!is_in && !is_out) is_in = TRUE;
504 if (!type->declarray && is_base_type(type->type))
506 if (is_return)
507 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
508 else
509 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
511 if (type->type == RPC_FC_BIND_PRIMITIVE)
513 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
514 size = 2; /* includes param type prefix */
516 else if (is_base_type(type->type))
518 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
519 size = 2; /* includes param type prefix */
521 else
523 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
524 size = 0;
527 else
529 if (is_return)
530 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
531 else if (is_in && is_out)
532 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
533 else if (is_out)
534 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
535 else
536 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
538 print_file(file, indent, "0x01,\n");
539 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
540 size = 4; /* includes param type prefix */
542 return size;
545 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
547 const ifref_t *iface;
548 int indent = 0;
549 const var_t *var;
551 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
552 print_file(file, indent, "{\n");
553 indent++;
554 print_file(file, indent, "0,\n");
555 print_file(file, indent, "{\n");
556 indent++;
558 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
560 if (!pred(iface->iface))
561 continue;
563 if (iface->iface->funcs)
565 const func_t *func;
566 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
568 if (is_local(func->def->attrs)) continue;
569 /* emit argument data */
570 if (func->args)
572 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
573 write_procformatstring_var(file, indent, var, FALSE);
576 /* emit return value data */
577 var = func->def;
578 if (is_void(var->type))
580 print_file(file, indent, "0x5b, /* FC_END */\n");
581 print_file(file, indent, "0x5c, /* FC_PAD */\n");
583 else
584 write_procformatstring_var(file, indent, var, TRUE);
589 print_file(file, indent, "0x0\n");
590 indent--;
591 print_file(file, indent, "}\n");
592 indent--;
593 print_file(file, indent, "};\n");
594 print_file(file, indent, "\n");
597 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
599 if (is_base_type(type->type))
601 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
602 *typestring_offset += 1;
603 return 1;
606 return 0;
609 /* write conformance / variance descriptor */
610 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
611 unsigned int baseoff, const type_t *type,
612 const expr_t *expr)
614 unsigned char operator_type = 0;
615 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
616 const char *conftype_string = "";
617 const char *operator_string = "no operators";
618 const expr_t *subexpr;
620 if (!expr)
622 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
623 return 4;
626 if (!structure)
628 /* Top-level conformance calculations are done inline. */
629 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
630 RPC_FC_TOP_LEVEL_CONFORMANCE);
631 print_file (file, 2, "0x0,\n");
632 print_file (file, 2, "NdrFcShort(0x0),\n");
633 return 4;
636 if (expr->is_const)
638 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
639 error("write_conf_or_var_desc: constant value %ld is greater than "
640 "the maximum constant size of %d\n", expr->cval,
641 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
643 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
644 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
645 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
646 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
648 return 4;
651 if (is_ptr(type) || (is_array(type) && !type->declarray))
653 conftype = RPC_FC_POINTER_CONFORMANCE;
654 conftype_string = "field pointer, ";
657 subexpr = expr;
658 switch (subexpr->type)
660 case EXPR_PPTR:
661 subexpr = subexpr->ref;
662 operator_type = RPC_FC_DEREFERENCE;
663 operator_string = "FC_DEREFERENCE";
664 break;
665 case EXPR_DIV:
666 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
668 subexpr = subexpr->ref;
669 operator_type = RPC_FC_DIV_2;
670 operator_string = "FC_DIV_2";
672 break;
673 case EXPR_MUL:
674 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
676 subexpr = subexpr->ref;
677 operator_type = RPC_FC_MULT_2;
678 operator_string = "FC_MULT_2";
680 break;
681 case EXPR_SUB:
682 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
684 subexpr = subexpr->ref;
685 operator_type = RPC_FC_SUB_1;
686 operator_string = "FC_SUB_1";
688 break;
689 case EXPR_ADD:
690 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
692 subexpr = subexpr->ref;
693 operator_type = RPC_FC_ADD_1;
694 operator_string = "FC_ADD_1";
696 break;
697 default:
698 break;
701 if (subexpr->type == EXPR_IDENTIFIER)
703 const type_t *correlation_variable = NULL;
704 unsigned char correlation_variable_type;
705 unsigned char param_type = 0;
706 size_t offset = 0;
707 const var_t *var;
709 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
711 unsigned int align = 0;
712 /* FIXME: take alignment into account */
713 if (var->name && !strcmp(var->name, subexpr->u.sval))
715 correlation_variable = var->type;
716 break;
718 offset += type_memsize(var->type, &align);
720 if (!correlation_variable)
721 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
722 subexpr->u.sval);
724 offset -= baseoff;
725 correlation_variable_type = correlation_variable->type;
727 switch (correlation_variable_type)
729 case RPC_FC_CHAR:
730 case RPC_FC_SMALL:
731 param_type = RPC_FC_SMALL;
732 break;
733 case RPC_FC_BYTE:
734 case RPC_FC_USMALL:
735 param_type = RPC_FC_USMALL;
736 break;
737 case RPC_FC_WCHAR:
738 case RPC_FC_SHORT:
739 case RPC_FC_ENUM16:
740 param_type = RPC_FC_SHORT;
741 break;
742 case RPC_FC_USHORT:
743 param_type = RPC_FC_USHORT;
744 break;
745 case RPC_FC_LONG:
746 case RPC_FC_ENUM32:
747 param_type = RPC_FC_LONG;
748 break;
749 case RPC_FC_ULONG:
750 param_type = RPC_FC_ULONG;
751 break;
752 case RPC_FC_RP:
753 case RPC_FC_UP:
754 case RPC_FC_OP:
755 case RPC_FC_FP:
756 if (sizeof(void *) == 4) /* FIXME */
757 param_type = RPC_FC_LONG;
758 else
759 param_type = RPC_FC_HYPER;
760 break;
761 default:
762 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
763 correlation_variable_type);
766 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
767 conftype | param_type, conftype_string, string_of_type(param_type));
768 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
769 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
770 offset, offset);
772 else
774 unsigned int callback_offset = 0;
775 struct expr_eval_routine *eval;
776 int found = 0;
778 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
780 if (!strcmp (eval->structure->name, structure->name)
781 && !compare_expr (eval->expr, expr))
783 found = 1;
784 break;
786 callback_offset++;
789 if (!found)
791 eval = xmalloc (sizeof(*eval));
792 eval->structure = structure;
793 eval->baseoff = baseoff;
794 eval->expr = expr;
795 list_add_tail (&expr_eval_routines, &eval->entry);
798 if (callback_offset > USHRT_MAX)
799 error("Maximum number of callback routines reached\n");
801 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
802 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
803 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
805 return 4;
808 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
810 int have_align = FALSE;
811 size_t size = 0;
812 const var_t *v;
814 if (!fields) return 0;
815 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
817 unsigned int falign = 0;
818 size_t fsize = type_memsize(v->type, &falign);
819 if (!have_align)
821 *align = falign;
822 have_align = TRUE;
824 size = (size + (falign - 1)) & ~(falign - 1);
825 size += fsize;
828 size = (size + (*align - 1)) & ~(*align - 1);
829 return size;
832 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
834 size_t size, maxs = 0;
835 unsigned int align = *pmaxa;
836 const var_t *v;
838 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
840 /* we could have an empty default field with NULL type */
841 if (v->type)
843 size = type_memsize(v->type, &align);
844 if (maxs < size) maxs = size;
845 if (*pmaxa < align) *pmaxa = align;
849 return maxs;
852 int get_padding(const var_list_t *fields)
854 unsigned short offset = 0;
855 int salign = -1;
856 const var_t *f;
858 if (!fields)
859 return 0;
861 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
863 type_t *ft = f->type;
864 unsigned int align = 0;
865 size_t size = type_memsize(ft, &align);
866 if (salign == -1)
867 salign = align;
868 offset = (offset + (align - 1)) & ~(align - 1);
869 offset += size;
872 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
875 size_t type_memsize(const type_t *t, unsigned int *align)
877 size_t size = 0;
879 if (t->declarray && is_conformant_array(t))
881 type_memsize(t->ref, align);
882 size = 0;
884 else if (is_ptr(t) || is_conformant_array(t))
886 size = sizeof(void *);
887 if (size > *align) *align = size;
889 else switch (t->type)
891 case RPC_FC_BYTE:
892 case RPC_FC_CHAR:
893 case RPC_FC_USMALL:
894 case RPC_FC_SMALL:
895 size = 1;
896 if (size > *align) *align = size;
897 break;
898 case RPC_FC_WCHAR:
899 case RPC_FC_USHORT:
900 case RPC_FC_SHORT:
901 case RPC_FC_ENUM16:
902 size = 2;
903 if (size > *align) *align = size;
904 break;
905 case RPC_FC_ULONG:
906 case RPC_FC_LONG:
907 case RPC_FC_ERROR_STATUS_T:
908 case RPC_FC_ENUM32:
909 case RPC_FC_FLOAT:
910 size = 4;
911 if (size > *align) *align = size;
912 break;
913 case RPC_FC_HYPER:
914 case RPC_FC_DOUBLE:
915 size = 8;
916 if (size > *align) *align = size;
917 break;
918 case RPC_FC_STRUCT:
919 case RPC_FC_CVSTRUCT:
920 case RPC_FC_CPSTRUCT:
921 case RPC_FC_CSTRUCT:
922 case RPC_FC_PSTRUCT:
923 case RPC_FC_BOGUS_STRUCT:
924 size = fields_memsize(t->fields, align);
925 break;
926 case RPC_FC_ENCAPSULATED_UNION:
927 case RPC_FC_NON_ENCAPSULATED_UNION:
928 size = union_memsize(t->fields, align);
929 break;
930 case RPC_FC_SMFARRAY:
931 case RPC_FC_LGFARRAY:
932 case RPC_FC_SMVARRAY:
933 case RPC_FC_LGVARRAY:
934 case RPC_FC_BOGUS_ARRAY:
935 size = t->dim * type_memsize(t->ref, align);
936 break;
937 default:
938 error("type_memsize: Unknown type %d\n", t->type);
939 size = 0;
942 return size;
945 int is_full_pointer_function(const func_t *func)
947 const var_t *var;
948 if (type_has_full_pointer(func->def->type))
949 return TRUE;
950 if (!func->args)
951 return FALSE;
952 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
953 if (type_has_full_pointer( var->type ))
954 return TRUE;
955 return FALSE;
958 void write_full_pointer_init(FILE *file, int indent, const func_t *func, int is_server)
960 print_file(file, indent, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
961 is_server ? "XLAT_SERVER" : "XLAT_CLIENT");
962 fprintf(file, "\n");
965 void write_full_pointer_free(FILE *file, int indent, const func_t *func)
967 print_file(file, indent, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
968 fprintf(file, "\n");
971 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
973 short absoff = type->ref->typestring_offset;
974 short reloff = absoff - (offset + 2);
975 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
977 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
978 type->type, ptr_attr, string_of_type(type->type));
979 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
980 reloff, reloff, absoff);
981 return 4;
984 static unsigned char conf_string_type_of_char_type(unsigned char t)
986 switch (t)
988 case RPC_FC_BYTE:
989 case RPC_FC_CHAR:
990 return RPC_FC_C_CSTRING;
991 case RPC_FC_WCHAR:
992 return RPC_FC_C_WSTRING;
995 error("string_type_of_char_type: unrecognized type %d\n", t);
996 return 0;
999 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
1001 unsigned char fc
1002 = is_string_type(type->attrs, type)
1003 ? conf_string_type_of_char_type(type->ref->type)
1004 : type->ref->type;
1005 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
1006 type->type, string_of_type(type->type));
1007 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
1008 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1009 return 4;
1012 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
1014 print_file(file, 0, "/* %u (", tfsoff);
1015 write_type_decl(file, t, NULL);
1016 print_file(file, 0, ") */\n");
1019 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
1021 unsigned int offset = *typestring_offset;
1023 print_start_tfs_comment(file, type, offset);
1024 update_tfsoff(type, offset, file);
1026 if (type->ref->typestring_offset)
1027 *typestring_offset += write_nonsimple_pointer(file, type, offset);
1028 else if (is_base_type(type->ref->type))
1029 *typestring_offset += write_simple_pointer(file, type);
1031 return offset;
1034 static int processed(const type_t *type)
1036 return type->typestring_offset && !type->tfswrite;
1039 static int user_type_has_variable_size(const type_t *t)
1041 if (is_ptr(t))
1042 return TRUE;
1043 else
1044 switch (t->type)
1046 case RPC_FC_PSTRUCT:
1047 case RPC_FC_CSTRUCT:
1048 case RPC_FC_CPSTRUCT:
1049 case RPC_FC_CVSTRUCT:
1050 return TRUE;
1052 /* Note: Since this only applies to user types, we can't have a conformant
1053 array here, and strings should get filed under pointer in this case. */
1054 return FALSE;
1057 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1059 unsigned int start, absoff, flags;
1060 unsigned int align = 0, ualign = 0;
1061 const char *name;
1062 type_t *utype = get_user_type(type, &name);
1063 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
1064 size_t size = type_memsize(type, &align);
1065 unsigned short funoff = user_type_offset(name);
1066 short reloff;
1068 guard_rec(type);
1070 if (is_base_type(utype->type))
1072 absoff = *tfsoff;
1073 print_start_tfs_comment(file, utype, absoff);
1074 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
1075 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1076 *tfsoff += 2;
1078 else
1080 if (!processed(utype))
1081 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
1082 absoff = utype->typestring_offset;
1085 if (utype->type == RPC_FC_RP)
1086 flags = 0x40;
1087 else if (utype->type == RPC_FC_UP)
1088 flags = 0x80;
1089 else
1090 flags = 0;
1092 start = *tfsoff;
1093 update_tfsoff(type, start, file);
1094 print_start_tfs_comment(file, type, start);
1095 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
1096 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1097 flags | (align - 1), align - 1, flags);
1098 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
1099 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
1100 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
1101 *tfsoff += 8;
1102 reloff = absoff - *tfsoff;
1103 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
1104 *tfsoff += 2;
1107 static void write_member_type(FILE *file, const type_t *cont,
1108 const attr_list_t *attrs, const type_t *type,
1109 unsigned int *corroff, unsigned int *tfsoff)
1111 if (is_embedded_complex(type) && !is_conformant_array(type))
1113 size_t absoff;
1114 short reloff;
1116 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1118 absoff = *corroff;
1119 *corroff += 8;
1121 else
1123 absoff = type->typestring_offset;
1125 reloff = absoff - (*tfsoff + 2);
1127 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1128 /* FIXME: actually compute necessary padding */
1129 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1130 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1131 reloff, reloff, absoff);
1132 *tfsoff += 4;
1134 else if (is_ptr(type) || is_conformant_array(type))
1136 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1137 ? RPC_FC_POINTER
1138 : RPC_FC_LONG);
1139 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1140 *tfsoff += 1;
1142 else if (!write_base_type(file, type, tfsoff))
1143 error("Unsupported member type 0x%x\n", type->type);
1146 static void write_end(FILE *file, unsigned int *tfsoff)
1148 if (*tfsoff % 2 == 0)
1150 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1151 *tfsoff += 1;
1153 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1154 *tfsoff += 1;
1157 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1159 unsigned int offset = 0;
1160 var_list_t *fs = type->fields;
1161 var_t *f;
1163 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1165 unsigned int align = 0;
1166 type_t *ft = f->type;
1167 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1169 unsigned int absoff = ft->typestring_offset;
1170 short reloff = absoff - (*tfsoff + 6);
1171 print_file(file, 0, "/* %d */\n", *tfsoff);
1172 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1173 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1174 write_conf_or_var_desc(file, current_structure, offset, ft,
1175 get_attrp(f->attrs, ATTR_SWITCHIS));
1176 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1177 reloff, reloff, absoff);
1178 *tfsoff += 8;
1181 /* FIXME: take alignment into account */
1182 offset += type_memsize(ft, &align);
1186 static int write_no_repeat_pointer_descriptions(
1187 FILE *file, type_t *type,
1188 size_t *offset_in_memory, size_t *offset_in_buffer,
1189 unsigned int *typestring_offset)
1191 int written = 0;
1192 unsigned int align;
1194 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1196 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1197 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1199 /* pointer instance */
1200 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1201 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1202 *typestring_offset += 6;
1204 if (is_ptr(type))
1205 write_pointer_tfs(file, type, typestring_offset);
1206 else
1208 unsigned absoff = type->typestring_offset;
1209 short reloff = absoff - (*typestring_offset + 2);
1210 /* FIXME: get pointer attributes from field */
1211 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1212 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1213 reloff, reloff, absoff);
1214 *typestring_offset += 4;
1217 align = 0;
1218 *offset_in_memory += type_memsize(type, &align);
1219 /* FIXME: is there a case where these two are different? */
1220 align = 0;
1221 *offset_in_buffer += type_memsize(type, &align);
1223 return 1;
1226 if (is_non_complex_struct(type))
1228 const var_t *v;
1229 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1230 written += write_no_repeat_pointer_descriptions(
1231 file, v->type,
1232 offset_in_memory, offset_in_buffer, typestring_offset);
1234 else
1236 align = 0;
1237 *offset_in_memory += type_memsize(type, &align);
1238 /* FIXME: is there a case where these two are different? */
1239 align = 0;
1240 *offset_in_buffer += type_memsize(type, &align);
1243 return written;
1246 static int write_pointer_description_offsets(
1247 FILE *file, const attr_list_t *attrs, type_t *type,
1248 size_t *offset_in_memory, size_t *offset_in_buffer,
1249 unsigned int *typestring_offset)
1251 int written = 0;
1252 unsigned int align;
1254 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1256 if (offset_in_memory && offset_in_buffer)
1258 /* pointer instance */
1259 /* FIXME: sometimes from end of structure, sometimes from beginning */
1260 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1261 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1263 align = 0;
1264 *offset_in_memory += type_memsize(type, &align);
1265 /* FIXME: is there a case where these two are different? */
1266 align = 0;
1267 *offset_in_buffer += type_memsize(type, &align);
1269 *typestring_offset += 4;
1271 if (processed(type->ref) || is_base_type(type->ref->type))
1272 write_pointer_tfs(file, type, typestring_offset);
1273 else
1274 error("write_pointer_description_offsets: type format string unknown\n");
1276 return 1;
1279 if (is_array(type))
1281 return write_pointer_description_offsets(
1282 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1283 typestring_offset);
1285 else if (is_non_complex_struct(type))
1287 /* otherwise search for interesting fields to parse */
1288 const var_t *v;
1289 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1291 written += write_pointer_description_offsets(
1292 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1293 typestring_offset);
1296 else
1298 align = 0;
1299 if (offset_in_memory)
1300 *offset_in_memory += type_memsize(type, &align);
1301 /* FIXME: is there a case where these two are different? */
1302 align = 0;
1303 if (offset_in_buffer)
1304 *offset_in_buffer += type_memsize(type, &align);
1307 return written;
1310 /* Note: if file is NULL return value is number of pointers to write, else
1311 * it is the number of type format characters written */
1312 static int write_fixed_array_pointer_descriptions(
1313 FILE *file, const attr_list_t *attrs, type_t *type,
1314 size_t *offset_in_memory, size_t *offset_in_buffer,
1315 unsigned int *typestring_offset)
1317 unsigned int align;
1318 int pointer_count = 0;
1320 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1322 unsigned int temp = 0;
1323 /* unfortunately, this needs to be done in two passes to avoid
1324 * writing out redundant FC_FIXED_REPEAT descriptions */
1325 pointer_count = write_pointer_description_offsets(
1326 NULL, attrs, type->ref, NULL, NULL, &temp);
1327 if (pointer_count > 0)
1329 unsigned int increment_size;
1330 size_t offset_of_array_pointer_mem = 0;
1331 size_t offset_of_array_pointer_buf = 0;
1333 align = 0;
1334 increment_size = type_memsize(type->ref, &align);
1336 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1337 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1338 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1339 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1340 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1341 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1342 *typestring_offset += 10;
1344 pointer_count = write_pointer_description_offsets(
1345 file, attrs, type, &offset_of_array_pointer_mem,
1346 &offset_of_array_pointer_buf, typestring_offset);
1349 else if (is_struct(type->type))
1351 const var_t *v;
1352 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1354 pointer_count += write_fixed_array_pointer_descriptions(
1355 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1356 typestring_offset);
1359 else
1361 align = 0;
1362 if (offset_in_memory)
1363 *offset_in_memory += type_memsize(type, &align);
1364 /* FIXME: is there a case where these two are different? */
1365 align = 0;
1366 if (offset_in_buffer)
1367 *offset_in_buffer += type_memsize(type, &align);
1370 return pointer_count;
1373 /* Note: if file is NULL return value is number of pointers to write, else
1374 * it is the number of type format characters written */
1375 static int write_conformant_array_pointer_descriptions(
1376 FILE *file, const attr_list_t *attrs, type_t *type,
1377 size_t offset_in_memory, unsigned int *typestring_offset)
1379 unsigned int align;
1380 int pointer_count = 0;
1382 if (is_conformant_array(type) && !type->length_is)
1384 unsigned int temp = 0;
1385 /* unfortunately, this needs to be done in two passes to avoid
1386 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1387 pointer_count = write_pointer_description_offsets(
1388 NULL, attrs, type->ref, NULL, NULL, &temp);
1389 if (pointer_count > 0)
1391 unsigned int increment_size;
1392 size_t offset_of_array_pointer_mem = offset_in_memory;
1393 size_t offset_of_array_pointer_buf = offset_in_memory;
1395 align = 0;
1396 increment_size = type_memsize(type->ref, &align);
1398 if (increment_size > USHRT_MAX)
1399 error("array size of %u bytes is too large\n", increment_size);
1401 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1402 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1403 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1404 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1405 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1406 *typestring_offset += 8;
1408 pointer_count = write_pointer_description_offsets(
1409 file, attrs, type->ref, &offset_of_array_pointer_mem,
1410 &offset_of_array_pointer_buf, typestring_offset);
1414 return pointer_count;
1417 /* Note: if file is NULL return value is number of pointers to write, else
1418 * it is the number of type format characters written */
1419 static int write_varying_array_pointer_descriptions(
1420 FILE *file, const attr_list_t *attrs, type_t *type,
1421 size_t *offset_in_memory, size_t *offset_in_buffer,
1422 unsigned int *typestring_offset)
1424 unsigned int align;
1425 int pointer_count = 0;
1427 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1429 if (is_array(type) && type->length_is)
1431 unsigned int temp = 0;
1432 /* unfortunately, this needs to be done in two passes to avoid
1433 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1434 pointer_count = write_pointer_description_offsets(
1435 NULL, attrs, type->ref, NULL, NULL, &temp);
1436 if (pointer_count > 0)
1438 unsigned int increment_size;
1439 size_t offset_of_array_pointer_mem = 0;
1440 size_t offset_of_array_pointer_buf = 0;
1442 align = 0;
1443 increment_size = type_memsize(type->ref, &align);
1445 if (increment_size > USHRT_MAX)
1446 error("array size of %u bytes is too large\n", increment_size);
1448 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1449 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1450 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1451 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1452 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1453 *typestring_offset += 8;
1455 pointer_count = write_pointer_description_offsets(
1456 file, attrs, type, &offset_of_array_pointer_mem,
1457 &offset_of_array_pointer_buf, typestring_offset);
1460 else if (is_struct(type->type))
1462 const var_t *v;
1463 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1465 pointer_count += write_varying_array_pointer_descriptions(
1466 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1467 typestring_offset);
1470 else
1472 align = 0;
1473 if (offset_in_memory)
1474 *offset_in_memory += type_memsize(type, &align);
1475 /* FIXME: is there a case where these two are different? */
1476 align = 0;
1477 if (offset_in_buffer)
1478 *offset_in_buffer += type_memsize(type, &align);
1481 return pointer_count;
1484 static void write_pointer_description(FILE *file, type_t *type,
1485 unsigned int *typestring_offset)
1487 size_t offset_in_buffer;
1488 size_t offset_in_memory;
1490 /* pass 1: search for single instance of a pointer (i.e. don't descend
1491 * into arrays) */
1492 if (!is_array(type))
1494 offset_in_memory = 0;
1495 offset_in_buffer = 0;
1496 write_no_repeat_pointer_descriptions(
1497 file, type,
1498 &offset_in_memory, &offset_in_buffer, typestring_offset);
1501 /* pass 2: search for pointers in fixed arrays */
1502 offset_in_memory = 0;
1503 offset_in_buffer = 0;
1504 write_fixed_array_pointer_descriptions(
1505 file, NULL, type,
1506 &offset_in_memory, &offset_in_buffer, typestring_offset);
1508 /* pass 3: search for pointers in conformant only arrays (but don't descend
1509 * into conformant varying or varying arrays) */
1510 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1511 write_conformant_array_pointer_descriptions(
1512 file, NULL, type, 0, typestring_offset);
1513 else if (type->type == RPC_FC_CPSTRUCT)
1515 unsigned int align = 0;
1516 type_t *carray = find_array_or_string_in_struct(type)->type;
1517 write_conformant_array_pointer_descriptions(
1518 file, NULL, carray,
1519 type_memsize(type, &align),
1520 typestring_offset);
1523 /* pass 4: search for pointers in varying arrays */
1524 offset_in_memory = 0;
1525 offset_in_buffer = 0;
1526 write_varying_array_pointer_descriptions(
1527 file, NULL, type,
1528 &offset_in_memory, &offset_in_buffer, typestring_offset);
1531 int is_declptr(const type_t *t)
1533 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1536 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1537 type_t *type,
1538 const char *name, unsigned int *typestring_offset,
1539 int toplevel)
1541 size_t start_offset;
1542 unsigned char rtype;
1544 if (toplevel && is_declptr(type))
1546 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1547 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1548 if (!pointer_type)
1549 pointer_type = RPC_FC_RP;
1550 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1551 pointer_type, flag, string_of_type(pointer_type),
1552 flag ? " [simple_pointer]" : "");
1553 *typestring_offset += 2;
1554 if (!flag)
1556 print_file(file, 2, "NdrFcShort(0x2),\n");
1557 *typestring_offset += 2;
1561 start_offset = *typestring_offset;
1562 update_tfsoff(type, start_offset, file);
1564 rtype = type->ref->type;
1566 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1568 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1569 return start_offset;
1572 if (type->declarray && !is_conformant_array(type))
1574 /* FIXME: multi-dimensional array */
1575 if (0xffffuL < type->dim)
1576 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1577 name, 0xffffu, type->dim - 0xffffu);
1579 if (rtype == RPC_FC_CHAR)
1580 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1581 else
1582 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1583 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1584 *typestring_offset += 2;
1586 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1587 *typestring_offset += 2;
1589 return start_offset;
1591 else if (type->size_is)
1593 unsigned int align = 0;
1595 if (rtype == RPC_FC_CHAR)
1596 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1597 else
1598 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1599 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1600 *typestring_offset += 2;
1602 *typestring_offset += write_conf_or_var_desc(
1603 file, current_structure,
1604 (type->declarray && current_structure
1605 ? type_memsize(current_structure, &align)
1606 : 0),
1607 type, type->size_is);
1609 return start_offset;
1611 else
1613 if (rtype == RPC_FC_WCHAR)
1614 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1615 else
1616 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1617 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1618 *typestring_offset += 2;
1620 return start_offset;
1624 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1625 const char *name, unsigned int *typestring_offset)
1627 const expr_t *length_is = type->length_is;
1628 const expr_t *size_is = type->size_is;
1629 unsigned int align = 0;
1630 size_t size;
1631 size_t start_offset;
1632 int has_pointer;
1633 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1634 unsigned int baseoff
1635 = type->declarray && current_structure
1636 ? type_memsize(current_structure, &align)
1637 : 0;
1639 if (!pointer_type)
1640 pointer_type = RPC_FC_RP;
1642 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1643 has_pointer = TRUE;
1644 else
1645 has_pointer = type_has_pointers(type->ref);
1647 align = 0;
1648 size = type_memsize((is_conformant_array(type) ? type->ref : type), &align);
1650 start_offset = *typestring_offset;
1651 update_tfsoff(type, start_offset, file);
1652 print_start_tfs_comment(file, type, start_offset);
1653 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1654 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1655 *typestring_offset += 2;
1657 align = 0;
1658 if (type->type != RPC_FC_BOGUS_ARRAY)
1660 unsigned char tc = type->type;
1662 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1664 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1665 *typestring_offset += 4;
1667 else
1669 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1670 *typestring_offset += 2;
1673 if (is_conformant_array(type))
1674 *typestring_offset
1675 += write_conf_or_var_desc(file, current_structure, baseoff,
1676 type, size_is);
1678 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1680 unsigned int elalign = 0;
1681 size_t elsize = type_memsize(type->ref, &elalign);
1683 if (type->type == RPC_FC_LGVARRAY)
1685 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1686 *typestring_offset += 4;
1688 else
1690 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1691 *typestring_offset += 2;
1694 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1695 *typestring_offset += 2;
1698 if (length_is)
1699 *typestring_offset
1700 += write_conf_or_var_desc(file, current_structure, baseoff,
1701 type, length_is);
1703 if (has_pointer && (!type->declarray || !current_structure))
1705 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1706 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1707 *typestring_offset += 2;
1708 write_pointer_description(file, type, typestring_offset);
1709 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1710 *typestring_offset += 1;
1713 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1714 write_end(file, typestring_offset);
1716 else
1718 unsigned int dim = size_is ? 0 : type->dim;
1719 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1720 *typestring_offset += 2;
1721 *typestring_offset
1722 += write_conf_or_var_desc(file, current_structure, baseoff,
1723 type, size_is);
1724 *typestring_offset
1725 += write_conf_or_var_desc(file, current_structure, baseoff,
1726 type, length_is);
1727 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1728 write_end(file, typestring_offset);
1731 return start_offset;
1734 static const var_t *find_array_or_string_in_struct(const type_t *type)
1736 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1737 const type_t *ft = last_field->type;
1739 if (ft->declarray && is_conformant_array(ft))
1740 return last_field;
1742 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1743 return find_array_or_string_in_struct(last_field->type);
1744 else
1745 return NULL;
1748 static void write_struct_members(FILE *file, const type_t *type,
1749 unsigned int *corroff, unsigned int *typestring_offset)
1751 const var_t *field;
1752 unsigned short offset = 0;
1753 int salign = -1;
1754 int padding;
1756 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1758 type_t *ft = field->type;
1759 if (!ft->declarray || !is_conformant_array(ft))
1761 unsigned int align = 0;
1762 size_t size = type_memsize(ft, &align);
1763 if (salign == -1)
1764 salign = align;
1765 if ((align - 1) & offset)
1767 unsigned char fc = 0;
1768 switch (align)
1770 case 4:
1771 fc = RPC_FC_ALIGNM4;
1772 break;
1773 case 8:
1774 fc = RPC_FC_ALIGNM8;
1775 break;
1776 default:
1777 error("write_struct_members: cannot align type %d\n", ft->type);
1779 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1780 offset = (offset + (align - 1)) & ~(align - 1);
1781 *typestring_offset += 1;
1783 write_member_type(file, type, field->attrs, field->type, corroff,
1784 typestring_offset);
1785 offset += size;
1789 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1790 if (padding)
1792 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1793 RPC_FC_STRUCTPAD1 + padding - 1,
1794 padding);
1795 *typestring_offset += 1;
1798 write_end(file, typestring_offset);
1801 static size_t write_struct_tfs(FILE *file, type_t *type,
1802 const char *name, unsigned int *tfsoff)
1804 const type_t *save_current_structure = current_structure;
1805 unsigned int total_size;
1806 const var_t *array;
1807 size_t start_offset;
1808 size_t array_offset;
1809 int has_pointers = 0;
1810 unsigned int align = 0;
1811 unsigned int corroff;
1812 var_t *f;
1814 guard_rec(type);
1815 current_structure = type;
1817 total_size = type_memsize(type, &align);
1818 if (total_size > USHRT_MAX)
1819 error("structure size for %s exceeds %d bytes by %d bytes\n",
1820 name, USHRT_MAX, total_size - USHRT_MAX);
1822 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1823 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1824 FALSE, tfsoff);
1825 if (!has_pointers) has_pointers = type_has_pointers(type);
1827 array = find_array_or_string_in_struct(type);
1828 if (array && !processed(array->type))
1829 array_offset
1830 = is_attr(array->attrs, ATTR_STRING)
1831 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff, FALSE)
1832 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1834 corroff = *tfsoff;
1835 write_descriptors(file, type, tfsoff);
1837 start_offset = *tfsoff;
1838 update_tfsoff(type, start_offset, file);
1839 print_start_tfs_comment(file, type, start_offset);
1840 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1841 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1842 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1843 *tfsoff += 4;
1845 if (array)
1847 unsigned int absoff = array->type->typestring_offset;
1848 short reloff = absoff - *tfsoff;
1849 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1850 reloff, reloff, absoff);
1851 *tfsoff += 2;
1853 else if (type->type == RPC_FC_BOGUS_STRUCT)
1855 print_file(file, 2, "NdrFcShort(0x0),\n");
1856 *tfsoff += 2;
1859 if (type->type == RPC_FC_BOGUS_STRUCT)
1861 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1862 nothing is written to file yet. On the actual writing pass,
1863 this will have been updated. */
1864 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1865 short reloff = absoff - *tfsoff;
1866 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1867 reloff, reloff, absoff);
1868 *tfsoff += 2;
1870 else if ((type->type == RPC_FC_PSTRUCT) ||
1871 (type->type == RPC_FC_CPSTRUCT) ||
1872 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1874 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1875 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1876 *tfsoff += 2;
1877 write_pointer_description(file, type, tfsoff);
1878 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1879 *tfsoff += 1;
1882 write_struct_members(file, type, &corroff, tfsoff);
1884 if (type->type == RPC_FC_BOGUS_STRUCT)
1886 const var_list_t *fs = type->fields;
1887 const var_t *f;
1889 type->ptrdesc = *tfsoff;
1890 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1892 type_t *ft = f->type;
1893 if (is_ptr(ft))
1894 write_pointer_tfs(file, ft, tfsoff);
1895 else if (!ft->declarray && is_conformant_array(ft))
1897 unsigned int absoff = ft->typestring_offset;
1898 short reloff = absoff - (*tfsoff + 2);
1899 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1900 /* FIXME: We need to store pointer attributes for arrays
1901 so we don't lose pointer_default info. */
1902 if (ptr_type == 0)
1903 ptr_type = RPC_FC_UP;
1904 print_file(file, 0, "/* %d */\n", *tfsoff);
1905 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1906 string_of_type(ptr_type));
1907 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1908 reloff, reloff, absoff);
1909 *tfsoff += 4;
1912 if (type->ptrdesc == *tfsoff)
1913 type->ptrdesc = 0;
1916 current_structure = save_current_structure;
1917 return start_offset;
1920 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1921 unsigned char flags, size_t offset,
1922 unsigned int *typeformat_offset)
1924 size_t start_offset = *typeformat_offset;
1925 short reloff = offset - (*typeformat_offset + 2);
1926 int in_attr, out_attr;
1927 in_attr = is_attr(attrs, ATTR_IN);
1928 out_attr = is_attr(attrs, ATTR_OUT);
1929 if (!in_attr && !out_attr) in_attr = 1;
1931 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1932 flags |= 0x04;
1934 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1935 pointer_type,
1936 flags,
1937 string_of_type(pointer_type));
1938 if (file)
1940 if (flags & 0x04)
1941 fprintf(file, " [allocated_on_stack]");
1942 if (flags & 0x10)
1943 fprintf(file, " [pointer_deref]");
1944 fprintf(file, " */\n");
1947 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1948 *typeformat_offset += 4;
1950 return start_offset;
1953 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1955 if (t == NULL)
1957 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1959 else if (is_base_type(t->type))
1961 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1962 t->type, string_of_type(t->type));
1964 else if (t->typestring_offset)
1966 short reloff = t->typestring_offset - *tfsoff;
1967 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1968 reloff, reloff, t->typestring_offset);
1970 else
1971 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1973 *tfsoff += 2;
1976 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1978 unsigned int align = 0;
1979 unsigned int start_offset;
1980 size_t size = type_memsize(type, &align);
1981 var_list_t *fields;
1982 size_t nbranch = 0;
1983 type_t *deftype = NULL;
1984 short nodeftype = 0xffff;
1985 var_t *f;
1987 guard_rec(type);
1989 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1991 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1992 fields = uv->type->fields;
1994 else
1995 fields = type->fields;
1997 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1999 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
2000 if (cases)
2001 nbranch += list_count(cases);
2002 if (f->type)
2003 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
2006 start_offset = *tfsoff;
2007 update_tfsoff(type, start_offset, file);
2008 print_start_tfs_comment(file, type, start_offset);
2009 if (type->type == RPC_FC_ENCAPSULATED_UNION)
2011 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
2012 const type_t *st = sv->type;
2014 switch (st->type)
2016 case RPC_FC_CHAR:
2017 case RPC_FC_SMALL:
2018 case RPC_FC_USMALL:
2019 case RPC_FC_SHORT:
2020 case RPC_FC_USHORT:
2021 case RPC_FC_LONG:
2022 case RPC_FC_ULONG:
2023 case RPC_FC_ENUM16:
2024 case RPC_FC_ENUM32:
2025 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
2026 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
2027 0x40 | st->type, string_of_type(st->type));
2028 *tfsoff += 2;
2029 break;
2030 default:
2031 error("union switch type must be an integer, char, or enum\n");
2034 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
2035 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
2036 *tfsoff += 4;
2038 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
2040 type_t *ft = f->type;
2041 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
2042 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
2043 expr_t *c;
2045 if (cases == NULL && !deflt)
2046 error("union field %s with neither case nor default attribute\n", f->name);
2048 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
2050 /* MIDL doesn't check for duplicate cases, even though that seems
2051 like a reasonable thing to do, it just dumps them to the TFS
2052 like we're going to do here. */
2053 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
2054 *tfsoff += 4;
2055 write_branch_type(file, ft, tfsoff);
2058 /* MIDL allows multiple default branches, even though that seems
2059 illogical, it just chooses the last one, which is what we will
2060 do. */
2061 if (deflt)
2063 deftype = ft;
2064 nodeftype = 0;
2068 if (deftype)
2070 write_branch_type(file, deftype, tfsoff);
2072 else
2074 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
2075 *tfsoff += 2;
2078 return start_offset;
2081 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2082 unsigned int *typeformat_offset)
2084 size_t i;
2085 size_t start_offset = *typeformat_offset;
2086 expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
2088 if (iid)
2090 print_file(file, 2, "0x2f, /* FC_IP */\n");
2091 print_file(file, 2, "0x5c, /* FC_PAD */\n");
2092 *typeformat_offset
2093 += write_conf_or_var_desc(file, NULL, 0, type, iid) + 2;
2095 else
2097 const type_t *base = is_ptr(type) ? type->ref : type;
2098 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
2100 if (! uuid)
2101 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
2103 update_tfsoff(type, start_offset, file);
2104 print_start_tfs_comment(file, type, start_offset);
2105 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2106 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2107 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2108 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2109 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2110 for (i = 0; i < 8; ++i)
2111 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2113 if (file)
2114 fprintf(file, "\n");
2116 *typeformat_offset += 18;
2118 return start_offset;
2121 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2122 const var_t *var,
2123 unsigned int *typeformat_offset)
2125 size_t start_offset = *typeformat_offset;
2126 unsigned char flags = 0;
2128 if (is_attr(current_iface->attrs, ATTR_STRICTCONTEXTHANDLE))
2129 flags |= NDR_STRICT_CONTEXT_HANDLE;
2131 if (is_ptr(type))
2132 flags |= 0x80;
2133 if (is_attr(var->attrs, ATTR_IN))
2135 flags |= 0x40;
2136 if (!is_attr(var->attrs, ATTR_OUT))
2137 flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
2139 if (is_attr(var->attrs, ATTR_OUT))
2140 flags |= 0x20;
2142 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2143 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2144 /* return and can't be null values overlap */
2145 if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
2146 print_file(file, 0, "can't be null, ");
2147 if (flags & NDR_CONTEXT_HANDLE_SERIALIZE)
2148 print_file(file, 0, "serialize, ");
2149 if (flags & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
2150 print_file(file, 0, "no serialize, ");
2151 if (flags & NDR_STRICT_CONTEXT_HANDLE)
2152 print_file(file, 0, "strict, ");
2153 if ((flags & 0x21) == 0x20)
2154 print_file(file, 0, "out, ");
2155 if ((flags & 0x21) == 0x21)
2156 print_file(file, 0, "return, ");
2157 if (flags & 0x40)
2158 print_file(file, 0, "in, ");
2159 if (flags & 0x80)
2160 print_file(file, 0, "via ptr, ");
2161 print_file(file, 0, "*/\n");
2162 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2163 print_file(file, 2, "0, /* FIXME: param num */\n");
2164 *typeformat_offset += 4;
2166 return start_offset;
2169 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2170 type_t *type, const var_t *var,
2171 unsigned int *typeformat_offset)
2173 size_t offset;
2175 if (is_context_handle(type))
2176 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2178 if (is_user_type(type))
2180 write_user_tfs(file, type, typeformat_offset);
2181 return type->typestring_offset;
2184 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2185 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset, TRUE);
2187 if (is_array(type))
2189 int ptr_type;
2190 size_t off;
2191 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2192 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2193 /* Top level pointers to conformant arrays may be handled specially
2194 since we can bypass the pointer, but if the array is buried
2195 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2196 always need to write the pointer. */
2197 if (!ptr_type && var->type != type)
2198 /* FIXME: This should use pointer_default, but the information
2199 isn't kept around for arrays. */
2200 ptr_type = RPC_FC_UP;
2201 if (ptr_type && ptr_type != RPC_FC_RP)
2203 unsigned int absoff = type->typestring_offset;
2204 short reloff = absoff - (*typeformat_offset + 2);
2205 off = *typeformat_offset;
2206 print_file(file, 0, "/* %d */\n", off);
2207 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2208 string_of_type(ptr_type));
2209 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2210 reloff, reloff, absoff);
2211 *typeformat_offset += 4;
2213 return off;
2216 if (!is_ptr(type))
2218 /* basic types don't need a type format string */
2219 if (is_base_type(type->type))
2220 return 0;
2222 switch (type->type)
2224 case RPC_FC_STRUCT:
2225 case RPC_FC_PSTRUCT:
2226 case RPC_FC_CSTRUCT:
2227 case RPC_FC_CPSTRUCT:
2228 case RPC_FC_CVSTRUCT:
2229 case RPC_FC_BOGUS_STRUCT:
2230 return write_struct_tfs(file, type, var->name, typeformat_offset);
2231 case RPC_FC_ENCAPSULATED_UNION:
2232 case RPC_FC_NON_ENCAPSULATED_UNION:
2233 return write_union_tfs(file, type, typeformat_offset);
2234 case RPC_FC_IGNORE:
2235 case RPC_FC_BIND_PRIMITIVE:
2236 /* nothing to do */
2237 return 0;
2238 default:
2239 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2242 else if (last_ptr(type))
2244 size_t start_offset = *typeformat_offset;
2245 int in_attr = is_attr(var->attrs, ATTR_IN);
2246 int out_attr = is_attr(var->attrs, ATTR_OUT);
2247 const type_t *base = type->ref;
2249 if (base->type == RPC_FC_IP
2250 || (base->type == 0
2251 && is_attr(var->attrs, ATTR_IIDIS)))
2253 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2256 /* special case for pointers to base types */
2257 if (is_base_type(base->type))
2259 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2260 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2261 string_of_type(type->type),
2262 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2263 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2264 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2265 *typeformat_offset += 4;
2266 return start_offset;
2270 assert(is_ptr(type));
2272 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2273 if (file)
2274 fprintf(file, "/* %2u */\n", *typeformat_offset);
2275 return write_pointer_only_tfs(file, var->attrs, type->type,
2276 !last_ptr(type) ? 0x10 : 0,
2277 offset, typeformat_offset);
2280 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2281 const char *name, int write_ptr, unsigned int *tfsoff)
2283 int retmask = 0;
2285 if (is_user_type(type))
2287 write_user_tfs(file, type, tfsoff);
2289 else if (is_ptr(type))
2291 type_t *ref = type->ref;
2293 if (ref->type == RPC_FC_IP
2294 || (ref->type == 0
2295 && is_attr(attrs, ATTR_IIDIS)))
2297 write_ip_tfs(file, attrs, type, tfsoff);
2299 else
2301 if (!processed(ref) && !is_base_type(ref->type))
2302 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2304 if (write_ptr)
2305 write_pointer_tfs(file, type, tfsoff);
2307 retmask |= 1;
2310 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2312 write_string_tfs(file, attrs, type, name, tfsoff, FALSE);
2314 else if (type->declarray && is_conformant_array(type))
2315 ; /* conformant arrays and strings are handled specially */
2316 else if (is_array(type))
2318 write_array_tfs(file, attrs, type, name, tfsoff);
2319 if (is_conformant_array(type))
2320 retmask |= 1;
2322 else if (is_struct(type->type))
2324 if (!processed(type))
2325 write_struct_tfs(file, type, name, tfsoff);
2327 else if (is_union(type->type))
2329 if (!processed(type))
2330 write_union_tfs(file, type, tfsoff);
2332 else if (!is_base_type(type->type))
2333 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2334 name, type->type);
2336 return retmask;
2339 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2341 const var_t *var;
2342 const ifref_t *iface;
2343 unsigned int typeformat_offset = 2;
2345 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2347 if (!pred(iface->iface))
2348 continue;
2350 if (iface->iface->funcs)
2352 const func_t *func;
2353 current_iface = iface;
2354 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2356 if (is_local(func->def->attrs)) continue;
2358 current_func = func;
2359 if (func->args)
2360 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2361 update_tfsoff(
2362 var->type,
2363 write_typeformatstring_var(
2364 file, 2, func, var->type, var,
2365 &typeformat_offset),
2366 file);
2371 return typeformat_offset + 1;
2375 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2377 int indent = 0;
2379 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2380 print_file(file, indent, "{\n");
2381 indent++;
2382 print_file(file, indent, "0,\n");
2383 print_file(file, indent, "{\n");
2384 indent++;
2385 print_file(file, indent, "NdrFcShort(0x0),\n");
2387 set_all_tfswrite(TRUE);
2388 process_tfs(file, ifaces, pred);
2390 print_file(file, indent, "0x0\n");
2391 indent--;
2392 print_file(file, indent, "}\n");
2393 indent--;
2394 print_file(file, indent, "};\n");
2395 print_file(file, indent, "\n");
2398 static unsigned int get_required_buffer_size_type(
2399 const type_t *type, const char *name, unsigned int *alignment)
2401 *alignment = 0;
2402 if (is_user_type(type))
2404 const char *uname;
2405 const type_t *utype = get_user_type(type, &uname);
2406 return get_required_buffer_size_type(utype, uname, alignment);
2408 else
2410 switch (type->type)
2412 case RPC_FC_BYTE:
2413 case RPC_FC_CHAR:
2414 case RPC_FC_USMALL:
2415 case RPC_FC_SMALL:
2416 *alignment = 4;
2417 return 1;
2419 case RPC_FC_WCHAR:
2420 case RPC_FC_USHORT:
2421 case RPC_FC_SHORT:
2422 case RPC_FC_ENUM16:
2423 *alignment = 4;
2424 return 2;
2426 case RPC_FC_ULONG:
2427 case RPC_FC_LONG:
2428 case RPC_FC_ENUM32:
2429 case RPC_FC_FLOAT:
2430 case RPC_FC_ERROR_STATUS_T:
2431 *alignment = 4;
2432 return 4;
2434 case RPC_FC_HYPER:
2435 case RPC_FC_DOUBLE:
2436 *alignment = 8;
2437 return 8;
2439 case RPC_FC_IGNORE:
2440 case RPC_FC_BIND_PRIMITIVE:
2441 return 0;
2443 case RPC_FC_STRUCT:
2444 case RPC_FC_PSTRUCT:
2446 size_t size = 0;
2447 const var_t *field;
2448 if (!type->fields) return 0;
2449 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2451 unsigned int alignment;
2452 size += get_required_buffer_size_type(field->type, field->name,
2453 &alignment);
2455 return size;
2458 case RPC_FC_RP:
2459 return
2460 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2461 ? get_required_buffer_size_type( type->ref, name, alignment )
2462 : 0;
2464 case RPC_FC_SMFARRAY:
2465 case RPC_FC_LGFARRAY:
2466 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2468 default:
2469 return 0;
2474 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2476 int in_attr = is_attr(var->attrs, ATTR_IN);
2477 int out_attr = is_attr(var->attrs, ATTR_OUT);
2478 const type_t *t;
2480 if (!in_attr && !out_attr)
2481 in_attr = 1;
2483 *alignment = 0;
2485 for (t = var->type; is_ptr(t); t = t->ref)
2486 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2488 *alignment = 4;
2489 return 20;
2492 if (pass == PASS_OUT)
2494 if (out_attr && is_ptr(var->type))
2496 type_t *type = var->type;
2498 if (type->type == RPC_FC_STRUCT)
2500 const var_t *field;
2501 unsigned int size = 36;
2503 if (!type->fields) return size;
2504 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2506 unsigned int align;
2507 size += get_required_buffer_size_type(
2508 field->type, field->name, &align);
2510 return size;
2513 return 0;
2515 else
2517 if ((!out_attr || in_attr) && !var->type->size_is
2518 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2520 if (is_ptr(var->type))
2522 type_t *type = var->type;
2524 if (is_base_type(type->type))
2526 return 25;
2528 else if (type->type == RPC_FC_STRUCT)
2530 unsigned int size = 36;
2531 const var_t *field;
2533 if (!type->fields) return size;
2534 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2536 unsigned int align;
2537 size += get_required_buffer_size_type(
2538 field->type, field->name, &align);
2540 return size;
2545 return get_required_buffer_size_type(var->type, var->name, alignment);
2549 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2551 const var_t *var;
2552 unsigned int total_size = 0, alignment;
2554 if (func->args)
2556 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2558 total_size += get_required_buffer_size(var, &alignment, pass);
2559 total_size += alignment;
2563 if (pass == PASS_OUT && !is_void(func->def->type))
2565 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2566 total_size += alignment;
2568 return total_size;
2571 static void print_phase_function(FILE *file, int indent, const char *type,
2572 enum remoting_phase phase,
2573 const var_t *var, unsigned int type_offset)
2575 const char *function;
2576 switch (phase)
2578 case PHASE_BUFFERSIZE:
2579 function = "BufferSize";
2580 break;
2581 case PHASE_MARSHAL:
2582 function = "Marshall";
2583 break;
2584 case PHASE_UNMARSHAL:
2585 function = "Unmarshall";
2586 break;
2587 case PHASE_FREE:
2588 function = "Free";
2589 break;
2590 default:
2591 assert(0);
2592 return;
2595 print_file(file, indent, "Ndr%s%s(\n", type, function);
2596 indent++;
2597 print_file(file, indent, "&_StubMsg,\n");
2598 print_file(file, indent, "%s%s%s%s,\n",
2599 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2600 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2601 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2602 var->name);
2603 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2604 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2605 if (phase == PHASE_UNMARSHAL)
2606 print_file(file, indent, "0);\n");
2607 indent--;
2610 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2611 enum pass pass, const var_t *var,
2612 const char *varname)
2614 type_t *type = var->type;
2615 unsigned int size;
2616 unsigned int alignment = 0;
2617 unsigned char rtype;
2619 /* no work to do for other phases, buffer sizing is done elsewhere */
2620 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2621 return;
2623 rtype = is_ptr(type) ? type->ref->type : type->type;
2625 switch (rtype)
2627 case RPC_FC_BYTE:
2628 case RPC_FC_CHAR:
2629 case RPC_FC_SMALL:
2630 case RPC_FC_USMALL:
2631 size = 1;
2632 alignment = 1;
2633 break;
2635 case RPC_FC_WCHAR:
2636 case RPC_FC_USHORT:
2637 case RPC_FC_SHORT:
2638 case RPC_FC_ENUM16:
2639 size = 2;
2640 alignment = 2;
2641 break;
2643 case RPC_FC_ULONG:
2644 case RPC_FC_LONG:
2645 case RPC_FC_ENUM32:
2646 case RPC_FC_FLOAT:
2647 case RPC_FC_ERROR_STATUS_T:
2648 size = 4;
2649 alignment = 4;
2650 break;
2652 case RPC_FC_HYPER:
2653 case RPC_FC_DOUBLE:
2654 size = 8;
2655 alignment = 8;
2656 break;
2658 case RPC_FC_IGNORE:
2659 case RPC_FC_BIND_PRIMITIVE:
2660 /* no marshalling needed */
2661 return;
2663 default:
2664 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2665 size = 0;
2668 if (phase == PHASE_MARSHAL)
2669 print_file(file, indent, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
2670 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2671 alignment - 1, alignment - 1);
2673 if (phase == PHASE_MARSHAL)
2675 print_file(file, indent, "*(");
2676 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2677 if (is_ptr(type))
2678 fprintf(file, " *)_StubMsg.Buffer = *");
2679 else
2680 fprintf(file, " *)_StubMsg.Buffer = ");
2681 fprintf(file, "%s", varname);
2682 fprintf(file, ";\n");
2684 else if (phase == PHASE_UNMARSHAL)
2686 print_file(file, indent, "if (_StubMsg.Buffer + sizeof(");
2687 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2688 fprintf(file, ") > _StubMsg.BufferEnd)\n");
2689 print_file(file, indent, "{\n");
2690 print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2691 print_file(file, indent, "}\n");
2692 if (pass == PASS_IN || pass == PASS_RETURN)
2693 print_file(file, indent, "");
2694 else
2695 print_file(file, indent, "*");
2696 fprintf(file, "%s", varname);
2697 if (pass == PASS_IN && is_ptr(type))
2698 fprintf(file, " = (");
2699 else
2700 fprintf(file, " = *(");
2701 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2702 fprintf(file, " *)_StubMsg.Buffer;\n");
2705 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2706 write_type_decl(file, var->type, NULL);
2707 fprintf(file, ");\n");
2710 /* returns whether the MaxCount, Offset or ActualCount members need to be
2711 * filled in for the specified phase */
2712 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2714 return (phase != PHASE_UNMARSHAL);
2717 expr_t *get_size_is_expr(const type_t *t, const char *name)
2719 expr_t *x = NULL;
2721 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2722 if (t->size_is)
2724 if (!x)
2725 x = t->size_is;
2726 else
2727 error("%s: multidimensional conformant"
2728 " arrays not supported at the top level\n",
2729 name);
2732 return x;
2735 static void write_remoting_arg(FILE *file, int indent, const func_t *func,
2736 enum pass pass, enum remoting_phase phase,
2737 const var_t *var)
2739 int in_attr, out_attr, pointer_type;
2740 const type_t *type = var->type;
2741 unsigned char rtype;
2742 size_t start_offset = type->typestring_offset;
2744 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2745 if (!pointer_type)
2746 pointer_type = RPC_FC_RP;
2748 in_attr = is_attr(var->attrs, ATTR_IN);
2749 out_attr = is_attr(var->attrs, ATTR_OUT);
2750 if (!in_attr && !out_attr)
2751 in_attr = 1;
2753 if (phase != PHASE_FREE)
2754 switch (pass)
2756 case PASS_IN:
2757 if (!in_attr) return;
2758 break;
2759 case PASS_OUT:
2760 if (!out_attr) return;
2761 break;
2762 case PASS_RETURN:
2763 break;
2766 rtype = type->type;
2768 if (is_context_handle(type))
2770 if (phase == PHASE_MARSHAL)
2772 if (pass == PASS_IN)
2774 print_file(file, indent, "NdrClientContextMarshall(\n");
2775 print_file(file, indent + 1, "&_StubMsg,\n");
2776 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2777 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2779 else
2781 print_file(file, indent, "NdrServerContextNewMarshall(\n");
2782 print_file(file, indent + 1, "&_StubMsg,\n");
2783 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2784 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type));
2785 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
2788 else if (phase == PHASE_UNMARSHAL)
2790 if (pass == PASS_OUT)
2792 if (!in_attr)
2793 print_file(file, indent, "*%s = 0;\n", var->name);
2794 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2795 print_file(file, indent + 1, "&_StubMsg,\n");
2796 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2797 print_file(file, indent + 1, "_Handle);\n");
2799 else
2801 print_file(file, indent, "%s = NdrServerContextNewUnmarshall(\n", var->name);
2802 print_file(file, indent + 1, "&_StubMsg,\n");
2803 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
2807 else if (is_user_type(var->type))
2809 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2811 else if (is_string_type(var->attrs, var->type))
2813 if (is_array(type) && !is_conformant_array(type))
2814 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2815 else
2817 if (type->size_is && is_size_needed_for_phase(phase))
2819 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2820 write_expr(file, type->size_is, 1);
2821 fprintf(file, ";\n");
2824 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2825 print_phase_function(file, indent, "Pointer", phase, var,
2826 start_offset - (type->size_is ? 4 : 2));
2827 else
2828 print_phase_function(file, indent, "ConformantString", phase, var,
2829 start_offset);
2832 else if (is_array(type))
2834 unsigned char tc = type->type;
2835 const char *array_type = "FixedArray";
2837 /* We already have the size_is expression since it's at the
2838 top level, but do checks for multidimensional conformant
2839 arrays. When we handle them, we'll need to extend this
2840 function to return a list, and then we'll actually use
2841 the return value. */
2842 get_size_is_expr(type, var->name);
2844 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2846 if (is_size_needed_for_phase(phase))
2848 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2849 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2850 write_expr(file, type->length_is, 1);
2851 fprintf(file, ";\n\n");
2853 array_type = "VaryingArray";
2855 else if (tc == RPC_FC_CARRAY)
2857 if (is_size_needed_for_phase(phase))
2859 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2860 write_expr(file, type->size_is, 1);
2861 fprintf(file, ";\n\n");
2863 array_type = "ConformantArray";
2865 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2867 if (is_size_needed_for_phase(phase))
2869 if (type->size_is)
2871 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2872 write_expr(file, type->size_is, 1);
2873 fprintf(file, ";\n");
2875 if (type->length_is)
2877 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2878 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2879 write_expr(file, type->length_is, 1);
2880 fprintf(file, ";\n\n");
2883 array_type = (tc == RPC_FC_BOGUS_ARRAY
2884 ? "ComplexArray"
2885 : "ConformantVaryingArray");
2888 if (pointer_type != RPC_FC_RP) array_type = "Pointer";
2889 print_phase_function(file, indent, array_type, phase, var, start_offset);
2890 if (phase == PHASE_FREE && pointer_type == RPC_FC_RP)
2892 /* these are all unmarshalled by allocating memory */
2893 if (type->type == RPC_FC_BOGUS_ARRAY ||
2894 type->type == RPC_FC_CVARRAY ||
2895 ((type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY) && in_attr) ||
2896 (type->type == RPC_FC_CARRAY && !in_attr))
2898 print_file(file, indent, "if (%s)\n", var->name);
2899 indent++;
2900 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2904 else if (!is_ptr(var->type) && is_base_type(rtype))
2906 if (phase != PHASE_FREE)
2907 print_phase_basetype(file, indent, phase, pass, var, var->name);
2909 else if (!is_ptr(var->type))
2911 switch (rtype)
2913 case RPC_FC_STRUCT:
2914 case RPC_FC_PSTRUCT:
2915 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2916 break;
2917 case RPC_FC_CSTRUCT:
2918 case RPC_FC_CPSTRUCT:
2919 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2920 break;
2921 case RPC_FC_CVSTRUCT:
2922 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2923 break;
2924 case RPC_FC_BOGUS_STRUCT:
2925 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2926 break;
2927 case RPC_FC_RP:
2928 if (is_base_type( var->type->ref->type ))
2930 print_phase_basetype(file, indent, phase, pass, var, var->name);
2932 else if (var->type->ref->type == RPC_FC_STRUCT)
2934 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2935 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2937 else
2939 expr_t *iid;
2940 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2942 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2943 write_expr( file, iid, 1 );
2944 fprintf( file, ";\n\n" );
2946 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2948 break;
2949 default:
2950 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2953 else
2955 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2957 if (phase != PHASE_FREE)
2958 print_phase_basetype(file, indent, phase, pass, var, var->name);
2960 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2962 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2963 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2965 else
2967 expr_t *iid;
2968 expr_t *sx = get_size_is_expr(type, var->name);
2970 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2972 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2973 write_expr( file, iid, 1 );
2974 fprintf( file, ";\n\n" );
2976 else if (sx)
2978 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2979 write_expr(file, sx, 1);
2980 fprintf(file, ";\n\n");
2982 if (var->type->ref->type == RPC_FC_IP)
2983 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2984 else
2985 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2988 fprintf(file, "\n");
2991 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2992 enum pass pass, enum remoting_phase phase)
2994 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN)
2996 unsigned int size = get_function_buffer_size( func, pass );
2997 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
3000 if (pass == PASS_RETURN)
3002 var_t var;
3003 var = *func->def;
3004 var.name = xstrdup( "_RetVal" );
3005 write_remoting_arg( file, indent, func, pass, phase, &var );
3006 free( var.name );
3008 else
3010 const var_t *var;
3011 if (!func->args)
3012 return;
3013 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3014 write_remoting_arg( file, indent, func, pass, phase, var );
3019 size_t get_size_procformatstring_var(const var_t *var)
3021 return write_procformatstring_var(NULL, 0, var, FALSE);
3025 size_t get_size_procformatstring_func(const func_t *func)
3027 const var_t *var;
3028 size_t size = 0;
3030 /* argument list size */
3031 if (func->args)
3032 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3033 size += get_size_procformatstring_var(var);
3035 /* return value size */
3036 if (is_void(func->def->type))
3037 size += 2; /* FC_END and FC_PAD */
3038 else
3039 size += get_size_procformatstring_var(func->def);
3041 return size;
3044 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
3046 const ifref_t *iface;
3047 size_t size = 1;
3048 const func_t *func;
3050 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
3052 if (!pred(iface->iface))
3053 continue;
3055 if (iface->iface->funcs)
3056 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
3057 if (!is_local(func->def->attrs))
3058 size += get_size_procformatstring_func( func );
3060 return size;
3063 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
3065 set_all_tfswrite(FALSE);
3066 return process_tfs(NULL, ifaces, pred);
3069 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
3070 const var_list_t *fields, const char *structvar)
3072 switch (e->type) {
3073 case EXPR_VOID:
3074 break;
3075 case EXPR_NUM:
3076 fprintf(h, "%lu", e->u.lval);
3077 break;
3078 case EXPR_HEXNUM:
3079 fprintf(h, "0x%lx", e->u.lval);
3080 break;
3081 case EXPR_DOUBLE:
3082 fprintf(h, "%#.15g", e->u.dval);
3083 break;
3084 case EXPR_TRUEFALSE:
3085 if (e->u.lval == 0)
3086 fprintf(h, "FALSE");
3087 else
3088 fprintf(h, "TRUE");
3089 break;
3090 case EXPR_IDENTIFIER:
3092 const var_t *field;
3093 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3094 if (!strcmp(e->u.sval, field->name))
3096 fprintf(h, "%s->%s", structvar, e->u.sval);
3097 break;
3100 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
3101 break;
3103 case EXPR_NEG:
3104 fprintf(h, "-");
3105 write_struct_expr(h, e->ref, 1, fields, structvar);
3106 break;
3107 case EXPR_NOT:
3108 fprintf(h, "~");
3109 write_struct_expr(h, e->ref, 1, fields, structvar);
3110 break;
3111 case EXPR_PPTR:
3112 fprintf(h, "*");
3113 write_struct_expr(h, e->ref, 1, fields, structvar);
3114 break;
3115 case EXPR_CAST:
3116 fprintf(h, "(");
3117 write_type_decl(h, e->u.tref, NULL);
3118 fprintf(h, ")");
3119 write_struct_expr(h, e->ref, 1, fields, structvar);
3120 break;
3121 case EXPR_SIZEOF:
3122 fprintf(h, "sizeof(");
3123 write_type_decl(h, e->u.tref, NULL);
3124 fprintf(h, ")");
3125 break;
3126 case EXPR_SHL:
3127 case EXPR_SHR:
3128 case EXPR_MUL:
3129 case EXPR_DIV:
3130 case EXPR_ADD:
3131 case EXPR_SUB:
3132 case EXPR_AND:
3133 case EXPR_OR:
3134 if (brackets) fprintf(h, "(");
3135 write_struct_expr(h, e->ref, 1, fields, structvar);
3136 switch (e->type) {
3137 case EXPR_SHL: fprintf(h, " << "); break;
3138 case EXPR_SHR: fprintf(h, " >> "); break;
3139 case EXPR_MUL: fprintf(h, " * "); break;
3140 case EXPR_DIV: fprintf(h, " / "); break;
3141 case EXPR_ADD: fprintf(h, " + "); break;
3142 case EXPR_SUB: fprintf(h, " - "); break;
3143 case EXPR_AND: fprintf(h, " & "); break;
3144 case EXPR_OR: fprintf(h, " | "); break;
3145 default: break;
3147 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3148 if (brackets) fprintf(h, ")");
3149 break;
3150 case EXPR_COND:
3151 if (brackets) fprintf(h, "(");
3152 write_struct_expr(h, e->ref, 1, fields, structvar);
3153 fprintf(h, " ? ");
3154 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3155 fprintf(h, " : ");
3156 write_struct_expr(h, e->ext2, 1, fields, structvar);
3157 if (brackets) fprintf(h, ")");
3158 break;
3159 case EXPR_ADDRESSOF:
3160 fprintf(h, "&");
3161 write_struct_expr(h, e->ref, 1, fields, structvar);
3162 break;
3167 void declare_stub_args( FILE *file, int indent, const func_t *func )
3169 int in_attr, out_attr;
3170 int i = 0;
3171 const var_t *def = func->def;
3172 const var_t *var;
3174 /* declare return value '_RetVal' */
3175 if (!is_void(def->type))
3177 print_file(file, indent, "");
3178 write_type_decl_left(file, def->type);
3179 fprintf(file, " _RetVal;\n");
3182 if (!func->args)
3183 return;
3185 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3187 int is_string = is_attr(var->attrs, ATTR_STRING);
3189 in_attr = is_attr(var->attrs, ATTR_IN);
3190 out_attr = is_attr(var->attrs, ATTR_OUT);
3191 if (!out_attr && !in_attr)
3192 in_attr = 1;
3194 if (is_context_handle(var->type))
3195 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3196 else
3198 if (!in_attr && !var->type->size_is && !is_string)
3200 print_file(file, indent, "");
3201 write_type_decl(file, var->type->declarray ? var->type : var->type->ref,
3202 "_W%u", i++);
3203 fprintf(file, ";\n");
3206 print_file(file, indent, "");
3207 write_type_decl_left(file, var->type);
3208 fprintf(file, " ");
3209 if (var->type->declarray) {
3210 fprintf(file, "( *");
3211 write_name(file, var);
3212 fprintf(file, " )");
3213 } else
3214 write_name(file, var);
3215 write_type_right(file, var->type, FALSE);
3216 fprintf(file, ";\n");
3218 if (decl_indirect(var->type))
3219 print_file(file, indent, "void *_p_%s = &%s;\n",
3220 var->name, var->name);
3226 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3228 int in_attr, out_attr;
3229 int i = 0, sep = 0;
3230 const var_t *var;
3232 if (!func->args)
3233 return;
3235 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3237 int is_string = is_attr(var->attrs, ATTR_STRING);
3238 in_attr = is_attr(var->attrs, ATTR_IN);
3239 out_attr = is_attr(var->attrs, ATTR_OUT);
3240 if (!out_attr && !in_attr)
3241 in_attr = 1;
3243 if (!in_attr)
3245 print_file(file, indent, "");
3246 write_name(file, var);
3248 if (is_context_handle(var->type))
3250 fprintf(file, " = NdrContextHandleInitialize(\n");
3251 print_file(file, indent + 1, "&_StubMsg,\n");
3252 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3253 var->type->typestring_offset);
3255 else if (var->type->size_is)
3257 unsigned int size, align = 0;
3258 type_t *type = var->type;
3260 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3261 for ( ; type->size_is ; type = type->ref)
3263 write_expr(file, type->size_is, TRUE);
3264 fprintf(file, " * ");
3266 size = type_memsize(type, &align);
3267 fprintf(file, "%u);\n", size);
3269 else if (!is_string)
3271 fprintf(file, " = &_W%u;\n", i);
3272 if (is_ptr(var->type) && !last_ptr(var->type))
3273 print_file(file, indent, "_W%u = 0;\n", i);
3274 i++;
3277 sep = 1;
3280 if (sep)
3281 fprintf(file, "\n");
3285 int write_expr_eval_routines(FILE *file, const char *iface)
3287 static const char *var_name = "pS";
3288 int result = 0;
3289 struct expr_eval_routine *eval;
3290 unsigned short callback_offset = 0;
3292 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3294 const char *name = eval->structure->name;
3295 const var_list_t *fields = eval->structure->fields;
3296 result = 1;
3298 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3299 iface, name, callback_offset);
3300 print_file(file, 0, "{\n");
3301 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3302 name, var_name, name, eval->baseoff);
3303 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3304 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3305 write_struct_expr(file, eval->expr, 1, fields, var_name);
3306 fprintf(file, ";\n");
3307 print_file(file, 0, "}\n\n");
3308 callback_offset++;
3310 return result;
3313 void write_expr_eval_routine_list(FILE *file, const char *iface)
3315 struct expr_eval_routine *eval;
3316 struct expr_eval_routine *cursor;
3317 unsigned short callback_offset = 0;
3319 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3320 fprintf(file, "{\n");
3322 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3324 const char *name = eval->structure->name;
3325 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3326 callback_offset++;
3327 list_remove(&eval->entry);
3328 free(eval);
3331 fprintf(file, "};\n\n");
3334 void write_user_quad_list(FILE *file)
3336 user_type_t *ut;
3338 if (list_empty(&user_type_list))
3339 return;
3341 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3342 fprintf(file, "{\n");
3343 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3345 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3346 print_file(file, 1, "{\n");
3347 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3348 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3349 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3350 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3351 print_file(file, 1, "}%s\n", sep);
3353 fprintf(file, "};\n\n");
3356 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3358 const struct str_list_entry_t *endpoint;
3359 const char *p;
3361 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3362 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3363 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3365 print_file( f, 1, "{ (const unsigned char *)\"" );
3366 for (p = endpoint->str; *p && *p != ':'; p++)
3368 if (*p == '"' || *p == '\\') fputc( '\\', f );
3369 fputc( *p, f );
3371 if (!*p) goto error;
3372 if (p[1] != '[') goto error;
3374 fprintf( f, "\", (const unsigned char *)\"" );
3375 for (p += 2; *p && *p != ']'; p++)
3377 if (*p == '"' || *p == '\\') fputc( '\\', f );
3378 fputc( *p, f );
3380 if (*p != ']') goto error;
3381 fprintf( f, "\" },\n" );
3383 print_file( f, 0, "};\n\n" );
3384 return;
3386 error:
3387 error("Invalid endpoint syntax '%s'\n", endpoint->str);