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 /* name of the structure variable for structure callbacks */
50 #define STRUCT_EXPR_EVAL_VAR "pS"
52 static struct list expr_eval_routines
= LIST_INIT(expr_eval_routines
);
54 struct expr_eval_routine
57 const type_t
*structure
;
58 size_t structure_size
;
62 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
);
63 static size_t write_struct_tfs(FILE *file
, type_t
*type
, const char *name
, unsigned int *tfsoff
);
64 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
65 const char *name
, int level
, unsigned int *tfsoff
);
67 const char *string_of_type(unsigned char type
)
71 case RPC_FC_BYTE
: return "FC_BYTE";
72 case RPC_FC_CHAR
: return "FC_CHAR";
73 case RPC_FC_SMALL
: return "FC_SMALL";
74 case RPC_FC_USMALL
: return "FC_USMALL";
75 case RPC_FC_WCHAR
: return "FC_WCHAR";
76 case RPC_FC_SHORT
: return "FC_SHORT";
77 case RPC_FC_USHORT
: return "FC_USHORT";
78 case RPC_FC_LONG
: return "FC_LONG";
79 case RPC_FC_ULONG
: return "FC_ULONG";
80 case RPC_FC_FLOAT
: return "FC_FLOAT";
81 case RPC_FC_HYPER
: return "FC_HYPER";
82 case RPC_FC_DOUBLE
: return "FC_DOUBLE";
83 case RPC_FC_ENUM16
: return "FC_ENUM16";
84 case RPC_FC_ENUM32
: return "FC_ENUM32";
85 case RPC_FC_IGNORE
: return "FC_IGNORE";
86 case RPC_FC_ERROR_STATUS_T
: return "FC_ERROR_STATUS_T";
87 case RPC_FC_RP
: return "FC_RP";
88 case RPC_FC_UP
: return "FC_UP";
89 case RPC_FC_OP
: return "FC_OP";
90 case RPC_FC_FP
: return "FC_FP";
91 case RPC_FC_ENCAPSULATED_UNION
: return "FC_ENCAPSULATED_UNION";
92 case RPC_FC_NON_ENCAPSULATED_UNION
: return "FC_NON_ENCAPSULATED_UNION";
93 case RPC_FC_STRUCT
: return "FC_STRUCT";
94 case RPC_FC_PSTRUCT
: return "FC_PSTRUCT";
95 case RPC_FC_CSTRUCT
: return "FC_CSTRUCT";
96 case RPC_FC_CPSTRUCT
: return "FC_CPSTRUCT";
97 case RPC_FC_CVSTRUCT
: return "FC_CVSTRUCT";
98 case RPC_FC_BOGUS_STRUCT
: return "FC_BOGUS_STRUCT";
99 case RPC_FC_SMFARRAY
: return "FC_SMFARRAY";
100 case RPC_FC_LGFARRAY
: return "FC_LGFARRAY";
101 case RPC_FC_SMVARRAY
: return "FC_SMVARRAY";
102 case RPC_FC_LGVARRAY
: return "FC_LGVARRAY";
103 case RPC_FC_CARRAY
: return "FC_CARRAY";
104 case RPC_FC_CVARRAY
: return "FC_CVARRAY";
105 case RPC_FC_BOGUS_ARRAY
: return "FC_BOGUS_ARRAY";
107 error("string_of_type: unknown type 0x%02x\n", type
);
112 static int is_struct(unsigned char type
)
119 case RPC_FC_CPSTRUCT
:
120 case RPC_FC_CVSTRUCT
:
121 case RPC_FC_BOGUS_STRUCT
:
128 static int is_union(unsigned char type
)
132 case RPC_FC_ENCAPSULATED_UNION
:
133 case RPC_FC_NON_ENCAPSULATED_UNION
:
140 static void update_tfsoff(type_t
*type
, unsigned int offset
, FILE *file
)
142 type
->typestring_offset
= offset
;
143 if (file
) type
->tfswrite
= FALSE
;
146 static void guard_rec(type_t
*type
)
148 /* types that contain references to themselves (like a linked list),
149 need to be shielded from infinite recursion when writing embedded
151 if (type
->typestring_offset
)
152 type
->tfswrite
= FALSE
;
154 type
->typestring_offset
= 1;
157 static int is_embedded_complex(const type_t
*type
)
159 unsigned char tc
= type
->type
;
160 return is_struct(tc
) || is_union(tc
) || is_array(type
);
163 static long field_offset(const type_t
*strct
, const char *name
, var_t
**pfield
)
166 var_list_t
*fields
= strct
->fields
;
169 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
171 unsigned int align
= 0;
173 if (f
->name
!= NULL
&& strcmp(name
, f
->name
) == 0)
175 if (pfield
) *pfield
= f
;
180 /* FIXME: handle possible padding */
181 offset
+= type_memsize(f
->type
, &align
);
185 if (pfield
) *pfield
= NULL
;
189 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
193 if (a
->type
!= b
->type
)
194 return a
->type
- b
->type
;
201 return a
->u
.lval
- b
->u
.lval
;
202 case EXPR_IDENTIFIER
:
203 return strcmp(a
->u
.sval
, b
->u
.sval
);
205 ret
= compare_expr(a
->ref
, b
->ref
);
208 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
211 return compare_expr(a
->ext2
, b
->ext2
);
220 ret
= compare_expr(a
->ref
, b
->ref
);
223 return compare_expr(a
->u
.ext
, b
->u
.ext
);
229 return compare_expr(a
->ref
, b
->ref
);
236 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
239 fprintf(file, "/* %2u */\n", typestring_offset); \
240 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
244 static int print_file(FILE *file
, int indent
, const char *format
, ...)
251 va_start(va
, format
);
252 for (i
= 0; i
< indent
; i
++)
254 r
= vfprintf(file
, format
, va
);
259 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
261 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
262 print_file(f
, indent
, "{\n");
263 print_file(f
, indent
+ 1, "short Pad;\n");
264 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
265 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
266 print_file(f
, indent
, "\n");
269 void write_formatstringsdecl(FILE *f
, int indent
, ifref_list_t
*ifaces
, int for_objects
)
271 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
272 get_size_typeformatstring(ifaces
, for_objects
));
274 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
275 get_size_procformatstring(ifaces
, for_objects
));
278 write_formatdesc(f
, indent
, "TYPE");
279 write_formatdesc(f
, indent
, "PROC");
281 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
282 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
283 print_file(f
, indent
, "\n");
286 static int is_user_derived(const var_t
*v
)
288 const type_t
*type
= v
->type
;
290 if (v
->attrs
&& is_attr( v
->attrs
, ATTR_WIREMARSHAL
)) return 1;
294 if (type
->attrs
&& is_attr( type
->attrs
, ATTR_WIREMARSHAL
)) return 1;
300 static inline int is_base_type(unsigned char type
)
319 case RPC_FC_ERROR_STATUS_T
:
320 case RPC_FC_BIND_PRIMITIVE
:
328 static size_t write_procformatstring_var(FILE *file
, int indent
,
329 const var_t
*var
, int is_return
)
332 const type_t
*type
= var
->type
;
334 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
335 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
337 if (!is_in
&& !is_out
) is_in
= TRUE
;
339 if (!type
->declarray
&& is_base_type(type
->type
))
342 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
344 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
346 if (type
->type
== RPC_FC_BIND_PRIMITIVE
)
348 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
349 size
= 2; /* includes param type prefix */
351 else if (is_base_type(type
->type
))
353 print_file(file
, indent
, "0x%02x, /* %s */\n", type
->type
, string_of_type(type
->type
));
354 size
= 2; /* includes param type prefix */
358 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
365 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
366 else if (is_in
&& is_out
)
367 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
369 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
371 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
373 print_file(file
, indent
, "0x01,\n");
374 print_file(file
, indent
, "NdrFcShort(0x%x),\n", type
->typestring_offset
);
375 size
= 4; /* includes param type prefix */
380 void write_procformatstring(FILE *file
, const ifref_list_t
*ifaces
, int for_objects
)
382 const ifref_t
*iface
;
386 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
387 print_file(file
, indent
, "{\n");
389 print_file(file
, indent
, "0,\n");
390 print_file(file
, indent
, "{\n");
393 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
395 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
398 if (iface
->iface
->funcs
)
401 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
403 if (is_local(func
->def
->attrs
)) continue;
404 /* emit argument data */
407 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
408 write_procformatstring_var(file
, indent
, var
, FALSE
);
411 /* emit return value data */
413 if (is_void(var
->type
))
415 print_file(file
, indent
, "0x5b, /* FC_END */\n");
416 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
419 write_procformatstring_var(file
, indent
, var
, TRUE
);
424 print_file(file
, indent
, "0x0\n");
426 print_file(file
, indent
, "}\n");
428 print_file(file
, indent
, "};\n");
429 print_file(file
, indent
, "\n");
432 static int write_base_type(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
434 if (is_base_type(type
->type
))
436 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
437 *typestring_offset
+= 1;
444 /* write conformance / variance descriptor */
445 static size_t write_conf_or_var_desc(FILE *file
, const func_t
*func
, const type_t
*structure
, const expr_t
*expr
)
447 unsigned char operator_type
= 0;
448 const char *operator_string
= "no operators";
449 const expr_t
*subexpr
;
450 unsigned char correlation_type
;
452 if (!file
) return 4; /* optimisation for sizing pass */
456 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
457 error("write_conf_or_var_desc: constant value %ld is greater than "
458 "the maximum constant size of %d\n", expr
->cval
,
459 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
461 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
462 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
463 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
464 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
470 switch (subexpr
->type
)
473 subexpr
= subexpr
->ref
;
474 operator_type
= RPC_FC_DEREFERENCE
;
475 operator_string
= "FC_DEREFERENCE";
478 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
480 subexpr
= subexpr
->ref
;
481 operator_type
= RPC_FC_DIV_2
;
482 operator_string
= "FC_DIV_2";
486 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
488 subexpr
= subexpr
->ref
;
489 operator_type
= RPC_FC_MULT_2
;
490 operator_string
= "FC_MULT_2";
494 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
496 subexpr
= subexpr
->ref
;
497 operator_type
= RPC_FC_SUB_1
;
498 operator_string
= "FC_SUB_1";
502 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
504 subexpr
= subexpr
->ref
;
505 operator_type
= RPC_FC_ADD_1
;
506 operator_string
= "FC_ADD_1";
513 if (subexpr
->type
== EXPR_IDENTIFIER
)
515 const type_t
*correlation_variable
= NULL
;
516 unsigned char correlation_variable_type
;
517 unsigned char param_type
= 0;
518 const char *param_type_string
= NULL
;
526 if (structure
->fields
) LIST_FOR_EACH_ENTRY( var
, structure
->fields
, const var_t
, entry
)
528 unsigned int align
= 0;
529 offset
-= type_memsize(var
->type
, &align
);
530 /* FIXME: take alignment into account */
531 if (!strcmp(var
->name
, subexpr
->u
.sval
))
533 correlation_variable
= var
->type
;
537 if (!correlation_variable
)
538 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
541 correlation_type
= RPC_FC_NORMAL_CONFORMANCE
;
547 offset
= sizeof(void *);
548 if (func
->args
) LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
550 if (!strcmp(var
->name
, subexpr
->u
.sval
))
552 correlation_variable
= var
->type
;
555 /* FIXME: not all stack variables are sizeof(void *) */
556 offset
+= sizeof(void *);
558 if (!correlation_variable
)
559 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
562 correlation_type
= RPC_FC_TOP_LEVEL_CONFORMANCE
;
565 correlation_variable_type
= correlation_variable
->type
;
567 switch (correlation_variable_type
)
571 param_type
= RPC_FC_SMALL
;
572 param_type_string
= "FC_SMALL";
576 param_type
= RPC_FC_USMALL
;
577 param_type_string
= "FC_USMALL";
581 param_type
= RPC_FC_SHORT
;
582 param_type_string
= "FC_SHORT";
585 param_type
= RPC_FC_USHORT
;
586 param_type_string
= "FC_USHORT";
589 param_type
= RPC_FC_LONG
;
590 param_type_string
= "FC_LONG";
593 param_type
= RPC_FC_ULONG
;
594 param_type_string
= "FC_ULONG";
600 if (sizeof(void *) == 4) /* FIXME */
602 param_type
= RPC_FC_LONG
;
603 param_type_string
= "FC_LONG";
607 param_type
= RPC_FC_HYPER
;
608 param_type_string
= "FC_HYPER";
612 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
613 correlation_variable_type
);
616 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
617 correlation_type
| param_type
,
618 correlation_type
== RPC_FC_TOP_LEVEL_CONFORMANCE
? "parameter, " : "",
620 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
621 print_file(file
, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
623 correlation_type
== RPC_FC_TOP_LEVEL_CONFORMANCE
? "x86 stack size / " : "",
628 unsigned int callback_offset
= 0;
632 struct expr_eval_routine
*eval
;
635 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
637 if (!strcmp(eval
->structure
->name
, structure
->name
) &&
638 !compare_expr(eval
->expr
, expr
))
648 unsigned int align
= 0;
649 eval
= xmalloc(sizeof(*eval
));
650 eval
->structure
= structure
;
651 eval
->structure_size
= fields_memsize(structure
->fields
, &align
);
653 list_add_tail(&expr_eval_routines
, &eval
->entry
);
656 correlation_type
= RPC_FC_NORMAL_CONFORMANCE
;
660 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
661 correlation_type
= RPC_FC_TOP_LEVEL_CONFORMANCE
;
664 if (callback_offset
> USHRT_MAX
)
665 error("Maximum number of callback routines reached\n");
667 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n",
669 correlation_type
== RPC_FC_TOP_LEVEL_CONFORMANCE
? "parameter" : "");
670 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
671 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
676 static size_t fields_memsize(const var_list_t
*fields
, unsigned int *align
)
681 if (!fields
) return 0;
682 LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
683 size
+= type_memsize(v
->type
, align
);
688 static size_t union_memsize(const var_list_t
*fields
, unsigned int *pmaxa
)
690 size_t size
, maxs
= 0;
691 unsigned int align
= *pmaxa
;
694 if (fields
) LIST_FOR_EACH_ENTRY( v
, fields
, const var_t
, entry
)
696 /* we could have an empty default field with NULL type */
699 size
= type_memsize(v
->type
, &align
);
700 if (maxs
< size
) maxs
= size
;
701 if (*pmaxa
< align
) *pmaxa
= align
;
708 size_t type_memsize(const type_t
*t
, unsigned int *align
)
714 size
= sizeof(void *);
715 if (size
> *align
) *align
= size
;
717 else switch (t
->type
)
724 if (size
> *align
) *align
= size
;
731 if (size
> *align
) *align
= size
;
735 case RPC_FC_ERROR_STATUS_T
:
739 if (size
> *align
) *align
= size
;
744 if (size
> *align
) *align
= size
;
747 case RPC_FC_CVSTRUCT
:
748 case RPC_FC_CPSTRUCT
:
751 case RPC_FC_BOGUS_STRUCT
:
752 size
= fields_memsize(t
->fields
, align
);
754 case RPC_FC_ENCAPSULATED_UNION
:
755 case RPC_FC_NON_ENCAPSULATED_UNION
:
756 size
= union_memsize(t
->fields
, align
);
758 case RPC_FC_SMFARRAY
:
759 case RPC_FC_LGFARRAY
:
760 case RPC_FC_SMVARRAY
:
761 case RPC_FC_LGVARRAY
:
762 size
= t
->dim
* type_memsize(t
->ref
, align
);
766 case RPC_FC_BOGUS_ARRAY
:
767 size
= type_memsize(t
->ref
, align
);
770 error("type_memsize: Unknown type %d\n", t
->type
);
777 static unsigned int write_nonsimple_pointer(FILE *file
, const type_t
*type
, size_t offset
)
779 short absoff
= type
->ref
->typestring_offset
;
780 short reloff
= absoff
- (offset
+ 2);
781 int ptr_attr
= is_ptr(type
->ref
) ? 0x10 : 0x0;
783 print_file(file
, 2, "0x%02x, 0x%x,\t/* %s */\n",
784 type
->type
, ptr_attr
, string_of_type(type
->type
));
785 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
786 reloff
, reloff
, absoff
);
790 static unsigned int write_simple_pointer(FILE *file
, const type_t
*type
)
792 print_file(file
, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
793 type
->type
, string_of_type(type
->type
));
794 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->ref
->type
,
795 string_of_type(type
->ref
->type
));
796 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
800 static size_t write_pointer_tfs(FILE *file
, type_t
*type
, unsigned int *typestring_offset
)
802 unsigned int offset
= *typestring_offset
;
804 print_file(file
, 0, "/* %d */\n", offset
);
805 update_tfsoff(type
, offset
, file
);
807 if (type
->ref
->typestring_offset
)
808 *typestring_offset
+= write_nonsimple_pointer(file
, type
, offset
);
809 else if (is_base_type(type
->ref
->type
))
810 *typestring_offset
+= write_simple_pointer(file
, type
);
815 static int processed(const type_t
*type
)
817 return type
->typestring_offset
&& !type
->tfswrite
;
820 static void write_member_type(FILE *file
, type_t
*type
, const var_t
*field
,
821 unsigned int *tfsoff
)
825 print_file(file
, 2, "0x8,\t/* FC_LONG */\n");
828 else if (is_embedded_complex(type
))
830 size_t absoff
= (field
&& field
->corrdesc
832 : type
->typestring_offset
);
833 short reloff
= absoff
- (*tfsoff
+ 2);
835 print_file(file
, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
836 /* FIXME: actually compute necessary padding */
837 print_file(file
, 2, "0x0,\t/* FIXME: padding */\n");
838 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
839 reloff
, reloff
, absoff
);
842 else if (!write_base_type(file
, type
, tfsoff
))
843 error("Unsupported member type 0x%x\n", type
->type
);
846 static void write_end(FILE *file
, unsigned int *tfsoff
)
848 if (*tfsoff
% 2 == 0)
850 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
853 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
857 static size_t write_pointer_description(FILE *file
, type_t
*type
, size_t mem_offset
,
858 int level
, unsigned int *typestring_offset
)
861 unsigned int align
= 0;
863 /* don't generate a pointer for first-level arrays since we want to
864 * descend into them to write their pointers, not stop here */
865 if (level
== 0 && is_array(type
))
867 write_pointer_description(file
, type
->ref
, mem_offset
, level
+ 1,
870 else if (is_ptr(type
))
872 print_file(file
, 2, "0x46,\t/* FC_NO_REPEAT */\n");
873 print_file(file
, 2, "0x5c,\t/* FC_PAD */\n");
874 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset
, mem_offset
);
875 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset
, mem_offset
);
876 *typestring_offset
+= 6;
878 if (processed(type
->ref
) || is_base_type(type
->ref
->type
))
879 write_pointer_tfs(file
, type
, typestring_offset
);
881 error("write_pointer_description: type format string unknown\n");
883 else if (level
== 0 && is_struct(type
->type
))
887 LIST_FOR_EACH_ENTRY( v
, type
->fields
, const var_t
, entry
)
889 += write_pointer_description(file
, v
->type
, mem_offset
,
890 level
+ 1, typestring_offset
);
894 return type_memsize(type
, &align
);
897 static size_t write_string_tfs(FILE *file
, const attr_list_t
*attrs
,
899 const char *name
, unsigned int *typestring_offset
)
901 size_t start_offset
= *typestring_offset
;
902 unsigned char flags
= 0;
908 pointer_type
= type
->type
;
912 pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
915 pointer_type
= RPC_FC_RP
;
917 if (!get_attrp(attrs
, ATTR_SIZEIS
))
918 flags
|= RPC_FC_P_SIMPLEPOINTER
;
922 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
924 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
928 print_file(file
, 2,"0x%x, 0x%x, /* %s%s */\n",
930 pointer_type
== RPC_FC_FP
? "FC_FP" : (pointer_type
== RPC_FC_UP
? "FC_UP" : "FC_RP"),
931 (flags
& RPC_FC_P_SIMPLEPOINTER
) ? " [simple_pointer]" : "");
932 *typestring_offset
+= 2;
934 if (!(flags
& RPC_FC_P_SIMPLEPOINTER
))
936 print_file(file
, 2, "NdrFcShort(0x2),\n");
937 *typestring_offset
+= 2;
940 if (type
->declarray
&& !is_conformant_array(type
))
942 /* FIXME: multi-dimensional array */
943 if (0xffffuL
< type
->dim
)
944 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
945 name
, 0xffffu
, type
->dim
- 0xffffu
);
947 if (rtype
== RPC_FC_CHAR
)
948 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
950 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
951 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
952 *typestring_offset
+= 2;
954 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", type
->dim
, type
->dim
);
955 *typestring_offset
+= 2;
959 else if (type
->size_is
)
961 if (rtype
== RPC_FC_CHAR
)
962 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
964 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
965 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
966 *typestring_offset
+= 2;
968 *typestring_offset
+= write_conf_or_var_desc(file
, current_func
, NULL
, type
->size_is
);
974 if (rtype
== RPC_FC_CHAR
)
975 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
977 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
978 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
979 *typestring_offset
+= 2;
985 static size_t write_array_tfs(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
986 const char *name
, unsigned int *typestring_offset
)
988 const expr_t
*length_is
= type
->length_is
;
989 const expr_t
*size_is
= type
->size_is
;
990 unsigned int align
= 0;
994 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
996 pointer_type
= RPC_FC_RP
;
999 if (write_embedded_types(file
, attrs
, type
, name
, 0, typestring_offset
))
1002 size
= type_memsize(type
, &align
);
1004 start_offset
= *typestring_offset
;
1005 update_tfsoff(type
, start_offset
, file
);
1006 print_file(file
, 0, "/* %lu */\n", start_offset
);
1007 print_file(file
, 2, "0x%02x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1008 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1009 *typestring_offset
+= 2;
1011 if (type
->type
!= RPC_FC_BOGUS_ARRAY
)
1013 unsigned char tc
= type
->type
;
1015 if (tc
== RPC_FC_LGFARRAY
|| tc
== RPC_FC_LGVARRAY
)
1017 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size
, size
);
1018 *typestring_offset
+= 4;
1022 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size
, size
);
1023 *typestring_offset
+= 2;
1026 if (is_conformant_array(type
))
1028 += write_conf_or_var_desc(file
, current_func
,
1029 current_structure
, size_is
);
1031 if (type
->type
== RPC_FC_SMVARRAY
|| type
->type
== RPC_FC_LGVARRAY
)
1033 unsigned int elalign
= 0;
1034 size_t elsize
= type_memsize(type
->ref
, &elalign
);
1036 if (type
->type
== RPC_FC_LGVARRAY
)
1038 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1039 *typestring_offset
+= 4;
1043 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type
->dim
, type
->dim
);
1044 *typestring_offset
+= 2;
1047 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize
, elsize
);
1048 *typestring_offset
+= 2;
1053 += write_conf_or_var_desc(file
, current_func
,
1054 current_structure
, length_is
);
1058 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1059 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1060 *typestring_offset
+= 2;
1061 write_pointer_description(file
, type
, 0, 0, typestring_offset
);
1062 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1063 *typestring_offset
+= 1;
1066 write_member_type(file
, type
->ref
, NULL
, typestring_offset
);
1067 write_end(file
, typestring_offset
);
1070 error("%s: complex arrays unimplemented\n", name
);
1072 return start_offset
;
1075 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1077 const var_t
*last_field
= LIST_ENTRY( list_tail(type
->fields
), const var_t
, entry
);
1079 if (last_field
->type
->declarray
)
1082 assert((last_field
->type
->type
== RPC_FC_CSTRUCT
) ||
1083 (last_field
->type
->type
== RPC_FC_CPSTRUCT
) ||
1084 (last_field
->type
->type
== RPC_FC_CVSTRUCT
));
1086 return find_array_or_string_in_struct(last_field
->type
);
1089 static void write_struct_members(FILE *file
, const type_t
*type
, unsigned int *typestring_offset
)
1093 if (type
->fields
) LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1094 write_member_type(file
, field
->type
, field
, typestring_offset
);
1096 write_end(file
, typestring_offset
);
1099 static size_t write_struct_tfs(FILE *file
, type_t
*type
,
1100 const char *name
, unsigned int *typestring_offset
)
1102 unsigned int total_size
;
1104 size_t start_offset
;
1105 size_t array_offset
;
1107 unsigned int align
= 0;
1114 case RPC_FC_PSTRUCT
:
1115 total_size
= type_memsize(type
, &align
);
1117 if (total_size
> USHRT_MAX
)
1118 error("structure size for %s exceeds %d bytes by %d bytes\n",
1119 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1121 if (type
->type
== RPC_FC_PSTRUCT
)
1122 write_embedded_types(file
, NULL
, type
, name
, 0, typestring_offset
);
1124 start_offset
= *typestring_offset
;
1125 update_tfsoff(type
, start_offset
, file
);
1126 if (type
->type
== RPC_FC_STRUCT
)
1127 WRITE_FCTYPE(file
, FC_STRUCT
, *typestring_offset
);
1129 WRITE_FCTYPE(file
, FC_PSTRUCT
, *typestring_offset
);
1131 print_file(file
, 2, "0x%02x,\n", align
- 1);
1133 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", total_size
, total_size
);
1134 *typestring_offset
+= 4;
1136 if (type
->type
== RPC_FC_PSTRUCT
)
1138 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1139 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1140 *typestring_offset
+= 2;
1141 write_pointer_description(file
, type
, 0, 0, typestring_offset
);
1142 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1143 *typestring_offset
+= 1;
1147 current_structure
= type
;
1148 write_struct_members(file
, type
, typestring_offset
);
1149 current_structure
= NULL
;
1150 return start_offset
;
1151 case RPC_FC_CSTRUCT
:
1152 case RPC_FC_CPSTRUCT
:
1153 total_size
= type_memsize(type
, &align
);
1155 if (total_size
> USHRT_MAX
)
1156 error("structure size for %s exceeds %d bytes by %d bytes\n",
1157 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1159 array
= find_array_or_string_in_struct(type
);
1160 current_structure
= type
;
1161 array_offset
= write_array_tfs(file
, array
->attrs
, array
->type
,
1162 array
->name
, typestring_offset
);
1163 current_structure
= NULL
;
1165 if (type
->type
== RPC_FC_CPSTRUCT
)
1166 write_embedded_types(file
, NULL
, type
, name
, 0, typestring_offset
);
1168 start_offset
= *typestring_offset
;
1169 update_tfsoff(type
, start_offset
, file
);
1170 if (type
->type
== RPC_FC_CSTRUCT
)
1171 WRITE_FCTYPE(file
, FC_CSTRUCT
, *typestring_offset
);
1173 WRITE_FCTYPE(file
, FC_CPSTRUCT
, *typestring_offset
);
1175 print_file(file
, 2, "0x%02x,\n", align
- 1);
1177 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", total_size
, total_size
);
1178 *typestring_offset
+= 4;
1179 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1180 array_offset
- *typestring_offset
,
1181 array_offset
- *typestring_offset
,
1183 *typestring_offset
+= 2;
1185 if (type
->type
== RPC_FC_CPSTRUCT
)
1187 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1188 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1189 *typestring_offset
+= 2;
1190 write_pointer_description(file
, type
, 0, 0, typestring_offset
);
1191 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1192 *typestring_offset
+= 1;
1195 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1196 *typestring_offset
+= 1;
1198 return start_offset
;
1199 case RPC_FC_CVSTRUCT
:
1200 total_size
= type_memsize(type
, &align
);
1202 if (total_size
> USHRT_MAX
)
1203 error("structure size for %s exceeds %d bytes by %d bytes\n",
1204 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1206 array
= find_array_or_string_in_struct(type
);
1207 current_structure
= type
;
1208 if (is_attr(array
->attrs
, ATTR_STRING
))
1209 array_offset
= write_string_tfs(file
, array
->attrs
, array
->type
,
1210 array
->name
, typestring_offset
);
1212 array_offset
= write_array_tfs(file
, array
->attrs
, array
->type
,
1213 array
->name
, typestring_offset
);
1214 current_structure
= NULL
;
1216 has_pointers
= write_embedded_types(file
, NULL
, type
, name
, 0,
1219 start_offset
= *typestring_offset
;
1220 update_tfsoff(type
, start_offset
, file
);
1221 WRITE_FCTYPE(file
, FC_CVSTRUCT
, *typestring_offset
);
1223 print_file(file
, 2, "0x%02x,\n", align
- 1);
1225 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", total_size
, total_size
);
1226 *typestring_offset
+= 4;
1227 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1228 array_offset
- *typestring_offset
,
1229 array_offset
- *typestring_offset
,
1231 *typestring_offset
+= 2;
1235 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1236 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1237 *typestring_offset
+= 2;
1238 write_pointer_description(file
, type
, 0, 0, typestring_offset
);
1239 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1240 *typestring_offset
+= 1;
1243 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1244 *typestring_offset
+= 1;
1246 return start_offset
;
1248 case RPC_FC_BOGUS_STRUCT
:
1249 total_size
= type_memsize(type
, &align
);
1250 if (total_size
> USHRT_MAX
)
1251 error("structure size for %s exceeds %d bytes by %d bytes\n",
1252 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1254 write_embedded_types(file
, NULL
, type
, name
, 0, typestring_offset
);
1256 start_offset
= *typestring_offset
;
1257 update_tfsoff(type
, start_offset
, file
);
1258 print_file(file
, 0, "/* %d */\n", start_offset
);
1259 print_file(file
, 2, "0x%x,\t/* %s */\n", type
->type
, string_of_type(type
->type
));
1260 print_file(file
, 2, "0x%x,\t/* %d */\n", align
- 1, align
- 1);
1261 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size
, total_size
);
1263 /* do conformant array stuff */
1264 print_file(file
, 2, "NdrFcShort(0x0),\t/* FIXME: conformant array stuff */\n");
1266 /* do pointer stuff here */
1267 print_file(file
, 2, "NdrFcShort(0x0),\t/* FIXME: pointer stuff */\n");
1269 *typestring_offset
+= 8;
1270 current_structure
= type
;
1271 write_struct_members(file
, type
, typestring_offset
);
1272 current_structure
= NULL
;
1274 return start_offset
;
1277 error("write_struct_tfs: Unimplemented for type 0x%x\n", type
->type
);
1278 return *typestring_offset
;
1282 static size_t write_pointer_only_tfs(FILE *file
, const attr_list_t
*attrs
, int pointer_type
,
1283 unsigned char flags
, size_t offset
,
1284 unsigned int *typeformat_offset
)
1286 size_t start_offset
= *typeformat_offset
;
1287 short reloff
= offset
- (*typeformat_offset
+ 2);
1288 int in_attr
, out_attr
;
1289 in_attr
= is_attr(attrs
, ATTR_IN
);
1290 out_attr
= is_attr(attrs
, ATTR_OUT
);
1291 if (!in_attr
&& !out_attr
) in_attr
= 1;
1293 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1296 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1299 string_of_type(pointer_type
));
1303 fprintf(file
, " [allocated_on_stack]");
1305 fprintf(file
, " [pointer_deref]");
1306 fprintf(file
, " */\n");
1309 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff
, offset
);
1310 *typeformat_offset
+= 4;
1312 return start_offset
;
1315 static void write_branch_type(FILE *file
, const type_t
*t
, unsigned int *tfsoff
)
1317 if (is_base_type(t
->type
))
1319 print_file(file
, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1320 t
->type
, string_of_type(t
->type
));
1322 else if (t
->typestring_offset
)
1324 short reloff
= t
->typestring_offset
- *tfsoff
;
1325 print_file(file
, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1326 reloff
, reloff
, t
->typestring_offset
);
1329 error("write_branch_type: type unimplemented (0x%x)\n", t
->type
);
1334 static size_t write_union_tfs(FILE *file
, type_t
*type
, const char *name
,
1335 unsigned int *tfsoff
)
1337 unsigned int align
= 0;
1338 unsigned int start_offset
;
1339 size_t size
= type_memsize(type
, &align
);
1340 var_list_t
*fields
= type
->fields
;
1342 type_t
*deftype
= NULL
;
1343 short nodeftype
= 0xffff;
1348 /* use a level of 1 so pointers always get written */
1349 write_embedded_types(file
, NULL
, type
, name
, 1, tfsoff
);
1351 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1353 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
1355 nbranch
+= list_count(cases
);
1358 start_offset
= *tfsoff
;
1359 update_tfsoff(type
, start_offset
, file
);
1360 print_file(file
, 0, "/* %d */\n", start_offset
);
1361 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", size
, size
);
1362 print_file(file
, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch
, nbranch
);
1365 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1367 type_t
*ft
= f
->type
;
1368 expr_list_t
*cases
= get_attrp(f
->attrs
, ATTR_CASE
);
1369 int deflt
= is_attr(f
->attrs
, ATTR_DEFAULT
);
1372 if (cases
== NULL
&& !deflt
)
1373 error("union field %s with neither case nor default attribute\n", f
->name
);
1375 if (cases
) LIST_FOR_EACH_ENTRY(c
, cases
, expr_t
, entry
)
1377 /* MIDL doesn't check for duplicate cases, even though that seems
1378 like a reasonable thing to do, it just dumps them to the TFS
1379 like we're going to do here. */
1380 print_file(file
, 2, "NdrFcLong(0x%x),\t/* %d */\n", c
->cval
, c
->cval
);
1382 write_branch_type(file
, ft
, tfsoff
);
1385 /* MIDL allows multiple default branches, even though that seems
1386 illogical, it just chooses the last one, which is what we will
1397 write_branch_type(file
, deftype
, tfsoff
);
1401 print_file(file
, 2, "NdrFcShort(0x%x),\n", nodeftype
);
1405 return start_offset
;
1408 static size_t write_ip_tfs(FILE *file
, const func_t
*func
, const type_t
*type
, const var_t
*var
,
1409 unsigned int *typeformat_offset
)
1412 size_t start_offset
= *typeformat_offset
;
1413 const var_t
*iid
= get_attrp(var
->attrs
, ATTR_IIDIS
);
1419 expr
.type
= EXPR_IDENTIFIER
;
1421 expr
.u
.sval
= iid
->name
;
1422 expr
.is_const
= FALSE
;
1423 print_file(file
, 2, "0x2f, /* FC_IP */\n");
1424 print_file(file
, 2, "0x5c, /* FC_PAD */\n");
1425 *typeformat_offset
+= write_conf_or_var_desc(file
, func
, NULL
, &expr
) + 2;
1429 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
1430 const UUID
*uuid
= get_attrp(base
->attrs
, ATTR_UUID
);
1433 error("%s: interface %s missing UUID\n", __FUNCTION__
, base
->name
);
1435 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
1436 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1437 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
1438 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
1439 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
1440 for (i
= 0; i
< 8; ++i
)
1441 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
1444 fprintf(file
, "\n");
1446 *typeformat_offset
+= 18;
1448 return start_offset
;
1451 static int get_ptr_attr(const type_t
*t
, int def_type
)
1455 int ptr_attr
= get_attrv(t
->attrs
, ATTR_POINTERTYPE
);
1458 if (t
->kind
!= TKIND_ALIAS
)
1464 static size_t write_typeformatstring_var(FILE *file
, int indent
, const func_t
*func
,
1465 type_t
*type
, const var_t
*var
,
1466 unsigned int *typeformat_offset
)
1471 if (type
== var
->type
) /* top-level pointers */
1473 int pointer_attr
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
1474 if (pointer_attr
!= 0 && !is_ptr(type
) && !is_array(type
))
1475 error("'%s': pointer attribute applied to non-pointer type\n", var
->name
);
1477 if (pointer_attr
== 0)
1478 pointer_attr
= get_ptr_attr(type
, RPC_FC_RP
);
1480 pointer_type
= pointer_attr
;
1483 pointer_type
= get_ptr_attr(type
, RPC_FC_UP
);
1485 if ((last_ptr(type
) || last_array(type
)) && is_ptrchain_attr(var
, ATTR_STRING
))
1486 return write_string_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
1489 return write_array_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
1493 /* basic types don't need a type format string */
1494 if (is_base_type(type
->type
))
1500 case RPC_FC_PSTRUCT
:
1501 case RPC_FC_CSTRUCT
:
1502 case RPC_FC_CPSTRUCT
:
1503 case RPC_FC_CVSTRUCT
:
1504 case RPC_FC_BOGUS_STRUCT
:
1505 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
1506 case RPC_FC_ENCAPSULATED_UNION
:
1507 case RPC_FC_NON_ENCAPSULATED_UNION
:
1508 return write_union_tfs(file
, type
, var
->name
, typeformat_offset
);
1510 case RPC_FC_BIND_PRIMITIVE
:
1514 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
1517 else if (last_ptr(type
))
1519 size_t start_offset
= *typeformat_offset
;
1520 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
1521 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
1522 const type_t
*base
= type
->ref
;
1524 if (base
->type
== RPC_FC_IP
)
1526 return write_ip_tfs(file
, func
, type
, var
, typeformat_offset
);
1529 /* special case for pointers to base types */
1530 if (is_base_type(base
->type
))
1532 print_file(file
, indent
, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
1533 pointer_type
, (!in_attr
&& out_attr
) ? 0x0C : 0x08,
1534 string_of_type(pointer_type
),
1535 (!in_attr
&& out_attr
) ? "[allocated_on_stack] " : "");
1536 print_file(file
, indent
, "0x%02x, /* %s */\n", base
->type
, string_of_type(base
->type
));
1537 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
1538 *typeformat_offset
+= 4;
1539 return start_offset
;
1543 assert(is_ptr(type
));
1545 offset
= write_typeformatstring_var(file
, indent
, func
, type
->ref
, var
, typeformat_offset
);
1547 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
1548 return write_pointer_only_tfs(file
, var
->attrs
, pointer_type
,
1549 !last_ptr(type
) ? 0x10 : 0,
1550 offset
, typeformat_offset
);
1553 static void set_tfswrite(type_t
*type
, int val
)
1555 while (type
->tfswrite
!= val
)
1557 type
->tfswrite
= val
;
1559 if (type
->kind
== TKIND_ALIAS
)
1561 else if (is_ptr(type
))
1568 LIST_FOR_EACH_ENTRY( v
, type
->fields
, var_t
, entry
)
1569 set_tfswrite(v
->type
, val
);
1577 static int write_embedded_types(FILE *file
, const attr_list_t
*attrs
, type_t
*type
,
1578 const char *name
, int level
, unsigned int *tfsoff
)
1580 var_list_t
*fields
= type
->fields
;
1585 if (fields
) LIST_FOR_EACH_ENTRY(f
, fields
, var_t
, entry
)
1587 unsigned int align
= 0;
1588 type_t
*ft
= f
->type
;
1591 else if (ft
->type
== RPC_FC_NON_ENCAPSULATED_UNION
)
1593 expr_t
*swexp
= get_attrp(f
->attrs
, ATTR_SWITCHIS
);
1597 unsigned char corrdesc
, op
= 0;
1598 short creloff
, ureloff
;
1601 error("union %s needs a switch_is attribute\n", f
->name
);
1602 if (swexp
->type
!= EXPR_IDENTIFIER
)
1603 error("%s: only identifiers are supported for switch_is at this time\n",
1607 write_union_tfs(file
, ft
, f
->name
, tfsoff
);
1609 swname
= swexp
->u
.sval
;
1610 corroff
= field_offset(type
, swname
, &swvar
);
1611 corrdesc
= swvar
->type
->type
;
1612 creloff
= corroff
- offset
;
1614 f
->corrdesc
= *tfsoff
;
1615 ureloff
= ft
->typestring_offset
- (f
->corrdesc
+ 6);
1616 print_file(file
, 0, "/* %d */\n", f
->corrdesc
);
1617 print_file(file
, 2, "0x%x,\t/* %s */\n", ft
->type
, string_of_type(ft
->type
));
1618 print_file(file
, 2, "0x8,\t/* FIXME: support other switch types */\n");
1619 print_file(file
, 2, "0x%x,\t/* Corr desc: %s */\n",
1620 corrdesc
, string_of_type(corrdesc
& 0xf));
1621 print_file(file
, 2, "0x%x,\n", op
);
1622 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* %hd */\n", creloff
, creloff
);
1623 print_file(file
, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1624 ureloff
, ureloff
, ft
->typestring_offset
);
1628 retmask
|= write_embedded_types(file
, attrs
, ft
, f
->name
,
1631 /* FIXME: this doesn't take alignment/padding into account */
1632 offset
+= type_memsize(ft
, &align
);
1634 /* don't generate a pointer for first-level arrays since we want to
1635 descend into them to write their pointers, not stop here */
1636 else if (level
== 0 && is_array(type
))
1638 return write_embedded_types(file
, NULL
, type
->ref
, name
, level
+ 1, tfsoff
);
1640 else if (is_ptr(type
))
1642 type_t
*ref
= type
->ref
;
1644 if (!processed(ref
) && !is_base_type(ref
->type
))
1648 retmask
|= write_embedded_types(file
, attrs
, ref
, name
,
1651 else if (is_struct(ref
->type
))
1653 write_struct_tfs(file
, ref
, name
, tfsoff
);
1657 error("write_embedded_types: type format string unknown for %s (0x%x)\n",
1662 /* top-level pointers are handled inline */
1664 write_pointer_tfs(file
, type
, tfsoff
);
1668 else if (is_array(type
))
1670 retmask
|= write_array_tfs(file
, attrs
, type
, name
, tfsoff
);
1672 else if (!is_base_type(type
->type
))
1673 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
1679 static void set_all_tfswrite(const ifref_list_t
*ifaces
, int val
)
1681 const ifref_t
* iface
;
1686 LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
1687 if (iface
->iface
->funcs
)
1688 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
1690 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
1691 set_tfswrite(var
->type
, val
);
1694 static size_t process_tfs(FILE *file
, const ifref_list_t
*ifaces
, int for_objects
)
1697 const ifref_t
*iface
;
1698 unsigned int typeformat_offset
= 2;
1700 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
1702 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
1705 if (iface
->iface
->funcs
)
1708 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
1710 if (is_local(func
->def
->attrs
)) continue;
1712 current_func
= func
;
1714 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
1717 write_typeformatstring_var(
1718 file
, 2, func
, var
->type
, var
,
1719 &typeformat_offset
),
1725 return typeformat_offset
+ 1;
1729 void write_typeformatstring(FILE *file
, const ifref_list_t
*ifaces
, int for_objects
)
1733 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1734 print_file(file
, indent
, "{\n");
1736 print_file(file
, indent
, "0,\n");
1737 print_file(file
, indent
, "{\n");
1739 print_file(file
, indent
, "NdrFcShort(0x0),\n");
1741 set_all_tfswrite(ifaces
, TRUE
);
1742 process_tfs(file
, ifaces
, for_objects
);
1744 print_file(file
, indent
, "0x0\n");
1746 print_file(file
, indent
, "}\n");
1748 print_file(file
, indent
, "};\n");
1749 print_file(file
, indent
, "\n");
1752 static unsigned int get_required_buffer_size_type(
1753 const type_t
*type
, const char *name
, unsigned int *alignment
)
1780 case RPC_FC_ERROR_STATUS_T
:
1792 case RPC_FC_BIND_PRIMITIVE
:
1796 case RPC_FC_PSTRUCT
:
1799 if (!type
->fields
) return 0;
1800 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1802 unsigned int alignment
;
1803 size
+= get_required_buffer_size_type(field
->type
, field
->name
,
1810 if (is_base_type( type
->ref
->type
) || type
->ref
->type
== RPC_FC_STRUCT
)
1811 size
= get_required_buffer_size_type( type
->ref
, name
, alignment
);
1814 case RPC_FC_SMFARRAY
:
1815 case RPC_FC_LGFARRAY
:
1816 size
= type
->dim
* get_required_buffer_size_type(type
->ref
, name
, alignment
);
1819 case RPC_FC_SMVARRAY
:
1820 case RPC_FC_LGVARRAY
:
1821 get_required_buffer_size_type(type
->ref
, name
, alignment
);
1826 case RPC_FC_CVARRAY
:
1827 get_required_buffer_size_type(type
->ref
, name
, alignment
);
1828 size
= sizeof(void *);
1832 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name
, type
->type
);
1839 static unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
1841 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
1842 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
1844 if (!in_attr
&& !out_attr
)
1849 if (pass
== PASS_OUT
)
1851 if (out_attr
&& is_ptr(var
->type
))
1853 type_t
*type
= var
->type
;
1855 if (type
->type
== RPC_FC_STRUCT
)
1858 unsigned int size
= 36;
1860 if (!type
->fields
) return size
;
1861 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1864 size
+= get_required_buffer_size_type(
1865 field
->type
, field
->name
, &align
);
1874 if ((!out_attr
|| in_attr
) && !var
->type
->size_is
1875 && !is_attr(var
->attrs
, ATTR_STRING
) && !var
->type
->declarray
)
1877 if (is_ptr(var
->type
))
1879 type_t
*type
= var
->type
;
1881 if (is_base_type(type
->type
))
1885 else if (type
->type
== RPC_FC_STRUCT
)
1887 unsigned int size
= 36;
1890 if (!type
->fields
) return size
;
1891 LIST_FOR_EACH_ENTRY( field
, type
->fields
, const var_t
, entry
)
1894 size
+= get_required_buffer_size_type(
1895 field
->type
, field
->name
, &align
);
1902 return get_required_buffer_size_type(var
->type
, var
->name
, alignment
);
1906 static unsigned int get_function_buffer_size( const func_t
*func
, enum pass pass
)
1909 unsigned int total_size
= 0, alignment
;
1913 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
1915 total_size
+= get_required_buffer_size(var
, &alignment
, pass
);
1916 total_size
+= alignment
;
1920 if (pass
== PASS_OUT
&& !is_void(func
->def
->type
))
1922 total_size
+= get_required_buffer_size(func
->def
, &alignment
, PASS_RETURN
);
1923 total_size
+= alignment
;
1928 static void print_phase_function(FILE *file
, int indent
, const char *type
,
1929 enum remoting_phase phase
,
1930 const char *varname
, unsigned int type_offset
)
1932 const char *function
;
1935 case PHASE_BUFFERSIZE
:
1936 function
= "BufferSize";
1939 function
= "Marshall";
1941 case PHASE_UNMARSHAL
:
1942 function
= "Unmarshall";
1952 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
1954 print_file(file
, indent
, "&_StubMsg,\n");
1955 print_file(file
, indent
, "%s%s,\n",
1956 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)&" : "(unsigned char *)",
1958 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
1959 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
1960 if (phase
== PHASE_UNMARSHAL
)
1961 print_file(file
, indent
, "0);\n");
1965 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
1966 enum pass pass
, const var_t
*var
,
1967 const char *varname
)
1969 type_t
*type
= var
->type
;
1971 unsigned int alignment
= 0;
1972 unsigned char rtype
;
1974 /* no work to do for other phases, buffer sizing is done elsewhere */
1975 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
1978 rtype
= is_ptr(type
) ? type
->ref
->type
: type
->type
;
2000 case RPC_FC_ERROR_STATUS_T
:
2012 case RPC_FC_BIND_PRIMITIVE
:
2013 /* no marshalling needed */
2017 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
2021 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2022 alignment
- 1, alignment
- 1);
2024 if (phase
== PHASE_MARSHAL
)
2026 print_file(file
, indent
, "*(");
2027 write_type(file
, is_ptr(type
) ? type
->ref
: type
, FALSE
, NULL
);
2029 fprintf(file
, " *)_StubMsg.Buffer = *");
2031 fprintf(file
, " *)_StubMsg.Buffer = ");
2032 fprintf(file
, varname
);
2033 fprintf(file
, ";\n");
2035 else if (phase
== PHASE_UNMARSHAL
)
2037 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
2038 print_file(file
, indent
, "");
2040 print_file(file
, indent
, "*");
2041 fprintf(file
, varname
);
2042 if (pass
== PASS_IN
&& is_ptr(type
))
2043 fprintf(file
, " = (");
2045 fprintf(file
, " = *(");
2046 write_type(file
, is_ptr(type
) ? type
->ref
: type
, FALSE
, NULL
);
2047 fprintf(file
, " *)_StubMsg.Buffer;\n");
2050 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
2051 write_type(file
, var
->type
, FALSE
, NULL
);
2052 fprintf(file
, ");\n");
2055 /* returns whether the MaxCount, Offset or ActualCount members need to be
2056 * filled in for the specified phase */
2057 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
2059 return (phase
!= PHASE_UNMARSHAL
);
2062 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
2063 enum pass pass
, enum remoting_phase phase
)
2065 int in_attr
, out_attr
, pointer_type
;
2071 if (phase
== PHASE_BUFFERSIZE
)
2073 unsigned int size
= get_function_buffer_size( func
, pass
);
2074 print_file(file
, indent
, "_StubMsg.BufferLength = %u;\n", size
);
2077 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2079 const type_t
*type
= var
->type
;
2080 unsigned char rtype
;
2081 size_t start_offset
= type
->typestring_offset
;
2083 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
2085 pointer_type
= RPC_FC_RP
;
2087 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2088 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2089 if (!in_attr
&& !out_attr
)
2095 if (!in_attr
) continue;
2098 if (!out_attr
) continue;
2106 if (is_user_derived( var
))
2108 print_phase_function(file
, indent
, "UserMarshal", phase
, var
->name
, start_offset
);
2110 else if (is_string_type(var
->attrs
, var
->type
))
2112 if (is_array(type
) && !is_conformant_array(type
))
2113 print_phase_function(file
, indent
, "NonConformantString", phase
, var
->name
, start_offset
);
2116 if (type
->size_is
&& is_size_needed_for_phase(phase
))
2118 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2119 write_expr(file
, type
->size_is
, 1);
2120 fprintf(file
, ";\n");
2123 if ((phase
== PHASE_FREE
) || (pointer_type
== RPC_FC_UP
))
2124 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, start_offset
);
2126 print_phase_function(file
, indent
, "ConformantString", phase
, var
->name
,
2127 start_offset
+ (type
->size_is
? 4 : 2));
2130 else if (is_array(type
))
2132 unsigned char tc
= type
->type
;
2133 const char *array_type
;
2135 if (tc
== RPC_FC_SMFARRAY
|| tc
== RPC_FC_LGFARRAY
)
2136 array_type
= "FixedArray";
2137 else if (tc
== RPC_FC_SMVARRAY
|| tc
== RPC_FC_LGVARRAY
)
2139 if (is_size_needed_for_phase(phase
))
2141 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2142 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2143 write_expr(file
, type
->length_is
, 1);
2144 fprintf(file
, ";\n\n");
2146 array_type
= "VaryingArray";
2148 else if (tc
== RPC_FC_CARRAY
)
2150 if (is_size_needed_for_phase(phase
) && phase
!= PHASE_FREE
)
2152 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2153 write_expr(file
, type
->size_is
, 1);
2154 fprintf(file
, ";\n\n");
2156 array_type
= "ConformantArray";
2158 else if (tc
== RPC_FC_CVARRAY
)
2160 if (is_size_needed_for_phase(phase
))
2162 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
2163 write_expr(file
, type
->size_is
, 1);
2164 fprintf(file
, ";\n");
2165 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2166 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
2167 write_expr(file
, type
->length_is
, 1);
2168 fprintf(file
, ";\n\n");
2170 array_type
= "ConformantVaryingArray";
2173 array_type
= "ComplexArray";
2175 if (!in_attr
&& phase
== PHASE_FREE
)
2177 print_file(file
, indent
, "if (%s)\n", var
->name
);
2179 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
2181 else if (phase
!= PHASE_FREE
)
2183 if (pointer_type
== RPC_FC_UP
)
2184 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, start_offset
);
2186 print_phase_function(file
, indent
, array_type
, phase
, var
->name
, start_offset
);
2189 else if (!is_ptr(var
->type
) && is_base_type(rtype
))
2191 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2193 else if (!is_ptr(var
->type
))
2198 case RPC_FC_PSTRUCT
:
2199 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
->name
, start_offset
);
2201 case RPC_FC_CSTRUCT
:
2202 case RPC_FC_CPSTRUCT
:
2203 print_phase_function(file
, indent
, "ConformantStruct", phase
, var
->name
, start_offset
);
2205 case RPC_FC_CVSTRUCT
:
2206 print_phase_function(file
, indent
, "ConformantVaryingStruct", phase
, var
->name
, start_offset
);
2208 case RPC_FC_BOGUS_STRUCT
:
2209 print_phase_function(file
, indent
, "ComplexStruct", phase
, var
->name
, start_offset
);
2212 if (is_base_type( var
->type
->ref
->type
))
2214 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2216 else if (var
->type
->ref
->type
== RPC_FC_STRUCT
)
2218 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2219 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
->name
, start_offset
+ 4);
2224 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2225 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid
->name
);
2226 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, start_offset
);
2230 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var
->name
, rtype
);
2235 if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
2237 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
2239 else if (last_ptr(var
->type
) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
2241 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
2242 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
->name
, start_offset
+ 4);
2247 if ((iid
= get_attrp( var
->attrs
, ATTR_IIDIS
)))
2248 print_file( file
, indent
, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid
->name
);
2249 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, start_offset
);
2252 fprintf(file
, "\n");
2257 size_t get_size_procformatstring_var(const var_t
*var
)
2259 return write_procformatstring_var(NULL
, 0, var
, FALSE
);
2263 size_t get_size_procformatstring_func(const func_t
*func
)
2268 /* argument list size */
2270 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2271 size
+= get_size_procformatstring_var(var
);
2273 /* return value size */
2274 if (is_void(func
->def
->type
))
2275 size
+= 2; /* FC_END and FC_PAD */
2277 size
+= get_size_procformatstring_var(func
->def
);
2282 size_t get_size_procformatstring(const ifref_list_t
*ifaces
, int for_objects
)
2284 const ifref_t
*iface
;
2288 if (ifaces
) LIST_FOR_EACH_ENTRY( iface
, ifaces
, const ifref_t
, entry
)
2290 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
2293 if (iface
->iface
->funcs
)
2294 LIST_FOR_EACH_ENTRY( func
, iface
->iface
->funcs
, const func_t
, entry
)
2295 if (!is_local(func
->def
->attrs
))
2296 size
+= get_size_procformatstring_func( func
);
2301 size_t get_size_typeformatstring(const ifref_list_t
*ifaces
, int for_objects
)
2303 set_all_tfswrite(ifaces
, FALSE
);
2304 return process_tfs(NULL
, ifaces
, for_objects
);
2307 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
2308 const var_list_t
*fields
, const char *structvar
)
2314 fprintf(h
, "%lu", e
->u
.lval
);
2317 fprintf(h
, "0x%lx", e
->u
.lval
);
2319 case EXPR_TRUEFALSE
:
2321 fprintf(h
, "FALSE");
2325 case EXPR_IDENTIFIER
:
2328 LIST_FOR_EACH_ENTRY( field
, fields
, const var_t
, entry
)
2329 if (!strcmp(e
->u
.sval
, field
->name
))
2331 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
2335 if (&field
->entry
== fields
) error("no field found for identifier %s\n", e
->u
.sval
);
2340 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2344 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2348 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2352 write_type(h
, e
->u
.tref
, FALSE
, NULL
);
2354 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2357 fprintf(h
, "sizeof(");
2358 write_type(h
, e
->u
.tref
, FALSE
, NULL
);
2369 if (brackets
) fprintf(h
, "(");
2370 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2372 case EXPR_SHL
: fprintf(h
, " << "); break;
2373 case EXPR_SHR
: fprintf(h
, " >> "); break;
2374 case EXPR_MUL
: fprintf(h
, " * "); break;
2375 case EXPR_DIV
: fprintf(h
, " / "); break;
2376 case EXPR_ADD
: fprintf(h
, " + "); break;
2377 case EXPR_SUB
: fprintf(h
, " - "); break;
2378 case EXPR_AND
: fprintf(h
, " & "); break;
2379 case EXPR_OR
: fprintf(h
, " | "); break;
2382 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
2383 if (brackets
) fprintf(h
, ")");
2386 if (brackets
) fprintf(h
, "(");
2387 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2389 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
2391 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
2392 if (brackets
) fprintf(h
, ")");
2398 void declare_stub_args( FILE *file
, int indent
, const func_t
*func
)
2400 int in_attr
, out_attr
;
2402 const var_t
*def
= func
->def
;
2405 /* declare return value '_RetVal' */
2406 if (!is_void(def
->type
))
2408 print_file(file
, indent
, "");
2409 write_type_left(file
, def
->type
);
2410 fprintf(file
, " _RetVal;\n");
2416 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2418 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
2420 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2421 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2422 if (!out_attr
&& !in_attr
)
2425 if (!in_attr
&& !var
->type
->size_is
&& !is_string
)
2427 print_file(file
, indent
, "");
2428 write_type(file
, var
->type
->ref
, FALSE
, "_W%u", i
++);
2429 fprintf(file
, ";\n");
2432 print_file(file
, indent
, "");
2433 write_type_left(file
, var
->type
);
2435 if (var
->type
->declarray
) {
2436 fprintf(file
, "( *");
2437 write_name(file
, var
);
2438 fprintf(file
, " )");
2440 write_name(file
, var
);
2441 write_type_right(file
, var
->type
, FALSE
);
2442 fprintf(file
, ";\n");
2447 void assign_stub_out_args( FILE *file
, int indent
, const func_t
*func
)
2449 int in_attr
, out_attr
;
2456 LIST_FOR_EACH_ENTRY( var
, func
->args
, const var_t
, entry
)
2458 int is_string
= is_attr(var
->attrs
, ATTR_STRING
);
2459 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
2460 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
2461 if (!out_attr
&& !in_attr
)
2466 print_file(file
, indent
, "");
2467 write_name(file
, var
);
2469 if (var
->type
->size_is
)
2471 unsigned int size
, align
= 0;
2472 type_t
*type
= var
->type
;
2474 fprintf(file
, " = NdrAllocate(&_StubMsg, ");
2475 for ( ; type
->size_is
; type
= type
->ref
)
2477 write_expr(file
, type
->size_is
, TRUE
);
2478 fprintf(file
, " * ");
2480 size
= type_memsize(type
, &align
);
2481 fprintf(file
, "%u);\n", size
);
2483 else if (!is_string
)
2485 fprintf(file
, " = &_W%u;\n", i
);
2486 if (is_ptr(var
->type
) && !last_ptr(var
->type
))
2487 print_file(file
, indent
, "_W%u = 0;\n", i
);
2495 fprintf(file
, "\n");
2499 int write_expr_eval_routines(FILE *file
, const char *iface
)
2502 struct expr_eval_routine
*eval
;
2503 unsigned short callback_offset
= 0;
2505 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
2509 print_file(file
, indent
, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2510 iface
, eval
->structure
->name
, callback_offset
);
2511 print_file(file
, indent
, "{\n");
2513 print_file(file
, indent
, "struct %s *" STRUCT_EXPR_EVAL_VAR
" = (struct %s *)(pStubMsg->StackTop - %u);\n",
2514 eval
->structure
->name
, eval
->structure
->name
, eval
->structure_size
);
2515 fprintf(file
, "\n");
2516 print_file(file
, indent
, "pStubMsg->Offset = 0;\n"); /* FIXME */
2517 print_file(file
, indent
, "pStubMsg->MaxCount = (unsigned long)");
2518 write_struct_expr(file
, eval
->expr
, 1, eval
->structure
->fields
, STRUCT_EXPR_EVAL_VAR
);
2519 fprintf(file
, ";\n");
2521 print_file(file
, indent
, "}\n\n");
2527 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
2529 struct expr_eval_routine
*eval
;
2530 struct expr_eval_routine
*cursor
;
2531 unsigned short callback_offset
= 0;
2533 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2534 fprintf(file
, "{\n");
2536 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
2538 print_file(file
, 1, "%s_%sExprEval_%04u,\n",
2539 iface
, eval
->structure
->name
, callback_offset
);
2542 list_remove(&eval
->entry
);
2546 fprintf(file
, "};\n\n");
2550 void write_endpoints( FILE *f
, const char *prefix
, const str_list_t
*list
)
2552 const struct str_list_entry_t
*endpoint
;
2555 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
2556 print_file( f
, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix
);
2557 LIST_FOR_EACH_ENTRY( endpoint
, list
, const struct str_list_entry_t
, entry
)
2559 print_file( f
, 1, "{ (const unsigned char *)\"" );
2560 for (p
= endpoint
->str
; *p
&& *p
!= ':'; p
++)
2562 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
2565 if (!*p
) goto error
;
2566 if (p
[1] != '[') goto error
;
2568 fprintf( f
, "\", (const unsigned char *)\"" );
2569 for (p
+= 2; *p
&& *p
!= ']'; p
++)
2571 if (*p
== '"' || *p
== '\\') fputc( '\\', f
);
2574 if (*p
!= ']') goto error
;
2575 fprintf( f
, "\" },\n" );
2577 print_file( f
, 0, "};\n\n" );
2581 error("Invalid endpoint syntax '%s'\n", endpoint
->str
);