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_or_args
) LIST_FOR_EACH_ENTRY( field
, type
->fields_or_args
, 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_or_args
), const var_t
, entry
);
184 fields
= uv
->type
->fields_or_args
;
187 fields
= type
->fields_or_args
;
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_or_args
) LIST_FOR_EACH_ENTRY( field
, type
->fields_or_args
, 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_or_args
), const var_t
, entry
);
224 fields
= uv
->type
->fields_or_args
;
227 fields
= type
->fields_or_args
;
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
);
362 ret
= compare_expr(a
->ref
, b
->ref
);
365 return compare_expr(a
->u
.ext
, b
->u
.ext
);
367 ret
= compare_type(a
->u
.tref
, b
->u
.tref
);
375 return compare_expr(a
->ref
, b
->ref
);
377 return compare_type(a
->u
.tref
, b
->u
.tref
);
384 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
387 fprintf(file, "/* %2u */\n", typestring_offset); \
388 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
392 static void print_file(FILE *file
, int indent
, const char *format
, ...)
395 va_start(va
, format
);
396 print(file
, indent
, format
, va
);
400 void print(FILE *file
, int indent
, const char *format
, va_list va
)
404 if (format
[0] != '\n')
407 vfprintf(file
, format
, va
);
412 static void write_var_init(FILE *file
, int indent
, const type_t
*t
, const char *n
)
414 if (decl_indirect(t
))
415 print_file(file
, indent
, "MIDL_memset(&%s, 0, sizeof(%s));\n", n
, n
);
416 else if (is_ptr(t
) || is_array(t
))
417 print_file(file
, indent
, "%s = 0;\n", n
);
420 void write_parameters_init(FILE *file
, int indent
, const func_t
*func
)
424 if (!is_void(get_func_return_type(func
)))
425 write_var_init(file
, indent
, get_func_return_type(func
), "_RetVal");
430 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
431 write_var_init(file
, indent
, var
->type
, var
->name
);
436 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
438 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
439 print_file(f
, indent
, "{\n");
440 print_file(f
, indent
+ 1, "short Pad;\n");
441 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
442 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
443 print_file(f
, indent
, "\n");
446 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, type_pred_t pred
)
448 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
449 get_size_typeformatstring(ifaces
, pred
));
451 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
452 get_size_procformatstring(ifaces
, pred
));
455 write_formatdesc(f
, indent
, "TYPE");
456 write_formatdesc(f
, indent
, "PROC");
458 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
459 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
460 print_file(f
, indent
, "\n");
463 static inline int is_base_type(unsigned char type
)
482 case RPC_FC_ERROR_STATUS_T
:
483 case RPC_FC_BIND_PRIMITIVE
:
491 int decl_indirect(const type_t
*t
)
493 return is_user_type(t
)
494 || (!is_base_type(t
->type
)
499 static size_t write_procformatstring_type(FILE *file
, int indent
,
502 const attr_list_t
*attrs
,
507 int is_in
= is_attr(attrs
, ATTR_IN
);
508 int is_out
= is_attr(attrs
, ATTR_OUT
);
510 if (!is_in
&& !is_out
) is_in
= TRUE
;
512 if (!type
->declarray
&& is_base_type(type
->type
))
515 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
517 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
519 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
521 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
522 size
= 2; /* includes param type prefix */
524 else if (is_base_type(type
->type
))
526 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
527 size
= 2; /* includes param type prefix */
531 error("Unknown/unsupported type: %s (0x%02x)\n", name
, type
->type
);
538 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
539 else if (is_in
&& is_out
)
540 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
542 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
544 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
546 print_file(file
, indent
, "0x01,\n");
547 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
548 size
= 4; /* includes param type prefix */
553 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
555 const ifref_t
*iface
;
559 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
560 print_file(file
, indent
, "{\n");
562 print_file(file
, indent
, "0,\n");
563 print_file(file
, indent
, "{\n");
566 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
568 if (!pred(iface
->iface
))
571 if (iface
->iface
->funcs
)
574 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
576 if (is_local(func
->def
->attrs
)) continue;
577 /* emit argument data */
580 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
581 write_procformatstring_type(file
, indent
, var
->name
, var
->type
, var
->attrs
, FALSE
);
584 /* emit return value data */
585 if (is_void(get_func_return_type(func
)))
587 print_file(file
, indent
, "0x5b, /* FC_END */\n");
588 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
591 write_procformatstring_type(file
, indent
, "return value", get_func_return_type(func
), NULL
, TRUE
);
596 print_file(file
, indent
, "0x0\n");
598 print_file(file
, indent
, "}\n");
600 print_file(file
, indent
, "};\n");
601 print_file(file
, indent
, "\n");
604 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
606 if (is_base_type(type
->type
))
608 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
609 *typestring_offset
+= 1;
616 /* write conformance / variance descriptor */
617 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
618 unsigned int baseoff
, const type_t
*type
,
621 unsigned char operator_type
= 0;
622 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
623 const char *conftype_string
= "";
624 const char *operator_string
= "no operators";
625 const expr_t
*subexpr
;
629 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
635 /* Top-level conformance calculations are done inline. */
636 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
637 RPC_FC_TOP_LEVEL_CONFORMANCE
);
638 print_file (file
, 2, "0x0,\n");
639 print_file (file
, 2, "NdrFcShort(0x0),\n");
645 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
646 error("write_conf_or_var_desc: constant value %ld is greater than "
647 "the maximum constant size of %d\n", expr
->cval
,
648 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
650 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
651 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
652 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
653 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
658 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
660 conftype
= RPC_FC_POINTER_CONFORMANCE
;
661 conftype_string
= "field pointer, ";
665 switch (subexpr
->type
)
668 subexpr
= subexpr
->ref
;
669 operator_type
= RPC_FC_DEREFERENCE
;
670 operator_string
= "FC_DEREFERENCE";
673 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
675 subexpr
= subexpr
->ref
;
676 operator_type
= RPC_FC_DIV_2
;
677 operator_string
= "FC_DIV_2";
681 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
683 subexpr
= subexpr
->ref
;
684 operator_type
= RPC_FC_MULT_2
;
685 operator_string
= "FC_MULT_2";
689 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
691 subexpr
= subexpr
->ref
;
692 operator_type
= RPC_FC_SUB_1
;
693 operator_string
= "FC_SUB_1";
697 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
699 subexpr
= subexpr
->ref
;
700 operator_type
= RPC_FC_ADD_1
;
701 operator_string
= "FC_ADD_1";
708 if (subexpr
->type
== EXPR_IDENTIFIER
)
710 const type_t
*correlation_variable
= NULL
;
711 unsigned char correlation_variable_type
;
712 unsigned char param_type
= 0;
716 if (structure
->fields_or_args
) LIST_FOR_EACH_ENTRY( var
, structure
->fields_or_args
, const var_t
, entry
)
718 unsigned int align
= 0;
719 /* FIXME: take alignment into account */
720 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
722 correlation_variable
= var
->type
;
725 offset
+= type_memsize(var
->type
, &align
);
727 if (!correlation_variable
)
728 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
732 correlation_variable_type
= correlation_variable
->type
;
734 switch (correlation_variable_type
)
738 param_type
= RPC_FC_SMALL
;
742 param_type
= RPC_FC_USMALL
;
747 param_type
= RPC_FC_SHORT
;
750 param_type
= RPC_FC_USHORT
;
754 param_type
= RPC_FC_LONG
;
757 param_type
= RPC_FC_ULONG
;
763 if (sizeof(void *) == 4) /* FIXME */
764 param_type
= RPC_FC_LONG
;
766 param_type
= RPC_FC_HYPER
;
769 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
770 correlation_variable_type
);
773 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
774 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
775 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
776 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
781 unsigned int callback_offset
= 0;
782 struct expr_eval_routine
*eval
;
785 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
787 if (!strcmp (eval
->structure
->name
, structure
->name
)
788 && !compare_expr (eval
->expr
, expr
))
798 eval
= xmalloc (sizeof(*eval
));
799 eval
->structure
= structure
;
800 eval
->baseoff
= baseoff
;
802 list_add_tail (&expr_eval_routines
, &eval
->entry
);
805 if (callback_offset
> USHRT_MAX
)
806 error("Maximum number of callback routines reached\n");
808 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
809 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
810 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
815 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
817 int have_align
= FALSE
;
821 if (!fields
) return 0;
822 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
824 unsigned int falign
= 0;
825 size_t fsize
= type_memsize(v
->type
, &falign
);
831 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
835 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
839 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
841 size_t size
, maxs
= 0;
842 unsigned int align
= *pmaxa
;
845 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
847 /* we could have an empty default field with NULL type */
850 size
= type_memsize(v
->type
, &align
);
851 if (maxs
< size
) maxs
= size
;
852 if (*pmaxa
< align
) *pmaxa
= align
;
859 int get_padding(const var_list_t
*fields
)
861 unsigned short offset
= 0;
868 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
870 type_t
*ft
= f
->type
;
871 unsigned int align
= 0;
872 size_t size
= type_memsize(ft
, &align
);
875 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
879 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
882 size_t type_memsize(const type_t
*t
, unsigned int *align
)
886 if (t
->declarray
&& is_conformant_array(t
))
888 type_memsize(t
->ref
, align
);
891 else if (is_ptr(t
) || is_conformant_array(t
))
893 size
= sizeof(void *);
894 if (size
> *align
) *align
= size
;
896 else switch (t
->type
)
903 if (size
> *align
) *align
= size
;
910 if (size
> *align
) *align
= size
;
914 case RPC_FC_ERROR_STATUS_T
:
918 if (size
> *align
) *align
= size
;
923 if (size
> *align
) *align
= size
;
926 case RPC_FC_CVSTRUCT
:
927 case RPC_FC_CPSTRUCT
:
930 case RPC_FC_BOGUS_STRUCT
:
931 size
= fields_memsize(t
->fields_or_args
, align
);
933 case RPC_FC_ENCAPSULATED_UNION
:
934 case RPC_FC_NON_ENCAPSULATED_UNION
:
935 size
= union_memsize(t
->fields_or_args
, align
);
937 case RPC_FC_SMFARRAY
:
938 case RPC_FC_LGFARRAY
:
939 case RPC_FC_SMVARRAY
:
940 case RPC_FC_LGVARRAY
:
941 case RPC_FC_BOGUS_ARRAY
:
942 size
= t
->dim
* type_memsize(t
->ref
, align
);
945 error("type_memsize: Unknown type %d\n", t
->type
);
952 int is_full_pointer_function(const func_t
*func
)
955 if (type_has_full_pointer(get_func_return_type(func
)))
959 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
960 if (type_has_full_pointer( var
->type
))
965 void write_full_pointer_init(FILE *file
, int indent
, const func_t
*func
, int is_server
)
967 print_file(file
, indent
, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
968 is_server
? "XLAT_SERVER" : "XLAT_CLIENT");
972 void write_full_pointer_free(FILE *file
, int indent
, const func_t
*func
)
974 print_file(file
, indent
, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
978 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
980 short absoff
= type
->ref
->typestring_offset
;
981 short reloff
= absoff
- (offset
+ 2);
982 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
984 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
985 type
->type
, ptr_attr
, string_of_type(type
->type
));
986 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
987 reloff
, reloff
, absoff
);
991 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
993 unsigned char fc
= type
->ref
->type
;
994 /* for historical reasons, write_simple_pointer also handled string types,
995 * but no longer does. catch bad uses of the function with this check */
996 if (is_string_type(type
->attrs
, type
))
997 error("write_simple_pointer: can't handle type %s which is a string type\n", type
->name
);
998 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
999 type
->type
, string_of_type(type
->type
));
1000 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
1001 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1005 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
1007 print_file(file
, 0, "/* %u (", tfsoff
);
1008 write_type_decl(file
, t
, NULL
);
1009 print_file(file
, 0, ") */\n");
1012 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
1014 unsigned int offset
= *typestring_offset
;
1016 print_start_tfs_comment(file
, type
, offset
);
1017 update_tfsoff(type
, offset
, file
);
1019 if (type
->ref
->typestring_offset
)
1020 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
1021 else if (is_base_type(type
->ref
->type
))
1022 *typestring_offset
+= write_simple_pointer(file
, type
);
1027 static int processed(const type_t
*type
)
1029 return type
->typestring_offset
&& !type
->tfswrite
;
1032 static int user_type_has_variable_size(const type_t
*t
)
1039 case RPC_FC_PSTRUCT
:
1040 case RPC_FC_CSTRUCT
:
1041 case RPC_FC_CPSTRUCT
:
1042 case RPC_FC_CVSTRUCT
:
1045 /* Note: Since this only applies to user types, we can't have a conformant
1046 array here, and strings should get filed under pointer in this case. */
1050 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1052 unsigned int start
, absoff
, flags
;
1053 unsigned int align
= 0, ualign
= 0;
1055 type_t
*utype
= get_user_type(type
, &name
);
1056 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
1057 size_t size
= type_memsize(type
, &align
);
1058 unsigned short funoff
= user_type_offset(name
);
1063 if (is_base_type(utype
->type
))
1066 print_start_tfs_comment(file
, utype
, absoff
);
1067 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
1068 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1073 if (!processed(utype
))
1074 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
1075 absoff
= utype
->typestring_offset
;
1078 if (utype
->type
== RPC_FC_RP
)
1080 else if (utype
->type
== RPC_FC_UP
)
1086 update_tfsoff(type
, start
, file
);
1087 print_start_tfs_comment(file
, type
, start
);
1088 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
1089 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1090 flags
| (align
- 1), align
- 1, flags
);
1091 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
1092 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
1093 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
1095 reloff
= absoff
- *tfsoff
;
1096 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
1100 static void write_member_type(FILE *file
, const type_t
*cont
,
1101 const attr_list_t
*attrs
, const type_t
*type
,
1102 unsigned int *corroff
, unsigned int *tfsoff
)
1104 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1109 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1116 absoff
= type
->typestring_offset
;
1118 reloff
= absoff
- (*tfsoff
+ 2);
1120 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1121 /* FIXME: actually compute necessary padding */
1122 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1123 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1124 reloff
, reloff
, absoff
);
1127 else if (is_ptr(type
) || is_conformant_array(type
))
1129 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1132 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1135 else if (!write_base_type(file
, type
, tfsoff
))
1136 error("Unsupported member type 0x%x\n", type
->type
);
1139 static void write_end(FILE *file
, unsigned int *tfsoff
)
1141 if (*tfsoff
% 2 == 0)
1143 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1146 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1150 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1152 unsigned int offset
= 0;
1153 var_list_t
*fs
= type
->fields_or_args
;
1156 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1158 unsigned int align
= 0;
1159 type_t
*ft
= f
->type
;
1160 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1162 unsigned int absoff
= ft
->typestring_offset
;
1163 short reloff
= absoff
- (*tfsoff
+ 6);
1164 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1165 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1166 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1167 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1168 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1169 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1170 reloff
, reloff
, absoff
);
1174 /* FIXME: take alignment into account */
1175 offset
+= type_memsize(ft
, &align
);
1179 static int write_no_repeat_pointer_descriptions(
1180 FILE *file
, type_t
*type
,
1181 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1182 unsigned int *typestring_offset
)
1187 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1189 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1190 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1192 /* pointer instance */
1193 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1194 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1195 *typestring_offset
+= 6;
1199 if (is_string_type(type
->attrs
, type
))
1200 write_string_tfs(file
, NULL
, type
, NULL
, typestring_offset
);
1202 write_pointer_tfs(file
, type
, typestring_offset
);
1206 unsigned absoff
= type
->typestring_offset
;
1207 short reloff
= absoff
- (*typestring_offset
+ 2);
1208 /* FIXME: get pointer attributes from field */
1209 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1210 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1211 reloff
, reloff
, absoff
);
1212 *typestring_offset
+= 4;
1216 *offset_in_memory
+= type_memsize(type
, &align
);
1217 /* FIXME: is there a case where these two are different? */
1219 *offset_in_buffer
+= type_memsize(type
, &align
);
1224 if (is_non_complex_struct(type
))
1227 LIST_FOR_EACH_ENTRY( v
, type
->fields_or_args
, const var_t
, entry
)
1228 written
+= write_no_repeat_pointer_descriptions(
1230 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1235 *offset_in_memory
+= type_memsize(type
, &align
);
1236 /* FIXME: is there a case where these two are different? */
1238 *offset_in_buffer
+= type_memsize(type
, &align
);
1244 static int write_pointer_description_offsets(
1245 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1246 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1247 unsigned int *typestring_offset
)
1252 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1254 if (offset_in_memory
&& offset_in_buffer
)
1256 /* pointer instance */
1257 /* FIXME: sometimes from end of structure, sometimes from beginning */
1258 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1259 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1262 *offset_in_memory
+= type_memsize(type
, &align
);
1263 /* FIXME: is there a case where these two are different? */
1265 *offset_in_buffer
+= type_memsize(type
, &align
);
1267 *typestring_offset
+= 4;
1269 if (is_string_type(attrs
, type
))
1270 write_string_tfs(file
, NULL
, type
, NULL
, typestring_offset
);
1271 else if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1272 write_pointer_tfs(file
, type
, typestring_offset
);
1274 error("write_pointer_description_offsets: type format string unknown\n");
1281 return write_pointer_description_offsets(
1282 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1285 else if (is_non_complex_struct(type
))
1287 /* otherwise search for interesting fields to parse */
1289 LIST_FOR_EACH_ENTRY( v
, type
->fields_or_args
, const var_t
, entry
)
1291 written
+= write_pointer_description_offsets(
1292 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1299 if (offset_in_memory
)
1300 *offset_in_memory
+= type_memsize(type
, &align
);
1301 /* FIXME: is there a case where these two are different? */
1303 if (offset_in_buffer
)
1304 *offset_in_buffer
+= type_memsize(type
, &align
);
1310 /* Note: if file is NULL return value is number of pointers to write, else
1311 * it is the number of type format characters written */
1312 static int write_fixed_array_pointer_descriptions(
1313 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1314 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1315 unsigned int *typestring_offset
)
1318 int pointer_count
= 0;
1320 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1322 unsigned int temp
= 0;
1323 /* unfortunately, this needs to be done in two passes to avoid
1324 * writing out redundant FC_FIXED_REPEAT descriptions */
1325 pointer_count
= write_pointer_description_offsets(
1326 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1327 if (pointer_count
> 0)
1329 unsigned int increment_size
;
1330 size_t offset_of_array_pointer_mem
= 0;
1331 size_t offset_of_array_pointer_buf
= 0;
1334 increment_size
= type_memsize(type
->ref
, &align
);
1336 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1337 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1338 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1339 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1340 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1341 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1342 *typestring_offset
+= 10;
1344 pointer_count
= write_pointer_description_offsets(
1345 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1346 &offset_of_array_pointer_buf
, typestring_offset
);
1349 else if (is_struct(type
->type
))
1352 LIST_FOR_EACH_ENTRY( v
, type
->fields_or_args
, const var_t
, entry
)
1354 pointer_count
+= write_fixed_array_pointer_descriptions(
1355 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1362 if (offset_in_memory
)
1363 *offset_in_memory
+= type_memsize(type
, &align
);
1364 /* FIXME: is there a case where these two are different? */
1366 if (offset_in_buffer
)
1367 *offset_in_buffer
+= type_memsize(type
, &align
);
1370 return pointer_count
;
1373 /* Note: if file is NULL return value is number of pointers to write, else
1374 * it is the number of type format characters written */
1375 static int write_conformant_array_pointer_descriptions(
1376 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1377 size_t offset_in_memory
, unsigned int *typestring_offset
)
1380 int pointer_count
= 0;
1382 if (is_conformant_array(type
) && !type
->length_is
)
1384 unsigned int temp
= 0;
1385 /* unfortunately, this needs to be done in two passes to avoid
1386 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1387 pointer_count
= write_pointer_description_offsets(
1388 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1389 if (pointer_count
> 0)
1391 unsigned int increment_size
;
1392 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1393 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1396 increment_size
= type_memsize(type
->ref
, &align
);
1398 if (increment_size
> USHRT_MAX
)
1399 error("array size of %u bytes is too large\n", increment_size
);
1401 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1402 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1403 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1404 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1405 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1406 *typestring_offset
+= 8;
1408 pointer_count
= write_pointer_description_offsets(
1409 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1410 &offset_of_array_pointer_buf
, typestring_offset
);
1414 return pointer_count
;
1417 /* Note: if file is NULL return value is number of pointers to write, else
1418 * it is the number of type format characters written */
1419 static int write_varying_array_pointer_descriptions(
1420 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1421 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1422 unsigned int *typestring_offset
)
1425 int pointer_count
= 0;
1427 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1429 if (is_array(type
) && type
->length_is
)
1431 unsigned int temp
= 0;
1432 /* unfortunately, this needs to be done in two passes to avoid
1433 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1434 pointer_count
= write_pointer_description_offsets(
1435 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1436 if (pointer_count
> 0)
1438 unsigned int increment_size
;
1439 size_t offset_of_array_pointer_mem
= 0;
1440 size_t offset_of_array_pointer_buf
= 0;
1443 increment_size
= type_memsize(type
->ref
, &align
);
1445 if (increment_size
> USHRT_MAX
)
1446 error("array size of %u bytes is too large\n", increment_size
);
1448 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1449 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1450 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1451 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1452 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1453 *typestring_offset
+= 8;
1455 pointer_count
= write_pointer_description_offsets(
1456 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1457 &offset_of_array_pointer_buf
, typestring_offset
);
1460 else if (is_struct(type
->type
))
1463 LIST_FOR_EACH_ENTRY( v
, type
->fields_or_args
, const var_t
, entry
)
1465 pointer_count
+= write_varying_array_pointer_descriptions(
1466 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1473 if (offset_in_memory
)
1474 *offset_in_memory
+= type_memsize(type
, &align
);
1475 /* FIXME: is there a case where these two are different? */
1477 if (offset_in_buffer
)
1478 *offset_in_buffer
+= type_memsize(type
, &align
);
1481 return pointer_count
;
1484 static void write_pointer_description(FILE *file
, type_t
*type
,
1485 unsigned int *typestring_offset
)
1487 size_t offset_in_buffer
;
1488 size_t offset_in_memory
;
1490 /* pass 1: search for single instance of a pointer (i.e. don't descend
1492 if (!is_array(type
))
1494 offset_in_memory
= 0;
1495 offset_in_buffer
= 0;
1496 write_no_repeat_pointer_descriptions(
1498 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1501 /* pass 2: search for pointers in fixed arrays */
1502 offset_in_memory
= 0;
1503 offset_in_buffer
= 0;
1504 write_fixed_array_pointer_descriptions(
1506 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1508 /* pass 3: search for pointers in conformant only arrays (but don't descend
1509 * into conformant varying or varying arrays) */
1510 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1511 write_conformant_array_pointer_descriptions(
1512 file
, NULL
, type
, 0, typestring_offset
);
1513 else if (type
->type
== RPC_FC_CPSTRUCT
)
1515 unsigned int align
= 0;
1516 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1517 write_conformant_array_pointer_descriptions(
1519 type_memsize(type
, &align
),
1523 /* pass 4: search for pointers in varying arrays */
1524 offset_in_memory
= 0;
1525 offset_in_buffer
= 0;
1526 write_varying_array_pointer_descriptions(
1528 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1531 int is_declptr(const type_t
*t
)
1533 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1536 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1538 const char *name
, unsigned int *typestring_offset
)
1540 size_t start_offset
;
1541 unsigned char rtype
;
1543 if (is_declptr(type
))
1545 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1546 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1548 pointer_type
= RPC_FC_RP
;
1549 print_start_tfs_comment(file
, type
, *typestring_offset
);
1550 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1551 pointer_type
, flag
, string_of_type(pointer_type
),
1552 flag
? " [simple_pointer]" : "");
1553 *typestring_offset
+= 2;
1556 print_file(file
, 2, "NdrFcShort(0x2),\n");
1557 *typestring_offset
+= 2;
1561 start_offset
= *typestring_offset
;
1562 update_tfsoff(type
, start_offset
, file
);
1564 rtype
= type
->ref
->type
;
1566 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1568 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1569 return start_offset
;
1572 if (type
->declarray
&& !is_conformant_array(type
))
1574 /* FIXME: multi-dimensional array */
1575 if (0xffffuL
< type
->dim
)
1576 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1577 name
, 0xffffu
, type
->dim
- 0xffffu
);
1579 if (rtype
== RPC_FC_CHAR
)
1580 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1582 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1583 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1584 *typestring_offset
+= 2;
1586 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1587 *typestring_offset
+= 2;
1589 return start_offset
;
1591 else if (type
->size_is
)
1593 unsigned int align
= 0;
1595 if (rtype
== RPC_FC_CHAR
)
1596 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1598 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1599 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1600 *typestring_offset
+= 2;
1602 *typestring_offset
+= write_conf_or_var_desc(
1603 file
, current_structure
,
1604 (type
->declarray
&& current_structure
1605 ? type_memsize(current_structure
, &align
)
1607 type
, type
->size_is
);
1609 return start_offset
;
1613 if (rtype
== RPC_FC_WCHAR
)
1614 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1616 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1617 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1618 *typestring_offset
+= 2;
1620 return start_offset
;
1624 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1625 const char *name
, unsigned int *typestring_offset
)
1627 const expr_t
*length_is
= type
->length_is
;
1628 const expr_t
*size_is
= type
->size_is
;
1629 unsigned int align
= 0;
1631 size_t start_offset
;
1633 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1634 unsigned int baseoff
1635 = type
->declarray
&& current_structure
1636 ? type_memsize(current_structure
, &align
)
1640 pointer_type
= RPC_FC_RP
;
1642 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1645 has_pointer
= type_has_pointers(type
->ref
);
1648 size
= type_memsize((is_conformant_array(type
) ? type
->ref
: type
), &align
);
1650 start_offset
= *typestring_offset
;
1651 update_tfsoff(type
, start_offset
, file
);
1652 print_start_tfs_comment(file
, type
, start_offset
);
1653 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1654 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1655 *typestring_offset
+= 2;
1658 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1660 unsigned char tc
= type
->type
;
1662 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1664 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1665 *typestring_offset
+= 4;
1669 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1670 *typestring_offset
+= 2;
1673 if (is_conformant_array(type
))
1675 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1678 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1680 unsigned int elalign
= 0;
1681 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1683 if (type
->type
== RPC_FC_LGVARRAY
)
1685 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1686 *typestring_offset
+= 4;
1690 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1691 *typestring_offset
+= 2;
1694 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1695 *typestring_offset
+= 2;
1700 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1703 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1705 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1706 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1707 *typestring_offset
+= 2;
1708 write_pointer_description(file
, type
, typestring_offset
);
1709 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1710 *typestring_offset
+= 1;
1713 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1714 write_end(file
, typestring_offset
);
1718 unsigned int dim
= size_is
? 0 : type
->dim
;
1719 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1720 *typestring_offset
+= 2;
1722 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1725 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1727 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1728 write_end(file
, typestring_offset
);
1731 return start_offset
;
1734 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1736 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields_or_args
), const var_t
, entry
);
1737 const type_t
*ft
= last_field
->type
;
1739 if (ft
->declarray
&& is_conformant_array(ft
))
1742 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1743 return find_array_or_string_in_struct(last_field
->type
);
1748 static void write_struct_members(FILE *file
, const type_t
*type
,
1749 unsigned int *corroff
, unsigned int *typestring_offset
)
1752 unsigned short offset
= 0;
1756 if (type
->fields_or_args
) LIST_FOR_EACH_ENTRY( field
, type
->fields_or_args
, const var_t
, entry
)
1758 type_t
*ft
= field
->type
;
1759 if (!ft
->declarray
|| !is_conformant_array(ft
))
1761 unsigned int align
= 0;
1762 size_t size
= type_memsize(ft
, &align
);
1765 if ((align
- 1) & offset
)
1767 unsigned char fc
= 0;
1771 fc
= RPC_FC_ALIGNM4
;
1774 fc
= RPC_FC_ALIGNM8
;
1777 error("write_struct_members: cannot align type %d\n", ft
->type
);
1779 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1780 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1781 *typestring_offset
+= 1;
1783 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1789 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1792 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1793 RPC_FC_STRUCTPAD1
+ padding
- 1,
1795 *typestring_offset
+= 1;
1798 write_end(file
, typestring_offset
);
1801 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1802 const char *name
, unsigned int *tfsoff
)
1804 const type_t
*save_current_structure
= current_structure
;
1805 unsigned int total_size
;
1807 size_t start_offset
;
1808 size_t array_offset
;
1809 int has_pointers
= 0;
1810 unsigned int align
= 0;
1811 unsigned int corroff
;
1815 current_structure
= type
;
1817 total_size
= type_memsize(type
, &align
);
1818 if (total_size
> USHRT_MAX
)
1819 error("structure size for %s exceeds %d bytes by %d bytes\n",
1820 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1822 if (type
->fields_or_args
) LIST_FOR_EACH_ENTRY(f
, type
->fields_or_args
, var_t
, entry
)
1823 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1825 if (!has_pointers
) has_pointers
= type_has_pointers(type
);
1827 array
= find_array_or_string_in_struct(type
);
1828 if (array
&& !processed(array
->type
))
1830 = is_attr(array
->attrs
, ATTR_STRING
)
1831 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
)
1832 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1835 write_descriptors(file
, type
, tfsoff
);
1837 start_offset
= *tfsoff
;
1838 update_tfsoff(type
, start_offset
, file
);
1839 print_start_tfs_comment(file
, type
, start_offset
);
1840 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1841 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1842 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1847 unsigned int absoff
= array
->type
->typestring_offset
;
1848 short reloff
= absoff
- *tfsoff
;
1849 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1850 reloff
, reloff
, absoff
);
1853 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1855 print_file(file
, 2, "NdrFcShort(0x0),\n");
1859 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1861 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1862 nothing is written to file yet. On the actual writing pass,
1863 this will have been updated. */
1864 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1865 short reloff
= absoff
- *tfsoff
;
1866 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1867 reloff
, reloff
, absoff
);
1870 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1871 (type
->type
== RPC_FC_CPSTRUCT
) ||
1872 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1874 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1875 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1877 write_pointer_description(file
, type
, tfsoff
);
1878 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1882 write_struct_members(file
, type
, &corroff
, tfsoff
);
1884 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1886 const var_list_t
*fs
= type
->fields_or_args
;
1889 type
->ptrdesc
= *tfsoff
;
1890 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1892 type_t
*ft
= f
->type
;
1895 if (is_string_type(f
->attrs
, ft
))
1896 write_string_tfs(file
, f
->attrs
, ft
, f
->name
, tfsoff
);
1898 write_pointer_tfs(file
, ft
, tfsoff
);
1900 else if (!ft
->declarray
&& is_conformant_array(ft
))
1902 unsigned int absoff
= ft
->typestring_offset
;
1903 short reloff
= absoff
- (*tfsoff
+ 2);
1904 int ptr_type
= get_attrv(f
->attrs
, ATTR_POINTERTYPE
);
1905 /* FIXME: We need to store pointer attributes for arrays
1906 so we don't lose pointer_default info. */
1908 ptr_type
= RPC_FC_UP
;
1909 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1910 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
1911 string_of_type(ptr_type
));
1912 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1913 reloff
, reloff
, absoff
);
1917 if (type
->ptrdesc
== *tfsoff
)
1921 current_structure
= save_current_structure
;
1922 return start_offset
;
1925 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1926 unsigned char flags
, size_t offset
,
1927 unsigned int *typeformat_offset
)
1929 size_t start_offset
= *typeformat_offset
;
1930 short reloff
= offset
- (*typeformat_offset
+ 2);
1931 int in_attr
, out_attr
;
1932 in_attr
= is_attr(attrs
, ATTR_IN
);
1933 out_attr
= is_attr(attrs
, ATTR_OUT
);
1934 if (!in_attr
&& !out_attr
) in_attr
= 1;
1936 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1939 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1942 string_of_type(pointer_type
));
1946 fprintf(file
, " [allocated_on_stack]");
1948 fprintf(file
, " [pointer_deref]");
1949 fprintf(file
, " */\n");
1952 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1953 *typeformat_offset
+= 4;
1955 return start_offset
;
1958 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1962 print_file(file
, 2, "NdrFcShort(0x0),\t/* No type */\n");
1964 else if (is_base_type(t
->type
))
1966 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1967 t
->type
, string_of_type(t
->type
));
1969 else if (t
->typestring_offset
)
1971 short reloff
= t
->typestring_offset
- *tfsoff
;
1972 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1973 reloff
, reloff
, t
->typestring_offset
);
1976 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1981 static size_t write_union_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1983 unsigned int align
= 0;
1984 unsigned int start_offset
;
1985 size_t size
= type_memsize(type
, &align
);
1988 type_t
*deftype
= NULL
;
1989 short nodeftype
= 0xffff;
1994 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1996 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields_or_args
), const var_t
, entry
);
1997 fields
= uv
->type
->fields_or_args
;
2000 fields
= type
->fields_or_args
;
2002 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2004 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2006 nbranch
+= list_count(cases
);
2008 write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
, TRUE
, tfsoff
);
2011 start_offset
= *tfsoff
;
2012 update_tfsoff(type
, start_offset
, file
);
2013 print_start_tfs_comment(file
, type
, start_offset
);
2014 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
2016 const var_t
*sv
= LIST_ENTRY(list_head(type
->fields_or_args
), const var_t
, entry
);
2017 const type_t
*st
= sv
->type
;
2030 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
2031 print_file(file
, 2, "0x%x,\t/* Switch type= %s */\n",
2032 0x40 | st
->type
, string_of_type(st
->type
));
2036 error("union switch type must be an integer, char, or enum\n");
2039 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
2040 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
2043 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2045 type_t
*ft
= f
->type
;
2046 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2047 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
2050 if (cases
== NULL
&& !deflt
)
2051 error("union field %s with neither case nor default attribute\n", f
->name
);
2053 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
2055 /* MIDL doesn't check for duplicate cases, even though that seems
2056 like a reasonable thing to do, it just dumps them to the TFS
2057 like we're going to do here. */
2058 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
2060 write_branch_type(file
, ft
, tfsoff
);
2063 /* MIDL allows multiple default branches, even though that seems
2064 illogical, it just chooses the last one, which is what we will
2075 write_branch_type(file
, deftype
, tfsoff
);
2079 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
2083 return start_offset
;
2086 static size_t write_ip_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2087 unsigned int *typeformat_offset
)
2090 size_t start_offset
= *typeformat_offset
;
2091 expr_t
*iid
= get_attrp(attrs
, ATTR_IIDIS
);
2095 print_file(file
, 2, "0x2f, /* FC_IP */\n");
2096 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
2098 += write_conf_or_var_desc(file
, NULL
, 0, type
, iid
) + 2;
2102 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
2103 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
2106 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
2108 update_tfsoff(type
, start_offset
, file
);
2109 print_start_tfs_comment(file
, type
, start_offset
);
2110 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
2111 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2112 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
2113 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
2114 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
2115 for (i
= 0; i
< 8; ++i
)
2116 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
2119 fprintf(file
, "\n");
2121 *typeformat_offset
+= 18;
2123 return start_offset
;
2126 static size_t write_contexthandle_tfs(FILE *file
, const type_t
*type
,
2128 unsigned int *typeformat_offset
)
2130 size_t start_offset
= *typeformat_offset
;
2131 unsigned char flags
= 0;
2133 if (is_attr(current_iface
->attrs
, ATTR_STRICTCONTEXTHANDLE
))
2134 flags
|= NDR_STRICT_CONTEXT_HANDLE
;
2138 if (is_attr(var
->attrs
, ATTR_IN
))
2141 if (!is_attr(var
->attrs
, ATTR_OUT
))
2142 flags
|= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
;
2144 if (is_attr(var
->attrs
, ATTR_OUT
))
2147 WRITE_FCTYPE(file
, FC_BIND_CONTEXT
, *typeformat_offset
);
2148 print_file(file
, 2, "0x%x,\t/* Context flags: ", flags
);
2149 /* return and can't be null values overlap */
2150 if (((flags
& 0x21) != 0x21) && (flags
& NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
))
2151 print_file(file
, 0, "can't be null, ");
2152 if (flags
& NDR_CONTEXT_HANDLE_SERIALIZE
)
2153 print_file(file
, 0, "serialize, ");
2154 if (flags
& NDR_CONTEXT_HANDLE_NO_SERIALIZE
)
2155 print_file(file
, 0, "no serialize, ");
2156 if (flags
& NDR_STRICT_CONTEXT_HANDLE
)
2157 print_file(file
, 0, "strict, ");
2158 if ((flags
& 0x21) == 0x20)
2159 print_file(file
, 0, "out, ");
2160 if ((flags
& 0x21) == 0x21)
2161 print_file(file
, 0, "return, ");
2163 print_file(file
, 0, "in, ");
2165 print_file(file
, 0, "via ptr, ");
2166 print_file(file
, 0, "*/\n");
2167 print_file(file
, 2, "0, /* FIXME: rundown routine index*/\n");
2168 print_file(file
, 2, "0, /* FIXME: param num */\n");
2169 *typeformat_offset
+= 4;
2171 return start_offset
;
2174 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
2175 type_t
*type
, const var_t
*var
,
2176 unsigned int *typeformat_offset
)
2180 if (is_context_handle(type
))
2181 return write_contexthandle_tfs(file
, type
, var
, typeformat_offset
);
2183 if (is_user_type(type
))
2185 write_user_tfs(file
, type
, typeformat_offset
);
2186 return type
->typestring_offset
;
2189 if (is_string_type(var
->attrs
, type
))
2190 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2196 off
= write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2197 ptr_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2198 /* Top level pointers to conformant arrays may be handled specially
2199 since we can bypass the pointer, but if the array is buried
2200 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2201 always need to write the pointer. */
2202 if (!ptr_type
&& var
->type
!= type
)
2203 /* FIXME: This should use pointer_default, but the information
2204 isn't kept around for arrays. */
2205 ptr_type
= RPC_FC_UP
;
2206 if (ptr_type
&& ptr_type
!= RPC_FC_RP
)
2208 unsigned int absoff
= type
->typestring_offset
;
2209 short reloff
= absoff
- (*typeformat_offset
+ 2);
2210 off
= *typeformat_offset
;
2211 print_file(file
, 0, "/* %d */\n", off
);
2212 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
2213 string_of_type(ptr_type
));
2214 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2215 reloff
, reloff
, absoff
);
2216 *typeformat_offset
+= 4;
2223 /* basic types don't need a type format string */
2224 if (is_base_type(type
->type
))
2230 case RPC_FC_PSTRUCT
:
2231 case RPC_FC_CSTRUCT
:
2232 case RPC_FC_CPSTRUCT
:
2233 case RPC_FC_CVSTRUCT
:
2234 case RPC_FC_BOGUS_STRUCT
:
2235 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
2236 case RPC_FC_ENCAPSULATED_UNION
:
2237 case RPC_FC_NON_ENCAPSULATED_UNION
:
2238 return write_union_tfs(file
, type
, typeformat_offset
);
2240 case RPC_FC_BIND_PRIMITIVE
:
2244 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
2247 else if (last_ptr(type
))
2249 size_t start_offset
= *typeformat_offset
;
2250 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2251 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2252 const type_t
*base
= type
->ref
;
2254 if (base
->type
== RPC_FC_IP
2256 && is_attr(var
->attrs
, ATTR_IIDIS
)))
2258 return write_ip_tfs(file
, var
->attrs
, type
, typeformat_offset
);
2261 /* special case for pointers to base types */
2262 if (is_base_type(base
->type
))
2264 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2265 type
->type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
2266 string_of_type(type
->type
),
2267 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
2268 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
2269 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
2270 *typeformat_offset
+= 4;
2271 return start_offset
;
2275 assert(is_ptr(type
));
2277 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
2279 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
2280 return write_pointer_only_tfs(file
, var
->attrs
, type
->type
,
2281 !last_ptr(type
) ? 0x10 : 0,
2282 offset
, typeformat_offset
);
2285 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2286 const char *name
, int write_ptr
, unsigned int *tfsoff
)
2290 if (is_user_type(type
))
2292 write_user_tfs(file
, type
, tfsoff
);
2294 else if (is_string_type(attrs
, type
))
2296 write_string_tfs(file
, attrs
, type
, name
, tfsoff
);
2298 else if (is_ptr(type
))
2300 type_t
*ref
= type
->ref
;
2302 if (ref
->type
== RPC_FC_IP
2304 && is_attr(attrs
, ATTR_IIDIS
)))
2306 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2310 if (!processed(ref
) && !is_base_type(ref
->type
))
2311 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2314 write_pointer_tfs(file
, type
, tfsoff
);
2319 else if (type
->declarray
&& is_conformant_array(type
))
2320 ; /* conformant arrays and strings are handled specially */
2321 else if (is_array(type
))
2323 write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
2324 if (is_conformant_array(type
))
2327 else if (is_struct(type
->type
))
2329 if (!processed(type
))
2330 write_struct_tfs(file
, type
, name
, tfsoff
);
2332 else if (is_union(type
->type
))
2334 if (!processed(type
))
2335 write_union_tfs(file
, type
, tfsoff
);
2337 else if (!is_base_type(type
->type
))
2338 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2344 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2347 const ifref_t
*iface
;
2348 unsigned int typeformat_offset
= 2;
2350 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2352 if (!pred(iface
->iface
))
2355 if (iface
->iface
->funcs
)
2358 current_iface
= iface
;
2359 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2361 if (is_local(func
->def
->attrs
)) continue;
2363 if (!is_void(get_func_return_type(func
)))
2365 var_t v
= *func
->def
;
2366 v
.type
= get_func_return_type(func
);
2367 update_tfsoff(get_func_return_type(func
),
2368 write_typeformatstring_var(
2369 file
, 2, NULL
, get_func_return_type(func
),
2370 &v
, &typeformat_offset
),
2374 current_func
= func
;
2376 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2379 write_typeformatstring_var(
2380 file
, 2, func
, var
->type
, var
,
2381 &typeformat_offset
),
2387 return typeformat_offset
+ 1;
2391 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2395 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2396 print_file(file
, indent
, "{\n");
2398 print_file(file
, indent
, "0,\n");
2399 print_file(file
, indent
, "{\n");
2401 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2403 set_all_tfswrite(TRUE
);
2404 process_tfs(file
, ifaces
, pred
);
2406 print_file(file
, indent
, "0x0\n");
2408 print_file(file
, indent
, "}\n");
2410 print_file(file
, indent
, "};\n");
2411 print_file(file
, indent
, "\n");
2414 static unsigned int get_required_buffer_size_type(
2415 const type_t
*type
, const char *name
, unsigned int *alignment
)
2418 if (is_user_type(type
))
2421 const type_t
*utype
= get_user_type(type
, &uname
);
2422 return get_required_buffer_size_type(utype
, uname
, alignment
);
2446 case RPC_FC_ERROR_STATUS_T
:
2456 case RPC_FC_BIND_PRIMITIVE
:
2460 case RPC_FC_PSTRUCT
:
2464 if (!type
->fields_or_args
) return 0;
2465 LIST_FOR_EACH_ENTRY( field
, type
->fields_or_args
, const var_t
, entry
)
2467 unsigned int alignment
;
2468 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2476 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2477 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2480 case RPC_FC_SMFARRAY
:
2481 case RPC_FC_LGFARRAY
:
2482 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2490 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2492 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2493 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2496 if (!in_attr
&& !out_attr
)
2501 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2502 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2508 if (pass
== PASS_OUT
)
2510 if (out_attr
&& is_ptr(var
->type
))
2512 type_t
*type
= var
->type
;
2514 if (type
->type
== RPC_FC_STRUCT
)
2517 unsigned int size
= 36;
2519 if (!type
->fields_or_args
) return size
;
2520 LIST_FOR_EACH_ENTRY( field
, type
->fields_or_args
, const var_t
, entry
)
2523 size
+= get_required_buffer_size_type(
2524 field
->type
, field
->name
, &align
);
2533 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2534 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2536 if (is_ptr(var
->type
))
2538 type_t
*type
= var
->type
;
2540 if (is_base_type(type
->type
))
2544 else if (type
->type
== RPC_FC_STRUCT
)
2546 unsigned int size
= 36;
2549 if (!type
->fields_or_args
) return size
;
2550 LIST_FOR_EACH_ENTRY( field
, type
->fields_or_args
, const var_t
, entry
)
2553 size
+= get_required_buffer_size_type(
2554 field
->type
, field
->name
, &align
);
2561 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2565 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2568 unsigned int total_size
= 0, alignment
;
2572 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2574 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2575 total_size
+= alignment
;
2579 if (pass
== PASS_OUT
&& !is_void(get_func_return_type(func
)))
2581 var_t v
= *func
->def
;
2582 v
.type
= get_func_return_type(func
);
2583 total_size
+= get_required_buffer_size(&v
, &alignment
, PASS_RETURN
);
2584 total_size
+= alignment
;
2589 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2590 enum remoting_phase phase
,
2591 const var_t
*var
, unsigned int type_offset
)
2593 const char *function
;
2596 case PHASE_BUFFERSIZE
:
2597 function
= "BufferSize";
2600 function
= "Marshall";
2602 case PHASE_UNMARSHAL
:
2603 function
= "Unmarshall";
2613 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2615 print_file(file
, indent
, "&_StubMsg,\n");
2616 print_file(file
, indent
, "%s%s%s%s,\n",
2617 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2618 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2619 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2621 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2622 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2623 if (phase
== PHASE_UNMARSHAL
)
2624 print_file(file
, indent
, "0);\n");
2628 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2629 enum pass pass
, const var_t
*var
,
2630 const char *varname
)
2632 type_t
*type
= var
->type
;
2634 unsigned int alignment
= 0;
2635 unsigned char rtype
;
2637 /* no work to do for other phases, buffer sizing is done elsewhere */
2638 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2641 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2665 case RPC_FC_ERROR_STATUS_T
:
2677 case RPC_FC_BIND_PRIMITIVE
:
2678 /* no marshalling needed */
2682 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2686 if (phase
== PHASE_MARSHAL
)
2687 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2688 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2689 alignment
- 1, alignment
- 1);
2691 if (phase
== PHASE_MARSHAL
)
2693 print_file(file
, indent
, "*(");
2694 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2696 fprintf(file
, " *)_StubMsg.Buffer = *");
2698 fprintf(file
, " *)_StubMsg.Buffer = ");
2699 fprintf(file
, "%s", varname
);
2700 fprintf(file
, ";\n");
2702 else if (phase
== PHASE_UNMARSHAL
)
2704 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2705 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2706 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2707 print_file(file
, indent
, "{\n");
2708 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2709 print_file(file
, indent
, "}\n");
2710 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2711 print_file(file
, indent
, "");
2713 print_file(file
, indent
, "*");
2714 fprintf(file
, "%s", varname
);
2715 if (pass
== PASS_IN
&& is_ptr(type
))
2716 fprintf(file
, " = (");
2718 fprintf(file
, " = *(");
2719 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2720 fprintf(file
, " *)_StubMsg.Buffer;\n");
2723 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2724 write_type_decl(file
, var
->type
, NULL
);
2725 fprintf(file
, ");\n");
2728 /* returns whether the MaxCount, Offset or ActualCount members need to be
2729 * filled in for the specified phase */
2730 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2732 return (phase
!= PHASE_UNMARSHAL
);
2735 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2739 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2745 error("%s: multidimensional conformant"
2746 " arrays not supported at the top level\n",
2753 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2754 enum pass pass
, enum remoting_phase phase
,
2757 int in_attr
, out_attr
, pointer_type
;
2758 const type_t
*type
= var
->type
;
2759 unsigned char rtype
;
2760 size_t start_offset
= type
->typestring_offset
;
2762 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2764 pointer_type
= RPC_FC_RP
;
2766 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2767 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2768 if (!in_attr
&& !out_attr
)
2771 if (phase
!= PHASE_FREE
)
2775 if (!in_attr
) return;
2778 if (!out_attr
) return;
2786 if (is_context_handle(type
))
2788 if (phase
== PHASE_MARSHAL
)
2790 if (pass
== PASS_IN
)
2792 /* if the context_handle attribute appears in the chain of types
2793 * without pointers being followed, then the context handle must
2794 * be direct, otherwise it is a pointer */
2795 int is_ch_ptr
= is_aliaschain_attr(type
, ATTR_CONTEXTHANDLE
) ? FALSE
: TRUE
;
2796 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2797 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2798 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ch_ptr
? "*" : "", var
->name
);
2799 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2803 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2804 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2805 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2806 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2807 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2810 else if (phase
== PHASE_UNMARSHAL
)
2812 if (pass
== PASS_OUT
)
2815 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2816 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2817 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2818 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2819 print_file(file
, indent
+ 1, "_Handle);\n");
2823 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2824 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2825 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2829 else if (is_user_type(var
->type
))
2831 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2833 else if (is_string_type(var
->attrs
, var
->type
))
2835 if (is_array(type
) && !is_conformant_array(type
))
2836 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2839 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2841 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2842 write_expr(file
, type
->size_is
, 1);
2843 fprintf(file
, ";\n");
2846 if (phase
== PHASE_FREE
|| pass
== PASS_RETURN
|| pointer_type
== RPC_FC_UP
)
2847 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2848 start_offset
- (type
->size_is
? 4 : 2));
2850 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2854 else if (is_array(type
))
2856 unsigned char tc
= type
->type
;
2857 const char *array_type
= "FixedArray";
2859 /* We already have the size_is expression since it's at the
2860 top level, but do checks for multidimensional conformant
2861 arrays. When we handle them, we'll need to extend this
2862 function to return a list, and then we'll actually use
2863 the return value. */
2864 get_size_is_expr(type
, var
->name
);
2866 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2868 if (is_size_needed_for_phase(phase
))
2870 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2871 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2872 write_expr(file
, type
->length_is
, 1);
2873 fprintf(file
, ";\n\n");
2875 array_type
= "VaryingArray";
2877 else if (tc
== RPC_FC_CARRAY
)
2879 if (is_size_needed_for_phase(phase
))
2881 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2882 write_expr(file
, type
->size_is
, 1);
2883 fprintf(file
, ";\n\n");
2885 array_type
= "ConformantArray";
2887 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2889 if (is_size_needed_for_phase(phase
))
2893 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2894 write_expr(file
, type
->size_is
, 1);
2895 fprintf(file
, ";\n");
2897 if (type
->length_is
)
2899 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2900 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2901 write_expr(file
, type
->length_is
, 1);
2902 fprintf(file
, ";\n\n");
2905 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2907 : "ConformantVaryingArray");
2910 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2911 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2912 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2914 /* these are all unmarshalled by allocating memory */
2915 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2916 type
->type
== RPC_FC_CVARRAY
||
2917 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2918 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2920 print_file(file
, indent
, "if (%s)\n", var
->name
);
2922 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2926 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2928 if (phase
!= PHASE_FREE
)
2929 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2931 else if (!is_ptr(var
->type
))
2936 case RPC_FC_PSTRUCT
:
2937 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2939 case RPC_FC_CSTRUCT
:
2940 case RPC_FC_CPSTRUCT
:
2941 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2943 case RPC_FC_CVSTRUCT
:
2944 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2946 case RPC_FC_BOGUS_STRUCT
:
2947 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2950 if (is_base_type( var
->type
->ref
->type
))
2952 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2954 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2956 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2957 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2962 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2964 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2965 write_expr( file
, iid
, 1 );
2966 fprintf( file
, ";\n\n" );
2968 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2972 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2977 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2979 if (phase
!= PHASE_FREE
)
2980 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2982 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2984 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2985 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2990 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2992 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2994 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2995 write_expr( file
, iid
, 1 );
2996 fprintf( file
, ";\n\n" );
3000 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
3001 write_expr(file
, sx
, 1);
3002 fprintf(file
, ";\n\n");
3004 if (var
->type
->ref
->type
== RPC_FC_IP
)
3005 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
3007 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
3010 fprintf(file
, "\n");
3013 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
3014 enum pass pass
, enum remoting_phase phase
)
3016 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
3018 unsigned int size
= get_function_buffer_size( func
, pass
);
3019 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
3022 if (pass
== PASS_RETURN
)
3026 var
.type
= get_func_return_type(func
);
3027 var
.name
= xstrdup( "_RetVal" );
3028 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
3036 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3037 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
3042 size_t get_size_procformatstring_type(const char *name
, const type_t
*type
, const attr_list_t
*attrs
)
3044 return write_procformatstring_type(NULL
, 0, name
, type
, attrs
, FALSE
);
3048 size_t get_size_procformatstring_func(const func_t
*func
)
3053 /* argument list size */
3055 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3056 size
+= get_size_procformatstring_type(var
->name
, var
->type
, var
->attrs
);
3058 /* return value size */
3059 if (is_void(get_func_return_type(func
)))
3060 size
+= 2; /* FC_END and FC_PAD */
3062 size
+= get_size_procformatstring_type("return value", get_func_return_type(func
), NULL
);
3067 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3069 const ifref_t
*iface
;
3073 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
3075 if (!pred(iface
->iface
))
3078 if (iface
->iface
->funcs
)
3079 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
3080 if (!is_local(func
->def
->attrs
))
3081 size
+= get_size_procformatstring_func( func
);
3086 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3088 set_all_tfswrite(FALSE
);
3089 return process_tfs(NULL
, ifaces
, pred
);
3092 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3093 const var_list_t
*fields
, const char *structvar
)
3099 fprintf(h
, "%lu", e
->u
.lval
);
3102 fprintf(h
, "0x%lx", e
->u
.lval
);
3105 fprintf(h
, "%#.15g", e
->u
.dval
);
3107 case EXPR_TRUEFALSE
:
3109 fprintf(h
, "FALSE");
3113 case EXPR_IDENTIFIER
:
3116 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3117 if (!strcmp(e
->u
.sval
, field
->name
))
3119 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3123 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3128 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3132 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3136 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3140 write_type_decl(h
, e
->u
.tref
, NULL
);
3142 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3145 fprintf(h
, "sizeof(");
3146 write_type_decl(h
, e
->u
.tref
, NULL
);
3157 case EXPR_MEMBERPTR
:
3159 if (brackets
) fprintf(h
, "(");
3160 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3162 case EXPR_SHL
: fprintf(h
, " << "); break;
3163 case EXPR_SHR
: fprintf(h
, " >> "); break;
3164 case EXPR_MUL
: fprintf(h
, " * "); break;
3165 case EXPR_DIV
: fprintf(h
, " / "); break;
3166 case EXPR_ADD
: fprintf(h
, " + "); break;
3167 case EXPR_SUB
: fprintf(h
, " - "); break;
3168 case EXPR_AND
: fprintf(h
, " & "); break;
3169 case EXPR_OR
: fprintf(h
, " | "); break;
3170 case EXPR_MEMBERPTR
: fprintf(h
, "->"); break;
3171 case EXPR_MEMBER
: fprintf(h
, "."); break;
3174 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3175 if (brackets
) fprintf(h
, ")");
3178 if (brackets
) fprintf(h
, "(");
3179 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3181 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3183 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3184 if (brackets
) fprintf(h
, ")");
3186 case EXPR_ADDRESSOF
:
3188 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3191 if (brackets
) fprintf(h
, "(");
3192 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3194 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3196 if (brackets
) fprintf(h
, ")");
3202 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3204 int in_attr
, out_attr
;
3208 /* declare return value '_RetVal' */
3209 if (!is_void(get_func_return_type(func
)))
3211 print_file(file
, indent
, "");
3212 write_type_decl_left(file
, get_func_return_type(func
));
3213 fprintf(file
, " _RetVal;\n");
3219 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3221 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3223 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3224 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3225 if (!out_attr
&& !in_attr
)
3228 if (is_context_handle(var
->type
))
3229 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3232 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3234 print_file(file
, indent
, "");
3235 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3237 fprintf(file
, ";\n");
3240 print_file(file
, indent
, "");
3241 write_type_decl_left(file
, var
->type
);
3243 if (var
->type
->declarray
) {
3244 fprintf(file
, "( *");
3245 write_name(file
, var
);
3246 fprintf(file
, " )");
3248 write_name(file
, var
);
3249 write_type_right(file
, var
->type
, FALSE
);
3250 fprintf(file
, ";\n");
3252 if (decl_indirect(var
->type
))
3253 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3254 var
->name
, var
->name
);
3260 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3262 int in_attr
, out_attr
;
3269 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3271 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3272 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3273 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3274 if (!out_attr
&& !in_attr
)
3279 print_file(file
, indent
, "");
3280 write_name(file
, var
);
3282 if (is_context_handle(var
->type
))
3284 fprintf(file
, " = NdrContextHandleInitialize(\n");
3285 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3286 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3287 var
->type
->typestring_offset
);
3289 else if (var
->type
->size_is
)
3291 unsigned int size
, align
= 0;
3292 type_t
*type
= var
->type
;
3294 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3295 for ( ; type
->size_is
; type
= type
->ref
)
3297 write_expr(file
, type
->size_is
, TRUE
);
3298 fprintf(file
, " * ");
3300 size
= type_memsize(type
, &align
);
3301 fprintf(file
, "%u);\n", size
);
3303 else if (!is_string
)
3305 fprintf(file
, " = &_W%u;\n", i
);
3306 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3307 print_file(file
, indent
, "_W%u = 0;\n", i
);
3315 fprintf(file
, "\n");
3319 int write_expr_eval_routines(FILE *file
, const char *iface
)
3321 static const char *var_name
= "pS";
3323 struct expr_eval_routine
*eval
;
3324 unsigned short callback_offset
= 0;
3326 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3328 const char *name
= eval
->structure
->name
;
3329 const var_list_t
*fields
= eval
->structure
->fields_or_args
;
3332 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3333 iface
, name
, callback_offset
);
3334 print_file(file
, 0, "{\n");
3335 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3336 name
, var_name
, name
, eval
->baseoff
);
3337 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3338 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3339 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3340 fprintf(file
, ";\n");
3341 print_file(file
, 0, "}\n\n");
3347 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3349 struct expr_eval_routine
*eval
;
3350 struct expr_eval_routine
*cursor
;
3351 unsigned short callback_offset
= 0;
3353 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3354 fprintf(file
, "{\n");
3356 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3358 const char *name
= eval
->structure
->name
;
3359 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3361 list_remove(&eval
->entry
);
3365 fprintf(file
, "};\n\n");
3368 void write_user_quad_list(FILE *file
)
3372 if (list_empty(&user_type_list
))
3375 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3376 fprintf(file
, "{\n");
3377 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3379 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3380 print_file(file
, 1, "{\n");
3381 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3382 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3383 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3384 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3385 print_file(file
, 1, "}%s\n", sep
);
3387 fprintf(file
, "};\n\n");
3390 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3392 const struct str_list_entry_t
*endpoint
;
3395 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3396 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3397 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3399 print_file( f
, 1, "{ (const unsigned char *)\"" );
3400 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3402 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3405 if (!*p
) goto error
;
3406 if (p
[1] != '[') goto error
;
3408 fprintf( f
, "\", (const unsigned char *)\"" );
3409 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3411 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3414 if (*p
!= ']') goto error
;
3415 fprintf( f
, "\" },\n" );
3417 print_file( f
, 0, "};\n\n" );
3421 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);