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 unsigned short user_type_offset(const char *name)
160 unsigned short off = 0;
161 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
163 if (strcmp(name, ut->name) == 0)
167 error("user_type_offset: couldn't find type (%s)\n", name);
171 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
173 type->typestring_offset = offset;
174 if (file) type->tfswrite = FALSE;
177 static void guard_rec(type_t *type)
179 /* types that contain references to themselves (like a linked list),
180 need to be shielded from infinite recursion when writing embedded
182 if (type->typestring_offset)
183 type->tfswrite = FALSE;
185 type->typestring_offset = 1;
188 static type_t *get_user_type(const type_t *t, const char **pname)
192 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
200 if (t->kind == TKIND_ALIAS)
207 int is_user_type(const type_t *t)
209 return get_user_type(t, NULL) != NULL;
212 static int is_embedded_complex(const type_t *type)
214 unsigned char tc = type->type;
215 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
216 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
219 static const char *get_context_handle_type_name(const type_t *type)
222 for (t = type; is_ptr(t); t = t->ref)
223 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
229 /* This is actually fairly involved to implement precisely, due to the
230 effects attributes may have and things like that. Right now this is
231 only used for optimization, so just check for a very small set of
232 criteria that guarantee the types are equivalent; assume every thing
233 else is different. */
234 static int compare_type(const type_t *a, const type_t *b)
239 && strcmp(a->name, b->name) == 0))
241 /* Ordering doesn't need to be implemented yet. */
245 static int compare_expr(const expr_t *a, const expr_t *b)
249 if (a->type != b->type)
250 return a->type - b->type;
257 return a->u.lval - b->u.lval;
259 return a->u.dval - b->u.dval;
260 case EXPR_IDENTIFIER:
261 return strcmp(a->u.sval, b->u.sval);
263 ret = compare_expr(a->ref, b->ref);
266 ret = compare_expr(a->u.ext, b->u.ext);
269 return compare_expr(a->ext2, b->ext2);
278 ret = compare_expr(a->ref, b->ref);
281 return compare_expr(a->u.ext, b->u.ext);
283 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);
328 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n)
330 if (decl_indirect(t))
331 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof(%s));\n", n, n);
332 else if (is_ptr(t) || is_array(t))
333 print_file(file, indent, "%s = 0;\n", n);
336 void write_parameters_init(FILE *file, int indent, const func_t *func)
340 if (!is_void(func->def->type))
341 write_var_init(file, indent, func->def->type, "_RetVal");
346 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
347 write_var_init(file, indent, var->type, var->name);
352 static void write_formatdesc(FILE *f, int indent, const char *str)
354 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
355 print_file(f, indent, "{\n");
356 print_file(f, indent + 1, "short Pad;\n");
357 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
358 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
359 print_file(f, indent, "\n");
362 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
364 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
365 get_size_typeformatstring(ifaces, pred));
367 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
368 get_size_procformatstring(ifaces, pred));
371 write_formatdesc(f, indent, "TYPE");
372 write_formatdesc(f, indent, "PROC");
374 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
375 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
376 print_file(f, indent, "\n");
379 static inline int is_base_type(unsigned char type)
398 case RPC_FC_ERROR_STATUS_T:
399 case RPC_FC_BIND_PRIMITIVE:
407 int decl_indirect(const type_t *t)
409 return is_user_type(t)
410 || (!is_base_type(t->type)
415 static size_t write_procformatstring_var(FILE *file, int indent,
416 const var_t *var, int is_return)
419 const type_t *type = var->type;
421 int is_in = is_attr(var->attrs, ATTR_IN);
422 int is_out = is_attr(var->attrs, ATTR_OUT);
424 if (!is_in && !is_out) is_in = TRUE;
426 if (!type->declarray && is_base_type(type->type))
429 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
431 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
433 if (type->type == RPC_FC_BIND_PRIMITIVE)
435 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
436 size = 2; /* includes param type prefix */
438 else if (is_base_type(type->type))
440 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
441 size = 2; /* includes param type prefix */
445 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
452 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
453 else if (is_in && is_out)
454 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
456 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
458 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
460 print_file(file, indent, "0x01,\n");
461 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
462 size = 4; /* includes param type prefix */
467 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
469 const ifref_t *iface;
473 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
474 print_file(file, indent, "{\n");
476 print_file(file, indent, "0,\n");
477 print_file(file, indent, "{\n");
480 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
482 if (!pred(iface->iface))
485 if (iface->iface->funcs)
488 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
490 if (is_local(func->def->attrs)) continue;
491 /* emit argument data */
494 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
495 write_procformatstring_var(file, indent, var, FALSE);
498 /* emit return value data */
500 if (is_void(var->type))
502 print_file(file, indent, "0x5b, /* FC_END */\n");
503 print_file(file, indent, "0x5c, /* FC_PAD */\n");
506 write_procformatstring_var(file, indent, var, TRUE);
511 print_file(file, indent, "0x0\n");
513 print_file(file, indent, "}\n");
515 print_file(file, indent, "};\n");
516 print_file(file, indent, "\n");
519 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
521 if (is_base_type(type->type))
523 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
524 *typestring_offset += 1;
531 /* write conformance / variance descriptor */
532 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
533 unsigned int baseoff, const type_t *type,
536 unsigned char operator_type = 0;
537 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
538 const char *conftype_string = "";
539 const char *operator_string = "no operators";
540 const expr_t *subexpr;
544 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
550 /* Top-level conformance calculations are done inline. */
551 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
552 RPC_FC_TOP_LEVEL_CONFORMANCE);
553 print_file (file, 2, "0x0,\n");
554 print_file (file, 2, "NdrFcShort(0x0),\n");
560 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
561 error("write_conf_or_var_desc: constant value %ld is greater than "
562 "the maximum constant size of %d\n", expr->cval,
563 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
565 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
566 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
567 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
568 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
573 if (is_ptr(type) || (is_array(type) && !type->declarray))
575 conftype = RPC_FC_POINTER_CONFORMANCE;
576 conftype_string = "field pointer, ";
580 switch (subexpr->type)
583 subexpr = subexpr->ref;
584 operator_type = RPC_FC_DEREFERENCE;
585 operator_string = "FC_DEREFERENCE";
588 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
590 subexpr = subexpr->ref;
591 operator_type = RPC_FC_DIV_2;
592 operator_string = "FC_DIV_2";
596 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
598 subexpr = subexpr->ref;
599 operator_type = RPC_FC_MULT_2;
600 operator_string = "FC_MULT_2";
604 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
606 subexpr = subexpr->ref;
607 operator_type = RPC_FC_SUB_1;
608 operator_string = "FC_SUB_1";
612 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
614 subexpr = subexpr->ref;
615 operator_type = RPC_FC_ADD_1;
616 operator_string = "FC_ADD_1";
623 if (subexpr->type == EXPR_IDENTIFIER)
625 const type_t *correlation_variable = NULL;
626 unsigned char correlation_variable_type;
627 unsigned char param_type = 0;
631 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
633 unsigned int align = 0;
634 /* FIXME: take alignment into account */
635 if (var->name && !strcmp(var->name, subexpr->u.sval))
637 correlation_variable = var->type;
640 offset += type_memsize(var->type, &align);
642 if (!correlation_variable)
643 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
647 correlation_variable_type = correlation_variable->type;
649 switch (correlation_variable_type)
653 param_type = RPC_FC_SMALL;
657 param_type = RPC_FC_USMALL;
662 param_type = RPC_FC_SHORT;
665 param_type = RPC_FC_USHORT;
669 param_type = RPC_FC_LONG;
672 param_type = RPC_FC_ULONG;
678 if (sizeof(void *) == 4) /* FIXME */
679 param_type = RPC_FC_LONG;
681 param_type = RPC_FC_HYPER;
684 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
685 correlation_variable_type);
688 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
689 conftype | param_type, conftype_string, string_of_type(param_type));
690 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
691 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
696 unsigned int callback_offset = 0;
697 struct expr_eval_routine *eval;
700 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
702 if (!strcmp (eval->structure->name, structure->name)
703 && !compare_expr (eval->expr, expr))
713 eval = xmalloc (sizeof(*eval));
714 eval->structure = structure;
715 eval->baseoff = baseoff;
717 list_add_tail (&expr_eval_routines, &eval->entry);
720 if (callback_offset > USHRT_MAX)
721 error("Maximum number of callback routines reached\n");
723 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
724 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
725 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
730 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
732 int have_align = FALSE;
736 if (!fields) return 0;
737 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
739 unsigned int falign = 0;
740 size_t fsize = type_memsize(v->type, &falign);
746 size = (size + (falign - 1)) & ~(falign - 1);
750 size = (size + (*align - 1)) & ~(*align - 1);
754 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
756 size_t size, maxs = 0;
757 unsigned int align = *pmaxa;
760 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
762 /* we could have an empty default field with NULL type */
765 size = type_memsize(v->type, &align);
766 if (maxs < size) maxs = size;
767 if (*pmaxa < align) *pmaxa = align;
774 int get_padding(const var_list_t *fields)
776 unsigned short offset = 0;
783 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
785 type_t *ft = f->type;
786 unsigned int align = 0;
787 size_t size = type_memsize(ft, &align);
790 offset = (offset + (align - 1)) & ~(align - 1);
794 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
797 size_t type_memsize(const type_t *t, unsigned int *align)
801 if (t->declarray && is_conformant_array(t))
803 type_memsize(t->ref, align);
806 else if (is_ptr(t) || is_conformant_array(t))
808 size = sizeof(void *);
809 if (size > *align) *align = size;
811 else switch (t->type)
818 if (size > *align) *align = size;
825 if (size > *align) *align = size;
829 case RPC_FC_ERROR_STATUS_T:
833 if (size > *align) *align = size;
838 if (size > *align) *align = size;
841 case RPC_FC_CVSTRUCT:
842 case RPC_FC_CPSTRUCT:
845 case RPC_FC_BOGUS_STRUCT:
846 size = fields_memsize(t->fields, align);
848 case RPC_FC_ENCAPSULATED_UNION:
849 case RPC_FC_NON_ENCAPSULATED_UNION:
850 size = union_memsize(t->fields, align);
852 case RPC_FC_SMFARRAY:
853 case RPC_FC_LGFARRAY:
854 case RPC_FC_SMVARRAY:
855 case RPC_FC_LGVARRAY:
856 case RPC_FC_BOGUS_ARRAY:
857 size = t->dim * type_memsize(t->ref, align);
860 error("type_memsize: Unknown type %d\n", t->type);
867 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
869 short absoff = type->ref->typestring_offset;
870 short reloff = absoff - (offset + 2);
871 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
873 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
874 type->type, ptr_attr, string_of_type(type->type));
875 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
876 reloff, reloff, absoff);
880 static unsigned char conf_string_type_of_char_type(unsigned char t)
886 return RPC_FC_C_CSTRING;
888 return RPC_FC_C_WSTRING;
891 error("string_type_of_char_type: unrecognized type %d\n", t);
895 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
898 = is_string_type(type->attrs, type)
899 ? conf_string_type_of_char_type(type->ref->type)
901 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
902 type->type, string_of_type(type->type));
903 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
904 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
908 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
910 print_file(file, 0, "/* %u (", tfsoff);
911 write_type_decl(file, t, NULL);
912 print_file(file, 0, ") */\n");
915 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
917 unsigned int offset = *typestring_offset;
919 print_start_tfs_comment(file, type, offset);
920 update_tfsoff(type, offset, file);
922 if (type->ref->typestring_offset)
923 *typestring_offset += write_nonsimple_pointer(file, type, offset);
924 else if (is_base_type(type->ref->type))
925 *typestring_offset += write_simple_pointer(file, type);
930 static int processed(const type_t *type)
932 return type->typestring_offset && !type->tfswrite;
935 static int user_type_has_variable_size(const type_t *t)
944 case RPC_FC_CPSTRUCT:
945 case RPC_FC_CVSTRUCT:
948 /* Note: Since this only applies to user types, we can't have a conformant
949 array here, and strings should get filed under pointer in this case. */
953 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
955 unsigned int start, absoff, flags;
956 unsigned int align = 0, ualign = 0;
958 type_t *utype = get_user_type(type, &name);
959 size_t usize = user_type_has_variable_size(utype) ? 0 : type_memsize(utype, &ualign);
960 size_t size = type_memsize(type, &align);
961 unsigned short funoff = user_type_offset(name);
966 if (is_base_type(utype->type))
969 print_start_tfs_comment(file, utype, absoff);
970 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
971 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
976 if (!processed(utype))
977 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
978 absoff = utype->typestring_offset;
981 if (utype->type == RPC_FC_RP)
983 else if (utype->type == RPC_FC_UP)
989 update_tfsoff(type, start, file);
990 print_start_tfs_comment(file, type, start);
991 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
992 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
993 flags | (align - 1), align - 1, flags);
994 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
995 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
996 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
998 reloff = absoff - *tfsoff;
999 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
1003 static void write_member_type(FILE *file, const type_t *cont,
1004 const attr_list_t *attrs, const type_t *type,
1005 unsigned int *corroff, unsigned int *tfsoff)
1007 if (is_embedded_complex(type) && !is_conformant_array(type))
1012 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
1019 absoff = type->typestring_offset;
1021 reloff = absoff - (*tfsoff + 2);
1023 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1024 /* FIXME: actually compute necessary padding */
1025 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
1026 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1027 reloff, reloff, absoff);
1030 else if (is_ptr(type) || is_conformant_array(type))
1032 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
1035 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1038 else if (!write_base_type(file, type, tfsoff))
1039 error("Unsupported member type 0x%x\n", type->type);
1042 static void write_end(FILE *file, unsigned int *tfsoff)
1044 if (*tfsoff % 2 == 0)
1046 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1049 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1053 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1055 unsigned int offset = 0;
1056 var_list_t *fs = type->fields;
1059 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1061 unsigned int align = 0;
1062 type_t *ft = f->type;
1063 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1065 unsigned int absoff = ft->typestring_offset;
1066 short reloff = absoff - (*tfsoff + 6);
1067 print_file(file, 0, "/* %d */\n", *tfsoff);
1068 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1069 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1070 write_conf_or_var_desc(file, current_structure, offset, ft,
1071 get_attrp(f->attrs, ATTR_SWITCHIS));
1072 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1073 reloff, reloff, absoff);
1077 /* FIXME: take alignment into account */
1078 offset += type_memsize(ft, &align);
1082 static int write_no_repeat_pointer_descriptions(
1083 FILE *file, type_t *type,
1084 size_t *offset_in_memory, size_t *offset_in_buffer,
1085 unsigned int *typestring_offset)
1090 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1092 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1093 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1095 /* pointer instance */
1096 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1097 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1098 *typestring_offset += 6;
1101 write_pointer_tfs(file, type, typestring_offset);
1104 unsigned absoff = type->typestring_offset;
1105 short reloff = absoff - (*typestring_offset + 2);
1106 /* FIXME: get pointer attributes from field */
1107 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1108 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1109 reloff, reloff, absoff);
1110 *typestring_offset += 4;
1114 *offset_in_memory += type_memsize(type, &align);
1115 /* FIXME: is there a case where these two are different? */
1117 *offset_in_buffer += type_memsize(type, &align);
1122 if (is_non_complex_struct(type))
1125 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1126 written += write_no_repeat_pointer_descriptions(
1128 offset_in_memory, offset_in_buffer, typestring_offset);
1133 *offset_in_memory += type_memsize(type, &align);
1134 /* FIXME: is there a case where these two are different? */
1136 *offset_in_buffer += type_memsize(type, &align);
1142 static int write_pointer_description_offsets(
1143 FILE *file, const attr_list_t *attrs, type_t *type,
1144 size_t *offset_in_memory, size_t *offset_in_buffer,
1145 unsigned int *typestring_offset)
1150 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1152 if (offset_in_memory && offset_in_buffer)
1154 /* pointer instance */
1155 /* FIXME: sometimes from end of structure, sometimes from beginning */
1156 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1157 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1160 *offset_in_memory += type_memsize(type, &align);
1161 /* FIXME: is there a case where these two are different? */
1163 *offset_in_buffer += type_memsize(type, &align);
1165 *typestring_offset += 4;
1167 if (processed(type->ref) || is_base_type(type->ref->type))
1168 write_pointer_tfs(file, type, typestring_offset);
1170 error("write_pointer_description_offsets: type format string unknown\n");
1177 return write_pointer_description_offsets(
1178 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1181 else if (is_non_complex_struct(type))
1183 /* otherwise search for interesting fields to parse */
1185 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1187 written += write_pointer_description_offsets(
1188 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1195 if (offset_in_memory)
1196 *offset_in_memory += type_memsize(type, &align);
1197 /* FIXME: is there a case where these two are different? */
1199 if (offset_in_buffer)
1200 *offset_in_buffer += type_memsize(type, &align);
1206 /* Note: if file is NULL return value is number of pointers to write, else
1207 * it is the number of type format characters written */
1208 static int write_fixed_array_pointer_descriptions(
1209 FILE *file, const attr_list_t *attrs, type_t *type,
1210 size_t *offset_in_memory, size_t *offset_in_buffer,
1211 unsigned int *typestring_offset)
1214 int pointer_count = 0;
1216 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1218 unsigned int temp = 0;
1219 /* unfortunately, this needs to be done in two passes to avoid
1220 * writing out redundant FC_FIXED_REPEAT descriptions */
1221 pointer_count = write_pointer_description_offsets(
1222 NULL, attrs, type->ref, NULL, NULL, &temp);
1223 if (pointer_count > 0)
1225 unsigned int increment_size;
1226 size_t offset_of_array_pointer_mem = 0;
1227 size_t offset_of_array_pointer_buf = 0;
1230 increment_size = type_memsize(type->ref, &align);
1232 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1233 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1234 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1235 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1236 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1237 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1238 *typestring_offset += 10;
1240 pointer_count = write_pointer_description_offsets(
1241 file, attrs, type, &offset_of_array_pointer_mem,
1242 &offset_of_array_pointer_buf, typestring_offset);
1245 else if (is_struct(type->type))
1248 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1250 pointer_count += write_fixed_array_pointer_descriptions(
1251 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1258 if (offset_in_memory)
1259 *offset_in_memory += type_memsize(type, &align);
1260 /* FIXME: is there a case where these two are different? */
1262 if (offset_in_buffer)
1263 *offset_in_buffer += type_memsize(type, &align);
1266 return pointer_count;
1269 /* Note: if file is NULL return value is number of pointers to write, else
1270 * it is the number of type format characters written */
1271 static int write_conformant_array_pointer_descriptions(
1272 FILE *file, const attr_list_t *attrs, type_t *type,
1273 size_t offset_in_memory, unsigned int *typestring_offset)
1276 int pointer_count = 0;
1278 if (is_conformant_array(type) && !type->length_is)
1280 unsigned int temp = 0;
1281 /* unfortunately, this needs to be done in two passes to avoid
1282 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1283 pointer_count = write_pointer_description_offsets(
1284 NULL, attrs, type->ref, NULL, NULL, &temp);
1285 if (pointer_count > 0)
1287 unsigned int increment_size;
1288 size_t offset_of_array_pointer_mem = offset_in_memory;
1289 size_t offset_of_array_pointer_buf = offset_in_memory;
1292 increment_size = type_memsize(type->ref, &align);
1294 if (increment_size > USHRT_MAX)
1295 error("array size of %u bytes is too large\n", increment_size);
1297 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1298 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1299 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1300 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1301 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1302 *typestring_offset += 8;
1304 pointer_count = write_pointer_description_offsets(
1305 file, attrs, type->ref, &offset_of_array_pointer_mem,
1306 &offset_of_array_pointer_buf, typestring_offset);
1310 return pointer_count;
1313 /* Note: if file is NULL return value is number of pointers to write, else
1314 * it is the number of type format characters written */
1315 static int write_varying_array_pointer_descriptions(
1316 FILE *file, const attr_list_t *attrs, type_t *type,
1317 size_t *offset_in_memory, size_t *offset_in_buffer,
1318 unsigned int *typestring_offset)
1321 int pointer_count = 0;
1323 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1325 if (is_array(type) && type->length_is)
1327 unsigned int temp = 0;
1328 /* unfortunately, this needs to be done in two passes to avoid
1329 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1330 pointer_count = write_pointer_description_offsets(
1331 NULL, attrs, type->ref, NULL, NULL, &temp);
1332 if (pointer_count > 0)
1334 unsigned int increment_size;
1335 size_t offset_of_array_pointer_mem = 0;
1336 size_t offset_of_array_pointer_buf = 0;
1339 increment_size = type_memsize(type->ref, &align);
1341 if (increment_size > USHRT_MAX)
1342 error("array size of %u bytes is too large\n", increment_size);
1344 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1345 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1346 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1347 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1348 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1349 *typestring_offset += 8;
1351 pointer_count = write_pointer_description_offsets(
1352 file, attrs, type, &offset_of_array_pointer_mem,
1353 &offset_of_array_pointer_buf, typestring_offset);
1356 else if (is_struct(type->type))
1359 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1361 pointer_count += write_varying_array_pointer_descriptions(
1362 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1369 if (offset_in_memory)
1370 *offset_in_memory += type_memsize(type, &align);
1371 /* FIXME: is there a case where these two are different? */
1373 if (offset_in_buffer)
1374 *offset_in_buffer += type_memsize(type, &align);
1377 return pointer_count;
1380 static void write_pointer_description(FILE *file, type_t *type,
1381 unsigned int *typestring_offset)
1383 size_t offset_in_buffer;
1384 size_t offset_in_memory;
1386 /* pass 1: search for single instance of a pointer (i.e. don't descend
1388 if (!is_array(type))
1390 offset_in_memory = 0;
1391 offset_in_buffer = 0;
1392 write_no_repeat_pointer_descriptions(
1394 &offset_in_memory, &offset_in_buffer, typestring_offset);
1397 /* pass 2: search for pointers in fixed arrays */
1398 offset_in_memory = 0;
1399 offset_in_buffer = 0;
1400 write_fixed_array_pointer_descriptions(
1402 &offset_in_memory, &offset_in_buffer, typestring_offset);
1404 /* pass 3: search for pointers in conformant only arrays (but don't descend
1405 * into conformant varying or varying arrays) */
1406 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1407 write_conformant_array_pointer_descriptions(
1408 file, NULL, type, 0, typestring_offset);
1409 else if (type->type == RPC_FC_CPSTRUCT)
1411 unsigned int align = 0;
1412 type_t *carray = find_array_or_string_in_struct(type)->type;
1413 write_conformant_array_pointer_descriptions(
1415 type_memsize(type, &align),
1419 /* pass 4: search for pointers in varying arrays */
1420 offset_in_memory = 0;
1421 offset_in_buffer = 0;
1422 write_varying_array_pointer_descriptions(
1424 &offset_in_memory, &offset_in_buffer, typestring_offset);
1427 int is_declptr(const type_t *t)
1429 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1432 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1434 const char *name, unsigned int *typestring_offset,
1437 size_t start_offset = *typestring_offset;
1438 unsigned char rtype;
1440 update_tfsoff(type, start_offset, file);
1442 if (toplevel && is_declptr(type))
1444 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1445 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1447 pointer_type = RPC_FC_RP;
1448 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1449 pointer_type, flag, string_of_type(pointer_type),
1450 flag ? " [simple_pointer]" : "");
1451 *typestring_offset += 2;
1454 print_file(file, 2, "NdrFcShort(0x2),\n");
1455 *typestring_offset += 2;
1459 rtype = type->ref->type;
1461 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1463 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1464 return start_offset;
1467 if (type->declarray && !is_conformant_array(type))
1469 /* FIXME: multi-dimensional array */
1470 if (0xffffuL < type->dim)
1471 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1472 name, 0xffffu, type->dim - 0xffffu);
1474 if (rtype == RPC_FC_CHAR)
1475 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1477 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1478 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1479 *typestring_offset += 2;
1481 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1482 *typestring_offset += 2;
1484 return start_offset;
1486 else if (type->size_is)
1488 unsigned int align = 0;
1490 if (rtype == RPC_FC_CHAR)
1491 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1493 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1494 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1495 *typestring_offset += 2;
1497 *typestring_offset += write_conf_or_var_desc(
1498 file, current_structure,
1499 (type->declarray && current_structure
1500 ? type_memsize(current_structure, &align)
1502 type, type->size_is);
1504 return start_offset;
1508 if (rtype == RPC_FC_WCHAR)
1509 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1511 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1512 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1513 *typestring_offset += 2;
1515 return start_offset;
1519 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1520 const char *name, unsigned int *typestring_offset)
1522 const expr_t *length_is = type->length_is;
1523 const expr_t *size_is = type->size_is;
1524 unsigned int align = 0;
1526 size_t start_offset;
1528 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1529 unsigned int baseoff
1530 = type->declarray && current_structure
1531 ? type_memsize(current_structure, &align)
1535 pointer_type = RPC_FC_RP;
1537 has_pointer = FALSE;
1538 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1542 size = type_memsize((is_conformant_array(type) ? type->ref : type), &align);
1544 start_offset = *typestring_offset;
1545 update_tfsoff(type, start_offset, file);
1546 print_start_tfs_comment(file, type, start_offset);
1547 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1548 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1549 *typestring_offset += 2;
1552 if (type->type != RPC_FC_BOGUS_ARRAY)
1554 unsigned char tc = type->type;
1556 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1558 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1559 *typestring_offset += 4;
1563 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1564 *typestring_offset += 2;
1567 if (is_conformant_array(type))
1569 += write_conf_or_var_desc(file, current_structure, baseoff,
1572 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1574 unsigned int elalign = 0;
1575 size_t elsize = type_memsize(type->ref, &elalign);
1577 if (type->type == RPC_FC_LGVARRAY)
1579 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1580 *typestring_offset += 4;
1584 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1585 *typestring_offset += 2;
1588 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1589 *typestring_offset += 2;
1594 += write_conf_or_var_desc(file, current_structure, baseoff,
1597 if (has_pointer && (!type->declarray || !current_structure))
1599 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1600 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1601 *typestring_offset += 2;
1602 write_pointer_description(file, type, typestring_offset);
1603 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1604 *typestring_offset += 1;
1607 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1608 write_end(file, typestring_offset);
1612 unsigned int dim = size_is ? 0 : type->dim;
1613 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1614 *typestring_offset += 2;
1616 += write_conf_or_var_desc(file, current_structure, baseoff,
1619 += write_conf_or_var_desc(file, current_structure, baseoff,
1621 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1622 write_end(file, typestring_offset);
1625 return start_offset;
1628 static const var_t *find_array_or_string_in_struct(const type_t *type)
1630 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1631 const type_t *ft = last_field->type;
1633 if (ft->declarray && is_conformant_array(ft))
1636 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1637 return find_array_or_string_in_struct(last_field->type);
1642 static void write_struct_members(FILE *file, const type_t *type,
1643 unsigned int *corroff, unsigned int *typestring_offset)
1646 unsigned short offset = 0;
1650 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1652 type_t *ft = field->type;
1653 if (!ft->declarray || !is_conformant_array(ft))
1655 unsigned int align = 0;
1656 size_t size = type_memsize(ft, &align);
1659 if ((align - 1) & offset)
1661 unsigned char fc = 0;
1665 fc = RPC_FC_ALIGNM4;
1668 fc = RPC_FC_ALIGNM8;
1671 error("write_struct_members: cannot align type %d\n", ft->type);
1673 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1674 offset = (offset + (align - 1)) & ~(align - 1);
1675 *typestring_offset += 1;
1677 write_member_type(file, type, field->attrs, field->type, corroff,
1683 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1686 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1687 RPC_FC_STRUCTPAD1 + padding - 1,
1689 *typestring_offset += 1;
1692 write_end(file, typestring_offset);
1695 static size_t write_struct_tfs(FILE *file, type_t *type,
1696 const char *name, unsigned int *tfsoff)
1698 const type_t *save_current_structure = current_structure;
1699 unsigned int total_size;
1701 size_t start_offset;
1702 size_t array_offset;
1703 int has_pointers = 0;
1704 unsigned int align = 0;
1705 unsigned int corroff;
1709 current_structure = type;
1711 total_size = type_memsize(type, &align);
1712 if (total_size > USHRT_MAX)
1713 error("structure size for %s exceeds %d bytes by %d bytes\n",
1714 name, USHRT_MAX, total_size - USHRT_MAX);
1716 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1717 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1720 array = find_array_or_string_in_struct(type);
1721 if (array && !processed(array->type))
1723 = is_attr(array->attrs, ATTR_STRING)
1724 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff, FALSE)
1725 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1728 write_descriptors(file, type, tfsoff);
1730 start_offset = *tfsoff;
1731 update_tfsoff(type, start_offset, file);
1732 print_start_tfs_comment(file, type, start_offset);
1733 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1734 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1735 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1740 unsigned int absoff = array->type->typestring_offset;
1741 short reloff = absoff - *tfsoff;
1742 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1743 reloff, reloff, absoff);
1746 else if (type->type == RPC_FC_BOGUS_STRUCT)
1748 print_file(file, 2, "NdrFcShort(0x0),\n");
1752 if (type->type == RPC_FC_BOGUS_STRUCT)
1754 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1755 nothing is written to file yet. On the actual writing pass,
1756 this will have been updated. */
1757 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1758 short reloff = absoff - *tfsoff;
1759 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1760 reloff, reloff, absoff);
1763 else if ((type->type == RPC_FC_PSTRUCT) ||
1764 (type->type == RPC_FC_CPSTRUCT) ||
1765 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1767 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1768 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1770 write_pointer_description(file, type, tfsoff);
1771 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1775 write_struct_members(file, type, &corroff, tfsoff);
1777 if (type->type == RPC_FC_BOGUS_STRUCT)
1779 const var_list_t *fs = type->fields;
1782 type->ptrdesc = *tfsoff;
1783 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1785 type_t *ft = f->type;
1787 write_pointer_tfs(file, ft, tfsoff);
1788 else if (!ft->declarray && is_conformant_array(ft))
1790 unsigned int absoff = ft->typestring_offset;
1791 short reloff = absoff - (*tfsoff + 2);
1792 int ptr_type = get_attrv(f->attrs, ATTR_POINTERTYPE);
1793 /* FIXME: We need to store pointer attributes for arrays
1794 so we don't lose pointer_default info. */
1796 ptr_type = RPC_FC_UP;
1797 print_file(file, 0, "/* %d */\n", *tfsoff);
1798 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
1799 string_of_type(ptr_type));
1800 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1801 reloff, reloff, absoff);
1805 if (type->ptrdesc == *tfsoff)
1809 current_structure = save_current_structure;
1810 return start_offset;
1813 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1814 unsigned char flags, size_t offset,
1815 unsigned int *typeformat_offset)
1817 size_t start_offset = *typeformat_offset;
1818 short reloff = offset - (*typeformat_offset + 2);
1819 int in_attr, out_attr;
1820 in_attr = is_attr(attrs, ATTR_IN);
1821 out_attr = is_attr(attrs, ATTR_OUT);
1822 if (!in_attr && !out_attr) in_attr = 1;
1824 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1827 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1830 string_of_type(pointer_type));
1834 fprintf(file, " [allocated_on_stack]");
1836 fprintf(file, " [pointer_deref]");
1837 fprintf(file, " */\n");
1840 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1841 *typeformat_offset += 4;
1843 return start_offset;
1846 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1850 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1852 else if (is_base_type(t->type))
1854 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1855 t->type, string_of_type(t->type));
1857 else if (t->typestring_offset)
1859 short reloff = t->typestring_offset - *tfsoff;
1860 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1861 reloff, reloff, t->typestring_offset);
1864 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1869 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1871 unsigned int align = 0;
1872 unsigned int start_offset;
1873 size_t size = type_memsize(type, &align);
1876 type_t *deftype = NULL;
1877 short nodeftype = 0xffff;
1882 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1884 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1885 fields = uv->type->fields;
1888 fields = type->fields;
1890 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1892 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1894 nbranch += list_count(cases);
1896 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1899 start_offset = *tfsoff;
1900 update_tfsoff(type, start_offset, file);
1901 print_start_tfs_comment(file, type, start_offset);
1902 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1904 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1905 const type_t *st = sv->type;
1918 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1919 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1920 0x40 | st->type, string_of_type(st->type));
1924 error("union switch type must be an integer, char, or enum\n");
1927 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1928 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1931 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1933 type_t *ft = f->type;
1934 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1935 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1938 if (cases == NULL && !deflt)
1939 error("union field %s with neither case nor default attribute\n", f->name);
1941 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1943 /* MIDL doesn't check for duplicate cases, even though that seems
1944 like a reasonable thing to do, it just dumps them to the TFS
1945 like we're going to do here. */
1946 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1948 write_branch_type(file, ft, tfsoff);
1951 /* MIDL allows multiple default branches, even though that seems
1952 illogical, it just chooses the last one, which is what we will
1963 write_branch_type(file, deftype, tfsoff);
1967 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1971 return start_offset;
1974 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1975 unsigned int *typeformat_offset)
1978 size_t start_offset = *typeformat_offset;
1979 expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
1983 print_file(file, 2, "0x2f, /* FC_IP */\n");
1984 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1986 += write_conf_or_var_desc(file, NULL, 0, type, iid) + 2;
1990 const type_t *base = is_ptr(type) ? type->ref : type;
1991 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1994 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1996 update_tfsoff(type, start_offset, file);
1997 print_start_tfs_comment(file, type, start_offset);
1998 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1999 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2000 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
2001 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2002 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2003 for (i = 0; i < 8; ++i)
2004 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2007 fprintf(file, "\n");
2009 *typeformat_offset += 18;
2011 return start_offset;
2014 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
2016 unsigned int *typeformat_offset)
2018 size_t start_offset = *typeformat_offset;
2019 unsigned char flags = 0x08 /* strict */;
2024 if (type->type != RPC_FC_RP)
2027 if (is_attr(var->attrs, ATTR_IN))
2029 if (is_attr(var->attrs, ATTR_OUT))
2032 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
2033 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
2034 if (((flags & 0x21) != 0x21) && (flags & 0x01))
2035 print_file(file, 0, "can't be null, ");
2037 print_file(file, 0, "serialize, ");
2039 print_file(file, 0, "no serialize, ");
2041 print_file(file, 0, "strict, ");
2042 if ((flags & 0x21) == 0x20)
2043 print_file(file, 0, "out, ");
2044 if ((flags & 0x21) == 0x21)
2045 print_file(file, 0, "return, ");
2047 print_file(file, 0, "in, ");
2049 print_file(file, 0, "via ptr, ");
2050 print_file(file, 0, "*/\n");
2051 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2052 print_file(file, 2, "0, /* FIXME: param num */\n");
2053 *typeformat_offset += 4;
2055 return start_offset;
2058 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2059 type_t *type, const var_t *var,
2060 unsigned int *typeformat_offset)
2064 if (is_context_handle(type))
2065 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2067 if (is_user_type(type))
2069 write_user_tfs(file, type, typeformat_offset);
2070 return type->typestring_offset;
2073 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2074 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset, TRUE);
2080 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2081 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2082 /* Top level pointers to conformant arrays may be handled specially
2083 since we can bypass the pointer, but if the array is burried
2084 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2085 always need to write the pointer. */
2086 if (!ptr_type && var->type != type)
2087 /* FIXME: This should use pointer_default, but the information
2088 isn't kept around for arrays. */
2089 ptr_type = RPC_FC_UP;
2090 if (ptr_type && ptr_type != RPC_FC_RP)
2092 unsigned int absoff = type->typestring_offset;
2093 short reloff = absoff - (*typeformat_offset + 2);
2094 off = *typeformat_offset;
2095 print_file(file, 0, "/* %d */\n", off);
2096 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2097 string_of_type(ptr_type));
2098 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2099 reloff, reloff, absoff);
2100 *typeformat_offset += 4;
2107 /* basic types don't need a type format string */
2108 if (is_base_type(type->type))
2114 case RPC_FC_PSTRUCT:
2115 case RPC_FC_CSTRUCT:
2116 case RPC_FC_CPSTRUCT:
2117 case RPC_FC_CVSTRUCT:
2118 case RPC_FC_BOGUS_STRUCT:
2119 return write_struct_tfs(file, type, var->name, typeformat_offset);
2120 case RPC_FC_ENCAPSULATED_UNION:
2121 case RPC_FC_NON_ENCAPSULATED_UNION:
2122 return write_union_tfs(file, type, typeformat_offset);
2124 case RPC_FC_BIND_PRIMITIVE:
2128 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2131 else if (last_ptr(type))
2133 size_t start_offset = *typeformat_offset;
2134 int in_attr = is_attr(var->attrs, ATTR_IN);
2135 int out_attr = is_attr(var->attrs, ATTR_OUT);
2136 const type_t *base = type->ref;
2138 if (base->type == RPC_FC_IP
2140 && is_attr(var->attrs, ATTR_IIDIS)))
2142 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2145 /* special case for pointers to base types */
2146 if (is_base_type(base->type))
2148 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2149 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2150 string_of_type(type->type),
2151 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2152 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2153 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2154 *typeformat_offset += 4;
2155 return start_offset;
2159 assert(is_ptr(type));
2161 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2163 fprintf(file, "/* %2u */\n", *typeformat_offset);
2164 return write_pointer_only_tfs(file, var->attrs, type->type,
2165 !last_ptr(type) ? 0x10 : 0,
2166 offset, typeformat_offset);
2169 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2170 const char *name, int write_ptr, unsigned int *tfsoff)
2174 if (is_user_type(type))
2176 write_user_tfs(file, type, tfsoff);
2178 else if (is_ptr(type))
2180 type_t *ref = type->ref;
2182 if (ref->type == RPC_FC_IP
2184 && is_attr(attrs, ATTR_IIDIS)))
2186 write_ip_tfs(file, attrs, type, tfsoff);
2190 if (!processed(ref) && !is_base_type(ref->type))
2191 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2194 write_pointer_tfs(file, type, tfsoff);
2199 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2201 write_string_tfs(file, attrs, type, name, tfsoff, FALSE);
2203 else if (type->declarray && is_conformant_array(type))
2204 ; /* conformant arrays and strings are handled specially */
2205 else if (is_array(type))
2207 write_array_tfs(file, attrs, type, name, tfsoff);
2208 if (is_conformant_array(type))
2211 else if (is_struct(type->type))
2213 if (!processed(type))
2214 write_struct_tfs(file, type, name, tfsoff);
2216 else if (is_union(type->type))
2218 if (!processed(type))
2219 write_union_tfs(file, type, tfsoff);
2221 else if (!is_base_type(type->type))
2222 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2228 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2231 const ifref_t *iface;
2232 unsigned int typeformat_offset = 2;
2234 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2236 if (!pred(iface->iface))
2239 if (iface->iface->funcs)
2242 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2244 if (is_local(func->def->attrs)) continue;
2246 current_func = func;
2248 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2251 write_typeformatstring_var(
2252 file, 2, func, var->type, var,
2253 &typeformat_offset),
2259 return typeformat_offset + 1;
2263 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2267 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2268 print_file(file, indent, "{\n");
2270 print_file(file, indent, "0,\n");
2271 print_file(file, indent, "{\n");
2273 print_file(file, indent, "NdrFcShort(0x0),\n");
2275 set_all_tfswrite(TRUE);
2276 process_tfs(file, ifaces, pred);
2278 print_file(file, indent, "0x0\n");
2280 print_file(file, indent, "}\n");
2282 print_file(file, indent, "};\n");
2283 print_file(file, indent, "\n");
2286 static unsigned int get_required_buffer_size_type(
2287 const type_t *type, const char *name, unsigned int *alignment)
2290 if (is_user_type(type))
2293 const type_t *utype = get_user_type(type, &uname);
2294 return get_required_buffer_size_type(utype, uname, alignment);
2318 case RPC_FC_ERROR_STATUS_T:
2328 case RPC_FC_BIND_PRIMITIVE:
2332 case RPC_FC_PSTRUCT:
2336 if (!type->fields) return 0;
2337 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2339 unsigned int alignment;
2340 size += get_required_buffer_size_type(field->type, field->name,
2348 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2349 ? get_required_buffer_size_type( type->ref, name, alignment )
2352 case RPC_FC_SMFARRAY:
2353 case RPC_FC_LGFARRAY:
2354 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2362 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2364 int in_attr = is_attr(var->attrs, ATTR_IN);
2365 int out_attr = is_attr(var->attrs, ATTR_OUT);
2368 if (!in_attr && !out_attr)
2373 for (t = var->type; is_ptr(t); t = t->ref)
2374 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2380 if (pass == PASS_OUT)
2382 if (out_attr && is_ptr(var->type))
2384 type_t *type = var->type;
2386 if (type->type == RPC_FC_STRUCT)
2389 unsigned int size = 36;
2391 if (!type->fields) return size;
2392 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2395 size += get_required_buffer_size_type(
2396 field->type, field->name, &align);
2405 if ((!out_attr || in_attr) && !var->type->size_is
2406 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2408 if (is_ptr(var->type))
2410 type_t *type = var->type;
2412 if (is_base_type(type->type))
2416 else if (type->type == RPC_FC_STRUCT)
2418 unsigned int size = 36;
2421 if (!type->fields) return size;
2422 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2425 size += get_required_buffer_size_type(
2426 field->type, field->name, &align);
2433 return get_required_buffer_size_type(var->type, var->name, alignment);
2437 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2440 unsigned int total_size = 0, alignment;
2444 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2446 total_size += get_required_buffer_size(var, &alignment, pass);
2447 total_size += alignment;
2451 if (pass == PASS_OUT && !is_void(func->def->type))
2453 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2454 total_size += alignment;
2459 static void print_phase_function(FILE *file, int indent, const char *type,
2460 enum remoting_phase phase,
2461 const var_t *var, unsigned int type_offset)
2463 const char *function;
2466 case PHASE_BUFFERSIZE:
2467 function = "BufferSize";
2470 function = "Marshall";
2472 case PHASE_UNMARSHAL:
2473 function = "Unmarshall";
2483 print_file(file, indent, "Ndr%s%s(\n", type, function);
2485 print_file(file, indent, "&_StubMsg,\n");
2486 print_file(file, indent, "%s%s%s%s,\n",
2487 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2488 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2489 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2491 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2492 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2493 if (phase == PHASE_UNMARSHAL)
2494 print_file(file, indent, "0);\n");
2498 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2499 enum pass pass, const var_t *var,
2500 const char *varname)
2502 type_t *type = var->type;
2504 unsigned int alignment = 0;
2505 unsigned char rtype;
2507 /* no work to do for other phases, buffer sizing is done elsewhere */
2508 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2511 rtype = is_ptr(type) ? type->ref->type : type->type;
2535 case RPC_FC_ERROR_STATUS_T:
2547 case RPC_FC_BIND_PRIMITIVE:
2548 /* no marshalling needed */
2552 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2556 print_file(file, indent, "memset(_StubMsg.Buffer, 0, ((long)_StubMsg.Buffer) & 0x%x);\n", alignment - 1);
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 type_t *t)
2600 return !is_base_type(t->type) && (t->type != RPC_FC_RP || !is_base_type(t->ref->type));
2603 expr_t *get_size_is_expr(const type_t *t, const char *name)
2607 for ( ; is_ptr(t) || is_array(t); t = t->ref)
2613 error("%s: multidimensional conformant"
2614 " arrays not supported at the top level\n",
2621 static void write_remoting_arg(FILE *file, int indent, const func_t *func,
2622 enum pass pass, enum remoting_phase phase,
2625 int in_attr, out_attr, pointer_type;
2626 const type_t *type = var->type;
2627 unsigned char rtype;
2628 size_t start_offset = type->typestring_offset;
2630 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2632 pointer_type = RPC_FC_RP;
2634 in_attr = is_attr(var->attrs, ATTR_IN);
2635 out_attr = is_attr(var->attrs, ATTR_OUT);
2636 if (!in_attr && !out_attr)
2639 if (phase == PHASE_FREE)
2641 if (!needs_freeing(type))
2648 if (!in_attr) return;
2651 if (!out_attr) return;
2659 if (is_context_handle(type))
2661 if (phase == PHASE_MARSHAL)
2663 if (pass == PASS_IN)
2665 print_file(file, indent, "NdrClientContextMarshall(\n");
2666 print_file(file, indent + 1, "&_StubMsg,\n");
2667 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2668 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2672 print_file(file, indent, "NdrServerContextMarshall(\n");
2673 print_file(file, indent + 1, "&_StubMsg,\n");
2674 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2675 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2678 else if (phase == PHASE_UNMARSHAL)
2680 if (pass == PASS_OUT)
2682 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2683 print_file(file, indent + 1, "&_StubMsg,\n");
2684 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2685 print_file(file, indent + 1, "_Handle);\n");
2688 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2691 else if (is_user_type(var->type))
2693 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2695 else if (is_string_type(var->attrs, var->type))
2697 if (is_array(type) && !is_conformant_array(type))
2698 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2701 if (type->size_is && is_size_needed_for_phase(phase))
2703 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2704 write_expr(file, type->size_is, 1);
2705 fprintf(file, ";\n");
2708 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2709 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2711 print_phase_function(file, indent, "ConformantString", phase, var,
2712 start_offset + (type->size_is ? 4 : 2));
2715 else if (is_array(type))
2717 unsigned char tc = type->type;
2718 const char *array_type = "FixedArray";
2720 /* We already have the size_is expression since it's at the
2721 top level, but do checks for multidimensional conformant
2722 arrays. When we handle them, we'll need to extend this
2723 function to return a list, and then we'll actually use
2724 the return value. */
2725 get_size_is_expr(type, var->name);
2727 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2729 if (is_size_needed_for_phase(phase))
2731 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2732 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2733 write_expr(file, type->length_is, 1);
2734 fprintf(file, ";\n\n");
2736 array_type = "VaryingArray";
2738 else if (tc == RPC_FC_CARRAY)
2740 if (is_size_needed_for_phase(phase))
2742 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2743 write_expr(file, type->size_is, 1);
2744 fprintf(file, ";\n\n");
2746 array_type = "ConformantArray";
2748 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2750 if (is_size_needed_for_phase(phase))
2754 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2755 write_expr(file, type->size_is, 1);
2756 fprintf(file, ";\n");
2758 if (type->length_is)
2760 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2761 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2762 write_expr(file, type->length_is, 1);
2763 fprintf(file, ";\n\n");
2766 array_type = (tc == RPC_FC_BOGUS_ARRAY
2768 : "ConformantVaryingArray");
2771 if (pointer_type != RPC_FC_RP) array_type = "Pointer";
2772 print_phase_function(file, indent, array_type, phase, var, start_offset);
2773 if (phase == PHASE_FREE && type->declarray && pointer_type == RPC_FC_RP)
2775 /* these are all unmarshalled by pointing into the buffer on the
2777 if (type->type != RPC_FC_SMFARRAY &&
2778 type->type != RPC_FC_LGFARRAY &&
2779 type->type != RPC_FC_CARRAY)
2781 print_file(file, indent, "if (%s)\n", var->name);
2783 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2787 else if (!is_ptr(var->type) && is_base_type(rtype))
2789 print_phase_basetype(file, indent, phase, pass, var, var->name);
2791 else if (!is_ptr(var->type))
2796 case RPC_FC_PSTRUCT:
2797 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2799 case RPC_FC_CSTRUCT:
2800 case RPC_FC_CPSTRUCT:
2801 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2803 case RPC_FC_CVSTRUCT:
2804 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2806 case RPC_FC_BOGUS_STRUCT:
2807 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2810 if (is_base_type( var->type->ref->type ))
2812 print_phase_basetype(file, indent, phase, pass, var, var->name);
2814 else if (var->type->ref->type == RPC_FC_STRUCT)
2816 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2817 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2822 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2824 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2825 write_expr( file, iid, 1 );
2826 fprintf( file, ";\n\n" );
2828 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2832 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2837 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2839 print_phase_basetype(file, indent, phase, pass, var, var->name);
2841 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2843 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2844 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2849 expr_t *sx = get_size_is_expr(type, var->name);
2851 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2853 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long) " );
2854 write_expr( file, iid, 1 );
2855 fprintf( file, ";\n\n" );
2859 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long) ");
2860 write_expr(file, sx, 1);
2861 fprintf(file, ";\n\n");
2863 if (var->type->ref->type == RPC_FC_IP)
2864 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2866 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2869 fprintf(file, "\n");
2872 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2873 enum pass pass, enum remoting_phase phase)
2875 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN)
2877 unsigned int size = get_function_buffer_size( func, pass );
2878 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2881 if (pass == PASS_RETURN)
2885 var.name = xstrdup( "_RetVal" );
2886 write_remoting_arg( file, indent, func, pass, phase, &var );
2894 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2895 write_remoting_arg( file, indent, func, pass, phase, var );
2900 size_t get_size_procformatstring_var(const var_t *var)
2902 return write_procformatstring_var(NULL, 0, var, FALSE);
2906 size_t get_size_procformatstring_func(const func_t *func)
2911 /* argument list size */
2913 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2914 size += get_size_procformatstring_var(var);
2916 /* return value size */
2917 if (is_void(func->def->type))
2918 size += 2; /* FC_END and FC_PAD */
2920 size += get_size_procformatstring_var(func->def);
2925 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2927 const ifref_t *iface;
2931 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2933 if (!pred(iface->iface))
2936 if (iface->iface->funcs)
2937 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2938 if (!is_local(func->def->attrs))
2939 size += get_size_procformatstring_func( func );
2944 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2946 set_all_tfswrite(FALSE);
2947 return process_tfs(NULL, ifaces, pred);
2950 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2951 const var_list_t *fields, const char *structvar)
2957 fprintf(h, "%lu", e->u.lval);
2960 fprintf(h, "0x%lx", e->u.lval);
2963 fprintf(h, "%#.15g", e->u.dval);
2965 case EXPR_TRUEFALSE:
2967 fprintf(h, "FALSE");
2971 case EXPR_IDENTIFIER:
2974 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2975 if (!strcmp(e->u.sval, field->name))
2977 fprintf(h, "%s->%s", structvar, e->u.sval);
2981 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2986 write_struct_expr(h, e->ref, 1, fields, structvar);
2990 write_struct_expr(h, e->ref, 1, fields, structvar);
2994 write_struct_expr(h, e->ref, 1, fields, structvar);
2998 write_type_decl(h, e->u.tref, NULL);
3000 write_struct_expr(h, e->ref, 1, fields, structvar);
3003 fprintf(h, "sizeof(");
3004 write_type_decl(h, e->u.tref, NULL);
3015 if (brackets) fprintf(h, "(");
3016 write_struct_expr(h, e->ref, 1, fields, structvar);
3018 case EXPR_SHL: fprintf(h, " << "); break;
3019 case EXPR_SHR: fprintf(h, " >> "); break;
3020 case EXPR_MUL: fprintf(h, " * "); break;
3021 case EXPR_DIV: fprintf(h, " / "); break;
3022 case EXPR_ADD: fprintf(h, " + "); break;
3023 case EXPR_SUB: fprintf(h, " - "); break;
3024 case EXPR_AND: fprintf(h, " & "); break;
3025 case EXPR_OR: fprintf(h, " | "); break;
3028 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3029 if (brackets) fprintf(h, ")");
3032 if (brackets) fprintf(h, "(");
3033 write_struct_expr(h, e->ref, 1, fields, structvar);
3035 write_struct_expr(h, e->u.ext, 1, fields, structvar);
3037 write_struct_expr(h, e->ext2, 1, fields, structvar);
3038 if (brackets) fprintf(h, ")");
3040 case EXPR_ADDRESSOF:
3042 write_struct_expr(h, e->ref, 1, fields, structvar);
3048 void declare_stub_args( FILE *file, int indent, const func_t *func )
3050 int in_attr, out_attr;
3052 const var_t *def = func->def;
3055 /* declare return value '_RetVal' */
3056 if (!is_void(def->type))
3058 print_file(file, indent, "");
3059 write_type_decl_left(file, def->type);
3060 fprintf(file, " _RetVal;\n");
3066 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3068 int is_string = is_attr(var->attrs, ATTR_STRING);
3070 in_attr = is_attr(var->attrs, ATTR_IN);
3071 out_attr = is_attr(var->attrs, ATTR_OUT);
3072 if (!out_attr && !in_attr)
3075 if (is_context_handle(var->type))
3076 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
3079 if (!in_attr && !var->type->size_is && !is_string)
3081 print_file(file, indent, "");
3082 write_type_decl(file, var->type->ref, "_W%u", i++);
3083 fprintf(file, ";\n");
3086 print_file(file, indent, "");
3087 write_type_decl_left(file, var->type);
3089 if (var->type->declarray) {
3090 fprintf(file, "( *");
3091 write_name(file, var);
3092 fprintf(file, " )");
3094 write_name(file, var);
3095 write_type_right(file, var->type, FALSE);
3096 fprintf(file, ";\n");
3098 if (decl_indirect(var->type))
3099 print_file(file, indent, "void *_p_%s = &%s;\n",
3100 var->name, var->name);
3106 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
3108 int in_attr, out_attr;
3115 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
3117 int is_string = is_attr(var->attrs, ATTR_STRING);
3118 in_attr = is_attr(var->attrs, ATTR_IN);
3119 out_attr = is_attr(var->attrs, ATTR_OUT);
3120 if (!out_attr && !in_attr)
3125 print_file(file, indent, "");
3126 write_name(file, var);
3128 if (var->type->size_is)
3130 unsigned int size, align = 0;
3131 type_t *type = var->type;
3133 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3134 for ( ; type->size_is ; type = type->ref)
3136 write_expr(file, type->size_is, TRUE);
3137 fprintf(file, " * ");
3139 size = type_memsize(type, &align);
3140 fprintf(file, "%u);\n", size);
3142 else if (!is_string)
3144 fprintf(file, " = &_W%u;\n", i);
3145 if (is_ptr(var->type) && !last_ptr(var->type))
3146 print_file(file, indent, "_W%u = 0;\n", i);
3154 fprintf(file, "\n");
3158 int write_expr_eval_routines(FILE *file, const char *iface)
3160 static const char *var_name = "pS";
3162 struct expr_eval_routine *eval;
3163 unsigned short callback_offset = 0;
3165 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3167 const char *name = eval->structure->name;
3168 const var_list_t *fields = eval->structure->fields;
3171 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3172 iface, name, callback_offset);
3173 print_file(file, 0, "{\n");
3174 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3175 name, var_name, name, eval->baseoff);
3176 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3177 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3178 write_struct_expr(file, eval->expr, 1, fields, var_name);
3179 fprintf(file, ";\n");
3180 print_file(file, 0, "}\n\n");
3186 void write_expr_eval_routine_list(FILE *file, const char *iface)
3188 struct expr_eval_routine *eval;
3189 struct expr_eval_routine *cursor;
3190 unsigned short callback_offset = 0;
3192 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3193 fprintf(file, "{\n");
3195 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3197 const char *name = eval->structure->name;
3198 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3200 list_remove(&eval->entry);
3204 fprintf(file, "};\n\n");
3207 void write_user_quad_list(FILE *file)
3211 if (list_empty(&user_type_list))
3214 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3215 fprintf(file, "{\n");
3216 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3218 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3219 print_file(file, 1, "{\n");
3220 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3221 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3222 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3223 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3224 print_file(file, 1, "}%s\n", sep);
3226 fprintf(file, "};\n\n");
3229 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3231 const struct str_list_entry_t *endpoint;
3234 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3235 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3236 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3238 print_file( f, 1, "{ (const unsigned char *)\"" );
3239 for (p = endpoint->str; *p && *p != ':'; p++)
3241 if (*p == '"' || *p == '\\') fputc( '\\', f );
3244 if (!*p) goto error;
3245 if (p[1] != '[') goto error;
3247 fprintf( f, "\", (const unsigned char *)\"" );
3248 for (p += 2; *p && *p != ']'; p++)
3250 if (*p == '"' || *p == '\\') fputc( '\\', f );
3253 if (*p != ']') goto error;
3254 fprintf( f, "\" },\n" );
3256 print_file( f, 0, "};\n\n" );
3260 error("Invalid endpoint syntax '%s'\n", endpoint->str);