2 * Format String Generator for IDL Compiler
4 * Copyright 2005-2006 Eric Kohl
5 * Copyright 2005-2006 Robert Shearman
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
40 #include "wine/list.h"
44 static const func_t
*current_func
;
45 static const type_t
*current_structure
;
46 static const ifref_t
*current_iface
;
48 static struct list expr_eval_routines
= LIST_INIT(expr_eval_routines
);
49 struct expr_eval_routine
52 const type_t
*structure
;
57 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
);
58 static size_t write_struct_tfs(FILE *file
, type_t
*type
, const char *name
, unsigned int *tfsoff
);
59 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
60 const char *name
, int write_ptr
, unsigned int *tfsoff
);
61 static const var_t
*find_array_or_string_in_struct(const type_t
*type
);
63 const char *string_of_type(unsigned char type
)
67 case RPC_FC_BYTE
: return "FC_BYTE";
68 case RPC_FC_CHAR
: return "FC_CHAR";
69 case RPC_FC_SMALL
: return "FC_SMALL";
70 case RPC_FC_USMALL
: return "FC_USMALL";
71 case RPC_FC_WCHAR
: return "FC_WCHAR";
72 case RPC_FC_SHORT
: return "FC_SHORT";
73 case RPC_FC_USHORT
: return "FC_USHORT";
74 case RPC_FC_LONG
: return "FC_LONG";
75 case RPC_FC_ULONG
: return "FC_ULONG";
76 case RPC_FC_FLOAT
: return "FC_FLOAT";
77 case RPC_FC_HYPER
: return "FC_HYPER";
78 case RPC_FC_DOUBLE
: return "FC_DOUBLE";
79 case RPC_FC_ENUM16
: return "FC_ENUM16";
80 case RPC_FC_ENUM32
: return "FC_ENUM32";
81 case RPC_FC_IGNORE
: return "FC_IGNORE";
82 case RPC_FC_ERROR_STATUS_T
: return "FC_ERROR_STATUS_T";
83 case RPC_FC_RP
: return "FC_RP";
84 case RPC_FC_UP
: return "FC_UP";
85 case RPC_FC_OP
: return "FC_OP";
86 case RPC_FC_FP
: return "FC_FP";
87 case RPC_FC_ENCAPSULATED_UNION
: return "FC_ENCAPSULATED_UNION";
88 case RPC_FC_NON_ENCAPSULATED_UNION
: return "FC_NON_ENCAPSULATED_UNION";
89 case RPC_FC_STRUCT
: return "FC_STRUCT";
90 case RPC_FC_PSTRUCT
: return "FC_PSTRUCT";
91 case RPC_FC_CSTRUCT
: return "FC_CSTRUCT";
92 case RPC_FC_CPSTRUCT
: return "FC_CPSTRUCT";
93 case RPC_FC_CVSTRUCT
: return "FC_CVSTRUCT";
94 case RPC_FC_BOGUS_STRUCT
: return "FC_BOGUS_STRUCT";
95 case RPC_FC_SMFARRAY
: return "FC_SMFARRAY";
96 case RPC_FC_LGFARRAY
: return "FC_LGFARRAY";
97 case RPC_FC_SMVARRAY
: return "FC_SMVARRAY";
98 case RPC_FC_LGVARRAY
: return "FC_LGVARRAY";
99 case RPC_FC_CARRAY
: return "FC_CARRAY";
100 case RPC_FC_CVARRAY
: return "FC_CVARRAY";
101 case RPC_FC_BOGUS_ARRAY
: return "FC_BOGUS_ARRAY";
102 case RPC_FC_ALIGNM4
: return "FC_ALIGNM4";
103 case RPC_FC_ALIGNM8
: return "FC_ALIGNM8";
104 case RPC_FC_POINTER
: return "FC_POINTER";
105 case RPC_FC_C_CSTRING
: return "FC_C_CSTRING";
106 case RPC_FC_C_WSTRING
: return "FC_C_WSTRING";
107 case RPC_FC_CSTRING
: return "FC_CSTRING";
108 case RPC_FC_WSTRING
: return "FC_WSTRING";
110 error("string_of_type: unknown type 0x%02x\n", type
);
115 int is_struct(unsigned char type
)
122 case RPC_FC_CPSTRUCT
:
123 case RPC_FC_CVSTRUCT
:
124 case RPC_FC_BOGUS_STRUCT
:
131 static int is_non_complex_struct(const type_t
*type
)
138 case RPC_FC_CPSTRUCT
:
139 case RPC_FC_CVSTRUCT
:
146 int is_union(unsigned char type
)
150 case RPC_FC_ENCAPSULATED_UNION
:
151 case RPC_FC_NON_ENCAPSULATED_UNION
:
158 static int type_has_pointers(const type_t
*type
)
160 if (is_user_type(type
))
162 else if (is_ptr(type
))
164 else if (is_array(type
))
165 return type_has_pointers(type
->ref
);
166 else if (is_struct(type
->type
))
169 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
171 if (type_has_pointers(field
->type
))
175 else if (is_union(type
->type
))
179 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
181 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
182 fields
= uv
->type
->fields
;
185 fields
= type
->fields
;
186 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
188 if (field
->type
&& type_has_pointers(field
->type
))
196 static int type_has_full_pointer(const type_t
*type
)
198 if (is_user_type(type
))
200 else if (type
->type
== RPC_FC_FP
)
202 else if (is_ptr(type
))
204 else if (is_array(type
))
205 return type_has_full_pointer(type
->ref
);
206 else if (is_struct(type
->type
))
209 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
211 if (type_has_full_pointer(field
->type
))
215 else if (is_union(type
->type
))
219 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
221 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
222 fields
= uv
->type
->fields
;
225 fields
= type
->fields
;
226 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
228 if (field
->type
&& type_has_full_pointer(field
->type
))
236 static unsigned short user_type_offset(const char *name
)
239 unsigned short off
= 0;
240 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
242 if (strcmp(name
, ut
->name
) == 0)
246 error("user_type_offset: couldn't find type (%s)\n", name
);
250 static void update_tfsoff(type_t
*type
, unsigned int offset
, FILE *file
)
252 type
->typestring_offset
= offset
;
253 if (file
) type
->tfswrite
= FALSE
;
256 static void guard_rec(type_t
*type
)
258 /* types that contain references to themselves (like a linked list),
259 need to be shielded from infinite recursion when writing embedded
261 if (type
->typestring_offset
)
262 type
->tfswrite
= FALSE
;
264 type
->typestring_offset
= 1;
267 static type_t
*get_user_type(const type_t
*t
, const char **pname
)
271 type_t
*ut
= get_attrp(t
->attrs
, ATTR_WIREMARSHAL
);
279 if (t
->kind
== TKIND_ALIAS
)
286 int is_user_type(const type_t
*t
)
288 return get_user_type(t
, NULL
) != NULL
;
291 static int is_embedded_complex(const type_t
*type
)
293 unsigned char tc
= type
->type
;
294 return is_struct(tc
) || is_union(tc
) || is_array(type
) || is_user_type(type
)
295 || (is_ptr(type
) && type
->ref
->type
== RPC_FC_IP
);
298 static const char *get_context_handle_type_name(const type_t
*type
)
301 for (t
= type
; is_ptr(t
); t
= t
->ref
)
302 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
308 /* This is actually fairly involved to implement precisely, due to the
309 effects attributes may have and things like that. Right now this is
310 only used for optimization, so just check for a very small set of
311 criteria that guarantee the types are equivalent; assume every thing
312 else is different. */
313 static int compare_type(const type_t
*a
, const type_t
*b
)
318 && strcmp(a
->name
, b
->name
) == 0))
320 /* Ordering doesn't need to be implemented yet. */
324 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
328 if (a
->type
!= b
->type
)
329 return a
->type
- b
->type
;
336 return a
->u
.lval
- b
->u
.lval
;
338 return a
->u
.dval
- b
->u
.dval
;
339 case EXPR_IDENTIFIER
:
340 return strcmp(a
->u
.sval
, b
->u
.sval
);
342 ret
= compare_expr(a
->ref
, b
->ref
);
345 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
348 return compare_expr(a
->ext2
, b
->ext2
);
357 ret
= compare_expr(a
->ref
, b
->ref
);
360 return compare_expr(a
->u
.ext
, b
->u
.ext
);
362 ret
= compare_type(a
->u
.tref
, b
->u
.tref
);
370 return compare_expr(a
->ref
, b
->ref
);
372 return compare_type(a
->u
.tref
, b
->u
.tref
);
379 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
382 fprintf(file, "/* %2u */\n", typestring_offset); \
383 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
387 static void print_file(FILE *file
, int indent
, const char *format
, ...)
390 va_start(va
, format
);
391 print(file
, indent
, format
, va
);
395 void print(FILE *file
, int indent
, const char *format
, va_list va
)
399 if (format
[0] != '\n')
402 vfprintf(file
, format
, va
);
407 static void write_var_init(FILE *file
, int indent
, const type_t
*t
, const char *n
)
409 if (decl_indirect(t
))
410 print_file(file
, indent
, "MIDL_memset(&%s, 0, sizeof(%s));\n", n
, n
);
411 else if (is_ptr(t
) || is_array(t
))
412 print_file(file
, indent
, "%s = 0;\n", n
);
415 void write_parameters_init(FILE *file
, int indent
, const func_t
*func
)
419 if (!is_void(func
->def
->type
))
420 write_var_init(file
, indent
, func
->def
->type
, "_RetVal");
425 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
426 write_var_init(file
, indent
, var
->type
, var
->name
);
431 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
433 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
434 print_file(f
, indent
, "{\n");
435 print_file(f
, indent
+ 1, "short Pad;\n");
436 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
437 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
438 print_file(f
, indent
, "\n");
441 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, type_pred_t pred
)
443 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
444 get_size_typeformatstring(ifaces
, pred
));
446 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
447 get_size_procformatstring(ifaces
, pred
));
450 write_formatdesc(f
, indent
, "TYPE");
451 write_formatdesc(f
, indent
, "PROC");
453 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
454 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
455 print_file(f
, indent
, "\n");
458 static inline int is_base_type(unsigned char type
)
477 case RPC_FC_ERROR_STATUS_T
:
478 case RPC_FC_BIND_PRIMITIVE
:
486 int decl_indirect(const type_t
*t
)
488 return is_user_type(t
)
489 || (!is_base_type(t
->type
)
494 static size_t write_procformatstring_var(FILE *file
, int indent
,
495 const var_t
*var
, int is_return
)
498 const type_t
*type
= var
->type
;
500 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
501 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
503 if (!is_in
&& !is_out
) is_in
= TRUE
;
505 if (!type
->declarray
&& is_base_type(type
->type
))
508 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
510 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
512 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
514 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
515 size
= 2; /* includes param type prefix */
517 else if (is_base_type(type
->type
))
519 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
520 size
= 2; /* includes param type prefix */
524 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
531 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
532 else if (is_in
&& is_out
)
533 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
535 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
537 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
539 print_file(file
, indent
, "0x01,\n");
540 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
541 size
= 4; /* includes param type prefix */
546 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
548 const ifref_t
*iface
;
552 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
553 print_file(file
, indent
, "{\n");
555 print_file(file
, indent
, "0,\n");
556 print_file(file
, indent
, "{\n");
559 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
561 if (!pred(iface
->iface
))
564 if (iface
->iface
->funcs
)
567 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
569 if (is_local(func
->def
->attrs
)) continue;
570 /* emit argument data */
573 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
574 write_procformatstring_var(file
, indent
, var
, FALSE
);
577 /* emit return value data */
579 if (is_void(var
->type
))
581 print_file(file
, indent
, "0x5b, /* FC_END */\n");
582 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
585 write_procformatstring_var(file
, indent
, var
, TRUE
);
590 print_file(file
, indent
, "0x0\n");
592 print_file(file
, indent
, "}\n");
594 print_file(file
, indent
, "};\n");
595 print_file(file
, indent
, "\n");
598 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
600 if (is_base_type(type
->type
))
602 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
603 *typestring_offset
+= 1;
610 /* write conformance / variance descriptor */
611 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
612 unsigned int baseoff
, const type_t
*type
,
615 unsigned char operator_type
= 0;
616 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
617 const char *conftype_string
= "";
618 const char *operator_string
= "no operators";
619 const expr_t
*subexpr
;
623 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
629 /* Top-level conformance calculations are done inline. */
630 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
631 RPC_FC_TOP_LEVEL_CONFORMANCE
);
632 print_file (file
, 2, "0x0,\n");
633 print_file (file
, 2, "NdrFcShort(0x0),\n");
639 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
640 error("write_conf_or_var_desc: constant value %ld is greater than "
641 "the maximum constant size of %d\n", expr
->cval
,
642 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
644 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
645 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
646 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
647 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
652 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
654 conftype
= RPC_FC_POINTER_CONFORMANCE
;
655 conftype_string
= "field pointer, ";
659 switch (subexpr
->type
)
662 subexpr
= subexpr
->ref
;
663 operator_type
= RPC_FC_DEREFERENCE
;
664 operator_string
= "FC_DEREFERENCE";
667 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
669 subexpr
= subexpr
->ref
;
670 operator_type
= RPC_FC_DIV_2
;
671 operator_string
= "FC_DIV_2";
675 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
677 subexpr
= subexpr
->ref
;
678 operator_type
= RPC_FC_MULT_2
;
679 operator_string
= "FC_MULT_2";
683 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
685 subexpr
= subexpr
->ref
;
686 operator_type
= RPC_FC_SUB_1
;
687 operator_string
= "FC_SUB_1";
691 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
693 subexpr
= subexpr
->ref
;
694 operator_type
= RPC_FC_ADD_1
;
695 operator_string
= "FC_ADD_1";
702 if (subexpr
->type
== EXPR_IDENTIFIER
)
704 const type_t
*correlation_variable
= NULL
;
705 unsigned char correlation_variable_type
;
706 unsigned char param_type
= 0;
710 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
712 unsigned int align
= 0;
713 /* FIXME: take alignment into account */
714 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
716 correlation_variable
= var
->type
;
719 offset
+= type_memsize(var
->type
, &align
);
721 if (!correlation_variable
)
722 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
726 correlation_variable_type
= correlation_variable
->type
;
728 switch (correlation_variable_type
)
732 param_type
= RPC_FC_SMALL
;
736 param_type
= RPC_FC_USMALL
;
741 param_type
= RPC_FC_SHORT
;
744 param_type
= RPC_FC_USHORT
;
748 param_type
= RPC_FC_LONG
;
751 param_type
= RPC_FC_ULONG
;
757 if (sizeof(void *) == 4) /* FIXME */
758 param_type
= RPC_FC_LONG
;
760 param_type
= RPC_FC_HYPER
;
763 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
764 correlation_variable_type
);
767 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
768 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
769 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
770 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
775 unsigned int callback_offset
= 0;
776 struct expr_eval_routine
*eval
;
779 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
781 if (!strcmp (eval
->structure
->name
, structure
->name
)
782 && !compare_expr (eval
->expr
, expr
))
792 eval
= xmalloc (sizeof(*eval
));
793 eval
->structure
= structure
;
794 eval
->baseoff
= baseoff
;
796 list_add_tail (&expr_eval_routines
, &eval
->entry
);
799 if (callback_offset
> USHRT_MAX
)
800 error("Maximum number of callback routines reached\n");
802 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
803 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
804 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
809 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
811 int have_align
= FALSE
;
815 if (!fields
) return 0;
816 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
818 unsigned int falign
= 0;
819 size_t fsize
= type_memsize(v
->type
, &falign
);
825 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
829 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
833 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
835 size_t size
, maxs
= 0;
836 unsigned int align
= *pmaxa
;
839 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
841 /* we could have an empty default field with NULL type */
844 size
= type_memsize(v
->type
, &align
);
845 if (maxs
< size
) maxs
= size
;
846 if (*pmaxa
< align
) *pmaxa
= align
;
853 int get_padding(const var_list_t
*fields
)
855 unsigned short offset
= 0;
862 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
864 type_t
*ft
= f
->type
;
865 unsigned int align
= 0;
866 size_t size
= type_memsize(ft
, &align
);
869 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
873 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
876 size_t type_memsize(const type_t
*t
, unsigned int *align
)
880 if (t
->declarray
&& is_conformant_array(t
))
882 type_memsize(t
->ref
, align
);
885 else if (is_ptr(t
) || is_conformant_array(t
))
887 size
= sizeof(void *);
888 if (size
> *align
) *align
= size
;
890 else switch (t
->type
)
897 if (size
> *align
) *align
= size
;
904 if (size
> *align
) *align
= size
;
908 case RPC_FC_ERROR_STATUS_T
:
912 if (size
> *align
) *align
= size
;
917 if (size
> *align
) *align
= size
;
920 case RPC_FC_CVSTRUCT
:
921 case RPC_FC_CPSTRUCT
:
924 case RPC_FC_BOGUS_STRUCT
:
925 size
= fields_memsize(t
->fields
, align
);
927 case RPC_FC_ENCAPSULATED_UNION
:
928 case RPC_FC_NON_ENCAPSULATED_UNION
:
929 size
= union_memsize(t
->fields
, align
);
931 case RPC_FC_SMFARRAY
:
932 case RPC_FC_LGFARRAY
:
933 case RPC_FC_SMVARRAY
:
934 case RPC_FC_LGVARRAY
:
935 case RPC_FC_BOGUS_ARRAY
:
936 size
= t
->dim
* type_memsize(t
->ref
, align
);
939 error("type_memsize: Unknown type %d\n", t
->type
);
946 int is_full_pointer_function(const func_t
*func
)
949 if (type_has_full_pointer(func
->def
->type
))
953 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
954 if (type_has_full_pointer( var
->type
))
959 void write_full_pointer_init(FILE *file
, int indent
, const func_t
*func
, int is_server
)
961 print_file(file
, indent
, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
962 is_server
? "XLAT_SERVER" : "XLAT_CLIENT");
966 void write_full_pointer_free(FILE *file
, int indent
, const func_t
*func
)
968 print_file(file
, indent
, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
972 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
974 short absoff
= type
->ref
->typestring_offset
;
975 short reloff
= absoff
- (offset
+ 2);
976 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
978 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
979 type
->type
, ptr_attr
, string_of_type(type
->type
));
980 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
981 reloff
, reloff
, absoff
);
985 static unsigned char conf_string_type_of_char_type(unsigned char t
)
991 return RPC_FC_C_CSTRING
;
993 return RPC_FC_C_WSTRING
;
996 error("string_type_of_char_type: unrecognized type %d\n", t
);
1000 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
1003 = is_string_type(type
->attrs
, type
)
1004 ? conf_string_type_of_char_type(type
->ref
->type
)
1006 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
1007 type
->type
, string_of_type(type
->type
));
1008 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
1009 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1013 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
1015 print_file(file
, 0, "/* %u (", tfsoff
);
1016 write_type_decl(file
, t
, NULL
);
1017 print_file(file
, 0, ") */\n");
1020 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
1022 unsigned int offset
= *typestring_offset
;
1024 print_start_tfs_comment(file
, type
, offset
);
1025 update_tfsoff(type
, offset
, file
);
1027 if (type
->ref
->typestring_offset
)
1028 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
1029 else if (is_base_type(type
->ref
->type
))
1030 *typestring_offset
+= write_simple_pointer(file
, type
);
1035 static int processed(const type_t
*type
)
1037 return type
->typestring_offset
&& !type
->tfswrite
;
1040 static int user_type_has_variable_size(const type_t
*t
)
1047 case RPC_FC_PSTRUCT
:
1048 case RPC_FC_CSTRUCT
:
1049 case RPC_FC_CPSTRUCT
:
1050 case RPC_FC_CVSTRUCT
:
1053 /* Note: Since this only applies to user types, we can't have a conformant
1054 array here, and strings should get filed under pointer in this case. */
1058 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1060 unsigned int start
, absoff
, flags
;
1061 unsigned int align
= 0, ualign
= 0;
1063 type_t
*utype
= get_user_type(type
, &name
);
1064 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
1065 size_t size
= type_memsize(type
, &align
);
1066 unsigned short funoff
= user_type_offset(name
);
1071 if (is_base_type(utype
->type
))
1074 print_start_tfs_comment(file
, utype
, absoff
);
1075 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
1076 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1081 if (!processed(utype
))
1082 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
1083 absoff
= utype
->typestring_offset
;
1086 if (utype
->type
== RPC_FC_RP
)
1088 else if (utype
->type
== RPC_FC_UP
)
1094 update_tfsoff(type
, start
, file
);
1095 print_start_tfs_comment(file
, type
, start
);
1096 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
1097 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1098 flags
| (align
- 1), align
- 1, flags
);
1099 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
1100 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
1101 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
1103 reloff
= absoff
- *tfsoff
;
1104 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
1108 static void write_member_type(FILE *file
, const type_t
*cont
,
1109 const attr_list_t
*attrs
, const type_t
*type
,
1110 unsigned int *corroff
, unsigned int *tfsoff
)
1112 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1117 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1124 absoff
= type
->typestring_offset
;
1126 reloff
= absoff
- (*tfsoff
+ 2);
1128 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1129 /* FIXME: actually compute necessary padding */
1130 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1131 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1132 reloff
, reloff
, absoff
);
1135 else if (is_ptr(type
) || is_conformant_array(type
))
1137 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1140 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1143 else if (!write_base_type(file
, type
, tfsoff
))
1144 error("Unsupported member type 0x%x\n", type
->type
);
1147 static void write_end(FILE *file
, unsigned int *tfsoff
)
1149 if (*tfsoff
% 2 == 0)
1151 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1154 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1158 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1160 unsigned int offset
= 0;
1161 var_list_t
*fs
= type
->fields
;
1164 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1166 unsigned int align
= 0;
1167 type_t
*ft
= f
->type
;
1168 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1170 unsigned int absoff
= ft
->typestring_offset
;
1171 short reloff
= absoff
- (*tfsoff
+ 6);
1172 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1173 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1174 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1175 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1176 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1177 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1178 reloff
, reloff
, absoff
);
1182 /* FIXME: take alignment into account */
1183 offset
+= type_memsize(ft
, &align
);
1187 static int write_no_repeat_pointer_descriptions(
1188 FILE *file
, type_t
*type
,
1189 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1190 unsigned int *typestring_offset
)
1195 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1197 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1198 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1200 /* pointer instance */
1201 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1202 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1203 *typestring_offset
+= 6;
1206 write_pointer_tfs(file
, type
, typestring_offset
);
1209 unsigned absoff
= type
->typestring_offset
;
1210 short reloff
= absoff
- (*typestring_offset
+ 2);
1211 /* FIXME: get pointer attributes from field */
1212 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1213 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1214 reloff
, reloff
, absoff
);
1215 *typestring_offset
+= 4;
1219 *offset_in_memory
+= type_memsize(type
, &align
);
1220 /* FIXME: is there a case where these two are different? */
1222 *offset_in_buffer
+= type_memsize(type
, &align
);
1227 if (is_non_complex_struct(type
))
1230 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1231 written
+= write_no_repeat_pointer_descriptions(
1233 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1238 *offset_in_memory
+= type_memsize(type
, &align
);
1239 /* FIXME: is there a case where these two are different? */
1241 *offset_in_buffer
+= type_memsize(type
, &align
);
1247 static int write_pointer_description_offsets(
1248 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1249 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1250 unsigned int *typestring_offset
)
1255 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1257 if (offset_in_memory
&& offset_in_buffer
)
1259 /* pointer instance */
1260 /* FIXME: sometimes from end of structure, sometimes from beginning */
1261 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1262 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1265 *offset_in_memory
+= type_memsize(type
, &align
);
1266 /* FIXME: is there a case where these two are different? */
1268 *offset_in_buffer
+= type_memsize(type
, &align
);
1270 *typestring_offset
+= 4;
1272 if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1273 write_pointer_tfs(file
, type
, typestring_offset
);
1275 error("write_pointer_description_offsets: type format string unknown\n");
1282 return write_pointer_description_offsets(
1283 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1286 else if (is_non_complex_struct(type
))
1288 /* otherwise search for interesting fields to parse */
1290 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1292 written
+= write_pointer_description_offsets(
1293 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1300 if (offset_in_memory
)
1301 *offset_in_memory
+= type_memsize(type
, &align
);
1302 /* FIXME: is there a case where these two are different? */
1304 if (offset_in_buffer
)
1305 *offset_in_buffer
+= type_memsize(type
, &align
);
1311 /* Note: if file is NULL return value is number of pointers to write, else
1312 * it is the number of type format characters written */
1313 static int write_fixed_array_pointer_descriptions(
1314 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1315 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1316 unsigned int *typestring_offset
)
1319 int pointer_count
= 0;
1321 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1323 unsigned int temp
= 0;
1324 /* unfortunately, this needs to be done in two passes to avoid
1325 * writing out redundant FC_FIXED_REPEAT descriptions */
1326 pointer_count
= write_pointer_description_offsets(
1327 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1328 if (pointer_count
> 0)
1330 unsigned int increment_size
;
1331 size_t offset_of_array_pointer_mem
= 0;
1332 size_t offset_of_array_pointer_buf
= 0;
1335 increment_size
= type_memsize(type
->ref
, &align
);
1337 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1338 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1339 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1340 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1341 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1342 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1343 *typestring_offset
+= 10;
1345 pointer_count
= write_pointer_description_offsets(
1346 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1347 &offset_of_array_pointer_buf
, typestring_offset
);
1350 else if (is_struct(type
->type
))
1353 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1355 pointer_count
+= write_fixed_array_pointer_descriptions(
1356 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1363 if (offset_in_memory
)
1364 *offset_in_memory
+= type_memsize(type
, &align
);
1365 /* FIXME: is there a case where these two are different? */
1367 if (offset_in_buffer
)
1368 *offset_in_buffer
+= type_memsize(type
, &align
);
1371 return pointer_count
;
1374 /* Note: if file is NULL return value is number of pointers to write, else
1375 * it is the number of type format characters written */
1376 static int write_conformant_array_pointer_descriptions(
1377 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1378 size_t offset_in_memory
, unsigned int *typestring_offset
)
1381 int pointer_count
= 0;
1383 if (is_conformant_array(type
) && !type
->length_is
)
1385 unsigned int temp
= 0;
1386 /* unfortunately, this needs to be done in two passes to avoid
1387 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1388 pointer_count
= write_pointer_description_offsets(
1389 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1390 if (pointer_count
> 0)
1392 unsigned int increment_size
;
1393 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1394 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1397 increment_size
= type_memsize(type
->ref
, &align
);
1399 if (increment_size
> USHRT_MAX
)
1400 error("array size of %u bytes is too large\n", increment_size
);
1402 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1403 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1404 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1405 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1406 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1407 *typestring_offset
+= 8;
1409 pointer_count
= write_pointer_description_offsets(
1410 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1411 &offset_of_array_pointer_buf
, typestring_offset
);
1415 return pointer_count
;
1418 /* Note: if file is NULL return value is number of pointers to write, else
1419 * it is the number of type format characters written */
1420 static int write_varying_array_pointer_descriptions(
1421 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1422 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1423 unsigned int *typestring_offset
)
1426 int pointer_count
= 0;
1428 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1430 if (is_array(type
) && type
->length_is
)
1432 unsigned int temp
= 0;
1433 /* unfortunately, this needs to be done in two passes to avoid
1434 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1435 pointer_count
= write_pointer_description_offsets(
1436 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1437 if (pointer_count
> 0)
1439 unsigned int increment_size
;
1440 size_t offset_of_array_pointer_mem
= 0;
1441 size_t offset_of_array_pointer_buf
= 0;
1444 increment_size
= type_memsize(type
->ref
, &align
);
1446 if (increment_size
> USHRT_MAX
)
1447 error("array size of %u bytes is too large\n", increment_size
);
1449 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1450 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1451 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1452 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1453 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1454 *typestring_offset
+= 8;
1456 pointer_count
= write_pointer_description_offsets(
1457 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1458 &offset_of_array_pointer_buf
, typestring_offset
);
1461 else if (is_struct(type
->type
))
1464 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1466 pointer_count
+= write_varying_array_pointer_descriptions(
1467 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1474 if (offset_in_memory
)
1475 *offset_in_memory
+= type_memsize(type
, &align
);
1476 /* FIXME: is there a case where these two are different? */
1478 if (offset_in_buffer
)
1479 *offset_in_buffer
+= type_memsize(type
, &align
);
1482 return pointer_count
;
1485 static void write_pointer_description(FILE *file
, type_t
*type
,
1486 unsigned int *typestring_offset
)
1488 size_t offset_in_buffer
;
1489 size_t offset_in_memory
;
1491 /* pass 1: search for single instance of a pointer (i.e. don't descend
1493 if (!is_array(type
))
1495 offset_in_memory
= 0;
1496 offset_in_buffer
= 0;
1497 write_no_repeat_pointer_descriptions(
1499 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1502 /* pass 2: search for pointers in fixed arrays */
1503 offset_in_memory
= 0;
1504 offset_in_buffer
= 0;
1505 write_fixed_array_pointer_descriptions(
1507 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1509 /* pass 3: search for pointers in conformant only arrays (but don't descend
1510 * into conformant varying or varying arrays) */
1511 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1512 write_conformant_array_pointer_descriptions(
1513 file
, NULL
, type
, 0, typestring_offset
);
1514 else if (type
->type
== RPC_FC_CPSTRUCT
)
1516 unsigned int align
= 0;
1517 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1518 write_conformant_array_pointer_descriptions(
1520 type_memsize(type
, &align
),
1524 /* pass 4: search for pointers in varying arrays */
1525 offset_in_memory
= 0;
1526 offset_in_buffer
= 0;
1527 write_varying_array_pointer_descriptions(
1529 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1532 int is_declptr(const type_t
*t
)
1534 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1537 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1539 const char *name
, unsigned int *typestring_offset
,
1542 size_t start_offset
;
1543 unsigned char rtype
;
1545 if (toplevel
&& is_declptr(type
))
1547 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1548 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1550 pointer_type
= RPC_FC_RP
;
1551 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1552 pointer_type
, flag
, string_of_type(pointer_type
),
1553 flag
? " [simple_pointer]" : "");
1554 *typestring_offset
+= 2;
1557 print_file(file
, 2, "NdrFcShort(0x2),\n");
1558 *typestring_offset
+= 2;
1562 start_offset
= *typestring_offset
;
1563 update_tfsoff(type
, start_offset
, file
);
1565 rtype
= type
->ref
->type
;
1567 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1569 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1570 return start_offset
;
1573 if (type
->declarray
&& !is_conformant_array(type
))
1575 /* FIXME: multi-dimensional array */
1576 if (0xffffuL
< type
->dim
)
1577 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1578 name
, 0xffffu
, type
->dim
- 0xffffu
);
1580 if (rtype
== RPC_FC_CHAR
)
1581 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1583 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1584 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1585 *typestring_offset
+= 2;
1587 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1588 *typestring_offset
+= 2;
1590 return start_offset
;
1592 else if (type
->size_is
)
1594 unsigned int align
= 0;
1596 if (rtype
== RPC_FC_CHAR
)
1597 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1599 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1600 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1601 *typestring_offset
+= 2;
1603 *typestring_offset
+= write_conf_or_var_desc(
1604 file
, current_structure
,
1605 (type
->declarray
&& current_structure
1606 ? type_memsize(current_structure
, &align
)
1608 type
, type
->size_is
);
1610 return start_offset
;
1614 if (rtype
== RPC_FC_WCHAR
)
1615 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1617 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1618 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1619 *typestring_offset
+= 2;
1621 return start_offset
;
1625 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1626 const char *name
, unsigned int *typestring_offset
)
1628 const expr_t
*length_is
= type
->length_is
;
1629 const expr_t
*size_is
= type
->size_is
;
1630 unsigned int align
= 0;
1632 size_t start_offset
;
1634 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1635 unsigned int baseoff
1636 = type
->declarray
&& current_structure
1637 ? type_memsize(current_structure
, &align
)
1641 pointer_type
= RPC_FC_RP
;
1643 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1646 has_pointer
= type_has_pointers(type
->ref
);
1649 size
= type_memsize((is_conformant_array(type
) ? type
->ref
: type
), &align
);
1651 start_offset
= *typestring_offset
;
1652 update_tfsoff(type
, start_offset
, file
);
1653 print_start_tfs_comment(file
, type
, start_offset
);
1654 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1655 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1656 *typestring_offset
+= 2;
1659 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1661 unsigned char tc
= type
->type
;
1663 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1665 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1666 *typestring_offset
+= 4;
1670 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1671 *typestring_offset
+= 2;
1674 if (is_conformant_array(type
))
1676 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1679 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1681 unsigned int elalign
= 0;
1682 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1684 if (type
->type
== RPC_FC_LGVARRAY
)
1686 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1687 *typestring_offset
+= 4;
1691 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1692 *typestring_offset
+= 2;
1695 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1696 *typestring_offset
+= 2;
1701 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1704 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1706 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1707 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1708 *typestring_offset
+= 2;
1709 write_pointer_description(file
, type
, typestring_offset
);
1710 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1711 *typestring_offset
+= 1;
1714 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1715 write_end(file
, typestring_offset
);
1719 unsigned int dim
= size_is
? 0 : type
->dim
;
1720 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1721 *typestring_offset
+= 2;
1723 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1726 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1728 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1729 write_end(file
, typestring_offset
);
1732 return start_offset
;
1735 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1737 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1738 const type_t
*ft
= last_field
->type
;
1740 if (ft
->declarray
&& is_conformant_array(ft
))
1743 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1744 return find_array_or_string_in_struct(last_field
->type
);
1749 static void write_struct_members(FILE *file
, const type_t
*type
,
1750 unsigned int *corroff
, unsigned int *typestring_offset
)
1753 unsigned short offset
= 0;
1757 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1759 type_t
*ft
= field
->type
;
1760 if (!ft
->declarray
|| !is_conformant_array(ft
))
1762 unsigned int align
= 0;
1763 size_t size
= type_memsize(ft
, &align
);
1766 if ((align
- 1) & offset
)
1768 unsigned char fc
= 0;
1772 fc
= RPC_FC_ALIGNM4
;
1775 fc
= RPC_FC_ALIGNM8
;
1778 error("write_struct_members: cannot align type %d\n", ft
->type
);
1780 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1781 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1782 *typestring_offset
+= 1;
1784 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1790 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1793 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1794 RPC_FC_STRUCTPAD1
+ padding
- 1,
1796 *typestring_offset
+= 1;
1799 write_end(file
, typestring_offset
);
1802 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1803 const char *name
, unsigned int *tfsoff
)
1805 const type_t
*save_current_structure
= current_structure
;
1806 unsigned int total_size
;
1808 size_t start_offset
;
1809 size_t array_offset
;
1810 int has_pointers
= 0;
1811 unsigned int align
= 0;
1812 unsigned int corroff
;
1816 current_structure
= type
;
1818 total_size
= type_memsize(type
, &align
);
1819 if (total_size
> USHRT_MAX
)
1820 error("structure size for %s exceeds %d bytes by %d bytes\n",
1821 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1823 if (type
->fields
) LIST_FOR_EACH_ENTRY(f
, type
->fields
, var_t
, entry
)
1824 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1826 if (!has_pointers
) has_pointers
= type_has_pointers(type
);
1828 array
= find_array_or_string_in_struct(type
);
1829 if (array
&& !processed(array
->type
))
1831 = is_attr(array
->attrs
, ATTR_STRING
)
1832 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
, FALSE
)
1833 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1836 write_descriptors(file
, type
, tfsoff
);
1838 start_offset
= *tfsoff
;
1839 update_tfsoff(type
, start_offset
, file
);
1840 print_start_tfs_comment(file
, type
, start_offset
);
1841 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1842 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1843 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1848 unsigned int absoff
= array
->type
->typestring_offset
;
1849 short reloff
= absoff
- *tfsoff
;
1850 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1851 reloff
, reloff
, absoff
);
1854 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1856 print_file(file
, 2, "NdrFcShort(0x0),\n");
1860 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1862 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1863 nothing is written to file yet. On the actual writing pass,
1864 this will have been updated. */
1865 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1866 short reloff
= absoff
- *tfsoff
;
1867 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1868 reloff
, reloff
, absoff
);
1871 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1872 (type
->type
== RPC_FC_CPSTRUCT
) ||
1873 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1875 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1876 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1878 write_pointer_description(file
, type
, tfsoff
);
1879 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1883 write_struct_members(file
, type
, &corroff
, tfsoff
);
1885 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1887 const var_list_t
*fs
= type
->fields
;
1890 type
->ptrdesc
= *tfsoff
;
1891 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1893 type_t
*ft
= f
->type
;
1895 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 ((last_ptr(type
) || last_array(type
)) && is_ptrchain_attr(var
, ATTR_STRING
))
2186 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
, TRUE
);
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_ptr(type
))
2292 type_t
*ref
= type
->ref
;
2294 if (ref
->type
== RPC_FC_IP
2296 && is_attr(attrs
, ATTR_IIDIS
)))
2298 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2302 if (!processed(ref
) && !is_base_type(ref
->type
))
2303 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2306 write_pointer_tfs(file
, type
, tfsoff
);
2311 else if (last_array(type
) && is_attr(attrs
, ATTR_STRING
))
2313 write_string_tfs(file
, attrs
, type
, name
, tfsoff
, FALSE
);
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 current_func
= func
;
2361 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2364 write_typeformatstring_var(
2365 file
, 2, func
, var
->type
, var
,
2366 &typeformat_offset
),
2372 return typeformat_offset
+ 1;
2376 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2380 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2381 print_file(file
, indent
, "{\n");
2383 print_file(file
, indent
, "0,\n");
2384 print_file(file
, indent
, "{\n");
2386 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2388 set_all_tfswrite(TRUE
);
2389 process_tfs(file
, ifaces
, pred
);
2391 print_file(file
, indent
, "0x0\n");
2393 print_file(file
, indent
, "}\n");
2395 print_file(file
, indent
, "};\n");
2396 print_file(file
, indent
, "\n");
2399 static unsigned int get_required_buffer_size_type(
2400 const type_t
*type
, const char *name
, unsigned int *alignment
)
2403 if (is_user_type(type
))
2406 const type_t
*utype
= get_user_type(type
, &uname
);
2407 return get_required_buffer_size_type(utype
, uname
, alignment
);
2431 case RPC_FC_ERROR_STATUS_T
:
2441 case RPC_FC_BIND_PRIMITIVE
:
2445 case RPC_FC_PSTRUCT
:
2449 if (!type
->fields
) return 0;
2450 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2452 unsigned int alignment
;
2453 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2461 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2462 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2465 case RPC_FC_SMFARRAY
:
2466 case RPC_FC_LGFARRAY
:
2467 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2475 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2477 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2478 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2481 if (!in_attr
&& !out_attr
)
2486 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2487 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2493 if (pass
== PASS_OUT
)
2495 if (out_attr
&& is_ptr(var
->type
))
2497 type_t
*type
= var
->type
;
2499 if (type
->type
== RPC_FC_STRUCT
)
2502 unsigned int size
= 36;
2504 if (!type
->fields
) return size
;
2505 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2508 size
+= get_required_buffer_size_type(
2509 field
->type
, field
->name
, &align
);
2518 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2519 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2521 if (is_ptr(var
->type
))
2523 type_t
*type
= var
->type
;
2525 if (is_base_type(type
->type
))
2529 else if (type
->type
== RPC_FC_STRUCT
)
2531 unsigned int size
= 36;
2534 if (!type
->fields
) return size
;
2535 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2538 size
+= get_required_buffer_size_type(
2539 field
->type
, field
->name
, &align
);
2546 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2550 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2553 unsigned int total_size
= 0, alignment
;
2557 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2559 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2560 total_size
+= alignment
;
2564 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
2566 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
2567 total_size
+= alignment
;
2572 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2573 enum remoting_phase phase
,
2574 const var_t
*var
, unsigned int type_offset
)
2576 const char *function
;
2579 case PHASE_BUFFERSIZE
:
2580 function
= "BufferSize";
2583 function
= "Marshall";
2585 case PHASE_UNMARSHAL
:
2586 function
= "Unmarshall";
2596 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2598 print_file(file
, indent
, "&_StubMsg,\n");
2599 print_file(file
, indent
, "%s%s%s%s,\n",
2600 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2601 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2602 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2604 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2605 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2606 if (phase
== PHASE_UNMARSHAL
)
2607 print_file(file
, indent
, "0);\n");
2611 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2612 enum pass pass
, const var_t
*var
,
2613 const char *varname
)
2615 type_t
*type
= var
->type
;
2617 unsigned int alignment
= 0;
2618 unsigned char rtype
;
2620 /* no work to do for other phases, buffer sizing is done elsewhere */
2621 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2624 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2648 case RPC_FC_ERROR_STATUS_T
:
2660 case RPC_FC_BIND_PRIMITIVE
:
2661 /* no marshalling needed */
2665 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2669 if (phase
== PHASE_MARSHAL
)
2670 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2671 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2672 alignment
- 1, alignment
- 1);
2674 if (phase
== PHASE_MARSHAL
)
2676 print_file(file
, indent
, "*(");
2677 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2679 fprintf(file
, " *)_StubMsg.Buffer = *");
2681 fprintf(file
, " *)_StubMsg.Buffer = ");
2682 fprintf(file
, "%s", varname
);
2683 fprintf(file
, ";\n");
2685 else if (phase
== PHASE_UNMARSHAL
)
2687 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2688 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2689 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2690 print_file(file
, indent
, "{\n");
2691 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2692 print_file(file
, indent
, "}\n");
2693 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2694 print_file(file
, indent
, "");
2696 print_file(file
, indent
, "*");
2697 fprintf(file
, "%s", varname
);
2698 if (pass
== PASS_IN
&& is_ptr(type
))
2699 fprintf(file
, " = (");
2701 fprintf(file
, " = *(");
2702 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2703 fprintf(file
, " *)_StubMsg.Buffer;\n");
2706 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2707 write_type_decl(file
, var
->type
, NULL
);
2708 fprintf(file
, ");\n");
2711 /* returns whether the MaxCount, Offset or ActualCount members need to be
2712 * filled in for the specified phase */
2713 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2715 return (phase
!= PHASE_UNMARSHAL
);
2718 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2722 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2728 error("%s: multidimensional conformant"
2729 " arrays not supported at the top level\n",
2736 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2737 enum pass pass
, enum remoting_phase phase
,
2740 int in_attr
, out_attr
, pointer_type
;
2741 const type_t
*type
= var
->type
;
2742 unsigned char rtype
;
2743 size_t start_offset
= type
->typestring_offset
;
2745 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2747 pointer_type
= RPC_FC_RP
;
2749 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2750 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2751 if (!in_attr
&& !out_attr
)
2754 if (phase
!= PHASE_FREE
)
2758 if (!in_attr
) return;
2761 if (!out_attr
) return;
2769 if (is_context_handle(type
))
2771 if (phase
== PHASE_MARSHAL
)
2773 if (pass
== PASS_IN
)
2775 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2776 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2777 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type
) ? "*" : "", var
->name
);
2778 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2782 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2783 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2784 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2785 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2786 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2789 else if (phase
== PHASE_UNMARSHAL
)
2791 if (pass
== PASS_OUT
)
2794 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2795 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2796 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2797 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2798 print_file(file
, indent
+ 1, "_Handle);\n");
2802 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2803 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2804 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2808 else if (is_user_type(var
->type
))
2810 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2812 else if (is_string_type(var
->attrs
, var
->type
))
2814 if (is_array(type
) && !is_conformant_array(type
))
2815 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2818 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2820 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2821 write_expr(file
, type
->size_is
, 1);
2822 fprintf(file
, ";\n");
2825 if ((phase
== PHASE_FREE
) || (pointer_type
== RPC_FC_UP
))
2826 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2827 start_offset
- (type
->size_is
? 4 : 2));
2829 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2833 else if (is_array(type
))
2835 unsigned char tc
= type
->type
;
2836 const char *array_type
= "FixedArray";
2838 /* We already have the size_is expression since it's at the
2839 top level, but do checks for multidimensional conformant
2840 arrays. When we handle them, we'll need to extend this
2841 function to return a list, and then we'll actually use
2842 the return value. */
2843 get_size_is_expr(type
, var
->name
);
2845 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2847 if (is_size_needed_for_phase(phase
))
2849 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2850 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2851 write_expr(file
, type
->length_is
, 1);
2852 fprintf(file
, ";\n\n");
2854 array_type
= "VaryingArray";
2856 else if (tc
== RPC_FC_CARRAY
)
2858 if (is_size_needed_for_phase(phase
))
2860 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2861 write_expr(file
, type
->size_is
, 1);
2862 fprintf(file
, ";\n\n");
2864 array_type
= "ConformantArray";
2866 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2868 if (is_size_needed_for_phase(phase
))
2872 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2873 write_expr(file
, type
->size_is
, 1);
2874 fprintf(file
, ";\n");
2876 if (type
->length_is
)
2878 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2879 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2880 write_expr(file
, type
->length_is
, 1);
2881 fprintf(file
, ";\n\n");
2884 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2886 : "ConformantVaryingArray");
2889 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2890 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2891 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2893 /* these are all unmarshalled by allocating memory */
2894 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2895 type
->type
== RPC_FC_CVARRAY
||
2896 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2897 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2899 print_file(file
, indent
, "if (%s)\n", var
->name
);
2901 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2905 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2907 if (phase
!= PHASE_FREE
)
2908 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2910 else if (!is_ptr(var
->type
))
2915 case RPC_FC_PSTRUCT
:
2916 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2918 case RPC_FC_CSTRUCT
:
2919 case RPC_FC_CPSTRUCT
:
2920 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2922 case RPC_FC_CVSTRUCT
:
2923 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2925 case RPC_FC_BOGUS_STRUCT
:
2926 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2929 if (is_base_type( var
->type
->ref
->type
))
2931 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2933 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2935 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2936 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2941 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2943 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2944 write_expr( file
, iid
, 1 );
2945 fprintf( file
, ";\n\n" );
2947 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2951 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2956 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2958 if (phase
!= PHASE_FREE
)
2959 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2961 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2963 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2964 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2969 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2971 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2973 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2974 write_expr( file
, iid
, 1 );
2975 fprintf( file
, ";\n\n" );
2979 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2980 write_expr(file
, sx
, 1);
2981 fprintf(file
, ";\n\n");
2983 if (var
->type
->ref
->type
== RPC_FC_IP
)
2984 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
2986 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2989 fprintf(file
, "\n");
2992 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
2993 enum pass pass
, enum remoting_phase phase
)
2995 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
2997 unsigned int size
= get_function_buffer_size( func
, pass
);
2998 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
3001 if (pass
== PASS_RETURN
)
3005 var
.name
= xstrdup( "_RetVal" );
3006 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
3014 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3015 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
3020 size_t get_size_procformatstring_var(const var_t
*var
)
3022 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
3026 size_t get_size_procformatstring_func(const func_t
*func
)
3031 /* argument list size */
3033 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3034 size
+= get_size_procformatstring_var(var
);
3036 /* return value size */
3037 if (is_void(func
->def
->type
))
3038 size
+= 2; /* FC_END and FC_PAD */
3040 size
+= get_size_procformatstring_var(func
->def
);
3045 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3047 const ifref_t
*iface
;
3051 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
3053 if (!pred(iface
->iface
))
3056 if (iface
->iface
->funcs
)
3057 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
3058 if (!is_local(func
->def
->attrs
))
3059 size
+= get_size_procformatstring_func( func
);
3064 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3066 set_all_tfswrite(FALSE
);
3067 return process_tfs(NULL
, ifaces
, pred
);
3070 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3071 const var_list_t
*fields
, const char *structvar
)
3077 fprintf(h
, "%lu", e
->u
.lval
);
3080 fprintf(h
, "0x%lx", e
->u
.lval
);
3083 fprintf(h
, "%#.15g", e
->u
.dval
);
3085 case EXPR_TRUEFALSE
:
3087 fprintf(h
, "FALSE");
3091 case EXPR_IDENTIFIER
:
3094 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3095 if (!strcmp(e
->u
.sval
, field
->name
))
3097 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3101 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3106 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3110 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3114 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3118 write_type_decl(h
, e
->u
.tref
, NULL
);
3120 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3123 fprintf(h
, "sizeof(");
3124 write_type_decl(h
, e
->u
.tref
, NULL
);
3135 if (brackets
) fprintf(h
, "(");
3136 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3138 case EXPR_SHL
: fprintf(h
, " << "); break;
3139 case EXPR_SHR
: fprintf(h
, " >> "); break;
3140 case EXPR_MUL
: fprintf(h
, " * "); break;
3141 case EXPR_DIV
: fprintf(h
, " / "); break;
3142 case EXPR_ADD
: fprintf(h
, " + "); break;
3143 case EXPR_SUB
: fprintf(h
, " - "); break;
3144 case EXPR_AND
: fprintf(h
, " & "); break;
3145 case EXPR_OR
: fprintf(h
, " | "); break;
3148 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3149 if (brackets
) fprintf(h
, ")");
3152 if (brackets
) fprintf(h
, "(");
3153 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3155 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3157 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3158 if (brackets
) fprintf(h
, ")");
3160 case EXPR_ADDRESSOF
:
3162 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3168 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3170 int in_attr
, out_attr
;
3172 const var_t
*def
= func
->def
;
3175 /* declare return value '_RetVal' */
3176 if (!is_void(def
->type
))
3178 print_file(file
, indent
, "");
3179 write_type_decl_left(file
, def
->type
);
3180 fprintf(file
, " _RetVal;\n");
3186 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3188 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3190 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3191 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3192 if (!out_attr
&& !in_attr
)
3195 if (is_context_handle(var
->type
))
3196 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3199 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3201 print_file(file
, indent
, "");
3202 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3204 fprintf(file
, ";\n");
3207 print_file(file
, indent
, "");
3208 write_type_decl_left(file
, var
->type
);
3210 if (var
->type
->declarray
) {
3211 fprintf(file
, "( *");
3212 write_name(file
, var
);
3213 fprintf(file
, " )");
3215 write_name(file
, var
);
3216 write_type_right(file
, var
->type
, FALSE
);
3217 fprintf(file
, ";\n");
3219 if (decl_indirect(var
->type
))
3220 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3221 var
->name
, var
->name
);
3227 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3229 int in_attr
, out_attr
;
3236 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3238 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3239 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3240 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3241 if (!out_attr
&& !in_attr
)
3246 print_file(file
, indent
, "");
3247 write_name(file
, var
);
3249 if (is_context_handle(var
->type
))
3251 fprintf(file
, " = NdrContextHandleInitialize(\n");
3252 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3253 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3254 var
->type
->typestring_offset
);
3256 else if (var
->type
->size_is
)
3258 unsigned int size
, align
= 0;
3259 type_t
*type
= var
->type
;
3261 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3262 for ( ; type
->size_is
; type
= type
->ref
)
3264 write_expr(file
, type
->size_is
, TRUE
);
3265 fprintf(file
, " * ");
3267 size
= type_memsize(type
, &align
);
3268 fprintf(file
, "%u);\n", size
);
3270 else if (!is_string
)
3272 fprintf(file
, " = &_W%u;\n", i
);
3273 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3274 print_file(file
, indent
, "_W%u = 0;\n", i
);
3282 fprintf(file
, "\n");
3286 int write_expr_eval_routines(FILE *file
, const char *iface
)
3288 static const char *var_name
= "pS";
3290 struct expr_eval_routine
*eval
;
3291 unsigned short callback_offset
= 0;
3293 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3295 const char *name
= eval
->structure
->name
;
3296 const var_list_t
*fields
= eval
->structure
->fields
;
3299 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3300 iface
, name
, callback_offset
);
3301 print_file(file
, 0, "{\n");
3302 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3303 name
, var_name
, name
, eval
->baseoff
);
3304 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3305 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3306 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3307 fprintf(file
, ";\n");
3308 print_file(file
, 0, "}\n\n");
3314 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3316 struct expr_eval_routine
*eval
;
3317 struct expr_eval_routine
*cursor
;
3318 unsigned short callback_offset
= 0;
3320 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3321 fprintf(file
, "{\n");
3323 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3325 const char *name
= eval
->structure
->name
;
3326 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3328 list_remove(&eval
->entry
);
3332 fprintf(file
, "};\n\n");
3335 void write_user_quad_list(FILE *file
)
3339 if (list_empty(&user_type_list
))
3342 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3343 fprintf(file
, "{\n");
3344 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3346 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3347 print_file(file
, 1, "{\n");
3348 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3349 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3350 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3351 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3352 print_file(file
, 1, "}%s\n", sep
);
3354 fprintf(file
, "};\n\n");
3357 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3359 const struct str_list_entry_t
*endpoint
;
3362 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3363 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3364 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3366 print_file( f
, 1, "{ (const unsigned char *)\"" );
3367 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3369 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3372 if (!*p
) goto error
;
3373 if (p
[1] != '[') goto error
;
3375 fprintf( f
, "\", (const unsigned char *)\"" );
3376 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3378 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3381 if (*p
!= ']') goto error
;
3382 fprintf( f
, "\" },\n" );
3384 print_file( f
, 0, "};\n\n" );
3388 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);