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"
39 #include "wine/list.h"
43 static const func_t
*current_func
;
44 static const type_t
*current_structure
;
45 static const ifref_t
*current_iface
;
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
);
61 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
63 const char *name
, unsigned int *typestring_offset
);
65 const char *string_of_type(unsigned char type
)
69 case RPC_FC_BYTE
: return "FC_BYTE";
70 case RPC_FC_CHAR
: return "FC_CHAR";
71 case RPC_FC_SMALL
: return "FC_SMALL";
72 case RPC_FC_USMALL
: return "FC_USMALL";
73 case RPC_FC_WCHAR
: return "FC_WCHAR";
74 case RPC_FC_SHORT
: return "FC_SHORT";
75 case RPC_FC_USHORT
: return "FC_USHORT";
76 case RPC_FC_LONG
: return "FC_LONG";
77 case RPC_FC_ULONG
: return "FC_ULONG";
78 case RPC_FC_FLOAT
: return "FC_FLOAT";
79 case RPC_FC_HYPER
: return "FC_HYPER";
80 case RPC_FC_DOUBLE
: return "FC_DOUBLE";
81 case RPC_FC_ENUM16
: return "FC_ENUM16";
82 case RPC_FC_ENUM32
: return "FC_ENUM32";
83 case RPC_FC_IGNORE
: return "FC_IGNORE";
84 case RPC_FC_ERROR_STATUS_T
: return "FC_ERROR_STATUS_T";
85 case RPC_FC_RP
: return "FC_RP";
86 case RPC_FC_UP
: return "FC_UP";
87 case RPC_FC_OP
: return "FC_OP";
88 case RPC_FC_FP
: return "FC_FP";
89 case RPC_FC_ENCAPSULATED_UNION
: return "FC_ENCAPSULATED_UNION";
90 case RPC_FC_NON_ENCAPSULATED_UNION
: return "FC_NON_ENCAPSULATED_UNION";
91 case RPC_FC_STRUCT
: return "FC_STRUCT";
92 case RPC_FC_PSTRUCT
: return "FC_PSTRUCT";
93 case RPC_FC_CSTRUCT
: return "FC_CSTRUCT";
94 case RPC_FC_CPSTRUCT
: return "FC_CPSTRUCT";
95 case RPC_FC_CVSTRUCT
: return "FC_CVSTRUCT";
96 case RPC_FC_BOGUS_STRUCT
: return "FC_BOGUS_STRUCT";
97 case RPC_FC_SMFARRAY
: return "FC_SMFARRAY";
98 case RPC_FC_LGFARRAY
: return "FC_LGFARRAY";
99 case RPC_FC_SMVARRAY
: return "FC_SMVARRAY";
100 case RPC_FC_LGVARRAY
: return "FC_LGVARRAY";
101 case RPC_FC_CARRAY
: return "FC_CARRAY";
102 case RPC_FC_CVARRAY
: return "FC_CVARRAY";
103 case RPC_FC_BOGUS_ARRAY
: return "FC_BOGUS_ARRAY";
104 case RPC_FC_ALIGNM4
: return "FC_ALIGNM4";
105 case RPC_FC_ALIGNM8
: return "FC_ALIGNM8";
106 case RPC_FC_POINTER
: return "FC_POINTER";
107 case RPC_FC_C_CSTRING
: return "FC_C_CSTRING";
108 case RPC_FC_C_WSTRING
: return "FC_C_WSTRING";
109 case RPC_FC_CSTRING
: return "FC_CSTRING";
110 case RPC_FC_WSTRING
: return "FC_WSTRING";
112 error("string_of_type: unknown type 0x%02x\n", type
);
117 int is_struct(unsigned char type
)
124 case RPC_FC_CPSTRUCT
:
125 case RPC_FC_CVSTRUCT
:
126 case RPC_FC_BOGUS_STRUCT
:
133 static int is_non_complex_struct(const type_t
*type
)
140 case RPC_FC_CPSTRUCT
:
141 case RPC_FC_CVSTRUCT
:
148 int is_union(unsigned char type
)
152 case RPC_FC_ENCAPSULATED_UNION
:
153 case RPC_FC_NON_ENCAPSULATED_UNION
:
160 static int type_has_pointers(const type_t
*type
)
162 if (is_user_type(type
))
164 else if (is_ptr(type
))
166 else if (is_array(type
))
167 return type_has_pointers(type
->ref
);
168 else if (is_struct(type
->type
))
171 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
173 if (type_has_pointers(field
->type
))
177 else if (is_union(type
->type
))
181 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
183 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
184 fields
= uv
->type
->fields
;
187 fields
= type
->fields
;
188 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
190 if (field
->type
&& type_has_pointers(field
->type
))
198 static int type_has_full_pointer(const type_t
*type
)
200 if (is_user_type(type
))
202 else if (type
->type
== RPC_FC_FP
)
204 else if (is_ptr(type
))
206 else if (is_array(type
))
207 return type_has_full_pointer(type
->ref
);
208 else if (is_struct(type
->type
))
211 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
213 if (type_has_full_pointer(field
->type
))
217 else if (is_union(type
->type
))
221 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
223 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
224 fields
= uv
->type
->fields
;
227 fields
= type
->fields
;
228 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
230 if (field
->type
&& type_has_full_pointer(field
->type
))
238 static unsigned short user_type_offset(const char *name
)
241 unsigned short off
= 0;
242 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
244 if (strcmp(name
, ut
->name
) == 0)
248 error("user_type_offset: couldn't find type (%s)\n", name
);
252 static void update_tfsoff(type_t
*type
, unsigned int offset
, FILE *file
)
254 type
->typestring_offset
= offset
;
255 if (file
) type
->tfswrite
= FALSE
;
258 static void guard_rec(type_t
*type
)
260 /* types that contain references to themselves (like a linked list),
261 need to be shielded from infinite recursion when writing embedded
263 if (type
->typestring_offset
)
264 type
->tfswrite
= FALSE
;
266 type
->typestring_offset
= 1;
269 static type_t
*get_user_type(const type_t
*t
, const char **pname
)
273 type_t
*ut
= get_attrp(t
->attrs
, ATTR_WIREMARSHAL
);
281 if (t
->kind
== TKIND_ALIAS
)
288 int is_user_type(const type_t
*t
)
290 return get_user_type(t
, NULL
) != NULL
;
293 static int is_embedded_complex(const type_t
*type
)
295 unsigned char tc
= type
->type
;
296 return is_struct(tc
) || is_union(tc
) || is_array(type
) || is_user_type(type
)
297 || (is_ptr(type
) && type
->ref
->type
== RPC_FC_IP
);
300 static const char *get_context_handle_type_name(const type_t
*type
)
303 for (t
= type
; is_ptr(t
); t
= t
->ref
)
304 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
310 /* This is actually fairly involved to implement precisely, due to the
311 effects attributes may have and things like that. Right now this is
312 only used for optimization, so just check for a very small set of
313 criteria that guarantee the types are equivalent; assume every thing
314 else is different. */
315 static int compare_type(const type_t
*a
, const type_t
*b
)
320 && strcmp(a
->name
, b
->name
) == 0))
322 /* Ordering doesn't need to be implemented yet. */
326 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
330 if (a
->type
!= b
->type
)
331 return a
->type
- b
->type
;
338 return a
->u
.lval
- b
->u
.lval
;
340 return a
->u
.dval
- b
->u
.dval
;
341 case EXPR_IDENTIFIER
:
342 return strcmp(a
->u
.sval
, b
->u
.sval
);
344 ret
= compare_expr(a
->ref
, b
->ref
);
347 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
350 return compare_expr(a
->ext2
, b
->ext2
);
359 ret
= compare_expr(a
->ref
, b
->ref
);
362 return compare_expr(a
->u
.ext
, b
->u
.ext
);
364 ret
= compare_type(a
->u
.tref
, b
->u
.tref
);
372 return compare_expr(a
->ref
, b
->ref
);
374 return compare_type(a
->u
.tref
, b
->u
.tref
);
381 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
384 fprintf(file, "/* %2u */\n", typestring_offset); \
385 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
389 static void print_file(FILE *file
, int indent
, const char *format
, ...)
392 va_start(va
, format
);
393 print(file
, indent
, format
, va
);
397 void print(FILE *file
, int indent
, const char *format
, va_list va
)
401 if (format
[0] != '\n')
404 vfprintf(file
, format
, va
);
409 static void write_var_init(FILE *file
, int indent
, const type_t
*t
, const char *n
)
411 if (decl_indirect(t
))
412 print_file(file
, indent
, "MIDL_memset(&%s, 0, sizeof(%s));\n", n
, n
);
413 else if (is_ptr(t
) || is_array(t
))
414 print_file(file
, indent
, "%s = 0;\n", n
);
417 void write_parameters_init(FILE *file
, int indent
, const func_t
*func
)
421 if (!is_void(get_func_return_type(func
)))
422 write_var_init(file
, indent
, get_func_return_type(func
), "_RetVal");
427 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
428 write_var_init(file
, indent
, var
->type
, var
->name
);
433 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
435 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
436 print_file(f
, indent
, "{\n");
437 print_file(f
, indent
+ 1, "short Pad;\n");
438 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
439 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
440 print_file(f
, indent
, "\n");
443 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, type_pred_t pred
)
445 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
446 get_size_typeformatstring(ifaces
, pred
));
448 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
449 get_size_procformatstring(ifaces
, pred
));
452 write_formatdesc(f
, indent
, "TYPE");
453 write_formatdesc(f
, indent
, "PROC");
455 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
456 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
457 print_file(f
, indent
, "\n");
460 static inline int is_base_type(unsigned char type
)
479 case RPC_FC_ERROR_STATUS_T
:
480 case RPC_FC_BIND_PRIMITIVE
:
488 int decl_indirect(const type_t
*t
)
490 return is_user_type(t
)
491 || (!is_base_type(t
->type
)
496 static size_t write_procformatstring_type(FILE *file
, int indent
,
499 const attr_list_t
*attrs
,
504 int is_in
= is_attr(attrs
, ATTR_IN
);
505 int is_out
= is_attr(attrs
, ATTR_OUT
);
507 if (!is_in
&& !is_out
) is_in
= TRUE
;
509 if (!type
->declarray
&& is_base_type(type
->type
))
512 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
514 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
516 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
518 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
519 size
= 2; /* includes param type prefix */
521 else if (is_base_type(type
->type
))
523 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
524 size
= 2; /* includes param type prefix */
528 error("Unknown/unsupported type: %s (0x%02x)\n", name
, type
->type
);
535 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
536 else if (is_in
&& is_out
)
537 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
539 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
541 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
543 print_file(file
, indent
, "0x01,\n");
544 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
545 size
= 4; /* includes param type prefix */
550 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
552 const ifref_t
*iface
;
556 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
557 print_file(file
, indent
, "{\n");
559 print_file(file
, indent
, "0,\n");
560 print_file(file
, indent
, "{\n");
563 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
565 if (!pred(iface
->iface
))
568 if (iface
->iface
->funcs
)
571 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
573 if (is_local(func
->def
->attrs
)) continue;
574 /* emit argument data */
577 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
578 write_procformatstring_type(file
, indent
, var
->name
, var
->type
, var
->attrs
, FALSE
);
581 /* emit return value data */
582 if (is_void(get_func_return_type(func
)))
584 print_file(file
, indent
, "0x5b, /* FC_END */\n");
585 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
588 write_procformatstring_type(file
, indent
, "return value", get_func_return_type(func
), NULL
, TRUE
);
593 print_file(file
, indent
, "0x0\n");
595 print_file(file
, indent
, "}\n");
597 print_file(file
, indent
, "};\n");
598 print_file(file
, indent
, "\n");
601 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
603 if (is_base_type(type
->type
))
605 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
606 *typestring_offset
+= 1;
613 /* write conformance / variance descriptor */
614 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
615 unsigned int baseoff
, const type_t
*type
,
618 unsigned char operator_type
= 0;
619 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
620 const char *conftype_string
= "";
621 const char *operator_string
= "no operators";
622 const expr_t
*subexpr
;
626 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
632 /* Top-level conformance calculations are done inline. */
633 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
634 RPC_FC_TOP_LEVEL_CONFORMANCE
);
635 print_file (file
, 2, "0x0,\n");
636 print_file (file
, 2, "NdrFcShort(0x0),\n");
642 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
643 error("write_conf_or_var_desc: constant value %ld is greater than "
644 "the maximum constant size of %d\n", expr
->cval
,
645 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
647 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
648 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
649 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
650 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
655 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
657 conftype
= RPC_FC_POINTER_CONFORMANCE
;
658 conftype_string
= "field pointer, ";
662 switch (subexpr
->type
)
665 subexpr
= subexpr
->ref
;
666 operator_type
= RPC_FC_DEREFERENCE
;
667 operator_string
= "FC_DEREFERENCE";
670 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
672 subexpr
= subexpr
->ref
;
673 operator_type
= RPC_FC_DIV_2
;
674 operator_string
= "FC_DIV_2";
678 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
680 subexpr
= subexpr
->ref
;
681 operator_type
= RPC_FC_MULT_2
;
682 operator_string
= "FC_MULT_2";
686 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
688 subexpr
= subexpr
->ref
;
689 operator_type
= RPC_FC_SUB_1
;
690 operator_string
= "FC_SUB_1";
694 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
696 subexpr
= subexpr
->ref
;
697 operator_type
= RPC_FC_ADD_1
;
698 operator_string
= "FC_ADD_1";
705 if (subexpr
->type
== EXPR_IDENTIFIER
)
707 const type_t
*correlation_variable
= NULL
;
708 unsigned char correlation_variable_type
;
709 unsigned char param_type
= 0;
713 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
715 unsigned int align
= 0;
716 /* FIXME: take alignment into account */
717 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
719 correlation_variable
= var
->type
;
722 offset
+= type_memsize(var
->type
, &align
);
724 if (!correlation_variable
)
725 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
729 correlation_variable_type
= correlation_variable
->type
;
731 switch (correlation_variable_type
)
735 param_type
= RPC_FC_SMALL
;
739 param_type
= RPC_FC_USMALL
;
744 param_type
= RPC_FC_SHORT
;
747 param_type
= RPC_FC_USHORT
;
751 param_type
= RPC_FC_LONG
;
754 param_type
= RPC_FC_ULONG
;
760 if (sizeof(void *) == 4) /* FIXME */
761 param_type
= RPC_FC_LONG
;
763 param_type
= RPC_FC_HYPER
;
766 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
767 correlation_variable_type
);
770 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
771 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
772 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
773 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
778 unsigned int callback_offset
= 0;
779 struct expr_eval_routine
*eval
;
782 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
784 if (!strcmp (eval
->structure
->name
, structure
->name
)
785 && !compare_expr (eval
->expr
, expr
))
795 eval
= xmalloc (sizeof(*eval
));
796 eval
->structure
= structure
;
797 eval
->baseoff
= baseoff
;
799 list_add_tail (&expr_eval_routines
, &eval
->entry
);
802 if (callback_offset
> USHRT_MAX
)
803 error("Maximum number of callback routines reached\n");
805 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
806 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
807 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
812 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
814 int have_align
= FALSE
;
818 if (!fields
) return 0;
819 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
821 unsigned int falign
= 0;
822 size_t fsize
= type_memsize(v
->type
, &falign
);
828 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
832 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
836 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
838 size_t size
, maxs
= 0;
839 unsigned int align
= *pmaxa
;
842 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
844 /* we could have an empty default field with NULL type */
847 size
= type_memsize(v
->type
, &align
);
848 if (maxs
< size
) maxs
= size
;
849 if (*pmaxa
< align
) *pmaxa
= align
;
856 int get_padding(const var_list_t
*fields
)
858 unsigned short offset
= 0;
865 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
867 type_t
*ft
= f
->type
;
868 unsigned int align
= 0;
869 size_t size
= type_memsize(ft
, &align
);
872 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
876 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
879 size_t type_memsize(const type_t
*t
, unsigned int *align
)
883 if (t
->declarray
&& is_conformant_array(t
))
885 type_memsize(t
->ref
, align
);
888 else if (is_ptr(t
) || is_conformant_array(t
))
890 size
= sizeof(void *);
891 if (size
> *align
) *align
= size
;
893 else switch (t
->type
)
900 if (size
> *align
) *align
= size
;
907 if (size
> *align
) *align
= size
;
911 case RPC_FC_ERROR_STATUS_T
:
915 if (size
> *align
) *align
= size
;
920 if (size
> *align
) *align
= size
;
923 case RPC_FC_CVSTRUCT
:
924 case RPC_FC_CPSTRUCT
:
927 case RPC_FC_BOGUS_STRUCT
:
928 size
= fields_memsize(t
->fields
, align
);
930 case RPC_FC_ENCAPSULATED_UNION
:
931 case RPC_FC_NON_ENCAPSULATED_UNION
:
932 size
= union_memsize(t
->fields
, align
);
934 case RPC_FC_SMFARRAY
:
935 case RPC_FC_LGFARRAY
:
936 case RPC_FC_SMVARRAY
:
937 case RPC_FC_LGVARRAY
:
938 case RPC_FC_BOGUS_ARRAY
:
939 size
= t
->dim
* type_memsize(t
->ref
, align
);
942 error("type_memsize: Unknown type %d\n", t
->type
);
949 int is_full_pointer_function(const func_t
*func
)
952 if (type_has_full_pointer(get_func_return_type(func
)))
956 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
957 if (type_has_full_pointer( var
->type
))
962 void write_full_pointer_init(FILE *file
, int indent
, const func_t
*func
, int is_server
)
964 print_file(file
, indent
, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
965 is_server
? "XLAT_SERVER" : "XLAT_CLIENT");
969 void write_full_pointer_free(FILE *file
, int indent
, const func_t
*func
)
971 print_file(file
, indent
, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
975 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
977 short absoff
= type
->ref
->typestring_offset
;
978 short reloff
= absoff
- (offset
+ 2);
979 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
981 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
982 type
->type
, ptr_attr
, string_of_type(type
->type
));
983 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
984 reloff
, reloff
, absoff
);
988 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
990 unsigned char fc
= type
->ref
->type
;
991 /* for historical reasons, write_simple_pointer also handled string types,
992 * but no longer does. catch bad uses of the function with this check */
993 if (is_string_type(type
->attrs
, type
))
994 error("write_simple_pointer: can't handle type %s which is a string type\n", type
->name
);
995 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
996 type
->type
, string_of_type(type
->type
));
997 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
998 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1002 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
1004 print_file(file
, 0, "/* %u (", tfsoff
);
1005 write_type_decl(file
, t
, NULL
);
1006 print_file(file
, 0, ") */\n");
1009 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
1011 unsigned int offset
= *typestring_offset
;
1013 print_start_tfs_comment(file
, type
, offset
);
1014 update_tfsoff(type
, offset
, file
);
1016 if (type
->ref
->typestring_offset
)
1017 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
1018 else if (is_base_type(type
->ref
->type
))
1019 *typestring_offset
+= write_simple_pointer(file
, type
);
1024 static int processed(const type_t
*type
)
1026 return type
->typestring_offset
&& !type
->tfswrite
;
1029 static int user_type_has_variable_size(const type_t
*t
)
1036 case RPC_FC_PSTRUCT
:
1037 case RPC_FC_CSTRUCT
:
1038 case RPC_FC_CPSTRUCT
:
1039 case RPC_FC_CVSTRUCT
:
1042 /* Note: Since this only applies to user types, we can't have a conformant
1043 array here, and strings should get filed under pointer in this case. */
1047 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1049 unsigned int start
, absoff
, flags
;
1050 unsigned int align
= 0, ualign
= 0;
1052 type_t
*utype
= get_user_type(type
, &name
);
1053 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
1054 size_t size
= type_memsize(type
, &align
);
1055 unsigned short funoff
= user_type_offset(name
);
1060 if (is_base_type(utype
->type
))
1063 print_start_tfs_comment(file
, utype
, absoff
);
1064 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
1065 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1070 if (!processed(utype
))
1071 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
1072 absoff
= utype
->typestring_offset
;
1075 if (utype
->type
== RPC_FC_RP
)
1077 else if (utype
->type
== RPC_FC_UP
)
1083 update_tfsoff(type
, start
, file
);
1084 print_start_tfs_comment(file
, type
, start
);
1085 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
1086 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1087 flags
| (align
- 1), align
- 1, flags
);
1088 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
1089 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
1090 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
1092 reloff
= absoff
- *tfsoff
;
1093 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
1097 static void write_member_type(FILE *file
, const type_t
*cont
,
1098 const attr_list_t
*attrs
, const type_t
*type
,
1099 unsigned int *corroff
, unsigned int *tfsoff
)
1101 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1106 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1113 absoff
= type
->typestring_offset
;
1115 reloff
= absoff
- (*tfsoff
+ 2);
1117 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1118 /* FIXME: actually compute necessary padding */
1119 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1120 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1121 reloff
, reloff
, absoff
);
1124 else if (is_ptr(type
) || is_conformant_array(type
))
1126 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1129 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1132 else if (!write_base_type(file
, type
, tfsoff
))
1133 error("Unsupported member type 0x%x\n", type
->type
);
1136 static void write_end(FILE *file
, unsigned int *tfsoff
)
1138 if (*tfsoff
% 2 == 0)
1140 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1143 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1147 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1149 unsigned int offset
= 0;
1150 var_list_t
*fs
= type
->fields
;
1153 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1155 unsigned int align
= 0;
1156 type_t
*ft
= f
->type
;
1157 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1159 unsigned int absoff
= ft
->typestring_offset
;
1160 short reloff
= absoff
- (*tfsoff
+ 6);
1161 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1162 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1163 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1164 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1165 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1166 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1167 reloff
, reloff
, absoff
);
1171 /* FIXME: take alignment into account */
1172 offset
+= type_memsize(ft
, &align
);
1176 static int write_no_repeat_pointer_descriptions(
1177 FILE *file
, type_t
*type
,
1178 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1179 unsigned int *typestring_offset
)
1184 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1186 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1187 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1189 /* pointer instance */
1190 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1191 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1192 *typestring_offset
+= 6;
1196 if (is_string_type(type
->attrs
, type
))
1197 write_string_tfs(file
, NULL
, type
, NULL
, typestring_offset
);
1199 write_pointer_tfs(file
, type
, typestring_offset
);
1203 unsigned absoff
= type
->typestring_offset
;
1204 short reloff
= absoff
- (*typestring_offset
+ 2);
1205 /* FIXME: get pointer attributes from field */
1206 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1207 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1208 reloff
, reloff
, absoff
);
1209 *typestring_offset
+= 4;
1213 *offset_in_memory
+= type_memsize(type
, &align
);
1214 /* FIXME: is there a case where these two are different? */
1216 *offset_in_buffer
+= type_memsize(type
, &align
);
1221 if (is_non_complex_struct(type
))
1224 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1225 written
+= write_no_repeat_pointer_descriptions(
1227 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1232 *offset_in_memory
+= type_memsize(type
, &align
);
1233 /* FIXME: is there a case where these two are different? */
1235 *offset_in_buffer
+= type_memsize(type
, &align
);
1241 static int write_pointer_description_offsets(
1242 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1243 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1244 unsigned int *typestring_offset
)
1249 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1251 if (offset_in_memory
&& offset_in_buffer
)
1253 /* pointer instance */
1254 /* FIXME: sometimes from end of structure, sometimes from beginning */
1255 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1256 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1259 *offset_in_memory
+= type_memsize(type
, &align
);
1260 /* FIXME: is there a case where these two are different? */
1262 *offset_in_buffer
+= type_memsize(type
, &align
);
1264 *typestring_offset
+= 4;
1266 if (is_string_type(attrs
, type
))
1267 write_string_tfs(file
, NULL
, type
, NULL
, typestring_offset
);
1268 else if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1269 write_pointer_tfs(file
, type
, typestring_offset
);
1271 error("write_pointer_description_offsets: type format string unknown\n");
1278 return write_pointer_description_offsets(
1279 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1282 else if (is_non_complex_struct(type
))
1284 /* otherwise search for interesting fields to parse */
1286 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1288 written
+= write_pointer_description_offsets(
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
);
1307 /* Note: if file is NULL return value is number of pointers to write, else
1308 * it is the number of type format characters written */
1309 static int write_fixed_array_pointer_descriptions(
1310 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1311 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1312 unsigned int *typestring_offset
)
1315 int pointer_count
= 0;
1317 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1319 unsigned int temp
= 0;
1320 /* unfortunately, this needs to be done in two passes to avoid
1321 * writing out redundant FC_FIXED_REPEAT descriptions */
1322 pointer_count
= write_pointer_description_offsets(
1323 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1324 if (pointer_count
> 0)
1326 unsigned int increment_size
;
1327 size_t offset_of_array_pointer_mem
= 0;
1328 size_t offset_of_array_pointer_buf
= 0;
1331 increment_size
= type_memsize(type
->ref
, &align
);
1333 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1334 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1335 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1336 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1337 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1338 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1339 *typestring_offset
+= 10;
1341 pointer_count
= write_pointer_description_offsets(
1342 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1343 &offset_of_array_pointer_buf
, typestring_offset
);
1346 else if (is_struct(type
->type
))
1349 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1351 pointer_count
+= write_fixed_array_pointer_descriptions(
1352 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1359 if (offset_in_memory
)
1360 *offset_in_memory
+= type_memsize(type
, &align
);
1361 /* FIXME: is there a case where these two are different? */
1363 if (offset_in_buffer
)
1364 *offset_in_buffer
+= type_memsize(type
, &align
);
1367 return pointer_count
;
1370 /* Note: if file is NULL return value is number of pointers to write, else
1371 * it is the number of type format characters written */
1372 static int write_conformant_array_pointer_descriptions(
1373 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1374 size_t offset_in_memory
, unsigned int *typestring_offset
)
1377 int pointer_count
= 0;
1379 if (is_conformant_array(type
) && !type
->length_is
)
1381 unsigned int temp
= 0;
1382 /* unfortunately, this needs to be done in two passes to avoid
1383 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1384 pointer_count
= write_pointer_description_offsets(
1385 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1386 if (pointer_count
> 0)
1388 unsigned int increment_size
;
1389 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1390 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1393 increment_size
= type_memsize(type
->ref
, &align
);
1395 if (increment_size
> USHRT_MAX
)
1396 error("array size of %u bytes is too large\n", increment_size
);
1398 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1399 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1400 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1401 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1402 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1403 *typestring_offset
+= 8;
1405 pointer_count
= write_pointer_description_offsets(
1406 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1407 &offset_of_array_pointer_buf
, typestring_offset
);
1411 return pointer_count
;
1414 /* Note: if file is NULL return value is number of pointers to write, else
1415 * it is the number of type format characters written */
1416 static int write_varying_array_pointer_descriptions(
1417 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1418 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1419 unsigned int *typestring_offset
)
1422 int pointer_count
= 0;
1424 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1426 if (is_array(type
) && type
->length_is
)
1428 unsigned int temp
= 0;
1429 /* unfortunately, this needs to be done in two passes to avoid
1430 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1431 pointer_count
= write_pointer_description_offsets(
1432 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1433 if (pointer_count
> 0)
1435 unsigned int increment_size
;
1436 size_t offset_of_array_pointer_mem
= 0;
1437 size_t offset_of_array_pointer_buf
= 0;
1440 increment_size
= type_memsize(type
->ref
, &align
);
1442 if (increment_size
> USHRT_MAX
)
1443 error("array size of %u bytes is too large\n", increment_size
);
1445 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1446 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1447 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1448 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1449 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1450 *typestring_offset
+= 8;
1452 pointer_count
= write_pointer_description_offsets(
1453 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1454 &offset_of_array_pointer_buf
, typestring_offset
);
1457 else if (is_struct(type
->type
))
1460 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1462 pointer_count
+= write_varying_array_pointer_descriptions(
1463 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1470 if (offset_in_memory
)
1471 *offset_in_memory
+= type_memsize(type
, &align
);
1472 /* FIXME: is there a case where these two are different? */
1474 if (offset_in_buffer
)
1475 *offset_in_buffer
+= type_memsize(type
, &align
);
1478 return pointer_count
;
1481 static void write_pointer_description(FILE *file
, type_t
*type
,
1482 unsigned int *typestring_offset
)
1484 size_t offset_in_buffer
;
1485 size_t offset_in_memory
;
1487 /* pass 1: search for single instance of a pointer (i.e. don't descend
1489 if (!is_array(type
))
1491 offset_in_memory
= 0;
1492 offset_in_buffer
= 0;
1493 write_no_repeat_pointer_descriptions(
1495 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1498 /* pass 2: search for pointers in fixed arrays */
1499 offset_in_memory
= 0;
1500 offset_in_buffer
= 0;
1501 write_fixed_array_pointer_descriptions(
1503 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1505 /* pass 3: search for pointers in conformant only arrays (but don't descend
1506 * into conformant varying or varying arrays) */
1507 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1508 write_conformant_array_pointer_descriptions(
1509 file
, NULL
, type
, 0, typestring_offset
);
1510 else if (type
->type
== RPC_FC_CPSTRUCT
)
1512 unsigned int align
= 0;
1513 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1514 write_conformant_array_pointer_descriptions(
1516 type_memsize(type
, &align
),
1520 /* pass 4: search for pointers in varying arrays */
1521 offset_in_memory
= 0;
1522 offset_in_buffer
= 0;
1523 write_varying_array_pointer_descriptions(
1525 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1528 int is_declptr(const type_t
*t
)
1530 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1533 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1535 const char *name
, unsigned int *typestring_offset
)
1537 size_t start_offset
;
1538 unsigned char rtype
;
1540 if (is_declptr(type
))
1542 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1543 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1545 pointer_type
= RPC_FC_RP
;
1546 print_start_tfs_comment(file
, type
, *typestring_offset
);
1547 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1548 pointer_type
, flag
, string_of_type(pointer_type
),
1549 flag
? " [simple_pointer]" : "");
1550 *typestring_offset
+= 2;
1553 print_file(file
, 2, "NdrFcShort(0x2),\n");
1554 *typestring_offset
+= 2;
1558 start_offset
= *typestring_offset
;
1559 update_tfsoff(type
, start_offset
, file
);
1561 rtype
= type
->ref
->type
;
1563 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1565 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1566 return start_offset
;
1569 if (type
->declarray
&& !is_conformant_array(type
))
1571 /* FIXME: multi-dimensional array */
1572 if (0xffffuL
< type
->dim
)
1573 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1574 name
, 0xffffu
, type
->dim
- 0xffffu
);
1576 if (rtype
== RPC_FC_CHAR
)
1577 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1579 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1580 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1581 *typestring_offset
+= 2;
1583 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1584 *typestring_offset
+= 2;
1586 return start_offset
;
1588 else if (type
->size_is
)
1590 unsigned int align
= 0;
1592 if (rtype
== RPC_FC_CHAR
)
1593 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1595 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1596 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1597 *typestring_offset
+= 2;
1599 *typestring_offset
+= write_conf_or_var_desc(
1600 file
, current_structure
,
1601 (type
->declarray
&& current_structure
1602 ? type_memsize(current_structure
, &align
)
1604 type
, type
->size_is
);
1606 return start_offset
;
1610 if (rtype
== RPC_FC_WCHAR
)
1611 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1613 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1614 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1615 *typestring_offset
+= 2;
1617 return start_offset
;
1621 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1622 const char *name
, unsigned int *typestring_offset
)
1624 const expr_t
*length_is
= type
->length_is
;
1625 const expr_t
*size_is
= type
->size_is
;
1626 unsigned int align
= 0;
1628 size_t start_offset
;
1630 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1631 unsigned int baseoff
1632 = type
->declarray
&& current_structure
1633 ? type_memsize(current_structure
, &align
)
1637 pointer_type
= RPC_FC_RP
;
1639 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1642 has_pointer
= type_has_pointers(type
->ref
);
1645 size
= type_memsize((is_conformant_array(type
) ? type
->ref
: type
), &align
);
1647 start_offset
= *typestring_offset
;
1648 update_tfsoff(type
, start_offset
, file
);
1649 print_start_tfs_comment(file
, type
, start_offset
);
1650 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1651 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1652 *typestring_offset
+= 2;
1655 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1657 unsigned char tc
= type
->type
;
1659 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1661 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1662 *typestring_offset
+= 4;
1666 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1667 *typestring_offset
+= 2;
1670 if (is_conformant_array(type
))
1672 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1675 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1677 unsigned int elalign
= 0;
1678 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1680 if (type
->type
== RPC_FC_LGVARRAY
)
1682 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1683 *typestring_offset
+= 4;
1687 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1688 *typestring_offset
+= 2;
1691 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1692 *typestring_offset
+= 2;
1697 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1700 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1702 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1703 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1704 *typestring_offset
+= 2;
1705 write_pointer_description(file
, type
, typestring_offset
);
1706 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1707 *typestring_offset
+= 1;
1710 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1711 write_end(file
, typestring_offset
);
1715 unsigned int dim
= size_is
? 0 : type
->dim
;
1716 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1717 *typestring_offset
+= 2;
1719 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1722 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1724 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1725 write_end(file
, typestring_offset
);
1728 return start_offset
;
1731 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1733 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1734 const type_t
*ft
= last_field
->type
;
1736 if (ft
->declarray
&& is_conformant_array(ft
))
1739 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1740 return find_array_or_string_in_struct(last_field
->type
);
1745 static void write_struct_members(FILE *file
, const type_t
*type
,
1746 unsigned int *corroff
, unsigned int *typestring_offset
)
1749 unsigned short offset
= 0;
1753 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1755 type_t
*ft
= field
->type
;
1756 if (!ft
->declarray
|| !is_conformant_array(ft
))
1758 unsigned int align
= 0;
1759 size_t size
= type_memsize(ft
, &align
);
1762 if ((align
- 1) & offset
)
1764 unsigned char fc
= 0;
1768 fc
= RPC_FC_ALIGNM4
;
1771 fc
= RPC_FC_ALIGNM8
;
1774 error("write_struct_members: cannot align type %d\n", ft
->type
);
1776 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1777 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1778 *typestring_offset
+= 1;
1780 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1786 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1789 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1790 RPC_FC_STRUCTPAD1
+ padding
- 1,
1792 *typestring_offset
+= 1;
1795 write_end(file
, typestring_offset
);
1798 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1799 const char *name
, unsigned int *tfsoff
)
1801 const type_t
*save_current_structure
= current_structure
;
1802 unsigned int total_size
;
1804 size_t start_offset
;
1805 size_t array_offset
;
1806 int has_pointers
= 0;
1807 unsigned int align
= 0;
1808 unsigned int corroff
;
1812 current_structure
= type
;
1814 total_size
= type_memsize(type
, &align
);
1815 if (total_size
> USHRT_MAX
)
1816 error("structure size for %s exceeds %d bytes by %d bytes\n",
1817 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1819 if (type
->fields
) LIST_FOR_EACH_ENTRY(f
, type
->fields
, var_t
, entry
)
1820 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1822 if (!has_pointers
) has_pointers
= type_has_pointers(type
);
1824 array
= find_array_or_string_in_struct(type
);
1825 if (array
&& !processed(array
->type
))
1827 = is_attr(array
->attrs
, ATTR_STRING
)
1828 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
)
1829 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1832 write_descriptors(file
, type
, tfsoff
);
1834 start_offset
= *tfsoff
;
1835 update_tfsoff(type
, start_offset
, file
);
1836 print_start_tfs_comment(file
, type
, start_offset
);
1837 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1838 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1839 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1844 unsigned int absoff
= array
->type
->typestring_offset
;
1845 short reloff
= absoff
- *tfsoff
;
1846 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1847 reloff
, reloff
, absoff
);
1850 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1852 print_file(file
, 2, "NdrFcShort(0x0),\n");
1856 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1858 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1859 nothing is written to file yet. On the actual writing pass,
1860 this will have been updated. */
1861 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1862 short reloff
= absoff
- *tfsoff
;
1863 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1864 reloff
, reloff
, absoff
);
1867 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1868 (type
->type
== RPC_FC_CPSTRUCT
) ||
1869 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1871 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1872 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1874 write_pointer_description(file
, type
, tfsoff
);
1875 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1879 write_struct_members(file
, type
, &corroff
, tfsoff
);
1881 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1883 const var_list_t
*fs
= type
->fields
;
1886 type
->ptrdesc
= *tfsoff
;
1887 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1889 type_t
*ft
= f
->type
;
1892 if (is_string_type(f
->attrs
, ft
))
1893 write_string_tfs(file
, f
->attrs
, ft
, f
->name
, tfsoff
);
1895 write_pointer_tfs(file
, ft
, tfsoff
);
1897 else if (!ft
->declarray
&& is_conformant_array(ft
))
1899 unsigned int absoff
= ft
->typestring_offset
;
1900 short reloff
= absoff
- (*tfsoff
+ 2);
1901 int ptr_type
= get_attrv(f
->attrs
, ATTR_POINTERTYPE
);
1902 /* FIXME: We need to store pointer attributes for arrays
1903 so we don't lose pointer_default info. */
1905 ptr_type
= RPC_FC_UP
;
1906 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1907 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
1908 string_of_type(ptr_type
));
1909 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1910 reloff
, reloff
, absoff
);
1914 if (type
->ptrdesc
== *tfsoff
)
1918 current_structure
= save_current_structure
;
1919 return start_offset
;
1922 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1923 unsigned char flags
, size_t offset
,
1924 unsigned int *typeformat_offset
)
1926 size_t start_offset
= *typeformat_offset
;
1927 short reloff
= offset
- (*typeformat_offset
+ 2);
1928 int in_attr
, out_attr
;
1929 in_attr
= is_attr(attrs
, ATTR_IN
);
1930 out_attr
= is_attr(attrs
, ATTR_OUT
);
1931 if (!in_attr
&& !out_attr
) in_attr
= 1;
1933 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1936 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1939 string_of_type(pointer_type
));
1943 fprintf(file
, " [allocated_on_stack]");
1945 fprintf(file
, " [pointer_deref]");
1946 fprintf(file
, " */\n");
1949 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1950 *typeformat_offset
+= 4;
1952 return start_offset
;
1955 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1959 print_file(file
, 2, "NdrFcShort(0x0),\t/* No type */\n");
1961 else if (is_base_type(t
->type
))
1963 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1964 t
->type
, string_of_type(t
->type
));
1966 else if (t
->typestring_offset
)
1968 short reloff
= t
->typestring_offset
- *tfsoff
;
1969 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1970 reloff
, reloff
, t
->typestring_offset
);
1973 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1978 static size_t write_union_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1980 unsigned int align
= 0;
1981 unsigned int start_offset
;
1982 size_t size
= type_memsize(type
, &align
);
1985 type_t
*deftype
= NULL
;
1986 short nodeftype
= 0xffff;
1991 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1993 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
1994 fields
= uv
->type
->fields
;
1997 fields
= type
->fields
;
1999 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2001 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2003 nbranch
+= list_count(cases
);
2005 write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
, TRUE
, tfsoff
);
2008 start_offset
= *tfsoff
;
2009 update_tfsoff(type
, start_offset
, file
);
2010 print_start_tfs_comment(file
, type
, start_offset
);
2011 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
2013 const var_t
*sv
= LIST_ENTRY(list_head(type
->fields
), const var_t
, entry
);
2014 const type_t
*st
= sv
->type
;
2027 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
2028 print_file(file
, 2, "0x%x,\t/* Switch type= %s */\n",
2029 0x40 | st
->type
, string_of_type(st
->type
));
2033 error("union switch type must be an integer, char, or enum\n");
2036 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
2037 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
2040 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2042 type_t
*ft
= f
->type
;
2043 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2044 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
2047 if (cases
== NULL
&& !deflt
)
2048 error("union field %s with neither case nor default attribute\n", f
->name
);
2050 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
2052 /* MIDL doesn't check for duplicate cases, even though that seems
2053 like a reasonable thing to do, it just dumps them to the TFS
2054 like we're going to do here. */
2055 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
2057 write_branch_type(file
, ft
, tfsoff
);
2060 /* MIDL allows multiple default branches, even though that seems
2061 illogical, it just chooses the last one, which is what we will
2072 write_branch_type(file
, deftype
, tfsoff
);
2076 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
2080 return start_offset
;
2083 static size_t write_ip_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2084 unsigned int *typeformat_offset
)
2087 size_t start_offset
= *typeformat_offset
;
2088 expr_t
*iid
= get_attrp(attrs
, ATTR_IIDIS
);
2092 print_file(file
, 2, "0x2f, /* FC_IP */\n");
2093 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
2095 += write_conf_or_var_desc(file
, NULL
, 0, type
, iid
) + 2;
2099 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
2100 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
2103 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
2105 update_tfsoff(type
, start_offset
, file
);
2106 print_start_tfs_comment(file
, type
, start_offset
);
2107 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
2108 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2109 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
2110 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
2111 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
2112 for (i
= 0; i
< 8; ++i
)
2113 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
2116 fprintf(file
, "\n");
2118 *typeformat_offset
+= 18;
2120 return start_offset
;
2123 static size_t write_contexthandle_tfs(FILE *file
, const type_t
*type
,
2125 unsigned int *typeformat_offset
)
2127 size_t start_offset
= *typeformat_offset
;
2128 unsigned char flags
= 0;
2130 if (is_attr(current_iface
->attrs
, ATTR_STRICTCONTEXTHANDLE
))
2131 flags
|= NDR_STRICT_CONTEXT_HANDLE
;
2135 if (is_attr(var
->attrs
, ATTR_IN
))
2138 if (!is_attr(var
->attrs
, ATTR_OUT
))
2139 flags
|= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
;
2141 if (is_attr(var
->attrs
, ATTR_OUT
))
2144 WRITE_FCTYPE(file
, FC_BIND_CONTEXT
, *typeformat_offset
);
2145 print_file(file
, 2, "0x%x,\t/* Context flags: ", flags
);
2146 /* return and can't be null values overlap */
2147 if (((flags
& 0x21) != 0x21) && (flags
& NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
))
2148 print_file(file
, 0, "can't be null, ");
2149 if (flags
& NDR_CONTEXT_HANDLE_SERIALIZE
)
2150 print_file(file
, 0, "serialize, ");
2151 if (flags
& NDR_CONTEXT_HANDLE_NO_SERIALIZE
)
2152 print_file(file
, 0, "no serialize, ");
2153 if (flags
& NDR_STRICT_CONTEXT_HANDLE
)
2154 print_file(file
, 0, "strict, ");
2155 if ((flags
& 0x21) == 0x20)
2156 print_file(file
, 0, "out, ");
2157 if ((flags
& 0x21) == 0x21)
2158 print_file(file
, 0, "return, ");
2160 print_file(file
, 0, "in, ");
2162 print_file(file
, 0, "via ptr, ");
2163 print_file(file
, 0, "*/\n");
2164 print_file(file
, 2, "0, /* FIXME: rundown routine index*/\n");
2165 print_file(file
, 2, "0, /* FIXME: param num */\n");
2166 *typeformat_offset
+= 4;
2168 return start_offset
;
2171 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
2172 type_t
*type
, const var_t
*var
,
2173 unsigned int *typeformat_offset
)
2177 if (is_context_handle(type
))
2178 return write_contexthandle_tfs(file
, type
, var
, typeformat_offset
);
2180 if (is_user_type(type
))
2182 write_user_tfs(file
, type
, typeformat_offset
);
2183 return type
->typestring_offset
;
2186 if (is_string_type(var
->attrs
, type
))
2187 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2193 off
= write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2194 ptr_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2195 /* Top level pointers to conformant arrays may be handled specially
2196 since we can bypass the pointer, but if the array is buried
2197 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2198 always need to write the pointer. */
2199 if (!ptr_type
&& var
->type
!= type
)
2200 /* FIXME: This should use pointer_default, but the information
2201 isn't kept around for arrays. */
2202 ptr_type
= RPC_FC_UP
;
2203 if (ptr_type
&& ptr_type
!= RPC_FC_RP
)
2205 unsigned int absoff
= type
->typestring_offset
;
2206 short reloff
= absoff
- (*typeformat_offset
+ 2);
2207 off
= *typeformat_offset
;
2208 print_file(file
, 0, "/* %d */\n", off
);
2209 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
2210 string_of_type(ptr_type
));
2211 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2212 reloff
, reloff
, absoff
);
2213 *typeformat_offset
+= 4;
2220 /* basic types don't need a type format string */
2221 if (is_base_type(type
->type
))
2227 case RPC_FC_PSTRUCT
:
2228 case RPC_FC_CSTRUCT
:
2229 case RPC_FC_CPSTRUCT
:
2230 case RPC_FC_CVSTRUCT
:
2231 case RPC_FC_BOGUS_STRUCT
:
2232 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
2233 case RPC_FC_ENCAPSULATED_UNION
:
2234 case RPC_FC_NON_ENCAPSULATED_UNION
:
2235 return write_union_tfs(file
, type
, typeformat_offset
);
2237 case RPC_FC_BIND_PRIMITIVE
:
2241 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
2244 else if (last_ptr(type
))
2246 size_t start_offset
= *typeformat_offset
;
2247 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2248 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2249 const type_t
*base
= type
->ref
;
2251 if (base
->type
== RPC_FC_IP
2253 && is_attr(var
->attrs
, ATTR_IIDIS
)))
2255 return write_ip_tfs(file
, var
->attrs
, type
, typeformat_offset
);
2258 /* special case for pointers to base types */
2259 if (is_base_type(base
->type
))
2261 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2262 type
->type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
2263 string_of_type(type
->type
),
2264 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
2265 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
2266 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
2267 *typeformat_offset
+= 4;
2268 return start_offset
;
2272 assert(is_ptr(type
));
2274 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
2276 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
2277 return write_pointer_only_tfs(file
, var
->attrs
, type
->type
,
2278 !last_ptr(type
) ? 0x10 : 0,
2279 offset
, typeformat_offset
);
2282 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2283 const char *name
, int write_ptr
, unsigned int *tfsoff
)
2287 if (is_user_type(type
))
2289 write_user_tfs(file
, type
, tfsoff
);
2291 else if (is_string_type(attrs
, type
))
2293 write_string_tfs(file
, attrs
, type
, name
, tfsoff
);
2295 else if (is_ptr(type
))
2297 type_t
*ref
= type
->ref
;
2299 if (ref
->type
== RPC_FC_IP
2301 && is_attr(attrs
, ATTR_IIDIS
)))
2303 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2307 if (!processed(ref
) && !is_base_type(ref
->type
))
2308 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2311 write_pointer_tfs(file
, type
, tfsoff
);
2316 else if (type
->declarray
&& is_conformant_array(type
))
2317 ; /* conformant arrays and strings are handled specially */
2318 else if (is_array(type
))
2320 write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
2321 if (is_conformant_array(type
))
2324 else if (is_struct(type
->type
))
2326 if (!processed(type
))
2327 write_struct_tfs(file
, type
, name
, tfsoff
);
2329 else if (is_union(type
->type
))
2331 if (!processed(type
))
2332 write_union_tfs(file
, type
, tfsoff
);
2334 else if (!is_base_type(type
->type
))
2335 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2341 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2344 const ifref_t
*iface
;
2345 unsigned int typeformat_offset
= 2;
2347 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2349 if (!pred(iface
->iface
))
2352 if (iface
->iface
->funcs
)
2355 current_iface
= iface
;
2356 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2358 if (is_local(func
->def
->attrs
)) continue;
2360 if (!is_void(get_func_return_type(func
)))
2362 var_t v
= *func
->def
;
2363 v
.type
= get_func_return_type(func
);
2364 update_tfsoff(get_func_return_type(func
),
2365 write_typeformatstring_var(
2366 file
, 2, NULL
, get_func_return_type(func
),
2367 &v
, &typeformat_offset
),
2371 current_func
= func
;
2373 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2376 write_typeformatstring_var(
2377 file
, 2, func
, var
->type
, var
,
2378 &typeformat_offset
),
2384 return typeformat_offset
+ 1;
2388 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2392 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2393 print_file(file
, indent
, "{\n");
2395 print_file(file
, indent
, "0,\n");
2396 print_file(file
, indent
, "{\n");
2398 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2400 set_all_tfswrite(TRUE
);
2401 process_tfs(file
, ifaces
, pred
);
2403 print_file(file
, indent
, "0x0\n");
2405 print_file(file
, indent
, "}\n");
2407 print_file(file
, indent
, "};\n");
2408 print_file(file
, indent
, "\n");
2411 static unsigned int get_required_buffer_size_type(
2412 const type_t
*type
, const char *name
, unsigned int *alignment
)
2415 if (is_user_type(type
))
2418 const type_t
*utype
= get_user_type(type
, &uname
);
2419 return get_required_buffer_size_type(utype
, uname
, alignment
);
2443 case RPC_FC_ERROR_STATUS_T
:
2453 case RPC_FC_BIND_PRIMITIVE
:
2457 case RPC_FC_PSTRUCT
:
2461 if (!type
->fields
) return 0;
2462 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2464 unsigned int alignment
;
2465 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2473 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2474 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2477 case RPC_FC_SMFARRAY
:
2478 case RPC_FC_LGFARRAY
:
2479 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2487 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2489 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2490 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2493 if (!in_attr
&& !out_attr
)
2498 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2499 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2505 if (pass
== PASS_OUT
)
2507 if (out_attr
&& is_ptr(var
->type
))
2509 type_t
*type
= var
->type
;
2511 if (type
->type
== RPC_FC_STRUCT
)
2514 unsigned int size
= 36;
2516 if (!type
->fields
) return size
;
2517 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2520 size
+= get_required_buffer_size_type(
2521 field
->type
, field
->name
, &align
);
2530 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2531 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2533 if (is_ptr(var
->type
))
2535 type_t
*type
= var
->type
;
2537 if (is_base_type(type
->type
))
2541 else if (type
->type
== RPC_FC_STRUCT
)
2543 unsigned int size
= 36;
2546 if (!type
->fields
) return size
;
2547 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2550 size
+= get_required_buffer_size_type(
2551 field
->type
, field
->name
, &align
);
2558 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2562 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2565 unsigned int total_size
= 0, alignment
;
2569 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2571 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2572 total_size
+= alignment
;
2576 if (pass
== PASS_OUT
&& !is_void(get_func_return_type(func
)))
2578 var_t v
= *func
->def
;
2579 v
.type
= get_func_return_type(func
);
2580 total_size
+= get_required_buffer_size(&v
, &alignment
, PASS_RETURN
);
2581 total_size
+= alignment
;
2586 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2587 enum remoting_phase phase
,
2588 const var_t
*var
, unsigned int type_offset
)
2590 const char *function
;
2593 case PHASE_BUFFERSIZE
:
2594 function
= "BufferSize";
2597 function
= "Marshall";
2599 case PHASE_UNMARSHAL
:
2600 function
= "Unmarshall";
2610 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2612 print_file(file
, indent
, "&_StubMsg,\n");
2613 print_file(file
, indent
, "%s%s%s%s,\n",
2614 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2615 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2616 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2618 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2619 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2620 if (phase
== PHASE_UNMARSHAL
)
2621 print_file(file
, indent
, "0);\n");
2625 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2626 enum pass pass
, const var_t
*var
,
2627 const char *varname
)
2629 type_t
*type
= var
->type
;
2631 unsigned int alignment
= 0;
2632 unsigned char rtype
;
2634 /* no work to do for other phases, buffer sizing is done elsewhere */
2635 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2638 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2662 case RPC_FC_ERROR_STATUS_T
:
2674 case RPC_FC_BIND_PRIMITIVE
:
2675 /* no marshalling needed */
2679 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2683 if (phase
== PHASE_MARSHAL
)
2684 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2685 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2686 alignment
- 1, alignment
- 1);
2688 if (phase
== PHASE_MARSHAL
)
2690 print_file(file
, indent
, "*(");
2691 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2693 fprintf(file
, " *)_StubMsg.Buffer = *");
2695 fprintf(file
, " *)_StubMsg.Buffer = ");
2696 fprintf(file
, "%s", varname
);
2697 fprintf(file
, ";\n");
2699 else if (phase
== PHASE_UNMARSHAL
)
2701 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2702 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2703 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2704 print_file(file
, indent
, "{\n");
2705 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2706 print_file(file
, indent
, "}\n");
2707 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2708 print_file(file
, indent
, "");
2710 print_file(file
, indent
, "*");
2711 fprintf(file
, "%s", varname
);
2712 if (pass
== PASS_IN
&& is_ptr(type
))
2713 fprintf(file
, " = (");
2715 fprintf(file
, " = *(");
2716 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2717 fprintf(file
, " *)_StubMsg.Buffer;\n");
2720 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2721 write_type_decl(file
, var
->type
, NULL
);
2722 fprintf(file
, ");\n");
2725 /* returns whether the MaxCount, Offset or ActualCount members need to be
2726 * filled in for the specified phase */
2727 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2729 return (phase
!= PHASE_UNMARSHAL
);
2732 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2736 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2742 error("%s: multidimensional conformant"
2743 " arrays not supported at the top level\n",
2750 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2751 enum pass pass
, enum remoting_phase phase
,
2754 int in_attr
, out_attr
, pointer_type
;
2755 const type_t
*type
= var
->type
;
2756 unsigned char rtype
;
2757 size_t start_offset
= type
->typestring_offset
;
2759 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2761 pointer_type
= RPC_FC_RP
;
2763 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2764 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2765 if (!in_attr
&& !out_attr
)
2768 if (phase
!= PHASE_FREE
)
2772 if (!in_attr
) return;
2775 if (!out_attr
) return;
2783 if (is_context_handle(type
))
2785 if (phase
== PHASE_MARSHAL
)
2787 if (pass
== PASS_IN
)
2789 /* if the context_handle attribute appears in the chain of types
2790 * without pointers being followed, then the context handle must
2791 * be direct, otherwise it is a pointer */
2792 int is_ch_ptr
= is_aliaschain_attr(type
, ATTR_CONTEXTHANDLE
) ? FALSE
: TRUE
;
2793 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2794 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2795 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ch_ptr
? "*" : "", var
->name
);
2796 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2800 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2801 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2802 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2803 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2804 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2807 else if (phase
== PHASE_UNMARSHAL
)
2809 if (pass
== PASS_OUT
)
2812 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2813 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2814 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2815 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2816 print_file(file
, indent
+ 1, "_Handle);\n");
2820 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2821 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2822 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2826 else if (is_user_type(var
->type
))
2828 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2830 else if (is_string_type(var
->attrs
, var
->type
))
2832 if (is_array(type
) && !is_conformant_array(type
))
2833 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2836 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2838 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2839 write_expr(file
, type
->size_is
, 1);
2840 fprintf(file
, ";\n");
2843 if (phase
== PHASE_FREE
|| pass
== PASS_RETURN
|| pointer_type
== RPC_FC_UP
)
2844 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2845 start_offset
- (type
->size_is
? 4 : 2));
2847 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2851 else if (is_array(type
))
2853 unsigned char tc
= type
->type
;
2854 const char *array_type
= "FixedArray";
2856 /* We already have the size_is expression since it's at the
2857 top level, but do checks for multidimensional conformant
2858 arrays. When we handle them, we'll need to extend this
2859 function to return a list, and then we'll actually use
2860 the return value. */
2861 get_size_is_expr(type
, var
->name
);
2863 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2865 if (is_size_needed_for_phase(phase
))
2867 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2868 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2869 write_expr(file
, type
->length_is
, 1);
2870 fprintf(file
, ";\n\n");
2872 array_type
= "VaryingArray";
2874 else if (tc
== RPC_FC_CARRAY
)
2876 if (is_size_needed_for_phase(phase
))
2878 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2879 write_expr(file
, type
->size_is
, 1);
2880 fprintf(file
, ";\n\n");
2882 array_type
= "ConformantArray";
2884 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2886 if (is_size_needed_for_phase(phase
))
2890 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2891 write_expr(file
, type
->size_is
, 1);
2892 fprintf(file
, ";\n");
2894 if (type
->length_is
)
2896 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2897 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2898 write_expr(file
, type
->length_is
, 1);
2899 fprintf(file
, ";\n\n");
2902 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2904 : "ConformantVaryingArray");
2907 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2908 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2909 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2911 /* these are all unmarshalled by allocating memory */
2912 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2913 type
->type
== RPC_FC_CVARRAY
||
2914 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2915 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2917 print_file(file
, indent
, "if (%s)\n", var
->name
);
2919 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2923 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2925 if (phase
!= PHASE_FREE
)
2926 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2928 else if (!is_ptr(var
->type
))
2933 case RPC_FC_PSTRUCT
:
2934 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2936 case RPC_FC_CSTRUCT
:
2937 case RPC_FC_CPSTRUCT
:
2938 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2940 case RPC_FC_CVSTRUCT
:
2941 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2943 case RPC_FC_BOGUS_STRUCT
:
2944 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2947 if (is_base_type( var
->type
->ref
->type
))
2949 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2951 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2953 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2954 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2959 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2961 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2962 write_expr( file
, iid
, 1 );
2963 fprintf( file
, ";\n\n" );
2965 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2969 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2974 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2976 if (phase
!= PHASE_FREE
)
2977 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2979 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2981 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2982 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2987 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2989 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2991 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2992 write_expr( file
, iid
, 1 );
2993 fprintf( file
, ";\n\n" );
2997 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2998 write_expr(file
, sx
, 1);
2999 fprintf(file
, ";\n\n");
3001 if (var
->type
->ref
->type
== RPC_FC_IP
)
3002 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
3004 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
3007 fprintf(file
, "\n");
3010 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
3011 enum pass pass
, enum remoting_phase phase
)
3013 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
3015 unsigned int size
= get_function_buffer_size( func
, pass
);
3016 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
3019 if (pass
== PASS_RETURN
)
3023 var
.type
= get_func_return_type(func
);
3024 var
.name
= xstrdup( "_RetVal" );
3025 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
3033 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3034 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
3039 size_t get_size_procformatstring_type(const char *name
, const type_t
*type
, const attr_list_t
*attrs
)
3041 return write_procformatstring_type(NULL
, 0, name
, type
, attrs
, FALSE
);
3045 size_t get_size_procformatstring_func(const func_t
*func
)
3050 /* argument list size */
3052 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3053 size
+= get_size_procformatstring_type(var
->name
, var
->type
, var
->attrs
);
3055 /* return value size */
3056 if (is_void(get_func_return_type(func
)))
3057 size
+= 2; /* FC_END and FC_PAD */
3059 size
+= get_size_procformatstring_type("return value", get_func_return_type(func
), NULL
);
3064 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3066 const ifref_t
*iface
;
3070 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
3072 if (!pred(iface
->iface
))
3075 if (iface
->iface
->funcs
)
3076 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
3077 if (!is_local(func
->def
->attrs
))
3078 size
+= get_size_procformatstring_func( func
);
3083 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3085 set_all_tfswrite(FALSE
);
3086 return process_tfs(NULL
, ifaces
, pred
);
3089 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3090 const var_list_t
*fields
, const char *structvar
)
3096 fprintf(h
, "%lu", e
->u
.lval
);
3099 fprintf(h
, "0x%lx", e
->u
.lval
);
3102 fprintf(h
, "%#.15g", e
->u
.dval
);
3104 case EXPR_TRUEFALSE
:
3106 fprintf(h
, "FALSE");
3110 case EXPR_IDENTIFIER
:
3113 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3114 if (!strcmp(e
->u
.sval
, field
->name
))
3116 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3120 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3125 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3129 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3133 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3137 write_type_decl(h
, e
->u
.tref
, NULL
);
3139 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3142 fprintf(h
, "sizeof(");
3143 write_type_decl(h
, e
->u
.tref
, NULL
);
3154 if (brackets
) fprintf(h
, "(");
3155 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3157 case EXPR_SHL
: fprintf(h
, " << "); break;
3158 case EXPR_SHR
: fprintf(h
, " >> "); break;
3159 case EXPR_MUL
: fprintf(h
, " * "); break;
3160 case EXPR_DIV
: fprintf(h
, " / "); break;
3161 case EXPR_ADD
: fprintf(h
, " + "); break;
3162 case EXPR_SUB
: fprintf(h
, " - "); break;
3163 case EXPR_AND
: fprintf(h
, " & "); break;
3164 case EXPR_OR
: fprintf(h
, " | "); break;
3167 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3168 if (brackets
) fprintf(h
, ")");
3171 if (brackets
) fprintf(h
, "(");
3172 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3174 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3176 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3177 if (brackets
) fprintf(h
, ")");
3179 case EXPR_ADDRESSOF
:
3181 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3187 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3189 int in_attr
, out_attr
;
3193 /* declare return value '_RetVal' */
3194 if (!is_void(get_func_return_type(func
)))
3196 print_file(file
, indent
, "");
3197 write_type_decl_left(file
, get_func_return_type(func
));
3198 fprintf(file
, " _RetVal;\n");
3204 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3206 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3208 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3209 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3210 if (!out_attr
&& !in_attr
)
3213 if (is_context_handle(var
->type
))
3214 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3217 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3219 print_file(file
, indent
, "");
3220 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3222 fprintf(file
, ";\n");
3225 print_file(file
, indent
, "");
3226 write_type_decl_left(file
, var
->type
);
3228 if (var
->type
->declarray
) {
3229 fprintf(file
, "( *");
3230 write_name(file
, var
);
3231 fprintf(file
, " )");
3233 write_name(file
, var
);
3234 write_type_right(file
, var
->type
, FALSE
);
3235 fprintf(file
, ";\n");
3237 if (decl_indirect(var
->type
))
3238 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3239 var
->name
, var
->name
);
3245 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3247 int in_attr
, out_attr
;
3254 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3256 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3257 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3258 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3259 if (!out_attr
&& !in_attr
)
3264 print_file(file
, indent
, "");
3265 write_name(file
, var
);
3267 if (is_context_handle(var
->type
))
3269 fprintf(file
, " = NdrContextHandleInitialize(\n");
3270 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3271 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3272 var
->type
->typestring_offset
);
3274 else if (var
->type
->size_is
)
3276 unsigned int size
, align
= 0;
3277 type_t
*type
= var
->type
;
3279 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3280 for ( ; type
->size_is
; type
= type
->ref
)
3282 write_expr(file
, type
->size_is
, TRUE
);
3283 fprintf(file
, " * ");
3285 size
= type_memsize(type
, &align
);
3286 fprintf(file
, "%u);\n", size
);
3288 else if (!is_string
)
3290 fprintf(file
, " = &_W%u;\n", i
);
3291 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3292 print_file(file
, indent
, "_W%u = 0;\n", i
);
3300 fprintf(file
, "\n");
3304 int write_expr_eval_routines(FILE *file
, const char *iface
)
3306 static const char *var_name
= "pS";
3308 struct expr_eval_routine
*eval
;
3309 unsigned short callback_offset
= 0;
3311 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3313 const char *name
= eval
->structure
->name
;
3314 const var_list_t
*fields
= eval
->structure
->fields
;
3317 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3318 iface
, name
, callback_offset
);
3319 print_file(file
, 0, "{\n");
3320 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3321 name
, var_name
, name
, eval
->baseoff
);
3322 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3323 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3324 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3325 fprintf(file
, ";\n");
3326 print_file(file
, 0, "}\n\n");
3332 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3334 struct expr_eval_routine
*eval
;
3335 struct expr_eval_routine
*cursor
;
3336 unsigned short callback_offset
= 0;
3338 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3339 fprintf(file
, "{\n");
3341 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3343 const char *name
= eval
->structure
->name
;
3344 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3346 list_remove(&eval
->entry
);
3350 fprintf(file
, "};\n\n");
3353 void write_user_quad_list(FILE *file
)
3357 if (list_empty(&user_type_list
))
3360 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3361 fprintf(file
, "{\n");
3362 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3364 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3365 print_file(file
, 1, "{\n");
3366 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3367 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3368 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3369 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3370 print_file(file
, 1, "}%s\n", sep
);
3372 fprintf(file
, "};\n\n");
3375 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3377 const struct str_list_entry_t
*endpoint
;
3380 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3381 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3382 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3384 print_file( f
, 1, "{ (const unsigned char *)\"" );
3385 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3387 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3390 if (!*p
) goto error
;
3391 if (p
[1] != '[') goto error
;
3393 fprintf( f
, "\", (const unsigned char *)\"" );
3394 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3396 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3399 if (*p
!= ']') goto error
;
3400 fprintf( f
, "\" },\n" );
3402 print_file( f
, 0, "};\n\n" );
3406 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);