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"
41 #include "wine/list.h"
46 static const func_t
*current_func
;
47 static const type_t
*current_structure
;
49 static struct list expr_eval_routines
= LIST_INIT(expr_eval_routines
);
50 struct expr_eval_routine
53 const type_t
*structure
;
58 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
);
59 static size_t write_struct_tfs(FILE *file
, type_t
*type
, const char *name
, unsigned int *tfsoff
);
60 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
61 const char *name
, int write_ptr
, unsigned int *tfsoff
);
62 static const var_t
*find_array_or_string_in_struct(const type_t
*type
);
64 const char *string_of_type(unsigned char type
)
68 case RPC_FC_BYTE
: return "FC_BYTE";
69 case RPC_FC_CHAR
: return "FC_CHAR";
70 case RPC_FC_SMALL
: return "FC_SMALL";
71 case RPC_FC_USMALL
: return "FC_USMALL";
72 case RPC_FC_WCHAR
: return "FC_WCHAR";
73 case RPC_FC_SHORT
: return "FC_SHORT";
74 case RPC_FC_USHORT
: return "FC_USHORT";
75 case RPC_FC_LONG
: return "FC_LONG";
76 case RPC_FC_ULONG
: return "FC_ULONG";
77 case RPC_FC_FLOAT
: return "FC_FLOAT";
78 case RPC_FC_HYPER
: return "FC_HYPER";
79 case RPC_FC_DOUBLE
: return "FC_DOUBLE";
80 case RPC_FC_ENUM16
: return "FC_ENUM16";
81 case RPC_FC_ENUM32
: return "FC_ENUM32";
82 case RPC_FC_IGNORE
: return "FC_IGNORE";
83 case RPC_FC_ERROR_STATUS_T
: return "FC_ERROR_STATUS_T";
84 case RPC_FC_RP
: return "FC_RP";
85 case RPC_FC_UP
: return "FC_UP";
86 case RPC_FC_OP
: return "FC_OP";
87 case RPC_FC_FP
: return "FC_FP";
88 case RPC_FC_ENCAPSULATED_UNION
: return "FC_ENCAPSULATED_UNION";
89 case RPC_FC_NON_ENCAPSULATED_UNION
: return "FC_NON_ENCAPSULATED_UNION";
90 case RPC_FC_STRUCT
: return "FC_STRUCT";
91 case RPC_FC_PSTRUCT
: return "FC_PSTRUCT";
92 case RPC_FC_CSTRUCT
: return "FC_CSTRUCT";
93 case RPC_FC_CPSTRUCT
: return "FC_CPSTRUCT";
94 case RPC_FC_CVSTRUCT
: return "FC_CVSTRUCT";
95 case RPC_FC_BOGUS_STRUCT
: return "FC_BOGUS_STRUCT";
96 case RPC_FC_SMFARRAY
: return "FC_SMFARRAY";
97 case RPC_FC_LGFARRAY
: return "FC_LGFARRAY";
98 case RPC_FC_SMVARRAY
: return "FC_SMVARRAY";
99 case RPC_FC_LGVARRAY
: return "FC_LGVARRAY";
100 case RPC_FC_CARRAY
: return "FC_CARRAY";
101 case RPC_FC_CVARRAY
: return "FC_CVARRAY";
102 case RPC_FC_BOGUS_ARRAY
: return "FC_BOGUS_ARRAY";
103 case RPC_FC_ALIGNM4
: return "FC_ALIGNM4";
104 case RPC_FC_ALIGNM8
: return "FC_ALIGNM8";
105 case RPC_FC_POINTER
: return "FC_POINTER";
106 case RPC_FC_C_CSTRING
: return "FC_C_CSTRING";
107 case RPC_FC_C_WSTRING
: return "FC_C_WSTRING";
108 case RPC_FC_CSTRING
: return "FC_CSTRING";
109 case RPC_FC_WSTRING
: return "FC_WSTRING";
111 error("string_of_type: unknown type 0x%02x\n", type
);
116 int is_struct(unsigned char type
)
123 case RPC_FC_CPSTRUCT
:
124 case RPC_FC_CVSTRUCT
:
125 case RPC_FC_BOGUS_STRUCT
:
132 static int is_non_complex_struct(const type_t
*type
)
139 case RPC_FC_CPSTRUCT
:
140 case RPC_FC_CVSTRUCT
:
147 int is_union(unsigned char type
)
151 case RPC_FC_ENCAPSULATED_UNION
:
152 case RPC_FC_NON_ENCAPSULATED_UNION
:
159 static unsigned short user_type_offset(const char *name
)
162 unsigned short off
= 0;
163 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
165 if (strcmp(name
, ut
->name
) == 0)
169 error("user_type_offset: couldn't find type (%s)\n", name
);
173 static void update_tfsoff(type_t
*type
, unsigned int offset
, FILE *file
)
175 type
->typestring_offset
= offset
;
176 if (file
) type
->tfswrite
= FALSE
;
179 static void guard_rec(type_t
*type
)
181 /* types that contain references to themselves (like a linked list),
182 need to be shielded from infinite recursion when writing embedded
184 if (type
->typestring_offset
)
185 type
->tfswrite
= FALSE
;
187 type
->typestring_offset
= 1;
190 static type_t
*get_user_type(const type_t
*t
, const char **pname
)
194 type_t
*ut
= get_attrp(t
->attrs
, ATTR_WIREMARSHAL
);
202 if (t
->kind
== TKIND_ALIAS
)
209 int is_user_type(const type_t
*t
)
211 return get_user_type(t
, NULL
) != NULL
;
214 static int is_embedded_complex(const type_t
*type
)
216 unsigned char tc
= type
->type
;
217 return is_struct(tc
) || is_union(tc
) || is_array(type
) || is_user_type(type
)
218 || (is_ptr(type
) && type
->ref
->type
== RPC_FC_IP
);
221 static const char *get_context_handle_type_name(const type_t
*type
)
224 for (t
= type
; is_ptr(t
); t
= t
->ref
)
225 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
231 /* This is actually fairly involved to implement precisely, due to the
232 effects attributes may have and things like that. Right now this is
233 only used for optimization, so just check for a very small set of
234 criteria that guarantee the types are equivalent; assume every thing
235 else is different. */
236 static int compare_type(const type_t
*a
, const type_t
*b
)
241 && strcmp(a
->name
, b
->name
) == 0))
243 /* Ordering doesn't need to be implemented yet. */
247 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
251 if (a
->type
!= b
->type
)
252 return a
->type
- b
->type
;
259 return a
->u
.lval
- b
->u
.lval
;
261 return a
->u
.dval
- b
->u
.dval
;
262 case EXPR_IDENTIFIER
:
263 return strcmp(a
->u
.sval
, b
->u
.sval
);
265 ret
= compare_expr(a
->ref
, b
->ref
);
268 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
271 return compare_expr(a
->ext2
, b
->ext2
);
280 ret
= compare_expr(a
->ref
, b
->ref
);
283 return compare_expr(a
->u
.ext
, b
->u
.ext
);
285 ret
= compare_type(a
->u
.tref
, b
->u
.tref
);
292 return compare_expr(a
->ref
, b
->ref
);
294 return compare_type(a
->u
.tref
, b
->u
.tref
);
301 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
304 fprintf(file, "/* %2u */\n", typestring_offset); \
305 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
309 static void print_file(FILE *file
, int indent
, const char *format
, ...)
312 va_start(va
, format
);
313 print(file
, indent
, format
, va
);
317 void print(FILE *file
, int indent
, const char *format
, va_list va
)
321 if (format
[0] != '\n')
324 vfprintf(file
, format
, va
);
328 void write_parameters_init(FILE *file
, int indent
, const func_t
*func
)
335 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
337 const type_t
*t
= var
->type
;
338 const char *n
= var
->name
;
339 if (decl_indirect(t
))
340 print_file(file
, indent
, "MIDL_memset(&%s, 0, sizeof %s);\n", n
, n
);
341 else if (is_ptr(t
) || is_array(t
))
342 print_file(file
, indent
, "%s = 0;\n", n
);
348 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
350 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
351 print_file(f
, indent
, "{\n");
352 print_file(f
, indent
+ 1, "short Pad;\n");
353 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
354 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
355 print_file(f
, indent
, "\n");
358 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, type_pred_t pred
)
360 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
361 get_size_typeformatstring(ifaces
, pred
));
363 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
364 get_size_procformatstring(ifaces
, pred
));
367 write_formatdesc(f
, indent
, "TYPE");
368 write_formatdesc(f
, indent
, "PROC");
370 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
371 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
372 print_file(f
, indent
, "\n");
375 static inline int is_base_type(unsigned char type
)
394 case RPC_FC_ERROR_STATUS_T
:
395 case RPC_FC_BIND_PRIMITIVE
:
403 int decl_indirect(const type_t
*t
)
405 return is_user_type(t
)
406 || (!is_base_type(t
->type
)
411 static size_t write_procformatstring_var(FILE *file
, int indent
,
412 const var_t
*var
, int is_return
)
415 const type_t
*type
= var
->type
;
417 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
418 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
420 if (!is_in
&& !is_out
) is_in
= TRUE
;
422 if (!type
->declarray
&& is_base_type(type
->type
))
425 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
427 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
429 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
431 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
432 size
= 2; /* includes param type prefix */
434 else if (is_base_type(type
->type
))
436 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
437 size
= 2; /* includes param type prefix */
441 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
448 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
449 else if (is_in
&& is_out
)
450 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
452 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
454 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
456 print_file(file
, indent
, "0x01,\n");
457 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
458 size
= 4; /* includes param type prefix */
463 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
465 const ifref_t
*iface
;
469 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
470 print_file(file
, indent
, "{\n");
472 print_file(file
, indent
, "0,\n");
473 print_file(file
, indent
, "{\n");
476 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
478 if (!pred(iface
->iface
))
481 if (iface
->iface
->funcs
)
484 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
486 if (is_local(func
->def
->attrs
)) continue;
487 /* emit argument data */
490 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
491 write_procformatstring_var(file
, indent
, var
, FALSE
);
494 /* emit return value data */
496 if (is_void(var
->type
))
498 print_file(file
, indent
, "0x5b, /* FC_END */\n");
499 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
502 write_procformatstring_var(file
, indent
, var
, TRUE
);
507 print_file(file
, indent
, "0x0\n");
509 print_file(file
, indent
, "}\n");
511 print_file(file
, indent
, "};\n");
512 print_file(file
, indent
, "\n");
515 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
517 if (is_base_type(type
->type
))
519 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
520 *typestring_offset
+= 1;
527 /* write conformance / variance descriptor */
528 static size_t write_conf_or_var_desc(FILE *file
, const type_t
*structure
,
529 unsigned int baseoff
, const type_t
*type
,
532 unsigned char operator_type
= 0;
533 unsigned char conftype
= RPC_FC_NORMAL_CONFORMANCE
;
534 const char *conftype_string
= "";
535 const char *operator_string
= "no operators";
536 const expr_t
*subexpr
;
540 print_file(file
, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
546 /* Top-level conformance calculations are done inline. */
547 print_file (file
, 2, "0x%x,\t/* Corr desc: parameter */\n",
548 RPC_FC_TOP_LEVEL_CONFORMANCE
);
549 print_file (file
, 2, "0x0,\n");
550 print_file (file
, 2, "NdrFcShort(0x0),\n");
556 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
557 error("write_conf_or_var_desc: constant value %ld is greater than "
558 "the maximum constant size of %d\n", expr
->cval
,
559 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
561 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
562 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
563 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
564 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
569 if (is_ptr(type
) || (is_array(type
) && !type
->declarray
))
571 conftype
= RPC_FC_POINTER_CONFORMANCE
;
572 conftype_string
= "field pointer, ";
576 switch (subexpr
->type
)
579 subexpr
= subexpr
->ref
;
580 operator_type
= RPC_FC_DEREFERENCE
;
581 operator_string
= "FC_DEREFERENCE";
584 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
586 subexpr
= subexpr
->ref
;
587 operator_type
= RPC_FC_DIV_2
;
588 operator_string
= "FC_DIV_2";
592 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
594 subexpr
= subexpr
->ref
;
595 operator_type
= RPC_FC_MULT_2
;
596 operator_string
= "FC_MULT_2";
600 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
602 subexpr
= subexpr
->ref
;
603 operator_type
= RPC_FC_SUB_1
;
604 operator_string
= "FC_SUB_1";
608 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
610 subexpr
= subexpr
->ref
;
611 operator_type
= RPC_FC_ADD_1
;
612 operator_string
= "FC_ADD_1";
619 if (subexpr
->type
== EXPR_IDENTIFIER
)
621 const type_t
*correlation_variable
= NULL
;
622 unsigned char correlation_variable_type
;
623 unsigned char param_type
= 0;
627 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
629 unsigned int align
= 0;
630 /* FIXME: take alignment into account */
631 if (var
->name
&& !strcmp(var
->name
, subexpr
->u
.sval
))
633 correlation_variable
= var
->type
;
636 offset
+= type_memsize(var
->type
, &align
);
638 if (!correlation_variable
)
639 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
643 correlation_variable_type
= correlation_variable
->type
;
645 switch (correlation_variable_type
)
649 param_type
= RPC_FC_SMALL
;
653 param_type
= RPC_FC_USMALL
;
658 param_type
= RPC_FC_SHORT
;
661 param_type
= RPC_FC_USHORT
;
665 param_type
= RPC_FC_LONG
;
668 param_type
= RPC_FC_ULONG
;
674 if (sizeof(void *) == 4) /* FIXME */
675 param_type
= RPC_FC_LONG
;
677 param_type
= RPC_FC_HYPER
;
680 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
681 correlation_variable_type
);
684 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
685 conftype
| param_type
, conftype_string
, string_of_type(param_type
));
686 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
687 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
692 unsigned int callback_offset
= 0;
693 struct expr_eval_routine
*eval
;
696 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
698 if (!strcmp (eval
->structure
->name
, structure
->name
)
699 && !compare_expr (eval
->expr
, expr
))
709 eval
= xmalloc (sizeof(*eval
));
710 eval
->structure
= structure
;
711 eval
->baseoff
= baseoff
;
713 list_add_tail (&expr_eval_routines
, &eval
->entry
);
716 if (callback_offset
> USHRT_MAX
)
717 error("Maximum number of callback routines reached\n");
719 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n", conftype
, conftype_string
);
720 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
721 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
726 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
728 int have_align
= FALSE
;
732 if (!fields
) return 0;
733 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
735 unsigned int falign
= 0;
736 size_t fsize
= type_memsize(v
->type
, &falign
);
742 size
= (size
+ (falign
- 1)) & ~(falign
- 1);
746 size
= (size
+ (*align
- 1)) & ~(*align
- 1);
750 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
752 size_t size
, maxs
= 0;
753 unsigned int align
= *pmaxa
;
756 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
758 /* we could have an empty default field with NULL type */
761 size
= type_memsize(v
->type
, &align
);
762 if (maxs
< size
) maxs
= size
;
763 if (*pmaxa
< align
) *pmaxa
= align
;
770 int get_padding(const var_list_t
*fields
)
772 unsigned short offset
= 0;
779 LIST_FOR_EACH_ENTRY(f
, fields
, const var_t
, entry
)
781 type_t
*ft
= f
->type
;
782 unsigned int align
= 0;
783 size_t size
= type_memsize(ft
, &align
);
786 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
790 return ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
793 size_t type_memsize(const type_t
*t
, unsigned int *align
)
797 if (t
->declarray
&& is_conformant_array(t
))
799 type_memsize(t
->ref
, align
);
802 else if (is_ptr(t
) || is_conformant_array(t
))
804 size
= sizeof(void *);
805 if (size
> *align
) *align
= size
;
807 else switch (t
->type
)
814 if (size
> *align
) *align
= size
;
821 if (size
> *align
) *align
= size
;
825 case RPC_FC_ERROR_STATUS_T
:
829 if (size
> *align
) *align
= size
;
834 if (size
> *align
) *align
= size
;
837 case RPC_FC_CVSTRUCT
:
838 case RPC_FC_CPSTRUCT
:
841 case RPC_FC_BOGUS_STRUCT
:
842 size
= fields_memsize(t
->fields
, align
);
844 case RPC_FC_ENCAPSULATED_UNION
:
845 case RPC_FC_NON_ENCAPSULATED_UNION
:
846 size
= union_memsize(t
->fields
, align
);
848 case RPC_FC_SMFARRAY
:
849 case RPC_FC_LGFARRAY
:
850 case RPC_FC_SMVARRAY
:
851 case RPC_FC_LGVARRAY
:
852 case RPC_FC_BOGUS_ARRAY
:
853 size
= t
->dim
* type_memsize(t
->ref
, align
);
856 error("type_memsize: Unknown type %d\n", t
->type
);
863 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
865 short absoff
= type
->ref
->typestring_offset
;
866 short reloff
= absoff
- (offset
+ 2);
867 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
869 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
870 type
->type
, ptr_attr
, string_of_type(type
->type
));
871 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
872 reloff
, reloff
, absoff
);
876 static unsigned char conf_string_type_of_char_type(unsigned char t
)
882 return RPC_FC_C_CSTRING
;
884 return RPC_FC_C_WSTRING
;
887 error("string_type_of_char_type: unrecognized type %d\n", t
);
891 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
894 = is_string_type(type
->attrs
, type
)
895 ? conf_string_type_of_char_type(type
->ref
->type
)
897 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
898 type
->type
, string_of_type(type
->type
));
899 print_file(file
, 2, "0x%02x,\t/* %s */\n", fc
, string_of_type(fc
));
900 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
904 static void print_start_tfs_comment(FILE *file
, type_t
*t
, unsigned int tfsoff
)
906 print_file(file
, 0, "/* %u (", tfsoff
);
907 write_type_decl(file
, t
, NULL
);
908 print_file(file
, 0, ") */\n");
911 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
913 unsigned int offset
= *typestring_offset
;
915 print_start_tfs_comment(file
, type
, offset
);
916 update_tfsoff(type
, offset
, file
);
918 if (type
->ref
->typestring_offset
)
919 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
920 else if (is_base_type(type
->ref
->type
))
921 *typestring_offset
+= write_simple_pointer(file
, type
);
926 static int processed(const type_t
*type
)
928 return type
->typestring_offset
&& !type
->tfswrite
;
931 static int user_type_has_variable_size(const type_t
*t
)
940 case RPC_FC_CPSTRUCT
:
941 case RPC_FC_CVSTRUCT
:
944 /* Note: Since this only applies to user types, we can't have a conformant
945 array here, and strings should get filed under pointer in this case. */
949 static void write_user_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
951 unsigned int start
, absoff
, flags
;
952 unsigned int align
= 0, ualign
= 0;
954 type_t
*utype
= get_user_type(type
, &name
);
955 size_t usize
= user_type_has_variable_size(utype
) ? 0 : type_memsize(utype
, &ualign
);
956 size_t size
= type_memsize(type
, &align
);
957 unsigned short funoff
= user_type_offset(name
);
962 if (is_base_type(utype
->type
))
965 print_start_tfs_comment(file
, utype
, absoff
);
966 print_file(file
, 2, "0x%x,\t/* %s */\n", utype
->type
, string_of_type(utype
->type
));
967 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
972 if (!processed(utype
))
973 write_embedded_types(file
, NULL
, utype
, utype
->name
, TRUE
, tfsoff
);
974 absoff
= utype
->typestring_offset
;
977 if (utype
->type
== RPC_FC_RP
)
979 else if (utype
->type
== RPC_FC_UP
)
985 update_tfsoff(type
, start
, file
);
986 print_start_tfs_comment(file
, type
, start
);
987 print_file(file
, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL
);
988 print_file(file
, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
989 flags
| (align
- 1), align
- 1, flags
);
990 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff
, funoff
);
991 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size
, size
);
992 print_file(file
, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize
, usize
);
994 reloff
= absoff
- *tfsoff
;
995 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff
, reloff
, absoff
);
999 static void write_member_type(FILE *file
, const type_t
*cont
,
1000 const attr_list_t
*attrs
, const type_t
*type
,
1001 unsigned int *corroff
, unsigned int *tfsoff
)
1003 if (is_embedded_complex(type
) && !is_conformant_array(type
))
1008 if (is_union(type
->type
) && is_attr(attrs
, ATTR_SWITCHIS
))
1015 absoff
= type
->typestring_offset
;
1017 reloff
= absoff
- (*tfsoff
+ 2);
1019 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1020 /* FIXME: actually compute necessary padding */
1021 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
1022 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1023 reloff
, reloff
, absoff
);
1026 else if (is_ptr(type
) || is_conformant_array(type
))
1028 unsigned char fc
= (cont
->type
== RPC_FC_BOGUS_STRUCT
1031 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1034 else if (!write_base_type(file
, type
, tfsoff
))
1035 error("Unsupported member type 0x%x\n", type
->type
);
1038 static void write_end(FILE *file
, unsigned int *tfsoff
)
1040 if (*tfsoff
% 2 == 0)
1042 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1045 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1049 static void write_descriptors(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1051 unsigned int offset
= 0;
1052 var_list_t
*fs
= type
->fields
;
1055 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, var_t
, entry
)
1057 unsigned int align
= 0;
1058 type_t
*ft
= f
->type
;
1059 if (is_union(ft
->type
) && is_attr(f
->attrs
, ATTR_SWITCHIS
))
1061 unsigned int absoff
= ft
->typestring_offset
;
1062 short reloff
= absoff
- (*tfsoff
+ 6);
1063 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1064 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1065 print_file(file
, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG
);
1066 write_conf_or_var_desc(file
, current_structure
, offset
, ft
,
1067 get_attrp(f
->attrs
, ATTR_SWITCHIS
));
1068 print_file(file
, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1069 reloff
, reloff
, absoff
);
1073 /* FIXME: take alignment into account */
1074 offset
+= type_memsize(ft
, &align
);
1078 static int write_no_repeat_pointer_descriptions(
1079 FILE *file
, type_t
*type
,
1080 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1081 unsigned int *typestring_offset
)
1086 if (is_ptr(type
) || (!type
->declarray
&& is_conformant_array(type
)))
1088 print_file(file
, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT
);
1089 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1091 /* pointer instance */
1092 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1093 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1094 *typestring_offset
+= 6;
1097 write_pointer_tfs(file
, type
, typestring_offset
);
1100 unsigned absoff
= type
->typestring_offset
;
1101 short reloff
= absoff
- (*typestring_offset
+ 2);
1102 /* FIXME: get pointer attributes from field */
1103 print_file(file
, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP
, "FC_UP");
1104 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1105 reloff
, reloff
, absoff
);
1106 *typestring_offset
+= 4;
1110 *offset_in_memory
+= type_memsize(type
, &align
);
1111 /* FIXME: is there a case where these two are different? */
1113 *offset_in_buffer
+= type_memsize(type
, &align
);
1118 if (is_non_complex_struct(type
))
1121 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1122 written
+= write_no_repeat_pointer_descriptions(
1124 offset_in_memory
, offset_in_buffer
, typestring_offset
);
1129 *offset_in_memory
+= type_memsize(type
, &align
);
1130 /* FIXME: is there a case where these two are different? */
1132 *offset_in_buffer
+= type_memsize(type
, &align
);
1138 static int write_pointer_description_offsets(
1139 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1140 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1141 unsigned int *typestring_offset
)
1146 if (is_ptr(type
) && type
->ref
->type
!= RPC_FC_IP
)
1148 if (offset_in_memory
&& offset_in_buffer
)
1150 /* pointer instance */
1151 /* FIXME: sometimes from end of structure, sometimes from beginning */
1152 print_file(file
, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory
, *offset_in_memory
);
1153 print_file(file
, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer
, *offset_in_buffer
);
1156 *offset_in_memory
+= type_memsize(type
, &align
);
1157 /* FIXME: is there a case where these two are different? */
1159 *offset_in_buffer
+= type_memsize(type
, &align
);
1161 *typestring_offset
+= 4;
1163 if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
1164 write_pointer_tfs(file
, type
, typestring_offset
);
1166 error("write_pointer_description_offsets: type format string unknown\n");
1173 return write_pointer_description_offsets(
1174 file
, attrs
, type
->ref
, offset_in_memory
, offset_in_buffer
,
1177 else if (is_non_complex_struct(type
))
1179 /* otherwise search for interesting fields to parse */
1181 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1183 written
+= write_pointer_description_offsets(
1184 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1191 if (offset_in_memory
)
1192 *offset_in_memory
+= type_memsize(type
, &align
);
1193 /* FIXME: is there a case where these two are different? */
1195 if (offset_in_buffer
)
1196 *offset_in_buffer
+= type_memsize(type
, &align
);
1202 /* Note: if file is NULL return value is number of pointers to write, else
1203 * it is the number of type format characters written */
1204 static int write_fixed_array_pointer_descriptions(
1205 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1206 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1207 unsigned int *typestring_offset
)
1210 int pointer_count
= 0;
1212 if (type
->type
== RPC_FC_SMFARRAY
|| type
->type
== RPC_FC_LGFARRAY
)
1214 unsigned int temp
= 0;
1215 /* unfortunately, this needs to be done in two passes to avoid
1216 * writing out redundant FC_FIXED_REPEAT descriptions */
1217 pointer_count
= write_pointer_description_offsets(
1218 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1219 if (pointer_count
> 0)
1221 unsigned int increment_size
;
1222 size_t offset_of_array_pointer_mem
= 0;
1223 size_t offset_of_array_pointer_buf
= 0;
1226 increment_size
= type_memsize(type
->ref
, &align
);
1228 print_file(file
, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT
);
1229 print_file(file
, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD
);
1230 print_file(file
, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type
->dim
, type
->dim
);
1231 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1232 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1233 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1234 *typestring_offset
+= 10;
1236 pointer_count
= write_pointer_description_offsets(
1237 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1238 &offset_of_array_pointer_buf
, typestring_offset
);
1241 else if (is_struct(type
->type
))
1244 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1246 pointer_count
+= write_fixed_array_pointer_descriptions(
1247 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1254 if (offset_in_memory
)
1255 *offset_in_memory
+= type_memsize(type
, &align
);
1256 /* FIXME: is there a case where these two are different? */
1258 if (offset_in_buffer
)
1259 *offset_in_buffer
+= type_memsize(type
, &align
);
1262 return pointer_count
;
1265 /* Note: if file is NULL return value is number of pointers to write, else
1266 * it is the number of type format characters written */
1267 static int write_conformant_array_pointer_descriptions(
1268 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1269 size_t offset_in_memory
, unsigned int *typestring_offset
)
1272 int pointer_count
= 0;
1274 if (is_conformant_array(type
) && !type
->length_is
)
1276 unsigned int temp
= 0;
1277 /* unfortunately, this needs to be done in two passes to avoid
1278 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1279 pointer_count
= write_pointer_description_offsets(
1280 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1281 if (pointer_count
> 0)
1283 unsigned int increment_size
;
1284 size_t offset_of_array_pointer_mem
= offset_in_memory
;
1285 size_t offset_of_array_pointer_buf
= offset_in_memory
;
1288 increment_size
= type_memsize(type
->ref
, &align
);
1290 if (increment_size
> USHRT_MAX
)
1291 error("array size of %u bytes is too large\n", increment_size
);
1293 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1294 print_file(file
, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET
);
1295 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1296 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory
, offset_in_memory
);
1297 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1298 *typestring_offset
+= 8;
1300 pointer_count
= write_pointer_description_offsets(
1301 file
, attrs
, type
->ref
, &offset_of_array_pointer_mem
,
1302 &offset_of_array_pointer_buf
, typestring_offset
);
1306 return pointer_count
;
1309 /* Note: if file is NULL return value is number of pointers to write, else
1310 * it is the number of type format characters written */
1311 static int write_varying_array_pointer_descriptions(
1312 FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1313 size_t *offset_in_memory
, size_t *offset_in_buffer
,
1314 unsigned int *typestring_offset
)
1317 int pointer_count
= 0;
1319 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1321 if (is_array(type
) && type
->length_is
)
1323 unsigned int temp
= 0;
1324 /* unfortunately, this needs to be done in two passes to avoid
1325 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1326 pointer_count
= write_pointer_description_offsets(
1327 NULL
, attrs
, type
->ref
, NULL
, NULL
, &temp
);
1328 if (pointer_count
> 0)
1330 unsigned int increment_size
;
1331 size_t offset_of_array_pointer_mem
= 0;
1332 size_t offset_of_array_pointer_buf
= 0;
1335 increment_size
= type_memsize(type
->ref
, &align
);
1337 if (increment_size
> USHRT_MAX
)
1338 error("array size of %u bytes is too large\n", increment_size
);
1340 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT
);
1341 print_file(file
, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET
);
1342 print_file(file
, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size
, increment_size
);
1343 print_file(file
, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory
, *offset_in_memory
);
1344 print_file(file
, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count
, pointer_count
);
1345 *typestring_offset
+= 8;
1347 pointer_count
= write_pointer_description_offsets(
1348 file
, attrs
, type
, &offset_of_array_pointer_mem
,
1349 &offset_of_array_pointer_buf
, typestring_offset
);
1352 else if (is_struct(type
->type
))
1355 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
1357 pointer_count
+= write_varying_array_pointer_descriptions(
1358 file
, v
->attrs
, v
->type
, offset_in_memory
, offset_in_buffer
,
1365 if (offset_in_memory
)
1366 *offset_in_memory
+= type_memsize(type
, &align
);
1367 /* FIXME: is there a case where these two are different? */
1369 if (offset_in_buffer
)
1370 *offset_in_buffer
+= type_memsize(type
, &align
);
1373 return pointer_count
;
1376 static void write_pointer_description(FILE *file
, type_t
*type
,
1377 unsigned int *typestring_offset
)
1379 size_t offset_in_buffer
;
1380 size_t offset_in_memory
;
1382 /* pass 1: search for single instance of a pointer (i.e. don't descend
1384 if (!is_array(type
))
1386 offset_in_memory
= 0;
1387 offset_in_buffer
= 0;
1388 write_no_repeat_pointer_descriptions(
1390 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1393 /* pass 2: search for pointers in fixed arrays */
1394 offset_in_memory
= 0;
1395 offset_in_buffer
= 0;
1396 write_fixed_array_pointer_descriptions(
1398 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1400 /* pass 3: search for pointers in conformant only arrays (but don't descend
1401 * into conformant varying or varying arrays) */
1402 if ((!type
->declarray
|| !current_structure
) && is_conformant_array(type
))
1403 write_conformant_array_pointer_descriptions(
1404 file
, NULL
, type
, 0, typestring_offset
);
1405 else if (type
->type
== RPC_FC_CPSTRUCT
)
1407 unsigned int align
= 0;
1408 type_t
*carray
= find_array_or_string_in_struct(type
)->type
;
1409 write_conformant_array_pointer_descriptions(
1411 type_memsize(type
, &align
),
1415 /* pass 4: search for pointers in varying arrays */
1416 offset_in_memory
= 0;
1417 offset_in_buffer
= 0;
1418 write_varying_array_pointer_descriptions(
1420 &offset_in_memory
, &offset_in_buffer
, typestring_offset
);
1423 int is_declptr(const type_t
*t
)
1425 return is_ptr(t
) || (is_conformant_array(t
) && !t
->declarray
);
1428 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
1430 const char *name
, unsigned int *typestring_offset
)
1432 size_t start_offset
= *typestring_offset
;
1433 unsigned char rtype
;
1435 update_tfsoff(type
, start_offset
, file
);
1437 if (is_declptr(type
))
1439 unsigned char flag
= is_conformant_array(type
) ? 0 : RPC_FC_P_SIMPLEPOINTER
;
1440 int pointer_type
= is_ptr(type
) ? type
->type
: get_attrv(attrs
, ATTR_POINTERTYPE
);
1442 pointer_type
= RPC_FC_RP
;
1443 print_file(file
, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1444 pointer_type
, flag
, string_of_type(pointer_type
),
1445 flag
? " [simple_pointer]" : "");
1446 *typestring_offset
+= 2;
1449 print_file(file
, 2, "NdrFcShort(0x2),\n");
1450 *typestring_offset
+= 2;
1452 rtype
= type
->ref
->type
;
1455 rtype
= type
->ref
->type
;
1457 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
1459 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
1460 return start_offset
;
1463 if (type
->declarray
&& !is_conformant_array(type
))
1465 /* FIXME: multi-dimensional array */
1466 if (0xffffuL
< type
->dim
)
1467 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1468 name
, 0xffffu
, type
->dim
- 0xffffu
);
1470 if (rtype
== RPC_FC_CHAR
)
1471 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
1473 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
1474 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1475 *typestring_offset
+= 2;
1477 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
1478 *typestring_offset
+= 2;
1480 return start_offset
;
1482 else if (type
->size_is
)
1484 unsigned int align
= 0;
1486 if (rtype
== RPC_FC_CHAR
)
1487 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1489 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1490 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
1491 *typestring_offset
+= 2;
1493 *typestring_offset
+= write_conf_or_var_desc(
1494 file
, current_structure
,
1495 (type
->declarray
&& current_structure
1496 ? type_memsize(current_structure
, &align
)
1498 type
, type
->size_is
);
1500 return start_offset
;
1504 if (rtype
== RPC_FC_WCHAR
)
1505 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
1507 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
1508 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1509 *typestring_offset
+= 2;
1511 return start_offset
;
1515 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1516 const char *name
, unsigned int *typestring_offset
)
1518 const expr_t
*length_is
= type
->length_is
;
1519 const expr_t
*size_is
= type
->size_is
;
1520 unsigned int align
= 0;
1522 size_t start_offset
;
1524 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
1525 unsigned int baseoff
1526 = type
->declarray
&& current_structure
1527 ? type_memsize(current_structure
, &align
)
1531 pointer_type
= RPC_FC_RP
;
1533 has_pointer
= FALSE
;
1534 if (write_embedded_types(file
, attrs
, type
->ref
, name
, FALSE
, typestring_offset
))
1538 size
= type_memsize(type
, &align
);
1539 if (size
== 0) /* conformant array */
1540 size
= type_memsize(type
->ref
, &align
);
1542 start_offset
= *typestring_offset
;
1543 update_tfsoff(type
, start_offset
, file
);
1544 print_start_tfs_comment(file
, type
, start_offset
);
1545 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1546 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1547 *typestring_offset
+= 2;
1550 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1552 unsigned char tc
= type
->type
;
1554 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1556 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1557 *typestring_offset
+= 4;
1561 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1562 *typestring_offset
+= 2;
1565 if (is_conformant_array(type
))
1567 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1570 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1572 unsigned int elalign
= 0;
1573 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1575 if (type
->type
== RPC_FC_LGVARRAY
)
1577 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1578 *typestring_offset
+= 4;
1582 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1583 *typestring_offset
+= 2;
1586 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1587 *typestring_offset
+= 2;
1592 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1595 if (has_pointer
&& (!type
->declarray
|| !current_structure
))
1597 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1598 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1599 *typestring_offset
+= 2;
1600 write_pointer_description(file
, type
, typestring_offset
);
1601 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1602 *typestring_offset
+= 1;
1605 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1606 write_end(file
, typestring_offset
);
1610 unsigned int dim
= size_is
? 0 : type
->dim
;
1611 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim
, dim
);
1612 *typestring_offset
+= 2;
1614 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1617 += write_conf_or_var_desc(file
, current_structure
, baseoff
,
1619 write_member_type(file
, type
, NULL
, type
->ref
, NULL
, typestring_offset
);
1620 write_end(file
, typestring_offset
);
1623 return start_offset
;
1626 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1628 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1629 const type_t
*ft
= last_field
->type
;
1631 if (ft
->declarray
&& is_conformant_array(ft
))
1634 if (ft
->type
== RPC_FC_CSTRUCT
|| ft
->type
== RPC_FC_CPSTRUCT
|| ft
->type
== RPC_FC_CVSTRUCT
)
1635 return find_array_or_string_in_struct(last_field
->type
);
1640 static void write_struct_members(FILE *file
, const type_t
*type
,
1641 unsigned int *corroff
, unsigned int *typestring_offset
)
1644 unsigned short offset
= 0;
1648 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1650 type_t
*ft
= field
->type
;
1651 if (!ft
->declarray
|| !is_conformant_array(ft
))
1653 unsigned int align
= 0;
1654 size_t size
= type_memsize(ft
, &align
);
1657 if ((align
- 1) & offset
)
1659 unsigned char fc
= 0;
1663 fc
= RPC_FC_ALIGNM4
;
1666 fc
= RPC_FC_ALIGNM8
;
1669 error("write_struct_members: cannot align type %d\n", ft
->type
);
1671 print_file(file
, 2, "0x%x,\t/* %s */\n", fc
, string_of_type(fc
));
1672 offset
= (offset
+ (align
- 1)) & ~(align
- 1);
1673 *typestring_offset
+= 1;
1675 write_member_type(file
, type
, field
->attrs
, field
->type
, corroff
,
1681 padding
= ((offset
+ (salign
- 1)) & ~(salign
- 1)) - offset
;
1684 print_file(file
, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1685 RPC_FC_STRUCTPAD1
+ padding
- 1,
1687 *typestring_offset
+= 1;
1690 write_end(file
, typestring_offset
);
1693 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1694 const char *name
, unsigned int *tfsoff
)
1696 const type_t
*save_current_structure
= current_structure
;
1697 unsigned int total_size
;
1699 size_t start_offset
;
1700 size_t array_offset
;
1701 int has_pointers
= 0;
1702 unsigned int align
= 0;
1703 unsigned int corroff
;
1707 current_structure
= type
;
1709 total_size
= type_memsize(type
, &align
);
1710 if (total_size
> USHRT_MAX
)
1711 error("structure size for %s exceeds %d bytes by %d bytes\n",
1712 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1714 if (type
->fields
) LIST_FOR_EACH_ENTRY(f
, type
->fields
, var_t
, entry
)
1715 has_pointers
|= write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
,
1718 array
= find_array_or_string_in_struct(type
);
1719 if (array
&& !processed(array
->type
))
1721 = is_attr(array
->attrs
, ATTR_STRING
)
1722 ? write_string_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
)
1723 : write_array_tfs(file
, array
->attrs
, array
->type
, array
->name
, tfsoff
);
1726 write_descriptors(file
, type
, tfsoff
);
1728 start_offset
= *tfsoff
;
1729 update_tfsoff(type
, start_offset
, file
);
1730 print_start_tfs_comment(file
, type
, start_offset
);
1731 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1732 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1733 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1738 unsigned int absoff
= array
->type
->typestring_offset
;
1739 short reloff
= absoff
- *tfsoff
;
1740 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1741 reloff
, reloff
, absoff
);
1744 else if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1746 print_file(file
, 2, "NdrFcShort(0x0),\n");
1750 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1752 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1753 nothing is written to file yet. On the actual writing pass,
1754 this will have been updated. */
1755 unsigned int absoff
= type
->ptrdesc
? type
->ptrdesc
: *tfsoff
;
1756 short reloff
= absoff
- *tfsoff
;
1757 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1758 reloff
, reloff
, absoff
);
1761 else if ((type
->type
== RPC_FC_PSTRUCT
) ||
1762 (type
->type
== RPC_FC_CPSTRUCT
) ||
1763 (type
->type
== RPC_FC_CVSTRUCT
&& has_pointers
))
1765 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1766 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1768 write_pointer_description(file
, type
, tfsoff
);
1769 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1773 write_struct_members(file
, type
, &corroff
, tfsoff
);
1775 if (type
->type
== RPC_FC_BOGUS_STRUCT
)
1777 const var_list_t
*fs
= type
->fields
;
1780 type
->ptrdesc
= *tfsoff
;
1781 if (fs
) LIST_FOR_EACH_ENTRY(f
, fs
, const var_t
, entry
)
1783 type_t
*ft
= f
->type
;
1785 write_pointer_tfs(file
, ft
, tfsoff
);
1786 else if (!ft
->declarray
&& is_conformant_array(ft
))
1788 unsigned int absoff
= ft
->typestring_offset
;
1789 short reloff
= absoff
- (*tfsoff
+ 2);
1790 int ptr_type
= get_attrv(f
->attrs
, ATTR_POINTERTYPE
);
1791 /* FIXME: We need to store pointer attributes for arrays
1792 so we don't lose pointer_default info. */
1794 ptr_type
= RPC_FC_UP
;
1795 print_file(file
, 0, "/* %d */\n", *tfsoff
);
1796 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
1797 string_of_type(ptr_type
));
1798 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1799 reloff
, reloff
, absoff
);
1803 if (type
->ptrdesc
== *tfsoff
)
1807 current_structure
= save_current_structure
;
1808 return start_offset
;
1811 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1812 unsigned char flags
, size_t offset
,
1813 unsigned int *typeformat_offset
)
1815 size_t start_offset
= *typeformat_offset
;
1816 short reloff
= offset
- (*typeformat_offset
+ 2);
1817 int in_attr
, out_attr
;
1818 in_attr
= is_attr(attrs
, ATTR_IN
);
1819 out_attr
= is_attr(attrs
, ATTR_OUT
);
1820 if (!in_attr
&& !out_attr
) in_attr
= 1;
1822 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1825 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1828 string_of_type(pointer_type
));
1832 fprintf(file
, " [allocated_on_stack]");
1834 fprintf(file
, " [pointer_deref]");
1835 fprintf(file
, " */\n");
1838 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1839 *typeformat_offset
+= 4;
1841 return start_offset
;
1844 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1848 print_file(file
, 2, "NdrFcShort(0x0),\t/* No type */\n");
1850 else if (is_base_type(t
->type
))
1852 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1853 t
->type
, string_of_type(t
->type
));
1855 else if (t
->typestring_offset
)
1857 short reloff
= t
->typestring_offset
- *tfsoff
;
1858 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1859 reloff
, reloff
, t
->typestring_offset
);
1862 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1867 static size_t write_union_tfs(FILE *file
, type_t
*type
, unsigned int *tfsoff
)
1869 unsigned int align
= 0;
1870 unsigned int start_offset
;
1871 size_t size
= type_memsize(type
, &align
);
1874 type_t
*deftype
= NULL
;
1875 short nodeftype
= 0xffff;
1880 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1882 const var_t
*uv
= LIST_ENTRY(list_tail(type
->fields
), const var_t
, entry
);
1883 fields
= uv
->type
->fields
;
1886 fields
= type
->fields
;
1888 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1890 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
1892 nbranch
+= list_count(cases
);
1894 write_embedded_types(file
, f
->attrs
, f
->type
, f
->name
, TRUE
, tfsoff
);
1897 start_offset
= *tfsoff
;
1898 update_tfsoff(type
, start_offset
, file
);
1899 print_start_tfs_comment(file
, type
, start_offset
);
1900 if (type
->type
== RPC_FC_ENCAPSULATED_UNION
)
1902 const var_t
*sv
= LIST_ENTRY(list_head(type
->fields
), const var_t
, entry
);
1903 const type_t
*st
= sv
->type
;
1916 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1917 print_file(file
, 2, "0x%x,\t/* Switch type= %s */\n",
1918 0x40 | st
->type
, string_of_type(st
->type
));
1922 error("union switch type must be an integer, char, or enum\n");
1925 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
1926 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
1929 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1931 type_t
*ft
= f
->type
;
1932 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
1933 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
1936 if (cases
== NULL
&& !deflt
)
1937 error("union field %s with neither case nor default attribute\n", f
->name
);
1939 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
1941 /* MIDL doesn't check for duplicate cases, even though that seems
1942 like a reasonable thing to do, it just dumps them to the TFS
1943 like we're going to do here. */
1944 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
1946 write_branch_type(file
, ft
, tfsoff
);
1949 /* MIDL allows multiple default branches, even though that seems
1950 illogical, it just chooses the last one, which is what we will
1961 write_branch_type(file
, deftype
, tfsoff
);
1965 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
1969 return start_offset
;
1972 static size_t write_ip_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1973 unsigned int *typeformat_offset
)
1976 size_t start_offset
= *typeformat_offset
;
1977 const var_t
*iid
= get_attrp(attrs
, ATTR_IIDIS
);
1983 expr
.type
= EXPR_IDENTIFIER
;
1985 expr
.u
.sval
= iid
->name
;
1986 expr
.is_const
= FALSE
;
1987 print_file(file
, 2, "0x2f, /* FC_IP */\n");
1988 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
1990 += write_conf_or_var_desc(file
, NULL
, 0, type
, &expr
) + 2;
1994 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
1995 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
1998 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
2000 update_tfsoff(type
, start_offset
, file
);
2001 print_start_tfs_comment(file
, type
, start_offset
);
2002 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
2003 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2004 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
2005 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
2006 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
2007 for (i
= 0; i
< 8; ++i
)
2008 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
2011 fprintf(file
, "\n");
2013 *typeformat_offset
+= 18;
2015 return start_offset
;
2018 static size_t write_contexthandle_tfs(FILE *file
, const type_t
*type
,
2020 unsigned int *typeformat_offset
)
2022 size_t start_offset
= *typeformat_offset
;
2023 unsigned char flags
= 0x08 /* strict */;
2028 if (type
->type
!= RPC_FC_RP
)
2031 if (is_attr(var
->attrs
, ATTR_IN
))
2033 if (is_attr(var
->attrs
, ATTR_OUT
))
2036 WRITE_FCTYPE(file
, FC_BIND_CONTEXT
, *typeformat_offset
);
2037 print_file(file
, 2, "0x%x,\t/* Context flags: ", flags
);
2038 if (((flags
& 0x21) != 0x21) && (flags
& 0x01))
2039 print_file(file
, 0, "can't be null, ");
2041 print_file(file
, 0, "serialize, ");
2043 print_file(file
, 0, "no serialize, ");
2045 print_file(file
, 0, "strict, ");
2046 if ((flags
& 0x21) == 0x20)
2047 print_file(file
, 0, "out, ");
2048 if ((flags
& 0x21) == 0x21)
2049 print_file(file
, 0, "return, ");
2051 print_file(file
, 0, "in, ");
2053 print_file(file
, 0, "via ptr, ");
2054 print_file(file
, 0, "*/\n");
2055 print_file(file
, 2, "0, /* FIXME: rundown routine index*/\n");
2056 print_file(file
, 2, "0, /* FIXME: param num */\n");
2057 *typeformat_offset
+= 4;
2059 return start_offset
;
2062 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
2063 type_t
*type
, const var_t
*var
,
2064 unsigned int *typeformat_offset
)
2068 if (is_context_handle(type
))
2069 return write_contexthandle_tfs(file
, type
, var
, typeformat_offset
);
2071 if (is_user_type(type
))
2073 write_user_tfs(file
, type
, typeformat_offset
);
2074 return type
->typestring_offset
;
2077 if ((last_ptr(type
) || last_array(type
)) && is_ptrchain_attr(var
, ATTR_STRING
))
2078 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2084 off
= write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
2085 ptr_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2086 /* Top level pointers to conformant arrays may be handled specially
2087 since we can bypass the pointer, but if the array is burried
2088 beneath another pointer (e.g., "[size_is(,n)] int **p" then we
2089 always need to write the pointer. */
2090 if (!ptr_type
&& var
->type
!= type
)
2091 /* FIXME: This should use pointer_default, but the information
2092 isn't kept around for arrays. */
2093 ptr_type
= RPC_FC_UP
;
2094 if (ptr_type
&& ptr_type
!= RPC_FC_RP
)
2096 unsigned int absoff
= type
->typestring_offset
;
2097 short reloff
= absoff
- (*typeformat_offset
+ 2);
2098 off
= *typeformat_offset
;
2099 print_file(file
, 0, "/* %d */\n", off
);
2100 print_file(file
, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type
,
2101 string_of_type(ptr_type
));
2102 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2103 reloff
, reloff
, absoff
);
2104 *typeformat_offset
+= 4;
2111 /* basic types don't need a type format string */
2112 if (is_base_type(type
->type
))
2118 case RPC_FC_PSTRUCT
:
2119 case RPC_FC_CSTRUCT
:
2120 case RPC_FC_CPSTRUCT
:
2121 case RPC_FC_CVSTRUCT
:
2122 case RPC_FC_BOGUS_STRUCT
:
2123 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
2124 case RPC_FC_ENCAPSULATED_UNION
:
2125 case RPC_FC_NON_ENCAPSULATED_UNION
:
2126 return write_union_tfs(file
, type
, typeformat_offset
);
2128 case RPC_FC_BIND_PRIMITIVE
:
2132 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
2135 else if (last_ptr(type
))
2137 size_t start_offset
= *typeformat_offset
;
2138 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2139 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2140 const type_t
*base
= type
->ref
;
2142 if (base
->type
== RPC_FC_IP
2144 && is_attr(var
->attrs
, ATTR_IIDIS
)))
2146 return write_ip_tfs(file
, var
->attrs
, type
, typeformat_offset
);
2149 /* special case for pointers to base types */
2150 if (is_base_type(base
->type
))
2152 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2153 type
->type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
2154 string_of_type(type
->type
),
2155 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
2156 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
2157 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
2158 *typeformat_offset
+= 4;
2159 return start_offset
;
2163 assert(is_ptr(type
));
2165 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
2167 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
2168 return write_pointer_only_tfs(file
, var
->attrs
, type
->type
,
2169 !last_ptr(type
) ? 0x10 : 0,
2170 offset
, typeformat_offset
);
2173 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
2174 const char *name
, int write_ptr
, unsigned int *tfsoff
)
2178 if (is_user_type(type
))
2180 write_user_tfs(file
, type
, tfsoff
);
2182 else if (is_ptr(type
))
2184 type_t
*ref
= type
->ref
;
2186 if (ref
->type
== RPC_FC_IP
2188 && is_attr(attrs
, ATTR_IIDIS
)))
2190 write_ip_tfs(file
, attrs
, type
, tfsoff
);
2194 if (!processed(ref
) && !is_base_type(ref
->type
))
2195 retmask
|= write_embedded_types(file
, NULL
, ref
, name
, TRUE
, tfsoff
);
2198 write_pointer_tfs(file
, type
, tfsoff
);
2203 else if (last_array(type
) && is_attr(attrs
, ATTR_STRING
))
2205 write_string_tfs(file
, attrs
, type
, name
, tfsoff
);
2207 else if (type
->declarray
&& is_conformant_array(type
))
2208 ; /* conformant arrays and strings are handled specially */
2209 else if (is_array(type
))
2211 write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
2212 if (is_conformant_array(type
))
2215 else if (is_struct(type
->type
))
2217 if (!processed(type
))
2218 write_struct_tfs(file
, type
, name
, tfsoff
);
2220 else if (is_union(type
->type
))
2222 if (!processed(type
))
2223 write_union_tfs(file
, type
, tfsoff
);
2225 else if (!is_base_type(type
->type
))
2226 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2232 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2235 const ifref_t
*iface
;
2236 unsigned int typeformat_offset
= 2;
2238 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2240 if (!pred(iface
->iface
))
2243 if (iface
->iface
->funcs
)
2246 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2248 if (is_local(func
->def
->attrs
)) continue;
2250 current_func
= func
;
2252 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2255 write_typeformatstring_var(
2256 file
, 2, func
, var
->type
, var
,
2257 &typeformat_offset
),
2263 return typeformat_offset
+ 1;
2267 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, type_pred_t pred
)
2271 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2272 print_file(file
, indent
, "{\n");
2274 print_file(file
, indent
, "0,\n");
2275 print_file(file
, indent
, "{\n");
2277 print_file(file
, indent
, "NdrFcShort(0x0),\n");
2279 set_all_tfswrite(TRUE
);
2280 process_tfs(file
, ifaces
, pred
);
2282 print_file(file
, indent
, "0x0\n");
2284 print_file(file
, indent
, "}\n");
2286 print_file(file
, indent
, "};\n");
2287 print_file(file
, indent
, "\n");
2290 static unsigned int get_required_buffer_size_type(
2291 const type_t
*type
, const char *name
, unsigned int *alignment
)
2294 if (is_user_type(type
))
2297 const type_t
*utype
= get_user_type(type
, &uname
);
2298 return get_required_buffer_size_type(utype
, uname
, alignment
);
2322 case RPC_FC_ERROR_STATUS_T
:
2332 case RPC_FC_BIND_PRIMITIVE
:
2336 case RPC_FC_PSTRUCT
:
2340 if (!type
->fields
) return 0;
2341 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2343 unsigned int alignment
;
2344 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
2352 is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
2353 ? get_required_buffer_size_type( type
->ref
, name
, alignment
)
2356 case RPC_FC_SMFARRAY
:
2357 case RPC_FC_LGFARRAY
:
2358 return type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
2366 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
2368 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2369 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2372 if (!in_attr
&& !out_attr
)
2377 for (t
= var
->type
; is_ptr(t
); t
= t
->ref
)
2378 if (is_attr(t
->attrs
, ATTR_CONTEXTHANDLE
))
2384 if (pass
== PASS_OUT
)
2386 if (out_attr
&& is_ptr(var
->type
))
2388 type_t
*type
= var
->type
;
2390 if (type
->type
== RPC_FC_STRUCT
)
2393 unsigned int size
= 36;
2395 if (!type
->fields
) return size
;
2396 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2399 size
+= get_required_buffer_size_type(
2400 field
->type
, field
->name
, &align
);
2409 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
2410 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
2412 if (is_ptr(var
->type
))
2414 type_t
*type
= var
->type
;
2416 if (is_base_type(type
->type
))
2420 else if (type
->type
== RPC_FC_STRUCT
)
2422 unsigned int size
= 36;
2425 if (!type
->fields
) return size
;
2426 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
2429 size
+= get_required_buffer_size_type(
2430 field
->type
, field
->name
, &align
);
2437 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
2441 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
2444 unsigned int total_size
= 0, alignment
;
2448 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2450 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
2451 total_size
+= alignment
;
2455 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
2457 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
2458 total_size
+= alignment
;
2463 static void print_phase_function(FILE *file
, int indent
, const char *type
,
2464 enum remoting_phase phase
,
2465 const var_t
*var
, unsigned int type_offset
)
2467 const char *function
;
2470 case PHASE_BUFFERSIZE
:
2471 function
= "BufferSize";
2474 function
= "Marshall";
2476 case PHASE_UNMARSHAL
:
2477 function
= "Unmarshall";
2487 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
2489 print_file(file
, indent
, "&_StubMsg,\n");
2490 print_file(file
, indent
, "%s%s%s%s,\n",
2491 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)" : "(unsigned char *)",
2492 (phase
== PHASE_UNMARSHAL
|| decl_indirect(var
->type
)) ? "&" : "",
2493 (phase
== PHASE_UNMARSHAL
&& decl_indirect(var
->type
)) ? "_p_" : "",
2495 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2496 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
2497 if (phase
== PHASE_UNMARSHAL
)
2498 print_file(file
, indent
, "0);\n");
2502 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
2503 enum pass pass
, const var_t
*var
,
2504 const char *varname
)
2506 type_t
*type
= var
->type
;
2508 unsigned int alignment
= 0;
2509 unsigned char rtype
;
2511 /* no work to do for other phases, buffer sizing is done elsewhere */
2512 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
2515 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2539 case RPC_FC_ERROR_STATUS_T
:
2551 case RPC_FC_BIND_PRIMITIVE
:
2552 /* no marshalling needed */
2556 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2560 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2561 alignment
- 1, alignment
- 1);
2563 if (phase
== PHASE_MARSHAL
)
2565 print_file(file
, indent
, "*(");
2566 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2568 fprintf(file
, " *)_StubMsg.Buffer = *");
2570 fprintf(file
, " *)_StubMsg.Buffer = ");
2571 fprintf(file
, "%s", varname
);
2572 fprintf(file
, ";\n");
2574 else if (phase
== PHASE_UNMARSHAL
)
2576 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2577 print_file(file
, indent
, "");
2579 print_file(file
, indent
, "*");
2580 fprintf(file
, "%s", varname
);
2581 if (pass
== PASS_IN
&& is_ptr(type
))
2582 fprintf(file
, " = (");
2584 fprintf(file
, " = *(");
2585 write_type_decl(file
, is_ptr(type
) ? type
->ref
: type
, NULL
);
2586 fprintf(file
, " *)_StubMsg.Buffer;\n");
2589 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2590 write_type_decl(file
, var
->type
, NULL
);
2591 fprintf(file
, ");\n");
2594 /* returns whether the MaxCount, Offset or ActualCount members need to be
2595 * filled in for the specified phase */
2596 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2598 return (phase
!= PHASE_UNMARSHAL
);
2601 static int needs_freeing(const attr_list_t
*attrs
, const type_t
*t
, int out
)
2606 && (t
->ref
->type
== RPC_FC_IP
2607 || is_ptr(t
->ref
))))
2608 || (out
&& (is_string_type(attrs
, t
)
2612 expr_t
*get_size_is_expr(const type_t
*t
, const char *name
)
2616 for ( ; is_ptr(t
) || is_array(t
); t
= t
->ref
)
2622 error("%s: multidimensional conformant"
2623 " arrays not supported at the top level\n",
2630 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
2631 enum pass pass
, enum remoting_phase phase
)
2633 int in_attr
, out_attr
, pointer_type
;
2639 if (phase
== PHASE_BUFFERSIZE
)
2641 unsigned int size
= get_function_buffer_size( func
, pass
);
2642 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
2645 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2647 const type_t
*type
= var
->type
;
2648 unsigned char rtype
;
2649 size_t start_offset
= type
->typestring_offset
;
2651 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2653 pointer_type
= RPC_FC_RP
;
2655 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2656 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2657 if (!in_attr
&& !out_attr
)
2660 if (phase
== PHASE_FREE
)
2662 if (!needs_freeing(var
->attrs
, type
, out_attr
))
2669 if (!in_attr
) continue;
2672 if (!out_attr
) continue;
2680 if (is_context_handle(type
))
2682 if (phase
== PHASE_MARSHAL
)
2684 if (pass
== PASS_IN
)
2686 print_file(file
, indent
, "NdrClientContextMarshall(\n");
2687 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2688 print_file(file
, indent
+ 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type
) ? "*" : "", var
->name
);
2689 print_file(file
, indent
+ 1, "%s);\n", in_attr
&& out_attr
? "1" : "0");
2693 print_file(file
, indent
, "NdrServerContextMarshall(\n");
2694 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2695 print_file(file
, indent
+ 1, "(NDR_SCONTEXT)%s,\n", var
->name
);
2696 print_file(file
, indent
+ 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var
->type
));
2699 else if (phase
== PHASE_UNMARSHAL
)
2701 if (pass
== PASS_OUT
)
2703 print_file(file
, indent
, "NdrClientContextUnmarshall(\n");
2704 print_file(file
, indent
+ 1, "&_StubMsg,\n");
2705 print_file(file
, indent
+ 1, "(NDR_CCONTEXT *)%s,\n", var
->name
);
2706 print_file(file
, indent
+ 1, "_Handle);\n");
2709 print_file(file
, indent
, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var
->name
);
2712 else if (is_user_type(var
->type
))
2714 print_phase_function(file
, indent
, "UserMarshal", phase
, var
, start_offset
);
2716 else if (is_string_type(var
->attrs
, var
->type
))
2718 if (is_array(type
) && !is_conformant_array(type
))
2719 print_phase_function(file
, indent
, "NonConformantString", phase
, var
, start_offset
);
2722 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2724 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2725 write_expr(file
, type
->size_is
, 1);
2726 fprintf(file
, ";\n");
2729 if ((phase
== PHASE_FREE
) || (pointer_type
== RPC_FC_UP
))
2730 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2732 print_phase_function(file
, indent
, "ConformantString", phase
, var
,
2733 start_offset
+ (type
->size_is
? 4 : 2));
2736 else if (is_array(type
))
2738 unsigned char tc
= type
->type
;
2739 const char *array_type
= "FixedArray";
2741 /* We already have the size_is expression since it's at the
2742 top level, but do checks for multidimensional conformant
2743 arrays. When we handle them, we'll need to extend this
2744 function to return a list, and then we'll actually use
2745 the return value. */
2746 get_size_is_expr(type
, var
->name
);
2748 if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2750 if (is_size_needed_for_phase(phase
))
2752 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2753 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2754 write_expr(file
, type
->length_is
, 1);
2755 fprintf(file
, ";\n\n");
2757 array_type
= "VaryingArray";
2759 else if (tc
== RPC_FC_CARRAY
)
2761 if (is_size_needed_for_phase(phase
) && phase
!= PHASE_FREE
)
2763 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2764 write_expr(file
, type
->size_is
, 1);
2765 fprintf(file
, ";\n\n");
2767 array_type
= "ConformantArray";
2769 else if (tc
== RPC_FC_CVARRAY
|| tc
== RPC_FC_BOGUS_ARRAY
)
2771 if (is_size_needed_for_phase(phase
))
2775 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2776 write_expr(file
, type
->size_is
, 1);
2777 fprintf(file
, ";\n");
2779 if (type
->length_is
)
2781 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2782 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2783 write_expr(file
, type
->length_is
, 1);
2784 fprintf(file
, ";\n\n");
2787 array_type
= (tc
== RPC_FC_BOGUS_ARRAY
2789 : "ConformantVaryingArray");
2792 if (!in_attr
&& phase
== PHASE_FREE
)
2794 print_file(file
, indent
, "if (%s)\n", var
->name
);
2796 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2798 else if (phase
!= PHASE_FREE
)
2800 const char *t
= pointer_type
== RPC_FC_RP
? array_type
: "Pointer";
2801 print_phase_function(file
, indent
, t
, phase
, var
, start_offset
);
2804 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2806 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2808 else if (!is_ptr(var
->type
))
2813 case RPC_FC_PSTRUCT
:
2814 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
);
2816 case RPC_FC_CSTRUCT
:
2817 case RPC_FC_CPSTRUCT
:
2818 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
, start_offset
);
2820 case RPC_FC_CVSTRUCT
:
2821 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
, start_offset
);
2823 case RPC_FC_BOGUS_STRUCT
:
2824 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
, start_offset
);
2827 if (is_base_type( var
->type
->ref
->type
))
2829 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2831 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2833 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2834 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2839 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2840 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid
->name
);
2841 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2845 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2850 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2852 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2854 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2856 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2857 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
, start_offset
+ 4);
2862 expr_t
*sx
= get_size_is_expr(type
, var
->name
);
2864 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2865 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid
->name
);
2868 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long) ");
2869 write_expr(file
, sx
, 1);
2870 fprintf(file
, ";\n\n");
2872 if (var
->type
->ref
->type
== RPC_FC_IP
)
2873 print_phase_function(file
, indent
, "InterfacePointer", phase
, var
, start_offset
);
2875 print_phase_function(file
, indent
, "Pointer", phase
, var
, start_offset
);
2878 fprintf(file
, "\n");
2883 size_t get_size_procformatstring_var(const var_t
*var
)
2885 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
2889 size_t get_size_procformatstring_func(const func_t
*func
)
2894 /* argument list size */
2896 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2897 size
+= get_size_procformatstring_var(var
);
2899 /* return value size */
2900 if (is_void(func
->def
->type
))
2901 size
+= 2; /* FC_END and FC_PAD */
2903 size
+= get_size_procformatstring_var(func
->def
);
2908 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
2910 const ifref_t
*iface
;
2914 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2916 if (!pred(iface
->iface
))
2919 if (iface
->iface
->funcs
)
2920 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2921 if (!is_local(func
->def
->attrs
))
2922 size
+= get_size_procformatstring_func( func
);
2927 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, type_pred_t pred
)
2929 set_all_tfswrite(FALSE
);
2930 return process_tfs(NULL
, ifaces
, pred
);
2933 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
2934 const var_list_t
*fields
, const char *structvar
)
2940 fprintf(h
, "%lu", e
->u
.lval
);
2943 fprintf(h
, "0x%lx", e
->u
.lval
);
2946 fprintf(h
, "%#.15g", e
->u
.dval
);
2948 case EXPR_TRUEFALSE
:
2950 fprintf(h
, "FALSE");
2954 case EXPR_IDENTIFIER
:
2957 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
2958 if (!strcmp(e
->u
.sval
, field
->name
))
2960 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
2964 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
2969 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2973 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2977 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2981 write_type_decl(h
, e
->u
.tref
, NULL
);
2983 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2986 fprintf(h
, "sizeof(");
2987 write_type_decl(h
, e
->u
.tref
, NULL
);
2998 if (brackets
) fprintf(h
, "(");
2999 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3001 case EXPR_SHL
: fprintf(h
, " << "); break;
3002 case EXPR_SHR
: fprintf(h
, " >> "); break;
3003 case EXPR_MUL
: fprintf(h
, " * "); break;
3004 case EXPR_DIV
: fprintf(h
, " / "); break;
3005 case EXPR_ADD
: fprintf(h
, " + "); break;
3006 case EXPR_SUB
: fprintf(h
, " - "); break;
3007 case EXPR_AND
: fprintf(h
, " & "); break;
3008 case EXPR_OR
: fprintf(h
, " | "); break;
3011 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3012 if (brackets
) fprintf(h
, ")");
3015 if (brackets
) fprintf(h
, "(");
3016 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
3018 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
3020 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
3021 if (brackets
) fprintf(h
, ")");
3027 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
3029 int in_attr
, out_attr
;
3031 const var_t
*def
= func
->def
;
3034 /* declare return value '_RetVal' */
3035 if (!is_void(def
->type
))
3037 print_file(file
, indent
, "");
3038 write_type_decl_left(file
, def
->type
);
3039 fprintf(file
, " _RetVal;\n");
3045 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3047 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3049 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3050 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3051 if (!out_attr
&& !in_attr
)
3054 if (is_context_handle(var
->type
))
3055 print_file(file
, indent
, "NDR_SCONTEXT %s;\n", var
->name
);
3058 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
3060 print_file(file
, indent
, "");
3061 write_type_decl(file
, var
->type
->ref
, "_W%u", i
++);
3062 fprintf(file
, ";\n");
3065 print_file(file
, indent
, "");
3066 write_type_decl_left(file
, var
->type
);
3068 if (var
->type
->declarray
) {
3069 fprintf(file
, "( *");
3070 write_name(file
, var
);
3071 fprintf(file
, " )");
3073 write_name(file
, var
);
3074 write_type_right(file
, var
->type
, FALSE
);
3075 fprintf(file
, ";\n");
3077 if (decl_indirect(var
->type
))
3078 print_file(file
, indent
, "void *_p_%s = &%s;\n",
3079 var
->name
, var
->name
);
3085 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
3087 int in_attr
, out_attr
;
3094 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
3096 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
3097 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
3098 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
3099 if (!out_attr
&& !in_attr
)
3104 print_file(file
, indent
, "");
3105 write_name(file
, var
);
3107 if (var
->type
->size_is
)
3109 unsigned int size
, align
= 0;
3110 type_t
*type
= var
->type
;
3112 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
3113 for ( ; type
->size_is
; type
= type
->ref
)
3115 write_expr(file
, type
->size_is
, TRUE
);
3116 fprintf(file
, " * ");
3118 size
= type_memsize(type
, &align
);
3119 fprintf(file
, "%u);\n", size
);
3121 else if (!is_string
)
3123 fprintf(file
, " = &_W%u;\n", i
);
3124 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
3125 print_file(file
, indent
, "_W%u = 0;\n", i
);
3133 fprintf(file
, "\n");
3137 int write_expr_eval_routines(FILE *file
, const char *iface
)
3139 static const char *var_name
= "pS";
3141 struct expr_eval_routine
*eval
;
3142 unsigned short callback_offset
= 0;
3144 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3146 const char *name
= eval
->structure
->name
;
3147 const var_list_t
*fields
= eval
->structure
->fields
;
3150 print_file(file
, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3151 iface
, name
, callback_offset
);
3152 print_file(file
, 0, "{\n");
3153 print_file (file
, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3154 name
, var_name
, name
, eval
->baseoff
);
3155 print_file(file
, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3156 print_file(file
, 1, "pStubMsg->MaxCount = (unsigned long)");
3157 write_struct_expr(file
, eval
->expr
, 1, fields
, var_name
);
3158 fprintf(file
, ";\n");
3159 print_file(file
, 0, "}\n\n");
3165 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
3167 struct expr_eval_routine
*eval
;
3168 struct expr_eval_routine
*cursor
;
3169 unsigned short callback_offset
= 0;
3171 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3172 fprintf(file
, "{\n");
3174 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
3176 const char *name
= eval
->structure
->name
;
3177 print_file(file
, 1, "%s_%sExprEval_%04u,\n", iface
, name
, callback_offset
);
3179 list_remove(&eval
->entry
);
3183 fprintf(file
, "};\n\n");
3186 void write_user_quad_list(FILE *file
)
3190 if (list_empty(&user_type_list
))
3193 fprintf(file
, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3194 fprintf(file
, "{\n");
3195 LIST_FOR_EACH_ENTRY(ut
, &user_type_list
, user_type_t
, entry
)
3197 const char *sep
= &ut
->entry
== list_tail(&user_type_list
) ? "" : ",";
3198 print_file(file
, 1, "{\n");
3199 print_file(file
, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut
->name
);
3200 print_file(file
, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut
->name
);
3201 print_file(file
, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut
->name
);
3202 print_file(file
, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut
->name
);
3203 print_file(file
, 1, "}%s\n", sep
);
3205 fprintf(file
, "};\n\n");
3208 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
3210 const struct str_list_entry_t
*endpoint
;
3213 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3214 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
3215 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
3217 print_file( f
, 1, "{ (const unsigned char *)\"" );
3218 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
3220 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3223 if (!*p
) goto error
;
3224 if (p
[1] != '[') goto error
;
3226 fprintf( f
, "\", (const unsigned char *)\"" );
3227 for (p
+= 2; *p
&& *p
!= ']'; p
++)
3229 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
3232 if (*p
!= ']') goto error
;
3233 fprintf( f
, "\" },\n" );
3235 print_file( f
, 0, "};\n\n" );
3239 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);