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(func
->def
->type
))
422 write_var_init(file
, indent
, func
->def
->type
, "_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_var(FILE *file
, int indent
,
497 const var_t
*var
, int is_return
)
500 const type_t
*type
= var
->type
;
502 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
503 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
505 if (!is_in
&& !is_out
) is_in
= TRUE
;
507 if (!type
->declarray
&& is_base_type(type
->type
))
510 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
512 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
514 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
516 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
517 size
= 2; /* includes param type prefix */
519 else if (is_base_type(type
->type
))
521 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
522 size
= 2; /* includes param type prefix */
526 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
533 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
534 else if (is_in
&& is_out
)
535 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
537 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
539 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
541 print_file(file
, indent
, "0x01,\n");
542 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
543 size
= 4; /* includes param type prefix */
548 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
550 const ifref_t
*iface
;
554 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
555 print_file(file
, indent
, "{\n");
557 print_file(file
, indent
, "0,\n");
558 print_file(file
, indent
, "{\n");
561 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
563 if (!pred(iface
->iface
))
566 if (iface
->iface
->funcs
)
569 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
571 if (is_local(func
->def
->attrs
)) continue;
572 /* emit argument data */
575 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
576 write_procformatstring_var(file
, indent
, var
, FALSE
);
579 /* emit return value data */
581 if (is_void(var
->type
))
583 print_file(file
, indent
, "0x5b, /* FC_END */\n");
584 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
587 write_procformatstring_var(file
, indent
, var
, TRUE
);
592 print_file(file
, indent
, "0x0\n");
594 print_file(file
, indent
, "}\n");
596 print_file(file
, indent
, "};\n");
597 print_file(file
, indent
, "\n");
600 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
602 if (is_base_type(type
->type
))
604 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
605 *typestring_offset
+= 1;
612 /* write conformance / variance descriptor */
613 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
614 unsigned int baseoff
, const type_t
*type
,
617 unsigned char operator_type
= 0;
618 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
619 const char *conftype_string
= "";
620 const char *operator_string
= "no operators";
621 const expr_t
*subexpr
;
625 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
631 /* Top-level conformance calculations are done inline. */
632 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
633 RPC_FC_TOP_LEVEL_CONFORMANCE
);
634 print_file (file
, 2, "0x0,\n");
635 print_file (file
, 2, "NdrFcShort(0x0),\n");
641 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
642 error("write_conf_or_var_desc: constant value %ld is greater than "
643 "the maximum constant size of %d\n", expr
->cval
,
644 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
646 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
647 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
648 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
649 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
654 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
656 conftype
= RPC_FC_POINTER_CONFORMANCE
;
657 conftype_string
= "field pointer, ";
661 switch (subexpr
->type
)
664 subexpr
= subexpr
->ref
;
665 operator_type
= RPC_FC_DEREFERENCE
;
666 operator_string
= "FC_DEREFERENCE";
669 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
671 subexpr
= subexpr
->ref
;
672 operator_type
= RPC_FC_DIV_2
;
673 operator_string
= "FC_DIV_2";
677 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
679 subexpr
= subexpr
->ref
;
680 operator_type
= RPC_FC_MULT_2
;
681 operator_string
= "FC_MULT_2";
685 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
687 subexpr
= subexpr
->ref
;
688 operator_type
= RPC_FC_SUB_1
;
689 operator_string
= "FC_SUB_1";
693 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
695 subexpr
= subexpr
->ref
;
696 operator_type
= RPC_FC_ADD_1
;
697 operator_string
= "FC_ADD_1";
704 if (subexpr
->type
== EXPR_IDENTIFIER
)
706 const type_t
*correlation_variable
= NULL
;
707 unsigned char correlation_variable_type
;
708 unsigned char param_type
= 0;
712 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
714 unsigned int align
= 0;
715 /* FIXME: take alignment into account */
716 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
718 correlation_variable
= var
->type
;
721 offset
+= type_memsize(var
->type
, &align
);
723 if (!correlation_variable
)
724 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
728 correlation_variable_type
= correlation_variable
->type
;
730 switch (correlation_variable_type
)
734 param_type
= RPC_FC_SMALL
;
738 param_type
= RPC_FC_USMALL
;
743 param_type
= RPC_FC_SHORT
;
746 param_type
= RPC_FC_USHORT
;
750 param_type
= RPC_FC_LONG
;
753 param_type
= RPC_FC_ULONG
;
759 if (sizeof(void *) == 4) /* FIXME */
760 param_type
= RPC_FC_LONG
;
762 param_type
= RPC_FC_HYPER
;
765 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
766 correlation_variable_type
);
769 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
770 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
771 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
772 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
777 unsigned int callback_offset
= 0;
778 struct expr_eval_routine
*eval
;
781 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
783 if (!strcmp (eval
->structure
->name
, structure
->name
)
784 && !compare_expr (eval
->expr
, expr
))
794 eval
= xmalloc (sizeof(*eval
));
795 eval
->structure
= structure
;
796 eval
->baseoff
= baseoff
;
798 list_add_tail (&expr_eval_routines
, &eval
->entry
);
801 if (callback_offset
> USHRT_MAX
)
802 error("Maximum number of callback routines reached\n");
804 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
805 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
806 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
811 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
813 int have_align
= FALSE
;
817 if (!fields
) return 0;
818 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
820 unsigned int falign
= 0;
821 size_t fsize
= type_memsize(v
->type
, &falign
);
827 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
831 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
835 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
837 size_t size
, maxs
= 0;
838 unsigned int align
= *pmaxa
;
841 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
843 /* we could have an empty default field with NULL type */
846 size
= type_memsize(v
->type
, &align
);
847 if (maxs
< size
) maxs
= size
;
848 if (*pmaxa
< align
) *pmaxa
= align
;
855 int get_padding(const var_list_t
*fields
)
857 unsigned short offset
= 0;
864 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
866 type_t
*ft
= f
->type
;
867 unsigned int align
= 0;
868 size_t size
= type_memsize(ft
, &align
);
871 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
875 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
878 size_t type_memsize(const type_t
*t
, unsigned int *align
)
882 if (t
->declarray
&& is_conformant_array(t
))
884 type_memsize(t
->ref
, align
);
887 else if (is_ptr(t
) || is_conformant_array(t
))
889 size
= sizeof(void *);
890 if (size
> *align
) *align
= size
;
892 else switch (t
->type
)
899 if (size
> *align
) *align
= size
;
906 if (size
> *align
) *align
= size
;
910 case RPC_FC_ERROR_STATUS_T
:
914 if (size
> *align
) *align
= size
;
919 if (size
> *align
) *align
= size
;
922 case RPC_FC_CVSTRUCT
:
923 case RPC_FC_CPSTRUCT
:
926 case RPC_FC_BOGUS_STRUCT
:
927 size
= fields_memsize(t
->fields
, align
);
929 case RPC_FC_ENCAPSULATED_UNION
:
930 case RPC_FC_NON_ENCAPSULATED_UNION
:
931 size
= union_memsize(t
->fields
, align
);
933 case RPC_FC_SMFARRAY
:
934 case RPC_FC_LGFARRAY
:
935 case RPC_FC_SMVARRAY
:
936 case RPC_FC_LGVARRAY
:
937 case RPC_FC_BOGUS_ARRAY
:
938 size
= t
->dim
* type_memsize(t
->ref
, align
);
941 error("type_memsize: Unknown type %d\n", t
->type
);
948 int is_full_pointer_function(const func_t
*func
)
951 if (type_has_full_pointer(func
->def
->type
))
955 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
956 if (type_has_full_pointer( var
->type
))
961 void write_full_pointer_init(FILE *file
, int indent
, const func_t
*func
, int is_server
)
963 print_file(file
, indent
, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
964 is_server
? "XLAT_SERVER" : "XLAT_CLIENT");
968 void write_full_pointer_free(FILE *file
, int indent
, const func_t
*func
)
970 print_file(file
, indent
, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
974 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
976 short absoff
= type
->ref
->typestring_offset
;
977 short reloff
= absoff
- (offset
+ 2);
978 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
980 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
981 type
->type
, ptr_attr
, string_of_type(type
->type
));
982 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
983 reloff
, reloff
, absoff
);
987 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
989 unsigned char fc
= type
->ref
->type
;
990 /* for historical reasons, write_simple_pointer also handled string types,
991 * but no longer does. catch bad uses of the function with this check */
992 if (is_string_type(type
->attrs
, type
))
993 error("write_simple_pointer: can't handle type %s which is a string type\n", type
->name
);
994 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
995 type
->type
, string_of_type(type
->type
));
996 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
997 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1001 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
1003 print_file(file
, 0, "/* %u (", tfsoff
);
1004 write_type_decl(file
, t
, NULL
);
1005 print_file(file
, 0, ") */\n");
1008 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
1010 unsigned int offset
= *typestring_offset
;
1012 print_start_tfs_comment(file
, type
, offset
);
1013 update_tfsoff(type
, offset
, file
);
1015 if (type
->ref
->typestring_offset
)
1016 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
1017 else if (is_base_type(type
->ref
->type
))
1018 *typestring_offset
+= write_simple_pointer(file
, type
);
1023 static int processed(const type_t
*type
)
1025 return type
->typestring_offset
&& !type
->tfswrite
;
1028 static int user_type_has_variable_size(const type_t
*t
)
1035 case RPC_FC_PSTRUCT
:
1036 case RPC_FC_CSTRUCT
:
1037 case RPC_FC_CPSTRUCT
:
1038 case RPC_FC_CVSTRUCT
:
1041 /* Note: Since this only applies to user types, we can't have a conformant
1042 array here, and strings should get filed under pointer in this case. */
1046 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1048 unsigned int start
, absoff
, flags
;
1049 unsigned int align
= 0, ualign
= 0;
1051 type_t
*utype
= get_user_type(type
, &name
);
1052 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
1053 size_t size
= type_memsize(type
, &align
);
1054 unsigned short funoff
= user_type_offset(name
);
1059 if (is_base_type(utype
->type
))
1062 print_start_tfs_comment(file
, utype
, absoff
);
1063 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
1064 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1069 if (!processed(utype
))
1070 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
1071 absoff
= utype
->typestring_offset
;
1074 if (utype
->type
== RPC_FC_RP
)
1076 else if (utype
->type
== RPC_FC_UP
)
1082 update_tfsoff(type
, start
, file
);
1083 print_start_tfs_comment(file
, type
, start
);
1084 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
1085 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1086 flags
| (align
- 1), align
- 1, flags
);
1087 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
1088 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
1089 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
1091 reloff
= absoff
- *tfsoff
;
1092 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
1096 static void write_member_type(FILE *file
, const type_t
*cont
,
1097 const attr_list_t
*attrs
, const type_t
*type
,
1098 unsigned int *corroff
, unsigned int *tfsoff
)
1100 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1105 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1112 absoff
= type
->typestring_offset
;
1114 reloff
= absoff
- (*tfsoff
+ 2);
1116 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1117 /* FIXME: actually compute necessary padding */
1118 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1119 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1120 reloff
, reloff
, absoff
);
1123 else if (is_ptr(type
) || is_conformant_array(type
))
1125 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1128 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1131 else if (!write_base_type(file
, type
, tfsoff
))
1132 error("Unsupported member type 0x%x\n", type
->type
);
1135 static void write_end(FILE *file
, unsigned int *tfsoff
)
1137 if (*tfsoff
% 2 == 0)
1139 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1142 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1146 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1148 unsigned int offset
= 0;
1149 var_list_t
*fs
= type
->fields
;
1152 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1154 unsigned int align
= 0;
1155 type_t
*ft
= f
->type
;
1156 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1158 unsigned int absoff
= ft
->typestring_offset
;
1159 short reloff
= absoff
- (*tfsoff
+ 6);
1160 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1161 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1162 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1163 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1164 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1165 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1166 reloff
, reloff
, absoff
);
1170 /* FIXME: take alignment into account */
1171 offset
+= type_memsize(ft
, &align
);
1175 static int write_no_repeat_pointer_descriptions(
1176 FILE *file
, type_t
*type
,
1177 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1178 unsigned int *typestring_offset
)
1183 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1185 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1186 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1188 /* pointer instance */
1189 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1190 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1191 *typestring_offset
+= 6;
1195 if (is_string_type(type
->attrs
, type
))
1196 write_string_tfs(file
, NULL
, type
, NULL
, typestring_offset
);
1198 write_pointer_tfs(file
, type
, typestring_offset
);
1202 unsigned absoff
= type
->typestring_offset
;
1203 short reloff
= absoff
- (*typestring_offset
+ 2);
1204 /* FIXME: get pointer attributes from field */
1205 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1206 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1207 reloff
, reloff
, absoff
);
1208 *typestring_offset
+= 4;
1212 *offset_in_memory
+= type_memsize(type
, &align
);
1213 /* FIXME: is there a case where these two are different? */
1215 *offset_in_buffer
+= type_memsize(type
, &align
);
1220 if (is_non_complex_struct(type
))
1223 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1224 written
+= write_no_repeat_pointer_descriptions(
1226 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1231 *offset_in_memory
+= type_memsize(type
, &align
);
1232 /* FIXME: is there a case where these two are different? */
1234 *offset_in_buffer
+= type_memsize(type
, &align
);
1240 static int write_pointer_description_offsets(
1241 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1242 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1243 unsigned int *typestring_offset
)
1248 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1250 if (offset_in_memory
&& offset_in_buffer
)
1252 /* pointer instance */
1253 /* FIXME: sometimes from end of structure, sometimes from beginning */
1254 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1255 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1258 *offset_in_memory
+= type_memsize(type
, &align
);
1259 /* FIXME: is there a case where these two are different? */
1261 *offset_in_buffer
+= type_memsize(type
, &align
);
1263 *typestring_offset
+= 4;
1265 if (is_string_type(attrs
, type
))
1266 write_string_tfs(file
, NULL
, type
, NULL
, typestring_offset
);
1267 else if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1268 write_pointer_tfs(file
, type
, typestring_offset
);
1270 error("write_pointer_description_offsets: type format string unknown\n");
1277 return write_pointer_description_offsets(
1278 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1281 else if (is_non_complex_struct(type
))
1283 /* otherwise search for interesting fields to parse */
1285 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1287 written
+= write_pointer_description_offsets(
1288 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1295 if (offset_in_memory
)
1296 *offset_in_memory
+= type_memsize(type
, &align
);
1297 /* FIXME: is there a case where these two are different? */
1299 if (offset_in_buffer
)
1300 *offset_in_buffer
+= type_memsize(type
, &align
);
1306 /* Note: if file is NULL return value is number of pointers to write, else
1307 * it is the number of type format characters written */
1308 static int write_fixed_array_pointer_descriptions(
1309 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1310 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1311 unsigned int *typestring_offset
)
1314 int pointer_count
= 0;
1316 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1318 unsigned int temp
= 0;
1319 /* unfortunately, this needs to be done in two passes to avoid
1320 * writing out redundant FC_FIXED_REPEAT descriptions */
1321 pointer_count
= write_pointer_description_offsets(
1322 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1323 if (pointer_count
> 0)
1325 unsigned int increment_size
;
1326 size_t offset_of_array_pointer_mem
= 0;
1327 size_t offset_of_array_pointer_buf
= 0;
1330 increment_size
= type_memsize(type
->ref
, &align
);
1332 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1333 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1334 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1335 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1336 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1337 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1338 *typestring_offset
+= 10;
1340 pointer_count
= write_pointer_description_offsets(
1341 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1342 &offset_of_array_pointer_buf
, typestring_offset
);
1345 else if (is_struct(type
->type
))
1348 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1350 pointer_count
+= write_fixed_array_pointer_descriptions(
1351 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1358 if (offset_in_memory
)
1359 *offset_in_memory
+= type_memsize(type
, &align
);
1360 /* FIXME: is there a case where these two are different? */
1362 if (offset_in_buffer
)
1363 *offset_in_buffer
+= type_memsize(type
, &align
);
1366 return pointer_count
;
1369 /* Note: if file is NULL return value is number of pointers to write, else
1370 * it is the number of type format characters written */
1371 static int write_conformant_array_pointer_descriptions(
1372 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1373 size_t offset_in_memory
, unsigned int *typestring_offset
)
1376 int pointer_count
= 0;
1378 if (is_conformant_array(type
) && !type
->length_is
)
1380 unsigned int temp
= 0;
1381 /* unfortunately, this needs to be done in two passes to avoid
1382 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1383 pointer_count
= write_pointer_description_offsets(
1384 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1385 if (pointer_count
> 0)
1387 unsigned int increment_size
;
1388 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1389 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1392 increment_size
= type_memsize(type
->ref
, &align
);
1394 if (increment_size
> USHRT_MAX
)
1395 error("array size of %u bytes is too large\n", increment_size
);
1397 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1398 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1399 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1400 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1401 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1402 *typestring_offset
+= 8;
1404 pointer_count
= write_pointer_description_offsets(
1405 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1406 &offset_of_array_pointer_buf
, typestring_offset
);
1410 return pointer_count
;
1413 /* Note: if file is NULL return value is number of pointers to write, else
1414 * it is the number of type format characters written */
1415 static int write_varying_array_pointer_descriptions(
1416 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1417 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1418 unsigned int *typestring_offset
)
1421 int pointer_count
= 0;
1423 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1425 if (is_array(type
) && type
->length_is
)
1427 unsigned int temp
= 0;
1428 /* unfortunately, this needs to be done in two passes to avoid
1429 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1430 pointer_count
= write_pointer_description_offsets(
1431 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1432 if (pointer_count
> 0)
1434 unsigned int increment_size
;
1435 size_t offset_of_array_pointer_mem
= 0;
1436 size_t offset_of_array_pointer_buf
= 0;
1439 increment_size
= type_memsize(type
->ref
, &align
);
1441 if (increment_size
> USHRT_MAX
)
1442 error("array size of %u bytes is too large\n", increment_size
);
1444 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1445 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1446 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1447 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1448 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1449 *typestring_offset
+= 8;
1451 pointer_count
= write_pointer_description_offsets(
1452 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1453 &offset_of_array_pointer_buf
, typestring_offset
);
1456 else if (is_struct(type
->type
))
1459 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1461 pointer_count
+= write_varying_array_pointer_descriptions(
1462 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1469 if (offset_in_memory
)
1470 *offset_in_memory
+= type_memsize(type
, &align
);
1471 /* FIXME: is there a case where these two are different? */
1473 if (offset_in_buffer
)
1474 *offset_in_buffer
+= type_memsize(type
, &align
);
1477 return pointer_count
;
1480 static void write_pointer_description(FILE *file
, type_t
*type
,
1481 unsigned int *typestring_offset
)
1483 size_t offset_in_buffer
;
1484 size_t offset_in_memory
;
1486 /* pass 1: search for single instance of a pointer (i.e. don't descend
1488 if (!is_array(type
))
1490 offset_in_memory
= 0;
1491 offset_in_buffer
= 0;
1492 write_no_repeat_pointer_descriptions(
1494 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1497 /* pass 2: search for pointers in fixed arrays */
1498 offset_in_memory
= 0;
1499 offset_in_buffer
= 0;
1500 write_fixed_array_pointer_descriptions(
1502 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1504 /* pass 3: search for pointers in conformant only arrays (but don't descend
1505 * into conformant varying or varying arrays) */
1506 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1507 write_conformant_array_pointer_descriptions(
1508 file
, NULL
, type
, 0, typestring_offset
);
1509 else if (type
->type
== RPC_FC_CPSTRUCT
)
1511 unsigned int align
= 0;
1512 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1513 write_conformant_array_pointer_descriptions(
1515 type_memsize(type
, &align
),
1519 /* pass 4: search for pointers in varying arrays */
1520 offset_in_memory
= 0;
1521 offset_in_buffer
= 0;
1522 write_varying_array_pointer_descriptions(
1524 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1527 int is_declptr(const type_t
*t
)
1529 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1532 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1534 const char *name
, unsigned int *typestring_offset
)
1536 size_t start_offset
;
1537 unsigned char rtype
;
1539 if (is_declptr(type
))
1541 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1542 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1544 pointer_type
= RPC_FC_RP
;
1545 print_start_tfs_comment(file
, type
, *typestring_offset
);
1546 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1547 pointer_type
, flag
, string_of_type(pointer_type
),
1548 flag
? " [simple_pointer]" : "");
1549 *typestring_offset
+= 2;
1552 print_file(file
, 2, "NdrFcShort(0x2),\n");
1553 *typestring_offset
+= 2;
1557 start_offset
= *typestring_offset
;
1558 update_tfsoff(type
, start_offset
, file
);
1560 rtype
= type
->ref
->type
;
1562 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1564 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1565 return start_offset
;
1568 if (type
->declarray
&& !is_conformant_array(type
))
1570 /* FIXME: multi-dimensional array */
1571 if (0xffffuL
< type
->dim
)
1572 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1573 name
, 0xffffu
, type
->dim
- 0xffffu
);
1575 if (rtype
== RPC_FC_CHAR
)
1576 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1578 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1579 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1580 *typestring_offset
+= 2;
1582 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1583 *typestring_offset
+= 2;
1585 return start_offset
;
1587 else if (type
->size_is
)
1589 unsigned int align
= 0;
1591 if (rtype
== RPC_FC_CHAR
)
1592 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1594 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1595 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1596 *typestring_offset
+= 2;
1598 *typestring_offset
+= write_conf_or_var_desc(
1599 file
, current_structure
,
1600 (type
->declarray
&& current_structure
1601 ? type_memsize(current_structure
, &align
)
1603 type
, type
->size_is
);
1605 return start_offset
;
1609 if (rtype
== RPC_FC_WCHAR
)
1610 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1612 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1613 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1614 *typestring_offset
+= 2;
1616 return start_offset
;
1620 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1621 const char *name
, unsigned int *typestring_offset
)
1623 const expr_t
*length_is
= type
->length_is
;
1624 const expr_t
*size_is
= type
->size_is
;
1625 unsigned int align
= 0;
1627 size_t start_offset
;
1629 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1630 unsigned int baseoff
1631 = type
->declarray
&& current_structure
1632 ? type_memsize(current_structure
, &align
)
1636 pointer_type
= RPC_FC_RP
;
1638 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1641 has_pointer
= type_has_pointers(type
->ref
);
1644 size
= type_memsize((is_conformant_array(type
) ? type
->ref
: type
), &align
);
1646 start_offset
= *typestring_offset
;
1647 update_tfsoff(type
, start_offset
, file
);
1648 print_start_tfs_comment(file
, type
, start_offset
);
1649 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1650 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1651 *typestring_offset
+= 2;
1654 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1656 unsigned char tc
= type
->type
;
1658 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1660 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1661 *typestring_offset
+= 4;
1665 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1666 *typestring_offset
+= 2;
1669 if (is_conformant_array(type
))
1671 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1674 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1676 unsigned int elalign
= 0;
1677 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1679 if (type
->type
== RPC_FC_LGVARRAY
)
1681 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1682 *typestring_offset
+= 4;
1686 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1687 *typestring_offset
+= 2;
1690 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1691 *typestring_offset
+= 2;
1696 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1699 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1701 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1702 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1703 *typestring_offset
+= 2;
1704 write_pointer_description(file
, type
, typestring_offset
);
1705 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1706 *typestring_offset
+= 1;
1709 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1710 write_end(file
, typestring_offset
);
1714 unsigned int dim
= size_is
? 0 : type
->dim
;
1715 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1716 *typestring_offset
+= 2;
1718 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1721 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1723 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1724 write_end(file
, typestring_offset
);
1727 return start_offset
;
1730 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1732 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1733 const type_t
*ft
= last_field
->type
;
1735 if (ft
->declarray
&& is_conformant_array(ft
))
1738 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1739 return find_array_or_string_in_struct(last_field
->type
);
1744 static void write_struct_members(FILE *file
, const type_t
*type
,
1745 unsigned int *corroff
, unsigned int *typestring_offset
)
1748 unsigned short offset
= 0;
1752 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1754 type_t
*ft
= field
->type
;
1755 if (!ft
->declarray
|| !is_conformant_array(ft
))
1757 unsigned int align
= 0;
1758 size_t size
= type_memsize(ft
, &align
);
1761 if ((align
- 1) & offset
)
1763 unsigned char fc
= 0;
1767 fc
= RPC_FC_ALIGNM4
;
1770 fc
= RPC_FC_ALIGNM8
;
1773 error("write_struct_members: cannot align type %d\n", ft
->type
);
1775 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1776 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1777 *typestring_offset
+= 1;
1779 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1785 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1788 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1789 RPC_FC_STRUCTPAD1
+ padding
- 1,
1791 *typestring_offset
+= 1;
1794 write_end(file
, typestring_offset
);
1797 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1798 const char *name
, unsigned int *tfsoff
)
1800 const type_t
*save_current_structure
= current_structure
;
1801 unsigned int total_size
;
1803 size_t start_offset
;
1804 size_t array_offset
;
1805 int has_pointers
= 0;
1806 unsigned int align
= 0;
1807 unsigned int corroff
;
1811 current_structure
= type
;
1813 total_size
= type_memsize(type
, &align
);
1814 if (total_size
> USHRT_MAX
)
1815 error("structure size for %s exceeds %d bytes by %d bytes\n",
1816 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1818 if (type
->fields
) LIST_FOR_EACH_ENTRY(f
, type
->fields
, var_t
, entry
)
1819 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1821 if (!has_pointers
) has_pointers
= type_has_pointers(type
);
1823 array
= find_array_or_string_in_struct(type
);
1824 if (array
&& !processed(array
->type
))
1826 = is_attr(array
->attrs
, ATTR_STRING
)
1827 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
)
1828 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1831 write_descriptors(file
, type
, tfsoff
);
1833 start_offset
= *tfsoff
;
1834 update_tfsoff(type
, start_offset
, file
);
1835 print_start_tfs_comment(file
, type
, start_offset
);
1836 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1837 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1838 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1843 unsigned int absoff
= array
->type
->typestring_offset
;
1844 short reloff
= absoff
- *tfsoff
;
1845 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1846 reloff
, reloff
, absoff
);
1849 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1851 print_file(file
, 2, "NdrFcShort(0x0),\n");
1855 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1857 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1858 nothing is written to file yet. On the actual writing pass,
1859 this will have been updated. */
1860 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1861 short reloff
= absoff
- *tfsoff
;
1862 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1863 reloff
, reloff
, absoff
);
1866 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1867 (type
->type
== RPC_FC_CPSTRUCT
) ||
1868 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1870 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1871 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1873 write_pointer_description(file
, type
, tfsoff
);
1874 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1878 write_struct_members(file
, type
, &corroff
, tfsoff
);
1880 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1882 const var_list_t
*fs
= type
->fields
;
1885 type
->ptrdesc
= *tfsoff
;
1886 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1888 type_t
*ft
= f
->type
;
1891 if (is_string_type(f
->attrs
, ft
))
1892 write_string_tfs(file
, f
->attrs
, ft
, f
->name
, tfsoff
);
1894 write_pointer_tfs(file
, ft
, tfsoff
);
1896 else if (!ft
->declarray
&& is_conformant_array(ft
))
1898 unsigned int absoff
= ft
->typestring_offset
;
1899 short reloff
= absoff
- (*tfsoff
+ 2);
1900 int ptr_type
= get_attrv(f
->attrs
, ATTR_POINTERTYPE
);
1901 /* FIXME: We need to store pointer attributes for arrays
1902 so we don't lose pointer_default info. */
1904 ptr_type
= RPC_FC_UP
;
1905 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1906 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
1907 string_of_type(ptr_type
));
1908 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1909 reloff
, reloff
, absoff
);
1913 if (type
->ptrdesc
== *tfsoff
)
1917 current_structure
= save_current_structure
;
1918 return start_offset
;
1921 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1922 unsigned char flags
, size_t offset
,
1923 unsigned int *typeformat_offset
)
1925 size_t start_offset
= *typeformat_offset
;
1926 short reloff
= offset
- (*typeformat_offset
+ 2);
1927 int in_attr
, out_attr
;
1928 in_attr
= is_attr(attrs
, ATTR_IN
);
1929 out_attr
= is_attr(attrs
, ATTR_OUT
);
1930 if (!in_attr
&& !out_attr
) in_attr
= 1;
1932 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1935 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1938 string_of_type(pointer_type
));
1942 fprintf(file
, " [allocated_on_stack]");
1944 fprintf(file
, " [pointer_deref]");
1945 fprintf(file
, " */\n");
1948 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1949 *typeformat_offset
+= 4;
1951 return start_offset
;
1954 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1958 print_file(file
, 2, "NdrFcShort(0x0),\t/* No type */\n");
1960 else if (is_base_type(t
->type
))
1962 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1963 t
->type
, string_of_type(t
->type
));
1965 else if (t
->typestring_offset
)
1967 short reloff
= t
->typestring_offset
- *tfsoff
;
1968 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1969 reloff
, reloff
, t
->typestring_offset
);
1972 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1977 static size_t write_union_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1979 unsigned int align
= 0;
1980 unsigned int start_offset
;
1981 size_t size
= type_memsize(type
, &align
);
1984 type_t
*deftype
= NULL
;
1985 short nodeftype
= 0xffff;
1990 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1992 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
1993 fields
= uv
->type
->fields
;
1996 fields
= type
->fields
;
1998 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2000 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2002 nbranch
+= list_count(cases
);
2004 write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
, TRUE
, tfsoff
);
2007 start_offset
= *tfsoff
;
2008 update_tfsoff(type
, start_offset
, file
);
2009 print_start_tfs_comment(file
, type
, start_offset
);
2010 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
2012 const var_t
*sv
= LIST_ENTRY(list_head(type
->fields
), const var_t
, entry
);
2013 const type_t
*st
= sv
->type
;
2026 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
2027 print_file(file
, 2, "0x%x,\t/* Switch type= %s */\n",
2028 0x40 | st
->type
, string_of_type(st
->type
));
2032 error("union switch type must be an integer, char, or enum\n");
2035 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
2036 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
2039 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2041 type_t
*ft
= f
->type
;
2042 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2043 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
2046 if (cases
== NULL
&& !deflt
)
2047 error("union field %s with neither case nor default attribute\n", f
->name
);
2049 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
2051 /* MIDL doesn't check for duplicate cases, even though that seems
2052 like a reasonable thing to do, it just dumps them to the TFS
2053 like we're going to do here. */
2054 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
2056 write_branch_type(file
, ft
, tfsoff
);
2059 /* MIDL allows multiple default branches, even though that seems
2060 illogical, it just chooses the last one, which is what we will
2071 write_branch_type(file
, deftype
, tfsoff
);
2075 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
2079 return start_offset
;
2082 static size_t write_ip_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2083 unsigned int *typeformat_offset
)
2086 size_t start_offset
= *typeformat_offset
;
2087 expr_t
*iid
= get_attrp(attrs
, ATTR_IIDIS
);
2091 print_file(file
, 2, "0x2f, /* FC_IP */\n");
2092 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
2094 += write_conf_or_var_desc(file
, NULL
, 0, type
, iid
) + 2;
2098 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
2099 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
2102 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
2104 update_tfsoff(type
, start_offset
, file
);
2105 print_start_tfs_comment(file
, type
, start_offset
);
2106 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
2107 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2108 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
2109 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
2110 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
2111 for (i
= 0; i
< 8; ++i
)
2112 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
2115 fprintf(file
, "\n");
2117 *typeformat_offset
+= 18;
2119 return start_offset
;
2122 static size_t write_contexthandle_tfs(FILE *file
, const type_t
*type
,
2124 unsigned int *typeformat_offset
)
2126 size_t start_offset
= *typeformat_offset
;
2127 unsigned char flags
= 0;
2129 if (is_attr(current_iface
->attrs
, ATTR_STRICTCONTEXTHANDLE
))
2130 flags
|= NDR_STRICT_CONTEXT_HANDLE
;
2134 if (is_attr(var
->attrs
, ATTR_IN
))
2137 if (!is_attr(var
->attrs
, ATTR_OUT
))
2138 flags
|= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
;
2140 if (is_attr(var
->attrs
, ATTR_OUT
))
2143 WRITE_FCTYPE(file
, FC_BIND_CONTEXT
, *typeformat_offset
);
2144 print_file(file
, 2, "0x%x,\t/* Context flags: ", flags
);
2145 /* return and can't be null values overlap */
2146 if (((flags
& 0x21) != 0x21) && (flags
& NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
))
2147 print_file(file
, 0, "can't be null, ");
2148 if (flags
& NDR_CONTEXT_HANDLE_SERIALIZE
)
2149 print_file(file
, 0, "serialize, ");
2150 if (flags
& NDR_CONTEXT_HANDLE_NO_SERIALIZE
)
2151 print_file(file
, 0, "no serialize, ");
2152 if (flags
& NDR_STRICT_CONTEXT_HANDLE
)
2153 print_file(file
, 0, "strict, ");
2154 if ((flags
& 0x21) == 0x20)
2155 print_file(file
, 0, "out, ");
2156 if ((flags
& 0x21) == 0x21)
2157 print_file(file
, 0, "return, ");
2159 print_file(file
, 0, "in, ");
2161 print_file(file
, 0, "via ptr, ");
2162 print_file(file
, 0, "*/\n");
2163 print_file(file
, 2, "0, /* FIXME: rundown routine index*/\n");
2164 print_file(file
, 2, "0, /* FIXME: param num */\n");
2165 *typeformat_offset
+= 4;
2167 return start_offset
;
2170 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
2171 type_t
*type
, const var_t
*var
,
2172 unsigned int *typeformat_offset
)
2176 if (is_context_handle(type
))
2177 return write_contexthandle_tfs(file
, type
, var
, typeformat_offset
);
2179 if (is_user_type(type
))
2181 write_user_tfs(file
, type
, typeformat_offset
);
2182 return type
->typestring_offset
;
2185 if (is_string_type(var
->attrs
, type
))
2186 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2192 off
= write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2193 ptr_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2194 /* Top level pointers to conformant arrays may be handled specially
2195 since we can bypass the pointer, but if the array is buried
2196 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2197 always need to write the pointer. */
2198 if (!ptr_type
&& var
->type
!= type
)
2199 /* FIXME: This should use pointer_default, but the information
2200 isn't kept around for arrays. */
2201 ptr_type
= RPC_FC_UP
;
2202 if (ptr_type
&& ptr_type
!= RPC_FC_RP
)
2204 unsigned int absoff
= type
->typestring_offset
;
2205 short reloff
= absoff
- (*typeformat_offset
+ 2);
2206 off
= *typeformat_offset
;
2207 print_file(file
, 0, "/* %d */\n", off
);
2208 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
2209 string_of_type(ptr_type
));
2210 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2211 reloff
, reloff
, absoff
);
2212 *typeformat_offset
+= 4;
2219 /* basic types don't need a type format string */
2220 if (is_base_type(type
->type
))
2226 case RPC_FC_PSTRUCT
:
2227 case RPC_FC_CSTRUCT
:
2228 case RPC_FC_CPSTRUCT
:
2229 case RPC_FC_CVSTRUCT
:
2230 case RPC_FC_BOGUS_STRUCT
:
2231 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
2232 case RPC_FC_ENCAPSULATED_UNION
:
2233 case RPC_FC_NON_ENCAPSULATED_UNION
:
2234 return write_union_tfs(file
, type
, typeformat_offset
);
2236 case RPC_FC_BIND_PRIMITIVE
:
2240 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
2243 else if (last_ptr(type
))
2245 size_t start_offset
= *typeformat_offset
;
2246 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2247 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2248 const type_t
*base
= type
->ref
;
2250 if (base
->type
== RPC_FC_IP
2252 && is_attr(var
->attrs
, ATTR_IIDIS
)))
2254 return write_ip_tfs(file
, var
->attrs
, type
, typeformat_offset
);
2257 /* special case for pointers to base types */
2258 if (is_base_type(base
->type
))
2260 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2261 type
->type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
2262 string_of_type(type
->type
),
2263 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
2264 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
2265 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
2266 *typeformat_offset
+= 4;
2267 return start_offset
;
2271 assert(is_ptr(type
));
2273 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
2275 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
2276 return write_pointer_only_tfs(file
, var
->attrs
, type
->type
,
2277 !last_ptr(type
) ? 0x10 : 0,
2278 offset
, typeformat_offset
);
2281 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2282 const char *name
, int write_ptr
, unsigned int *tfsoff
)
2286 if (is_user_type(type
))
2288 write_user_tfs(file
, type
, tfsoff
);
2290 else if (is_string_type(attrs
, type
))
2292 write_string_tfs(file
, attrs
, type
, name
, tfsoff
);
2294 else if (is_ptr(type
))
2296 type_t
*ref
= type
->ref
;
2298 if (ref
->type
== RPC_FC_IP
2300 && is_attr(attrs
, ATTR_IIDIS
)))
2302 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2306 if (!processed(ref
) && !is_base_type(ref
->type
))
2307 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2310 write_pointer_tfs(file
, type
, tfsoff
);
2315 else if (type
->declarray
&& is_conformant_array(type
))
2316 ; /* conformant arrays and strings are handled specially */
2317 else if (is_array(type
))
2319 write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
2320 if (is_conformant_array(type
))
2323 else if (is_struct(type
->type
))
2325 if (!processed(type
))
2326 write_struct_tfs(file
, type
, name
, tfsoff
);
2328 else if (is_union(type
->type
))
2330 if (!processed(type
))
2331 write_union_tfs(file
, type
, tfsoff
);
2333 else if (!is_base_type(type
->type
))
2334 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2340 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2343 const ifref_t
*iface
;
2344 unsigned int typeformat_offset
= 2;
2346 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2348 if (!pred(iface
->iface
))
2351 if (iface
->iface
->funcs
)
2354 current_iface
= iface
;
2355 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2357 if (is_local(func
->def
->attrs
)) continue;
2359 if (!is_void(func
->def
->type
))
2360 update_tfsoff(func
->def
->type
,
2361 write_typeformatstring_var(
2362 file
, 2, NULL
, func
->def
->type
,
2363 func
->def
, &typeformat_offset
),
2366 current_func
= func
;
2368 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2371 write_typeformatstring_var(
2372 file
, 2, func
, var
->type
, var
,
2373 &typeformat_offset
),
2379 return typeformat_offset
+ 1;
2383 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2387 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2388 print_file(file
, indent
, "{\n");
2390 print_file(file
, indent
, "0,\n");
2391 print_file(file
, indent
, "{\n");
2393 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2395 set_all_tfswrite(TRUE
);
2396 process_tfs(file
, ifaces
, pred
);
2398 print_file(file
, indent
, "0x0\n");
2400 print_file(file
, indent
, "}\n");
2402 print_file(file
, indent
, "};\n");
2403 print_file(file
, indent
, "\n");
2406 static unsigned int get_required_buffer_size_type(
2407 const type_t
*type
, const char *name
, unsigned int *alignment
)
2410 if (is_user_type(type
))
2413 const type_t
*utype
= get_user_type(type
, &uname
);
2414 return get_required_buffer_size_type(utype
, uname
, alignment
);
2438 case RPC_FC_ERROR_STATUS_T
:
2448 case RPC_FC_BIND_PRIMITIVE
:
2452 case RPC_FC_PSTRUCT
:
2456 if (!type
->fields
) return 0;
2457 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2459 unsigned int alignment
;
2460 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2468 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2469 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2472 case RPC_FC_SMFARRAY
:
2473 case RPC_FC_LGFARRAY
:
2474 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2482 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2484 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2485 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2488 if (!in_attr
&& !out_attr
)
2493 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2494 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2500 if (pass
== PASS_OUT
)
2502 if (out_attr
&& is_ptr(var
->type
))
2504 type_t
*type
= var
->type
;
2506 if (type
->type
== RPC_FC_STRUCT
)
2509 unsigned int size
= 36;
2511 if (!type
->fields
) return size
;
2512 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2515 size
+= get_required_buffer_size_type(
2516 field
->type
, field
->name
, &align
);
2525 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2526 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2528 if (is_ptr(var
->type
))
2530 type_t
*type
= var
->type
;
2532 if (is_base_type(type
->type
))
2536 else if (type
->type
== RPC_FC_STRUCT
)
2538 unsigned int size
= 36;
2541 if (!type
->fields
) return size
;
2542 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2545 size
+= get_required_buffer_size_type(
2546 field
->type
, field
->name
, &align
);
2553 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2557 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2560 unsigned int total_size
= 0, alignment
;
2564 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2566 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2567 total_size
+= alignment
;
2571 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
2573 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
2574 total_size
+= alignment
;
2579 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2580 enum remoting_phase phase
,
2581 const var_t
*var
, unsigned int type_offset
)
2583 const char *function
;
2586 case PHASE_BUFFERSIZE
:
2587 function
= "BufferSize";
2590 function
= "Marshall";
2592 case PHASE_UNMARSHAL
:
2593 function
= "Unmarshall";
2603 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2605 print_file(file
, indent
, "&_StubMsg,\n");
2606 print_file(file
, indent
, "%s%s%s%s,\n",
2607 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2608 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2609 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2611 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2612 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2613 if (phase
== PHASE_UNMARSHAL
)
2614 print_file(file
, indent
, "0);\n");
2618 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2619 enum pass pass
, const var_t
*var
,
2620 const char *varname
)
2622 type_t
*type
= var
->type
;
2624 unsigned int alignment
= 0;
2625 unsigned char rtype
;
2627 /* no work to do for other phases, buffer sizing is done elsewhere */
2628 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2631 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2655 case RPC_FC_ERROR_STATUS_T
:
2667 case RPC_FC_BIND_PRIMITIVE
:
2668 /* no marshalling needed */
2672 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2676 if (phase
== PHASE_MARSHAL
)
2677 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2678 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2679 alignment
- 1, alignment
- 1);
2681 if (phase
== PHASE_MARSHAL
)
2683 print_file(file
, indent
, "*(");
2684 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2686 fprintf(file
, " *)_StubMsg.Buffer = *");
2688 fprintf(file
, " *)_StubMsg.Buffer = ");
2689 fprintf(file
, "%s", varname
);
2690 fprintf(file
, ";\n");
2692 else if (phase
== PHASE_UNMARSHAL
)
2694 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2695 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2696 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2697 print_file(file
, indent
, "{\n");
2698 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2699 print_file(file
, indent
, "}\n");
2700 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2701 print_file(file
, indent
, "");
2703 print_file(file
, indent
, "*");
2704 fprintf(file
, "%s", varname
);
2705 if (pass
== PASS_IN
&& is_ptr(type
))
2706 fprintf(file
, " = (");
2708 fprintf(file
, " = *(");
2709 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2710 fprintf(file
, " *)_StubMsg.Buffer;\n");
2713 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2714 write_type_decl(file
, var
->type
, NULL
);
2715 fprintf(file
, ");\n");
2718 /* returns whether the MaxCount, Offset or ActualCount members need to be
2719 * filled in for the specified phase */
2720 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2722 return (phase
!= PHASE_UNMARSHAL
);
2725 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2729 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2735 error("%s: multidimensional conformant"
2736 " arrays not supported at the top level\n",
2743 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2744 enum pass pass
, enum remoting_phase phase
,
2747 int in_attr
, out_attr
, pointer_type
;
2748 const type_t
*type
= var
->type
;
2749 unsigned char rtype
;
2750 size_t start_offset
= type
->typestring_offset
;
2752 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2754 pointer_type
= RPC_FC_RP
;
2756 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2757 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2758 if (!in_attr
&& !out_attr
)
2761 if (phase
!= PHASE_FREE
)
2765 if (!in_attr
) return;
2768 if (!out_attr
) return;
2776 if (is_context_handle(type
))
2778 if (phase
== PHASE_MARSHAL
)
2780 if (pass
== PASS_IN
)
2782 /* if the context_handle attribute appears in the chain of types
2783 * without pointers being followed, then the context handle must
2784 * be direct, otherwise it is a pointer */
2785 int is_ch_ptr
= is_aliaschain_attr(type
, ATTR_CONTEXTHANDLE
) ? FALSE
: TRUE
;
2786 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2787 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2788 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ch_ptr
? "*" : "", var
->name
);
2789 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2793 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2794 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2795 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2796 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2797 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2800 else if (phase
== PHASE_UNMARSHAL
)
2802 if (pass
== PASS_OUT
)
2805 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2806 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2807 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2808 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2809 print_file(file
, indent
+ 1, "_Handle);\n");
2813 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2814 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2815 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2819 else if (is_user_type(var
->type
))
2821 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2823 else if (is_string_type(var
->attrs
, var
->type
))
2825 if (is_array(type
) && !is_conformant_array(type
))
2826 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2829 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2831 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2832 write_expr(file
, type
->size_is
, 1);
2833 fprintf(file
, ";\n");
2836 if (phase
== PHASE_FREE
|| pass
== PASS_RETURN
|| pointer_type
== RPC_FC_UP
)
2837 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2838 start_offset
- (type
->size_is
? 4 : 2));
2840 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2844 else if (is_array(type
))
2846 unsigned char tc
= type
->type
;
2847 const char *array_type
= "FixedArray";
2849 /* We already have the size_is expression since it's at the
2850 top level, but do checks for multidimensional conformant
2851 arrays. When we handle them, we'll need to extend this
2852 function to return a list, and then we'll actually use
2853 the return value. */
2854 get_size_is_expr(type
, var
->name
);
2856 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2858 if (is_size_needed_for_phase(phase
))
2860 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2861 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2862 write_expr(file
, type
->length_is
, 1);
2863 fprintf(file
, ";\n\n");
2865 array_type
= "VaryingArray";
2867 else if (tc
== RPC_FC_CARRAY
)
2869 if (is_size_needed_for_phase(phase
))
2871 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2872 write_expr(file
, type
->size_is
, 1);
2873 fprintf(file
, ";\n\n");
2875 array_type
= "ConformantArray";
2877 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2879 if (is_size_needed_for_phase(phase
))
2883 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2884 write_expr(file
, type
->size_is
, 1);
2885 fprintf(file
, ";\n");
2887 if (type
->length_is
)
2889 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2890 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2891 write_expr(file
, type
->length_is
, 1);
2892 fprintf(file
, ";\n\n");
2895 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2897 : "ConformantVaryingArray");
2900 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2901 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2902 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2904 /* these are all unmarshalled by allocating memory */
2905 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2906 type
->type
== RPC_FC_CVARRAY
||
2907 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2908 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2910 print_file(file
, indent
, "if (%s)\n", var
->name
);
2912 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2916 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2918 if (phase
!= PHASE_FREE
)
2919 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2921 else if (!is_ptr(var
->type
))
2926 case RPC_FC_PSTRUCT
:
2927 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2929 case RPC_FC_CSTRUCT
:
2930 case RPC_FC_CPSTRUCT
:
2931 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2933 case RPC_FC_CVSTRUCT
:
2934 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2936 case RPC_FC_BOGUS_STRUCT
:
2937 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2940 if (is_base_type( var
->type
->ref
->type
))
2942 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2944 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2946 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2947 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2952 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2954 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2955 write_expr( file
, iid
, 1 );
2956 fprintf( file
, ";\n\n" );
2958 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2962 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2967 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2969 if (phase
!= PHASE_FREE
)
2970 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2972 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2974 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2975 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2980 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2982 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2984 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2985 write_expr( file
, iid
, 1 );
2986 fprintf( file
, ";\n\n" );
2990 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2991 write_expr(file
, sx
, 1);
2992 fprintf(file
, ";\n\n");
2994 if (var
->type
->ref
->type
== RPC_FC_IP
)
2995 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
2997 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
3000 fprintf(file
, "\n");
3003 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
3004 enum pass pass
, enum remoting_phase phase
)
3006 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
3008 unsigned int size
= get_function_buffer_size( func
, pass
);
3009 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
3012 if (pass
== PASS_RETURN
)
3016 var
.name
= xstrdup( "_RetVal" );
3017 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
3025 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3026 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
3031 size_t get_size_procformatstring_var(const var_t
*var
)
3033 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
3037 size_t get_size_procformatstring_func(const func_t
*func
)
3042 /* argument list size */
3044 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3045 size
+= get_size_procformatstring_var(var
);
3047 /* return value size */
3048 if (is_void(func
->def
->type
))
3049 size
+= 2; /* FC_END and FC_PAD */
3051 size
+= get_size_procformatstring_var(func
->def
);
3056 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3058 const ifref_t
*iface
;
3062 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
3064 if (!pred(iface
->iface
))
3067 if (iface
->iface
->funcs
)
3068 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
3069 if (!is_local(func
->def
->attrs
))
3070 size
+= get_size_procformatstring_func( func
);
3075 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3077 set_all_tfswrite(FALSE
);
3078 return process_tfs(NULL
, ifaces
, pred
);
3081 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3082 const var_list_t
*fields
, const char *structvar
)
3088 fprintf(h
, "%lu", e
->u
.lval
);
3091 fprintf(h
, "0x%lx", e
->u
.lval
);
3094 fprintf(h
, "%#.15g", e
->u
.dval
);
3096 case EXPR_TRUEFALSE
:
3098 fprintf(h
, "FALSE");
3102 case EXPR_IDENTIFIER
:
3105 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3106 if (!strcmp(e
->u
.sval
, field
->name
))
3108 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3112 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3117 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3121 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3125 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3129 write_type_decl(h
, e
->u
.tref
, NULL
);
3131 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3134 fprintf(h
, "sizeof(");
3135 write_type_decl(h
, e
->u
.tref
, NULL
);
3146 if (brackets
) fprintf(h
, "(");
3147 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3149 case EXPR_SHL
: fprintf(h
, " << "); break;
3150 case EXPR_SHR
: fprintf(h
, " >> "); break;
3151 case EXPR_MUL
: fprintf(h
, " * "); break;
3152 case EXPR_DIV
: fprintf(h
, " / "); break;
3153 case EXPR_ADD
: fprintf(h
, " + "); break;
3154 case EXPR_SUB
: fprintf(h
, " - "); break;
3155 case EXPR_AND
: fprintf(h
, " & "); break;
3156 case EXPR_OR
: fprintf(h
, " | "); break;
3159 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3160 if (brackets
) fprintf(h
, ")");
3163 if (brackets
) fprintf(h
, "(");
3164 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3166 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3168 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3169 if (brackets
) fprintf(h
, ")");
3171 case EXPR_ADDRESSOF
:
3173 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3179 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3181 int in_attr
, out_attr
;
3183 const var_t
*def
= func
->def
;
3186 /* declare return value '_RetVal' */
3187 if (!is_void(def
->type
))
3189 print_file(file
, indent
, "");
3190 write_type_decl_left(file
, def
->type
);
3191 fprintf(file
, " _RetVal;\n");
3197 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3199 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3201 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3202 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3203 if (!out_attr
&& !in_attr
)
3206 if (is_context_handle(var
->type
))
3207 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3210 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3212 print_file(file
, indent
, "");
3213 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3215 fprintf(file
, ";\n");
3218 print_file(file
, indent
, "");
3219 write_type_decl_left(file
, var
->type
);
3221 if (var
->type
->declarray
) {
3222 fprintf(file
, "( *");
3223 write_name(file
, var
);
3224 fprintf(file
, " )");
3226 write_name(file
, var
);
3227 write_type_right(file
, var
->type
, FALSE
);
3228 fprintf(file
, ";\n");
3230 if (decl_indirect(var
->type
))
3231 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3232 var
->name
, var
->name
);
3238 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3240 int in_attr
, out_attr
;
3247 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3249 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3250 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3251 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3252 if (!out_attr
&& !in_attr
)
3257 print_file(file
, indent
, "");
3258 write_name(file
, var
);
3260 if (is_context_handle(var
->type
))
3262 fprintf(file
, " = NdrContextHandleInitialize(\n");
3263 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3264 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3265 var
->type
->typestring_offset
);
3267 else if (var
->type
->size_is
)
3269 unsigned int size
, align
= 0;
3270 type_t
*type
= var
->type
;
3272 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3273 for ( ; type
->size_is
; type
= type
->ref
)
3275 write_expr(file
, type
->size_is
, TRUE
);
3276 fprintf(file
, " * ");
3278 size
= type_memsize(type
, &align
);
3279 fprintf(file
, "%u);\n", size
);
3281 else if (!is_string
)
3283 fprintf(file
, " = &_W%u;\n", i
);
3284 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3285 print_file(file
, indent
, "_W%u = 0;\n", i
);
3293 fprintf(file
, "\n");
3297 int write_expr_eval_routines(FILE *file
, const char *iface
)
3299 static const char *var_name
= "pS";
3301 struct expr_eval_routine
*eval
;
3302 unsigned short callback_offset
= 0;
3304 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3306 const char *name
= eval
->structure
->name
;
3307 const var_list_t
*fields
= eval
->structure
->fields
;
3310 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3311 iface
, name
, callback_offset
);
3312 print_file(file
, 0, "{\n");
3313 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3314 name
, var_name
, name
, eval
->baseoff
);
3315 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3316 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3317 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3318 fprintf(file
, ";\n");
3319 print_file(file
, 0, "}\n\n");
3325 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3327 struct expr_eval_routine
*eval
;
3328 struct expr_eval_routine
*cursor
;
3329 unsigned short callback_offset
= 0;
3331 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3332 fprintf(file
, "{\n");
3334 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3336 const char *name
= eval
->structure
->name
;
3337 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3339 list_remove(&eval
->entry
);
3343 fprintf(file
, "};\n\n");
3346 void write_user_quad_list(FILE *file
)
3350 if (list_empty(&user_type_list
))
3353 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3354 fprintf(file
, "{\n");
3355 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3357 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3358 print_file(file
, 1, "{\n");
3359 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3360 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3361 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3362 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3363 print_file(file
, 1, "}%s\n", sep
);
3365 fprintf(file
, "};\n\n");
3368 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3370 const struct str_list_entry_t
*endpoint
;
3373 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3374 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3375 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3377 print_file( f
, 1, "{ (const unsigned char *)\"" );
3378 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3380 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3383 if (!*p
) goto error
;
3384 if (p
[1] != '[') goto error
;
3386 fprintf( f
, "\", (const unsigned char *)\"" );
3387 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3389 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3392 if (*p
!= ']') goto error
;
3393 fprintf( f
, "\" },\n" );
3395 print_file( f
, 0, "};\n\n" );
3399 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);