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 if (!is_void(func
->def
->type
))
2359 update_tfsoff(func
->def
->type
,
2360 write_typeformatstring_var(
2361 file
, 2, NULL
, func
->def
->type
,
2362 func
->def
, &typeformat_offset
),
2365 current_func
= func
;
2367 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2370 write_typeformatstring_var(
2371 file
, 2, func
, var
->type
, var
,
2372 &typeformat_offset
),
2378 return typeformat_offset
+ 1;
2382 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2386 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2387 print_file(file
, indent
, "{\n");
2389 print_file(file
, indent
, "0,\n");
2390 print_file(file
, indent
, "{\n");
2392 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2394 set_all_tfswrite(TRUE
);
2395 process_tfs(file
, ifaces
, pred
);
2397 print_file(file
, indent
, "0x0\n");
2399 print_file(file
, indent
, "}\n");
2401 print_file(file
, indent
, "};\n");
2402 print_file(file
, indent
, "\n");
2405 static unsigned int get_required_buffer_size_type(
2406 const type_t
*type
, const char *name
, unsigned int *alignment
)
2409 if (is_user_type(type
))
2412 const type_t
*utype
= get_user_type(type
, &uname
);
2413 return get_required_buffer_size_type(utype
, uname
, alignment
);
2437 case RPC_FC_ERROR_STATUS_T
:
2447 case RPC_FC_BIND_PRIMITIVE
:
2451 case RPC_FC_PSTRUCT
:
2455 if (!type
->fields
) return 0;
2456 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2458 unsigned int alignment
;
2459 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2467 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2468 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2471 case RPC_FC_SMFARRAY
:
2472 case RPC_FC_LGFARRAY
:
2473 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2481 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2483 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2484 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2487 if (!in_attr
&& !out_attr
)
2492 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2493 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2499 if (pass
== PASS_OUT
)
2501 if (out_attr
&& is_ptr(var
->type
))
2503 type_t
*type
= var
->type
;
2505 if (type
->type
== RPC_FC_STRUCT
)
2508 unsigned int size
= 36;
2510 if (!type
->fields
) return size
;
2511 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2514 size
+= get_required_buffer_size_type(
2515 field
->type
, field
->name
, &align
);
2524 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2525 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2527 if (is_ptr(var
->type
))
2529 type_t
*type
= var
->type
;
2531 if (is_base_type(type
->type
))
2535 else if (type
->type
== RPC_FC_STRUCT
)
2537 unsigned int size
= 36;
2540 if (!type
->fields
) return size
;
2541 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2544 size
+= get_required_buffer_size_type(
2545 field
->type
, field
->name
, &align
);
2552 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2556 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2559 unsigned int total_size
= 0, alignment
;
2563 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2565 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2566 total_size
+= alignment
;
2570 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
2572 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
2573 total_size
+= alignment
;
2578 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2579 enum remoting_phase phase
,
2580 const var_t
*var
, unsigned int type_offset
)
2582 const char *function
;
2585 case PHASE_BUFFERSIZE
:
2586 function
= "BufferSize";
2589 function
= "Marshall";
2591 case PHASE_UNMARSHAL
:
2592 function
= "Unmarshall";
2602 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2604 print_file(file
, indent
, "&_StubMsg,\n");
2605 print_file(file
, indent
, "%s%s%s%s,\n",
2606 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2607 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2608 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2610 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2611 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2612 if (phase
== PHASE_UNMARSHAL
)
2613 print_file(file
, indent
, "0);\n");
2617 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2618 enum pass pass
, const var_t
*var
,
2619 const char *varname
)
2621 type_t
*type
= var
->type
;
2623 unsigned int alignment
= 0;
2624 unsigned char rtype
;
2626 /* no work to do for other phases, buffer sizing is done elsewhere */
2627 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2630 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2654 case RPC_FC_ERROR_STATUS_T
:
2666 case RPC_FC_BIND_PRIMITIVE
:
2667 /* no marshalling needed */
2671 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2675 if (phase
== PHASE_MARSHAL
)
2676 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2677 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2678 alignment
- 1, alignment
- 1);
2680 if (phase
== PHASE_MARSHAL
)
2682 print_file(file
, indent
, "*(");
2683 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2685 fprintf(file
, " *)_StubMsg.Buffer = *");
2687 fprintf(file
, " *)_StubMsg.Buffer = ");
2688 fprintf(file
, "%s", varname
);
2689 fprintf(file
, ";\n");
2691 else if (phase
== PHASE_UNMARSHAL
)
2693 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2694 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2695 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2696 print_file(file
, indent
, "{\n");
2697 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2698 print_file(file
, indent
, "}\n");
2699 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2700 print_file(file
, indent
, "");
2702 print_file(file
, indent
, "*");
2703 fprintf(file
, "%s", varname
);
2704 if (pass
== PASS_IN
&& is_ptr(type
))
2705 fprintf(file
, " = (");
2707 fprintf(file
, " = *(");
2708 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2709 fprintf(file
, " *)_StubMsg.Buffer;\n");
2712 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2713 write_type_decl(file
, var
->type
, NULL
);
2714 fprintf(file
, ");\n");
2717 /* returns whether the MaxCount, Offset or ActualCount members need to be
2718 * filled in for the specified phase */
2719 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2721 return (phase
!= PHASE_UNMARSHAL
);
2724 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2728 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2734 error("%s: multidimensional conformant"
2735 " arrays not supported at the top level\n",
2742 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2743 enum pass pass
, enum remoting_phase phase
,
2746 int in_attr
, out_attr
, pointer_type
;
2747 const type_t
*type
= var
->type
;
2748 unsigned char rtype
;
2749 size_t start_offset
= type
->typestring_offset
;
2751 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2753 pointer_type
= RPC_FC_RP
;
2755 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2756 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2757 if (!in_attr
&& !out_attr
)
2760 if (phase
!= PHASE_FREE
)
2764 if (!in_attr
) return;
2767 if (!out_attr
) return;
2775 if (is_context_handle(type
))
2777 if (phase
== PHASE_MARSHAL
)
2779 if (pass
== PASS_IN
)
2781 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2782 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2783 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type
) ? "*" : "", var
->name
);
2784 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2788 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2789 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2790 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2791 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2792 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2795 else if (phase
== PHASE_UNMARSHAL
)
2797 if (pass
== PASS_OUT
)
2800 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2801 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2802 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2803 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2804 print_file(file
, indent
+ 1, "_Handle);\n");
2808 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2809 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2810 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2814 else if (is_user_type(var
->type
))
2816 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2818 else if (is_string_type(var
->attrs
, var
->type
))
2820 if (is_array(type
) && !is_conformant_array(type
))
2821 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2824 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2826 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2827 write_expr(file
, type
->size_is
, 1);
2828 fprintf(file
, ";\n");
2831 if (phase
== PHASE_FREE
|| pass
== PASS_RETURN
|| pointer_type
== RPC_FC_UP
)
2832 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2833 start_offset
- (type
->size_is
? 4 : 2));
2835 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2839 else if (is_array(type
))
2841 unsigned char tc
= type
->type
;
2842 const char *array_type
= "FixedArray";
2844 /* We already have the size_is expression since it's at the
2845 top level, but do checks for multidimensional conformant
2846 arrays. When we handle them, we'll need to extend this
2847 function to return a list, and then we'll actually use
2848 the return value. */
2849 get_size_is_expr(type
, var
->name
);
2851 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2853 if (is_size_needed_for_phase(phase
))
2855 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2856 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2857 write_expr(file
, type
->length_is
, 1);
2858 fprintf(file
, ";\n\n");
2860 array_type
= "VaryingArray";
2862 else if (tc
== RPC_FC_CARRAY
)
2864 if (is_size_needed_for_phase(phase
))
2866 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2867 write_expr(file
, type
->size_is
, 1);
2868 fprintf(file
, ";\n\n");
2870 array_type
= "ConformantArray";
2872 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2874 if (is_size_needed_for_phase(phase
))
2878 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2879 write_expr(file
, type
->size_is
, 1);
2880 fprintf(file
, ";\n");
2882 if (type
->length_is
)
2884 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2885 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2886 write_expr(file
, type
->length_is
, 1);
2887 fprintf(file
, ";\n\n");
2890 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2892 : "ConformantVaryingArray");
2895 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2896 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2897 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2899 /* these are all unmarshalled by allocating memory */
2900 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2901 type
->type
== RPC_FC_CVARRAY
||
2902 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2903 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2905 print_file(file
, indent
, "if (%s)\n", var
->name
);
2907 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2911 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2913 if (phase
!= PHASE_FREE
)
2914 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2916 else if (!is_ptr(var
->type
))
2921 case RPC_FC_PSTRUCT
:
2922 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2924 case RPC_FC_CSTRUCT
:
2925 case RPC_FC_CPSTRUCT
:
2926 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2928 case RPC_FC_CVSTRUCT
:
2929 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2931 case RPC_FC_BOGUS_STRUCT
:
2932 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2935 if (is_base_type( var
->type
->ref
->type
))
2937 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2939 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2941 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2942 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2947 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2949 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2950 write_expr( file
, iid
, 1 );
2951 fprintf( file
, ";\n\n" );
2953 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2957 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2962 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2964 if (phase
!= PHASE_FREE
)
2965 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2967 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2969 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2970 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2975 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2977 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2979 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2980 write_expr( file
, iid
, 1 );
2981 fprintf( file
, ";\n\n" );
2985 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2986 write_expr(file
, sx
, 1);
2987 fprintf(file
, ";\n\n");
2989 if (var
->type
->ref
->type
== RPC_FC_IP
)
2990 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
2992 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2995 fprintf(file
, "\n");
2998 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
2999 enum pass pass
, enum remoting_phase phase
)
3001 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
3003 unsigned int size
= get_function_buffer_size( func
, pass
);
3004 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
3007 if (pass
== PASS_RETURN
)
3011 var
.name
= xstrdup( "_RetVal" );
3012 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
3020 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3021 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
3026 size_t get_size_procformatstring_var(const var_t
*var
)
3028 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
3032 size_t get_size_procformatstring_func(const func_t
*func
)
3037 /* argument list size */
3039 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3040 size
+= get_size_procformatstring_var(var
);
3042 /* return value size */
3043 if (is_void(func
->def
->type
))
3044 size
+= 2; /* FC_END and FC_PAD */
3046 size
+= get_size_procformatstring_var(func
->def
);
3051 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3053 const ifref_t
*iface
;
3057 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
3059 if (!pred(iface
->iface
))
3062 if (iface
->iface
->funcs
)
3063 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
3064 if (!is_local(func
->def
->attrs
))
3065 size
+= get_size_procformatstring_func( func
);
3070 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3072 set_all_tfswrite(FALSE
);
3073 return process_tfs(NULL
, ifaces
, pred
);
3076 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3077 const var_list_t
*fields
, const char *structvar
)
3083 fprintf(h
, "%lu", e
->u
.lval
);
3086 fprintf(h
, "0x%lx", e
->u
.lval
);
3089 fprintf(h
, "%#.15g", e
->u
.dval
);
3091 case EXPR_TRUEFALSE
:
3093 fprintf(h
, "FALSE");
3097 case EXPR_IDENTIFIER
:
3100 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3101 if (!strcmp(e
->u
.sval
, field
->name
))
3103 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3107 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3112 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3116 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3120 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3124 write_type_decl(h
, e
->u
.tref
, NULL
);
3126 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3129 fprintf(h
, "sizeof(");
3130 write_type_decl(h
, e
->u
.tref
, NULL
);
3141 if (brackets
) fprintf(h
, "(");
3142 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3144 case EXPR_SHL
: fprintf(h
, " << "); break;
3145 case EXPR_SHR
: fprintf(h
, " >> "); break;
3146 case EXPR_MUL
: fprintf(h
, " * "); break;
3147 case EXPR_DIV
: fprintf(h
, " / "); break;
3148 case EXPR_ADD
: fprintf(h
, " + "); break;
3149 case EXPR_SUB
: fprintf(h
, " - "); break;
3150 case EXPR_AND
: fprintf(h
, " & "); break;
3151 case EXPR_OR
: fprintf(h
, " | "); break;
3154 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3155 if (brackets
) fprintf(h
, ")");
3158 if (brackets
) fprintf(h
, "(");
3159 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3161 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3163 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3164 if (brackets
) fprintf(h
, ")");
3166 case EXPR_ADDRESSOF
:
3168 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3174 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3176 int in_attr
, out_attr
;
3178 const var_t
*def
= func
->def
;
3181 /* declare return value '_RetVal' */
3182 if (!is_void(def
->type
))
3184 print_file(file
, indent
, "");
3185 write_type_decl_left(file
, def
->type
);
3186 fprintf(file
, " _RetVal;\n");
3192 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3194 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3196 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3197 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3198 if (!out_attr
&& !in_attr
)
3201 if (is_context_handle(var
->type
))
3202 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3205 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3207 print_file(file
, indent
, "");
3208 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3210 fprintf(file
, ";\n");
3213 print_file(file
, indent
, "");
3214 write_type_decl_left(file
, var
->type
);
3216 if (var
->type
->declarray
) {
3217 fprintf(file
, "( *");
3218 write_name(file
, var
);
3219 fprintf(file
, " )");
3221 write_name(file
, var
);
3222 write_type_right(file
, var
->type
, FALSE
);
3223 fprintf(file
, ";\n");
3225 if (decl_indirect(var
->type
))
3226 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3227 var
->name
, var
->name
);
3233 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3235 int in_attr
, out_attr
;
3242 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3244 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3245 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3246 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3247 if (!out_attr
&& !in_attr
)
3252 print_file(file
, indent
, "");
3253 write_name(file
, var
);
3255 if (is_context_handle(var
->type
))
3257 fprintf(file
, " = NdrContextHandleInitialize(\n");
3258 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3259 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3260 var
->type
->typestring_offset
);
3262 else if (var
->type
->size_is
)
3264 unsigned int size
, align
= 0;
3265 type_t
*type
= var
->type
;
3267 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3268 for ( ; type
->size_is
; type
= type
->ref
)
3270 write_expr(file
, type
->size_is
, TRUE
);
3271 fprintf(file
, " * ");
3273 size
= type_memsize(type
, &align
);
3274 fprintf(file
, "%u);\n", size
);
3276 else if (!is_string
)
3278 fprintf(file
, " = &_W%u;\n", i
);
3279 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3280 print_file(file
, indent
, "_W%u = 0;\n", i
);
3288 fprintf(file
, "\n");
3292 int write_expr_eval_routines(FILE *file
, const char *iface
)
3294 static const char *var_name
= "pS";
3296 struct expr_eval_routine
*eval
;
3297 unsigned short callback_offset
= 0;
3299 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3301 const char *name
= eval
->structure
->name
;
3302 const var_list_t
*fields
= eval
->structure
->fields
;
3305 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3306 iface
, name
, callback_offset
);
3307 print_file(file
, 0, "{\n");
3308 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3309 name
, var_name
, name
, eval
->baseoff
);
3310 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3311 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3312 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3313 fprintf(file
, ";\n");
3314 print_file(file
, 0, "}\n\n");
3320 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3322 struct expr_eval_routine
*eval
;
3323 struct expr_eval_routine
*cursor
;
3324 unsigned short callback_offset
= 0;
3326 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3327 fprintf(file
, "{\n");
3329 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3331 const char *name
= eval
->structure
->name
;
3332 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3334 list_remove(&eval
->entry
);
3338 fprintf(file
, "};\n\n");
3341 void write_user_quad_list(FILE *file
)
3345 if (list_empty(&user_type_list
))
3348 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3349 fprintf(file
, "{\n");
3350 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3352 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3353 print_file(file
, 1, "{\n");
3354 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3355 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3356 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3357 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3358 print_file(file
, 1, "}%s\n", sep
);
3360 fprintf(file
, "};\n\n");
3363 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3365 const struct str_list_entry_t
*endpoint
;
3368 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3369 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3370 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3372 print_file( f
, 1, "{ (const unsigned char *)\"" );
3373 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3375 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3378 if (!*p
) goto error
;
3379 if (p
[1] != '[') goto error
;
3381 fprintf( f
, "\", (const unsigned char *)\"" );
3382 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3384 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3387 if (*p
!= ']') goto error
;
3388 fprintf( f
, "\" },\n" );
3390 print_file( f
, 0, "};\n\n" );
3394 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);