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"
45 static const func_t *current_func;
46 static const type_t *current_structure;
48 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
49 struct expr_eval_routine
52 const type_t *structure;
57 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
58 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
59 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
60 const char *name, int write_ptr, unsigned int *tfsoff);
61 static const var_t *find_array_or_string_in_struct(const type_t *type);
63 const char *string_of_type(unsigned char type)
67 case RPC_FC_BYTE: return "FC_BYTE";
68 case RPC_FC_CHAR: return "FC_CHAR";
69 case RPC_FC_SMALL: return "FC_SMALL";
70 case RPC_FC_USMALL: return "FC_USMALL";
71 case RPC_FC_WCHAR: return "FC_WCHAR";
72 case RPC_FC_SHORT: return "FC_SHORT";
73 case RPC_FC_USHORT: return "FC_USHORT";
74 case RPC_FC_LONG: return "FC_LONG";
75 case RPC_FC_ULONG: return "FC_ULONG";
76 case RPC_FC_FLOAT: return "FC_FLOAT";
77 case RPC_FC_HYPER: return "FC_HYPER";
78 case RPC_FC_DOUBLE: return "FC_DOUBLE";
79 case RPC_FC_ENUM16: return "FC_ENUM16";
80 case RPC_FC_ENUM32: return "FC_ENUM32";
81 case RPC_FC_IGNORE: return "FC_IGNORE";
82 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
83 case RPC_FC_RP: return "FC_RP";
84 case RPC_FC_UP: return "FC_UP";
85 case RPC_FC_OP: return "FC_OP";
86 case RPC_FC_FP: return "FC_FP";
87 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
88 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
89 case RPC_FC_STRUCT: return "FC_STRUCT";
90 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
91 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
92 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
93 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
94 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
95 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
96 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
97 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
98 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
99 case RPC_FC_CARRAY: return "FC_CARRAY";
100 case RPC_FC_CVARRAY: return "FC_CVARRAY";
101 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
102 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
103 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
104 case RPC_FC_POINTER: return "FC_POINTER";
105 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
106 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
107 case RPC_FC_CSTRING: return "FC_CSTRING";
108 case RPC_FC_WSTRING: return "FC_WSTRING";
110 error("string_of_type: unknown type 0x%02x\n", type);
115 int is_struct(unsigned char type)
122 case RPC_FC_CPSTRUCT:
123 case RPC_FC_CVSTRUCT:
124 case RPC_FC_BOGUS_STRUCT:
131 static int is_non_complex_struct(const type_t *type)
138 case RPC_FC_CPSTRUCT:
139 case RPC_FC_CVSTRUCT:
146 int is_union(unsigned char type)
150 case RPC_FC_ENCAPSULATED_UNION:
151 case RPC_FC_NON_ENCAPSULATED_UNION:
158 static unsigned short user_type_offset(const char *name)
161 unsigned short off = 0;
162 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
164 if (strcmp(name, ut->name) == 0)
168 error("user_type_offset: couldn't find type (%s)\n", name);
172 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
174 type->typestring_offset = offset;
175 if (file) type->tfswrite = FALSE;
178 static void guard_rec(type_t *type)
180 /* types that contain references to themselves (like a linked list),
181 need to be shielded from infinite recursion when writing embedded
183 if (type->typestring_offset)
184 type->tfswrite = FALSE;
186 type->typestring_offset = 1;
189 static type_t *get_user_type(const type_t *t, const char **pname)
193 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
201 if (t->kind == TKIND_ALIAS)
208 int is_user_type(const type_t *t)
210 return get_user_type(t, NULL) != NULL;
213 static int is_embedded_complex(const type_t *type)
215 unsigned char tc = type->type;
216 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
217 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
220 static const char *get_context_handle_type_name(const type_t *type)
223 for (t = type; is_ptr(t); t = t->ref)
224 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
230 /* This is actually fairly involved to implement precisely, due to the
231 effects attributes may have and things like that. Right now this is
232 only used for optimization, so just check for a very small set of
233 criteria that guarantee the types are equivalent; assume every thing
234 else is different. */
235 static int compare_type(const type_t *a, const type_t *b)
240 && strcmp(a->name, b->name) == 0))
242 /* Ordering doesn't need to be implemented yet. */
246 static int compare_expr(const expr_t *a, const expr_t *b)
250 if (a->type != b->type)
251 return a->type - b->type;
258 return a->u.lval - b->u.lval;
260 return a->u.dval - b->u.dval;
261 case EXPR_IDENTIFIER:
262 return strcmp(a->u.sval, b->u.sval);
264 ret = compare_expr(a->ref, b->ref);
267 ret = compare_expr(a->u.ext, b->u.ext);
270 return compare_expr(a->ext2, b->ext2);
279 ret = compare_expr(a->ref, b->ref);
282 return compare_expr(a->u.ext, b->u.ext);
284 ret = compare_type(a->u.tref, b->u.tref);
291 return compare_expr(a->ref, b->ref);
293 return compare_type(a->u.tref, b->u.tref);
300 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
303 fprintf(file, "/* %2u */\n", typestring_offset); \
304 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
308 static void print_file(FILE *file, int indent, const char *format, ...)
311 va_start(va, format);
312 print(file, indent, format, va);
316 void print(FILE *file, int indent, const char *format, va_list va)
320 if (format[0] != '\n')
323 vfprintf(file, format, va);
327 void write_parameters_init(FILE *file, int indent, const func_t *func)
334 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
336 const type_t *t = var->type;
337 const char *n = var->name;
338 if (decl_indirect(t))
339 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
340 else if (is_ptr(t) || is_array(t))
341 print_file(file, indent, "%s = 0;\n", n);
347 static void write_formatdesc(FILE *f, int indent, const char *str)
349 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
350 print_file(f, indent, "{\n");
351 print_file(f, indent + 1, "short Pad;\n");
352 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
353 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
354 print_file(f, indent, "\n");
357 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
359 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
360 get_size_typeformatstring(ifaces, pred));
362 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
363 get_size_procformatstring(ifaces, pred));
366 write_formatdesc(f, indent, "TYPE");
367 write_formatdesc(f, indent, "PROC");
369 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
370 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
371 print_file(f, indent, "\n");
374 static inline int is_base_type(unsigned char type)
393 case RPC_FC_ERROR_STATUS_T:
394 case RPC_FC_BIND_PRIMITIVE:
402 int decl_indirect(const type_t *t)
404 return is_user_type(t)
405 || (!is_base_type(t->type)
410 static size_t write_procformatstring_var(FILE *file, int indent,
411 const var_t *var, int is_return)
414 const type_t *type = var->type;
416 int is_in = is_attr(var->attrs, ATTR_IN);
417 int is_out = is_attr(var->attrs, ATTR_OUT);
419 if (!is_in && !is_out) is_in = TRUE;
421 if (!type->declarray && is_base_type(type->type))
424 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
426 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
428 if (type->type == RPC_FC_BIND_PRIMITIVE)
430 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
431 size = 2; /* includes param type prefix */
433 else if (is_base_type(type->type))
435 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
436 size = 2; /* includes param type prefix */
440 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
447 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
448 else if (is_in && is_out)
449 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
451 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
453 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
455 print_file(file, indent, "0x01,\n");
456 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
457 size = 4; /* includes param type prefix */
462 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
464 const ifref_t *iface;
468 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
469 print_file(file, indent, "{\n");
471 print_file(file, indent, "0,\n");
472 print_file(file, indent, "{\n");
475 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
477 if (!pred(iface->iface))
480 if (iface->iface->funcs)
483 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
485 if (is_local(func->def->attrs)) continue;
486 /* emit argument data */
489 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
490 write_procformatstring_var(file, indent, var, FALSE);
493 /* emit return value data */
495 if (is_void(var->type))
497 print_file(file, indent, "0x5b, /* FC_END */\n");
498 print_file(file, indent, "0x5c, /* FC_PAD */\n");
501 write_procformatstring_var(file, indent, var, TRUE);
506 print_file(file, indent, "0x0\n");
508 print_file(file, indent, "}\n");
510 print_file(file, indent, "};\n");
511 print_file(file, indent, "\n");
514 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
516 if (is_base_type(type->type))
518 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
519 *typestring_offset += 1;
526 /* write conformance / variance descriptor */
527 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
528 unsigned int baseoff, const type_t *type,
531 unsigned char operator_type = 0;
532 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
533 const char *conftype_string = "";
534 const char *operator_string = "no operators";
535 const expr_t *subexpr;
539 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
545 /* Top-level conformance calculations are done inline. */
546 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
547 RPC_FC_TOP_LEVEL_CONFORMANCE);
548 print_file (file, 2, "0x0,\n");
549 print_file (file, 2, "NdrFcShort(0x0),\n");
555 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
556 error("write_conf_or_var_desc: constant value %ld is greater than "
557 "the maximum constant size of %d\n", expr->cval,
558 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
560 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
561 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
562 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
563 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
568 if (is_ptr(type) || (is_array(type) && !type->declarray))
570 conftype = RPC_FC_POINTER_CONFORMANCE;
571 conftype_string = "field pointer, ";
575 switch (subexpr->type)
578 subexpr = subexpr->ref;
579 operator_type = RPC_FC_DEREFERENCE;
580 operator_string = "FC_DEREFERENCE";
583 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
585 subexpr = subexpr->ref;
586 operator_type = RPC_FC_DIV_2;
587 operator_string = "FC_DIV_2";
591 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
593 subexpr = subexpr->ref;
594 operator_type = RPC_FC_MULT_2;
595 operator_string = "FC_MULT_2";
599 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
601 subexpr = subexpr->ref;
602 operator_type = RPC_FC_SUB_1;
603 operator_string = "FC_SUB_1";
607 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
609 subexpr = subexpr->ref;
610 operator_type = RPC_FC_ADD_1;
611 operator_string = "FC_ADD_1";
618 if (subexpr->type == EXPR_IDENTIFIER)
620 const type_t *correlation_variable = NULL;
621 unsigned char correlation_variable_type;
622 unsigned char param_type = 0;
626 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
628 unsigned int align = 0;
629 /* FIXME: take alignment into account */
630 if (var->name && !strcmp(var->name, subexpr->u.sval))
632 correlation_variable = var->type;
635 offset += type_memsize(var->type, &align);
637 if (!correlation_variable)
638 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
642 correlation_variable_type = correlation_variable->type;
644 switch (correlation_variable_type)
648 param_type = RPC_FC_SMALL;
652 param_type = RPC_FC_USMALL;
657 param_type = RPC_FC_SHORT;
660 param_type = RPC_FC_USHORT;
664 param_type = RPC_FC_LONG;
667 param_type = RPC_FC_ULONG;
673 if (sizeof(void *) == 4) /* FIXME */
674 param_type = RPC_FC_LONG;
676 param_type = RPC_FC_HYPER;
679 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
680 correlation_variable_type);
683 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
684 conftype | param_type, conftype_string, string_of_type(param_type));
685 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
686 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
691 unsigned int callback_offset = 0;
692 struct expr_eval_routine *eval;
695 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
697 if (!strcmp (eval->structure->name, structure->name)
698 && !compare_expr (eval->expr, expr))
708 eval = xmalloc (sizeof(*eval));
709 eval->structure = structure;
710 eval->baseoff = baseoff;
712 list_add_tail (&expr_eval_routines, &eval->entry);
715 if (callback_offset > USHRT_MAX)
716 error("Maximum number of callback routines reached\n");
718 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
719 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
720 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
725 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
727 int have_align = FALSE;
731 if (!fields) return 0;
732 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
734 unsigned int falign = 0;
735 size_t fsize = type_memsize(v->type, &falign);
741 size = (size + (falign - 1)) & ~(falign - 1);
745 size = (size + (*align - 1)) & ~(*align - 1);
749 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
751 size_t size, maxs = 0;
752 unsigned int align = *pmaxa;
755 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
757 /* we could have an empty default field with NULL type */
760 size = type_memsize(v->type, &align);
761 if (maxs < size) maxs = size;
762 if (*pmaxa < align) *pmaxa = align;
769 int get_padding(const var_list_t *fields)
771 unsigned short offset = 0;
778 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
780 type_t *ft = f->type;
781 unsigned int align = 0;
782 size_t size = type_memsize(ft, &align);
785 offset = (offset + (align - 1)) & ~(align - 1);
789 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
792 size_t type_memsize(const type_t *t, unsigned int *align)
796 if (t->declarray && is_conformant_array(t))
798 type_memsize(t->ref, align);
801 else if (is_ptr(t) || is_conformant_array(t))
803 size = sizeof(void *);
804 if (size > *align) *align = size;
806 else switch (t->type)
813 if (size > *align) *align = size;
820 if (size > *align) *align = size;
824 case RPC_FC_ERROR_STATUS_T:
828 if (size > *align) *align = size;
833 if (size > *align) *align = size;
836 case RPC_FC_CVSTRUCT:
837 case RPC_FC_CPSTRUCT:
840 case RPC_FC_BOGUS_STRUCT:
841 size = fields_memsize(t->fields, align);
843 case RPC_FC_ENCAPSULATED_UNION:
844 case RPC_FC_NON_ENCAPSULATED_UNION:
845 size = union_memsize(t->fields, align);
847 case RPC_FC_SMFARRAY:
848 case RPC_FC_LGFARRAY:
849 case RPC_FC_SMVARRAY:
850 case RPC_FC_LGVARRAY:
851 case RPC_FC_BOGUS_ARRAY:
852 size = t->dim * type_memsize(t->ref, align);
855 error("type_memsize: Unknown type %d\n", t->type);
862 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
864 short absoff = type->ref->typestring_offset;
865 short reloff = absoff - (offset + 2);
866 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
868 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
869 type->type, ptr_attr, string_of_type(type->type));
870 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
871 reloff, reloff, absoff);
875 static unsigned char conf_string_type_of_char_type(unsigned char t)
881 return RPC_FC_C_CSTRING;
883 return RPC_FC_C_WSTRING;
886 error("string_type_of_char_type: unrecognized type %d\n", t);
890 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
893 = is_string_type(type->attrs, type)
894 ? conf_string_type_of_char_type(type->ref->type)
896 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
897 type->type, string_of_type(type->type));
898 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
899 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
903 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
905 print_file(file, 0, "/* %u (", tfsoff);
906 write_type_decl(file, t, NULL);
907 print_file(file, 0, ") */\n");
910 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
912 unsigned int offset = *typestring_offset;
914 print_start_tfs_comment(file, type, offset);
915 update_tfsoff(type, offset, file);
917 if (type->ref->typestring_offset)
918 *typestring_offset += write_nonsimple_pointer(file, type, offset);
919 else if (is_base_type(type->ref->type))
920 *typestring_offset += write_simple_pointer(file, type);
925 static int processed(const type_t *type)
927 return type->typestring_offset && !type->tfswrite;
930 static int user_type_has_variable_size(const type_t *t)
939 case RPC_FC_CPSTRUCT:
940 case RPC_FC_CVSTRUCT:
943 /* Note: Since this only applies to user types, we can't have a conformant
944 array here, and strings should get filed under pointer in this case. */
948 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
950 unsigned int start, absoff, flags;
951 unsigned int align = 0, ualign = 0;
953 type_t *utype = get_user_type(type, &name);
954 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
955 size_t size = type_memsize(type, &align);
956 unsigned short funoff = user_type_offset(name);
961 if (is_base_type(utype->type))
964 print_start_tfs_comment(file, utype, absoff);
965 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
966 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
971 if (!processed(utype))
972 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
973 absoff = utype->typestring_offset;
976 if (utype->type == RPC_FC_RP)
978 else if (utype->type == RPC_FC_UP)
984 update_tfsoff(type, start, file);
985 print_start_tfs_comment(file, type, start);
986 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
987 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
988 flags | (align - 1), align - 1, flags);
989 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
990 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
991 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
993 reloff = absoff - *tfsoff;
994 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
998 static void write_member_type(FILE *file, const type_t *cont,
999 const attr_list_t *attrs, const type_t *type,
1000 unsigned int *corroff, unsigned int *tfsoff)
1002 if (is_embedded_complex(type) && !is_conformant_array(type))
1007 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1014 absoff = type->typestring_offset;
1016 reloff = absoff - (*tfsoff + 2);
1018 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1019 /* FIXME: actually compute necessary padding */
1020 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1021 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1022 reloff, reloff, absoff);
1025 else if (is_ptr(type) || is_conformant_array(type))
1027 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1030 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1033 else if (!write_base_type(file, type, tfsoff))
1034 error("Unsupported member type 0x%x\n", type->type);
1037 static void write_end(FILE *file, unsigned int *tfsoff)
1039 if (*tfsoff % 2 == 0)
1041 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1044 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1048 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1050 unsigned int offset = 0;
1051 var_list_t *fs = type->fields;
1054 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1056 unsigned int align = 0;
1057 type_t *ft = f->type;
1058 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1060 unsigned int absoff = ft->typestring_offset;
1061 short reloff = absoff - (*tfsoff + 6);
1062 print_file(file, 0, "/* %d */\n", *tfsoff);
1063 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1064 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1065 write_conf_or_var_desc(file, current_structure, offset, ft,
1066 get_attrp(f->attrs, ATTR_SWITCHIS));
1067 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1068 reloff, reloff, absoff);
1072 /* FIXME: take alignment into account */
1073 offset += type_memsize(ft, &align);
1077 static int write_no_repeat_pointer_descriptions(
1078 FILE *file, type_t *type,
1079 size_t *offset_in_memory, size_t *offset_in_buffer,
1080 unsigned int *typestring_offset)
1085 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1087 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1088 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1090 /* pointer instance */
1091 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1092 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1093 *typestring_offset += 6;
1096 write_pointer_tfs(file, type, typestring_offset);
1099 unsigned absoff = type->typestring_offset;
1100 short reloff = absoff - (*typestring_offset + 2);
1101 /* FIXME: get pointer attributes from field */
1102 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1103 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1104 reloff, reloff, absoff);
1105 *typestring_offset += 4;
1109 *offset_in_memory += type_memsize(type, &align);
1110 /* FIXME: is there a case where these two are different? */
1112 *offset_in_buffer += type_memsize(type, &align);
1117 if (is_non_complex_struct(type))
1120 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1121 written += write_no_repeat_pointer_descriptions(
1123 offset_in_memory, offset_in_buffer, typestring_offset);
1128 *offset_in_memory += type_memsize(type, &align);
1129 /* FIXME: is there a case where these two are different? */
1131 *offset_in_buffer += type_memsize(type, &align);
1137 static int write_pointer_description_offsets(
1138 FILE *file, const attr_list_t *attrs, type_t *type,
1139 size_t *offset_in_memory, size_t *offset_in_buffer,
1140 unsigned int *typestring_offset)
1145 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1147 if (offset_in_memory && offset_in_buffer)
1149 /* pointer instance */
1150 /* FIXME: sometimes from end of structure, sometimes from beginning */
1151 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1152 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1155 *offset_in_memory += type_memsize(type, &align);
1156 /* FIXME: is there a case where these two are different? */
1158 *offset_in_buffer += type_memsize(type, &align);
1160 *typestring_offset += 4;
1162 if (processed(type->ref) || is_base_type(type->ref->type))
1163 write_pointer_tfs(file, type, typestring_offset);
1165 error("write_pointer_description_offsets: type format string unknown\n");
1172 return write_pointer_description_offsets(
1173 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1176 else if (is_non_complex_struct(type))
1178 /* otherwise search for interesting fields to parse */
1180 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1182 written += write_pointer_description_offsets(
1183 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1190 if (offset_in_memory)
1191 *offset_in_memory += type_memsize(type, &align);
1192 /* FIXME: is there a case where these two are different? */
1194 if (offset_in_buffer)
1195 *offset_in_buffer += type_memsize(type, &align);
1201 /* Note: if file is NULL return value is number of pointers to write, else
1202 * it is the number of type format characters written */
1203 static int write_fixed_array_pointer_descriptions(
1204 FILE *file, const attr_list_t *attrs, type_t *type,
1205 size_t *offset_in_memory, size_t *offset_in_buffer,
1206 unsigned int *typestring_offset)
1209 int pointer_count = 0;
1211 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1213 unsigned int temp = 0;
1214 /* unfortunately, this needs to be done in two passes to avoid
1215 * writing out redundant FC_FIXED_REPEAT descriptions */
1216 pointer_count = write_pointer_description_offsets(
1217 NULL, attrs, type->ref, NULL, NULL, &temp);
1218 if (pointer_count > 0)
1220 unsigned int increment_size;
1221 size_t offset_of_array_pointer_mem = 0;
1222 size_t offset_of_array_pointer_buf = 0;
1225 increment_size = type_memsize(type->ref, &align);
1227 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1228 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1229 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1230 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1231 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1232 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1233 *typestring_offset += 10;
1235 pointer_count = write_pointer_description_offsets(
1236 file, attrs, type, &offset_of_array_pointer_mem,
1237 &offset_of_array_pointer_buf, typestring_offset);
1240 else if (is_struct(type->type))
1243 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1245 pointer_count += write_fixed_array_pointer_descriptions(
1246 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1253 if (offset_in_memory)
1254 *offset_in_memory += type_memsize(type, &align);
1255 /* FIXME: is there a case where these two are different? */
1257 if (offset_in_buffer)
1258 *offset_in_buffer += type_memsize(type, &align);
1261 return pointer_count;
1264 /* Note: if file is NULL return value is number of pointers to write, else
1265 * it is the number of type format characters written */
1266 static int write_conformant_array_pointer_descriptions(
1267 FILE *file, const attr_list_t *attrs, type_t *type,
1268 size_t offset_in_memory, unsigned int *typestring_offset)
1271 int pointer_count = 0;
1273 if (is_conformant_array(type) && !type->length_is)
1275 unsigned int temp = 0;
1276 /* unfortunately, this needs to be done in two passes to avoid
1277 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1278 pointer_count = write_pointer_description_offsets(
1279 NULL, attrs, type->ref, NULL, NULL, &temp);
1280 if (pointer_count > 0)
1282 unsigned int increment_size;
1283 size_t offset_of_array_pointer_mem = offset_in_memory;
1284 size_t offset_of_array_pointer_buf = offset_in_memory;
1287 increment_size = type_memsize(type->ref, &align);
1289 if (increment_size > USHRT_MAX)
1290 error("array size of %u bytes is too large\n", increment_size);
1292 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1293 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1294 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1295 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1296 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1297 *typestring_offset += 8;
1299 pointer_count = write_pointer_description_offsets(
1300 file, attrs, type->ref, &offset_of_array_pointer_mem,
1301 &offset_of_array_pointer_buf, typestring_offset);
1305 return pointer_count;
1308 /* Note: if file is NULL return value is number of pointers to write, else
1309 * it is the number of type format characters written */
1310 static int write_varying_array_pointer_descriptions(
1311 FILE *file, const attr_list_t *attrs, type_t *type,
1312 size_t *offset_in_memory, size_t *offset_in_buffer,
1313 unsigned int *typestring_offset)
1316 int pointer_count = 0;
1318 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1320 if (is_array(type) && type->length_is)
1322 unsigned int temp = 0;
1323 /* unfortunately, this needs to be done in two passes to avoid
1324 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1325 pointer_count = write_pointer_description_offsets(
1326 NULL, attrs, type->ref, NULL, NULL, &temp);
1327 if (pointer_count > 0)
1329 unsigned int increment_size;
1330 size_t offset_of_array_pointer_mem = 0;
1331 size_t offset_of_array_pointer_buf = 0;
1334 increment_size = type_memsize(type->ref, &align);
1336 if (increment_size > USHRT_MAX)
1337 error("array size of %u bytes is too large\n", increment_size);
1339 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1340 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1341 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1342 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1343 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1344 *typestring_offset += 8;
1346 pointer_count = write_pointer_description_offsets(
1347 file, attrs, type, &offset_of_array_pointer_mem,
1348 &offset_of_array_pointer_buf, typestring_offset);
1351 else if (is_struct(type->type))
1354 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1356 pointer_count += write_varying_array_pointer_descriptions(
1357 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1364 if (offset_in_memory)
1365 *offset_in_memory += type_memsize(type, &align);
1366 /* FIXME: is there a case where these two are different? */
1368 if (offset_in_buffer)
1369 *offset_in_buffer += type_memsize(type, &align);
1372 return pointer_count;
1375 static void write_pointer_description(FILE *file, type_t *type,
1376 unsigned int *typestring_offset)
1378 size_t offset_in_buffer;
1379 size_t offset_in_memory;
1381 /* pass 1: search for single instance of a pointer (i.e. don't descend
1383 if (!is_array(type))
1385 offset_in_memory = 0;
1386 offset_in_buffer = 0;
1387 write_no_repeat_pointer_descriptions(
1389 &offset_in_memory, &offset_in_buffer, typestring_offset);
1392 /* pass 2: search for pointers in fixed arrays */
1393 offset_in_memory = 0;
1394 offset_in_buffer = 0;
1395 write_fixed_array_pointer_descriptions(
1397 &offset_in_memory, &offset_in_buffer, typestring_offset);
1399 /* pass 3: search for pointers in conformant only arrays (but don't descend
1400 * into conformant varying or varying arrays) */
1401 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1402 write_conformant_array_pointer_descriptions(
1403 file, NULL, type, 0, typestring_offset);
1404 else if (type->type == RPC_FC_CPSTRUCT)
1406 unsigned int align = 0;
1407 type_t *carray = find_array_or_string_in_struct(type)->type;
1408 write_conformant_array_pointer_descriptions(
1410 type_memsize(type, &align),
1414 /* pass 4: search for pointers in varying arrays */
1415 offset_in_memory = 0;
1416 offset_in_buffer = 0;
1417 write_varying_array_pointer_descriptions(
1419 &offset_in_memory, &offset_in_buffer, typestring_offset);
1422 int is_declptr(const type_t *t)
1424 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1427 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1429 const char *name, unsigned int *typestring_offset)
1431 size_t start_offset = *typestring_offset;
1432 unsigned char rtype;
1434 update_tfsoff(type, start_offset, file);
1436 if (is_declptr(type))
1438 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1439 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1441 pointer_type = RPC_FC_RP;
1442 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1443 pointer_type, flag, string_of_type(pointer_type),
1444 flag ? " [simple_pointer]" : "");
1445 *typestring_offset += 2;
1448 print_file(file, 2, "NdrFcShort(0x2),\n");
1449 *typestring_offset += 2;
1451 rtype = type->ref->type;
1454 rtype = type->ref->type;
1456 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1458 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1459 return start_offset;
1462 if (type->declarray && !is_conformant_array(type))
1464 /* FIXME: multi-dimensional array */
1465 if (0xffffuL < type->dim)
1466 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1467 name, 0xffffu, type->dim - 0xffffu);
1469 if (rtype == RPC_FC_CHAR)
1470 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1472 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1473 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1474 *typestring_offset += 2;
1476 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1477 *typestring_offset += 2;
1479 return start_offset;
1481 else if (type->size_is)
1483 unsigned int align = 0;
1485 if (rtype == RPC_FC_CHAR)
1486 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1488 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1489 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1490 *typestring_offset += 2;
1492 *typestring_offset += write_conf_or_var_desc(
1493 file, current_structure,
1494 (type->declarray && current_structure
1495 ? type_memsize(current_structure, &align)
1497 type, type->size_is);
1499 return start_offset;
1503 if (rtype == RPC_FC_WCHAR)
1504 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1506 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1507 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1508 *typestring_offset += 2;
1510 return start_offset;
1514 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1515 const char *name, unsigned int *typestring_offset)
1517 const expr_t *length_is = type->length_is;
1518 const expr_t *size_is = type->size_is;
1519 unsigned int align = 0;
1521 size_t start_offset;
1523 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1524 unsigned int baseoff
1525 = type->declarray && current_structure
1526 ? type_memsize(current_structure, &align)
1530 pointer_type = RPC_FC_RP;
1532 has_pointer = FALSE;
1533 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1537 size = type_memsize((is_conformant_array(type) ? type->ref : type), &align);
1539 start_offset = *typestring_offset;
1540 update_tfsoff(type, start_offset, file);
1541 print_start_tfs_comment(file, type, start_offset);
1542 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1543 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1544 *typestring_offset += 2;
1547 if (type->type != RPC_FC_BOGUS_ARRAY)
1549 unsigned char tc = type->type;
1551 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1553 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1554 *typestring_offset += 4;
1558 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1559 *typestring_offset += 2;
1562 if (is_conformant_array(type))
1564 += write_conf_or_var_desc(file, current_structure, baseoff,
1567 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1569 unsigned int elalign = 0;
1570 size_t elsize = type_memsize(type->ref, &elalign);
1572 if (type->type == RPC_FC_LGVARRAY)
1574 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1575 *typestring_offset += 4;
1579 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1580 *typestring_offset += 2;
1583 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1584 *typestring_offset += 2;
1589 += write_conf_or_var_desc(file, current_structure, baseoff,
1592 if (has_pointer && (!type->declarray || !current_structure))
1594 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1595 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1596 *typestring_offset += 2;
1597 write_pointer_description(file, type, typestring_offset);
1598 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1599 *typestring_offset += 1;
1602 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1603 write_end(file, typestring_offset);
1607 unsigned int dim = size_is ? 0 : type->dim;
1608 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1609 *typestring_offset += 2;
1611 += write_conf_or_var_desc(file, current_structure, baseoff,
1614 += write_conf_or_var_desc(file, current_structure, baseoff,
1616 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1617 write_end(file, typestring_offset);
1620 return start_offset;
1623 static const var_t *find_array_or_string_in_struct(const type_t *type)
1625 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1626 const type_t *ft = last_field->type;
1628 if (ft->declarray && is_conformant_array(ft))
1631 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1632 return find_array_or_string_in_struct(last_field->type);
1637 static void write_struct_members(FILE *file, const type_t *type,
1638 unsigned int *corroff, unsigned int *typestring_offset)
1641 unsigned short offset = 0;
1645 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1647 type_t *ft = field->type;
1648 if (!ft->declarray || !is_conformant_array(ft))
1650 unsigned int align = 0;
1651 size_t size = type_memsize(ft, &align);
1654 if ((align - 1) & offset)
1656 unsigned char fc = 0;
1660 fc = RPC_FC_ALIGNM4;
1663 fc = RPC_FC_ALIGNM8;
1666 error("write_struct_members: cannot align type %d\n", ft->type);
1668 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1669 offset = (offset + (align - 1)) & ~(align - 1);
1670 *typestring_offset += 1;
1672 write_member_type(file, type, field->attrs, field->type, corroff,
1678 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1681 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1682 RPC_FC_STRUCTPAD1 + padding - 1,
1684 *typestring_offset += 1;
1687 write_end(file, typestring_offset);
1690 static size_t write_struct_tfs(FILE *file, type_t *type,
1691 const char *name, unsigned int *tfsoff)
1693 const type_t *save_current_structure = current_structure;
1694 unsigned int total_size;
1696 size_t start_offset;
1697 size_t array_offset;
1698 int has_pointers = 0;
1699 unsigned int align = 0;
1700 unsigned int corroff;
1704 current_structure = type;
1706 total_size = type_memsize(type, &align);
1707 if (total_size > USHRT_MAX)
1708 error("structure size for %s exceeds %d bytes by %d bytes\n",
1709 name, USHRT_MAX, total_size - USHRT_MAX);
1711 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1712 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1715 array = find_array_or_string_in_struct(type);
1716 if (array && !processed(array->type))
1718 = is_attr(array->attrs, ATTR_STRING)
1719 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1720 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1723 write_descriptors(file, type, tfsoff);
1725 start_offset = *tfsoff;
1726 update_tfsoff(type, start_offset, file);
1727 print_start_tfs_comment(file, type, start_offset);
1728 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1729 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1730 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1735 unsigned int absoff = array->type->typestring_offset;
1736 short reloff = absoff - *tfsoff;
1737 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1738 reloff, reloff, absoff);
1741 else if (type->type == RPC_FC_BOGUS_STRUCT)
1743 print_file(file, 2, "NdrFcShort(0x0),\n");
1747 if (type->type == RPC_FC_BOGUS_STRUCT)
1749 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1750 nothing is written to file yet. On the actual writing pass,
1751 this will have been updated. */
1752 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1753 short reloff = absoff - *tfsoff;
1754 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1755 reloff, reloff, absoff);
1758 else if ((type->type == RPC_FC_PSTRUCT) ||
1759 (type->type == RPC_FC_CPSTRUCT) ||
1760 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1762 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1763 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1765 write_pointer_description(file, type, tfsoff);
1766 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1770 write_struct_members(file, type, &corroff, tfsoff);
1772 if (type->type == RPC_FC_BOGUS_STRUCT)
1774 const var_list_t *fs = type->fields;
1777 type->ptrdesc = *tfsoff;
1778 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1780 type_t *ft = f->type;
1782 write_pointer_tfs(file, ft, tfsoff);
1783 else if (!ft->declarray && is_conformant_array(ft))
1785 unsigned int absoff = ft->typestring_offset;
1786 short reloff = absoff - (*tfsoff + 2);
1787 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1788 /* FIXME: We need to store pointer attributes for arrays
1789 so we don't lose pointer_default info. */
1791 ptr_type = RPC_FC_UP;
1792 print_file(file, 0, "/* %d */\n", *tfsoff);
1793 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1794 string_of_type(ptr_type));
1795 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1796 reloff, reloff, absoff);
1800 if (type->ptrdesc == *tfsoff)
1804 current_structure = save_current_structure;
1805 return start_offset;
1808 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1809 unsigned char flags, size_t offset,
1810 unsigned int *typeformat_offset)
1812 size_t start_offset = *typeformat_offset;
1813 short reloff = offset - (*typeformat_offset + 2);
1814 int in_attr, out_attr;
1815 in_attr = is_attr(attrs, ATTR_IN);
1816 out_attr = is_attr(attrs, ATTR_OUT);
1817 if (!in_attr && !out_attr) in_attr = 1;
1819 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1822 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1825 string_of_type(pointer_type));
1829 fprintf(file, " [allocated_on_stack]");
1831 fprintf(file, " [pointer_deref]");
1832 fprintf(file, " */\n");
1835 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1836 *typeformat_offset += 4;
1838 return start_offset;
1841 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1845 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1847 else if (is_base_type(t->type))
1849 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1850 t->type, string_of_type(t->type));
1852 else if (t->typestring_offset)
1854 short reloff = t->typestring_offset - *tfsoff;
1855 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1856 reloff, reloff, t->typestring_offset);
1859 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1864 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1866 unsigned int align = 0;
1867 unsigned int start_offset;
1868 size_t size = type_memsize(type, &align);
1871 type_t *deftype = NULL;
1872 short nodeftype = 0xffff;
1877 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1879 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1880 fields = uv->type->fields;
1883 fields = type->fields;
1885 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1887 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1889 nbranch += list_count(cases);
1891 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1894 start_offset = *tfsoff;
1895 update_tfsoff(type, start_offset, file);
1896 print_start_tfs_comment(file, type, start_offset);
1897 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1899 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1900 const type_t *st = sv->type;
1913 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1914 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1915 0x40 | st->type, string_of_type(st->type));
1919 error("union switch type must be an integer, char, or enum\n");
1922 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1923 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1926 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1928 type_t *ft = f->type;
1929 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1930 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1933 if (cases == NULL && !deflt)
1934 error("union field %s with neither case nor default attribute\n", f->name);
1936 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1938 /* MIDL doesn't check for duplicate cases, even though that seems
1939 like a reasonable thing to do, it just dumps them to the TFS
1940 like we're going to do here. */
1941 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1943 write_branch_type(file, ft, tfsoff);
1946 /* MIDL allows multiple default branches, even though that seems
1947 illogical, it just chooses the last one, which is what we will
1958 write_branch_type(file, deftype, tfsoff);
1962 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1966 return start_offset;
1969 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1970 unsigned int *typeformat_offset)
1973 size_t start_offset = *typeformat_offset;
1974 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1980 expr.type = EXPR_IDENTIFIER;
1982 expr.u.sval = iid->name;
1983 expr.is_const = FALSE;
1984 print_file(file, 2, "0x2f, /* FC_IP */\n");
1985 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1987 += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
1991 const type_t *base = is_ptr(type) ? type->ref : type;
1992 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1995 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1997 update_tfsoff(type, start_offset, file);
1998 print_start_tfs_comment(file, type, start_offset);
1999 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2000 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2001 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2002 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2003 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2004 for (i = 0; i < 8; ++i)
2005 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2008 fprintf(file, "\n");
2010 *typeformat_offset += 18;
2012 return start_offset;
2015 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2017 unsigned int *typeformat_offset)
2019 size_t start_offset = *typeformat_offset;
2020 unsigned char flags = 0x08 /* strict */;
2025 if (type->type != RPC_FC_RP)
2028 if (is_attr(var->attrs, ATTR_IN))
2030 if (is_attr(var->attrs, ATTR_OUT))
2033 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2034 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2035 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2036 print_file(file, 0, "can't be null, ");
2038 print_file(file, 0, "serialize, ");
2040 print_file(file, 0, "no serialize, ");
2042 print_file(file, 0, "strict, ");
2043 if ((flags & 0x21) == 0x20)
2044 print_file(file, 0, "out, ");
2045 if ((flags & 0x21) == 0x21)
2046 print_file(file, 0, "return, ");
2048 print_file(file, 0, "in, ");
2050 print_file(file, 0, "via ptr, ");
2051 print_file(file, 0, "*/\n");
2052 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2053 print_file(file, 2, "0, /* FIXME: param num */\n");
2054 *typeformat_offset += 4;
2056 return start_offset;
2059 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2060 type_t *type, const var_t *var,
2061 unsigned int *typeformat_offset)
2065 if (is_context_handle(type))
2066 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2068 if (is_user_type(type))
2070 write_user_tfs(file, type, typeformat_offset);
2071 return type->typestring_offset;
2074 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2075 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
2081 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2082 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2083 /* Top level pointers to conformant arrays may be handled specially
2084 since we can bypass the pointer, but if the array is burried
2085 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2086 always need to write the pointer. */
2087 if (!ptr_type && var->type != type)
2088 /* FIXME: This should use pointer_default, but the information
2089 isn't kept around for arrays. */
2090 ptr_type = RPC_FC_UP;
2091 if (ptr_type && ptr_type != RPC_FC_RP)
2093 unsigned int absoff = type->typestring_offset;
2094 short reloff = absoff - (*typeformat_offset + 2);
2095 off = *typeformat_offset;
2096 print_file(file, 0, "/* %d */\n", off);
2097 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2098 string_of_type(ptr_type));
2099 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2100 reloff, reloff, absoff);
2101 *typeformat_offset += 4;
2108 /* basic types don't need a type format string */
2109 if (is_base_type(type->type))
2115 case RPC_FC_PSTRUCT:
2116 case RPC_FC_CSTRUCT:
2117 case RPC_FC_CPSTRUCT:
2118 case RPC_FC_CVSTRUCT:
2119 case RPC_FC_BOGUS_STRUCT:
2120 return write_struct_tfs(file, type, var->name, typeformat_offset);
2121 case RPC_FC_ENCAPSULATED_UNION:
2122 case RPC_FC_NON_ENCAPSULATED_UNION:
2123 return write_union_tfs(file, type, typeformat_offset);
2125 case RPC_FC_BIND_PRIMITIVE:
2129 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2132 else if (last_ptr(type))
2134 size_t start_offset = *typeformat_offset;
2135 int in_attr = is_attr(var->attrs, ATTR_IN);
2136 int out_attr = is_attr(var->attrs, ATTR_OUT);
2137 const type_t *base = type->ref;
2139 if (base->type == RPC_FC_IP
2141 && is_attr(var->attrs, ATTR_IIDIS)))
2143 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2146 /* special case for pointers to base types */
2147 if (is_base_type(base->type))
2149 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2150 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2151 string_of_type(type->type),
2152 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2153 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2154 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2155 *typeformat_offset += 4;
2156 return start_offset;
2160 assert(is_ptr(type));
2162 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2164 fprintf(file, "/* %2u */\n", *typeformat_offset);
2165 return write_pointer_only_tfs(file, var->attrs, type->type,
2166 !last_ptr(type) ? 0x10 : 0,
2167 offset, typeformat_offset);
2170 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2171 const char *name, int write_ptr, unsigned int *tfsoff)
2175 if (is_user_type(type))
2177 write_user_tfs(file, type, tfsoff);
2179 else if (is_ptr(type))
2181 type_t *ref = type->ref;
2183 if (ref->type == RPC_FC_IP
2185 && is_attr(attrs, ATTR_IIDIS)))
2187 write_ip_tfs(file, attrs, type, tfsoff);
2191 if (!processed(ref) && !is_base_type(ref->type))
2192 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2195 write_pointer_tfs(file, type, tfsoff);
2200 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2202 write_string_tfs(file, attrs, type, name, tfsoff);
2204 else if (type->declarray && is_conformant_array(type))
2205 ; /* conformant arrays and strings are handled specially */
2206 else if (is_array(type))
2208 write_array_tfs(file, attrs, type, name, tfsoff);
2209 if (is_conformant_array(type))
2212 else if (is_struct(type->type))
2214 if (!processed(type))
2215 write_struct_tfs(file, type, name, tfsoff);
2217 else if (is_union(type->type))
2219 if (!processed(type))
2220 write_union_tfs(file, type, tfsoff);
2222 else if (!is_base_type(type->type))
2223 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2229 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2232 const ifref_t *iface;
2233 unsigned int typeformat_offset = 2;
2235 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2237 if (!pred(iface->iface))
2240 if (iface->iface->funcs)
2243 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2245 if (is_local(func->def->attrs)) continue;
2247 current_func = func;
2249 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2252 write_typeformatstring_var(
2253 file, 2, func, var->type, var,
2254 &typeformat_offset),
2260 return typeformat_offset + 1;
2264 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2268 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2269 print_file(file, indent, "{\n");
2271 print_file(file, indent, "0,\n");
2272 print_file(file, indent, "{\n");
2274 print_file(file, indent, "NdrFcShort(0x0),\n");
2276 set_all_tfswrite(TRUE);
2277 process_tfs(file, ifaces, pred);
2279 print_file(file, indent, "0x0\n");
2281 print_file(file, indent, "}\n");
2283 print_file(file, indent, "};\n");
2284 print_file(file, indent, "\n");
2287 static unsigned int get_required_buffer_size_type(
2288 const type_t *type, const char *name, unsigned int *alignment)
2291 if (is_user_type(type))
2294 const type_t *utype = get_user_type(type, &uname);
2295 return get_required_buffer_size_type(utype, uname, alignment);
2319 case RPC_FC_ERROR_STATUS_T:
2329 case RPC_FC_BIND_PRIMITIVE:
2333 case RPC_FC_PSTRUCT:
2337 if (!type->fields) return 0;
2338 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2340 unsigned int alignment;
2341 size += get_required_buffer_size_type(field->type, field->name,
2349 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2350 ? get_required_buffer_size_type( type->ref, name, alignment )
2353 case RPC_FC_SMFARRAY:
2354 case RPC_FC_LGFARRAY:
2355 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2363 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2365 int in_attr = is_attr(var->attrs, ATTR_IN);
2366 int out_attr = is_attr(var->attrs, ATTR_OUT);
2369 if (!in_attr && !out_attr)
2374 for (t = var->type; is_ptr(t); t = t->ref)
2375 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2381 if (pass == PASS_OUT)
2383 if (out_attr && is_ptr(var->type))
2385 type_t *type = var->type;
2387 if (type->type == RPC_FC_STRUCT)
2390 unsigned int size = 36;
2392 if (!type->fields) return size;
2393 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2396 size += get_required_buffer_size_type(
2397 field->type, field->name, &align);
2406 if ((!out_attr || in_attr) && !var->type->size_is
2407 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2409 if (is_ptr(var->type))
2411 type_t *type = var->type;
2413 if (is_base_type(type->type))
2417 else if (type->type == RPC_FC_STRUCT)
2419 unsigned int size = 36;
2422 if (!type->fields) return size;
2423 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2426 size += get_required_buffer_size_type(
2427 field->type, field->name, &align);
2434 return get_required_buffer_size_type(var->type, var->name, alignment);
2438 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2441 unsigned int total_size = 0, alignment;
2445 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2447 total_size += get_required_buffer_size(var, &alignment, pass);
2448 total_size += alignment;
2452 if (pass == PASS_OUT && !is_void(func->def->type))
2454 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2455 total_size += alignment;
2460 static void print_phase_function(FILE *file, int indent, const char *type,
2461 enum remoting_phase phase,
2462 const var_t *var, unsigned int type_offset)
2464 const char *function;
2467 case PHASE_BUFFERSIZE:
2468 function = "BufferSize";
2471 function = "Marshall";
2473 case PHASE_UNMARSHAL:
2474 function = "Unmarshall";
2484 print_file(file, indent, "Ndr%s%s(\n", type, function);
2486 print_file(file, indent, "&_StubMsg,\n");
2487 print_file(file, indent, "%s%s%s%s,\n",
2488 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2489 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2490 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2492 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2493 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2494 if (phase == PHASE_UNMARSHAL)
2495 print_file(file, indent, "0);\n");
2499 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2500 enum pass pass, const var_t *var,
2501 const char *varname)
2503 type_t *type = var->type;
2505 unsigned int alignment = 0;
2506 unsigned char rtype;
2508 /* no work to do for other phases, buffer sizing is done elsewhere */
2509 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2512 rtype = is_ptr(type) ? type->ref->type : type->type;
2536 case RPC_FC_ERROR_STATUS_T:
2548 case RPC_FC_BIND_PRIMITIVE:
2549 /* no marshalling needed */
2553 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2557 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2558 alignment - 1, alignment - 1);
2560 if (phase == PHASE_MARSHAL)
2562 print_file(file, indent, "*(");
2563 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2565 fprintf(file, " *)_StubMsg.Buffer = *");
2567 fprintf(file, " *)_StubMsg.Buffer = ");
2568 fprintf(file, "%s", varname);
2569 fprintf(file, ";\n");
2571 else if (phase == PHASE_UNMARSHAL)
2573 if (pass == PASS_IN || pass == PASS_RETURN)
2574 print_file(file, indent, "");
2576 print_file(file, indent, "*");
2577 fprintf(file, "%s", varname);
2578 if (pass == PASS_IN && is_ptr(type))
2579 fprintf(file, " = (");
2581 fprintf(file, " = *(");
2582 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2583 fprintf(file, " *)_StubMsg.Buffer;\n");
2586 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2587 write_type_decl(file, var->type, NULL);
2588 fprintf(file, ");\n");
2591 /* returns whether the MaxCount, Offset or ActualCount members need to be
2592 * filled in for the specified phase */
2593 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2595 return (phase != PHASE_UNMARSHAL);
2598 static int needs_freeing(const attr_list_t *attrs, const type_t *t, int out)
2603 && (t->ref->type == RPC_FC_IP
2604 || is_ptr(t->ref))))
2605 || (out && (is_string_type(attrs, t)
2609 expr_t *get_size_is_expr(const type_t *t, const char *name)
2613 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2619 error("%s: multidimensional conformant"
2620 " arrays not supported at the top level\n",
2627 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2628 enum pass pass, enum remoting_phase phase)
2630 int in_attr, out_attr, pointer_type;
2636 if (phase == PHASE_BUFFERSIZE)
2638 unsigned int size = get_function_buffer_size( func, pass );
2639 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2642 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2644 const type_t *type = var->type;
2645 unsigned char rtype;
2646 size_t start_offset = type->typestring_offset;
2648 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2650 pointer_type = RPC_FC_RP;
2652 in_attr = is_attr(var->attrs, ATTR_IN);
2653 out_attr = is_attr(var->attrs, ATTR_OUT);
2654 if (!in_attr && !out_attr)
2657 if (phase == PHASE_FREE)
2659 if (!needs_freeing(var->attrs, type, out_attr))
2666 if (!in_attr) continue;
2669 if (!out_attr) continue;
2677 if (is_context_handle(type))
2679 if (phase == PHASE_MARSHAL)
2681 if (pass == PASS_IN)
2683 print_file(file, indent, "NdrClientContextMarshall(\n");
2684 print_file(file, indent + 1, "&_StubMsg,\n");
2685 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2686 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2690 print_file(file, indent, "NdrServerContextMarshall(\n");
2691 print_file(file, indent + 1, "&_StubMsg,\n");
2692 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2693 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2696 else if (phase == PHASE_UNMARSHAL)
2698 if (pass == PASS_OUT)
2700 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2701 print_file(file, indent + 1, "&_StubMsg,\n");
2702 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2703 print_file(file, indent + 1, "_Handle);\n");
2706 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2709 else if (is_user_type(var->type))
2711 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2713 else if (is_string_type(var->attrs, var->type))
2715 if (is_array(type) && !is_conformant_array(type))
2716 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2719 if (type->size_is && 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");
2726 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2727 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2729 print_phase_function(file, indent, "ConformantString", phase, var,
2730 start_offset + (type->size_is ? 4 : 2));
2733 else if (is_array(type))
2735 unsigned char tc = type->type;
2736 const char *array_type = "FixedArray";
2738 /* We already have the size_is expression since it's at the
2739 top level, but do checks for multidimensional conformant
2740 arrays. When we handle them, we'll need to extend this
2741 function to return a list, and then we'll actually use
2742 the return value. */
2743 get_size_is_expr(type, var->name);
2745 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2747 if (is_size_needed_for_phase(phase))
2749 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2750 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2751 write_expr(file, type->length_is, 1);
2752 fprintf(file, ";\n\n");
2754 array_type = "VaryingArray";
2756 else if (tc == RPC_FC_CARRAY)
2758 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2760 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2761 write_expr(file, type->size_is, 1);
2762 fprintf(file, ";\n\n");
2764 array_type = "ConformantArray";
2766 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2768 if (is_size_needed_for_phase(phase))
2772 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2773 write_expr(file, type->size_is, 1);
2774 fprintf(file, ";\n");
2776 if (type->length_is)
2778 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2779 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2780 write_expr(file, type->length_is, 1);
2781 fprintf(file, ";\n\n");
2784 array_type = (tc == RPC_FC_BOGUS_ARRAY
2786 : "ConformantVaryingArray");
2789 if (!in_attr && phase == PHASE_FREE)
2791 print_file(file, indent, "if (%s)\n", var->name);
2793 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2795 else if (phase != PHASE_FREE)
2797 const char *t = pointer_type == RPC_FC_RP ? array_type : "Pointer";
2798 print_phase_function(file, indent, t, phase, var, start_offset);
2801 else if (!is_ptr(var->type) && is_base_type(rtype))
2803 print_phase_basetype(file, indent, phase, pass, var, var->name);
2805 else if (!is_ptr(var->type))
2810 case RPC_FC_PSTRUCT:
2811 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2813 case RPC_FC_CSTRUCT:
2814 case RPC_FC_CPSTRUCT:
2815 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2817 case RPC_FC_CVSTRUCT:
2818 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2820 case RPC_FC_BOGUS_STRUCT:
2821 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2824 if (is_base_type( var->type->ref->type ))
2826 print_phase_basetype(file, indent, phase, pass, var, var->name);
2828 else if (var->type->ref->type == RPC_FC_STRUCT)
2830 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2831 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2836 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2837 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2838 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2842 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2847 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2849 print_phase_basetype(file, indent, phase, pass, var, var->name);
2851 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2853 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2854 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2859 expr_t *sx = get_size_is_expr(type, var->name);
2861 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2862 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2865 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2866 write_expr(file, sx, 1);
2867 fprintf(file, ";\n\n");
2869 if (var->type->ref->type == RPC_FC_IP)
2870 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2872 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2875 fprintf(file, "\n");
2880 size_t get_size_procformatstring_var(const var_t *var)
2882 return write_procformatstring_var(NULL, 0, var, FALSE);
2886 size_t get_size_procformatstring_func(const func_t *func)
2891 /* argument list size */
2893 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2894 size += get_size_procformatstring_var(var);
2896 /* return value size */
2897 if (is_void(func->def->type))
2898 size += 2; /* FC_END and FC_PAD */
2900 size += get_size_procformatstring_var(func->def);
2905 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2907 const ifref_t *iface;
2911 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2913 if (!pred(iface->iface))
2916 if (iface->iface->funcs)
2917 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2918 if (!is_local(func->def->attrs))
2919 size += get_size_procformatstring_func( func );
2924 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2926 set_all_tfswrite(FALSE);
2927 return process_tfs(NULL, ifaces, pred);
2930 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2931 const var_list_t *fields, const char *structvar)
2937 fprintf(h, "%lu", e->u.lval);
2940 fprintf(h, "0x%lx", e->u.lval);
2943 fprintf(h, "%#.15g", e->u.dval);
2945 case EXPR_TRUEFALSE:
2947 fprintf(h, "FALSE");
2951 case EXPR_IDENTIFIER:
2954 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2955 if (!strcmp(e->u.sval, field->name))
2957 fprintf(h, "%s->%s", structvar, e->u.sval);
2961 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2966 write_struct_expr(h, e->ref, 1, fields, structvar);
2970 write_struct_expr(h, e->ref, 1, fields, structvar);
2974 write_struct_expr(h, e->ref, 1, fields, structvar);
2978 write_type_decl(h, e->u.tref, NULL);
2980 write_struct_expr(h, e->ref, 1, fields, structvar);
2983 fprintf(h, "sizeof(");
2984 write_type_decl(h, e->u.tref, NULL);
2995 if (brackets) fprintf(h, "(");
2996 write_struct_expr(h, e->ref, 1, fields, structvar);
2998 case EXPR_SHL: fprintf(h, " << "); break;
2999 case EXPR_SHR: fprintf(h, " >> "); break;
3000 case EXPR_MUL: fprintf(h, " * "); break;
3001 case EXPR_DIV: fprintf(h, " / "); break;
3002 case EXPR_ADD: fprintf(h, " + "); break;
3003 case EXPR_SUB: fprintf(h, " - "); break;
3004 case EXPR_AND: fprintf(h, " & "); break;
3005 case EXPR_OR: fprintf(h, " | "); break;
3008 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3009 if (brackets) fprintf(h, ")");
3012 if (brackets) fprintf(h, "(");
3013 write_struct_expr(h, e->ref, 1, fields, structvar);
3015 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3017 write_struct_expr(h, e->ext2, 1, fields, structvar);
3018 if (brackets) fprintf(h, ")");
3024 void declare_stub_args( FILE *file, int indent, const func_t *func )
3026 int in_attr, out_attr;
3028 const var_t *def = func->def;
3031 /* declare return value '_RetVal' */
3032 if (!is_void(def->type))
3034 print_file(file, indent, "");
3035 write_type_decl_left(file, def->type);
3036 fprintf(file, " _RetVal;\n");
3042 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3044 int is_string = is_attr(var->attrs, ATTR_STRING);
3046 in_attr = is_attr(var->attrs, ATTR_IN);
3047 out_attr = is_attr(var->attrs, ATTR_OUT);
3048 if (!out_attr && !in_attr)
3051 if (is_context_handle(var->type))
3052 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3055 if (!in_attr && !var->type->size_is && !is_string)
3057 print_file(file, indent, "");
3058 write_type_decl(file, var->type->ref, "_W%u", i++);
3059 fprintf(file, ";\n");
3062 print_file(file, indent, "");
3063 write_type_decl_left(file, var->type);
3065 if (var->type->declarray) {
3066 fprintf(file, "( *");
3067 write_name(file, var);
3068 fprintf(file, " )");
3070 write_name(file, var);
3071 write_type_right(file, var->type, FALSE);
3072 fprintf(file, ";\n");
3074 if (decl_indirect(var->type))
3075 print_file(file, indent, "void *_p_%s = &%s;\n",
3076 var->name, var->name);
3082 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3084 int in_attr, out_attr;
3091 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3093 int is_string = is_attr(var->attrs, ATTR_STRING);
3094 in_attr = is_attr(var->attrs, ATTR_IN);
3095 out_attr = is_attr(var->attrs, ATTR_OUT);
3096 if (!out_attr && !in_attr)
3101 print_file(file, indent, "");
3102 write_name(file, var);
3104 if (var->type->size_is)
3106 unsigned int size, align = 0;
3107 type_t *type = var->type;
3109 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3110 for ( ; type->size_is ; type = type->ref)
3112 write_expr(file, type->size_is, TRUE);
3113 fprintf(file, " * ");
3115 size = type_memsize(type, &align);
3116 fprintf(file, "%u);\n", size);
3118 else if (!is_string)
3120 fprintf(file, " = &_W%u;\n", i);
3121 if (is_ptr(var->type) && !last_ptr(var->type))
3122 print_file(file, indent, "_W%u = 0;\n", i);
3130 fprintf(file, "\n");
3134 int write_expr_eval_routines(FILE *file, const char *iface)
3136 static const char *var_name = "pS";
3138 struct expr_eval_routine *eval;
3139 unsigned short callback_offset = 0;
3141 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3143 const char *name = eval->structure->name;
3144 const var_list_t *fields = eval->structure->fields;
3147 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3148 iface, name, callback_offset);
3149 print_file(file, 0, "{\n");
3150 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3151 name, var_name, name, eval->baseoff);
3152 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3153 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3154 write_struct_expr(file, eval->expr, 1, fields, var_name);
3155 fprintf(file, ";\n");
3156 print_file(file, 0, "}\n\n");
3162 void write_expr_eval_routine_list(FILE *file, const char *iface)
3164 struct expr_eval_routine *eval;
3165 struct expr_eval_routine *cursor;
3166 unsigned short callback_offset = 0;
3168 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3169 fprintf(file, "{\n");
3171 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3173 const char *name = eval->structure->name;
3174 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3176 list_remove(&eval->entry);
3180 fprintf(file, "};\n\n");
3183 void write_user_quad_list(FILE *file)
3187 if (list_empty(&user_type_list))
3190 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3191 fprintf(file, "{\n");
3192 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3194 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3195 print_file(file, 1, "{\n");
3196 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3197 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3198 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3199 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3200 print_file(file, 1, "}%s\n", sep);
3202 fprintf(file, "};\n\n");
3205 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3207 const struct str_list_entry_t *endpoint;
3210 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3211 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3212 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3214 print_file( f, 1, "{ (const unsigned char *)\"" );
3215 for (p = endpoint->str; *p && *p != ':'; p++)
3217 if (*p == '"' || *p == '\\') fputc( '\\', f );
3220 if (!*p) goto error;
3221 if (p[1] != '[') goto error;
3223 fprintf( f, "\", (const unsigned char *)\"" );
3224 for (p += 2; *p && *p != ']'; p++)
3226 if (*p == '"' || *p == '\\') fputc( '\\', f );
3229 if (*p != ']') goto error;
3230 fprintf( f, "\" },\n" );
3232 print_file( f, 0, "};\n\n" );
3236 error("Invalid endpoint syntax '%s'\n", endpoint->str);