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"
40 #include "wine/list.h"
44 static const func_t *current_func;
45 static const type_t *current_structure;
47 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
48 struct expr_eval_routine
51 const type_t *structure;
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)
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";
109 error("string_of_type: unknown type 0x%02x\n", type);
114 int is_struct(unsigned char type)
121 case RPC_FC_CPSTRUCT:
122 case RPC_FC_CVSTRUCT:
123 case RPC_FC_BOGUS_STRUCT:
130 static int is_non_complex_struct(const type_t *type)
137 case RPC_FC_CPSTRUCT:
138 case RPC_FC_CVSTRUCT:
145 int is_union(unsigned char type)
149 case RPC_FC_ENCAPSULATED_UNION:
150 case RPC_FC_NON_ENCAPSULATED_UNION:
157 static int type_has_pointers(const type_t *type)
159 if (is_user_type(type))
161 else if (is_ptr(type))
163 else if (is_array(type))
164 return type_has_pointers(type->ref);
165 else if (is_struct(type->type))
168 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
170 if (type_has_pointers(field->type))
174 else if (is_union(type->type))
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;
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))
195 static unsigned short user_type_offset(const char *name)
198 unsigned short off = 0;
199 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
201 if (strcmp(name, ut->name) == 0)
205 error("user_type_offset: couldn't find type (%s)\n", name);
209 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
211 type->typestring_offset = offset;
212 if (file) type->tfswrite = FALSE;
215 static void guard_rec(type_t *type)
217 /* types that contain references to themselves (like a linked list),
218 need to be shielded from infinite recursion when writing embedded
220 if (type->typestring_offset)
221 type->tfswrite = FALSE;
223 type->typestring_offset = 1;
226 static type_t *get_user_type(const type_t *t, const char **pname)
230 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
238 if (t->kind == TKIND_ALIAS)
245 int is_user_type(const type_t *t)
247 return get_user_type(t, NULL) != NULL;
250 static int is_embedded_complex(const type_t *type)
252 unsigned char tc = type->type;
253 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
254 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
257 static const char *get_context_handle_type_name(const type_t *type)
260 for (t = type; is_ptr(t); t = t->ref)
261 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
267 /* This is actually fairly involved to implement precisely, due to the
268 effects attributes may have and things like that. Right now this is
269 only used for optimization, so just check for a very small set of
270 criteria that guarantee the types are equivalent; assume every thing
271 else is different. */
272 static int compare_type(const type_t *a, const type_t *b)
277 && strcmp(a->name, b->name) == 0))
279 /* Ordering doesn't need to be implemented yet. */
283 static int compare_expr(const expr_t *a, const expr_t *b)
287 if (a->type != b->type)
288 return a->type - b->type;
295 return a->u.lval - b->u.lval;
297 return a->u.dval - b->u.dval;
298 case EXPR_IDENTIFIER:
299 return strcmp(a->u.sval, b->u.sval);
301 ret = compare_expr(a->ref, b->ref);
304 ret = compare_expr(a->u.ext, b->u.ext);
307 return compare_expr(a->ext2, b->ext2);
316 ret = compare_expr(a->ref, b->ref);
319 return compare_expr(a->u.ext, b->u.ext);
321 ret = compare_type(a->u.tref, b->u.tref);
329 return compare_expr(a->ref, b->ref);
331 return compare_type(a->u.tref, b->u.tref);
338 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
341 fprintf(file, "/* %2u */\n", typestring_offset); \
342 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
346 static void print_file(FILE *file, int indent, const char *format, ...)
349 va_start(va, format);
350 print(file, indent, format, va);
354 void print(FILE *file, int indent, const char *format, va_list va)
358 if (format[0] != '\n')
361 vfprintf(file, format, va);
366 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n)
368 if (decl_indirect(t))
369 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof(%s));\n", n, n);
370 else if (is_ptr(t) || is_array(t))
371 print_file(file, indent, "%s = 0;\n", n);
374 void write_parameters_init(FILE *file, int indent, const func_t *func)
378 if (!is_void(func->def->type))
379 write_var_init(file, indent, func->def->type, "_RetVal");
384 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
385 write_var_init(file, indent, var->type, var->name);
390 static void write_formatdesc(FILE *f, int indent, const char *str)
392 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
393 print_file(f, indent, "{\n");
394 print_file(f, indent + 1, "short Pad;\n");
395 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
396 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
397 print_file(f, indent, "\n");
400 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
402 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
403 get_size_typeformatstring(ifaces, pred));
405 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
406 get_size_procformatstring(ifaces, pred));
409 write_formatdesc(f, indent, "TYPE");
410 write_formatdesc(f, indent, "PROC");
412 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
413 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
414 print_file(f, indent, "\n");
417 static inline int is_base_type(unsigned char type)
436 case RPC_FC_ERROR_STATUS_T:
437 case RPC_FC_BIND_PRIMITIVE:
445 int decl_indirect(const type_t *t)
447 return is_user_type(t)
448 || (!is_base_type(t->type)
453 static size_t write_procformatstring_var(FILE *file, int indent,
454 const var_t *var, int is_return)
457 const type_t *type = var->type;
459 int is_in = is_attr(var->attrs, ATTR_IN);
460 int is_out = is_attr(var->attrs, ATTR_OUT);
462 if (!is_in && !is_out) is_in = TRUE;
464 if (!type->declarray && is_base_type(type->type))
467 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
469 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
471 if (type->type == RPC_FC_BIND_PRIMITIVE)
473 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
474 size = 2; /* includes param type prefix */
476 else if (is_base_type(type->type))
478 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
479 size = 2; /* includes param type prefix */
483 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
490 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
491 else if (is_in && is_out)
492 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
494 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
496 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
498 print_file(file, indent, "0x01,\n");
499 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
500 size = 4; /* includes param type prefix */
505 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
507 const ifref_t *iface;
511 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
512 print_file(file, indent, "{\n");
514 print_file(file, indent, "0,\n");
515 print_file(file, indent, "{\n");
518 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
520 if (!pred(iface->iface))
523 if (iface->iface->funcs)
526 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
528 if (is_local(func->def->attrs)) continue;
529 /* emit argument data */
532 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
533 write_procformatstring_var(file, indent, var, FALSE);
536 /* emit return value data */
538 if (is_void(var->type))
540 print_file(file, indent, "0x5b, /* FC_END */\n");
541 print_file(file, indent, "0x5c, /* FC_PAD */\n");
544 write_procformatstring_var(file, indent, var, TRUE);
549 print_file(file, indent, "0x0\n");
551 print_file(file, indent, "}\n");
553 print_file(file, indent, "};\n");
554 print_file(file, indent, "\n");
557 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
559 if (is_base_type(type->type))
561 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
562 *typestring_offset += 1;
569 /* write conformance / variance descriptor */
570 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
571 unsigned int baseoff, const type_t *type,
574 unsigned char operator_type = 0;
575 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
576 const char *conftype_string = "";
577 const char *operator_string = "no operators";
578 const expr_t *subexpr;
582 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
588 /* Top-level conformance calculations are done inline. */
589 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
590 RPC_FC_TOP_LEVEL_CONFORMANCE);
591 print_file (file, 2, "0x0,\n");
592 print_file (file, 2, "NdrFcShort(0x0),\n");
598 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
599 error("write_conf_or_var_desc: constant value %ld is greater than "
600 "the maximum constant size of %d\n", expr->cval,
601 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
603 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
604 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
605 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
606 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
611 if (is_ptr(type) || (is_array(type) && !type->declarray))
613 conftype = RPC_FC_POINTER_CONFORMANCE;
614 conftype_string = "field pointer, ";
618 switch (subexpr->type)
621 subexpr = subexpr->ref;
622 operator_type = RPC_FC_DEREFERENCE;
623 operator_string = "FC_DEREFERENCE";
626 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
628 subexpr = subexpr->ref;
629 operator_type = RPC_FC_DIV_2;
630 operator_string = "FC_DIV_2";
634 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
636 subexpr = subexpr->ref;
637 operator_type = RPC_FC_MULT_2;
638 operator_string = "FC_MULT_2";
642 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
644 subexpr = subexpr->ref;
645 operator_type = RPC_FC_SUB_1;
646 operator_string = "FC_SUB_1";
650 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
652 subexpr = subexpr->ref;
653 operator_type = RPC_FC_ADD_1;
654 operator_string = "FC_ADD_1";
661 if (subexpr->type == EXPR_IDENTIFIER)
663 const type_t *correlation_variable = NULL;
664 unsigned char correlation_variable_type;
665 unsigned char param_type = 0;
669 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
671 unsigned int align = 0;
672 /* FIXME: take alignment into account */
673 if (var->name && !strcmp(var->name, subexpr->u.sval))
675 correlation_variable = var->type;
678 offset += type_memsize(var->type, &align);
680 if (!correlation_variable)
681 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
685 correlation_variable_type = correlation_variable->type;
687 switch (correlation_variable_type)
691 param_type = RPC_FC_SMALL;
695 param_type = RPC_FC_USMALL;
700 param_type = RPC_FC_SHORT;
703 param_type = RPC_FC_USHORT;
707 param_type = RPC_FC_LONG;
710 param_type = RPC_FC_ULONG;
716 if (sizeof(void *) == 4) /* FIXME */
717 param_type = RPC_FC_LONG;
719 param_type = RPC_FC_HYPER;
722 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
723 correlation_variable_type);
726 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
727 conftype | param_type, conftype_string, string_of_type(param_type));
728 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
729 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
734 unsigned int callback_offset = 0;
735 struct expr_eval_routine *eval;
738 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
740 if (!strcmp (eval->structure->name, structure->name)
741 && !compare_expr (eval->expr, expr))
751 eval = xmalloc (sizeof(*eval));
752 eval->structure = structure;
753 eval->baseoff = baseoff;
755 list_add_tail (&expr_eval_routines, &eval->entry);
758 if (callback_offset > USHRT_MAX)
759 error("Maximum number of callback routines reached\n");
761 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
762 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
763 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
768 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
770 int have_align = FALSE;
774 if (!fields) return 0;
775 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
777 unsigned int falign = 0;
778 size_t fsize = type_memsize(v->type, &falign);
784 size = (size + (falign - 1)) & ~(falign - 1);
788 size = (size + (*align - 1)) & ~(*align - 1);
792 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
794 size_t size, maxs = 0;
795 unsigned int align = *pmaxa;
798 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
800 /* we could have an empty default field with NULL type */
803 size = type_memsize(v->type, &align);
804 if (maxs < size) maxs = size;
805 if (*pmaxa < align) *pmaxa = align;
812 int get_padding(const var_list_t *fields)
814 unsigned short offset = 0;
821 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
823 type_t *ft = f->type;
824 unsigned int align = 0;
825 size_t size = type_memsize(ft, &align);
828 offset = (offset + (align - 1)) & ~(align - 1);
832 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
835 size_t type_memsize(const type_t *t, unsigned int *align)
839 if (t->declarray && is_conformant_array(t))
841 type_memsize(t->ref, align);
844 else if (is_ptr(t) || is_conformant_array(t))
846 size = sizeof(void *);
847 if (size > *align) *align = size;
849 else switch (t->type)
856 if (size > *align) *align = size;
863 if (size > *align) *align = size;
867 case RPC_FC_ERROR_STATUS_T:
871 if (size > *align) *align = size;
876 if (size > *align) *align = size;
879 case RPC_FC_CVSTRUCT:
880 case RPC_FC_CPSTRUCT:
883 case RPC_FC_BOGUS_STRUCT:
884 size = fields_memsize(t->fields, align);
886 case RPC_FC_ENCAPSULATED_UNION:
887 case RPC_FC_NON_ENCAPSULATED_UNION:
888 size = union_memsize(t->fields, align);
890 case RPC_FC_SMFARRAY:
891 case RPC_FC_LGFARRAY:
892 case RPC_FC_SMVARRAY:
893 case RPC_FC_LGVARRAY:
894 case RPC_FC_BOGUS_ARRAY:
895 size = t->dim * type_memsize(t->ref, align);
898 error("type_memsize: Unknown type %d\n", t->type);
905 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
907 short absoff = type->ref->typestring_offset;
908 short reloff = absoff - (offset + 2);
909 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
911 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
912 type->type, ptr_attr, string_of_type(type->type));
913 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
914 reloff, reloff, absoff);
918 static unsigned char conf_string_type_of_char_type(unsigned char t)
924 return RPC_FC_C_CSTRING;
926 return RPC_FC_C_WSTRING;
929 error("string_type_of_char_type: unrecognized type %d\n", t);
933 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
936 = is_string_type(type->attrs, type)
937 ? conf_string_type_of_char_type(type->ref->type)
939 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
940 type->type, string_of_type(type->type));
941 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
942 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
946 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
948 print_file(file, 0, "/* %u (", tfsoff);
949 write_type_decl(file, t, NULL);
950 print_file(file, 0, ") */\n");
953 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
955 unsigned int offset = *typestring_offset;
957 print_start_tfs_comment(file, type, offset);
958 update_tfsoff(type, offset, file);
960 if (type->ref->typestring_offset)
961 *typestring_offset += write_nonsimple_pointer(file, type, offset);
962 else if (is_base_type(type->ref->type))
963 *typestring_offset += write_simple_pointer(file, type);
968 static int processed(const type_t *type)
970 return type->typestring_offset && !type->tfswrite;
973 static int user_type_has_variable_size(const type_t *t)
982 case RPC_FC_CPSTRUCT:
983 case RPC_FC_CVSTRUCT:
986 /* Note: Since this only applies to user types, we can't have a conformant
987 array here, and strings should get filed under pointer in this case. */
991 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
993 unsigned int start, absoff, flags;
994 unsigned int align = 0, ualign = 0;
996 type_t *utype = get_user_type(type, &name);
997 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
998 size_t size = type_memsize(type, &align);
999 unsigned short funoff = user_type_offset(name);
1004 if (is_base_type(utype->type))
1007 print_start_tfs_comment(file, utype, absoff);
1008 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
1009 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1014 if (!processed(utype))
1015 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
1016 absoff = utype->typestring_offset;
1019 if (utype->type == RPC_FC_RP)
1021 else if (utype->type == RPC_FC_UP)
1027 update_tfsoff(type, start, file);
1028 print_start_tfs_comment(file, type, start);
1029 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
1030 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1031 flags | (align - 1), align - 1, flags);
1032 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
1033 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
1034 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
1036 reloff = absoff - *tfsoff;
1037 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
1041 static void write_member_type(FILE *file, const type_t *cont,
1042 const attr_list_t *attrs, const type_t *type,
1043 unsigned int *corroff, unsigned int *tfsoff)
1045 if (is_embedded_complex(type) && !is_conformant_array(type))
1050 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1057 absoff = type->typestring_offset;
1059 reloff = absoff - (*tfsoff + 2);
1061 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1062 /* FIXME: actually compute necessary padding */
1063 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1064 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1065 reloff, reloff, absoff);
1068 else if (is_ptr(type) || is_conformant_array(type))
1070 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1073 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1076 else if (!write_base_type(file, type, tfsoff))
1077 error("Unsupported member type 0x%x\n", type->type);
1080 static void write_end(FILE *file, unsigned int *tfsoff)
1082 if (*tfsoff % 2 == 0)
1084 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1087 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1091 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1093 unsigned int offset = 0;
1094 var_list_t *fs = type->fields;
1097 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1099 unsigned int align = 0;
1100 type_t *ft = f->type;
1101 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1103 unsigned int absoff = ft->typestring_offset;
1104 short reloff = absoff - (*tfsoff + 6);
1105 print_file(file, 0, "/* %d */\n", *tfsoff);
1106 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1107 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1108 write_conf_or_var_desc(file, current_structure, offset, ft,
1109 get_attrp(f->attrs, ATTR_SWITCHIS));
1110 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1111 reloff, reloff, absoff);
1115 /* FIXME: take alignment into account */
1116 offset += type_memsize(ft, &align);
1120 static int write_no_repeat_pointer_descriptions(
1121 FILE *file, type_t *type,
1122 size_t *offset_in_memory, size_t *offset_in_buffer,
1123 unsigned int *typestring_offset)
1128 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1130 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1131 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1133 /* pointer instance */
1134 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1135 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1136 *typestring_offset += 6;
1139 write_pointer_tfs(file, type, typestring_offset);
1142 unsigned absoff = type->typestring_offset;
1143 short reloff = absoff - (*typestring_offset + 2);
1144 /* FIXME: get pointer attributes from field */
1145 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1146 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1147 reloff, reloff, absoff);
1148 *typestring_offset += 4;
1152 *offset_in_memory += type_memsize(type, &align);
1153 /* FIXME: is there a case where these two are different? */
1155 *offset_in_buffer += type_memsize(type, &align);
1160 if (is_non_complex_struct(type))
1163 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1164 written += write_no_repeat_pointer_descriptions(
1166 offset_in_memory, offset_in_buffer, typestring_offset);
1171 *offset_in_memory += type_memsize(type, &align);
1172 /* FIXME: is there a case where these two are different? */
1174 *offset_in_buffer += type_memsize(type, &align);
1180 static int write_pointer_description_offsets(
1181 FILE *file, const attr_list_t *attrs, type_t *type,
1182 size_t *offset_in_memory, size_t *offset_in_buffer,
1183 unsigned int *typestring_offset)
1188 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1190 if (offset_in_memory && offset_in_buffer)
1192 /* pointer instance */
1193 /* FIXME: sometimes from end of structure, sometimes from beginning */
1194 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1195 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1198 *offset_in_memory += type_memsize(type, &align);
1199 /* FIXME: is there a case where these two are different? */
1201 *offset_in_buffer += type_memsize(type, &align);
1203 *typestring_offset += 4;
1205 if (processed(type->ref) || is_base_type(type->ref->type))
1206 write_pointer_tfs(file, type, typestring_offset);
1208 error("write_pointer_description_offsets: type format string unknown\n");
1215 return write_pointer_description_offsets(
1216 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1219 else if (is_non_complex_struct(type))
1221 /* otherwise search for interesting fields to parse */
1223 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1225 written += write_pointer_description_offsets(
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);
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_fixed_array_pointer_descriptions(
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)
1252 int pointer_count = 0;
1254 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1256 unsigned int temp = 0;
1257 /* unfortunately, this needs to be done in two passes to avoid
1258 * writing out redundant FC_FIXED_REPEAT descriptions */
1259 pointer_count = write_pointer_description_offsets(
1260 NULL, attrs, type->ref, NULL, NULL, &temp);
1261 if (pointer_count > 0)
1263 unsigned int increment_size;
1264 size_t offset_of_array_pointer_mem = 0;
1265 size_t offset_of_array_pointer_buf = 0;
1268 increment_size = type_memsize(type->ref, &align);
1270 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1271 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1272 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1273 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1274 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1275 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1276 *typestring_offset += 10;
1278 pointer_count = write_pointer_description_offsets(
1279 file, attrs, type, &offset_of_array_pointer_mem,
1280 &offset_of_array_pointer_buf, typestring_offset);
1283 else if (is_struct(type->type))
1286 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1288 pointer_count += write_fixed_array_pointer_descriptions(
1289 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1296 if (offset_in_memory)
1297 *offset_in_memory += type_memsize(type, &align);
1298 /* FIXME: is there a case where these two are different? */
1300 if (offset_in_buffer)
1301 *offset_in_buffer += type_memsize(type, &align);
1304 return pointer_count;
1307 /* Note: if file is NULL return value is number of pointers to write, else
1308 * it is the number of type format characters written */
1309 static int write_conformant_array_pointer_descriptions(
1310 FILE *file, const attr_list_t *attrs, type_t *type,
1311 size_t offset_in_memory, unsigned int *typestring_offset)
1314 int pointer_count = 0;
1316 if (is_conformant_array(type) && !type->length_is)
1318 unsigned int temp = 0;
1319 /* unfortunately, this needs to be done in two passes to avoid
1320 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1321 pointer_count = write_pointer_description_offsets(
1322 NULL, attrs, type->ref, NULL, NULL, &temp);
1323 if (pointer_count > 0)
1325 unsigned int increment_size;
1326 size_t offset_of_array_pointer_mem = offset_in_memory;
1327 size_t offset_of_array_pointer_buf = offset_in_memory;
1330 increment_size = type_memsize(type->ref, &align);
1332 if (increment_size > USHRT_MAX)
1333 error("array size of %u bytes is too large\n", increment_size);
1335 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1336 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1337 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1338 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1339 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1340 *typestring_offset += 8;
1342 pointer_count = write_pointer_description_offsets(
1343 file, attrs, type->ref, &offset_of_array_pointer_mem,
1344 &offset_of_array_pointer_buf, typestring_offset);
1348 return pointer_count;
1351 /* Note: if file is NULL return value is number of pointers to write, else
1352 * it is the number of type format characters written */
1353 static int write_varying_array_pointer_descriptions(
1354 FILE *file, const attr_list_t *attrs, type_t *type,
1355 size_t *offset_in_memory, size_t *offset_in_buffer,
1356 unsigned int *typestring_offset)
1359 int pointer_count = 0;
1361 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1363 if (is_array(type) && type->length_is)
1365 unsigned int temp = 0;
1366 /* unfortunately, this needs to be done in two passes to avoid
1367 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1368 pointer_count = write_pointer_description_offsets(
1369 NULL, attrs, type->ref, NULL, NULL, &temp);
1370 if (pointer_count > 0)
1372 unsigned int increment_size;
1373 size_t offset_of_array_pointer_mem = 0;
1374 size_t offset_of_array_pointer_buf = 0;
1377 increment_size = type_memsize(type->ref, &align);
1379 if (increment_size > USHRT_MAX)
1380 error("array size of %u bytes is too large\n", increment_size);
1382 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1383 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1384 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1385 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1386 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1387 *typestring_offset += 8;
1389 pointer_count = write_pointer_description_offsets(
1390 file, attrs, type, &offset_of_array_pointer_mem,
1391 &offset_of_array_pointer_buf, typestring_offset);
1394 else if (is_struct(type->type))
1397 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1399 pointer_count += write_varying_array_pointer_descriptions(
1400 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1407 if (offset_in_memory)
1408 *offset_in_memory += type_memsize(type, &align);
1409 /* FIXME: is there a case where these two are different? */
1411 if (offset_in_buffer)
1412 *offset_in_buffer += type_memsize(type, &align);
1415 return pointer_count;
1418 static void write_pointer_description(FILE *file, type_t *type,
1419 unsigned int *typestring_offset)
1421 size_t offset_in_buffer;
1422 size_t offset_in_memory;
1424 /* pass 1: search for single instance of a pointer (i.e. don't descend
1426 if (!is_array(type))
1428 offset_in_memory = 0;
1429 offset_in_buffer = 0;
1430 write_no_repeat_pointer_descriptions(
1432 &offset_in_memory, &offset_in_buffer, typestring_offset);
1435 /* pass 2: search for pointers in fixed arrays */
1436 offset_in_memory = 0;
1437 offset_in_buffer = 0;
1438 write_fixed_array_pointer_descriptions(
1440 &offset_in_memory, &offset_in_buffer, typestring_offset);
1442 /* pass 3: search for pointers in conformant only arrays (but don't descend
1443 * into conformant varying or varying arrays) */
1444 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1445 write_conformant_array_pointer_descriptions(
1446 file, NULL, type, 0, typestring_offset);
1447 else if (type->type == RPC_FC_CPSTRUCT)
1449 unsigned int align = 0;
1450 type_t *carray = find_array_or_string_in_struct(type)->type;
1451 write_conformant_array_pointer_descriptions(
1453 type_memsize(type, &align),
1457 /* pass 4: search for pointers in varying arrays */
1458 offset_in_memory = 0;
1459 offset_in_buffer = 0;
1460 write_varying_array_pointer_descriptions(
1462 &offset_in_memory, &offset_in_buffer, typestring_offset);
1465 int is_declptr(const type_t *t)
1467 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1470 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1472 const char *name, unsigned int *typestring_offset,
1475 size_t start_offset = *typestring_offset;
1476 unsigned char rtype;
1478 update_tfsoff(type, start_offset, file);
1480 if (toplevel && is_declptr(type))
1482 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1483 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1485 pointer_type = RPC_FC_RP;
1486 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1487 pointer_type, flag, string_of_type(pointer_type),
1488 flag ? " [simple_pointer]" : "");
1489 *typestring_offset += 2;
1492 print_file(file, 2, "NdrFcShort(0x2),\n");
1493 *typestring_offset += 2;
1497 rtype = type->ref->type;
1499 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1501 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1502 return start_offset;
1505 if (type->declarray && !is_conformant_array(type))
1507 /* FIXME: multi-dimensional array */
1508 if (0xffffuL < type->dim)
1509 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1510 name, 0xffffu, type->dim - 0xffffu);
1512 if (rtype == RPC_FC_CHAR)
1513 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1515 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1516 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1517 *typestring_offset += 2;
1519 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1520 *typestring_offset += 2;
1522 return start_offset;
1524 else if (type->size_is)
1526 unsigned int align = 0;
1528 if (rtype == RPC_FC_CHAR)
1529 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1531 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1532 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1533 *typestring_offset += 2;
1535 *typestring_offset += write_conf_or_var_desc(
1536 file, current_structure,
1537 (type->declarray && current_structure
1538 ? type_memsize(current_structure, &align)
1540 type, type->size_is);
1542 return start_offset;
1546 if (rtype == RPC_FC_WCHAR)
1547 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1549 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1550 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1551 *typestring_offset += 2;
1553 return start_offset;
1557 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1558 const char *name, unsigned int *typestring_offset)
1560 const expr_t *length_is = type->length_is;
1561 const expr_t *size_is = type->size_is;
1562 unsigned int align = 0;
1564 size_t start_offset;
1566 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1567 unsigned int baseoff
1568 = type->declarray && current_structure
1569 ? type_memsize(current_structure, &align)
1573 pointer_type = RPC_FC_RP;
1575 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1578 has_pointer = type_has_pointers(type->ref);
1581 size = type_memsize((is_conformant_array(type) ? type->ref : type), &align);
1583 start_offset = *typestring_offset;
1584 update_tfsoff(type, start_offset, file);
1585 print_start_tfs_comment(file, type, start_offset);
1586 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1587 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1588 *typestring_offset += 2;
1591 if (type->type != RPC_FC_BOGUS_ARRAY)
1593 unsigned char tc = type->type;
1595 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1597 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1598 *typestring_offset += 4;
1602 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1603 *typestring_offset += 2;
1606 if (is_conformant_array(type))
1608 += write_conf_or_var_desc(file, current_structure, baseoff,
1611 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1613 unsigned int elalign = 0;
1614 size_t elsize = type_memsize(type->ref, &elalign);
1616 if (type->type == RPC_FC_LGVARRAY)
1618 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1619 *typestring_offset += 4;
1623 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1624 *typestring_offset += 2;
1627 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1628 *typestring_offset += 2;
1633 += write_conf_or_var_desc(file, current_structure, baseoff,
1636 if (has_pointer && (!type->declarray || !current_structure))
1638 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1639 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1640 *typestring_offset += 2;
1641 write_pointer_description(file, type, typestring_offset);
1642 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1643 *typestring_offset += 1;
1646 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1647 write_end(file, typestring_offset);
1651 unsigned int dim = size_is ? 0 : type->dim;
1652 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1653 *typestring_offset += 2;
1655 += write_conf_or_var_desc(file, current_structure, baseoff,
1658 += write_conf_or_var_desc(file, current_structure, baseoff,
1660 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1661 write_end(file, typestring_offset);
1664 return start_offset;
1667 static const var_t *find_array_or_string_in_struct(const type_t *type)
1669 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1670 const type_t *ft = last_field->type;
1672 if (ft->declarray && is_conformant_array(ft))
1675 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1676 return find_array_or_string_in_struct(last_field->type);
1681 static void write_struct_members(FILE *file, const type_t *type,
1682 unsigned int *corroff, unsigned int *typestring_offset)
1685 unsigned short offset = 0;
1689 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1691 type_t *ft = field->type;
1692 if (!ft->declarray || !is_conformant_array(ft))
1694 unsigned int align = 0;
1695 size_t size = type_memsize(ft, &align);
1698 if ((align - 1) & offset)
1700 unsigned char fc = 0;
1704 fc = RPC_FC_ALIGNM4;
1707 fc = RPC_FC_ALIGNM8;
1710 error("write_struct_members: cannot align type %d\n", ft->type);
1712 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1713 offset = (offset + (align - 1)) & ~(align - 1);
1714 *typestring_offset += 1;
1716 write_member_type(file, type, field->attrs, field->type, corroff,
1722 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1725 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1726 RPC_FC_STRUCTPAD1 + padding - 1,
1728 *typestring_offset += 1;
1731 write_end(file, typestring_offset);
1734 static size_t write_struct_tfs(FILE *file, type_t *type,
1735 const char *name, unsigned int *tfsoff)
1737 const type_t *save_current_structure = current_structure;
1738 unsigned int total_size;
1740 size_t start_offset;
1741 size_t array_offset;
1742 int has_pointers = 0;
1743 unsigned int align = 0;
1744 unsigned int corroff;
1748 current_structure = type;
1750 total_size = type_memsize(type, &align);
1751 if (total_size > USHRT_MAX)
1752 error("structure size for %s exceeds %d bytes by %d bytes\n",
1753 name, USHRT_MAX, total_size - USHRT_MAX);
1755 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1756 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1758 if (!has_pointers) has_pointers = type_has_pointers(type);
1760 array = find_array_or_string_in_struct(type);
1761 if (array && !processed(array->type))
1763 = is_attr(array->attrs, ATTR_STRING)
1764 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff, FALSE)
1765 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1768 write_descriptors(file, type, tfsoff);
1770 start_offset = *tfsoff;
1771 update_tfsoff(type, start_offset, file);
1772 print_start_tfs_comment(file, type, start_offset);
1773 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1774 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1775 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1780 unsigned int absoff = array->type->typestring_offset;
1781 short reloff = absoff - *tfsoff;
1782 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1783 reloff, reloff, absoff);
1786 else if (type->type == RPC_FC_BOGUS_STRUCT)
1788 print_file(file, 2, "NdrFcShort(0x0),\n");
1792 if (type->type == RPC_FC_BOGUS_STRUCT)
1794 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1795 nothing is written to file yet. On the actual writing pass,
1796 this will have been updated. */
1797 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1798 short reloff = absoff - *tfsoff;
1799 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1800 reloff, reloff, absoff);
1803 else if ((type->type == RPC_FC_PSTRUCT) ||
1804 (type->type == RPC_FC_CPSTRUCT) ||
1805 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1807 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1808 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1810 write_pointer_description(file, type, tfsoff);
1811 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1815 write_struct_members(file, type, &corroff, tfsoff);
1817 if (type->type == RPC_FC_BOGUS_STRUCT)
1819 const var_list_t *fs = type->fields;
1822 type->ptrdesc = *tfsoff;
1823 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1825 type_t *ft = f->type;
1827 write_pointer_tfs(file, ft, tfsoff);
1828 else if (!ft->declarray && is_conformant_array(ft))
1830 unsigned int absoff = ft->typestring_offset;
1831 short reloff = absoff - (*tfsoff + 2);
1832 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1833 /* FIXME: We need to store pointer attributes for arrays
1834 so we don't lose pointer_default info. */
1836 ptr_type = RPC_FC_UP;
1837 print_file(file, 0, "/* %d */\n", *tfsoff);
1838 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1839 string_of_type(ptr_type));
1840 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1841 reloff, reloff, absoff);
1845 if (type->ptrdesc == *tfsoff)
1849 current_structure = save_current_structure;
1850 return start_offset;
1853 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1854 unsigned char flags, size_t offset,
1855 unsigned int *typeformat_offset)
1857 size_t start_offset = *typeformat_offset;
1858 short reloff = offset - (*typeformat_offset + 2);
1859 int in_attr, out_attr;
1860 in_attr = is_attr(attrs, ATTR_IN);
1861 out_attr = is_attr(attrs, ATTR_OUT);
1862 if (!in_attr && !out_attr) in_attr = 1;
1864 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1867 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1870 string_of_type(pointer_type));
1874 fprintf(file, " [allocated_on_stack]");
1876 fprintf(file, " [pointer_deref]");
1877 fprintf(file, " */\n");
1880 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1881 *typeformat_offset += 4;
1883 return start_offset;
1886 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1890 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1892 else if (is_base_type(t->type))
1894 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1895 t->type, string_of_type(t->type));
1897 else if (t->typestring_offset)
1899 short reloff = t->typestring_offset - *tfsoff;
1900 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1901 reloff, reloff, t->typestring_offset);
1904 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1909 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1911 unsigned int align = 0;
1912 unsigned int start_offset;
1913 size_t size = type_memsize(type, &align);
1916 type_t *deftype = NULL;
1917 short nodeftype = 0xffff;
1922 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1924 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1925 fields = uv->type->fields;
1928 fields = type->fields;
1930 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1932 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1934 nbranch += list_count(cases);
1936 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1939 start_offset = *tfsoff;
1940 update_tfsoff(type, start_offset, file);
1941 print_start_tfs_comment(file, type, start_offset);
1942 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1944 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1945 const type_t *st = sv->type;
1958 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1959 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1960 0x40 | st->type, string_of_type(st->type));
1964 error("union switch type must be an integer, char, or enum\n");
1967 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1968 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1971 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1973 type_t *ft = f->type;
1974 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1975 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1978 if (cases == NULL && !deflt)
1979 error("union field %s with neither case nor default attribute\n", f->name);
1981 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1983 /* MIDL doesn't check for duplicate cases, even though that seems
1984 like a reasonable thing to do, it just dumps them to the TFS
1985 like we're going to do here. */
1986 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1988 write_branch_type(file, ft, tfsoff);
1991 /* MIDL allows multiple default branches, even though that seems
1992 illogical, it just chooses the last one, which is what we will
2003 write_branch_type(file, deftype, tfsoff);
2007 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
2011 return start_offset;
2014 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2015 unsigned int *typeformat_offset)
2018 size_t start_offset = *typeformat_offset;
2019 expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
2023 print_file(file, 2, "0x2f, /* FC_IP */\n");
2024 print_file(file, 2, "0x5c, /* FC_PAD */\n");
2026 += write_conf_or_var_desc(file, NULL, 0, type, iid) + 2;
2030 const type_t *base = is_ptr(type) ? type->ref : type;
2031 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
2034 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
2036 update_tfsoff(type, start_offset, file);
2037 print_start_tfs_comment(file, type, start_offset);
2038 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2039 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2040 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2041 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2042 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2043 for (i = 0; i < 8; ++i)
2044 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2047 fprintf(file, "\n");
2049 *typeformat_offset += 18;
2051 return start_offset;
2054 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2056 unsigned int *typeformat_offset)
2058 size_t start_offset = *typeformat_offset;
2059 unsigned char flags = 0x08 /* strict */;
2064 if (type->type != RPC_FC_RP)
2067 if (is_attr(var->attrs, ATTR_IN))
2069 if (is_attr(var->attrs, ATTR_OUT))
2072 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2073 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2074 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2075 print_file(file, 0, "can't be null, ");
2077 print_file(file, 0, "serialize, ");
2079 print_file(file, 0, "no serialize, ");
2081 print_file(file, 0, "strict, ");
2082 if ((flags & 0x21) == 0x20)
2083 print_file(file, 0, "out, ");
2084 if ((flags & 0x21) == 0x21)
2085 print_file(file, 0, "return, ");
2087 print_file(file, 0, "in, ");
2089 print_file(file, 0, "via ptr, ");
2090 print_file(file, 0, "*/\n");
2091 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2092 print_file(file, 2, "0, /* FIXME: param num */\n");
2093 *typeformat_offset += 4;
2095 return start_offset;
2098 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2099 type_t *type, const var_t *var,
2100 unsigned int *typeformat_offset)
2104 if (is_context_handle(type))
2105 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2107 if (is_user_type(type))
2109 write_user_tfs(file, type, typeformat_offset);
2110 return type->typestring_offset;
2113 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2114 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset, TRUE);
2120 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2121 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2122 /* Top level pointers to conformant arrays may be handled specially
2123 since we can bypass the pointer, but if the array is burried
2124 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2125 always need to write the pointer. */
2126 if (!ptr_type && var->type != type)
2127 /* FIXME: This should use pointer_default, but the information
2128 isn't kept around for arrays. */
2129 ptr_type = RPC_FC_UP;
2130 if (ptr_type && ptr_type != RPC_FC_RP)
2132 unsigned int absoff = type->typestring_offset;
2133 short reloff = absoff - (*typeformat_offset + 2);
2134 off = *typeformat_offset;
2135 print_file(file, 0, "/* %d */\n", off);
2136 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2137 string_of_type(ptr_type));
2138 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2139 reloff, reloff, absoff);
2140 *typeformat_offset += 4;
2147 /* basic types don't need a type format string */
2148 if (is_base_type(type->type))
2154 case RPC_FC_PSTRUCT:
2155 case RPC_FC_CSTRUCT:
2156 case RPC_FC_CPSTRUCT:
2157 case RPC_FC_CVSTRUCT:
2158 case RPC_FC_BOGUS_STRUCT:
2159 return write_struct_tfs(file, type, var->name, typeformat_offset);
2160 case RPC_FC_ENCAPSULATED_UNION:
2161 case RPC_FC_NON_ENCAPSULATED_UNION:
2162 return write_union_tfs(file, type, typeformat_offset);
2164 case RPC_FC_BIND_PRIMITIVE:
2168 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2171 else if (last_ptr(type))
2173 size_t start_offset = *typeformat_offset;
2174 int in_attr = is_attr(var->attrs, ATTR_IN);
2175 int out_attr = is_attr(var->attrs, ATTR_OUT);
2176 const type_t *base = type->ref;
2178 if (base->type == RPC_FC_IP
2180 && is_attr(var->attrs, ATTR_IIDIS)))
2182 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2185 /* special case for pointers to base types */
2186 if (is_base_type(base->type))
2188 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2189 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2190 string_of_type(type->type),
2191 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2192 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2193 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2194 *typeformat_offset += 4;
2195 return start_offset;
2199 assert(is_ptr(type));
2201 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2203 fprintf(file, "/* %2u */\n", *typeformat_offset);
2204 return write_pointer_only_tfs(file, var->attrs, type->type,
2205 !last_ptr(type) ? 0x10 : 0,
2206 offset, typeformat_offset);
2209 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2210 const char *name, int write_ptr, unsigned int *tfsoff)
2214 if (is_user_type(type))
2216 write_user_tfs(file, type, tfsoff);
2218 else if (is_ptr(type))
2220 type_t *ref = type->ref;
2222 if (ref->type == RPC_FC_IP
2224 && is_attr(attrs, ATTR_IIDIS)))
2226 write_ip_tfs(file, attrs, type, tfsoff);
2230 if (!processed(ref) && !is_base_type(ref->type))
2231 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2234 write_pointer_tfs(file, type, tfsoff);
2239 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2241 write_string_tfs(file, attrs, type, name, tfsoff, FALSE);
2243 else if (type->declarray && is_conformant_array(type))
2244 ; /* conformant arrays and strings are handled specially */
2245 else if (is_array(type))
2247 write_array_tfs(file, attrs, type, name, tfsoff);
2248 if (is_conformant_array(type))
2251 else if (is_struct(type->type))
2253 if (!processed(type))
2254 write_struct_tfs(file, type, name, tfsoff);
2256 else if (is_union(type->type))
2258 if (!processed(type))
2259 write_union_tfs(file, type, tfsoff);
2261 else if (!is_base_type(type->type))
2262 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2268 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2271 const ifref_t *iface;
2272 unsigned int typeformat_offset = 2;
2274 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2276 if (!pred(iface->iface))
2279 if (iface->iface->funcs)
2282 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2284 if (is_local(func->def->attrs)) continue;
2286 current_func = func;
2288 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2291 write_typeformatstring_var(
2292 file, 2, func, var->type, var,
2293 &typeformat_offset),
2299 return typeformat_offset + 1;
2303 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2307 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2308 print_file(file, indent, "{\n");
2310 print_file(file, indent, "0,\n");
2311 print_file(file, indent, "{\n");
2313 print_file(file, indent, "NdrFcShort(0x0),\n");
2315 set_all_tfswrite(TRUE);
2316 process_tfs(file, ifaces, pred);
2318 print_file(file, indent, "0x0\n");
2320 print_file(file, indent, "}\n");
2322 print_file(file, indent, "};\n");
2323 print_file(file, indent, "\n");
2326 static unsigned int get_required_buffer_size_type(
2327 const type_t *type, const char *name, unsigned int *alignment)
2330 if (is_user_type(type))
2333 const type_t *utype = get_user_type(type, &uname);
2334 return get_required_buffer_size_type(utype, uname, alignment);
2358 case RPC_FC_ERROR_STATUS_T:
2368 case RPC_FC_BIND_PRIMITIVE:
2372 case RPC_FC_PSTRUCT:
2376 if (!type->fields) return 0;
2377 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2379 unsigned int alignment;
2380 size += get_required_buffer_size_type(field->type, field->name,
2388 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2389 ? get_required_buffer_size_type( type->ref, name, alignment )
2392 case RPC_FC_SMFARRAY:
2393 case RPC_FC_LGFARRAY:
2394 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2402 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2404 int in_attr = is_attr(var->attrs, ATTR_IN);
2405 int out_attr = is_attr(var->attrs, ATTR_OUT);
2408 if (!in_attr && !out_attr)
2413 for (t = var->type; is_ptr(t); t = t->ref)
2414 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2420 if (pass == PASS_OUT)
2422 if (out_attr && is_ptr(var->type))
2424 type_t *type = var->type;
2426 if (type->type == RPC_FC_STRUCT)
2429 unsigned int size = 36;
2431 if (!type->fields) return size;
2432 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2435 size += get_required_buffer_size_type(
2436 field->type, field->name, &align);
2445 if ((!out_attr || in_attr) && !var->type->size_is
2446 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2448 if (is_ptr(var->type))
2450 type_t *type = var->type;
2452 if (is_base_type(type->type))
2456 else if (type->type == RPC_FC_STRUCT)
2458 unsigned int size = 36;
2461 if (!type->fields) return size;
2462 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2465 size += get_required_buffer_size_type(
2466 field->type, field->name, &align);
2473 return get_required_buffer_size_type(var->type, var->name, alignment);
2477 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2480 unsigned int total_size = 0, alignment;
2484 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2486 total_size += get_required_buffer_size(var, &alignment, pass);
2487 total_size += alignment;
2491 if (pass == PASS_OUT && !is_void(func->def->type))
2493 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2494 total_size += alignment;
2499 static void print_phase_function(FILE *file, int indent, const char *type,
2500 enum remoting_phase phase,
2501 const var_t *var, unsigned int type_offset)
2503 const char *function;
2506 case PHASE_BUFFERSIZE:
2507 function = "BufferSize";
2510 function = "Marshall";
2512 case PHASE_UNMARSHAL:
2513 function = "Unmarshall";
2523 print_file(file, indent, "Ndr%s%s(\n", type, function);
2525 print_file(file, indent, "&_StubMsg,\n");
2526 print_file(file, indent, "%s%s%s%s,\n",
2527 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2528 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2529 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2531 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2532 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2533 if (phase == PHASE_UNMARSHAL)
2534 print_file(file, indent, "0);\n");
2538 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2539 enum pass pass, const var_t *var,
2540 const char *varname)
2542 type_t *type = var->type;
2544 unsigned int alignment = 0;
2545 unsigned char rtype;
2547 /* no work to do for other phases, buffer sizing is done elsewhere */
2548 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2551 rtype = is_ptr(type) ? type->ref->type : type->type;
2575 case RPC_FC_ERROR_STATUS_T:
2587 case RPC_FC_BIND_PRIMITIVE:
2588 /* no marshalling needed */
2592 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2596 if (phase == PHASE_MARSHAL)
2597 print_file(file, indent, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
2598 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2599 alignment - 1, alignment - 1);
2601 if (phase == PHASE_MARSHAL)
2603 print_file(file, indent, "*(");
2604 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2606 fprintf(file, " *)_StubMsg.Buffer = *");
2608 fprintf(file, " *)_StubMsg.Buffer = ");
2609 fprintf(file, "%s", varname);
2610 fprintf(file, ";\n");
2612 else if (phase == PHASE_UNMARSHAL)
2614 if (pass == PASS_IN || pass == PASS_RETURN)
2615 print_file(file, indent, "");
2617 print_file(file, indent, "*");
2618 fprintf(file, "%s", varname);
2619 if (pass == PASS_IN && is_ptr(type))
2620 fprintf(file, " = (");
2622 fprintf(file, " = *(");
2623 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2624 fprintf(file, " *)_StubMsg.Buffer;\n");
2627 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2628 write_type_decl(file, var->type, NULL);
2629 fprintf(file, ");\n");
2632 /* returns whether the MaxCount, Offset or ActualCount members need to be
2633 * filled in for the specified phase */
2634 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2636 return (phase != PHASE_UNMARSHAL);
2639 expr_t *get_size_is_expr(const type_t *t, const char *name)
2643 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2649 error("%s: multidimensional conformant"
2650 " arrays not supported at the top level\n",
2657 static void write_remoting_arg(FILE *file, int indent, const func_t *func,
2658 enum pass pass, enum remoting_phase phase,
2661 int in_attr, out_attr, pointer_type;
2662 const type_t *type = var->type;
2663 unsigned char rtype;
2664 size_t start_offset = type->typestring_offset;
2666 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2668 pointer_type = RPC_FC_RP;
2670 in_attr = is_attr(var->attrs, ATTR_IN);
2671 out_attr = is_attr(var->attrs, ATTR_OUT);
2672 if (!in_attr && !out_attr)
2675 if (phase != PHASE_FREE)
2679 if (!in_attr) return;
2682 if (!out_attr) return;
2690 if (is_context_handle(type))
2692 if (phase == PHASE_MARSHAL)
2694 if (pass == PASS_IN)
2696 print_file(file, indent, "NdrClientContextMarshall(\n");
2697 print_file(file, indent + 1, "&_StubMsg,\n");
2698 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2699 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2703 print_file(file, indent, "NdrServerContextMarshall(\n");
2704 print_file(file, indent + 1, "&_StubMsg,\n");
2705 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2706 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2709 else if (phase == PHASE_UNMARSHAL)
2711 if (pass == PASS_OUT)
2713 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2714 print_file(file, indent + 1, "&_StubMsg,\n");
2715 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2716 print_file(file, indent + 1, "_Handle);\n");
2719 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2722 else if (is_user_type(var->type))
2724 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2726 else if (is_string_type(var->attrs, var->type))
2728 if (is_array(type) && !is_conformant_array(type))
2729 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2732 if (type->size_is && is_size_needed_for_phase(phase))
2734 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2735 write_expr(file, type->size_is, 1);
2736 fprintf(file, ";\n");
2739 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2740 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2742 print_phase_function(file, indent, "ConformantString", phase, var,
2743 start_offset + (type->size_is ? 4 : 2));
2746 else if (is_array(type))
2748 unsigned char tc = type->type;
2749 const char *array_type = "FixedArray";
2751 /* We already have the size_is expression since it's at the
2752 top level, but do checks for multidimensional conformant
2753 arrays. When we handle them, we'll need to extend this
2754 function to return a list, and then we'll actually use
2755 the return value. */
2756 get_size_is_expr(type, var->name);
2758 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2760 if (is_size_needed_for_phase(phase))
2762 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2763 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2764 write_expr(file, type->length_is, 1);
2765 fprintf(file, ";\n\n");
2767 array_type = "VaryingArray";
2769 else if (tc == RPC_FC_CARRAY)
2771 if (is_size_needed_for_phase(phase))
2773 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2774 write_expr(file, type->size_is, 1);
2775 fprintf(file, ";\n\n");
2777 array_type = "ConformantArray";
2779 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2781 if (is_size_needed_for_phase(phase))
2785 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2786 write_expr(file, type->size_is, 1);
2787 fprintf(file, ";\n");
2789 if (type->length_is)
2791 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2792 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2793 write_expr(file, type->length_is, 1);
2794 fprintf(file, ";\n\n");
2797 array_type = (tc == RPC_FC_BOGUS_ARRAY
2799 : "ConformantVaryingArray");
2802 if (pointer_type != RPC_FC_RP) array_type = "Pointer";
2803 print_phase_function(file, indent, array_type, phase, var, start_offset);
2804 if (phase == PHASE_FREE && type->declarray && pointer_type == RPC_FC_RP)
2806 /* these are all unmarshalled by pointing into the buffer on the
2808 if (type->type == RPC_FC_BOGUS_ARRAY ||
2809 type->type == RPC_FC_CVARRAY ||
2810 (type->type == RPC_FC_SMVARRAY && type->type == RPC_FC_LGVARRAY && in_attr) ||
2811 (type->type == RPC_FC_CARRAY && type->type == RPC_FC_CARRAY && !in_attr))
2813 print_file(file, indent, "if (%s)\n", var->name);
2815 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2819 else if (!is_ptr(var->type) && is_base_type(rtype))
2821 if (phase != PHASE_FREE)
2822 print_phase_basetype(file, indent, phase, pass, var, var->name);
2824 else if (!is_ptr(var->type))
2829 case RPC_FC_PSTRUCT:
2830 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2832 case RPC_FC_CSTRUCT:
2833 case RPC_FC_CPSTRUCT:
2834 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2836 case RPC_FC_CVSTRUCT:
2837 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2839 case RPC_FC_BOGUS_STRUCT:
2840 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2843 if (is_base_type( var->type->ref->type ))
2845 print_phase_basetype(file, indent, phase, pass, var, var->name);
2847 else if (var->type->ref->type == RPC_FC_STRUCT)
2849 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2850 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2855 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2857 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2858 write_expr( file, iid, 1 );
2859 fprintf( file, ";\n\n" );
2861 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2865 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2870 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2872 if (phase != PHASE_FREE)
2873 print_phase_basetype(file, indent, phase, pass, var, var->name);
2875 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2877 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2878 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2883 expr_t *sx = get_size_is_expr(type, var->name);
2885 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2887 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2888 write_expr( file, iid, 1 );
2889 fprintf( file, ";\n\n" );
2893 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2894 write_expr(file, sx, 1);
2895 fprintf(file, ";\n\n");
2897 if (var->type->ref->type == RPC_FC_IP)
2898 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2900 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2903 fprintf(file, "\n");
2906 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2907 enum pass pass, enum remoting_phase phase)
2909 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN)
2911 unsigned int size = get_function_buffer_size( func, pass );
2912 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2915 if (pass == PASS_RETURN)
2919 var.name = xstrdup( "_RetVal" );
2920 write_remoting_arg( file, indent, func, pass, phase, &var );
2928 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2929 write_remoting_arg( file, indent, func, pass, phase, var );
2934 size_t get_size_procformatstring_var(const var_t *var)
2936 return write_procformatstring_var(NULL, 0, var, FALSE);
2940 size_t get_size_procformatstring_func(const func_t *func)
2945 /* argument list size */
2947 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2948 size += get_size_procformatstring_var(var);
2950 /* return value size */
2951 if (is_void(func->def->type))
2952 size += 2; /* FC_END and FC_PAD */
2954 size += get_size_procformatstring_var(func->def);
2959 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2961 const ifref_t *iface;
2965 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2967 if (!pred(iface->iface))
2970 if (iface->iface->funcs)
2971 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2972 if (!is_local(func->def->attrs))
2973 size += get_size_procformatstring_func( func );
2978 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2980 set_all_tfswrite(FALSE);
2981 return process_tfs(NULL, ifaces, pred);
2984 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2985 const var_list_t *fields, const char *structvar)
2991 fprintf(h, "%lu", e->u.lval);
2994 fprintf(h, "0x%lx", e->u.lval);
2997 fprintf(h, "%#.15g", e->u.dval);
2999 case EXPR_TRUEFALSE:
3001 fprintf(h, "FALSE");
3005 case EXPR_IDENTIFIER:
3008 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3009 if (!strcmp(e->u.sval, field->name))
3011 fprintf(h, "%s->%s", structvar, e->u.sval);
3015 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
3020 write_struct_expr(h, e->ref, 1, fields, structvar);
3024 write_struct_expr(h, e->ref, 1, fields, structvar);
3028 write_struct_expr(h, e->ref, 1, fields, structvar);
3032 write_type_decl(h, e->u.tref, NULL);
3034 write_struct_expr(h, e->ref, 1, fields, structvar);
3037 fprintf(h, "sizeof(");
3038 write_type_decl(h, e->u.tref, NULL);
3049 if (brackets) fprintf(h, "(");
3050 write_struct_expr(h, e->ref, 1, fields, structvar);
3052 case EXPR_SHL: fprintf(h, " << "); break;
3053 case EXPR_SHR: fprintf(h, " >> "); break;
3054 case EXPR_MUL: fprintf(h, " * "); break;
3055 case EXPR_DIV: fprintf(h, " / "); break;
3056 case EXPR_ADD: fprintf(h, " + "); break;
3057 case EXPR_SUB: fprintf(h, " - "); break;
3058 case EXPR_AND: fprintf(h, " & "); break;
3059 case EXPR_OR: fprintf(h, " | "); break;
3062 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3063 if (brackets) fprintf(h, ")");
3066 if (brackets) fprintf(h, "(");
3067 write_struct_expr(h, e->ref, 1, fields, structvar);
3069 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3071 write_struct_expr(h, e->ext2, 1, fields, structvar);
3072 if (brackets) fprintf(h, ")");
3074 case EXPR_ADDRESSOF:
3076 write_struct_expr(h, e->ref, 1, fields, structvar);
3082 void declare_stub_args( FILE *file, int indent, const func_t *func )
3084 int in_attr, out_attr;
3086 const var_t *def = func->def;
3089 /* declare return value '_RetVal' */
3090 if (!is_void(def->type))
3092 print_file(file, indent, "");
3093 write_type_decl_left(file, def->type);
3094 fprintf(file, " _RetVal;\n");
3100 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3102 int is_string = is_attr(var->attrs, ATTR_STRING);
3104 in_attr = is_attr(var->attrs, ATTR_IN);
3105 out_attr = is_attr(var->attrs, ATTR_OUT);
3106 if (!out_attr && !in_attr)
3109 if (is_context_handle(var->type))
3110 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3113 if (!in_attr && !var->type->size_is && !is_string)
3115 print_file(file, indent, "");
3116 write_type_decl(file, var->type->declarray ? var->type : var->type->ref,
3118 fprintf(file, ";\n");
3121 print_file(file, indent, "");
3122 write_type_decl_left(file, var->type);
3124 if (var->type->declarray) {
3125 fprintf(file, "( *");
3126 write_name(file, var);
3127 fprintf(file, " )");
3129 write_name(file, var);
3130 write_type_right(file, var->type, FALSE);
3131 fprintf(file, ";\n");
3133 if (decl_indirect(var->type))
3134 print_file(file, indent, "void *_p_%s = &%s;\n",
3135 var->name, var->name);
3141 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3143 int in_attr, out_attr;
3150 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3152 int is_string = is_attr(var->attrs, ATTR_STRING);
3153 in_attr = is_attr(var->attrs, ATTR_IN);
3154 out_attr = is_attr(var->attrs, ATTR_OUT);
3155 if (!out_attr && !in_attr)
3160 print_file(file, indent, "");
3161 write_name(file, var);
3163 if (var->type->size_is)
3165 unsigned int size, align = 0;
3166 type_t *type = var->type;
3168 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3169 for ( ; type->size_is ; type = type->ref)
3171 write_expr(file, type->size_is, TRUE);
3172 fprintf(file, " * ");
3174 size = type_memsize(type, &align);
3175 fprintf(file, "%u);\n", size);
3177 else if (!is_string)
3179 fprintf(file, " = &_W%u;\n", i);
3180 if (is_ptr(var->type) && !last_ptr(var->type))
3181 print_file(file, indent, "_W%u = 0;\n", i);
3189 fprintf(file, "\n");
3193 int write_expr_eval_routines(FILE *file, const char *iface)
3195 static const char *var_name = "pS";
3197 struct expr_eval_routine *eval;
3198 unsigned short callback_offset = 0;
3200 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3202 const char *name = eval->structure->name;
3203 const var_list_t *fields = eval->structure->fields;
3206 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3207 iface, name, callback_offset);
3208 print_file(file, 0, "{\n");
3209 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3210 name, var_name, name, eval->baseoff);
3211 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3212 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3213 write_struct_expr(file, eval->expr, 1, fields, var_name);
3214 fprintf(file, ";\n");
3215 print_file(file, 0, "}\n\n");
3221 void write_expr_eval_routine_list(FILE *file, const char *iface)
3223 struct expr_eval_routine *eval;
3224 struct expr_eval_routine *cursor;
3225 unsigned short callback_offset = 0;
3227 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3228 fprintf(file, "{\n");
3230 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3232 const char *name = eval->structure->name;
3233 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3235 list_remove(&eval->entry);
3239 fprintf(file, "};\n\n");
3242 void write_user_quad_list(FILE *file)
3246 if (list_empty(&user_type_list))
3249 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3250 fprintf(file, "{\n");
3251 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3253 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3254 print_file(file, 1, "{\n");
3255 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3256 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3257 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3258 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3259 print_file(file, 1, "}%s\n", sep);
3261 fprintf(file, "};\n\n");
3264 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3266 const struct str_list_entry_t *endpoint;
3269 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3270 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3271 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3273 print_file( f, 1, "{ (const unsigned char *)\"" );
3274 for (p = endpoint->str; *p && *p != ':'; p++)
3276 if (*p == '"' || *p == '\\') fputc( '\\', f );
3279 if (!*p) goto error;
3280 if (p[1] != '[') goto error;
3282 fprintf( f, "\", (const unsigned char *)\"" );
3283 for (p += 2; *p && *p != ']'; p++)
3285 if (*p == '"' || *p == '\\') fputc( '\\', f );
3288 if (*p != ']') goto error;
3289 fprintf( f, "\" },\n" );
3291 print_file( f, 0, "};\n\n" );
3295 error("Invalid endpoint syntax '%s'\n", endpoint->str);