2 * Format String Generator for IDL Compiler
4 * Copyright 2005-2006 Eric Kohl
5 * Copyright 2005-2006 Robert Shearman
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
41 #include "wine/list.h"
46 static const func_t *current_func;
47 static const type_t *current_structure;
49 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
50 struct expr_eval_routine
53 const type_t *structure;
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);
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 "RPC_FC_ALIGNM4";
102 case RPC_FC_ALIGNM8: return "RPC_FC_ALIGNM8";
104 error("string_of_type: unknown type 0x%02x\n", type);
109 int is_struct(unsigned char type)
116 case RPC_FC_CPSTRUCT:
117 case RPC_FC_CVSTRUCT:
118 case RPC_FC_BOGUS_STRUCT:
125 static int is_non_complex_struct(const type_t *type)
132 case RPC_FC_CPSTRUCT:
133 case RPC_FC_CVSTRUCT:
140 int is_union(unsigned char type)
144 case RPC_FC_ENCAPSULATED_UNION:
145 case RPC_FC_NON_ENCAPSULATED_UNION:
152 static unsigned short user_type_offset(const char *name)
155 unsigned short off = 0;
156 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
158 if (strcmp(name, ut->name) == 0)
162 error("user_type_offset: couldn't find type (%s)\n", name);
166 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
168 type->typestring_offset = offset;
169 if (file) type->tfswrite = FALSE;
172 static void guard_rec(type_t *type)
174 /* types that contain references to themselves (like a linked list),
175 need to be shielded from infinite recursion when writing embedded
177 if (type->typestring_offset)
178 type->tfswrite = FALSE;
180 type->typestring_offset = 1;
183 static type_t *get_user_type(const type_t *t, const char **pname)
187 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
195 if (t->kind == TKIND_ALIAS)
202 static int is_user_type(const type_t *t)
204 return get_user_type(t, NULL) != NULL;
207 static int is_embedded_complex(const type_t *type)
209 unsigned char tc = type->type;
210 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
211 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
214 static int compare_expr(const expr_t *a, const expr_t *b)
218 if (a->type != b->type)
219 return a->type - b->type;
226 return a->u.lval - b->u.lval;
228 return a->u.dval - b->u.dval;
229 case EXPR_IDENTIFIER:
230 return strcmp(a->u.sval, b->u.sval);
232 ret = compare_expr(a->ref, b->ref);
235 ret = compare_expr(a->u.ext, b->u.ext);
238 return compare_expr(a->ext2, b->ext2);
247 ret = compare_expr(a->ref, b->ref);
250 return compare_expr(a->u.ext, b->u.ext);
256 return compare_expr(a->ref, b->ref);
263 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
266 fprintf(file, "/* %2u */\n", typestring_offset); \
267 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
271 static void print_file(FILE *file, int indent, const char *format, ...)
274 va_start(va, format);
275 print(file, indent, format, va);
279 void print(FILE *file, int indent, const char *format, va_list va)
283 if (format[0] != '\n')
286 vfprintf(file, format, va);
290 void write_parameters_init(FILE *file, int indent, const func_t *func)
297 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
299 const type_t *t = var->type;
300 const char *n = var->name;
301 if (decl_indirect(t))
302 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
303 else if (is_ptr(t) || is_array(t))
304 print_file(file, indent, "%s = 0;\n", n);
310 static void write_formatdesc(FILE *f, int indent, const char *str)
312 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
313 print_file(f, indent, "{\n");
314 print_file(f, indent + 1, "short Pad;\n");
315 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
316 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
317 print_file(f, indent, "\n");
320 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, int for_objects)
322 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
323 get_size_typeformatstring(ifaces, for_objects));
325 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
326 get_size_procformatstring(ifaces, for_objects));
329 write_formatdesc(f, indent, "TYPE");
330 write_formatdesc(f, indent, "PROC");
332 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
333 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
334 print_file(f, indent, "\n");
337 static inline int is_base_type(unsigned char type)
356 case RPC_FC_ERROR_STATUS_T:
357 case RPC_FC_BIND_PRIMITIVE:
365 int decl_indirect(const type_t *t)
367 return is_user_type(t)
368 || (!is_base_type(t->type)
373 static size_t write_procformatstring_var(FILE *file, int indent,
374 const var_t *var, int is_return)
377 const type_t *type = var->type;
379 int is_in = is_attr(var->attrs, ATTR_IN);
380 int is_out = is_attr(var->attrs, ATTR_OUT);
382 if (!is_in && !is_out) is_in = TRUE;
384 if (!type->declarray && is_base_type(type->type))
387 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
389 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
391 if (type->type == RPC_FC_BIND_PRIMITIVE)
393 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
394 size = 2; /* includes param type prefix */
396 else if (is_base_type(type->type))
398 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
399 size = 2; /* includes param type prefix */
403 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
410 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
411 else if (is_in && is_out)
412 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
414 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
416 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
418 print_file(file, indent, "0x01,\n");
419 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
420 size = 4; /* includes param type prefix */
425 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
427 const ifref_t *iface;
431 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
432 print_file(file, indent, "{\n");
434 print_file(file, indent, "0,\n");
435 print_file(file, indent, "{\n");
438 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
440 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
443 if (iface->iface->funcs)
446 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
448 if (is_local(func->def->attrs)) continue;
449 /* emit argument data */
452 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
453 write_procformatstring_var(file, indent, var, FALSE);
456 /* emit return value data */
458 if (is_void(var->type))
460 print_file(file, indent, "0x5b, /* FC_END */\n");
461 print_file(file, indent, "0x5c, /* FC_PAD */\n");
464 write_procformatstring_var(file, indent, var, TRUE);
469 print_file(file, indent, "0x0\n");
471 print_file(file, indent, "}\n");
473 print_file(file, indent, "};\n");
474 print_file(file, indent, "\n");
477 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
479 if (is_base_type(type->type))
481 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
482 *typestring_offset += 1;
489 /* write conformance / variance descriptor */
490 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
491 unsigned int baseoff, const expr_t *expr)
493 unsigned char operator_type = 0;
494 const char *operator_string = "no operators";
495 const expr_t *subexpr;
499 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
505 /* Top-level conformance calculations are done inline. */
506 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
507 RPC_FC_TOP_LEVEL_CONFORMANCE);
508 print_file (file, 2, "0x0,\n");
509 print_file (file, 2, "NdrFcShort(0x0),\n");
515 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
516 error("write_conf_or_var_desc: constant value %ld is greater than "
517 "the maximum constant size of %d\n", expr->cval,
518 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
520 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
521 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
522 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
523 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
529 switch (subexpr->type)
532 subexpr = subexpr->ref;
533 operator_type = RPC_FC_DEREFERENCE;
534 operator_string = "FC_DEREFERENCE";
537 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
539 subexpr = subexpr->ref;
540 operator_type = RPC_FC_DIV_2;
541 operator_string = "FC_DIV_2";
545 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
547 subexpr = subexpr->ref;
548 operator_type = RPC_FC_MULT_2;
549 operator_string = "FC_MULT_2";
553 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
555 subexpr = subexpr->ref;
556 operator_type = RPC_FC_SUB_1;
557 operator_string = "FC_SUB_1";
561 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
563 subexpr = subexpr->ref;
564 operator_type = RPC_FC_ADD_1;
565 operator_string = "FC_ADD_1";
572 if (subexpr->type == EXPR_IDENTIFIER)
574 const type_t *correlation_variable = NULL;
575 unsigned char correlation_variable_type;
576 unsigned char param_type = 0;
577 const char *param_type_string = NULL;
581 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
583 unsigned int align = 0;
584 /* FIXME: take alignment into account */
585 if (var->name && !strcmp(var->name, subexpr->u.sval))
587 correlation_variable = var->type;
590 offset += type_memsize(var->type, &align);
592 if (!correlation_variable)
593 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
597 correlation_variable_type = correlation_variable->type;
599 switch (correlation_variable_type)
603 param_type = RPC_FC_SMALL;
604 param_type_string = "FC_SMALL";
608 param_type = RPC_FC_USMALL;
609 param_type_string = "FC_USMALL";
614 param_type = RPC_FC_SHORT;
615 param_type_string = "FC_SHORT";
618 param_type = RPC_FC_USHORT;
619 param_type_string = "FC_USHORT";
623 param_type = RPC_FC_LONG;
624 param_type_string = "FC_LONG";
627 param_type = RPC_FC_ULONG;
628 param_type_string = "FC_ULONG";
634 if (sizeof(void *) == 4) /* FIXME */
636 param_type = RPC_FC_LONG;
637 param_type_string = "FC_LONG";
641 param_type = RPC_FC_HYPER;
642 param_type_string = "FC_HYPER";
646 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
647 correlation_variable_type);
650 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
651 RPC_FC_NORMAL_CONFORMANCE | param_type, param_type_string);
652 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
653 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
658 unsigned int callback_offset = 0;
659 struct expr_eval_routine *eval;
662 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
664 if (!strcmp (eval->structure->name, structure->name)
665 && !compare_expr (eval->expr, expr))
675 eval = xmalloc (sizeof(*eval));
676 eval->structure = structure;
678 list_add_tail (&expr_eval_routines, &eval->entry);
681 if (callback_offset > USHRT_MAX)
682 error("Maximum number of callback routines reached\n");
684 print_file(file, 2, "0x%x, /* Corr desc: */\n", RPC_FC_NORMAL_CONFORMANCE);
685 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
686 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
691 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
693 int have_align = FALSE;
697 if (!fields) return 0;
698 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
700 unsigned int falign = 0;
701 size_t fsize = type_memsize(v->type, &falign);
707 size = (size + (falign - 1)) & ~(falign - 1);
711 size = (size + (*align - 1)) & ~(*align - 1);
715 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
717 size_t size, maxs = 0;
718 unsigned int align = *pmaxa;
721 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
723 /* we could have an empty default field with NULL type */
726 size = type_memsize(v->type, &align);
727 if (maxs < size) maxs = size;
728 if (*pmaxa < align) *pmaxa = align;
735 int get_padding(const var_list_t *fields)
737 unsigned short offset = 0;
744 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
746 type_t *ft = f->type;
747 unsigned int align = 0;
748 size_t size = type_memsize(ft, &align);
751 offset = (offset + (align - 1)) & ~(align - 1);
755 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
758 size_t type_memsize(const type_t *t, unsigned int *align)
762 if (t->declarray && is_conformant_array(t))
764 type_memsize(t->ref, align);
767 else if (is_ptr(t) || is_conformant_array(t))
769 size = sizeof(void *);
770 if (size > *align) *align = size;
772 else switch (t->type)
779 if (size > *align) *align = size;
786 if (size > *align) *align = size;
790 case RPC_FC_ERROR_STATUS_T:
794 if (size > *align) *align = size;
799 if (size > *align) *align = size;
802 case RPC_FC_CVSTRUCT:
803 case RPC_FC_CPSTRUCT:
806 case RPC_FC_BOGUS_STRUCT:
807 size = fields_memsize(t->fields, align);
809 case RPC_FC_ENCAPSULATED_UNION:
810 case RPC_FC_NON_ENCAPSULATED_UNION:
811 size = union_memsize(t->fields, align);
813 case RPC_FC_SMFARRAY:
814 case RPC_FC_LGFARRAY:
815 case RPC_FC_SMVARRAY:
816 case RPC_FC_LGVARRAY:
817 case RPC_FC_BOGUS_ARRAY:
818 size = t->dim * type_memsize(t->ref, align);
821 error("type_memsize: Unknown type %d\n", t->type);
828 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
830 short absoff = type->ref->typestring_offset;
831 short reloff = absoff - (offset + 2);
832 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
834 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
835 type->type, ptr_attr, string_of_type(type->type));
836 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
837 reloff, reloff, absoff);
841 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
843 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
844 type->type, string_of_type(type->type));
845 print_file(file, 2, "0x%02x,\t/* %s */\n", type->ref->type,
846 string_of_type(type->ref->type));
847 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
851 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
853 unsigned int offset = *typestring_offset;
855 print_file(file, 0, "/* %d */\n", offset);
856 update_tfsoff(type, offset, file);
858 if (type->ref->typestring_offset)
859 *typestring_offset += write_nonsimple_pointer(file, type, offset);
860 else if (is_base_type(type->ref->type))
861 *typestring_offset += write_simple_pointer(file, type);
866 static int processed(const type_t *type)
868 return type->typestring_offset && !type->tfswrite;
871 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
873 unsigned int start, absoff, flags;
874 unsigned int align = 0, ualign = 0;
876 type_t *utype = get_user_type(type, &name);
877 size_t usize = type_memsize(utype, &ualign);
878 size_t size = type_memsize(type, &align);
879 unsigned short funoff = user_type_offset(name);
884 if (is_base_type(utype->type))
887 print_file(file, 0, "/* %d */\n", absoff);
888 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
889 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
894 if (!processed(utype))
895 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
896 absoff = utype->typestring_offset;
899 if (utype->type == RPC_FC_RP)
901 else if (utype->type == RPC_FC_UP)
907 update_tfsoff(type, start, file);
908 print_file(file, 0, "/* %d */\n", start);
909 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
910 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
911 flags | (align - 1), align - 1, flags);
912 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
913 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
914 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
916 reloff = absoff - *tfsoff;
917 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
921 static void write_member_type(FILE *file, type_t *type, const var_t *field,
922 unsigned int *corroff, unsigned int *tfsoff)
924 if (is_embedded_complex(type))
929 if (is_union(type->type) && is_attr(field->attrs, ATTR_SWITCHIS))
936 absoff = type->typestring_offset;
938 reloff = absoff - (*tfsoff + 2);
940 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
941 /* FIXME: actually compute necessary padding */
942 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
943 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
944 reloff, reloff, absoff);
947 else if (is_ptr(type))
949 print_file(file, 2, "0x8,\t/* FC_LONG */\n");
952 else if (!write_base_type(file, type, tfsoff))
953 error("Unsupported member type 0x%x\n", type->type);
956 static void write_end(FILE *file, unsigned int *tfsoff)
958 if (*tfsoff % 2 == 0)
960 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
963 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
967 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
969 unsigned int offset = 0;
970 var_list_t *fs = type->fields;
973 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
975 unsigned int align = 0;
976 type_t *ft = f->type;
977 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
979 unsigned int absoff = ft->typestring_offset;
980 short reloff = absoff - (*tfsoff + 6);
981 print_file(file, 0, "/* %d */\n", *tfsoff);
982 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
983 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
984 write_conf_or_var_desc(file, current_structure, offset,
985 get_attrp(f->attrs, ATTR_SWITCHIS));
986 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
987 reloff, reloff, absoff);
991 /* FIXME: take alignment into account */
992 offset += type_memsize(ft, &align);
996 static int write_no_repeat_pointer_descriptions(
997 FILE *file, type_t *type,
998 size_t *offset_in_memory, size_t *offset_in_buffer,
999 unsigned int *typestring_offset)
1006 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1007 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1009 /* pointer instance */
1010 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1011 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1012 *typestring_offset += 6;
1014 if (processed(type->ref) || is_base_type(type->ref->type))
1015 write_pointer_tfs(file, type, typestring_offset);
1017 error("write_pointer_description: type format string unknown\n");
1020 *offset_in_memory += type_memsize(type, &align);
1021 /* FIXME: is there a case where these two are different? */
1023 *offset_in_buffer += type_memsize(type, &align);
1028 if (is_non_complex_struct(type))
1031 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1032 written += write_no_repeat_pointer_descriptions(
1034 offset_in_memory, offset_in_buffer, typestring_offset);
1039 *offset_in_memory += type_memsize(type, &align);
1040 /* FIXME: is there a case where these two are different? */
1042 *offset_in_buffer += type_memsize(type, &align);
1048 static int write_pointer_description_offsets(
1049 FILE *file, const attr_list_t *attrs, type_t *type,
1050 size_t *offset_in_memory, size_t *offset_in_buffer,
1051 unsigned int *typestring_offset)
1056 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1058 if (offset_in_memory && offset_in_buffer)
1060 /* pointer instance */
1061 /* FIXME: sometimes from end of structure, sometimes from beginning */
1062 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1063 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1066 *offset_in_memory += type_memsize(type, &align);
1067 /* FIXME: is there a case where these two are different? */
1069 *offset_in_buffer += type_memsize(type, &align);
1071 *typestring_offset += 4;
1073 if (processed(type->ref) || is_base_type(type->ref->type))
1074 write_pointer_tfs(file, type, typestring_offset);
1076 error("write_pointer_description_offsets: type format string unknown\n");
1083 return write_pointer_description_offsets(
1084 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1087 else if (is_non_complex_struct(type))
1089 /* otherwise search for interesting fields to parse */
1091 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1093 written += write_pointer_description_offsets(
1094 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1101 if (offset_in_memory)
1102 *offset_in_memory += type_memsize(type, &align);
1103 /* FIXME: is there a case where these two are different? */
1105 if (offset_in_buffer)
1106 *offset_in_buffer += type_memsize(type, &align);
1112 /* Note: if file is NULL return value is number of pointers to write, else
1113 * it is the number of type format characters written */
1114 static int write_fixed_array_pointer_descriptions(
1115 FILE *file, const attr_list_t *attrs, type_t *type,
1116 size_t *offset_in_memory, size_t *offset_in_buffer,
1117 unsigned int *typestring_offset)
1120 int pointer_count = 0;
1122 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1124 unsigned int temp = 0;
1125 /* unfortunately, this needs to be done in two passes to avoid
1126 * writing out redundant FC_FIXED_REPEAT descriptions */
1127 pointer_count = write_pointer_description_offsets(
1128 NULL, attrs, type->ref, NULL, NULL, &temp);
1129 if (pointer_count > 0)
1131 unsigned int increment_size;
1132 size_t offset_of_array_pointer_mem = 0;
1133 size_t offset_of_array_pointer_buf = 0;
1136 increment_size = type_memsize(type->ref, &align);
1138 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1139 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1140 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1141 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1142 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1143 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1144 *typestring_offset += 10;
1146 pointer_count = write_pointer_description_offsets(
1147 file, attrs, type, &offset_of_array_pointer_mem,
1148 &offset_of_array_pointer_buf, typestring_offset);
1151 else if (is_struct(type->type))
1154 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1156 pointer_count += write_fixed_array_pointer_descriptions(
1157 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1164 if (offset_in_memory)
1165 *offset_in_memory += type_memsize(type, &align);
1166 /* FIXME: is there a case where these two are different? */
1168 if (offset_in_buffer)
1169 *offset_in_buffer += type_memsize(type, &align);
1172 return pointer_count;
1175 /* Note: if file is NULL return value is number of pointers to write, else
1176 * it is the number of type format characters written */
1177 static int write_conformant_array_pointer_descriptions(
1178 FILE *file, const attr_list_t *attrs, type_t *type,
1179 size_t *offset_in_memory, size_t *offset_in_buffer,
1180 unsigned int *typestring_offset)
1183 int pointer_count = 0;
1185 if (is_conformant_array(type) && !type->length_is)
1187 unsigned int temp = 0;
1188 /* unfortunately, this needs to be done in two passes to avoid
1189 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1190 pointer_count = write_pointer_description_offsets(
1191 NULL, attrs, type->ref, NULL, NULL, &temp);
1192 if (pointer_count > 0)
1194 unsigned int increment_size;
1195 size_t offset_of_array_pointer_mem = 0;
1196 size_t offset_of_array_pointer_buf = 0;
1199 increment_size = type_memsize(type->ref, &align);
1201 if (increment_size > USHRT_MAX)
1202 error("array size of %u bytes is too large\n", increment_size);
1204 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1205 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1206 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1207 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1208 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1209 *typestring_offset += 8;
1211 pointer_count = write_pointer_description_offsets(
1212 file, attrs, type->ref, &offset_of_array_pointer_mem,
1213 &offset_of_array_pointer_buf, typestring_offset);
1216 else if (is_struct(type->type))
1219 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1221 pointer_count += write_conformant_array_pointer_descriptions(
1222 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1229 if (offset_in_memory)
1230 *offset_in_memory += type_memsize(type, &align);
1231 /* FIXME: is there a case where these two are different? */
1233 if (offset_in_buffer)
1234 *offset_in_buffer += type_memsize(type, &align);
1237 return pointer_count;
1240 /* Note: if file is NULL return value is number of pointers to write, else
1241 * it is the number of type format characters written */
1242 static int write_varying_array_pointer_descriptions(
1243 FILE *file, const attr_list_t *attrs, type_t *type,
1244 size_t *offset_in_memory, size_t *offset_in_buffer,
1245 unsigned int *typestring_offset)
1248 int pointer_count = 0;
1250 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1252 if (is_array(type) && type->length_is)
1254 unsigned int temp = 0;
1255 /* unfortunately, this needs to be done in two passes to avoid
1256 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1257 pointer_count = write_pointer_description_offsets(
1258 NULL, attrs, type->ref, NULL, NULL, &temp);
1259 if (pointer_count > 0)
1261 unsigned int increment_size;
1262 size_t offset_of_array_pointer_mem = 0;
1263 size_t offset_of_array_pointer_buf = 0;
1266 increment_size = type_memsize(type->ref, &align);
1268 if (increment_size > USHRT_MAX)
1269 error("array size of %u bytes is too large\n", increment_size);
1271 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1272 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1273 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1274 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1275 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1276 *typestring_offset += 8;
1278 pointer_count = write_pointer_description_offsets(
1279 file, attrs, type, &offset_of_array_pointer_mem,
1280 &offset_of_array_pointer_buf, typestring_offset);
1283 else if (is_struct(type->type))
1286 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1288 pointer_count += write_varying_array_pointer_descriptions(
1289 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1296 if (offset_in_memory)
1297 *offset_in_memory += type_memsize(type, &align);
1298 /* FIXME: is there a case where these two are different? */
1300 if (offset_in_buffer)
1301 *offset_in_buffer += type_memsize(type, &align);
1304 return pointer_count;
1307 static void write_pointer_description(FILE *file, type_t *type,
1308 unsigned int *typestring_offset)
1310 size_t offset_in_buffer;
1311 size_t offset_in_memory;
1313 /* pass 1: search for single instance of a pointer (i.e. don't descend
1315 offset_in_memory = 0;
1316 offset_in_buffer = 0;
1317 write_no_repeat_pointer_descriptions(
1319 &offset_in_memory, &offset_in_buffer, typestring_offset);
1321 /* pass 2: search for pointers in fixed arrays */
1322 offset_in_memory = 0;
1323 offset_in_buffer = 0;
1324 write_fixed_array_pointer_descriptions(
1326 &offset_in_memory, &offset_in_buffer, typestring_offset);
1328 /* pass 3: search for pointers in conformant only arrays (but don't descend
1329 * into conformant varying or varying arrays) */
1330 offset_in_memory = 0;
1331 offset_in_buffer = 0;
1332 write_conformant_array_pointer_descriptions(
1334 &offset_in_memory, &offset_in_buffer, typestring_offset);
1336 /* pass 4: search for pointers in varying arrays */
1337 offset_in_memory = 0;
1338 offset_in_buffer = 0;
1339 write_varying_array_pointer_descriptions(
1341 &offset_in_memory, &offset_in_buffer, typestring_offset);
1344 static int is_declptr(const type_t *t)
1346 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1349 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1351 const char *name, unsigned int *typestring_offset)
1353 size_t start_offset = *typestring_offset;
1354 unsigned char rtype;
1356 update_tfsoff(type, start_offset, file);
1358 if (is_declptr(type))
1360 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1361 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1363 pointer_type = RPC_FC_RP;
1364 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1365 pointer_type, flag, string_of_type(pointer_type),
1366 flag ? " [simple_pointer]" : "");
1367 *typestring_offset += 2;
1370 print_file(file, 2, "NdrFcShort(0x2),\n");
1371 *typestring_offset += 2;
1373 rtype = type->ref->type;
1376 rtype = type->ref->type;
1378 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1380 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1381 return start_offset;
1384 if (type->declarray && !is_conformant_array(type))
1386 /* FIXME: multi-dimensional array */
1387 if (0xffffuL < type->dim)
1388 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1389 name, 0xffffu, type->dim - 0xffffu);
1391 if (rtype == RPC_FC_CHAR)
1392 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1394 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1395 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1396 *typestring_offset += 2;
1398 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1399 *typestring_offset += 2;
1401 return start_offset;
1403 else if (type->size_is)
1405 unsigned int align = 0;
1407 if (rtype == RPC_FC_CHAR)
1408 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1410 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1411 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1412 *typestring_offset += 2;
1414 *typestring_offset += write_conf_or_var_desc(
1415 file, current_structure,
1416 (type->declarray && current_structure
1417 ? type_memsize(current_structure, &align)
1421 return start_offset;
1425 if (rtype == RPC_FC_WCHAR)
1426 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1428 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1429 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1430 *typestring_offset += 2;
1432 return start_offset;
1436 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1437 const char *name, unsigned int *typestring_offset)
1439 const expr_t *length_is = type->length_is;
1440 const expr_t *size_is = type->size_is;
1441 unsigned int align = 0;
1443 size_t start_offset;
1445 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1447 pointer_type = RPC_FC_RP;
1449 has_pointer = FALSE;
1450 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1453 size = type_memsize(type, &align);
1454 if (size == 0) /* conformant array */
1455 size = type_memsize(type->ref, &align);
1457 start_offset = *typestring_offset;
1458 update_tfsoff(type, start_offset, file);
1459 print_file(file, 0, "/* %lu */\n", start_offset);
1460 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1461 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1462 *typestring_offset += 2;
1465 if (type->type != RPC_FC_BOGUS_ARRAY)
1467 unsigned char tc = type->type;
1468 unsigned int baseoff
1469 = type->declarray && current_structure
1470 ? type_memsize(current_structure, &align)
1473 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1475 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1476 *typestring_offset += 4;
1480 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1481 *typestring_offset += 2;
1484 if (is_conformant_array(type))
1486 += write_conf_or_var_desc(file, current_structure, baseoff,
1489 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1491 unsigned int elalign = 0;
1492 size_t elsize = type_memsize(type->ref, &elalign);
1494 if (type->type == RPC_FC_LGVARRAY)
1496 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1497 *typestring_offset += 4;
1501 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1502 *typestring_offset += 2;
1505 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1506 *typestring_offset += 2;
1511 += write_conf_or_var_desc(file, current_structure, baseoff,
1516 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1517 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1518 *typestring_offset += 2;
1519 write_pointer_description(file, type, typestring_offset);
1520 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1521 *typestring_offset += 1;
1524 write_member_type(file, type->ref, NULL, NULL, typestring_offset);
1525 write_end(file, typestring_offset);
1528 error("%s: complex arrays unimplemented\n", name);
1530 return start_offset;
1533 static const var_t *find_array_or_string_in_struct(const type_t *type)
1535 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1536 const type_t *ft = last_field->type;
1538 if (ft->declarray && is_conformant_array(ft))
1541 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1542 return find_array_or_string_in_struct(last_field->type);
1547 static void write_struct_members(FILE *file, const type_t *type,
1548 unsigned int *corroff, unsigned int *typestring_offset)
1551 unsigned short offset = 0;
1555 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1557 type_t *ft = field->type;
1558 if (!ft->declarray || !is_conformant_array(ft))
1560 unsigned int align = 0;
1561 size_t size = type_memsize(ft, &align);
1564 if ((align - 1) & offset)
1566 unsigned char fc = 0;
1570 fc = RPC_FC_ALIGNM4;
1573 fc = RPC_FC_ALIGNM8;
1576 error("write_struct_members: cannot align type %d", ft->type);
1578 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1579 offset = (offset + (align - 1)) & ~(align - 1);
1580 *typestring_offset += 1;
1582 write_member_type(file, ft, field, corroff, typestring_offset);
1587 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1590 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1591 RPC_FC_STRUCTPAD1 + padding - 1,
1593 *typestring_offset += 1;
1596 write_end(file, typestring_offset);
1599 static size_t write_struct_tfs(FILE *file, type_t *type,
1600 const char *name, unsigned int *tfsoff)
1602 const type_t *save_current_structure = current_structure;
1603 unsigned int total_size;
1605 size_t start_offset;
1606 size_t array_offset;
1607 int has_pointers = 0;
1608 unsigned int align = 0;
1609 unsigned int corroff;
1613 current_structure = type;
1615 total_size = type_memsize(type, &align);
1616 if (total_size > USHRT_MAX)
1617 error("structure size for %s exceeds %d bytes by %d bytes\n",
1618 name, USHRT_MAX, total_size - USHRT_MAX);
1620 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1621 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1624 array = find_array_or_string_in_struct(type);
1625 if (array && !processed(array->type))
1627 = is_attr(array->attrs, ATTR_STRING)
1628 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1629 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1632 write_descriptors(file, type, tfsoff);
1634 start_offset = *tfsoff;
1635 update_tfsoff(type, start_offset, file);
1636 print_file(file, 0, "/* %d */\n", start_offset);
1637 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1638 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1639 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1644 unsigned int absoff = array->type->typestring_offset;
1645 short reloff = absoff - *tfsoff;
1646 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1647 reloff, reloff, absoff);
1650 else if (type->type == RPC_FC_BOGUS_STRUCT)
1652 print_file(file, 2, "NdrFcShort(0x0),\n");
1656 if (type->type == RPC_FC_BOGUS_STRUCT)
1659 print_file(file, 2, "NdrFcShort(0x0),\t/* FIXME: pointer stuff */\n");
1662 else if ((type->type == RPC_FC_PSTRUCT) ||
1663 (type->type == RPC_FC_CPSTRUCT) ||
1664 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1666 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1667 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1669 write_pointer_description(file, type, tfsoff);
1670 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1674 write_struct_members(file, type, &corroff, tfsoff);
1676 current_structure = save_current_structure;
1677 return start_offset;
1680 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1681 unsigned char flags, size_t offset,
1682 unsigned int *typeformat_offset)
1684 size_t start_offset = *typeformat_offset;
1685 short reloff = offset - (*typeformat_offset + 2);
1686 int in_attr, out_attr;
1687 in_attr = is_attr(attrs, ATTR_IN);
1688 out_attr = is_attr(attrs, ATTR_OUT);
1689 if (!in_attr && !out_attr) in_attr = 1;
1691 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1694 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1697 string_of_type(pointer_type));
1701 fprintf(file, " [allocated_on_stack]");
1703 fprintf(file, " [pointer_deref]");
1704 fprintf(file, " */\n");
1707 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1708 *typeformat_offset += 4;
1710 return start_offset;
1713 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1717 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1719 else if (is_base_type(t->type))
1721 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1722 t->type, string_of_type(t->type));
1724 else if (t->typestring_offset)
1726 short reloff = t->typestring_offset - *tfsoff;
1727 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1728 reloff, reloff, t->typestring_offset);
1731 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1736 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1738 unsigned int align = 0;
1739 unsigned int start_offset;
1740 size_t size = type_memsize(type, &align);
1743 type_t *deftype = NULL;
1744 short nodeftype = 0xffff;
1749 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1751 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1752 fields = uv->type->fields;
1755 fields = type->fields;
1757 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1759 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1761 nbranch += list_count(cases);
1763 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1766 start_offset = *tfsoff;
1767 update_tfsoff(type, start_offset, file);
1768 print_file(file, 0, "/* %d */\n", start_offset);
1769 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1771 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1772 const type_t *st = sv->type;
1785 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1786 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1787 0x40 | st->type, string_of_type(st->type));
1791 error("union switch type must be an integer, char, or enum\n");
1794 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1795 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1798 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1800 type_t *ft = f->type;
1801 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1802 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1805 if (cases == NULL && !deflt)
1806 error("union field %s with neither case nor default attribute\n", f->name);
1808 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1810 /* MIDL doesn't check for duplicate cases, even though that seems
1811 like a reasonable thing to do, it just dumps them to the TFS
1812 like we're going to do here. */
1813 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1815 write_branch_type(file, ft, tfsoff);
1818 /* MIDL allows multiple default branches, even though that seems
1819 illogical, it just chooses the last one, which is what we will
1830 write_branch_type(file, deftype, tfsoff);
1834 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1838 return start_offset;
1841 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1842 unsigned int *typeformat_offset)
1845 size_t start_offset = *typeformat_offset;
1846 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1852 expr.type = EXPR_IDENTIFIER;
1854 expr.u.sval = iid->name;
1855 expr.is_const = FALSE;
1856 print_file(file, 2, "0x2f, /* FC_IP */\n");
1857 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1858 *typeformat_offset += write_conf_or_var_desc(file, NULL, 0, &expr) + 2;
1862 const type_t *base = is_ptr(type) ? type->ref : type;
1863 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1866 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1868 update_tfsoff(type, start_offset, file);
1869 print_file(file, 0, "/* %d */\n", start_offset);
1870 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1871 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1872 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1873 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1874 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1875 for (i = 0; i < 8; ++i)
1876 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1879 fprintf(file, "\n");
1881 *typeformat_offset += 18;
1883 return start_offset;
1886 static int get_ptr_attr(const type_t *t, int def_type)
1890 int ptr_attr = get_attrv(t->attrs, ATTR_POINTERTYPE);
1893 if (t->kind != TKIND_ALIAS)
1899 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
1900 type_t *type, const var_t *var,
1901 unsigned int *typeformat_offset)
1906 if (is_user_type(type))
1908 write_user_tfs(file, type, typeformat_offset);
1909 return type->typestring_offset;
1912 if (type == var->type) /* top-level pointers */
1914 int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE);
1915 if (pointer_attr != 0 && !is_ptr(type) && !is_array(type))
1916 error("'%s': pointer attribute applied to non-pointer type\n", var->name);
1918 if (pointer_attr == 0)
1919 pointer_attr = get_ptr_attr(type, RPC_FC_RP);
1921 pointer_type = pointer_attr;
1924 pointer_type = get_ptr_attr(type, RPC_FC_UP);
1926 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
1927 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
1930 return write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
1934 /* basic types don't need a type format string */
1935 if (is_base_type(type->type))
1941 case RPC_FC_PSTRUCT:
1942 case RPC_FC_CSTRUCT:
1943 case RPC_FC_CPSTRUCT:
1944 case RPC_FC_CVSTRUCT:
1945 case RPC_FC_BOGUS_STRUCT:
1946 return write_struct_tfs(file, type, var->name, typeformat_offset);
1947 case RPC_FC_ENCAPSULATED_UNION:
1948 case RPC_FC_NON_ENCAPSULATED_UNION:
1949 return write_union_tfs(file, type, typeformat_offset);
1951 case RPC_FC_BIND_PRIMITIVE:
1955 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
1958 else if (last_ptr(type))
1960 size_t start_offset = *typeformat_offset;
1961 int in_attr = is_attr(var->attrs, ATTR_IN);
1962 int out_attr = is_attr(var->attrs, ATTR_OUT);
1963 const type_t *base = type->ref;
1965 if (base->type == RPC_FC_IP)
1967 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
1970 /* special case for pointers to base types */
1971 if (is_base_type(base->type))
1973 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
1974 pointer_type, (!in_attr && out_attr) ? 0x0C : 0x08,
1975 string_of_type(pointer_type),
1976 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
1977 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
1978 print_file(file, indent, "0x5c, /* FC_PAD */\n");
1979 *typeformat_offset += 4;
1980 return start_offset;
1984 assert(is_ptr(type));
1986 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
1988 fprintf(file, "/* %2u */\n", *typeformat_offset);
1989 return write_pointer_only_tfs(file, var->attrs, pointer_type,
1990 !last_ptr(type) ? 0x10 : 0,
1991 offset, typeformat_offset);
1994 static void set_tfswrite(type_t *type, int val)
1996 while (type->tfswrite != val)
1998 type_t *utype = get_user_type(type, NULL);
2000 type->tfswrite = val;
2003 set_tfswrite(utype, val);
2005 if (type->kind == TKIND_ALIAS)
2007 else if (is_ptr(type) || is_array(type))
2014 LIST_FOR_EACH_ENTRY( v, type->fields, var_t, entry )
2016 set_tfswrite(v->type, val);
2024 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2025 const char *name, int write_ptr, unsigned int *tfsoff)
2029 if (is_user_type(type))
2031 write_user_tfs(file, type, tfsoff);
2033 else if (is_ptr(type))
2035 type_t *ref = type->ref;
2037 if (ref->type == RPC_FC_IP)
2039 write_ip_tfs(file, attrs, type, tfsoff);
2043 if (!processed(ref) && !is_base_type(ref->type))
2044 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2047 write_pointer_tfs(file, type, tfsoff);
2052 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2054 write_string_tfs(file, attrs, type, name, tfsoff);
2056 else if (type->declarray && is_conformant_array(type))
2057 ; /* conformant arrays and strings are handled specially */
2058 else if (is_array(type))
2060 write_array_tfs(file, attrs, type, name, tfsoff);
2062 else if (is_struct(type->type))
2064 if (!processed(type))
2065 write_struct_tfs(file, type, name, tfsoff);
2067 else if (is_union(type->type))
2069 if (!processed(type))
2070 write_union_tfs(file, type, tfsoff);
2072 else if (!is_base_type(type->type))
2073 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2079 static void set_all_tfswrite(const ifref_list_t *ifaces, int val)
2081 const ifref_t * iface;
2086 LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2087 if (iface->iface->funcs)
2088 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2090 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2091 set_tfswrite(var->type, val);
2094 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, int for_objects)
2097 const ifref_t *iface;
2098 unsigned int typeformat_offset = 2;
2100 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2102 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2105 if (iface->iface->funcs)
2108 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2110 if (is_local(func->def->attrs)) continue;
2112 current_func = func;
2114 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2117 write_typeformatstring_var(
2118 file, 2, func, var->type, var,
2119 &typeformat_offset),
2125 return typeformat_offset + 1;
2129 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
2133 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2134 print_file(file, indent, "{\n");
2136 print_file(file, indent, "0,\n");
2137 print_file(file, indent, "{\n");
2139 print_file(file, indent, "NdrFcShort(0x0),\n");
2141 set_all_tfswrite(ifaces, TRUE);
2142 process_tfs(file, ifaces, for_objects);
2144 print_file(file, indent, "0x0\n");
2146 print_file(file, indent, "}\n");
2148 print_file(file, indent, "};\n");
2149 print_file(file, indent, "\n");
2152 static unsigned int get_required_buffer_size_type(
2153 const type_t *type, const char *name, unsigned int *alignment)
2158 if (is_user_type(type))
2161 const type_t *utype = get_user_type(type, &uname);
2162 size = get_required_buffer_size_type(utype, uname, alignment);
2164 else if (!is_ptr(type))
2188 case RPC_FC_ERROR_STATUS_T:
2200 case RPC_FC_BIND_PRIMITIVE:
2204 case RPC_FC_PSTRUCT:
2207 if (!type->fields) return 0;
2208 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2210 unsigned int alignment;
2211 size += get_required_buffer_size_type(field->type, field->name,
2218 if (is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT)
2219 size = get_required_buffer_size_type( type->ref, name, alignment );
2222 case RPC_FC_SMFARRAY:
2223 case RPC_FC_LGFARRAY:
2224 size = type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2227 case RPC_FC_SMVARRAY:
2228 case RPC_FC_LGVARRAY:
2229 get_required_buffer_size_type(type->ref, name, alignment);
2234 case RPC_FC_CVARRAY:
2235 get_required_buffer_size_type(type->ref, name, alignment);
2236 size = sizeof(void *);
2240 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
2247 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2249 int in_attr = is_attr(var->attrs, ATTR_IN);
2250 int out_attr = is_attr(var->attrs, ATTR_OUT);
2252 if (!in_attr && !out_attr)
2257 if (pass == PASS_OUT)
2259 if (out_attr && is_ptr(var->type))
2261 type_t *type = var->type;
2263 if (type->type == RPC_FC_STRUCT)
2266 unsigned int size = 36;
2268 if (!type->fields) return size;
2269 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2272 size += get_required_buffer_size_type(
2273 field->type, field->name, &align);
2282 if ((!out_attr || in_attr) && !var->type->size_is
2283 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2285 if (is_ptr(var->type))
2287 type_t *type = var->type;
2289 if (is_base_type(type->type))
2293 else if (type->type == RPC_FC_STRUCT)
2295 unsigned int size = 36;
2298 if (!type->fields) return size;
2299 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2302 size += get_required_buffer_size_type(
2303 field->type, field->name, &align);
2310 return get_required_buffer_size_type(var->type, var->name, alignment);
2314 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2317 unsigned int total_size = 0, alignment;
2321 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2323 total_size += get_required_buffer_size(var, &alignment, pass);
2324 total_size += alignment;
2328 if (pass == PASS_OUT && !is_void(func->def->type))
2330 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2331 total_size += alignment;
2336 static void print_phase_function(FILE *file, int indent, const char *type,
2337 enum remoting_phase phase,
2338 const var_t *var, unsigned int type_offset)
2340 const char *function;
2343 case PHASE_BUFFERSIZE:
2344 function = "BufferSize";
2347 function = "Marshall";
2349 case PHASE_UNMARSHAL:
2350 function = "Unmarshall";
2360 print_file(file, indent, "Ndr%s%s(\n", type, function);
2362 print_file(file, indent, "&_StubMsg,\n");
2363 print_file(file, indent, "%s%s%s%s,\n",
2364 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2365 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2366 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2368 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2369 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2370 if (phase == PHASE_UNMARSHAL)
2371 print_file(file, indent, "0);\n");
2375 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2376 enum pass pass, const var_t *var,
2377 const char *varname)
2379 type_t *type = var->type;
2381 unsigned int alignment = 0;
2382 unsigned char rtype;
2384 /* no work to do for other phases, buffer sizing is done elsewhere */
2385 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2388 rtype = is_ptr(type) ? type->ref->type : type->type;
2412 case RPC_FC_ERROR_STATUS_T:
2424 case RPC_FC_BIND_PRIMITIVE:
2425 /* no marshalling needed */
2429 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2433 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2434 alignment - 1, alignment - 1);
2436 if (phase == PHASE_MARSHAL)
2438 print_file(file, indent, "*(");
2439 write_type(file, is_ptr(type) ? type->ref : type, FALSE, NULL);
2441 fprintf(file, " *)_StubMsg.Buffer = *");
2443 fprintf(file, " *)_StubMsg.Buffer = ");
2444 fprintf(file, varname);
2445 fprintf(file, ";\n");
2447 else if (phase == PHASE_UNMARSHAL)
2449 if (pass == PASS_IN || pass == PASS_RETURN)
2450 print_file(file, indent, "");
2452 print_file(file, indent, "*");
2453 fprintf(file, varname);
2454 if (pass == PASS_IN && is_ptr(type))
2455 fprintf(file, " = (");
2457 fprintf(file, " = *(");
2458 write_type(file, is_ptr(type) ? type->ref : type, FALSE, NULL);
2459 fprintf(file, " *)_StubMsg.Buffer;\n");
2462 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2463 write_type(file, var->type, FALSE, NULL);
2464 fprintf(file, ");\n");
2467 /* returns whether the MaxCount, Offset or ActualCount members need to be
2468 * filled in for the specified phase */
2469 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2471 return (phase != PHASE_UNMARSHAL);
2474 static int needs_freeing(const attr_list_t *attrs, const type_t *t, int out)
2479 && (t->ref->type == RPC_FC_IP
2480 || is_ptr(t->ref))))
2481 || (out && (is_string_type(attrs, t)
2485 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2486 enum pass pass, enum remoting_phase phase)
2488 int in_attr, out_attr, pointer_type;
2494 if (phase == PHASE_BUFFERSIZE)
2496 unsigned int size = get_function_buffer_size( func, pass );
2497 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2500 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2502 const type_t *type = var->type;
2503 unsigned char rtype;
2504 size_t start_offset = type->typestring_offset;
2506 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2508 pointer_type = RPC_FC_RP;
2510 in_attr = is_attr(var->attrs, ATTR_IN);
2511 out_attr = is_attr(var->attrs, ATTR_OUT);
2512 if (!in_attr && !out_attr)
2515 if (phase == PHASE_FREE)
2517 if (!needs_freeing(var->attrs, type, out_attr))
2524 if (!in_attr) continue;
2527 if (!out_attr) continue;
2535 if (is_user_type(var->type))
2537 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2539 else if (is_string_type(var->attrs, var->type))
2541 if (is_array(type) && !is_conformant_array(type))
2542 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2545 if (type->size_is && is_size_needed_for_phase(phase))
2547 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2548 write_expr(file, type->size_is, 1);
2549 fprintf(file, ";\n");
2552 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2553 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2555 print_phase_function(file, indent, "ConformantString", phase, var,
2556 start_offset + (type->size_is ? 4 : 2));
2559 else if (is_array(type))
2561 unsigned char tc = type->type;
2562 const char *array_type;
2564 if (tc == RPC_FC_SMFARRAY || tc == RPC_FC_LGFARRAY)
2565 array_type = "FixedArray";
2566 else if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2568 if (is_size_needed_for_phase(phase))
2570 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2571 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2572 write_expr(file, type->length_is, 1);
2573 fprintf(file, ";\n\n");
2575 array_type = "VaryingArray";
2577 else if (tc == RPC_FC_CARRAY)
2579 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2581 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2582 write_expr(file, type->size_is, 1);
2583 fprintf(file, ";\n\n");
2585 array_type = "ConformantArray";
2587 else if (tc == RPC_FC_CVARRAY)
2589 if (is_size_needed_for_phase(phase))
2591 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2592 write_expr(file, type->size_is, 1);
2593 fprintf(file, ";\n");
2594 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2595 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2596 write_expr(file, type->length_is, 1);
2597 fprintf(file, ";\n\n");
2599 array_type = "ConformantVaryingArray";
2602 array_type = "ComplexArray";
2604 if (!in_attr && phase == PHASE_FREE)
2606 print_file(file, indent, "if (%s)\n", var->name);
2608 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2610 else if (phase != PHASE_FREE)
2612 if (pointer_type == RPC_FC_UP)
2613 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2615 print_phase_function(file, indent, array_type, phase, var, start_offset);
2618 else if (!is_ptr(var->type) && is_base_type(rtype))
2620 print_phase_basetype(file, indent, phase, pass, var, var->name);
2622 else if (!is_ptr(var->type))
2627 case RPC_FC_PSTRUCT:
2628 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2630 case RPC_FC_CSTRUCT:
2631 case RPC_FC_CPSTRUCT:
2632 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2634 case RPC_FC_CVSTRUCT:
2635 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2637 case RPC_FC_BOGUS_STRUCT:
2638 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2641 if (is_base_type( var->type->ref->type ))
2643 print_phase_basetype(file, indent, phase, pass, var, var->name);
2645 else if (var->type->ref->type == RPC_FC_STRUCT)
2647 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2648 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2653 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2654 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2655 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2659 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2664 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2666 print_phase_basetype(file, indent, phase, pass, var, var->name);
2668 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2670 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2671 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2676 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2677 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2678 if (var->type->ref->type == RPC_FC_IP)
2679 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2681 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2684 fprintf(file, "\n");
2689 size_t get_size_procformatstring_var(const var_t *var)
2691 return write_procformatstring_var(NULL, 0, var, FALSE);
2695 size_t get_size_procformatstring_func(const func_t *func)
2700 /* argument list size */
2702 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2703 size += get_size_procformatstring_var(var);
2705 /* return value size */
2706 if (is_void(func->def->type))
2707 size += 2; /* FC_END and FC_PAD */
2709 size += get_size_procformatstring_var(func->def);
2714 size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects)
2716 const ifref_t *iface;
2720 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2722 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2725 if (iface->iface->funcs)
2726 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2727 if (!is_local(func->def->attrs))
2728 size += get_size_procformatstring_func( func );
2733 size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects)
2735 set_all_tfswrite(ifaces, FALSE);
2736 return process_tfs(NULL, ifaces, for_objects);
2739 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2740 const var_list_t *fields, const char *structvar)
2746 fprintf(h, "%lu", e->u.lval);
2749 fprintf(h, "0x%lx", e->u.lval);
2752 fprintf(h, "%#.15g", e->u.dval);
2754 case EXPR_TRUEFALSE:
2756 fprintf(h, "FALSE");
2760 case EXPR_IDENTIFIER:
2763 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2764 if (!strcmp(e->u.sval, field->name))
2766 fprintf(h, "%s->%s", structvar, e->u.sval);
2770 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2775 write_struct_expr(h, e->ref, 1, fields, structvar);
2779 write_struct_expr(h, e->ref, 1, fields, structvar);
2783 write_struct_expr(h, e->ref, 1, fields, structvar);
2787 write_type(h, e->u.tref, FALSE, NULL);
2789 write_struct_expr(h, e->ref, 1, fields, structvar);
2792 fprintf(h, "sizeof(");
2793 write_type(h, e->u.tref, FALSE, NULL);
2804 if (brackets) fprintf(h, "(");
2805 write_struct_expr(h, e->ref, 1, fields, structvar);
2807 case EXPR_SHL: fprintf(h, " << "); break;
2808 case EXPR_SHR: fprintf(h, " >> "); break;
2809 case EXPR_MUL: fprintf(h, " * "); break;
2810 case EXPR_DIV: fprintf(h, " / "); break;
2811 case EXPR_ADD: fprintf(h, " + "); break;
2812 case EXPR_SUB: fprintf(h, " - "); break;
2813 case EXPR_AND: fprintf(h, " & "); break;
2814 case EXPR_OR: fprintf(h, " | "); break;
2817 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2818 if (brackets) fprintf(h, ")");
2821 if (brackets) fprintf(h, "(");
2822 write_struct_expr(h, e->ref, 1, fields, structvar);
2824 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2826 write_struct_expr(h, e->ext2, 1, fields, structvar);
2827 if (brackets) fprintf(h, ")");
2833 void declare_stub_args( FILE *file, int indent, const func_t *func )
2835 int in_attr, out_attr;
2837 const var_t *def = func->def;
2840 /* declare return value '_RetVal' */
2841 if (!is_void(def->type))
2843 print_file(file, indent, "");
2844 write_type_left(file, def->type);
2845 fprintf(file, " _RetVal;\n");
2851 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2853 int is_string = is_attr(var->attrs, ATTR_STRING);
2855 in_attr = is_attr(var->attrs, ATTR_IN);
2856 out_attr = is_attr(var->attrs, ATTR_OUT);
2857 if (!out_attr && !in_attr)
2860 if (!in_attr && !var->type->size_is && !is_string)
2862 print_file(file, indent, "");
2863 write_type(file, var->type->ref, FALSE, "_W%u", i++);
2864 fprintf(file, ";\n");
2867 print_file(file, indent, "");
2868 write_type_left(file, var->type);
2870 if (var->type->declarray) {
2871 fprintf(file, "( *");
2872 write_name(file, var);
2873 fprintf(file, " )");
2875 write_name(file, var);
2876 write_type_right(file, var->type, FALSE);
2877 fprintf(file, ";\n");
2879 if (decl_indirect(var->type))
2880 print_file(file, indent, "void *_p_%s = &%s;\n",
2881 var->name, var->name);
2886 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
2888 int in_attr, out_attr;
2895 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2897 int is_string = is_attr(var->attrs, ATTR_STRING);
2898 in_attr = is_attr(var->attrs, ATTR_IN);
2899 out_attr = is_attr(var->attrs, ATTR_OUT);
2900 if (!out_attr && !in_attr)
2905 print_file(file, indent, "");
2906 write_name(file, var);
2908 if (var->type->size_is)
2910 unsigned int size, align = 0;
2911 type_t *type = var->type;
2913 fprintf(file, " = NdrAllocate(&_StubMsg, ");
2914 for ( ; type->size_is ; type = type->ref)
2916 write_expr(file, type->size_is, TRUE);
2917 fprintf(file, " * ");
2919 size = type_memsize(type, &align);
2920 fprintf(file, "%u);\n", size);
2922 else if (!is_string)
2924 fprintf(file, " = &_W%u;\n", i);
2925 if (is_ptr(var->type) && !last_ptr(var->type))
2926 print_file(file, indent, "_W%u = 0;\n", i);
2934 fprintf(file, "\n");
2938 int write_expr_eval_routines(FILE *file, const char *iface)
2940 static const char *var_name = "pS";
2942 struct expr_eval_routine *eval;
2943 unsigned short callback_offset = 0;
2945 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
2947 const char *name = eval->structure->name;
2948 const var_list_t *fields = eval->structure->fields;
2952 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2953 iface, name, callback_offset);
2954 print_file(file, 0, "{\n");
2955 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
2956 name, var_name, name, type_memsize (eval->structure, &align));
2957 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
2958 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
2959 write_struct_expr(file, eval->expr, 1, fields, var_name);
2960 fprintf(file, ";\n");
2961 print_file(file, 0, "}\n\n");
2967 void write_expr_eval_routine_list(FILE *file, const char *iface)
2969 struct expr_eval_routine *eval;
2970 struct expr_eval_routine *cursor;
2971 unsigned short callback_offset = 0;
2973 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2974 fprintf(file, "{\n");
2976 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
2978 const char *name = eval->structure->name;
2979 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
2981 list_remove(&eval->entry);
2985 fprintf(file, "};\n\n");
2988 void write_user_quad_list(FILE *file)
2992 if (list_empty(&user_type_list))
2995 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
2996 fprintf(file, "{\n");
2997 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
2999 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3000 print_file(file, 1, "{\n");
3001 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3002 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3003 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3004 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3005 print_file(file, 1, "}%s\n", sep);
3007 fprintf(file, "};\n\n");
3010 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3012 const struct str_list_entry_t *endpoint;
3015 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3016 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3017 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3019 print_file( f, 1, "{ (const unsigned char *)\"" );
3020 for (p = endpoint->str; *p && *p != ':'; p++)
3022 if (*p == '"' || *p == '\\') fputc( '\\', f );
3025 if (!*p) goto error;
3026 if (p[1] != '[') goto error;
3028 fprintf( f, "\", (const unsigned char *)\"" );
3029 for (p += 2; *p && *p != ']'; p++)
3031 if (*p == '"' || *p == '\\') fputc( '\\', f );
3034 if (*p != ']') goto error;
3035 fprintf( f, "\" },\n" );
3037 print_file( f, 0, "};\n\n" );
3041 error("Invalid endpoint syntax '%s'\n", endpoint->str);