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
23 #include "wine/port.h"
41 #include "wine/list.h"
46 static const func_t *current_func;
47 static const type_t *current_structure;
49 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
50 struct expr_eval_routine
53 const type_t *structure;
58 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
59 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
60 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
61 const char *name, int write_ptr, unsigned int *tfsoff);
62 static const var_t *find_array_or_string_in_struct(const type_t *type);
64 const char *string_of_type(unsigned char type)
68 case RPC_FC_BYTE: return "FC_BYTE";
69 case RPC_FC_CHAR: return "FC_CHAR";
70 case RPC_FC_SMALL: return "FC_SMALL";
71 case RPC_FC_USMALL: return "FC_USMALL";
72 case RPC_FC_WCHAR: return "FC_WCHAR";
73 case RPC_FC_SHORT: return "FC_SHORT";
74 case RPC_FC_USHORT: return "FC_USHORT";
75 case RPC_FC_LONG: return "FC_LONG";
76 case RPC_FC_ULONG: return "FC_ULONG";
77 case RPC_FC_FLOAT: return "FC_FLOAT";
78 case RPC_FC_HYPER: return "FC_HYPER";
79 case RPC_FC_DOUBLE: return "FC_DOUBLE";
80 case RPC_FC_ENUM16: return "FC_ENUM16";
81 case RPC_FC_ENUM32: return "FC_ENUM32";
82 case RPC_FC_IGNORE: return "FC_IGNORE";
83 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
84 case RPC_FC_RP: return "FC_RP";
85 case RPC_FC_UP: return "FC_UP";
86 case RPC_FC_OP: return "FC_OP";
87 case RPC_FC_FP: return "FC_FP";
88 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
89 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
90 case RPC_FC_STRUCT: return "FC_STRUCT";
91 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
92 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
93 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
94 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
95 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
96 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
97 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
98 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
99 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
100 case RPC_FC_CARRAY: return "FC_CARRAY";
101 case RPC_FC_CVARRAY: return "FC_CVARRAY";
102 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
103 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
104 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
105 case RPC_FC_POINTER: return "FC_POINTER";
106 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
107 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
108 case RPC_FC_CSTRING: return "FC_CSTRING";
109 case RPC_FC_WSTRING: return "FC_WSTRING";
111 error("string_of_type: unknown type 0x%02x\n", type);
116 int is_struct(unsigned char type)
123 case RPC_FC_CPSTRUCT:
124 case RPC_FC_CVSTRUCT:
125 case RPC_FC_BOGUS_STRUCT:
132 static int is_non_complex_struct(const type_t *type)
139 case RPC_FC_CPSTRUCT:
140 case RPC_FC_CVSTRUCT:
147 int is_union(unsigned char type)
151 case RPC_FC_ENCAPSULATED_UNION:
152 case RPC_FC_NON_ENCAPSULATED_UNION:
159 static unsigned short user_type_offset(const char *name)
162 unsigned short off = 0;
163 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
165 if (strcmp(name, ut->name) == 0)
169 error("user_type_offset: couldn't find type (%s)\n", name);
173 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
175 type->typestring_offset = offset;
176 if (file) type->tfswrite = FALSE;
179 static void guard_rec(type_t *type)
181 /* types that contain references to themselves (like a linked list),
182 need to be shielded from infinite recursion when writing embedded
184 if (type->typestring_offset)
185 type->tfswrite = FALSE;
187 type->typestring_offset = 1;
190 static type_t *get_user_type(const type_t *t, const char **pname)
194 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
202 if (t->kind == TKIND_ALIAS)
209 int is_user_type(const type_t *t)
211 return get_user_type(t, NULL) != NULL;
214 static int is_embedded_complex(const type_t *type)
216 unsigned char tc = type->type;
217 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
218 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
221 static const char *get_context_handle_type_name(const type_t *type)
224 for (t = type; is_ptr(t); t = t->ref)
225 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
231 static int compare_expr(const expr_t *a, const expr_t *b)
235 if (a->type != b->type)
236 return a->type - b->type;
243 return a->u.lval - b->u.lval;
245 return a->u.dval - b->u.dval;
246 case EXPR_IDENTIFIER:
247 return strcmp(a->u.sval, b->u.sval);
249 ret = compare_expr(a->ref, b->ref);
252 ret = compare_expr(a->u.ext, b->u.ext);
255 return compare_expr(a->ext2, b->ext2);
264 ret = compare_expr(a->ref, b->ref);
267 return compare_expr(a->u.ext, b->u.ext);
273 return compare_expr(a->ref, b->ref);
280 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
283 fprintf(file, "/* %2u */\n", typestring_offset); \
284 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
288 static void print_file(FILE *file, int indent, const char *format, ...)
291 va_start(va, format);
292 print(file, indent, format, va);
296 void print(FILE *file, int indent, const char *format, va_list va)
300 if (format[0] != '\n')
303 vfprintf(file, format, va);
307 void write_parameters_init(FILE *file, int indent, const func_t *func)
314 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
316 const type_t *t = var->type;
317 const char *n = var->name;
318 if (decl_indirect(t))
319 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
320 else if (is_ptr(t) || is_array(t))
321 print_file(file, indent, "%s = 0;\n", n);
327 static void write_formatdesc(FILE *f, int indent, const char *str)
329 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
330 print_file(f, indent, "{\n");
331 print_file(f, indent + 1, "short Pad;\n");
332 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
333 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
334 print_file(f, indent, "\n");
337 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
339 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
340 get_size_typeformatstring(ifaces, pred));
342 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
343 get_size_procformatstring(ifaces, pred));
346 write_formatdesc(f, indent, "TYPE");
347 write_formatdesc(f, indent, "PROC");
349 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
350 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
351 print_file(f, indent, "\n");
354 static inline int is_base_type(unsigned char type)
373 case RPC_FC_ERROR_STATUS_T:
374 case RPC_FC_BIND_PRIMITIVE:
382 int decl_indirect(const type_t *t)
384 return is_user_type(t)
385 || (!is_base_type(t->type)
390 static size_t write_procformatstring_var(FILE *file, int indent,
391 const var_t *var, int is_return)
394 const type_t *type = var->type;
396 int is_in = is_attr(var->attrs, ATTR_IN);
397 int is_out = is_attr(var->attrs, ATTR_OUT);
399 if (!is_in && !is_out) is_in = TRUE;
401 if (!type->declarray && is_base_type(type->type))
404 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
406 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
408 if (type->type == RPC_FC_BIND_PRIMITIVE)
410 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
411 size = 2; /* includes param type prefix */
413 else if (is_base_type(type->type))
415 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
416 size = 2; /* includes param type prefix */
420 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
427 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
428 else if (is_in && is_out)
429 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
431 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
433 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
435 print_file(file, indent, "0x01,\n");
436 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
437 size = 4; /* includes param type prefix */
442 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
444 const ifref_t *iface;
448 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
449 print_file(file, indent, "{\n");
451 print_file(file, indent, "0,\n");
452 print_file(file, indent, "{\n");
455 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
457 if (!pred(iface->iface))
460 if (iface->iface->funcs)
463 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
465 if (is_local(func->def->attrs)) continue;
466 /* emit argument data */
469 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
470 write_procformatstring_var(file, indent, var, FALSE);
473 /* emit return value data */
475 if (is_void(var->type))
477 print_file(file, indent, "0x5b, /* FC_END */\n");
478 print_file(file, indent, "0x5c, /* FC_PAD */\n");
481 write_procformatstring_var(file, indent, var, TRUE);
486 print_file(file, indent, "0x0\n");
488 print_file(file, indent, "}\n");
490 print_file(file, indent, "};\n");
491 print_file(file, indent, "\n");
494 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
496 if (is_base_type(type->type))
498 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
499 *typestring_offset += 1;
506 /* write conformance / variance descriptor */
507 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
508 unsigned int baseoff, const type_t *type,
511 unsigned char operator_type = 0;
512 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
513 const char *conftype_string = "";
514 const char *operator_string = "no operators";
515 const expr_t *subexpr;
519 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
525 /* Top-level conformance calculations are done inline. */
526 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
527 RPC_FC_TOP_LEVEL_CONFORMANCE);
528 print_file (file, 2, "0x0,\n");
529 print_file (file, 2, "NdrFcShort(0x0),\n");
535 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
536 error("write_conf_or_var_desc: constant value %ld is greater than "
537 "the maximum constant size of %d\n", expr->cval,
538 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
540 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
541 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
542 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
543 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
548 if (is_ptr(type) || (is_array(type) && !type->declarray))
550 conftype = RPC_FC_POINTER_CONFORMANCE;
551 conftype_string = "field pointer, ";
555 switch (subexpr->type)
558 subexpr = subexpr->ref;
559 operator_type = RPC_FC_DEREFERENCE;
560 operator_string = "FC_DEREFERENCE";
563 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
565 subexpr = subexpr->ref;
566 operator_type = RPC_FC_DIV_2;
567 operator_string = "FC_DIV_2";
571 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
573 subexpr = subexpr->ref;
574 operator_type = RPC_FC_MULT_2;
575 operator_string = "FC_MULT_2";
579 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
581 subexpr = subexpr->ref;
582 operator_type = RPC_FC_SUB_1;
583 operator_string = "FC_SUB_1";
587 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
589 subexpr = subexpr->ref;
590 operator_type = RPC_FC_ADD_1;
591 operator_string = "FC_ADD_1";
598 if (subexpr->type == EXPR_IDENTIFIER)
600 const type_t *correlation_variable = NULL;
601 unsigned char correlation_variable_type;
602 unsigned char param_type = 0;
606 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
608 unsigned int align = 0;
609 /* FIXME: take alignment into account */
610 if (var->name && !strcmp(var->name, subexpr->u.sval))
612 correlation_variable = var->type;
615 offset += type_memsize(var->type, &align);
617 if (!correlation_variable)
618 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
622 correlation_variable_type = correlation_variable->type;
624 switch (correlation_variable_type)
628 param_type = RPC_FC_SMALL;
632 param_type = RPC_FC_USMALL;
637 param_type = RPC_FC_SHORT;
640 param_type = RPC_FC_USHORT;
644 param_type = RPC_FC_LONG;
647 param_type = RPC_FC_ULONG;
653 if (sizeof(void *) == 4) /* FIXME */
654 param_type = RPC_FC_LONG;
656 param_type = RPC_FC_HYPER;
659 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
660 correlation_variable_type);
663 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
664 conftype | param_type, conftype_string, string_of_type(param_type));
665 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
666 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
671 unsigned int callback_offset = 0;
672 struct expr_eval_routine *eval;
675 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
677 if (!strcmp (eval->structure->name, structure->name)
678 && !compare_expr (eval->expr, expr))
688 eval = xmalloc (sizeof(*eval));
689 eval->structure = structure;
690 eval->baseoff = baseoff;
692 list_add_tail (&expr_eval_routines, &eval->entry);
695 if (callback_offset > USHRT_MAX)
696 error("Maximum number of callback routines reached\n");
698 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
699 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
700 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
705 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
707 int have_align = FALSE;
711 if (!fields) return 0;
712 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
714 unsigned int falign = 0;
715 size_t fsize = type_memsize(v->type, &falign);
721 size = (size + (falign - 1)) & ~(falign - 1);
725 size = (size + (*align - 1)) & ~(*align - 1);
729 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
731 size_t size, maxs = 0;
732 unsigned int align = *pmaxa;
735 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
737 /* we could have an empty default field with NULL type */
740 size = type_memsize(v->type, &align);
741 if (maxs < size) maxs = size;
742 if (*pmaxa < align) *pmaxa = align;
749 int get_padding(const var_list_t *fields)
751 unsigned short offset = 0;
758 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
760 type_t *ft = f->type;
761 unsigned int align = 0;
762 size_t size = type_memsize(ft, &align);
765 offset = (offset + (align - 1)) & ~(align - 1);
769 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
772 size_t type_memsize(const type_t *t, unsigned int *align)
776 if (t->declarray && is_conformant_array(t))
778 type_memsize(t->ref, align);
781 else if (is_ptr(t) || is_conformant_array(t))
783 size = sizeof(void *);
784 if (size > *align) *align = size;
786 else switch (t->type)
793 if (size > *align) *align = size;
800 if (size > *align) *align = size;
804 case RPC_FC_ERROR_STATUS_T:
808 if (size > *align) *align = size;
813 if (size > *align) *align = size;
816 case RPC_FC_CVSTRUCT:
817 case RPC_FC_CPSTRUCT:
820 case RPC_FC_BOGUS_STRUCT:
821 size = fields_memsize(t->fields, align);
823 case RPC_FC_ENCAPSULATED_UNION:
824 case RPC_FC_NON_ENCAPSULATED_UNION:
825 size = union_memsize(t->fields, align);
827 case RPC_FC_SMFARRAY:
828 case RPC_FC_LGFARRAY:
829 case RPC_FC_SMVARRAY:
830 case RPC_FC_LGVARRAY:
831 case RPC_FC_BOGUS_ARRAY:
832 size = t->dim * type_memsize(t->ref, align);
835 error("type_memsize: Unknown type %d\n", t->type);
842 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
844 short absoff = type->ref->typestring_offset;
845 short reloff = absoff - (offset + 2);
846 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
848 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
849 type->type, ptr_attr, string_of_type(type->type));
850 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
851 reloff, reloff, absoff);
855 static unsigned char conf_string_type_of_char_type(unsigned char t)
861 return RPC_FC_C_CSTRING;
863 return RPC_FC_C_WSTRING;
866 error("string_type_of_char_type: unrecognized type %d\n", t);
870 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
873 = is_string_type(type->attrs, type)
874 ? conf_string_type_of_char_type(type->ref->type)
876 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
877 type->type, string_of_type(type->type));
878 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
879 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
883 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
885 print_file(file, 0, "/* %u (", tfsoff);
886 write_type_decl(file, t, NULL);
887 print_file(file, 0, ") */\n");
890 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
892 unsigned int offset = *typestring_offset;
894 print_start_tfs_comment(file, type, offset);
895 update_tfsoff(type, offset, file);
897 if (type->ref->typestring_offset)
898 *typestring_offset += write_nonsimple_pointer(file, type, offset);
899 else if (is_base_type(type->ref->type))
900 *typestring_offset += write_simple_pointer(file, type);
905 static int processed(const type_t *type)
907 return type->typestring_offset && !type->tfswrite;
910 static int user_type_has_variable_size(const type_t *t)
919 case RPC_FC_CPSTRUCT:
920 case RPC_FC_CVSTRUCT:
923 /* Note: Since this only applies to user types, we can't have a conformant
924 array here, and strings should get filed under pointer in this case. */
928 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
930 unsigned int start, absoff, flags;
931 unsigned int align = 0, ualign = 0;
933 type_t *utype = get_user_type(type, &name);
934 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
935 size_t size = type_memsize(type, &align);
936 unsigned short funoff = user_type_offset(name);
941 if (is_base_type(utype->type))
944 print_start_tfs_comment(file, utype, absoff);
945 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
946 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
951 if (!processed(utype))
952 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
953 absoff = utype->typestring_offset;
956 if (utype->type == RPC_FC_RP)
958 else if (utype->type == RPC_FC_UP)
964 update_tfsoff(type, start, file);
965 print_start_tfs_comment(file, type, start);
966 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
967 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
968 flags | (align - 1), align - 1, flags);
969 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
970 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
971 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
973 reloff = absoff - *tfsoff;
974 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
978 static void write_member_type(FILE *file, const type_t *cont,
979 const attr_list_t *attrs, const type_t *type,
980 unsigned int *corroff, unsigned int *tfsoff)
982 if (is_embedded_complex(type) && !is_conformant_array(type))
987 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
994 absoff = type->typestring_offset;
996 reloff = absoff - (*tfsoff + 2);
998 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
999 /* FIXME: actually compute necessary padding */
1000 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1001 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1002 reloff, reloff, absoff);
1005 else if (is_ptr(type) || is_conformant_array(type))
1007 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1010 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1013 else if (!write_base_type(file, type, tfsoff))
1014 error("Unsupported member type 0x%x\n", type->type);
1017 static void write_end(FILE *file, unsigned int *tfsoff)
1019 if (*tfsoff % 2 == 0)
1021 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1024 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1028 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1030 unsigned int offset = 0;
1031 var_list_t *fs = type->fields;
1034 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1036 unsigned int align = 0;
1037 type_t *ft = f->type;
1038 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1040 unsigned int absoff = ft->typestring_offset;
1041 short reloff = absoff - (*tfsoff + 6);
1042 print_file(file, 0, "/* %d */\n", *tfsoff);
1043 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1044 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1045 write_conf_or_var_desc(file, current_structure, offset, ft,
1046 get_attrp(f->attrs, ATTR_SWITCHIS));
1047 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1048 reloff, reloff, absoff);
1052 /* FIXME: take alignment into account */
1053 offset += type_memsize(ft, &align);
1057 static int write_no_repeat_pointer_descriptions(
1058 FILE *file, type_t *type,
1059 size_t *offset_in_memory, size_t *offset_in_buffer,
1060 unsigned int *typestring_offset)
1065 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1067 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1068 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1070 /* pointer instance */
1071 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1072 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1073 *typestring_offset += 6;
1076 write_pointer_tfs(file, type, typestring_offset);
1079 unsigned absoff = type->typestring_offset;
1080 short reloff = absoff - (*typestring_offset + 2);
1081 /* FIXME: get pointer attributes from field */
1082 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1083 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1084 reloff, reloff, absoff);
1085 *typestring_offset += 4;
1089 *offset_in_memory += type_memsize(type, &align);
1090 /* FIXME: is there a case where these two are different? */
1092 *offset_in_buffer += type_memsize(type, &align);
1097 if (is_non_complex_struct(type))
1100 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1101 written += write_no_repeat_pointer_descriptions(
1103 offset_in_memory, offset_in_buffer, typestring_offset);
1108 *offset_in_memory += type_memsize(type, &align);
1109 /* FIXME: is there a case where these two are different? */
1111 *offset_in_buffer += type_memsize(type, &align);
1117 static int write_pointer_description_offsets(
1118 FILE *file, const attr_list_t *attrs, type_t *type,
1119 size_t *offset_in_memory, size_t *offset_in_buffer,
1120 unsigned int *typestring_offset)
1125 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1127 if (offset_in_memory && offset_in_buffer)
1129 /* pointer instance */
1130 /* FIXME: sometimes from end of structure, sometimes from beginning */
1131 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1132 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1135 *offset_in_memory += type_memsize(type, &align);
1136 /* FIXME: is there a case where these two are different? */
1138 *offset_in_buffer += type_memsize(type, &align);
1140 *typestring_offset += 4;
1142 if (processed(type->ref) || is_base_type(type->ref->type))
1143 write_pointer_tfs(file, type, typestring_offset);
1145 error("write_pointer_description_offsets: type format string unknown\n");
1152 return write_pointer_description_offsets(
1153 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1156 else if (is_non_complex_struct(type))
1158 /* otherwise search for interesting fields to parse */
1160 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1162 written += write_pointer_description_offsets(
1163 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1170 if (offset_in_memory)
1171 *offset_in_memory += type_memsize(type, &align);
1172 /* FIXME: is there a case where these two are different? */
1174 if (offset_in_buffer)
1175 *offset_in_buffer += type_memsize(type, &align);
1181 /* Note: if file is NULL return value is number of pointers to write, else
1182 * it is the number of type format characters written */
1183 static int write_fixed_array_pointer_descriptions(
1184 FILE *file, const attr_list_t *attrs, type_t *type,
1185 size_t *offset_in_memory, size_t *offset_in_buffer,
1186 unsigned int *typestring_offset)
1189 int pointer_count = 0;
1191 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1193 unsigned int temp = 0;
1194 /* unfortunately, this needs to be done in two passes to avoid
1195 * writing out redundant FC_FIXED_REPEAT descriptions */
1196 pointer_count = write_pointer_description_offsets(
1197 NULL, attrs, type->ref, NULL, NULL, &temp);
1198 if (pointer_count > 0)
1200 unsigned int increment_size;
1201 size_t offset_of_array_pointer_mem = 0;
1202 size_t offset_of_array_pointer_buf = 0;
1205 increment_size = type_memsize(type->ref, &align);
1207 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1208 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1209 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1210 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1211 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1212 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1213 *typestring_offset += 10;
1215 pointer_count = write_pointer_description_offsets(
1216 file, attrs, type, &offset_of_array_pointer_mem,
1217 &offset_of_array_pointer_buf, typestring_offset);
1220 else if (is_struct(type->type))
1223 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1225 pointer_count += write_fixed_array_pointer_descriptions(
1226 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1233 if (offset_in_memory)
1234 *offset_in_memory += type_memsize(type, &align);
1235 /* FIXME: is there a case where these two are different? */
1237 if (offset_in_buffer)
1238 *offset_in_buffer += type_memsize(type, &align);
1241 return pointer_count;
1244 /* Note: if file is NULL return value is number of pointers to write, else
1245 * it is the number of type format characters written */
1246 static int write_conformant_array_pointer_descriptions(
1247 FILE *file, const attr_list_t *attrs, type_t *type,
1248 size_t offset_in_memory, unsigned int *typestring_offset)
1251 int pointer_count = 0;
1253 if (is_conformant_array(type) && !type->length_is)
1255 unsigned int temp = 0;
1256 /* unfortunately, this needs to be done in two passes to avoid
1257 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1258 pointer_count = write_pointer_description_offsets(
1259 NULL, attrs, type->ref, NULL, NULL, &temp);
1260 if (pointer_count > 0)
1262 unsigned int increment_size;
1263 size_t offset_of_array_pointer_mem = offset_in_memory;
1264 size_t offset_of_array_pointer_buf = offset_in_memory;
1267 increment_size = type_memsize(type->ref, &align);
1269 if (increment_size > USHRT_MAX)
1270 error("array size of %u bytes is too large\n", increment_size);
1272 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1273 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1274 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1275 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1276 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1277 *typestring_offset += 8;
1279 pointer_count = write_pointer_description_offsets(
1280 file, attrs, type->ref, &offset_of_array_pointer_mem,
1281 &offset_of_array_pointer_buf, typestring_offset);
1285 return pointer_count;
1288 /* Note: if file is NULL return value is number of pointers to write, else
1289 * it is the number of type format characters written */
1290 static int write_varying_array_pointer_descriptions(
1291 FILE *file, const attr_list_t *attrs, type_t *type,
1292 size_t *offset_in_memory, size_t *offset_in_buffer,
1293 unsigned int *typestring_offset)
1296 int pointer_count = 0;
1298 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1300 if (is_array(type) && type->length_is)
1302 unsigned int temp = 0;
1303 /* unfortunately, this needs to be done in two passes to avoid
1304 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1305 pointer_count = write_pointer_description_offsets(
1306 NULL, attrs, type->ref, NULL, NULL, &temp);
1307 if (pointer_count > 0)
1309 unsigned int increment_size;
1310 size_t offset_of_array_pointer_mem = 0;
1311 size_t offset_of_array_pointer_buf = 0;
1314 increment_size = type_memsize(type->ref, &align);
1316 if (increment_size > USHRT_MAX)
1317 error("array size of %u bytes is too large\n", increment_size);
1319 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1320 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1321 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1322 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1323 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1324 *typestring_offset += 8;
1326 pointer_count = write_pointer_description_offsets(
1327 file, attrs, type, &offset_of_array_pointer_mem,
1328 &offset_of_array_pointer_buf, typestring_offset);
1331 else if (is_struct(type->type))
1334 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1336 pointer_count += write_varying_array_pointer_descriptions(
1337 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1344 if (offset_in_memory)
1345 *offset_in_memory += type_memsize(type, &align);
1346 /* FIXME: is there a case where these two are different? */
1348 if (offset_in_buffer)
1349 *offset_in_buffer += type_memsize(type, &align);
1352 return pointer_count;
1355 static void write_pointer_description(FILE *file, type_t *type,
1356 unsigned int *typestring_offset)
1358 size_t offset_in_buffer;
1359 size_t offset_in_memory;
1361 /* pass 1: search for single instance of a pointer (i.e. don't descend
1363 if (!is_array(type))
1365 offset_in_memory = 0;
1366 offset_in_buffer = 0;
1367 write_no_repeat_pointer_descriptions(
1369 &offset_in_memory, &offset_in_buffer, typestring_offset);
1372 /* pass 2: search for pointers in fixed arrays */
1373 offset_in_memory = 0;
1374 offset_in_buffer = 0;
1375 write_fixed_array_pointer_descriptions(
1377 &offset_in_memory, &offset_in_buffer, typestring_offset);
1379 /* pass 3: search for pointers in conformant only arrays (but don't descend
1380 * into conformant varying or varying arrays) */
1381 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1382 write_conformant_array_pointer_descriptions(
1383 file, NULL, type, 0, typestring_offset);
1384 else if (type->type == RPC_FC_CPSTRUCT)
1386 unsigned int align = 0;
1387 type_t *carray = find_array_or_string_in_struct(type)->type;
1388 write_conformant_array_pointer_descriptions(
1390 type_memsize(type, &align),
1394 /* pass 4: search for pointers in varying arrays */
1395 offset_in_memory = 0;
1396 offset_in_buffer = 0;
1397 write_varying_array_pointer_descriptions(
1399 &offset_in_memory, &offset_in_buffer, typestring_offset);
1402 static int is_declptr(const type_t *t)
1404 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1407 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1409 const char *name, unsigned int *typestring_offset)
1411 size_t start_offset = *typestring_offset;
1412 unsigned char rtype;
1414 update_tfsoff(type, start_offset, file);
1416 if (is_declptr(type))
1418 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1419 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1421 pointer_type = RPC_FC_RP;
1422 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1423 pointer_type, flag, string_of_type(pointer_type),
1424 flag ? " [simple_pointer]" : "");
1425 *typestring_offset += 2;
1428 print_file(file, 2, "NdrFcShort(0x2),\n");
1429 *typestring_offset += 2;
1431 rtype = type->ref->type;
1434 rtype = type->ref->type;
1436 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1438 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1439 return start_offset;
1442 if (type->declarray && !is_conformant_array(type))
1444 /* FIXME: multi-dimensional array */
1445 if (0xffffuL < type->dim)
1446 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1447 name, 0xffffu, type->dim - 0xffffu);
1449 if (rtype == RPC_FC_CHAR)
1450 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1452 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1453 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1454 *typestring_offset += 2;
1456 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1457 *typestring_offset += 2;
1459 return start_offset;
1461 else if (type->size_is)
1463 unsigned int align = 0;
1465 if (rtype == RPC_FC_CHAR)
1466 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1468 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1469 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1470 *typestring_offset += 2;
1472 *typestring_offset += write_conf_or_var_desc(
1473 file, current_structure,
1474 (type->declarray && current_structure
1475 ? type_memsize(current_structure, &align)
1477 type, type->size_is);
1479 return start_offset;
1483 if (rtype == RPC_FC_WCHAR)
1484 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1486 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1487 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1488 *typestring_offset += 2;
1490 return start_offset;
1494 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1495 const char *name, unsigned int *typestring_offset)
1497 const expr_t *length_is = type->length_is;
1498 const expr_t *size_is = type->size_is;
1499 unsigned int align = 0;
1501 size_t start_offset;
1503 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1504 unsigned int baseoff
1505 = type->declarray && current_structure
1506 ? type_memsize(current_structure, &align)
1510 pointer_type = RPC_FC_RP;
1512 has_pointer = FALSE;
1513 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1517 size = type_memsize(type, &align);
1518 if (size == 0) /* conformant array */
1519 size = type_memsize(type->ref, &align);
1521 start_offset = *typestring_offset;
1522 update_tfsoff(type, start_offset, file);
1523 print_start_tfs_comment(file, type, start_offset);
1524 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1525 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1526 *typestring_offset += 2;
1529 if (type->type != RPC_FC_BOGUS_ARRAY)
1531 unsigned char tc = type->type;
1533 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1535 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1536 *typestring_offset += 4;
1540 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1541 *typestring_offset += 2;
1544 if (is_conformant_array(type))
1546 += write_conf_or_var_desc(file, current_structure, baseoff,
1549 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1551 unsigned int elalign = 0;
1552 size_t elsize = type_memsize(type->ref, &elalign);
1554 if (type->type == RPC_FC_LGVARRAY)
1556 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1557 *typestring_offset += 4;
1561 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1562 *typestring_offset += 2;
1565 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1566 *typestring_offset += 2;
1571 += write_conf_or_var_desc(file, current_structure, baseoff,
1574 if (has_pointer && (!type->declarray || !current_structure))
1576 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1577 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1578 *typestring_offset += 2;
1579 write_pointer_description(file, type, typestring_offset);
1580 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1581 *typestring_offset += 1;
1584 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1585 write_end(file, typestring_offset);
1589 unsigned int dim = size_is ? 0 : type->dim;
1590 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1591 *typestring_offset += 2;
1593 += write_conf_or_var_desc(file, current_structure, baseoff,
1596 += write_conf_or_var_desc(file, current_structure, baseoff,
1598 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1599 write_end(file, typestring_offset);
1602 return start_offset;
1605 static const var_t *find_array_or_string_in_struct(const type_t *type)
1607 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1608 const type_t *ft = last_field->type;
1610 if (ft->declarray && is_conformant_array(ft))
1613 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1614 return find_array_or_string_in_struct(last_field->type);
1619 static void write_struct_members(FILE *file, const type_t *type,
1620 unsigned int *corroff, unsigned int *typestring_offset)
1623 unsigned short offset = 0;
1627 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1629 type_t *ft = field->type;
1630 if (!ft->declarray || !is_conformant_array(ft))
1632 unsigned int align = 0;
1633 size_t size = type_memsize(ft, &align);
1636 if ((align - 1) & offset)
1638 unsigned char fc = 0;
1642 fc = RPC_FC_ALIGNM4;
1645 fc = RPC_FC_ALIGNM8;
1648 error("write_struct_members: cannot align type %d\n", ft->type);
1650 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1651 offset = (offset + (align - 1)) & ~(align - 1);
1652 *typestring_offset += 1;
1654 write_member_type(file, type, field->attrs, field->type, corroff,
1660 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1663 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1664 RPC_FC_STRUCTPAD1 + padding - 1,
1666 *typestring_offset += 1;
1669 write_end(file, typestring_offset);
1672 static size_t write_struct_tfs(FILE *file, type_t *type,
1673 const char *name, unsigned int *tfsoff)
1675 const type_t *save_current_structure = current_structure;
1676 unsigned int total_size;
1678 size_t start_offset;
1679 size_t array_offset;
1680 int has_pointers = 0;
1681 unsigned int align = 0;
1682 unsigned int corroff;
1686 current_structure = type;
1688 total_size = type_memsize(type, &align);
1689 if (total_size > USHRT_MAX)
1690 error("structure size for %s exceeds %d bytes by %d bytes\n",
1691 name, USHRT_MAX, total_size - USHRT_MAX);
1693 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1694 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1697 array = find_array_or_string_in_struct(type);
1698 if (array && !processed(array->type))
1700 = is_attr(array->attrs, ATTR_STRING)
1701 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1702 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1705 write_descriptors(file, type, tfsoff);
1707 start_offset = *tfsoff;
1708 update_tfsoff(type, start_offset, file);
1709 print_start_tfs_comment(file, type, start_offset);
1710 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1711 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1712 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1717 unsigned int absoff = array->type->typestring_offset;
1718 short reloff = absoff - *tfsoff;
1719 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1720 reloff, reloff, absoff);
1723 else if (type->type == RPC_FC_BOGUS_STRUCT)
1725 print_file(file, 2, "NdrFcShort(0x0),\n");
1729 if (type->type == RPC_FC_BOGUS_STRUCT)
1731 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1732 nothing is written to file yet. On the actual writing pass,
1733 this will have been updated. */
1734 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1735 short reloff = absoff - *tfsoff;
1736 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1737 reloff, reloff, absoff);
1740 else if ((type->type == RPC_FC_PSTRUCT) ||
1741 (type->type == RPC_FC_CPSTRUCT) ||
1742 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1744 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1745 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1747 write_pointer_description(file, type, tfsoff);
1748 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1752 write_struct_members(file, type, &corroff, tfsoff);
1754 if (type->type == RPC_FC_BOGUS_STRUCT)
1756 const var_list_t *fs = type->fields;
1759 type->ptrdesc = *tfsoff;
1760 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1762 type_t *ft = f->type;
1764 write_pointer_tfs(file, ft, tfsoff);
1765 else if (!ft->declarray && is_conformant_array(ft))
1767 unsigned int absoff = ft->typestring_offset;
1768 short reloff = absoff - (*tfsoff + 2);
1769 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1770 /* FIXME: We need to store pointer attributes for arrays
1771 so we don't lose pointer_default info. */
1773 ptr_type = RPC_FC_UP;
1774 print_file(file, 0, "/* %d */\n", *tfsoff);
1775 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1776 string_of_type(ptr_type));
1777 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1778 reloff, reloff, absoff);
1782 if (type->ptrdesc == *tfsoff)
1786 current_structure = save_current_structure;
1787 return start_offset;
1790 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1791 unsigned char flags, size_t offset,
1792 unsigned int *typeformat_offset)
1794 size_t start_offset = *typeformat_offset;
1795 short reloff = offset - (*typeformat_offset + 2);
1796 int in_attr, out_attr;
1797 in_attr = is_attr(attrs, ATTR_IN);
1798 out_attr = is_attr(attrs, ATTR_OUT);
1799 if (!in_attr && !out_attr) in_attr = 1;
1801 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1804 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1807 string_of_type(pointer_type));
1811 fprintf(file, " [allocated_on_stack]");
1813 fprintf(file, " [pointer_deref]");
1814 fprintf(file, " */\n");
1817 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1818 *typeformat_offset += 4;
1820 return start_offset;
1823 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1827 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1829 else if (is_base_type(t->type))
1831 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1832 t->type, string_of_type(t->type));
1834 else if (t->typestring_offset)
1836 short reloff = t->typestring_offset - *tfsoff;
1837 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1838 reloff, reloff, t->typestring_offset);
1841 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1846 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1848 unsigned int align = 0;
1849 unsigned int start_offset;
1850 size_t size = type_memsize(type, &align);
1853 type_t *deftype = NULL;
1854 short nodeftype = 0xffff;
1859 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1861 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1862 fields = uv->type->fields;
1865 fields = type->fields;
1867 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1869 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1871 nbranch += list_count(cases);
1873 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1876 start_offset = *tfsoff;
1877 update_tfsoff(type, start_offset, file);
1878 print_start_tfs_comment(file, type, start_offset);
1879 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1881 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1882 const type_t *st = sv->type;
1895 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1896 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1897 0x40 | st->type, string_of_type(st->type));
1901 error("union switch type must be an integer, char, or enum\n");
1904 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1905 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1908 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1910 type_t *ft = f->type;
1911 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1912 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1915 if (cases == NULL && !deflt)
1916 error("union field %s with neither case nor default attribute\n", f->name);
1918 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1920 /* MIDL doesn't check for duplicate cases, even though that seems
1921 like a reasonable thing to do, it just dumps them to the TFS
1922 like we're going to do here. */
1923 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1925 write_branch_type(file, ft, tfsoff);
1928 /* MIDL allows multiple default branches, even though that seems
1929 illogical, it just chooses the last one, which is what we will
1940 write_branch_type(file, deftype, tfsoff);
1944 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1948 return start_offset;
1951 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1952 unsigned int *typeformat_offset)
1955 size_t start_offset = *typeformat_offset;
1956 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1962 expr.type = EXPR_IDENTIFIER;
1964 expr.u.sval = iid->name;
1965 expr.is_const = FALSE;
1966 print_file(file, 2, "0x2f, /* FC_IP */\n");
1967 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1969 += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
1973 const type_t *base = is_ptr(type) ? type->ref : type;
1974 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1977 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1979 update_tfsoff(type, start_offset, file);
1980 print_start_tfs_comment(file, type, start_offset);
1981 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1982 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1983 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1984 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1985 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1986 for (i = 0; i < 8; ++i)
1987 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1990 fprintf(file, "\n");
1992 *typeformat_offset += 18;
1994 return start_offset;
1997 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
1999 unsigned int *typeformat_offset)
2001 size_t start_offset = *typeformat_offset;
2002 unsigned char flags = 0x08 /* strict */;
2007 if (type->type != RPC_FC_RP)
2010 if (is_attr(var->attrs, ATTR_IN))
2012 if (is_attr(var->attrs, ATTR_OUT))
2015 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2016 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2017 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2018 print_file(file, 0, "can't be null, ");
2020 print_file(file, 0, "serialize, ");
2022 print_file(file, 0, "no serialize, ");
2024 print_file(file, 0, "strict, ");
2025 if ((flags & 0x21) == 0x20)
2026 print_file(file, 0, "out, ");
2027 if ((flags & 0x21) == 0x21)
2028 print_file(file, 0, "return, ");
2030 print_file(file, 0, "in, ");
2032 print_file(file, 0, "via ptr, ");
2033 print_file(file, 0, "*/\n");
2034 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2035 print_file(file, 2, "0, /* FIXME: param num */\n");
2036 *typeformat_offset += 4;
2038 return start_offset;
2041 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2042 type_t *type, const var_t *var,
2043 unsigned int *typeformat_offset)
2047 if (is_context_handle(type))
2048 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2050 if (is_user_type(type))
2052 write_user_tfs(file, type, typeformat_offset);
2053 return type->typestring_offset;
2056 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2057 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
2063 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2064 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2065 if (ptr_type && ptr_type != RPC_FC_RP)
2067 unsigned int absoff = type->typestring_offset;
2068 short reloff = absoff - (*typeformat_offset + 2);
2069 off = *typeformat_offset;
2070 print_file(file, 0, "/* %d */\n", off);
2071 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2072 string_of_type(ptr_type));
2073 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2074 reloff, reloff, absoff);
2075 *typeformat_offset += 4;
2082 /* basic types don't need a type format string */
2083 if (is_base_type(type->type))
2089 case RPC_FC_PSTRUCT:
2090 case RPC_FC_CSTRUCT:
2091 case RPC_FC_CPSTRUCT:
2092 case RPC_FC_CVSTRUCT:
2093 case RPC_FC_BOGUS_STRUCT:
2094 return write_struct_tfs(file, type, var->name, typeformat_offset);
2095 case RPC_FC_ENCAPSULATED_UNION:
2096 case RPC_FC_NON_ENCAPSULATED_UNION:
2097 return write_union_tfs(file, type, typeformat_offset);
2099 case RPC_FC_BIND_PRIMITIVE:
2103 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2106 else if (last_ptr(type))
2108 size_t start_offset = *typeformat_offset;
2109 int in_attr = is_attr(var->attrs, ATTR_IN);
2110 int out_attr = is_attr(var->attrs, ATTR_OUT);
2111 const type_t *base = type->ref;
2113 if (base->type == RPC_FC_IP
2115 && is_attr(var->attrs, ATTR_IIDIS)))
2117 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2120 /* special case for pointers to base types */
2121 if (is_base_type(base->type))
2123 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2124 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2125 string_of_type(type->type),
2126 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2127 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2128 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2129 *typeformat_offset += 4;
2130 return start_offset;
2134 assert(is_ptr(type));
2136 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2138 fprintf(file, "/* %2u */\n", *typeformat_offset);
2139 return write_pointer_only_tfs(file, var->attrs, type->type,
2140 !last_ptr(type) ? 0x10 : 0,
2141 offset, typeformat_offset);
2144 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2145 const char *name, int write_ptr, unsigned int *tfsoff)
2149 if (is_user_type(type))
2151 write_user_tfs(file, type, tfsoff);
2153 else if (is_ptr(type))
2155 type_t *ref = type->ref;
2157 if (ref->type == RPC_FC_IP
2159 && is_attr(attrs, ATTR_IIDIS)))
2161 write_ip_tfs(file, attrs, type, tfsoff);
2165 if (!processed(ref) && !is_base_type(ref->type))
2166 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2169 write_pointer_tfs(file, type, tfsoff);
2174 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2176 write_string_tfs(file, attrs, type, name, tfsoff);
2178 else if (type->declarray && is_conformant_array(type))
2179 ; /* conformant arrays and strings are handled specially */
2180 else if (is_array(type))
2182 write_array_tfs(file, attrs, type, name, tfsoff);
2183 if (is_conformant_array(type))
2186 else if (is_struct(type->type))
2188 if (!processed(type))
2189 write_struct_tfs(file, type, name, tfsoff);
2191 else if (is_union(type->type))
2193 if (!processed(type))
2194 write_union_tfs(file, type, tfsoff);
2196 else if (!is_base_type(type->type))
2197 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2203 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2206 const ifref_t *iface;
2207 unsigned int typeformat_offset = 2;
2209 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2211 if (!pred(iface->iface))
2214 if (iface->iface->funcs)
2217 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2219 if (is_local(func->def->attrs)) continue;
2221 current_func = func;
2223 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2226 write_typeformatstring_var(
2227 file, 2, func, var->type, var,
2228 &typeformat_offset),
2234 return typeformat_offset + 1;
2238 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2242 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2243 print_file(file, indent, "{\n");
2245 print_file(file, indent, "0,\n");
2246 print_file(file, indent, "{\n");
2248 print_file(file, indent, "NdrFcShort(0x0),\n");
2250 set_all_tfswrite(TRUE);
2251 process_tfs(file, ifaces, pred);
2253 print_file(file, indent, "0x0\n");
2255 print_file(file, indent, "}\n");
2257 print_file(file, indent, "};\n");
2258 print_file(file, indent, "\n");
2261 static unsigned int get_required_buffer_size_type(
2262 const type_t *type, const char *name, unsigned int *alignment)
2265 if (is_user_type(type))
2268 const type_t *utype = get_user_type(type, &uname);
2269 return get_required_buffer_size_type(utype, uname, alignment);
2293 case RPC_FC_ERROR_STATUS_T:
2303 case RPC_FC_BIND_PRIMITIVE:
2307 case RPC_FC_PSTRUCT:
2311 if (!type->fields) return 0;
2312 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2314 unsigned int alignment;
2315 size += get_required_buffer_size_type(field->type, field->name,
2323 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2324 ? get_required_buffer_size_type( type->ref, name, alignment )
2327 case RPC_FC_SMFARRAY:
2328 case RPC_FC_LGFARRAY:
2329 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2337 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2339 int in_attr = is_attr(var->attrs, ATTR_IN);
2340 int out_attr = is_attr(var->attrs, ATTR_OUT);
2343 if (!in_attr && !out_attr)
2348 for (t = var->type; is_ptr(t); t = t->ref)
2349 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2355 if (pass == PASS_OUT)
2357 if (out_attr && is_ptr(var->type))
2359 type_t *type = var->type;
2361 if (type->type == RPC_FC_STRUCT)
2364 unsigned int size = 36;
2366 if (!type->fields) return size;
2367 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2370 size += get_required_buffer_size_type(
2371 field->type, field->name, &align);
2380 if ((!out_attr || in_attr) && !var->type->size_is
2381 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2383 if (is_ptr(var->type))
2385 type_t *type = var->type;
2387 if (is_base_type(type->type))
2391 else if (type->type == RPC_FC_STRUCT)
2393 unsigned int size = 36;
2396 if (!type->fields) return size;
2397 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2400 size += get_required_buffer_size_type(
2401 field->type, field->name, &align);
2408 return get_required_buffer_size_type(var->type, var->name, alignment);
2412 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2415 unsigned int total_size = 0, alignment;
2419 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2421 total_size += get_required_buffer_size(var, &alignment, pass);
2422 total_size += alignment;
2426 if (pass == PASS_OUT && !is_void(func->def->type))
2428 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2429 total_size += alignment;
2434 static void print_phase_function(FILE *file, int indent, const char *type,
2435 enum remoting_phase phase,
2436 const var_t *var, unsigned int type_offset)
2438 const char *function;
2441 case PHASE_BUFFERSIZE:
2442 function = "BufferSize";
2445 function = "Marshall";
2447 case PHASE_UNMARSHAL:
2448 function = "Unmarshall";
2458 print_file(file, indent, "Ndr%s%s(\n", type, function);
2460 print_file(file, indent, "&_StubMsg,\n");
2461 print_file(file, indent, "%s%s%s%s,\n",
2462 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2463 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2464 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2466 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2467 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2468 if (phase == PHASE_UNMARSHAL)
2469 print_file(file, indent, "0);\n");
2473 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2474 enum pass pass, const var_t *var,
2475 const char *varname)
2477 type_t *type = var->type;
2479 unsigned int alignment = 0;
2480 unsigned char rtype;
2482 /* no work to do for other phases, buffer sizing is done elsewhere */
2483 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2486 rtype = is_ptr(type) ? type->ref->type : type->type;
2510 case RPC_FC_ERROR_STATUS_T:
2522 case RPC_FC_BIND_PRIMITIVE:
2523 /* no marshalling needed */
2527 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2531 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2532 alignment - 1, alignment - 1);
2534 if (phase == PHASE_MARSHAL)
2536 print_file(file, indent, "*(");
2537 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2539 fprintf(file, " *)_StubMsg.Buffer = *");
2541 fprintf(file, " *)_StubMsg.Buffer = ");
2542 fprintf(file, "%s", varname);
2543 fprintf(file, ";\n");
2545 else if (phase == PHASE_UNMARSHAL)
2547 if (pass == PASS_IN || pass == PASS_RETURN)
2548 print_file(file, indent, "");
2550 print_file(file, indent, "*");
2551 fprintf(file, "%s", varname);
2552 if (pass == PASS_IN && is_ptr(type))
2553 fprintf(file, " = (");
2555 fprintf(file, " = *(");
2556 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2557 fprintf(file, " *)_StubMsg.Buffer;\n");
2560 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2561 write_type_decl(file, var->type, NULL);
2562 fprintf(file, ");\n");
2565 /* returns whether the MaxCount, Offset or ActualCount members need to be
2566 * filled in for the specified phase */
2567 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2569 return (phase != PHASE_UNMARSHAL);
2572 static int needs_freeing(const attr_list_t *attrs, const type_t *t, int out)
2577 && (t->ref->type == RPC_FC_IP
2578 || is_ptr(t->ref))))
2579 || (out && (is_string_type(attrs, t)
2583 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2584 enum pass pass, enum remoting_phase phase)
2586 int in_attr, out_attr, pointer_type;
2592 if (phase == PHASE_BUFFERSIZE)
2594 unsigned int size = get_function_buffer_size( func, pass );
2595 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2598 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2600 const type_t *type = var->type;
2601 unsigned char rtype;
2602 size_t start_offset = type->typestring_offset;
2604 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2606 pointer_type = RPC_FC_RP;
2608 in_attr = is_attr(var->attrs, ATTR_IN);
2609 out_attr = is_attr(var->attrs, ATTR_OUT);
2610 if (!in_attr && !out_attr)
2613 if (phase == PHASE_FREE)
2615 if (!needs_freeing(var->attrs, type, out_attr))
2622 if (!in_attr) continue;
2625 if (!out_attr) continue;
2633 if (is_context_handle(type))
2635 if (phase == PHASE_MARSHAL)
2637 if (pass == PASS_IN)
2639 print_file(file, indent, "NdrClientContextMarshall(\n");
2640 print_file(file, indent + 1, "&_StubMsg,\n");
2641 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2642 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2646 print_file(file, indent, "NdrServerContextMarshall(\n");
2647 print_file(file, indent + 1, "&_StubMsg,\n");
2648 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2649 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2652 else if (phase == PHASE_UNMARSHAL)
2654 if (pass == PASS_OUT)
2656 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2657 print_file(file, indent + 1, "&_StubMsg,\n");
2658 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2659 print_file(file, indent + 1, "_Handle);\n");
2662 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2665 else if (is_user_type(var->type))
2667 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2669 else if (is_string_type(var->attrs, var->type))
2671 if (is_array(type) && !is_conformant_array(type))
2672 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2675 if (type->size_is && is_size_needed_for_phase(phase))
2677 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2678 write_expr(file, type->size_is, 1);
2679 fprintf(file, ";\n");
2682 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2683 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2685 print_phase_function(file, indent, "ConformantString", phase, var,
2686 start_offset + (type->size_is ? 4 : 2));
2689 else if (is_array(type))
2691 unsigned char tc = type->type;
2692 const char *array_type = "FixedArray";
2694 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2696 if (is_size_needed_for_phase(phase))
2698 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2699 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2700 write_expr(file, type->length_is, 1);
2701 fprintf(file, ";\n\n");
2703 array_type = "VaryingArray";
2705 else if (tc == RPC_FC_CARRAY)
2707 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2709 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2710 write_expr(file, type->size_is, 1);
2711 fprintf(file, ";\n\n");
2713 array_type = "ConformantArray";
2715 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2717 if (is_size_needed_for_phase(phase))
2721 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2722 write_expr(file, type->size_is, 1);
2723 fprintf(file, ";\n");
2725 if (type->length_is)
2727 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2728 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2729 write_expr(file, type->length_is, 1);
2730 fprintf(file, ";\n\n");
2733 array_type = (tc == RPC_FC_BOGUS_ARRAY
2735 : "ConformantVaryingArray");
2738 if (!in_attr && phase == PHASE_FREE)
2740 print_file(file, indent, "if (%s)\n", var->name);
2742 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2744 else if (phase != PHASE_FREE)
2746 const char *t = pointer_type == RPC_FC_RP ? array_type : "Pointer";
2747 print_phase_function(file, indent, t, phase, var, start_offset);
2750 else if (!is_ptr(var->type) && is_base_type(rtype))
2752 print_phase_basetype(file, indent, phase, pass, var, var->name);
2754 else if (!is_ptr(var->type))
2759 case RPC_FC_PSTRUCT:
2760 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2762 case RPC_FC_CSTRUCT:
2763 case RPC_FC_CPSTRUCT:
2764 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2766 case RPC_FC_CVSTRUCT:
2767 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2769 case RPC_FC_BOGUS_STRUCT:
2770 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2773 if (is_base_type( var->type->ref->type ))
2775 print_phase_basetype(file, indent, phase, pass, var, var->name);
2777 else if (var->type->ref->type == RPC_FC_STRUCT)
2779 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2780 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2785 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2786 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2787 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2791 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2796 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2798 print_phase_basetype(file, indent, phase, pass, var, var->name);
2800 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2802 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2803 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2808 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2809 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2810 if (var->type->ref->type == RPC_FC_IP)
2811 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2813 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2816 fprintf(file, "\n");
2821 size_t get_size_procformatstring_var(const var_t *var)
2823 return write_procformatstring_var(NULL, 0, var, FALSE);
2827 size_t get_size_procformatstring_func(const func_t *func)
2832 /* argument list size */
2834 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2835 size += get_size_procformatstring_var(var);
2837 /* return value size */
2838 if (is_void(func->def->type))
2839 size += 2; /* FC_END and FC_PAD */
2841 size += get_size_procformatstring_var(func->def);
2846 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2848 const ifref_t *iface;
2852 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2854 if (!pred(iface->iface))
2857 if (iface->iface->funcs)
2858 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2859 if (!is_local(func->def->attrs))
2860 size += get_size_procformatstring_func( func );
2865 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2867 set_all_tfswrite(FALSE);
2868 return process_tfs(NULL, ifaces, pred);
2871 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2872 const var_list_t *fields, const char *structvar)
2878 fprintf(h, "%lu", e->u.lval);
2881 fprintf(h, "0x%lx", e->u.lval);
2884 fprintf(h, "%#.15g", e->u.dval);
2886 case EXPR_TRUEFALSE:
2888 fprintf(h, "FALSE");
2892 case EXPR_IDENTIFIER:
2895 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2896 if (!strcmp(e->u.sval, field->name))
2898 fprintf(h, "%s->%s", structvar, e->u.sval);
2902 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2907 write_struct_expr(h, e->ref, 1, fields, structvar);
2911 write_struct_expr(h, e->ref, 1, fields, structvar);
2915 write_struct_expr(h, e->ref, 1, fields, structvar);
2919 write_type_decl(h, e->u.tref, NULL);
2921 write_struct_expr(h, e->ref, 1, fields, structvar);
2924 fprintf(h, "sizeof(");
2925 write_type_decl(h, e->u.tref, NULL);
2936 if (brackets) fprintf(h, "(");
2937 write_struct_expr(h, e->ref, 1, fields, structvar);
2939 case EXPR_SHL: fprintf(h, " << "); break;
2940 case EXPR_SHR: fprintf(h, " >> "); break;
2941 case EXPR_MUL: fprintf(h, " * "); break;
2942 case EXPR_DIV: fprintf(h, " / "); break;
2943 case EXPR_ADD: fprintf(h, " + "); break;
2944 case EXPR_SUB: fprintf(h, " - "); break;
2945 case EXPR_AND: fprintf(h, " & "); break;
2946 case EXPR_OR: fprintf(h, " | "); break;
2949 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2950 if (brackets) fprintf(h, ")");
2953 if (brackets) fprintf(h, "(");
2954 write_struct_expr(h, e->ref, 1, fields, structvar);
2956 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2958 write_struct_expr(h, e->ext2, 1, fields, structvar);
2959 if (brackets) fprintf(h, ")");
2965 void declare_stub_args( FILE *file, int indent, const func_t *func )
2967 int in_attr, out_attr;
2969 const var_t *def = func->def;
2972 /* declare return value '_RetVal' */
2973 if (!is_void(def->type))
2975 print_file(file, indent, "");
2976 write_type_decl_left(file, def->type);
2977 fprintf(file, " _RetVal;\n");
2983 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2985 int is_string = is_attr(var->attrs, ATTR_STRING);
2987 in_attr = is_attr(var->attrs, ATTR_IN);
2988 out_attr = is_attr(var->attrs, ATTR_OUT);
2989 if (!out_attr && !in_attr)
2992 if (is_context_handle(var->type))
2993 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
2996 if (!in_attr && !var->type->size_is && !is_string)
2998 print_file(file, indent, "");
2999 write_type_decl(file, var->type->ref, "_W%u", i++);
3000 fprintf(file, ";\n");
3003 print_file(file, indent, "");
3004 write_type_decl_left(file, var->type);
3006 if (var->type->declarray) {
3007 fprintf(file, "( *");
3008 write_name(file, var);
3009 fprintf(file, " )");
3011 write_name(file, var);
3012 write_type_right(file, var->type, FALSE);
3013 fprintf(file, ";\n");
3015 if (decl_indirect(var->type))
3016 print_file(file, indent, "void *_p_%s = &%s;\n",
3017 var->name, var->name);
3023 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3025 int in_attr, out_attr;
3032 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3034 int is_string = is_attr(var->attrs, ATTR_STRING);
3035 in_attr = is_attr(var->attrs, ATTR_IN);
3036 out_attr = is_attr(var->attrs, ATTR_OUT);
3037 if (!out_attr && !in_attr)
3042 print_file(file, indent, "");
3043 write_name(file, var);
3045 if (var->type->size_is)
3047 unsigned int size, align = 0;
3048 type_t *type = var->type;
3050 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3051 for ( ; type->size_is ; type = type->ref)
3053 write_expr(file, type->size_is, TRUE);
3054 fprintf(file, " * ");
3056 size = type_memsize(type, &align);
3057 fprintf(file, "%u);\n", size);
3059 else if (!is_string)
3061 fprintf(file, " = &_W%u;\n", i);
3062 if (is_ptr(var->type) && !last_ptr(var->type))
3063 print_file(file, indent, "_W%u = 0;\n", i);
3071 fprintf(file, "\n");
3075 int write_expr_eval_routines(FILE *file, const char *iface)
3077 static const char *var_name = "pS";
3079 struct expr_eval_routine *eval;
3080 unsigned short callback_offset = 0;
3082 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3084 const char *name = eval->structure->name;
3085 const var_list_t *fields = eval->structure->fields;
3088 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3089 iface, name, callback_offset);
3090 print_file(file, 0, "{\n");
3091 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3092 name, var_name, name, eval->baseoff);
3093 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3094 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3095 write_struct_expr(file, eval->expr, 1, fields, var_name);
3096 fprintf(file, ";\n");
3097 print_file(file, 0, "}\n\n");
3103 void write_expr_eval_routine_list(FILE *file, const char *iface)
3105 struct expr_eval_routine *eval;
3106 struct expr_eval_routine *cursor;
3107 unsigned short callback_offset = 0;
3109 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3110 fprintf(file, "{\n");
3112 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3114 const char *name = eval->structure->name;
3115 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3117 list_remove(&eval->entry);
3121 fprintf(file, "};\n\n");
3124 void write_user_quad_list(FILE *file)
3128 if (list_empty(&user_type_list))
3131 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3132 fprintf(file, "{\n");
3133 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3135 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3136 print_file(file, 1, "{\n");
3137 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3138 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3139 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3140 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3141 print_file(file, 1, "}%s\n", sep);
3143 fprintf(file, "};\n\n");
3146 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3148 const struct str_list_entry_t *endpoint;
3151 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3152 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3153 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3155 print_file( f, 1, "{ (const unsigned char *)\"" );
3156 for (p = endpoint->str; *p && *p != ':'; p++)
3158 if (*p == '"' || *p == '\\') fputc( '\\', f );
3161 if (!*p) goto error;
3162 if (p[1] != '[') goto error;
3164 fprintf( f, "\", (const unsigned char *)\"" );
3165 for (p += 2; *p && *p != ']'; p++)
3167 if (*p == '"' || *p == '\\') fputc( '\\', f );
3170 if (*p != ']') goto error;
3171 fprintf( f, "\" },\n" );
3173 print_file( f, 0, "};\n\n" );
3177 error("Invalid endpoint syntax '%s'\n", endpoint->str);