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
);
62 const char *string_of_type(unsigned char type
)
66 case RPC_FC_BYTE
: return "FC_BYTE";
67 case RPC_FC_CHAR
: return "FC_CHAR";
68 case RPC_FC_SMALL
: return "FC_SMALL";
69 case RPC_FC_USMALL
: return "FC_USMALL";
70 case RPC_FC_WCHAR
: return "FC_WCHAR";
71 case RPC_FC_SHORT
: return "FC_SHORT";
72 case RPC_FC_USHORT
: return "FC_USHORT";
73 case RPC_FC_LONG
: return "FC_LONG";
74 case RPC_FC_ULONG
: return "FC_ULONG";
75 case RPC_FC_FLOAT
: return "FC_FLOAT";
76 case RPC_FC_HYPER
: return "FC_HYPER";
77 case RPC_FC_DOUBLE
: return "FC_DOUBLE";
78 case RPC_FC_ENUM16
: return "FC_ENUM16";
79 case RPC_FC_ENUM32
: return "FC_ENUM32";
80 case RPC_FC_IGNORE
: return "FC_IGNORE";
81 case RPC_FC_ERROR_STATUS_T
: return "FC_ERROR_STATUS_T";
82 case RPC_FC_RP
: return "FC_RP";
83 case RPC_FC_UP
: return "FC_UP";
84 case RPC_FC_OP
: return "FC_OP";
85 case RPC_FC_FP
: return "FC_FP";
86 case RPC_FC_ENCAPSULATED_UNION
: return "FC_ENCAPSULATED_UNION";
87 case RPC_FC_NON_ENCAPSULATED_UNION
: return "FC_NON_ENCAPSULATED_UNION";
88 case RPC_FC_STRUCT
: return "FC_STRUCT";
89 case RPC_FC_PSTRUCT
: return "FC_PSTRUCT";
90 case RPC_FC_CSTRUCT
: return "FC_CSTRUCT";
91 case RPC_FC_CPSTRUCT
: return "FC_CPSTRUCT";
92 case RPC_FC_CVSTRUCT
: return "FC_CVSTRUCT";
93 case RPC_FC_BOGUS_STRUCT
: return "FC_BOGUS_STRUCT";
94 case RPC_FC_SMFARRAY
: return "FC_SMFARRAY";
95 case RPC_FC_LGFARRAY
: return "FC_LGFARRAY";
96 case RPC_FC_SMVARRAY
: return "FC_SMVARRAY";
97 case RPC_FC_LGVARRAY
: return "FC_LGVARRAY";
98 case RPC_FC_CARRAY
: return "FC_CARRAY";
99 case RPC_FC_CVARRAY
: return "FC_CVARRAY";
100 case RPC_FC_BOGUS_ARRAY
: return "FC_BOGUS_ARRAY";
101 case RPC_FC_ALIGNM4
: return "FC_ALIGNM4";
102 case RPC_FC_ALIGNM8
: return "FC_ALIGNM8";
103 case RPC_FC_POINTER
: return "FC_POINTER";
104 case RPC_FC_C_CSTRING
: return "FC_C_CSTRING";
105 case RPC_FC_C_WSTRING
: return "FC_C_WSTRING";
106 case RPC_FC_CSTRING
: return "FC_CSTRING";
107 case RPC_FC_WSTRING
: return "FC_WSTRING";
109 error("string_of_type: unknown type 0x%02x\n", type
);
114 int is_struct(unsigned char type
)
121 case RPC_FC_CPSTRUCT
:
122 case RPC_FC_CVSTRUCT
:
123 case RPC_FC_BOGUS_STRUCT
:
130 static int is_non_complex_struct(const type_t
*type
)
137 case RPC_FC_CPSTRUCT
:
138 case RPC_FC_CVSTRUCT
:
145 int is_union(unsigned char type
)
149 case RPC_FC_ENCAPSULATED_UNION
:
150 case RPC_FC_NON_ENCAPSULATED_UNION
:
157 static int type_has_pointers(const type_t
*type
)
159 if (is_user_type(type
))
161 else if (is_ptr(type
))
163 else if (is_array(type
))
164 return type_has_pointers(type
->ref
);
165 else if (is_struct(type
->type
))
168 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
170 if (type_has_pointers(field
->type
))
174 else if (is_union(type
->type
))
178 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
180 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
181 fields
= uv
->type
->fields
;
184 fields
= type
->fields
;
185 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
187 if (field
->type
&& type_has_pointers(field
->type
))
195 static int type_has_full_pointer(const type_t
*type
)
197 if (is_user_type(type
))
199 else if (type
->type
== RPC_FC_FP
)
201 else if (is_ptr(type
))
203 else if (is_array(type
))
204 return type_has_full_pointer(type
->ref
);
205 else if (is_struct(type
->type
))
208 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
210 if (type_has_full_pointer(field
->type
))
214 else if (is_union(type
->type
))
218 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
220 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
221 fields
= uv
->type
->fields
;
224 fields
= type
->fields
;
225 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
227 if (field
->type
&& type_has_full_pointer(field
->type
))
235 static unsigned short user_type_offset(const char *name
)
238 unsigned short off
= 0;
239 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
241 if (strcmp(name
, ut
->name
) == 0)
245 error("user_type_offset: couldn't find type (%s)\n", name
);
249 static void update_tfsoff(type_t
*type
, unsigned int offset
, FILE *file
)
251 type
->typestring_offset
= offset
;
252 if (file
) type
->tfswrite
= FALSE
;
255 static void guard_rec(type_t
*type
)
257 /* types that contain references to themselves (like a linked list),
258 need to be shielded from infinite recursion when writing embedded
260 if (type
->typestring_offset
)
261 type
->tfswrite
= FALSE
;
263 type
->typestring_offset
= 1;
266 static type_t
*get_user_type(const type_t
*t
, const char **pname
)
270 type_t
*ut
= get_attrp(t
->attrs
, ATTR_WIREMARSHAL
);
278 if (t
->kind
== TKIND_ALIAS
)
285 int is_user_type(const type_t
*t
)
287 return get_user_type(t
, NULL
) != NULL
;
290 static int is_embedded_complex(const type_t
*type
)
292 unsigned char tc
= type
->type
;
293 return is_struct(tc
) || is_union(tc
) || is_array(type
) || is_user_type(type
)
294 || (is_ptr(type
) && type
->ref
->type
== RPC_FC_IP
);
297 static const char *get_context_handle_type_name(const type_t
*type
)
300 for (t
= type
; is_ptr(t
); t
= t
->ref
)
301 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
307 /* This is actually fairly involved to implement precisely, due to the
308 effects attributes may have and things like that. Right now this is
309 only used for optimization, so just check for a very small set of
310 criteria that guarantee the types are equivalent; assume every thing
311 else is different. */
312 static int compare_type(const type_t
*a
, const type_t
*b
)
317 && strcmp(a
->name
, b
->name
) == 0))
319 /* Ordering doesn't need to be implemented yet. */
323 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
327 if (a
->type
!= b
->type
)
328 return a
->type
- b
->type
;
335 return a
->u
.lval
- b
->u
.lval
;
337 return a
->u
.dval
- b
->u
.dval
;
338 case EXPR_IDENTIFIER
:
339 return strcmp(a
->u
.sval
, b
->u
.sval
);
341 ret
= compare_expr(a
->ref
, b
->ref
);
344 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
347 return compare_expr(a
->ext2
, b
->ext2
);
356 ret
= compare_expr(a
->ref
, b
->ref
);
359 return compare_expr(a
->u
.ext
, b
->u
.ext
);
361 ret
= compare_type(a
->u
.tref
, b
->u
.tref
);
369 return compare_expr(a
->ref
, b
->ref
);
371 return compare_type(a
->u
.tref
, b
->u
.tref
);
378 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
381 fprintf(file, "/* %2u */\n", typestring_offset); \
382 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
386 static void print_file(FILE *file
, int indent
, const char *format
, ...)
389 va_start(va
, format
);
390 print(file
, indent
, format
, va
);
394 void print(FILE *file
, int indent
, const char *format
, va_list va
)
398 if (format
[0] != '\n')
401 vfprintf(file
, format
, va
);
406 static void write_var_init(FILE *file
, int indent
, const type_t
*t
, const char *n
)
408 if (decl_indirect(t
))
409 print_file(file
, indent
, "MIDL_memset(&%s, 0, sizeof(%s));\n", n
, n
);
410 else if (is_ptr(t
) || is_array(t
))
411 print_file(file
, indent
, "%s = 0;\n", n
);
414 void write_parameters_init(FILE *file
, int indent
, const func_t
*func
)
418 if (!is_void(func
->def
->type
))
419 write_var_init(file
, indent
, func
->def
->type
, "_RetVal");
424 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
425 write_var_init(file
, indent
, var
->type
, var
->name
);
430 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
432 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
433 print_file(f
, indent
, "{\n");
434 print_file(f
, indent
+ 1, "short Pad;\n");
435 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
436 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
437 print_file(f
, indent
, "\n");
440 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, type_pred_t pred
)
442 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
443 get_size_typeformatstring(ifaces
, pred
));
445 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
446 get_size_procformatstring(ifaces
, pred
));
449 write_formatdesc(f
, indent
, "TYPE");
450 write_formatdesc(f
, indent
, "PROC");
452 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
453 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
454 print_file(f
, indent
, "\n");
457 static inline int is_base_type(unsigned char type
)
476 case RPC_FC_ERROR_STATUS_T
:
477 case RPC_FC_BIND_PRIMITIVE
:
485 int decl_indirect(const type_t
*t
)
487 return is_user_type(t
)
488 || (!is_base_type(t
->type
)
493 static size_t write_procformatstring_var(FILE *file
, int indent
,
494 const var_t
*var
, int is_return
)
497 const type_t
*type
= var
->type
;
499 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
500 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
502 if (!is_in
&& !is_out
) is_in
= TRUE
;
504 if (!type
->declarray
&& is_base_type(type
->type
))
507 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
509 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
511 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
513 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
514 size
= 2; /* includes param type prefix */
516 else if (is_base_type(type
->type
))
518 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
519 size
= 2; /* includes param type prefix */
523 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
530 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
531 else if (is_in
&& is_out
)
532 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
534 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
536 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
538 print_file(file
, indent
, "0x01,\n");
539 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
540 size
= 4; /* includes param type prefix */
545 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
547 const ifref_t
*iface
;
551 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
552 print_file(file
, indent
, "{\n");
554 print_file(file
, indent
, "0,\n");
555 print_file(file
, indent
, "{\n");
558 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
560 if (!pred(iface
->iface
))
563 if (iface
->iface
->funcs
)
566 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
568 if (is_local(func
->def
->attrs
)) continue;
569 /* emit argument data */
572 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
573 write_procformatstring_var(file
, indent
, var
, FALSE
);
576 /* emit return value data */
578 if (is_void(var
->type
))
580 print_file(file
, indent
, "0x5b, /* FC_END */\n");
581 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
584 write_procformatstring_var(file
, indent
, var
, TRUE
);
589 print_file(file
, indent
, "0x0\n");
591 print_file(file
, indent
, "}\n");
593 print_file(file
, indent
, "};\n");
594 print_file(file
, indent
, "\n");
597 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
599 if (is_base_type(type
->type
))
601 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
602 *typestring_offset
+= 1;
609 /* write conformance / variance descriptor */
610 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
611 unsigned int baseoff
, const type_t
*type
,
614 unsigned char operator_type
= 0;
615 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
616 const char *conftype_string
= "";
617 const char *operator_string
= "no operators";
618 const expr_t
*subexpr
;
622 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
628 /* Top-level conformance calculations are done inline. */
629 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
630 RPC_FC_TOP_LEVEL_CONFORMANCE
);
631 print_file (file
, 2, "0x0,\n");
632 print_file (file
, 2, "NdrFcShort(0x0),\n");
638 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
639 error("write_conf_or_var_desc: constant value %ld is greater than "
640 "the maximum constant size of %d\n", expr
->cval
,
641 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
643 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
644 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
645 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
646 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
651 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
653 conftype
= RPC_FC_POINTER_CONFORMANCE
;
654 conftype_string
= "field pointer, ";
658 switch (subexpr
->type
)
661 subexpr
= subexpr
->ref
;
662 operator_type
= RPC_FC_DEREFERENCE
;
663 operator_string
= "FC_DEREFERENCE";
666 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
668 subexpr
= subexpr
->ref
;
669 operator_type
= RPC_FC_DIV_2
;
670 operator_string
= "FC_DIV_2";
674 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
676 subexpr
= subexpr
->ref
;
677 operator_type
= RPC_FC_MULT_2
;
678 operator_string
= "FC_MULT_2";
682 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
684 subexpr
= subexpr
->ref
;
685 operator_type
= RPC_FC_SUB_1
;
686 operator_string
= "FC_SUB_1";
690 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
692 subexpr
= subexpr
->ref
;
693 operator_type
= RPC_FC_ADD_1
;
694 operator_string
= "FC_ADD_1";
701 if (subexpr
->type
== EXPR_IDENTIFIER
)
703 const type_t
*correlation_variable
= NULL
;
704 unsigned char correlation_variable_type
;
705 unsigned char param_type
= 0;
709 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
711 unsigned int align
= 0;
712 /* FIXME: take alignment into account */
713 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
715 correlation_variable
= var
->type
;
718 offset
+= type_memsize(var
->type
, &align
);
720 if (!correlation_variable
)
721 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
725 correlation_variable_type
= correlation_variable
->type
;
727 switch (correlation_variable_type
)
731 param_type
= RPC_FC_SMALL
;
735 param_type
= RPC_FC_USMALL
;
740 param_type
= RPC_FC_SHORT
;
743 param_type
= RPC_FC_USHORT
;
747 param_type
= RPC_FC_LONG
;
750 param_type
= RPC_FC_ULONG
;
756 if (sizeof(void *) == 4) /* FIXME */
757 param_type
= RPC_FC_LONG
;
759 param_type
= RPC_FC_HYPER
;
762 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
763 correlation_variable_type
);
766 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
767 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
768 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
769 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
774 unsigned int callback_offset
= 0;
775 struct expr_eval_routine
*eval
;
778 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
780 if (!strcmp (eval
->structure
->name
, structure
->name
)
781 && !compare_expr (eval
->expr
, expr
))
791 eval
= xmalloc (sizeof(*eval
));
792 eval
->structure
= structure
;
793 eval
->baseoff
= baseoff
;
795 list_add_tail (&expr_eval_routines
, &eval
->entry
);
798 if (callback_offset
> USHRT_MAX
)
799 error("Maximum number of callback routines reached\n");
801 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
802 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
803 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
808 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
810 int have_align
= FALSE
;
814 if (!fields
) return 0;
815 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
817 unsigned int falign
= 0;
818 size_t fsize
= type_memsize(v
->type
, &falign
);
824 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
828 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
832 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
834 size_t size
, maxs
= 0;
835 unsigned int align
= *pmaxa
;
838 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
840 /* we could have an empty default field with NULL type */
843 size
= type_memsize(v
->type
, &align
);
844 if (maxs
< size
) maxs
= size
;
845 if (*pmaxa
< align
) *pmaxa
= align
;
852 int get_padding(const var_list_t
*fields
)
854 unsigned short offset
= 0;
861 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
863 type_t
*ft
= f
->type
;
864 unsigned int align
= 0;
865 size_t size
= type_memsize(ft
, &align
);
868 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
872 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
875 size_t type_memsize(const type_t
*t
, unsigned int *align
)
879 if (t
->declarray
&& is_conformant_array(t
))
881 type_memsize(t
->ref
, align
);
884 else if (is_ptr(t
) || is_conformant_array(t
))
886 size
= sizeof(void *);
887 if (size
> *align
) *align
= size
;
889 else switch (t
->type
)
896 if (size
> *align
) *align
= size
;
903 if (size
> *align
) *align
= size
;
907 case RPC_FC_ERROR_STATUS_T
:
911 if (size
> *align
) *align
= size
;
916 if (size
> *align
) *align
= size
;
919 case RPC_FC_CVSTRUCT
:
920 case RPC_FC_CPSTRUCT
:
923 case RPC_FC_BOGUS_STRUCT
:
924 size
= fields_memsize(t
->fields
, align
);
926 case RPC_FC_ENCAPSULATED_UNION
:
927 case RPC_FC_NON_ENCAPSULATED_UNION
:
928 size
= union_memsize(t
->fields
, align
);
930 case RPC_FC_SMFARRAY
:
931 case RPC_FC_LGFARRAY
:
932 case RPC_FC_SMVARRAY
:
933 case RPC_FC_LGVARRAY
:
934 case RPC_FC_BOGUS_ARRAY
:
935 size
= t
->dim
* type_memsize(t
->ref
, align
);
938 error("type_memsize: Unknown type %d\n", t
->type
);
945 int is_full_pointer_function(const func_t
*func
)
948 if (type_has_full_pointer(func
->def
->type
))
952 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
953 if (type_has_full_pointer( var
->type
))
958 void write_full_pointer_init(FILE *file
, int indent
, const func_t
*func
, int is_server
)
960 print_file(file
, indent
, "_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
961 is_server
? "XLAT_SERVER" : "XLAT_CLIENT");
965 void write_full_pointer_free(FILE *file
, int indent
, const func_t
*func
)
967 print_file(file
, indent
, "NdrFullPointerXlatFree(_StubMsg.FullPtrXlatTables);\n");
971 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
973 short absoff
= type
->ref
->typestring_offset
;
974 short reloff
= absoff
- (offset
+ 2);
975 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
977 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
978 type
->type
, ptr_attr
, string_of_type(type
->type
));
979 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
980 reloff
, reloff
, absoff
);
984 static unsigned char conf_string_type_of_char_type(unsigned char t
)
990 return RPC_FC_C_CSTRING
;
992 return RPC_FC_C_WSTRING
;
995 error("string_type_of_char_type: unrecognized type %d\n", t
);
999 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
1002 = is_string_type(type
->attrs
, type
)
1003 ? conf_string_type_of_char_type(type
->ref
->type
)
1005 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
1006 type
->type
, string_of_type(type
->type
));
1007 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
1008 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1012 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
1014 print_file(file
, 0, "/* %u (", tfsoff
);
1015 write_type_decl(file
, t
, NULL
);
1016 print_file(file
, 0, ") */\n");
1019 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
1021 unsigned int offset
= *typestring_offset
;
1023 print_start_tfs_comment(file
, type
, offset
);
1024 update_tfsoff(type
, offset
, file
);
1026 if (type
->ref
->typestring_offset
)
1027 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
1028 else if (is_base_type(type
->ref
->type
))
1029 *typestring_offset
+= write_simple_pointer(file
, type
);
1034 static int processed(const type_t
*type
)
1036 return type
->typestring_offset
&& !type
->tfswrite
;
1039 static int user_type_has_variable_size(const type_t
*t
)
1046 case RPC_FC_PSTRUCT
:
1047 case RPC_FC_CSTRUCT
:
1048 case RPC_FC_CPSTRUCT
:
1049 case RPC_FC_CVSTRUCT
:
1052 /* Note: Since this only applies to user types, we can't have a conformant
1053 array here, and strings should get filed under pointer in this case. */
1057 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1059 unsigned int start
, absoff
, flags
;
1060 unsigned int align
= 0, ualign
= 0;
1062 type_t
*utype
= get_user_type(type
, &name
);
1063 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
1064 size_t size
= type_memsize(type
, &align
);
1065 unsigned short funoff
= user_type_offset(name
);
1070 if (is_base_type(utype
->type
))
1073 print_start_tfs_comment(file
, utype
, absoff
);
1074 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
1075 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1080 if (!processed(utype
))
1081 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
1082 absoff
= utype
->typestring_offset
;
1085 if (utype
->type
== RPC_FC_RP
)
1087 else if (utype
->type
== RPC_FC_UP
)
1093 update_tfsoff(type
, start
, file
);
1094 print_start_tfs_comment(file
, type
, start
);
1095 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
1096 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1097 flags
| (align
- 1), align
- 1, flags
);
1098 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
1099 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
1100 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
1102 reloff
= absoff
- *tfsoff
;
1103 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
1107 static void write_member_type(FILE *file
, const type_t
*cont
,
1108 const attr_list_t
*attrs
, const type_t
*type
,
1109 unsigned int *corroff
, unsigned int *tfsoff
)
1111 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1116 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1123 absoff
= type
->typestring_offset
;
1125 reloff
= absoff
- (*tfsoff
+ 2);
1127 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1128 /* FIXME: actually compute necessary padding */
1129 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1130 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1131 reloff
, reloff
, absoff
);
1134 else if (is_ptr(type
) || is_conformant_array(type
))
1136 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1139 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1142 else if (!write_base_type(file
, type
, tfsoff
))
1143 error("Unsupported member type 0x%x\n", type
->type
);
1146 static void write_end(FILE *file
, unsigned int *tfsoff
)
1148 if (*tfsoff
% 2 == 0)
1150 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1153 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1157 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1159 unsigned int offset
= 0;
1160 var_list_t
*fs
= type
->fields
;
1163 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1165 unsigned int align
= 0;
1166 type_t
*ft
= f
->type
;
1167 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1169 unsigned int absoff
= ft
->typestring_offset
;
1170 short reloff
= absoff
- (*tfsoff
+ 6);
1171 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1172 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1173 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1174 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1175 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1176 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1177 reloff
, reloff
, absoff
);
1181 /* FIXME: take alignment into account */
1182 offset
+= type_memsize(ft
, &align
);
1186 static int write_no_repeat_pointer_descriptions(
1187 FILE *file
, type_t
*type
,
1188 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1189 unsigned int *typestring_offset
)
1194 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1196 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1197 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1199 /* pointer instance */
1200 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1201 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1202 *typestring_offset
+= 6;
1205 write_pointer_tfs(file
, type
, typestring_offset
);
1208 unsigned absoff
= type
->typestring_offset
;
1209 short reloff
= absoff
- (*typestring_offset
+ 2);
1210 /* FIXME: get pointer attributes from field */
1211 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1212 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1213 reloff
, reloff
, absoff
);
1214 *typestring_offset
+= 4;
1218 *offset_in_memory
+= type_memsize(type
, &align
);
1219 /* FIXME: is there a case where these two are different? */
1221 *offset_in_buffer
+= type_memsize(type
, &align
);
1226 if (is_non_complex_struct(type
))
1229 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1230 written
+= write_no_repeat_pointer_descriptions(
1232 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1237 *offset_in_memory
+= type_memsize(type
, &align
);
1238 /* FIXME: is there a case where these two are different? */
1240 *offset_in_buffer
+= type_memsize(type
, &align
);
1246 static int write_pointer_description_offsets(
1247 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1248 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1249 unsigned int *typestring_offset
)
1254 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1256 if (offset_in_memory
&& offset_in_buffer
)
1258 /* pointer instance */
1259 /* FIXME: sometimes from end of structure, sometimes from beginning */
1260 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1261 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1264 *offset_in_memory
+= type_memsize(type
, &align
);
1265 /* FIXME: is there a case where these two are different? */
1267 *offset_in_buffer
+= type_memsize(type
, &align
);
1269 *typestring_offset
+= 4;
1271 if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1272 write_pointer_tfs(file
, type
, typestring_offset
);
1274 error("write_pointer_description_offsets: type format string unknown\n");
1281 return write_pointer_description_offsets(
1282 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1285 else if (is_non_complex_struct(type
))
1287 /* otherwise search for interesting fields to parse */
1289 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1291 written
+= write_pointer_description_offsets(
1292 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1299 if (offset_in_memory
)
1300 *offset_in_memory
+= type_memsize(type
, &align
);
1301 /* FIXME: is there a case where these two are different? */
1303 if (offset_in_buffer
)
1304 *offset_in_buffer
+= type_memsize(type
, &align
);
1310 /* Note: if file is NULL return value is number of pointers to write, else
1311 * it is the number of type format characters written */
1312 static int write_fixed_array_pointer_descriptions(
1313 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1314 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1315 unsigned int *typestring_offset
)
1318 int pointer_count
= 0;
1320 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1322 unsigned int temp
= 0;
1323 /* unfortunately, this needs to be done in two passes to avoid
1324 * writing out redundant FC_FIXED_REPEAT descriptions */
1325 pointer_count
= write_pointer_description_offsets(
1326 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1327 if (pointer_count
> 0)
1329 unsigned int increment_size
;
1330 size_t offset_of_array_pointer_mem
= 0;
1331 size_t offset_of_array_pointer_buf
= 0;
1334 increment_size
= type_memsize(type
->ref
, &align
);
1336 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1337 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1338 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1339 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1340 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1341 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1342 *typestring_offset
+= 10;
1344 pointer_count
= write_pointer_description_offsets(
1345 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1346 &offset_of_array_pointer_buf
, typestring_offset
);
1349 else if (is_struct(type
->type
))
1352 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1354 pointer_count
+= write_fixed_array_pointer_descriptions(
1355 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1362 if (offset_in_memory
)
1363 *offset_in_memory
+= type_memsize(type
, &align
);
1364 /* FIXME: is there a case where these two are different? */
1366 if (offset_in_buffer
)
1367 *offset_in_buffer
+= type_memsize(type
, &align
);
1370 return pointer_count
;
1373 /* Note: if file is NULL return value is number of pointers to write, else
1374 * it is the number of type format characters written */
1375 static int write_conformant_array_pointer_descriptions(
1376 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1377 size_t offset_in_memory
, unsigned int *typestring_offset
)
1380 int pointer_count
= 0;
1382 if (is_conformant_array(type
) && !type
->length_is
)
1384 unsigned int temp
= 0;
1385 /* unfortunately, this needs to be done in two passes to avoid
1386 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1387 pointer_count
= write_pointer_description_offsets(
1388 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1389 if (pointer_count
> 0)
1391 unsigned int increment_size
;
1392 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1393 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1396 increment_size
= type_memsize(type
->ref
, &align
);
1398 if (increment_size
> USHRT_MAX
)
1399 error("array size of %u bytes is too large\n", increment_size
);
1401 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1402 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1403 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1404 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1405 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1406 *typestring_offset
+= 8;
1408 pointer_count
= write_pointer_description_offsets(
1409 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1410 &offset_of_array_pointer_buf
, typestring_offset
);
1414 return pointer_count
;
1417 /* Note: if file is NULL return value is number of pointers to write, else
1418 * it is the number of type format characters written */
1419 static int write_varying_array_pointer_descriptions(
1420 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1421 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1422 unsigned int *typestring_offset
)
1425 int pointer_count
= 0;
1427 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1429 if (is_array(type
) && type
->length_is
)
1431 unsigned int temp
= 0;
1432 /* unfortunately, this needs to be done in two passes to avoid
1433 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1434 pointer_count
= write_pointer_description_offsets(
1435 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1436 if (pointer_count
> 0)
1438 unsigned int increment_size
;
1439 size_t offset_of_array_pointer_mem
= 0;
1440 size_t offset_of_array_pointer_buf
= 0;
1443 increment_size
= type_memsize(type
->ref
, &align
);
1445 if (increment_size
> USHRT_MAX
)
1446 error("array size of %u bytes is too large\n", increment_size
);
1448 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1449 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1450 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1451 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1452 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1453 *typestring_offset
+= 8;
1455 pointer_count
= write_pointer_description_offsets(
1456 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1457 &offset_of_array_pointer_buf
, typestring_offset
);
1460 else if (is_struct(type
->type
))
1463 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1465 pointer_count
+= write_varying_array_pointer_descriptions(
1466 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1473 if (offset_in_memory
)
1474 *offset_in_memory
+= type_memsize(type
, &align
);
1475 /* FIXME: is there a case where these two are different? */
1477 if (offset_in_buffer
)
1478 *offset_in_buffer
+= type_memsize(type
, &align
);
1481 return pointer_count
;
1484 static void write_pointer_description(FILE *file
, type_t
*type
,
1485 unsigned int *typestring_offset
)
1487 size_t offset_in_buffer
;
1488 size_t offset_in_memory
;
1490 /* pass 1: search for single instance of a pointer (i.e. don't descend
1492 if (!is_array(type
))
1494 offset_in_memory
= 0;
1495 offset_in_buffer
= 0;
1496 write_no_repeat_pointer_descriptions(
1498 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1501 /* pass 2: search for pointers in fixed arrays */
1502 offset_in_memory
= 0;
1503 offset_in_buffer
= 0;
1504 write_fixed_array_pointer_descriptions(
1506 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1508 /* pass 3: search for pointers in conformant only arrays (but don't descend
1509 * into conformant varying or varying arrays) */
1510 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1511 write_conformant_array_pointer_descriptions(
1512 file
, NULL
, type
, 0, typestring_offset
);
1513 else if (type
->type
== RPC_FC_CPSTRUCT
)
1515 unsigned int align
= 0;
1516 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1517 write_conformant_array_pointer_descriptions(
1519 type_memsize(type
, &align
),
1523 /* pass 4: search for pointers in varying arrays */
1524 offset_in_memory
= 0;
1525 offset_in_buffer
= 0;
1526 write_varying_array_pointer_descriptions(
1528 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1531 int is_declptr(const type_t
*t
)
1533 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1536 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1538 const char *name
, unsigned int *typestring_offset
,
1541 size_t start_offset
;
1542 unsigned char rtype
;
1544 if (toplevel
&& is_declptr(type
))
1546 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1547 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1549 pointer_type
= RPC_FC_RP
;
1550 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1551 pointer_type
, flag
, string_of_type(pointer_type
),
1552 flag
? " [simple_pointer]" : "");
1553 *typestring_offset
+= 2;
1556 print_file(file
, 2, "NdrFcShort(0x2),\n");
1557 *typestring_offset
+= 2;
1561 start_offset
= *typestring_offset
;
1562 update_tfsoff(type
, start_offset
, file
);
1564 rtype
= type
->ref
->type
;
1566 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1568 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1569 return start_offset
;
1572 if (type
->declarray
&& !is_conformant_array(type
))
1574 /* FIXME: multi-dimensional array */
1575 if (0xffffuL
< type
->dim
)
1576 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1577 name
, 0xffffu
, type
->dim
- 0xffffu
);
1579 if (rtype
== RPC_FC_CHAR
)
1580 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1582 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1583 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1584 *typestring_offset
+= 2;
1586 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1587 *typestring_offset
+= 2;
1589 return start_offset
;
1591 else if (type
->size_is
)
1593 unsigned int align
= 0;
1595 if (rtype
== RPC_FC_CHAR
)
1596 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1598 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1599 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1600 *typestring_offset
+= 2;
1602 *typestring_offset
+= write_conf_or_var_desc(
1603 file
, current_structure
,
1604 (type
->declarray
&& current_structure
1605 ? type_memsize(current_structure
, &align
)
1607 type
, type
->size_is
);
1609 return start_offset
;
1613 if (rtype
== RPC_FC_WCHAR
)
1614 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1616 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1617 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1618 *typestring_offset
+= 2;
1620 return start_offset
;
1624 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1625 const char *name
, unsigned int *typestring_offset
)
1627 const expr_t
*length_is
= type
->length_is
;
1628 const expr_t
*size_is
= type
->size_is
;
1629 unsigned int align
= 0;
1631 size_t start_offset
;
1633 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1634 unsigned int baseoff
1635 = type
->declarray
&& current_structure
1636 ? type_memsize(current_structure
, &align
)
1640 pointer_type
= RPC_FC_RP
;
1642 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1645 has_pointer
= type_has_pointers(type
->ref
);
1648 size
= type_memsize((is_conformant_array(type
) ? type
->ref
: type
), &align
);
1650 start_offset
= *typestring_offset
;
1651 update_tfsoff(type
, start_offset
, file
);
1652 print_start_tfs_comment(file
, type
, start_offset
);
1653 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1654 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1655 *typestring_offset
+= 2;
1658 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1660 unsigned char tc
= type
->type
;
1662 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1664 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1665 *typestring_offset
+= 4;
1669 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1670 *typestring_offset
+= 2;
1673 if (is_conformant_array(type
))
1675 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1678 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1680 unsigned int elalign
= 0;
1681 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1683 if (type
->type
== RPC_FC_LGVARRAY
)
1685 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1686 *typestring_offset
+= 4;
1690 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1691 *typestring_offset
+= 2;
1694 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1695 *typestring_offset
+= 2;
1700 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1703 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1705 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1706 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1707 *typestring_offset
+= 2;
1708 write_pointer_description(file
, type
, typestring_offset
);
1709 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1710 *typestring_offset
+= 1;
1713 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1714 write_end(file
, typestring_offset
);
1718 unsigned int dim
= size_is
? 0 : type
->dim
;
1719 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1720 *typestring_offset
+= 2;
1722 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1725 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1727 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1728 write_end(file
, typestring_offset
);
1731 return start_offset
;
1734 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1736 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1737 const type_t
*ft
= last_field
->type
;
1739 if (ft
->declarray
&& is_conformant_array(ft
))
1742 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1743 return find_array_or_string_in_struct(last_field
->type
);
1748 static void write_struct_members(FILE *file
, const type_t
*type
,
1749 unsigned int *corroff
, unsigned int *typestring_offset
)
1752 unsigned short offset
= 0;
1756 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1758 type_t
*ft
= field
->type
;
1759 if (!ft
->declarray
|| !is_conformant_array(ft
))
1761 unsigned int align
= 0;
1762 size_t size
= type_memsize(ft
, &align
);
1765 if ((align
- 1) & offset
)
1767 unsigned char fc
= 0;
1771 fc
= RPC_FC_ALIGNM4
;
1774 fc
= RPC_FC_ALIGNM8
;
1777 error("write_struct_members: cannot align type %d\n", ft
->type
);
1779 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1780 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1781 *typestring_offset
+= 1;
1783 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1789 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1792 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1793 RPC_FC_STRUCTPAD1
+ padding
- 1,
1795 *typestring_offset
+= 1;
1798 write_end(file
, typestring_offset
);
1801 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1802 const char *name
, unsigned int *tfsoff
)
1804 const type_t
*save_current_structure
= current_structure
;
1805 unsigned int total_size
;
1807 size_t start_offset
;
1808 size_t array_offset
;
1809 int has_pointers
= 0;
1810 unsigned int align
= 0;
1811 unsigned int corroff
;
1815 current_structure
= type
;
1817 total_size
= type_memsize(type
, &align
);
1818 if (total_size
> USHRT_MAX
)
1819 error("structure size for %s exceeds %d bytes by %d bytes\n",
1820 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1822 if (type
->fields
) LIST_FOR_EACH_ENTRY(f
, type
->fields
, var_t
, entry
)
1823 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1825 if (!has_pointers
) has_pointers
= type_has_pointers(type
);
1827 array
= find_array_or_string_in_struct(type
);
1828 if (array
&& !processed(array
->type
))
1830 = is_attr(array
->attrs
, ATTR_STRING
)
1831 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
, FALSE
)
1832 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1835 write_descriptors(file
, type
, tfsoff
);
1837 start_offset
= *tfsoff
;
1838 update_tfsoff(type
, start_offset
, file
);
1839 print_start_tfs_comment(file
, type
, start_offset
);
1840 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1841 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1842 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1847 unsigned int absoff
= array
->type
->typestring_offset
;
1848 short reloff
= absoff
- *tfsoff
;
1849 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1850 reloff
, reloff
, absoff
);
1853 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1855 print_file(file
, 2, "NdrFcShort(0x0),\n");
1859 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1861 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1862 nothing is written to file yet. On the actual writing pass,
1863 this will have been updated. */
1864 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1865 short reloff
= absoff
- *tfsoff
;
1866 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1867 reloff
, reloff
, absoff
);
1870 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1871 (type
->type
== RPC_FC_CPSTRUCT
) ||
1872 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1874 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1875 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1877 write_pointer_description(file
, type
, tfsoff
);
1878 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1882 write_struct_members(file
, type
, &corroff
, tfsoff
);
1884 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1886 const var_list_t
*fs
= type
->fields
;
1889 type
->ptrdesc
= *tfsoff
;
1890 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1892 type_t
*ft
= f
->type
;
1894 write_pointer_tfs(file
, ft
, tfsoff
);
1895 else if (!ft
->declarray
&& is_conformant_array(ft
))
1897 unsigned int absoff
= ft
->typestring_offset
;
1898 short reloff
= absoff
- (*tfsoff
+ 2);
1899 int ptr_type
= get_attrv(f
->attrs
, ATTR_POINTERTYPE
);
1900 /* FIXME: We need to store pointer attributes for arrays
1901 so we don't lose pointer_default info. */
1903 ptr_type
= RPC_FC_UP
;
1904 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1905 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
1906 string_of_type(ptr_type
));
1907 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1908 reloff
, reloff
, absoff
);
1912 if (type
->ptrdesc
== *tfsoff
)
1916 current_structure
= save_current_structure
;
1917 return start_offset
;
1920 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1921 unsigned char flags
, size_t offset
,
1922 unsigned int *typeformat_offset
)
1924 size_t start_offset
= *typeformat_offset
;
1925 short reloff
= offset
- (*typeformat_offset
+ 2);
1926 int in_attr
, out_attr
;
1927 in_attr
= is_attr(attrs
, ATTR_IN
);
1928 out_attr
= is_attr(attrs
, ATTR_OUT
);
1929 if (!in_attr
&& !out_attr
) in_attr
= 1;
1931 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1934 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1937 string_of_type(pointer_type
));
1941 fprintf(file
, " [allocated_on_stack]");
1943 fprintf(file
, " [pointer_deref]");
1944 fprintf(file
, " */\n");
1947 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1948 *typeformat_offset
+= 4;
1950 return start_offset
;
1953 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1957 print_file(file
, 2, "NdrFcShort(0x0),\t/* No type */\n");
1959 else if (is_base_type(t
->type
))
1961 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1962 t
->type
, string_of_type(t
->type
));
1964 else if (t
->typestring_offset
)
1966 short reloff
= t
->typestring_offset
- *tfsoff
;
1967 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1968 reloff
, reloff
, t
->typestring_offset
);
1971 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1976 static size_t write_union_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1978 unsigned int align
= 0;
1979 unsigned int start_offset
;
1980 size_t size
= type_memsize(type
, &align
);
1983 type_t
*deftype
= NULL
;
1984 short nodeftype
= 0xffff;
1989 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1991 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
1992 fields
= uv
->type
->fields
;
1995 fields
= type
->fields
;
1997 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1999 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2001 nbranch
+= list_count(cases
);
2003 write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
, TRUE
, tfsoff
);
2006 start_offset
= *tfsoff
;
2007 update_tfsoff(type
, start_offset
, file
);
2008 print_start_tfs_comment(file
, type
, start_offset
);
2009 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
2011 const var_t
*sv
= LIST_ENTRY(list_head(type
->fields
), const var_t
, entry
);
2012 const type_t
*st
= sv
->type
;
2025 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
2026 print_file(file
, 2, "0x%x,\t/* Switch type= %s */\n",
2027 0x40 | st
->type
, string_of_type(st
->type
));
2031 error("union switch type must be an integer, char, or enum\n");
2034 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
2035 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
2038 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
2040 type_t
*ft
= f
->type
;
2041 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
2042 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
2045 if (cases
== NULL
&& !deflt
)
2046 error("union field %s with neither case nor default attribute\n", f
->name
);
2048 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
2050 /* MIDL doesn't check for duplicate cases, even though that seems
2051 like a reasonable thing to do, it just dumps them to the TFS
2052 like we're going to do here. */
2053 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
2055 write_branch_type(file
, ft
, tfsoff
);
2058 /* MIDL allows multiple default branches, even though that seems
2059 illogical, it just chooses the last one, which is what we will
2070 write_branch_type(file
, deftype
, tfsoff
);
2074 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
2078 return start_offset
;
2081 static size_t write_ip_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2082 unsigned int *typeformat_offset
)
2085 size_t start_offset
= *typeformat_offset
;
2086 expr_t
*iid
= get_attrp(attrs
, ATTR_IIDIS
);
2090 print_file(file
, 2, "0x2f, /* FC_IP */\n");
2091 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
2093 += write_conf_or_var_desc(file
, NULL
, 0, type
, iid
) + 2;
2097 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
2098 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
2101 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
2103 update_tfsoff(type
, start_offset
, file
);
2104 print_start_tfs_comment(file
, type
, start_offset
);
2105 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
2106 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2107 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
2108 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
2109 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
2110 for (i
= 0; i
< 8; ++i
)
2111 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
2114 fprintf(file
, "\n");
2116 *typeformat_offset
+= 18;
2118 return start_offset
;
2121 static size_t write_contexthandle_tfs(FILE *file
, const type_t
*type
,
2123 unsigned int *typeformat_offset
)
2125 size_t start_offset
= *typeformat_offset
;
2126 unsigned char flags
= 0;
2128 if (is_attr(current_iface
->attrs
, ATTR_STRICTCONTEXTHANDLE
))
2129 flags
|= NDR_STRICT_CONTEXT_HANDLE
;
2133 if (is_attr(var
->attrs
, ATTR_IN
))
2136 if (!is_attr(var
->attrs
, ATTR_OUT
))
2137 flags
|= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
;
2139 if (is_attr(var
->attrs
, ATTR_OUT
))
2142 WRITE_FCTYPE(file
, FC_BIND_CONTEXT
, *typeformat_offset
);
2143 print_file(file
, 2, "0x%x,\t/* Context flags: ", flags
);
2144 /* return and can't be null values overlap */
2145 if (((flags
& 0x21) != 0x21) && (flags
& NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
))
2146 print_file(file
, 0, "can't be null, ");
2147 if (flags
& NDR_CONTEXT_HANDLE_SERIALIZE
)
2148 print_file(file
, 0, "serialize, ");
2149 if (flags
& NDR_CONTEXT_HANDLE_NO_SERIALIZE
)
2150 print_file(file
, 0, "no serialize, ");
2151 if (flags
& NDR_STRICT_CONTEXT_HANDLE
)
2152 print_file(file
, 0, "strict, ");
2153 if ((flags
& 0x21) == 0x20)
2154 print_file(file
, 0, "out, ");
2155 if ((flags
& 0x21) == 0x21)
2156 print_file(file
, 0, "return, ");
2158 print_file(file
, 0, "in, ");
2160 print_file(file
, 0, "via ptr, ");
2161 print_file(file
, 0, "*/\n");
2162 print_file(file
, 2, "0, /* FIXME: rundown routine index*/\n");
2163 print_file(file
, 2, "0, /* FIXME: param num */\n");
2164 *typeformat_offset
+= 4;
2166 return start_offset
;
2169 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
2170 type_t
*type
, const var_t
*var
,
2171 unsigned int *typeformat_offset
)
2175 if (is_context_handle(type
))
2176 return write_contexthandle_tfs(file
, type
, var
, typeformat_offset
);
2178 if (is_user_type(type
))
2180 write_user_tfs(file
, type
, typeformat_offset
);
2181 return type
->typestring_offset
;
2184 if ((last_ptr(type
) || last_array(type
)) && is_ptrchain_attr(var
, ATTR_STRING
))
2185 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
, TRUE
);
2191 off
= write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2192 ptr_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2193 /* Top level pointers to conformant arrays may be handled specially
2194 since we can bypass the pointer, but if the array is buried
2195 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2196 always need to write the pointer. */
2197 if (!ptr_type
&& var
->type
!= type
)
2198 /* FIXME: This should use pointer_default, but the information
2199 isn't kept around for arrays. */
2200 ptr_type
= RPC_FC_UP
;
2201 if (ptr_type
&& ptr_type
!= RPC_FC_RP
)
2203 unsigned int absoff
= type
->typestring_offset
;
2204 short reloff
= absoff
- (*typeformat_offset
+ 2);
2205 off
= *typeformat_offset
;
2206 print_file(file
, 0, "/* %d */\n", off
);
2207 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
2208 string_of_type(ptr_type
));
2209 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2210 reloff
, reloff
, absoff
);
2211 *typeformat_offset
+= 4;
2218 /* basic types don't need a type format string */
2219 if (is_base_type(type
->type
))
2225 case RPC_FC_PSTRUCT
:
2226 case RPC_FC_CSTRUCT
:
2227 case RPC_FC_CPSTRUCT
:
2228 case RPC_FC_CVSTRUCT
:
2229 case RPC_FC_BOGUS_STRUCT
:
2230 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
2231 case RPC_FC_ENCAPSULATED_UNION
:
2232 case RPC_FC_NON_ENCAPSULATED_UNION
:
2233 return write_union_tfs(file
, type
, typeformat_offset
);
2235 case RPC_FC_BIND_PRIMITIVE
:
2239 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
2242 else if (last_ptr(type
))
2244 size_t start_offset
= *typeformat_offset
;
2245 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2246 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2247 const type_t
*base
= type
->ref
;
2249 if (base
->type
== RPC_FC_IP
2251 && is_attr(var
->attrs
, ATTR_IIDIS
)))
2253 return write_ip_tfs(file
, var
->attrs
, type
, typeformat_offset
);
2256 /* special case for pointers to base types */
2257 if (is_base_type(base
->type
))
2259 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2260 type
->type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
2261 string_of_type(type
->type
),
2262 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
2263 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
2264 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
2265 *typeformat_offset
+= 4;
2266 return start_offset
;
2270 assert(is_ptr(type
));
2272 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
2274 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
2275 return write_pointer_only_tfs(file
, var
->attrs
, type
->type
,
2276 !last_ptr(type
) ? 0x10 : 0,
2277 offset
, typeformat_offset
);
2280 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2281 const char *name
, int write_ptr
, unsigned int *tfsoff
)
2285 if (is_user_type(type
))
2287 write_user_tfs(file
, type
, tfsoff
);
2289 else if (is_ptr(type
))
2291 type_t
*ref
= type
->ref
;
2293 if (ref
->type
== RPC_FC_IP
2295 && is_attr(attrs
, ATTR_IIDIS
)))
2297 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2301 if (!processed(ref
) && !is_base_type(ref
->type
))
2302 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2305 write_pointer_tfs(file
, type
, tfsoff
);
2310 else if (last_array(type
) && is_attr(attrs
, ATTR_STRING
))
2312 write_string_tfs(file
, attrs
, type
, name
, tfsoff
, FALSE
);
2314 else if (type
->declarray
&& is_conformant_array(type
))
2315 ; /* conformant arrays and strings are handled specially */
2316 else if (is_array(type
))
2318 write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
2319 if (is_conformant_array(type
))
2322 else if (is_struct(type
->type
))
2324 if (!processed(type
))
2325 write_struct_tfs(file
, type
, name
, tfsoff
);
2327 else if (is_union(type
->type
))
2329 if (!processed(type
))
2330 write_union_tfs(file
, type
, tfsoff
);
2332 else if (!is_base_type(type
->type
))
2333 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2339 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2342 const ifref_t
*iface
;
2343 unsigned int typeformat_offset
= 2;
2345 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2347 if (!pred(iface
->iface
))
2350 if (iface
->iface
->funcs
)
2353 current_iface
= iface
;
2354 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2356 if (is_local(func
->def
->attrs
)) continue;
2358 current_func
= func
;
2360 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2363 write_typeformatstring_var(
2364 file
, 2, func
, var
->type
, var
,
2365 &typeformat_offset
),
2371 return typeformat_offset
+ 1;
2375 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2379 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2380 print_file(file
, indent
, "{\n");
2382 print_file(file
, indent
, "0,\n");
2383 print_file(file
, indent
, "{\n");
2385 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2387 set_all_tfswrite(TRUE
);
2388 process_tfs(file
, ifaces
, pred
);
2390 print_file(file
, indent
, "0x0\n");
2392 print_file(file
, indent
, "}\n");
2394 print_file(file
, indent
, "};\n");
2395 print_file(file
, indent
, "\n");
2398 static unsigned int get_required_buffer_size_type(
2399 const type_t
*type
, const char *name
, unsigned int *alignment
)
2402 if (is_user_type(type
))
2405 const type_t
*utype
= get_user_type(type
, &uname
);
2406 return get_required_buffer_size_type(utype
, uname
, alignment
);
2430 case RPC_FC_ERROR_STATUS_T
:
2440 case RPC_FC_BIND_PRIMITIVE
:
2444 case RPC_FC_PSTRUCT
:
2448 if (!type
->fields
) return 0;
2449 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2451 unsigned int alignment
;
2452 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2460 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2461 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2464 case RPC_FC_SMFARRAY
:
2465 case RPC_FC_LGFARRAY
:
2466 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2474 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2476 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2477 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2480 if (!in_attr
&& !out_attr
)
2485 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2486 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2492 if (pass
== PASS_OUT
)
2494 if (out_attr
&& is_ptr(var
->type
))
2496 type_t
*type
= var
->type
;
2498 if (type
->type
== RPC_FC_STRUCT
)
2501 unsigned int size
= 36;
2503 if (!type
->fields
) return size
;
2504 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2507 size
+= get_required_buffer_size_type(
2508 field
->type
, field
->name
, &align
);
2517 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2518 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2520 if (is_ptr(var
->type
))
2522 type_t
*type
= var
->type
;
2524 if (is_base_type(type
->type
))
2528 else if (type
->type
== RPC_FC_STRUCT
)
2530 unsigned int size
= 36;
2533 if (!type
->fields
) return size
;
2534 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2537 size
+= get_required_buffer_size_type(
2538 field
->type
, field
->name
, &align
);
2545 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2549 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2552 unsigned int total_size
= 0, alignment
;
2556 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2558 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2559 total_size
+= alignment
;
2563 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
2565 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
2566 total_size
+= alignment
;
2571 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2572 enum remoting_phase phase
,
2573 const var_t
*var
, unsigned int type_offset
)
2575 const char *function
;
2578 case PHASE_BUFFERSIZE
:
2579 function
= "BufferSize";
2582 function
= "Marshall";
2584 case PHASE_UNMARSHAL
:
2585 function
= "Unmarshall";
2595 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2597 print_file(file
, indent
, "&_StubMsg,\n");
2598 print_file(file
, indent
, "%s%s%s%s,\n",
2599 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2600 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2601 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2603 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2604 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2605 if (phase
== PHASE_UNMARSHAL
)
2606 print_file(file
, indent
, "0);\n");
2610 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2611 enum pass pass
, const var_t
*var
,
2612 const char *varname
)
2614 type_t
*type
= var
->type
;
2616 unsigned int alignment
= 0;
2617 unsigned char rtype
;
2619 /* no work to do for other phases, buffer sizing is done elsewhere */
2620 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2623 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2647 case RPC_FC_ERROR_STATUS_T
:
2659 case RPC_FC_BIND_PRIMITIVE
:
2660 /* no marshalling needed */
2664 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2668 if (phase
== PHASE_MARSHAL
)
2669 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2670 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2671 alignment
- 1, alignment
- 1);
2673 if (phase
== PHASE_MARSHAL
)
2675 print_file(file
, indent
, "*(");
2676 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2678 fprintf(file
, " *)_StubMsg.Buffer = *");
2680 fprintf(file
, " *)_StubMsg.Buffer = ");
2681 fprintf(file
, "%s", varname
);
2682 fprintf(file
, ";\n");
2684 else if (phase
== PHASE_UNMARSHAL
)
2686 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2687 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2688 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2689 print_file(file
, indent
, "{\n");
2690 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2691 print_file(file
, indent
, "}\n");
2692 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2693 print_file(file
, indent
, "");
2695 print_file(file
, indent
, "*");
2696 fprintf(file
, "%s", varname
);
2697 if (pass
== PASS_IN
&& is_ptr(type
))
2698 fprintf(file
, " = (");
2700 fprintf(file
, " = *(");
2701 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2702 fprintf(file
, " *)_StubMsg.Buffer;\n");
2705 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2706 write_type_decl(file
, var
->type
, NULL
);
2707 fprintf(file
, ");\n");
2710 /* returns whether the MaxCount, Offset or ActualCount members need to be
2711 * filled in for the specified phase */
2712 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2714 return (phase
!= PHASE_UNMARSHAL
);
2717 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2721 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2727 error("%s: multidimensional conformant"
2728 " arrays not supported at the top level\n",
2735 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2736 enum pass pass
, enum remoting_phase phase
,
2739 int in_attr
, out_attr
, pointer_type
;
2740 const type_t
*type
= var
->type
;
2741 unsigned char rtype
;
2742 size_t start_offset
= type
->typestring_offset
;
2744 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2746 pointer_type
= RPC_FC_RP
;
2748 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2749 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2750 if (!in_attr
&& !out_attr
)
2753 if (phase
!= PHASE_FREE
)
2757 if (!in_attr
) return;
2760 if (!out_attr
) return;
2768 if (is_context_handle(type
))
2770 if (phase
== PHASE_MARSHAL
)
2772 if (pass
== PASS_IN
)
2774 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2775 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2776 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type
) ? "*" : "", var
->name
);
2777 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2781 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2782 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2783 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2784 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2785 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2788 else if (phase
== PHASE_UNMARSHAL
)
2790 if (pass
== PASS_OUT
)
2793 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2794 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2795 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2796 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2797 print_file(file
, indent
+ 1, "_Handle);\n");
2801 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2802 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2803 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2807 else if (is_user_type(var
->type
))
2809 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2811 else if (is_string_type(var
->attrs
, var
->type
))
2813 if (is_array(type
) && !is_conformant_array(type
))
2814 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2817 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2819 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2820 write_expr(file
, type
->size_is
, 1);
2821 fprintf(file
, ";\n");
2824 if ((phase
== PHASE_FREE
) || (pointer_type
== RPC_FC_UP
))
2825 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2826 start_offset
- (type
->size_is
? 4 : 2));
2828 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2832 else if (is_array(type
))
2834 unsigned char tc
= type
->type
;
2835 const char *array_type
= "FixedArray";
2837 /* We already have the size_is expression since it's at the
2838 top level, but do checks for multidimensional conformant
2839 arrays. When we handle them, we'll need to extend this
2840 function to return a list, and then we'll actually use
2841 the return value. */
2842 get_size_is_expr(type
, var
->name
);
2844 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2846 if (is_size_needed_for_phase(phase
))
2848 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2849 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2850 write_expr(file
, type
->length_is
, 1);
2851 fprintf(file
, ";\n\n");
2853 array_type
= "VaryingArray";
2855 else if (tc
== RPC_FC_CARRAY
)
2857 if (is_size_needed_for_phase(phase
))
2859 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2860 write_expr(file
, type
->size_is
, 1);
2861 fprintf(file
, ";\n\n");
2863 array_type
= "ConformantArray";
2865 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2867 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");
2875 if (type
->length_is
)
2877 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2878 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2879 write_expr(file
, type
->length_is
, 1);
2880 fprintf(file
, ";\n\n");
2883 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2885 : "ConformantVaryingArray");
2888 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2889 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2890 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2892 /* these are all unmarshalled by allocating memory */
2893 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2894 type
->type
== RPC_FC_CVARRAY
||
2895 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2896 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2898 print_file(file
, indent
, "if (%s)\n", var
->name
);
2900 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2904 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2906 if (phase
!= PHASE_FREE
)
2907 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2909 else if (!is_ptr(var
->type
))
2914 case RPC_FC_PSTRUCT
:
2915 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2917 case RPC_FC_CSTRUCT
:
2918 case RPC_FC_CPSTRUCT
:
2919 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2921 case RPC_FC_CVSTRUCT
:
2922 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2924 case RPC_FC_BOGUS_STRUCT
:
2925 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2928 if (is_base_type( var
->type
->ref
->type
))
2930 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2932 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2934 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2935 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2940 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2942 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2943 write_expr( file
, iid
, 1 );
2944 fprintf( file
, ";\n\n" );
2946 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2950 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2955 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2957 if (phase
!= PHASE_FREE
)
2958 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2960 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2962 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2963 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2968 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2970 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2972 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2973 write_expr( file
, iid
, 1 );
2974 fprintf( file
, ";\n\n" );
2978 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2979 write_expr(file
, sx
, 1);
2980 fprintf(file
, ";\n\n");
2982 if (var
->type
->ref
->type
== RPC_FC_IP
)
2983 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
2985 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2988 fprintf(file
, "\n");
2991 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
2992 enum pass pass
, enum remoting_phase phase
)
2994 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
2996 unsigned int size
= get_function_buffer_size( func
, pass
);
2997 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
3000 if (pass
== PASS_RETURN
)
3004 var
.name
= xstrdup( "_RetVal" );
3005 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
3013 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3014 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
3019 size_t get_size_procformatstring_var(const var_t
*var
)
3021 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
3025 size_t get_size_procformatstring_func(const func_t
*func
)
3030 /* argument list size */
3032 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3033 size
+= get_size_procformatstring_var(var
);
3035 /* return value size */
3036 if (is_void(func
->def
->type
))
3037 size
+= 2; /* FC_END and FC_PAD */
3039 size
+= get_size_procformatstring_var(func
->def
);
3044 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3046 const ifref_t
*iface
;
3050 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
3052 if (!pred(iface
->iface
))
3055 if (iface
->iface
->funcs
)
3056 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
3057 if (!is_local(func
->def
->attrs
))
3058 size
+= get_size_procformatstring_func( func
);
3063 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3065 set_all_tfswrite(FALSE
);
3066 return process_tfs(NULL
, ifaces
, pred
);
3069 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3070 const var_list_t
*fields
, const char *structvar
)
3076 fprintf(h
, "%lu", e
->u
.lval
);
3079 fprintf(h
, "0x%lx", e
->u
.lval
);
3082 fprintf(h
, "%#.15g", e
->u
.dval
);
3084 case EXPR_TRUEFALSE
:
3086 fprintf(h
, "FALSE");
3090 case EXPR_IDENTIFIER
:
3093 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3094 if (!strcmp(e
->u
.sval
, field
->name
))
3096 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3100 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3105 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3109 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3113 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3117 write_type_decl(h
, e
->u
.tref
, NULL
);
3119 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3122 fprintf(h
, "sizeof(");
3123 write_type_decl(h
, e
->u
.tref
, NULL
);
3134 if (brackets
) fprintf(h
, "(");
3135 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3137 case EXPR_SHL
: fprintf(h
, " << "); break;
3138 case EXPR_SHR
: fprintf(h
, " >> "); break;
3139 case EXPR_MUL
: fprintf(h
, " * "); break;
3140 case EXPR_DIV
: fprintf(h
, " / "); break;
3141 case EXPR_ADD
: fprintf(h
, " + "); break;
3142 case EXPR_SUB
: fprintf(h
, " - "); break;
3143 case EXPR_AND
: fprintf(h
, " & "); break;
3144 case EXPR_OR
: fprintf(h
, " | "); break;
3147 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3148 if (brackets
) fprintf(h
, ")");
3151 if (brackets
) fprintf(h
, "(");
3152 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3154 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3156 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3157 if (brackets
) fprintf(h
, ")");
3159 case EXPR_ADDRESSOF
:
3161 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3167 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3169 int in_attr
, out_attr
;
3171 const var_t
*def
= func
->def
;
3174 /* declare return value '_RetVal' */
3175 if (!is_void(def
->type
))
3177 print_file(file
, indent
, "");
3178 write_type_decl_left(file
, def
->type
);
3179 fprintf(file
, " _RetVal;\n");
3185 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3187 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3189 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3190 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3191 if (!out_attr
&& !in_attr
)
3194 if (is_context_handle(var
->type
))
3195 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3198 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3200 print_file(file
, indent
, "");
3201 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3203 fprintf(file
, ";\n");
3206 print_file(file
, indent
, "");
3207 write_type_decl_left(file
, var
->type
);
3209 if (var
->type
->declarray
) {
3210 fprintf(file
, "( *");
3211 write_name(file
, var
);
3212 fprintf(file
, " )");
3214 write_name(file
, var
);
3215 write_type_right(file
, var
->type
, FALSE
);
3216 fprintf(file
, ";\n");
3218 if (decl_indirect(var
->type
))
3219 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3220 var
->name
, var
->name
);
3226 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3228 int in_attr
, out_attr
;
3235 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3237 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3238 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3239 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3240 if (!out_attr
&& !in_attr
)
3245 print_file(file
, indent
, "");
3246 write_name(file
, var
);
3248 if (is_context_handle(var
->type
))
3250 fprintf(file
, " = NdrContextHandleInitialize(\n");
3251 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3252 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3253 var
->type
->typestring_offset
);
3255 else if (var
->type
->size_is
)
3257 unsigned int size
, align
= 0;
3258 type_t
*type
= var
->type
;
3260 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3261 for ( ; type
->size_is
; type
= type
->ref
)
3263 write_expr(file
, type
->size_is
, TRUE
);
3264 fprintf(file
, " * ");
3266 size
= type_memsize(type
, &align
);
3267 fprintf(file
, "%u);\n", size
);
3269 else if (!is_string
)
3271 fprintf(file
, " = &_W%u;\n", i
);
3272 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3273 print_file(file
, indent
, "_W%u = 0;\n", i
);
3281 fprintf(file
, "\n");
3285 int write_expr_eval_routines(FILE *file
, const char *iface
)
3287 static const char *var_name
= "pS";
3289 struct expr_eval_routine
*eval
;
3290 unsigned short callback_offset
= 0;
3292 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3294 const char *name
= eval
->structure
->name
;
3295 const var_list_t
*fields
= eval
->structure
->fields
;
3298 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3299 iface
, name
, callback_offset
);
3300 print_file(file
, 0, "{\n");
3301 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3302 name
, var_name
, name
, eval
->baseoff
);
3303 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3304 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3305 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3306 fprintf(file
, ";\n");
3307 print_file(file
, 0, "}\n\n");
3313 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3315 struct expr_eval_routine
*eval
;
3316 struct expr_eval_routine
*cursor
;
3317 unsigned short callback_offset
= 0;
3319 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3320 fprintf(file
, "{\n");
3322 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3324 const char *name
= eval
->structure
->name
;
3325 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3327 list_remove(&eval
->entry
);
3331 fprintf(file
, "};\n\n");
3334 void write_user_quad_list(FILE *file
)
3338 if (list_empty(&user_type_list
))
3341 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3342 fprintf(file
, "{\n");
3343 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3345 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3346 print_file(file
, 1, "{\n");
3347 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3348 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3349 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3350 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3351 print_file(file
, 1, "}%s\n", sep
);
3353 fprintf(file
, "};\n\n");
3356 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3358 const struct str_list_entry_t
*endpoint
;
3361 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3362 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3363 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3365 print_file( f
, 1, "{ (const unsigned char *)\"" );
3366 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3368 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3371 if (!*p
) goto error
;
3372 if (p
[1] != '[') goto error
;
3374 fprintf( f
, "\", (const unsigned char *)\"" );
3375 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3377 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3380 if (*p
!= ']') goto error
;
3381 fprintf( f
, "\" },\n" );
3383 print_file( f
, 0, "};\n\n" );
3387 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);