2 * Format String Generator for IDL Compiler
4 * Copyright 2005-2006 Eric Kohl
5 * Copyright 2005-2006 Robert Shearman
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
40 #include "wine/list.h"
44 static const func_t
*current_func
;
45 static const type_t
*current_structure
;
46 static const ifref_t
*current_iface
;
48 static struct list expr_eval_routines
= LIST_INIT(expr_eval_routines
);
49 struct expr_eval_routine
52 const type_t
*structure
;
57 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
);
58 static size_t write_struct_tfs(FILE *file
, type_t
*type
, const char *name
, unsigned int *tfsoff
);
59 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
60 const char *name
, int write_ptr
, unsigned int *tfsoff
);
61 static const var_t
*find_array_or_string_in_struct(const type_t
*type
);
63 const char *string_of_type(unsigned char type
)
67 case RPC_FC_BYTE
: return "FC_BYTE";
68 case RPC_FC_CHAR
: return "FC_CHAR";
69 case RPC_FC_SMALL
: return "FC_SMALL";
70 case RPC_FC_USMALL
: return "FC_USMALL";
71 case RPC_FC_WCHAR
: return "FC_WCHAR";
72 case RPC_FC_SHORT
: return "FC_SHORT";
73 case RPC_FC_USHORT
: return "FC_USHORT";
74 case RPC_FC_LONG
: return "FC_LONG";
75 case RPC_FC_ULONG
: return "FC_ULONG";
76 case RPC_FC_FLOAT
: return "FC_FLOAT";
77 case RPC_FC_HYPER
: return "FC_HYPER";
78 case RPC_FC_DOUBLE
: return "FC_DOUBLE";
79 case RPC_FC_ENUM16
: return "FC_ENUM16";
80 case RPC_FC_ENUM32
: return "FC_ENUM32";
81 case RPC_FC_IGNORE
: return "FC_IGNORE";
82 case RPC_FC_ERROR_STATUS_T
: return "FC_ERROR_STATUS_T";
83 case RPC_FC_RP
: return "FC_RP";
84 case RPC_FC_UP
: return "FC_UP";
85 case RPC_FC_OP
: return "FC_OP";
86 case RPC_FC_FP
: return "FC_FP";
87 case RPC_FC_ENCAPSULATED_UNION
: return "FC_ENCAPSULATED_UNION";
88 case RPC_FC_NON_ENCAPSULATED_UNION
: return "FC_NON_ENCAPSULATED_UNION";
89 case RPC_FC_STRUCT
: return "FC_STRUCT";
90 case RPC_FC_PSTRUCT
: return "FC_PSTRUCT";
91 case RPC_FC_CSTRUCT
: return "FC_CSTRUCT";
92 case RPC_FC_CPSTRUCT
: return "FC_CPSTRUCT";
93 case RPC_FC_CVSTRUCT
: return "FC_CVSTRUCT";
94 case RPC_FC_BOGUS_STRUCT
: return "FC_BOGUS_STRUCT";
95 case RPC_FC_SMFARRAY
: return "FC_SMFARRAY";
96 case RPC_FC_LGFARRAY
: return "FC_LGFARRAY";
97 case RPC_FC_SMVARRAY
: return "FC_SMVARRAY";
98 case RPC_FC_LGVARRAY
: return "FC_LGVARRAY";
99 case RPC_FC_CARRAY
: return "FC_CARRAY";
100 case RPC_FC_CVARRAY
: return "FC_CVARRAY";
101 case RPC_FC_BOGUS_ARRAY
: return "FC_BOGUS_ARRAY";
102 case RPC_FC_ALIGNM4
: return "FC_ALIGNM4";
103 case RPC_FC_ALIGNM8
: return "FC_ALIGNM8";
104 case RPC_FC_POINTER
: return "FC_POINTER";
105 case RPC_FC_C_CSTRING
: return "FC_C_CSTRING";
106 case RPC_FC_C_WSTRING
: return "FC_C_WSTRING";
107 case RPC_FC_CSTRING
: return "FC_CSTRING";
108 case RPC_FC_WSTRING
: return "FC_WSTRING";
110 error("string_of_type: unknown type 0x%02x\n", type
);
115 int is_struct(unsigned char type
)
122 case RPC_FC_CPSTRUCT
:
123 case RPC_FC_CVSTRUCT
:
124 case RPC_FC_BOGUS_STRUCT
:
131 static int is_non_complex_struct(const type_t
*type
)
138 case RPC_FC_CPSTRUCT
:
139 case RPC_FC_CVSTRUCT
:
146 int is_union(unsigned char type
)
150 case RPC_FC_ENCAPSULATED_UNION
:
151 case RPC_FC_NON_ENCAPSULATED_UNION
:
158 static int type_has_pointers(const type_t
*type
)
160 if (is_user_type(type
))
162 else if (is_ptr(type
))
164 else if (is_array(type
))
165 return type_has_pointers(type
->ref
);
166 else if (is_struct(type
->type
))
169 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
171 if (type_has_pointers(field
->type
))
175 else if (is_union(type
->type
))
179 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
181 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
182 fields
= uv
->type
->fields
;
185 fields
= type
->fields
;
186 if (fields
) LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
188 if (field
->type
&& type_has_pointers(field
->type
))
196 static unsigned short user_type_offset(const char *name
)
199 unsigned short off
= 0;
200 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
202 if (strcmp(name
, ut
->name
) == 0)
206 error("user_type_offset: couldn't find type (%s)\n", name
);
210 static void update_tfsoff(type_t
*type
, unsigned int offset
, FILE *file
)
212 type
->typestring_offset
= offset
;
213 if (file
) type
->tfswrite
= FALSE
;
216 static void guard_rec(type_t
*type
)
218 /* types that contain references to themselves (like a linked list),
219 need to be shielded from infinite recursion when writing embedded
221 if (type
->typestring_offset
)
222 type
->tfswrite
= FALSE
;
224 type
->typestring_offset
= 1;
227 static type_t
*get_user_type(const type_t
*t
, const char **pname
)
231 type_t
*ut
= get_attrp(t
->attrs
, ATTR_WIREMARSHAL
);
239 if (t
->kind
== TKIND_ALIAS
)
246 int is_user_type(const type_t
*t
)
248 return get_user_type(t
, NULL
) != NULL
;
251 static int is_embedded_complex(const type_t
*type
)
253 unsigned char tc
= type
->type
;
254 return is_struct(tc
) || is_union(tc
) || is_array(type
) || is_user_type(type
)
255 || (is_ptr(type
) && type
->ref
->type
== RPC_FC_IP
);
258 static const char *get_context_handle_type_name(const type_t
*type
)
261 for (t
= type
; is_ptr(t
); t
= t
->ref
)
262 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
268 /* This is actually fairly involved to implement precisely, due to the
269 effects attributes may have and things like that. Right now this is
270 only used for optimization, so just check for a very small set of
271 criteria that guarantee the types are equivalent; assume every thing
272 else is different. */
273 static int compare_type(const type_t
*a
, const type_t
*b
)
278 && strcmp(a
->name
, b
->name
) == 0))
280 /* Ordering doesn't need to be implemented yet. */
284 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
288 if (a
->type
!= b
->type
)
289 return a
->type
- b
->type
;
296 return a
->u
.lval
- b
->u
.lval
;
298 return a
->u
.dval
- b
->u
.dval
;
299 case EXPR_IDENTIFIER
:
300 return strcmp(a
->u
.sval
, b
->u
.sval
);
302 ret
= compare_expr(a
->ref
, b
->ref
);
305 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
308 return compare_expr(a
->ext2
, b
->ext2
);
317 ret
= compare_expr(a
->ref
, b
->ref
);
320 return compare_expr(a
->u
.ext
, b
->u
.ext
);
322 ret
= compare_type(a
->u
.tref
, b
->u
.tref
);
330 return compare_expr(a
->ref
, b
->ref
);
332 return compare_type(a
->u
.tref
, b
->u
.tref
);
339 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
342 fprintf(file, "/* %2u */\n", typestring_offset); \
343 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
347 static void print_file(FILE *file
, int indent
, const char *format
, ...)
350 va_start(va
, format
);
351 print(file
, indent
, format
, va
);
355 void print(FILE *file
, int indent
, const char *format
, va_list va
)
359 if (format
[0] != '\n')
362 vfprintf(file
, format
, va
);
367 static void write_var_init(FILE *file
, int indent
, const type_t
*t
, const char *n
)
369 if (decl_indirect(t
))
370 print_file(file
, indent
, "MIDL_memset(&%s, 0, sizeof(%s));\n", n
, n
);
371 else if (is_ptr(t
) || is_array(t
))
372 print_file(file
, indent
, "%s = 0;\n", n
);
375 void write_parameters_init(FILE *file
, int indent
, const func_t
*func
)
379 if (!is_void(func
->def
->type
))
380 write_var_init(file
, indent
, func
->def
->type
, "_RetVal");
385 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
386 write_var_init(file
, indent
, var
->type
, var
->name
);
391 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
393 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
394 print_file(f
, indent
, "{\n");
395 print_file(f
, indent
+ 1, "short Pad;\n");
396 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
397 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
398 print_file(f
, indent
, "\n");
401 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, type_pred_t pred
)
403 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
404 get_size_typeformatstring(ifaces
, pred
));
406 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
407 get_size_procformatstring(ifaces
, pred
));
410 write_formatdesc(f
, indent
, "TYPE");
411 write_formatdesc(f
, indent
, "PROC");
413 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
414 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
415 print_file(f
, indent
, "\n");
418 static inline int is_base_type(unsigned char type
)
437 case RPC_FC_ERROR_STATUS_T
:
438 case RPC_FC_BIND_PRIMITIVE
:
446 int decl_indirect(const type_t
*t
)
448 return is_user_type(t
)
449 || (!is_base_type(t
->type
)
454 static size_t write_procformatstring_var(FILE *file
, int indent
,
455 const var_t
*var
, int is_return
)
458 const type_t
*type
= var
->type
;
460 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
461 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
463 if (!is_in
&& !is_out
) is_in
= TRUE
;
465 if (!type
->declarray
&& is_base_type(type
->type
))
468 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
470 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
472 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
474 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
475 size
= 2; /* includes param type prefix */
477 else if (is_base_type(type
->type
))
479 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
480 size
= 2; /* includes param type prefix */
484 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
491 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
492 else if (is_in
&& is_out
)
493 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
495 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
497 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
499 print_file(file
, indent
, "0x01,\n");
500 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
501 size
= 4; /* includes param type prefix */
506 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
508 const ifref_t
*iface
;
512 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
513 print_file(file
, indent
, "{\n");
515 print_file(file
, indent
, "0,\n");
516 print_file(file
, indent
, "{\n");
519 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
521 if (!pred(iface
->iface
))
524 if (iface
->iface
->funcs
)
527 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
529 if (is_local(func
->def
->attrs
)) continue;
530 /* emit argument data */
533 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
534 write_procformatstring_var(file
, indent
, var
, FALSE
);
537 /* emit return value data */
539 if (is_void(var
->type
))
541 print_file(file
, indent
, "0x5b, /* FC_END */\n");
542 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
545 write_procformatstring_var(file
, indent
, var
, TRUE
);
550 print_file(file
, indent
, "0x0\n");
552 print_file(file
, indent
, "}\n");
554 print_file(file
, indent
, "};\n");
555 print_file(file
, indent
, "\n");
558 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
560 if (is_base_type(type
->type
))
562 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
563 *typestring_offset
+= 1;
570 /* write conformance / variance descriptor */
571 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
572 unsigned int baseoff
, const type_t
*type
,
575 unsigned char operator_type
= 0;
576 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
577 const char *conftype_string
= "";
578 const char *operator_string
= "no operators";
579 const expr_t
*subexpr
;
583 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
589 /* Top-level conformance calculations are done inline. */
590 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
591 RPC_FC_TOP_LEVEL_CONFORMANCE
);
592 print_file (file
, 2, "0x0,\n");
593 print_file (file
, 2, "NdrFcShort(0x0),\n");
599 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
600 error("write_conf_or_var_desc: constant value %ld is greater than "
601 "the maximum constant size of %d\n", expr
->cval
,
602 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
604 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
605 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
606 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
607 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
612 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
614 conftype
= RPC_FC_POINTER_CONFORMANCE
;
615 conftype_string
= "field pointer, ";
619 switch (subexpr
->type
)
622 subexpr
= subexpr
->ref
;
623 operator_type
= RPC_FC_DEREFERENCE
;
624 operator_string
= "FC_DEREFERENCE";
627 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
629 subexpr
= subexpr
->ref
;
630 operator_type
= RPC_FC_DIV_2
;
631 operator_string
= "FC_DIV_2";
635 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
637 subexpr
= subexpr
->ref
;
638 operator_type
= RPC_FC_MULT_2
;
639 operator_string
= "FC_MULT_2";
643 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
645 subexpr
= subexpr
->ref
;
646 operator_type
= RPC_FC_SUB_1
;
647 operator_string
= "FC_SUB_1";
651 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
653 subexpr
= subexpr
->ref
;
654 operator_type
= RPC_FC_ADD_1
;
655 operator_string
= "FC_ADD_1";
662 if (subexpr
->type
== EXPR_IDENTIFIER
)
664 const type_t
*correlation_variable
= NULL
;
665 unsigned char correlation_variable_type
;
666 unsigned char param_type
= 0;
670 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
672 unsigned int align
= 0;
673 /* FIXME: take alignment into account */
674 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
676 correlation_variable
= var
->type
;
679 offset
+= type_memsize(var
->type
, &align
);
681 if (!correlation_variable
)
682 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
686 correlation_variable_type
= correlation_variable
->type
;
688 switch (correlation_variable_type
)
692 param_type
= RPC_FC_SMALL
;
696 param_type
= RPC_FC_USMALL
;
701 param_type
= RPC_FC_SHORT
;
704 param_type
= RPC_FC_USHORT
;
708 param_type
= RPC_FC_LONG
;
711 param_type
= RPC_FC_ULONG
;
717 if (sizeof(void *) == 4) /* FIXME */
718 param_type
= RPC_FC_LONG
;
720 param_type
= RPC_FC_HYPER
;
723 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
724 correlation_variable_type
);
727 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
728 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
729 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
730 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
735 unsigned int callback_offset
= 0;
736 struct expr_eval_routine
*eval
;
739 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
741 if (!strcmp (eval
->structure
->name
, structure
->name
)
742 && !compare_expr (eval
->expr
, expr
))
752 eval
= xmalloc (sizeof(*eval
));
753 eval
->structure
= structure
;
754 eval
->baseoff
= baseoff
;
756 list_add_tail (&expr_eval_routines
, &eval
->entry
);
759 if (callback_offset
> USHRT_MAX
)
760 error("Maximum number of callback routines reached\n");
762 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
763 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
764 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
769 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
771 int have_align
= FALSE
;
775 if (!fields
) return 0;
776 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
778 unsigned int falign
= 0;
779 size_t fsize
= type_memsize(v
->type
, &falign
);
785 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
789 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
793 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
795 size_t size
, maxs
= 0;
796 unsigned int align
= *pmaxa
;
799 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
801 /* we could have an empty default field with NULL type */
804 size
= type_memsize(v
->type
, &align
);
805 if (maxs
< size
) maxs
= size
;
806 if (*pmaxa
< align
) *pmaxa
= align
;
813 int get_padding(const var_list_t
*fields
)
815 unsigned short offset
= 0;
822 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
824 type_t
*ft
= f
->type
;
825 unsigned int align
= 0;
826 size_t size
= type_memsize(ft
, &align
);
829 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
833 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
836 size_t type_memsize(const type_t
*t
, unsigned int *align
)
840 if (t
->declarray
&& is_conformant_array(t
))
842 type_memsize(t
->ref
, align
);
845 else if (is_ptr(t
) || is_conformant_array(t
))
847 size
= sizeof(void *);
848 if (size
> *align
) *align
= size
;
850 else switch (t
->type
)
857 if (size
> *align
) *align
= size
;
864 if (size
> *align
) *align
= size
;
868 case RPC_FC_ERROR_STATUS_T
:
872 if (size
> *align
) *align
= size
;
877 if (size
> *align
) *align
= size
;
880 case RPC_FC_CVSTRUCT
:
881 case RPC_FC_CPSTRUCT
:
884 case RPC_FC_BOGUS_STRUCT
:
885 size
= fields_memsize(t
->fields
, align
);
887 case RPC_FC_ENCAPSULATED_UNION
:
888 case RPC_FC_NON_ENCAPSULATED_UNION
:
889 size
= union_memsize(t
->fields
, align
);
891 case RPC_FC_SMFARRAY
:
892 case RPC_FC_LGFARRAY
:
893 case RPC_FC_SMVARRAY
:
894 case RPC_FC_LGVARRAY
:
895 case RPC_FC_BOGUS_ARRAY
:
896 size
= t
->dim
* type_memsize(t
->ref
, align
);
899 error("type_memsize: Unknown type %d\n", t
->type
);
906 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
908 short absoff
= type
->ref
->typestring_offset
;
909 short reloff
= absoff
- (offset
+ 2);
910 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
912 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
913 type
->type
, ptr_attr
, string_of_type(type
->type
));
914 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
915 reloff
, reloff
, absoff
);
919 static unsigned char conf_string_type_of_char_type(unsigned char t
)
925 return RPC_FC_C_CSTRING
;
927 return RPC_FC_C_WSTRING
;
930 error("string_type_of_char_type: unrecognized type %d\n", t
);
934 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
937 = is_string_type(type
->attrs
, type
)
938 ? conf_string_type_of_char_type(type
->ref
->type
)
940 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
941 type
->type
, string_of_type(type
->type
));
942 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
943 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
947 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
949 print_file(file
, 0, "/* %u (", tfsoff
);
950 write_type_decl(file
, t
, NULL
);
951 print_file(file
, 0, ") */\n");
954 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
956 unsigned int offset
= *typestring_offset
;
958 print_start_tfs_comment(file
, type
, offset
);
959 update_tfsoff(type
, offset
, file
);
961 if (type
->ref
->typestring_offset
)
962 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
963 else if (is_base_type(type
->ref
->type
))
964 *typestring_offset
+= write_simple_pointer(file
, type
);
969 static int processed(const type_t
*type
)
971 return type
->typestring_offset
&& !type
->tfswrite
;
974 static int user_type_has_variable_size(const type_t
*t
)
983 case RPC_FC_CPSTRUCT
:
984 case RPC_FC_CVSTRUCT
:
987 /* Note: Since this only applies to user types, we can't have a conformant
988 array here, and strings should get filed under pointer in this case. */
992 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
994 unsigned int start
, absoff
, flags
;
995 unsigned int align
= 0, ualign
= 0;
997 type_t
*utype
= get_user_type(type
, &name
);
998 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
999 size_t size
= type_memsize(type
, &align
);
1000 unsigned short funoff
= user_type_offset(name
);
1005 if (is_base_type(utype
->type
))
1008 print_start_tfs_comment(file
, utype
, absoff
);
1009 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
1010 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
1015 if (!processed(utype
))
1016 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
1017 absoff
= utype
->typestring_offset
;
1020 if (utype
->type
== RPC_FC_RP
)
1022 else if (utype
->type
== RPC_FC_UP
)
1028 update_tfsoff(type
, start
, file
);
1029 print_start_tfs_comment(file
, type
, start
);
1030 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
1031 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1032 flags
| (align
- 1), align
- 1, flags
);
1033 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
1034 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
1035 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
1037 reloff
= absoff
- *tfsoff
;
1038 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
1042 static void write_member_type(FILE *file
, const type_t
*cont
,
1043 const attr_list_t
*attrs
, const type_t
*type
,
1044 unsigned int *corroff
, unsigned int *tfsoff
)
1046 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1051 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1058 absoff
= type
->typestring_offset
;
1060 reloff
= absoff
- (*tfsoff
+ 2);
1062 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1063 /* FIXME: actually compute necessary padding */
1064 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1065 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1066 reloff
, reloff
, absoff
);
1069 else if (is_ptr(type
) || is_conformant_array(type
))
1071 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1074 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1077 else if (!write_base_type(file
, type
, tfsoff
))
1078 error("Unsupported member type 0x%x\n", type
->type
);
1081 static void write_end(FILE *file
, unsigned int *tfsoff
)
1083 if (*tfsoff
% 2 == 0)
1085 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1088 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1092 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1094 unsigned int offset
= 0;
1095 var_list_t
*fs
= type
->fields
;
1098 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1100 unsigned int align
= 0;
1101 type_t
*ft
= f
->type
;
1102 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1104 unsigned int absoff
= ft
->typestring_offset
;
1105 short reloff
= absoff
- (*tfsoff
+ 6);
1106 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1107 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1108 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1109 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1110 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1111 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1112 reloff
, reloff
, absoff
);
1116 /* FIXME: take alignment into account */
1117 offset
+= type_memsize(ft
, &align
);
1121 static int write_no_repeat_pointer_descriptions(
1122 FILE *file
, type_t
*type
,
1123 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1124 unsigned int *typestring_offset
)
1129 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1131 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1132 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1134 /* pointer instance */
1135 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1136 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1137 *typestring_offset
+= 6;
1140 write_pointer_tfs(file
, type
, typestring_offset
);
1143 unsigned absoff
= type
->typestring_offset
;
1144 short reloff
= absoff
- (*typestring_offset
+ 2);
1145 /* FIXME: get pointer attributes from field */
1146 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1147 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1148 reloff
, reloff
, absoff
);
1149 *typestring_offset
+= 4;
1153 *offset_in_memory
+= type_memsize(type
, &align
);
1154 /* FIXME: is there a case where these two are different? */
1156 *offset_in_buffer
+= type_memsize(type
, &align
);
1161 if (is_non_complex_struct(type
))
1164 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1165 written
+= write_no_repeat_pointer_descriptions(
1167 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1172 *offset_in_memory
+= type_memsize(type
, &align
);
1173 /* FIXME: is there a case where these two are different? */
1175 *offset_in_buffer
+= type_memsize(type
, &align
);
1181 static int write_pointer_description_offsets(
1182 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1183 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1184 unsigned int *typestring_offset
)
1189 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1191 if (offset_in_memory
&& offset_in_buffer
)
1193 /* pointer instance */
1194 /* FIXME: sometimes from end of structure, sometimes from beginning */
1195 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1196 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1199 *offset_in_memory
+= type_memsize(type
, &align
);
1200 /* FIXME: is there a case where these two are different? */
1202 *offset_in_buffer
+= type_memsize(type
, &align
);
1204 *typestring_offset
+= 4;
1206 if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1207 write_pointer_tfs(file
, type
, typestring_offset
);
1209 error("write_pointer_description_offsets: type format string unknown\n");
1216 return write_pointer_description_offsets(
1217 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1220 else if (is_non_complex_struct(type
))
1222 /* otherwise search for interesting fields to parse */
1224 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1226 written
+= write_pointer_description_offsets(
1227 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1234 if (offset_in_memory
)
1235 *offset_in_memory
+= type_memsize(type
, &align
);
1236 /* FIXME: is there a case where these two are different? */
1238 if (offset_in_buffer
)
1239 *offset_in_buffer
+= type_memsize(type
, &align
);
1245 /* Note: if file is NULL return value is number of pointers to write, else
1246 * it is the number of type format characters written */
1247 static int write_fixed_array_pointer_descriptions(
1248 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1249 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1250 unsigned int *typestring_offset
)
1253 int pointer_count
= 0;
1255 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1257 unsigned int temp
= 0;
1258 /* unfortunately, this needs to be done in two passes to avoid
1259 * writing out redundant FC_FIXED_REPEAT descriptions */
1260 pointer_count
= write_pointer_description_offsets(
1261 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1262 if (pointer_count
> 0)
1264 unsigned int increment_size
;
1265 size_t offset_of_array_pointer_mem
= 0;
1266 size_t offset_of_array_pointer_buf
= 0;
1269 increment_size
= type_memsize(type
->ref
, &align
);
1271 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1272 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1273 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1274 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1275 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1276 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1277 *typestring_offset
+= 10;
1279 pointer_count
= write_pointer_description_offsets(
1280 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1281 &offset_of_array_pointer_buf
, typestring_offset
);
1284 else if (is_struct(type
->type
))
1287 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1289 pointer_count
+= write_fixed_array_pointer_descriptions(
1290 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1297 if (offset_in_memory
)
1298 *offset_in_memory
+= type_memsize(type
, &align
);
1299 /* FIXME: is there a case where these two are different? */
1301 if (offset_in_buffer
)
1302 *offset_in_buffer
+= type_memsize(type
, &align
);
1305 return pointer_count
;
1308 /* Note: if file is NULL return value is number of pointers to write, else
1309 * it is the number of type format characters written */
1310 static int write_conformant_array_pointer_descriptions(
1311 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1312 size_t offset_in_memory
, unsigned int *typestring_offset
)
1315 int pointer_count
= 0;
1317 if (is_conformant_array(type
) && !type
->length_is
)
1319 unsigned int temp
= 0;
1320 /* unfortunately, this needs to be done in two passes to avoid
1321 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1322 pointer_count
= write_pointer_description_offsets(
1323 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1324 if (pointer_count
> 0)
1326 unsigned int increment_size
;
1327 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1328 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1331 increment_size
= type_memsize(type
->ref
, &align
);
1333 if (increment_size
> USHRT_MAX
)
1334 error("array size of %u bytes is too large\n", increment_size
);
1336 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1337 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1338 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1339 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1340 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1341 *typestring_offset
+= 8;
1343 pointer_count
= write_pointer_description_offsets(
1344 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1345 &offset_of_array_pointer_buf
, typestring_offset
);
1349 return pointer_count
;
1352 /* Note: if file is NULL return value is number of pointers to write, else
1353 * it is the number of type format characters written */
1354 static int write_varying_array_pointer_descriptions(
1355 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1356 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1357 unsigned int *typestring_offset
)
1360 int pointer_count
= 0;
1362 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1364 if (is_array(type
) && type
->length_is
)
1366 unsigned int temp
= 0;
1367 /* unfortunately, this needs to be done in two passes to avoid
1368 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1369 pointer_count
= write_pointer_description_offsets(
1370 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1371 if (pointer_count
> 0)
1373 unsigned int increment_size
;
1374 size_t offset_of_array_pointer_mem
= 0;
1375 size_t offset_of_array_pointer_buf
= 0;
1378 increment_size
= type_memsize(type
->ref
, &align
);
1380 if (increment_size
> USHRT_MAX
)
1381 error("array size of %u bytes is too large\n", increment_size
);
1383 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1384 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1385 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1386 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1387 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1388 *typestring_offset
+= 8;
1390 pointer_count
= write_pointer_description_offsets(
1391 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1392 &offset_of_array_pointer_buf
, typestring_offset
);
1395 else if (is_struct(type
->type
))
1398 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1400 pointer_count
+= write_varying_array_pointer_descriptions(
1401 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1408 if (offset_in_memory
)
1409 *offset_in_memory
+= type_memsize(type
, &align
);
1410 /* FIXME: is there a case where these two are different? */
1412 if (offset_in_buffer
)
1413 *offset_in_buffer
+= type_memsize(type
, &align
);
1416 return pointer_count
;
1419 static void write_pointer_description(FILE *file
, type_t
*type
,
1420 unsigned int *typestring_offset
)
1422 size_t offset_in_buffer
;
1423 size_t offset_in_memory
;
1425 /* pass 1: search for single instance of a pointer (i.e. don't descend
1427 if (!is_array(type
))
1429 offset_in_memory
= 0;
1430 offset_in_buffer
= 0;
1431 write_no_repeat_pointer_descriptions(
1433 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1436 /* pass 2: search for pointers in fixed arrays */
1437 offset_in_memory
= 0;
1438 offset_in_buffer
= 0;
1439 write_fixed_array_pointer_descriptions(
1441 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1443 /* pass 3: search for pointers in conformant only arrays (but don't descend
1444 * into conformant varying or varying arrays) */
1445 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1446 write_conformant_array_pointer_descriptions(
1447 file
, NULL
, type
, 0, typestring_offset
);
1448 else if (type
->type
== RPC_FC_CPSTRUCT
)
1450 unsigned int align
= 0;
1451 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1452 write_conformant_array_pointer_descriptions(
1454 type_memsize(type
, &align
),
1458 /* pass 4: search for pointers in varying arrays */
1459 offset_in_memory
= 0;
1460 offset_in_buffer
= 0;
1461 write_varying_array_pointer_descriptions(
1463 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1466 int is_declptr(const type_t
*t
)
1468 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1471 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1473 const char *name
, unsigned int *typestring_offset
,
1476 size_t start_offset
;
1477 unsigned char rtype
;
1479 if (toplevel
&& is_declptr(type
))
1481 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1482 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1484 pointer_type
= RPC_FC_RP
;
1485 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1486 pointer_type
, flag
, string_of_type(pointer_type
),
1487 flag
? " [simple_pointer]" : "");
1488 *typestring_offset
+= 2;
1491 print_file(file
, 2, "NdrFcShort(0x2),\n");
1492 *typestring_offset
+= 2;
1496 start_offset
= *typestring_offset
;
1497 update_tfsoff(type
, start_offset
, file
);
1499 rtype
= type
->ref
->type
;
1501 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1503 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1504 return start_offset
;
1507 if (type
->declarray
&& !is_conformant_array(type
))
1509 /* FIXME: multi-dimensional array */
1510 if (0xffffuL
< type
->dim
)
1511 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1512 name
, 0xffffu
, type
->dim
- 0xffffu
);
1514 if (rtype
== RPC_FC_CHAR
)
1515 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1517 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1518 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1519 *typestring_offset
+= 2;
1521 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1522 *typestring_offset
+= 2;
1524 return start_offset
;
1526 else if (type
->size_is
)
1528 unsigned int align
= 0;
1530 if (rtype
== RPC_FC_CHAR
)
1531 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1533 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1534 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1535 *typestring_offset
+= 2;
1537 *typestring_offset
+= write_conf_or_var_desc(
1538 file
, current_structure
,
1539 (type
->declarray
&& current_structure
1540 ? type_memsize(current_structure
, &align
)
1542 type
, type
->size_is
);
1544 return start_offset
;
1548 if (rtype
== RPC_FC_WCHAR
)
1549 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1551 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1552 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1553 *typestring_offset
+= 2;
1555 return start_offset
;
1559 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1560 const char *name
, unsigned int *typestring_offset
)
1562 const expr_t
*length_is
= type
->length_is
;
1563 const expr_t
*size_is
= type
->size_is
;
1564 unsigned int align
= 0;
1566 size_t start_offset
;
1568 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1569 unsigned int baseoff
1570 = type
->declarray
&& current_structure
1571 ? type_memsize(current_structure
, &align
)
1575 pointer_type
= RPC_FC_RP
;
1577 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1580 has_pointer
= type_has_pointers(type
->ref
);
1583 size
= type_memsize((is_conformant_array(type
) ? type
->ref
: type
), &align
);
1585 start_offset
= *typestring_offset
;
1586 update_tfsoff(type
, start_offset
, file
);
1587 print_start_tfs_comment(file
, type
, start_offset
);
1588 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1589 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1590 *typestring_offset
+= 2;
1593 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1595 unsigned char tc
= type
->type
;
1597 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1599 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1600 *typestring_offset
+= 4;
1604 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1605 *typestring_offset
+= 2;
1608 if (is_conformant_array(type
))
1610 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1613 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1615 unsigned int elalign
= 0;
1616 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1618 if (type
->type
== RPC_FC_LGVARRAY
)
1620 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1621 *typestring_offset
+= 4;
1625 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1626 *typestring_offset
+= 2;
1629 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1630 *typestring_offset
+= 2;
1635 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1638 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1640 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1641 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1642 *typestring_offset
+= 2;
1643 write_pointer_description(file
, type
, typestring_offset
);
1644 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1645 *typestring_offset
+= 1;
1648 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1649 write_end(file
, typestring_offset
);
1653 unsigned int dim
= size_is
? 0 : type
->dim
;
1654 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1655 *typestring_offset
+= 2;
1657 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1660 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1662 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1663 write_end(file
, typestring_offset
);
1666 return start_offset
;
1669 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1671 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1672 const type_t
*ft
= last_field
->type
;
1674 if (ft
->declarray
&& is_conformant_array(ft
))
1677 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1678 return find_array_or_string_in_struct(last_field
->type
);
1683 static void write_struct_members(FILE *file
, const type_t
*type
,
1684 unsigned int *corroff
, unsigned int *typestring_offset
)
1687 unsigned short offset
= 0;
1691 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1693 type_t
*ft
= field
->type
;
1694 if (!ft
->declarray
|| !is_conformant_array(ft
))
1696 unsigned int align
= 0;
1697 size_t size
= type_memsize(ft
, &align
);
1700 if ((align
- 1) & offset
)
1702 unsigned char fc
= 0;
1706 fc
= RPC_FC_ALIGNM4
;
1709 fc
= RPC_FC_ALIGNM8
;
1712 error("write_struct_members: cannot align type %d\n", ft
->type
);
1714 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1715 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1716 *typestring_offset
+= 1;
1718 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1724 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1727 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1728 RPC_FC_STRUCTPAD1
+ padding
- 1,
1730 *typestring_offset
+= 1;
1733 write_end(file
, typestring_offset
);
1736 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1737 const char *name
, unsigned int *tfsoff
)
1739 const type_t
*save_current_structure
= current_structure
;
1740 unsigned int total_size
;
1742 size_t start_offset
;
1743 size_t array_offset
;
1744 int has_pointers
= 0;
1745 unsigned int align
= 0;
1746 unsigned int corroff
;
1750 current_structure
= type
;
1752 total_size
= type_memsize(type
, &align
);
1753 if (total_size
> USHRT_MAX
)
1754 error("structure size for %s exceeds %d bytes by %d bytes\n",
1755 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1757 if (type
->fields
) LIST_FOR_EACH_ENTRY(f
, type
->fields
, var_t
, entry
)
1758 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1760 if (!has_pointers
) has_pointers
= type_has_pointers(type
);
1762 array
= find_array_or_string_in_struct(type
);
1763 if (array
&& !processed(array
->type
))
1765 = is_attr(array
->attrs
, ATTR_STRING
)
1766 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
, FALSE
)
1767 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1770 write_descriptors(file
, type
, tfsoff
);
1772 start_offset
= *tfsoff
;
1773 update_tfsoff(type
, start_offset
, file
);
1774 print_start_tfs_comment(file
, type
, start_offset
);
1775 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1776 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1777 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1782 unsigned int absoff
= array
->type
->typestring_offset
;
1783 short reloff
= absoff
- *tfsoff
;
1784 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1785 reloff
, reloff
, absoff
);
1788 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1790 print_file(file
, 2, "NdrFcShort(0x0),\n");
1794 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1796 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1797 nothing is written to file yet. On the actual writing pass,
1798 this will have been updated. */
1799 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1800 short reloff
= absoff
- *tfsoff
;
1801 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1802 reloff
, reloff
, absoff
);
1805 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1806 (type
->type
== RPC_FC_CPSTRUCT
) ||
1807 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1809 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1810 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1812 write_pointer_description(file
, type
, tfsoff
);
1813 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1817 write_struct_members(file
, type
, &corroff
, tfsoff
);
1819 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1821 const var_list_t
*fs
= type
->fields
;
1824 type
->ptrdesc
= *tfsoff
;
1825 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1827 type_t
*ft
= f
->type
;
1829 write_pointer_tfs(file
, ft
, tfsoff
);
1830 else if (!ft
->declarray
&& is_conformant_array(ft
))
1832 unsigned int absoff
= ft
->typestring_offset
;
1833 short reloff
= absoff
- (*tfsoff
+ 2);
1834 int ptr_type
= get_attrv(f
->attrs
, ATTR_POINTERTYPE
);
1835 /* FIXME: We need to store pointer attributes for arrays
1836 so we don't lose pointer_default info. */
1838 ptr_type
= RPC_FC_UP
;
1839 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1840 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
1841 string_of_type(ptr_type
));
1842 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1843 reloff
, reloff
, absoff
);
1847 if (type
->ptrdesc
== *tfsoff
)
1851 current_structure
= save_current_structure
;
1852 return start_offset
;
1855 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1856 unsigned char flags
, size_t offset
,
1857 unsigned int *typeformat_offset
)
1859 size_t start_offset
= *typeformat_offset
;
1860 short reloff
= offset
- (*typeformat_offset
+ 2);
1861 int in_attr
, out_attr
;
1862 in_attr
= is_attr(attrs
, ATTR_IN
);
1863 out_attr
= is_attr(attrs
, ATTR_OUT
);
1864 if (!in_attr
&& !out_attr
) in_attr
= 1;
1866 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1869 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1872 string_of_type(pointer_type
));
1876 fprintf(file
, " [allocated_on_stack]");
1878 fprintf(file
, " [pointer_deref]");
1879 fprintf(file
, " */\n");
1882 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1883 *typeformat_offset
+= 4;
1885 return start_offset
;
1888 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1892 print_file(file
, 2, "NdrFcShort(0x0),\t/* No type */\n");
1894 else if (is_base_type(t
->type
))
1896 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1897 t
->type
, string_of_type(t
->type
));
1899 else if (t
->typestring_offset
)
1901 short reloff
= t
->typestring_offset
- *tfsoff
;
1902 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1903 reloff
, reloff
, t
->typestring_offset
);
1906 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1911 static size_t write_union_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1913 unsigned int align
= 0;
1914 unsigned int start_offset
;
1915 size_t size
= type_memsize(type
, &align
);
1918 type_t
*deftype
= NULL
;
1919 short nodeftype
= 0xffff;
1924 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1926 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
1927 fields
= uv
->type
->fields
;
1930 fields
= type
->fields
;
1932 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1934 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
1936 nbranch
+= list_count(cases
);
1938 write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
, TRUE
, tfsoff
);
1941 start_offset
= *tfsoff
;
1942 update_tfsoff(type
, start_offset
, file
);
1943 print_start_tfs_comment(file
, type
, start_offset
);
1944 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1946 const var_t
*sv
= LIST_ENTRY(list_head(type
->fields
), const var_t
, entry
);
1947 const type_t
*st
= sv
->type
;
1960 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1961 print_file(file
, 2, "0x%x,\t/* Switch type= %s */\n",
1962 0x40 | st
->type
, string_of_type(st
->type
));
1966 error("union switch type must be an integer, char, or enum\n");
1969 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
1970 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
1973 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1975 type_t
*ft
= f
->type
;
1976 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
1977 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
1980 if (cases
== NULL
&& !deflt
)
1981 error("union field %s with neither case nor default attribute\n", f
->name
);
1983 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
1985 /* MIDL doesn't check for duplicate cases, even though that seems
1986 like a reasonable thing to do, it just dumps them to the TFS
1987 like we're going to do here. */
1988 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
1990 write_branch_type(file
, ft
, tfsoff
);
1993 /* MIDL allows multiple default branches, even though that seems
1994 illogical, it just chooses the last one, which is what we will
2005 write_branch_type(file
, deftype
, tfsoff
);
2009 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
2013 return start_offset
;
2016 static size_t write_ip_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2017 unsigned int *typeformat_offset
)
2020 size_t start_offset
= *typeformat_offset
;
2021 expr_t
*iid
= get_attrp(attrs
, ATTR_IIDIS
);
2025 print_file(file
, 2, "0x2f, /* FC_IP */\n");
2026 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
2028 += write_conf_or_var_desc(file
, NULL
, 0, type
, iid
) + 2;
2032 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
2033 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
2036 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
2038 update_tfsoff(type
, start_offset
, file
);
2039 print_start_tfs_comment(file
, type
, start_offset
);
2040 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
2041 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2042 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
2043 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
2044 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
2045 for (i
= 0; i
< 8; ++i
)
2046 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
2049 fprintf(file
, "\n");
2051 *typeformat_offset
+= 18;
2053 return start_offset
;
2056 static size_t write_contexthandle_tfs(FILE *file
, const type_t
*type
,
2058 unsigned int *typeformat_offset
)
2060 size_t start_offset
= *typeformat_offset
;
2061 unsigned char flags
= 0;
2063 if (is_attr(current_iface
->attrs
, ATTR_STRICTCONTEXTHANDLE
))
2064 flags
|= NDR_STRICT_CONTEXT_HANDLE
;
2068 if (is_attr(var
->attrs
, ATTR_IN
))
2071 if (!is_attr(var
->attrs
, ATTR_OUT
))
2072 flags
|= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
;
2074 if (is_attr(var
->attrs
, ATTR_OUT
))
2077 WRITE_FCTYPE(file
, FC_BIND_CONTEXT
, *typeformat_offset
);
2078 print_file(file
, 2, "0x%x,\t/* Context flags: ", flags
);
2079 /* return and can't be null values overlap */
2080 if (((flags
& 0x21) != 0x21) && (flags
& NDR_CONTEXT_HANDLE_CANNOT_BE_NULL
))
2081 print_file(file
, 0, "can't be null, ");
2082 if (flags
& NDR_CONTEXT_HANDLE_SERIALIZE
)
2083 print_file(file
, 0, "serialize, ");
2084 if (flags
& NDR_CONTEXT_HANDLE_NO_SERIALIZE
)
2085 print_file(file
, 0, "no serialize, ");
2086 if (flags
& NDR_STRICT_CONTEXT_HANDLE
)
2087 print_file(file
, 0, "strict, ");
2088 if ((flags
& 0x21) == 0x20)
2089 print_file(file
, 0, "out, ");
2090 if ((flags
& 0x21) == 0x21)
2091 print_file(file
, 0, "return, ");
2093 print_file(file
, 0, "in, ");
2095 print_file(file
, 0, "via ptr, ");
2096 print_file(file
, 0, "*/\n");
2097 print_file(file
, 2, "0, /* FIXME: rundown routine index*/\n");
2098 print_file(file
, 2, "0, /* FIXME: param num */\n");
2099 *typeformat_offset
+= 4;
2101 return start_offset
;
2104 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
2105 type_t
*type
, const var_t
*var
,
2106 unsigned int *typeformat_offset
)
2110 if (is_context_handle(type
))
2111 return write_contexthandle_tfs(file
, type
, var
, typeformat_offset
);
2113 if (is_user_type(type
))
2115 write_user_tfs(file
, type
, typeformat_offset
);
2116 return type
->typestring_offset
;
2119 if ((last_ptr(type
) || last_array(type
)) && is_ptrchain_attr(var
, ATTR_STRING
))
2120 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
, TRUE
);
2126 off
= write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2127 ptr_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2128 /* Top level pointers to conformant arrays may be handled specially
2129 since we can bypass the pointer, but if the array is buried
2130 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2131 always need to write the pointer. */
2132 if (!ptr_type
&& var
->type
!= type
)
2133 /* FIXME: This should use pointer_default, but the information
2134 isn't kept around for arrays. */
2135 ptr_type
= RPC_FC_UP
;
2136 if (ptr_type
&& ptr_type
!= RPC_FC_RP
)
2138 unsigned int absoff
= type
->typestring_offset
;
2139 short reloff
= absoff
- (*typeformat_offset
+ 2);
2140 off
= *typeformat_offset
;
2141 print_file(file
, 0, "/* %d */\n", off
);
2142 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
2143 string_of_type(ptr_type
));
2144 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2145 reloff
, reloff
, absoff
);
2146 *typeformat_offset
+= 4;
2153 /* basic types don't need a type format string */
2154 if (is_base_type(type
->type
))
2160 case RPC_FC_PSTRUCT
:
2161 case RPC_FC_CSTRUCT
:
2162 case RPC_FC_CPSTRUCT
:
2163 case RPC_FC_CVSTRUCT
:
2164 case RPC_FC_BOGUS_STRUCT
:
2165 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
2166 case RPC_FC_ENCAPSULATED_UNION
:
2167 case RPC_FC_NON_ENCAPSULATED_UNION
:
2168 return write_union_tfs(file
, type
, typeformat_offset
);
2170 case RPC_FC_BIND_PRIMITIVE
:
2174 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
2177 else if (last_ptr(type
))
2179 size_t start_offset
= *typeformat_offset
;
2180 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2181 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2182 const type_t
*base
= type
->ref
;
2184 if (base
->type
== RPC_FC_IP
2186 && is_attr(var
->attrs
, ATTR_IIDIS
)))
2188 return write_ip_tfs(file
, var
->attrs
, type
, typeformat_offset
);
2191 /* special case for pointers to base types */
2192 if (is_base_type(base
->type
))
2194 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2195 type
->type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
2196 string_of_type(type
->type
),
2197 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
2198 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
2199 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
2200 *typeformat_offset
+= 4;
2201 return start_offset
;
2205 assert(is_ptr(type
));
2207 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
2209 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
2210 return write_pointer_only_tfs(file
, var
->attrs
, type
->type
,
2211 !last_ptr(type
) ? 0x10 : 0,
2212 offset
, typeformat_offset
);
2215 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2216 const char *name
, int write_ptr
, unsigned int *tfsoff
)
2220 if (is_user_type(type
))
2222 write_user_tfs(file
, type
, tfsoff
);
2224 else if (is_ptr(type
))
2226 type_t
*ref
= type
->ref
;
2228 if (ref
->type
== RPC_FC_IP
2230 && is_attr(attrs
, ATTR_IIDIS
)))
2232 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2236 if (!processed(ref
) && !is_base_type(ref
->type
))
2237 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2240 write_pointer_tfs(file
, type
, tfsoff
);
2245 else if (last_array(type
) && is_attr(attrs
, ATTR_STRING
))
2247 write_string_tfs(file
, attrs
, type
, name
, tfsoff
, FALSE
);
2249 else if (type
->declarray
&& is_conformant_array(type
))
2250 ; /* conformant arrays and strings are handled specially */
2251 else if (is_array(type
))
2253 write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
2254 if (is_conformant_array(type
))
2257 else if (is_struct(type
->type
))
2259 if (!processed(type
))
2260 write_struct_tfs(file
, type
, name
, tfsoff
);
2262 else if (is_union(type
->type
))
2264 if (!processed(type
))
2265 write_union_tfs(file
, type
, tfsoff
);
2267 else if (!is_base_type(type
->type
))
2268 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2274 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2277 const ifref_t
*iface
;
2278 unsigned int typeformat_offset
= 2;
2280 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2282 if (!pred(iface
->iface
))
2285 if (iface
->iface
->funcs
)
2288 current_iface
= iface
;
2289 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2291 if (is_local(func
->def
->attrs
)) continue;
2293 current_func
= func
;
2295 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2298 write_typeformatstring_var(
2299 file
, 2, func
, var
->type
, var
,
2300 &typeformat_offset
),
2306 return typeformat_offset
+ 1;
2310 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2314 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2315 print_file(file
, indent
, "{\n");
2317 print_file(file
, indent
, "0,\n");
2318 print_file(file
, indent
, "{\n");
2320 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2322 set_all_tfswrite(TRUE
);
2323 process_tfs(file
, ifaces
, pred
);
2325 print_file(file
, indent
, "0x0\n");
2327 print_file(file
, indent
, "}\n");
2329 print_file(file
, indent
, "};\n");
2330 print_file(file
, indent
, "\n");
2333 static unsigned int get_required_buffer_size_type(
2334 const type_t
*type
, const char *name
, unsigned int *alignment
)
2337 if (is_user_type(type
))
2340 const type_t
*utype
= get_user_type(type
, &uname
);
2341 return get_required_buffer_size_type(utype
, uname
, alignment
);
2365 case RPC_FC_ERROR_STATUS_T
:
2375 case RPC_FC_BIND_PRIMITIVE
:
2379 case RPC_FC_PSTRUCT
:
2383 if (!type
->fields
) return 0;
2384 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2386 unsigned int alignment
;
2387 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2395 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2396 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2399 case RPC_FC_SMFARRAY
:
2400 case RPC_FC_LGFARRAY
:
2401 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2409 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2411 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2412 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2415 if (!in_attr
&& !out_attr
)
2420 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2421 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2427 if (pass
== PASS_OUT
)
2429 if (out_attr
&& is_ptr(var
->type
))
2431 type_t
*type
= var
->type
;
2433 if (type
->type
== RPC_FC_STRUCT
)
2436 unsigned int size
= 36;
2438 if (!type
->fields
) return size
;
2439 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2442 size
+= get_required_buffer_size_type(
2443 field
->type
, field
->name
, &align
);
2452 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2453 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2455 if (is_ptr(var
->type
))
2457 type_t
*type
= var
->type
;
2459 if (is_base_type(type
->type
))
2463 else if (type
->type
== RPC_FC_STRUCT
)
2465 unsigned int size
= 36;
2468 if (!type
->fields
) return size
;
2469 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2472 size
+= get_required_buffer_size_type(
2473 field
->type
, field
->name
, &align
);
2480 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2484 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2487 unsigned int total_size
= 0, alignment
;
2491 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2493 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2494 total_size
+= alignment
;
2498 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
2500 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
2501 total_size
+= alignment
;
2506 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2507 enum remoting_phase phase
,
2508 const var_t
*var
, unsigned int type_offset
)
2510 const char *function
;
2513 case PHASE_BUFFERSIZE
:
2514 function
= "BufferSize";
2517 function
= "Marshall";
2519 case PHASE_UNMARSHAL
:
2520 function
= "Unmarshall";
2530 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2532 print_file(file
, indent
, "&_StubMsg,\n");
2533 print_file(file
, indent
, "%s%s%s%s,\n",
2534 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2535 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2536 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2538 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2539 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2540 if (phase
== PHASE_UNMARSHAL
)
2541 print_file(file
, indent
, "0);\n");
2545 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2546 enum pass pass
, const var_t
*var
,
2547 const char *varname
)
2549 type_t
*type
= var
->type
;
2551 unsigned int alignment
= 0;
2552 unsigned char rtype
;
2554 /* no work to do for other phases, buffer sizing is done elsewhere */
2555 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2558 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2582 case RPC_FC_ERROR_STATUS_T
:
2594 case RPC_FC_BIND_PRIMITIVE
:
2595 /* no marshalling needed */
2599 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2603 if (phase
== PHASE_MARSHAL
)
2604 print_file(file
, indent
, "MIDL_memset(_StubMsg.Buffer, 0, (0x%x - (long)_StubMsg.Buffer) & 0x%x);\n", alignment
, alignment
- 1);
2605 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2606 alignment
- 1, alignment
- 1);
2608 if (phase
== PHASE_MARSHAL
)
2610 print_file(file
, indent
, "*(");
2611 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2613 fprintf(file
, " *)_StubMsg.Buffer = *");
2615 fprintf(file
, " *)_StubMsg.Buffer = ");
2616 fprintf(file
, "%s", varname
);
2617 fprintf(file
, ";\n");
2619 else if (phase
== PHASE_UNMARSHAL
)
2621 print_file(file
, indent
, "if (_StubMsg.Buffer + sizeof(");
2622 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2623 fprintf(file
, ") > _StubMsg.BufferEnd)\n");
2624 print_file(file
, indent
, "{\n");
2625 print_file(file
, indent
+ 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
2626 print_file(file
, indent
, "}\n");
2627 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2628 print_file(file
, indent
, "");
2630 print_file(file
, indent
, "*");
2631 fprintf(file
, "%s", varname
);
2632 if (pass
== PASS_IN
&& is_ptr(type
))
2633 fprintf(file
, " = (");
2635 fprintf(file
, " = *(");
2636 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2637 fprintf(file
, " *)_StubMsg.Buffer;\n");
2640 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2641 write_type_decl(file
, var
->type
, NULL
);
2642 fprintf(file
, ");\n");
2645 /* returns whether the MaxCount, Offset or ActualCount members need to be
2646 * filled in for the specified phase */
2647 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2649 return (phase
!= PHASE_UNMARSHAL
);
2652 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2656 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2662 error("%s: multidimensional conformant"
2663 " arrays not supported at the top level\n",
2670 static void write_remoting_arg(FILE *file
, int indent
, const func_t
*func
,
2671 enum pass pass
, enum remoting_phase phase
,
2674 int in_attr
, out_attr
, pointer_type
;
2675 const type_t
*type
= var
->type
;
2676 unsigned char rtype
;
2677 size_t start_offset
= type
->typestring_offset
;
2679 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2681 pointer_type
= RPC_FC_RP
;
2683 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2684 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2685 if (!in_attr
&& !out_attr
)
2688 if (phase
!= PHASE_FREE
)
2692 if (!in_attr
) return;
2695 if (!out_attr
) return;
2703 if (is_context_handle(type
))
2705 if (phase
== PHASE_MARSHAL
)
2707 if (pass
== PASS_IN
)
2709 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2710 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2711 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type
) ? "*" : "", var
->name
);
2712 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2716 print_file(file
, indent
, "NdrServerContextNewMarshall(\n");
2717 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2718 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2719 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var
->type
));
2720 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2723 else if (phase
== PHASE_UNMARSHAL
)
2725 if (pass
== PASS_OUT
)
2728 print_file(file
, indent
, "*%s = 0;\n", var
->name
);
2729 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2730 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2731 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2732 print_file(file
, indent
+ 1, "_Handle);\n");
2736 print_file(file
, indent
, "%s = NdrServerContextNewUnmarshall(\n", var
->name
);
2737 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2738 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset
);
2742 else if (is_user_type(var
->type
))
2744 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2746 else if (is_string_type(var
->attrs
, var
->type
))
2748 if (is_array(type
) && !is_conformant_array(type
))
2749 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2752 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2754 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2755 write_expr(file
, type
->size_is
, 1);
2756 fprintf(file
, ";\n");
2759 if ((phase
== PHASE_FREE
) || (pointer_type
== RPC_FC_UP
))
2760 print_phase_function(file
, indent
, "Pointer", phase
, var
,
2761 start_offset
- (type
->size_is
? 4 : 2));
2763 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2767 else if (is_array(type
))
2769 unsigned char tc
= type
->type
;
2770 const char *array_type
= "FixedArray";
2772 /* We already have the size_is expression since it's at the
2773 top level, but do checks for multidimensional conformant
2774 arrays. When we handle them, we'll need to extend this
2775 function to return a list, and then we'll actually use
2776 the return value. */
2777 get_size_is_expr(type
, var
->name
);
2779 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2781 if (is_size_needed_for_phase(phase
))
2783 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2784 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2785 write_expr(file
, type
->length_is
, 1);
2786 fprintf(file
, ";\n\n");
2788 array_type
= "VaryingArray";
2790 else if (tc
== RPC_FC_CARRAY
)
2792 if (is_size_needed_for_phase(phase
))
2794 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2795 write_expr(file
, type
->size_is
, 1);
2796 fprintf(file
, ";\n\n");
2798 array_type
= "ConformantArray";
2800 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2802 if (is_size_needed_for_phase(phase
))
2806 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2807 write_expr(file
, type
->size_is
, 1);
2808 fprintf(file
, ";\n");
2810 if (type
->length_is
)
2812 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2813 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2814 write_expr(file
, type
->length_is
, 1);
2815 fprintf(file
, ";\n\n");
2818 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2820 : "ConformantVaryingArray");
2823 if (pointer_type
!= RPC_FC_RP
) array_type
= "Pointer";
2824 print_phase_function(file
, indent
, array_type
, phase
, var
, start_offset
);
2825 if (phase
== PHASE_FREE
&& pointer_type
== RPC_FC_RP
)
2827 /* these are all unmarshalled by allocating memory */
2828 if (type
->type
== RPC_FC_BOGUS_ARRAY
||
2829 type
->type
== RPC_FC_CVARRAY
||
2830 ((type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
) && in_attr
) ||
2831 (type
->type
== RPC_FC_CARRAY
&& !in_attr
))
2833 print_file(file
, indent
, "if (%s)\n", var
->name
);
2835 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2839 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2841 if (phase
!= PHASE_FREE
)
2842 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2844 else if (!is_ptr(var
->type
))
2849 case RPC_FC_PSTRUCT
:
2850 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2852 case RPC_FC_CSTRUCT
:
2853 case RPC_FC_CPSTRUCT
:
2854 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2856 case RPC_FC_CVSTRUCT
:
2857 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2859 case RPC_FC_BOGUS_STRUCT
:
2860 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2863 if (is_base_type( var
->type
->ref
->type
))
2865 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2867 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2869 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2870 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2875 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2877 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2878 write_expr( file
, iid
, 1 );
2879 fprintf( file
, ";\n\n" );
2881 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2885 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2890 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2892 if (phase
!= PHASE_FREE
)
2893 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2895 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2897 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2898 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2903 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2905 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2907 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long) " );
2908 write_expr( file
, iid
, 1 );
2909 fprintf( file
, ";\n\n" );
2913 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2914 write_expr(file
, sx
, 1);
2915 fprintf(file
, ";\n\n");
2917 if (var
->type
->ref
->type
== RPC_FC_IP
)
2918 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
2920 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2923 fprintf(file
, "\n");
2926 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
2927 enum pass pass
, enum remoting_phase phase
)
2929 if (phase
== PHASE_BUFFERSIZE
&& pass
!= PASS_RETURN
)
2931 unsigned int size
= get_function_buffer_size( func
, pass
);
2932 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
2935 if (pass
== PASS_RETURN
)
2939 var
.name
= xstrdup( "_RetVal" );
2940 write_remoting_arg( file
, indent
, func
, pass
, phase
, &var
);
2948 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2949 write_remoting_arg( file
, indent
, func
, pass
, phase
, var
);
2954 size_t get_size_procformatstring_var(const var_t
*var
)
2956 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
2960 size_t get_size_procformatstring_func(const func_t
*func
)
2965 /* argument list size */
2967 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2968 size
+= get_size_procformatstring_var(var
);
2970 /* return value size */
2971 if (is_void(func
->def
->type
))
2972 size
+= 2; /* FC_END and FC_PAD */
2974 size
+= get_size_procformatstring_var(func
->def
);
2979 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
2981 const ifref_t
*iface
;
2985 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2987 if (!pred(iface
->iface
))
2990 if (iface
->iface
->funcs
)
2991 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2992 if (!is_local(func
->def
->attrs
))
2993 size
+= get_size_procformatstring_func( func
);
2998 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
3000 set_all_tfswrite(FALSE
);
3001 return process_tfs(NULL
, ifaces
, pred
);
3004 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
3005 const var_list_t
*fields
, const char *structvar
)
3011 fprintf(h
, "%lu", e
->u
.lval
);
3014 fprintf(h
, "0x%lx", e
->u
.lval
);
3017 fprintf(h
, "%#.15g", e
->u
.dval
);
3019 case EXPR_TRUEFALSE
:
3021 fprintf(h
, "FALSE");
3025 case EXPR_IDENTIFIER
:
3028 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
3029 if (!strcmp(e
->u
.sval
, field
->name
))
3031 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
3035 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
3040 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3044 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3048 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3052 write_type_decl(h
, e
->u
.tref
, NULL
);
3054 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3057 fprintf(h
, "sizeof(");
3058 write_type_decl(h
, e
->u
.tref
, NULL
);
3069 if (brackets
) fprintf(h
, "(");
3070 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3072 case EXPR_SHL
: fprintf(h
, " << "); break;
3073 case EXPR_SHR
: fprintf(h
, " >> "); break;
3074 case EXPR_MUL
: fprintf(h
, " * "); break;
3075 case EXPR_DIV
: fprintf(h
, " / "); break;
3076 case EXPR_ADD
: fprintf(h
, " + "); break;
3077 case EXPR_SUB
: fprintf(h
, " - "); break;
3078 case EXPR_AND
: fprintf(h
, " & "); break;
3079 case EXPR_OR
: fprintf(h
, " | "); break;
3082 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3083 if (brackets
) fprintf(h
, ")");
3086 if (brackets
) fprintf(h
, "(");
3087 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3089 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3091 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3092 if (brackets
) fprintf(h
, ")");
3094 case EXPR_ADDRESSOF
:
3096 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3102 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3104 int in_attr
, out_attr
;
3106 const var_t
*def
= func
->def
;
3109 /* declare return value '_RetVal' */
3110 if (!is_void(def
->type
))
3112 print_file(file
, indent
, "");
3113 write_type_decl_left(file
, def
->type
);
3114 fprintf(file
, " _RetVal;\n");
3120 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3122 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3124 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3125 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3126 if (!out_attr
&& !in_attr
)
3129 if (is_context_handle(var
->type
))
3130 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3133 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3135 print_file(file
, indent
, "");
3136 write_type_decl(file
, var
->type
->declarray
? var
->type
: var
->type
->ref
,
3138 fprintf(file
, ";\n");
3141 print_file(file
, indent
, "");
3142 write_type_decl_left(file
, var
->type
);
3144 if (var
->type
->declarray
) {
3145 fprintf(file
, "( *");
3146 write_name(file
, var
);
3147 fprintf(file
, " )");
3149 write_name(file
, var
);
3150 write_type_right(file
, var
->type
, FALSE
);
3151 fprintf(file
, ";\n");
3153 if (decl_indirect(var
->type
))
3154 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3155 var
->name
, var
->name
);
3161 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3163 int in_attr
, out_attr
;
3170 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3172 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3173 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3174 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3175 if (!out_attr
&& !in_attr
)
3180 print_file(file
, indent
, "");
3181 write_name(file
, var
);
3183 if (is_context_handle(var
->type
))
3185 fprintf(file
, " = NdrContextHandleInitialize(\n");
3186 print_file(file
, indent
+ 1, "&_StubMsg,\n");
3187 print_file(file
, indent
+ 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
3188 var
->type
->typestring_offset
);
3190 else if (var
->type
->size_is
)
3192 unsigned int size
, align
= 0;
3193 type_t
*type
= var
->type
;
3195 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3196 for ( ; type
->size_is
; type
= type
->ref
)
3198 write_expr(file
, type
->size_is
, TRUE
);
3199 fprintf(file
, " * ");
3201 size
= type_memsize(type
, &align
);
3202 fprintf(file
, "%u);\n", size
);
3204 else if (!is_string
)
3206 fprintf(file
, " = &_W%u;\n", i
);
3207 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3208 print_file(file
, indent
, "_W%u = 0;\n", i
);
3216 fprintf(file
, "\n");
3220 int write_expr_eval_routines(FILE *file
, const char *iface
)
3222 static const char *var_name
= "pS";
3224 struct expr_eval_routine
*eval
;
3225 unsigned short callback_offset
= 0;
3227 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3229 const char *name
= eval
->structure
->name
;
3230 const var_list_t
*fields
= eval
->structure
->fields
;
3233 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3234 iface
, name
, callback_offset
);
3235 print_file(file
, 0, "{\n");
3236 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3237 name
, var_name
, name
, eval
->baseoff
);
3238 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3239 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3240 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3241 fprintf(file
, ";\n");
3242 print_file(file
, 0, "}\n\n");
3248 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3250 struct expr_eval_routine
*eval
;
3251 struct expr_eval_routine
*cursor
;
3252 unsigned short callback_offset
= 0;
3254 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3255 fprintf(file
, "{\n");
3257 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3259 const char *name
= eval
->structure
->name
;
3260 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3262 list_remove(&eval
->entry
);
3266 fprintf(file
, "};\n\n");
3269 void write_user_quad_list(FILE *file
)
3273 if (list_empty(&user_type_list
))
3276 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3277 fprintf(file
, "{\n");
3278 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3280 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3281 print_file(file
, 1, "{\n");
3282 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3283 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3284 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3285 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3286 print_file(file
, 1, "}%s\n", sep
);
3288 fprintf(file
, "};\n\n");
3291 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3293 const struct str_list_entry_t
*endpoint
;
3296 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3297 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3298 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3300 print_file( f
, 1, "{ (const unsigned char *)\"" );
3301 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3303 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3306 if (!*p
) goto error
;
3307 if (p
[1] != '[') goto error
;
3309 fprintf( f
, "\", (const unsigned char *)\"" );
3310 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3312 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3315 if (*p
!= ']') goto error
;
3316 fprintf( f
, "\" },\n" );
3318 print_file( f
, 0, "};\n\n" );
3322 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);