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 type_memsize(const type_t
*t
, int ptr_level
, const expr_t
*array
);
63 static size_t fields_memsize(const var_t
*v
);
65 static int compare_expr(const expr_t
*a
, const expr_t
*b
)
69 if (a
->type
!= b
->type
)
70 return a
->type
- b
->type
;
77 return a
->u
.lval
- b
->u
.lval
;
79 return strcmp(a
->u
.sval
, b
->u
.sval
);
81 ret
= compare_expr(a
->ref
, b
->ref
);
84 ret
= compare_expr(a
->u
.ext
, b
->u
.ext
);
87 return compare_expr(a
->ext2
, b
->ext2
);
96 ret
= compare_expr(a
->ref
, b
->ref
);
99 return compare_expr(a
->u
.ext
, b
->u
.ext
);
105 return compare_expr(a
->ref
, b
->ref
);
112 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
115 fprintf(file, "/* %2u */\n", typestring_offset); \
116 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
120 static int print_file(FILE *file
, int indent
, const char *format
, ...)
127 va_start(va
, format
);
128 for (i
= 0; i
< indent
; i
++)
130 r
= vfprintf(file
, format
, va
);
135 static void write_formatdesc(FILE *f
, int indent
, const char *str
)
137 print_file(f
, indent
, "typedef struct _MIDL_%s_FORMAT_STRING\n", str
);
138 print_file(f
, indent
, "{\n");
139 print_file(f
, indent
+ 1, "short Pad;\n");
140 print_file(f
, indent
+ 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str
);
141 print_file(f
, indent
, "} MIDL_%s_FORMAT_STRING;\n", str
);
142 print_file(f
, indent
, "\n");
145 void write_formatstringsdecl(FILE *f
, int indent
, ifref_t
*ifaces
, int for_objects
)
147 print_file(f
, indent
, "#define TYPE_FORMAT_STRING_SIZE %d\n",
148 get_size_typeformatstring(ifaces
, for_objects
));
150 print_file(f
, indent
, "#define PROC_FORMAT_STRING_SIZE %d\n",
151 get_size_procformatstring(ifaces
, for_objects
));
154 write_formatdesc(f
, indent
, "TYPE");
155 write_formatdesc(f
, indent
, "PROC");
157 print_file(f
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
158 print_file(f
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
159 print_file(f
, indent
, "\n");
162 static inline int is_base_type(unsigned char type
)
181 case RPC_FC_ERROR_STATUS_T
:
182 case RPC_FC_BIND_PRIMITIVE
:
190 static size_t write_procformatstring_var(FILE *file
, int indent
,
191 const var_t
*var
, int is_return
, unsigned int *type_offset
)
194 int ptr_level
= var
->ptr_level
;
195 const type_t
*type
= var
->type
;
197 int is_in
= is_attr(var
->attrs
, ATTR_IN
);
198 int is_out
= is_attr(var
->attrs
, ATTR_OUT
);
200 if (!is_in
&& !is_out
) is_in
= TRUE
;
202 if (ptr_level
== 0 && !var
->array
&& is_base_type(type
->type
))
205 print_file(file
, indent
, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
207 print_file(file
, indent
, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
211 #define CASE_BASETYPE(fctype) \
213 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
214 size = 2; /* includes param type prefix */ \
217 CASE_BASETYPE(FC_BYTE
);
218 CASE_BASETYPE(FC_CHAR
);
219 CASE_BASETYPE(FC_WCHAR
);
220 CASE_BASETYPE(FC_USHORT
);
221 CASE_BASETYPE(FC_SHORT
);
222 CASE_BASETYPE(FC_ULONG
);
223 CASE_BASETYPE(FC_LONG
);
224 CASE_BASETYPE(FC_HYPER
);
225 CASE_BASETYPE(FC_IGNORE
);
226 CASE_BASETYPE(FC_USMALL
);
227 CASE_BASETYPE(FC_SMALL
);
228 CASE_BASETYPE(FC_FLOAT
);
229 CASE_BASETYPE(FC_DOUBLE
);
230 CASE_BASETYPE(FC_ERROR_STATUS_T
);
233 case RPC_FC_BIND_PRIMITIVE
:
234 print_file(file
, indent
, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE
);
235 size
= 2; /* includes param type prefix */
239 error("Unknown/unsupported type: %s (0x%02x)\n", var
->name
, type
->type
);
246 print_file(file
, indent
, "0x52, /* FC_RETURN_PARAM */\n");
247 else if (is_in
&& is_out
)
248 print_file(file
, indent
, "0x50, /* FC_IN_OUT_PARAM */\n");
250 print_file(file
, indent
, "0x51, /* FC_OUT_PARAM */\n");
252 print_file(file
, indent
, "0x4d, /* FC_IN_PARAM */\n");
254 print_file(file
, indent
, "0x01,\n");
255 print_file(file
, indent
, "NdrFcShort(0x%x),\n", *type_offset
);
256 size
= 4; /* includes param type prefix */
258 *type_offset
+= get_size_typeformatstring_var(var
);
262 void write_procformatstring(FILE *file
, const ifref_t
*ifaces
, int for_objects
)
264 const ifref_t
*iface
= ifaces
;
267 unsigned int type_offset
= 2;
269 print_file(file
, indent
, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
270 print_file(file
, indent
, "{\n");
272 print_file(file
, indent
, "0,\n");
273 print_file(file
, indent
, "{\n");
278 for (; iface
; iface
= PREV_LINK(iface
))
280 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
283 if (iface
->iface
->funcs
)
285 func_t
*func
= iface
->iface
->funcs
;
286 while (NEXT_LINK(func
)) func
= NEXT_LINK(func
);
287 for (; func
; func
= PREV_LINK(func
))
289 /* emit argument data */
293 while (NEXT_LINK(var
)) var
= NEXT_LINK(var
);
296 write_procformatstring_var(file
, indent
, var
, FALSE
,
299 var
= PREV_LINK(var
);
303 /* emit return value data */
305 if (is_void(var
->type
, NULL
))
307 print_file(file
, indent
, "0x5b, /* FC_END */\n");
308 print_file(file
, indent
, "0x5c, /* FC_PAD */\n");
311 write_procformatstring_var(file
, indent
, var
, TRUE
,
317 print_file(file
, indent
, "0x0\n");
319 print_file(file
, indent
, "}\n");
321 print_file(file
, indent
, "};\n");
322 print_file(file
, indent
, "\n");
325 /* write conformance / variance descriptor */
326 static size_t write_conf_or_var_desc(FILE *file
, const func_t
*func
, const type_t
*structure
, const expr_t
*expr
)
328 unsigned char operator_type
= 0;
329 const char *operator_string
= "no operators";
330 const expr_t
*subexpr
= expr
;
331 unsigned char correlation_type
;
333 if (!file
) return 4; /* optimisation for sizing pass */
337 if (expr
->cval
> UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
)
338 error("write_conf_or_var_desc: constant value %ld is greater than "
339 "the maximum constant size of %d\n", expr
->cval
,
340 UCHAR_MAX
* (USHRT_MAX
+ 1) + USHRT_MAX
);
342 print_file(file
, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
343 RPC_FC_CONSTANT_CONFORMANCE
, expr
->cval
);
344 print_file(file
, 2, "0x%x,\n", expr
->cval
& ~USHRT_MAX
);
345 print_file(file
, 2, "NdrFcShort(0x%x),\n", expr
->cval
& USHRT_MAX
);
350 switch (subexpr
->type
)
353 subexpr
= subexpr
->ref
;
354 operator_type
= RPC_FC_DEREFERENCE
;
355 operator_string
= "FC_DEREFERENCE";
358 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
360 subexpr
= subexpr
->ref
;
361 operator_type
= RPC_FC_DIV_2
;
362 operator_string
= "FC_DIV_2";
366 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 2))
368 subexpr
= subexpr
->ref
;
369 operator_type
= RPC_FC_MULT_2
;
370 operator_string
= "FC_MULT_2";
374 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
376 subexpr
= subexpr
->ref
;
377 operator_type
= RPC_FC_SUB_1
;
378 operator_string
= "FC_SUB_1";
382 if (subexpr
->u
.ext
->is_const
&& (subexpr
->u
.ext
->cval
== 1))
384 subexpr
= subexpr
->ref
;
385 operator_type
= RPC_FC_ADD_1
;
386 operator_string
= "FC_ADD_1";
393 if (subexpr
->type
== EXPR_IDENTIFIER
)
395 const type_t
*correlation_variable
= NULL
;
396 unsigned char correlation_variable_type
;
397 unsigned char param_type
= 0;
398 const char *param_type_string
= NULL
;
405 for (offset
= 0, var
= structure
->fields
; var
; var
= NEXT_LINK(var
))
407 offset
-= type_memsize(var
->type
, var
->ptr_level
, var
->array
);
408 if (!strcmp(var
->name
, subexpr
->u
.sval
))
410 correlation_variable
= var
->type
;
414 if (!correlation_variable
)
415 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
418 correlation_type
= RPC_FC_NORMAL_CONFORMANCE
;
422 const var_t
*var
= func
->args
;
424 while (NEXT_LINK(var
)) var
= NEXT_LINK(var
);
425 /* FIXME: not all stack variables are sizeof(void *) */
426 for (offset
= 0; var
; offset
+= sizeof(void *), var
= PREV_LINK(var
))
428 if (!strcmp(var
->name
, subexpr
->u
.sval
))
430 correlation_variable
= var
->type
;
434 if (!correlation_variable
)
435 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
438 correlation_type
= RPC_FC_TOP_LEVEL_CONFORMANCE
;
441 correlation_variable_type
= correlation_variable
->type
;
443 switch (correlation_variable_type
)
447 param_type
= RPC_FC_SMALL
;
448 param_type_string
= "FC_SMALL";
452 param_type
= RPC_FC_USMALL
;
453 param_type_string
= "FC_USMALL";
457 param_type
= RPC_FC_SHORT
;
458 param_type_string
= "FC_SHORT";
461 param_type
= RPC_FC_USHORT
;
462 param_type_string
= "FC_USHORT";
465 param_type
= RPC_FC_LONG
;
466 param_type_string
= "FC_LONG";
469 param_type
= RPC_FC_ULONG
;
470 param_type_string
= "FC_ULONG";
473 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
474 correlation_variable_type
);
477 print_file(file
, 2, "0x%x, /* Corr desc: %s%s */\n",
478 correlation_type
| param_type
,
479 correlation_type
== RPC_FC_TOP_LEVEL_CONFORMANCE
? "parameter, " : "",
481 print_file(file
, 2, "0x%x, /* %s */\n", operator_type
, operator_string
);
482 print_file(file
, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
484 correlation_type
== RPC_FC_TOP_LEVEL_CONFORMANCE
? "x86 stack size / " : "",
489 unsigned int callback_offset
= 0;
493 struct expr_eval_routine
*eval
;
496 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
498 if (!strcmp(eval
->structure
->name
, structure
->name
) &&
499 !compare_expr(eval
->expr
, expr
))
509 eval
= xmalloc(sizeof(*eval
));
510 eval
->structure
= structure
;
511 eval
->structure_size
= fields_memsize(structure
->fields
);
513 list_add_tail(&expr_eval_routines
, &eval
->entry
);
516 correlation_type
= RPC_FC_NORMAL_CONFORMANCE
;
520 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
521 correlation_type
= RPC_FC_TOP_LEVEL_CONFORMANCE
;
524 if (callback_offset
> USHRT_MAX
)
525 error("Maximum number of callback routines reached\n");
527 print_file(file
, 2, "0x%x, /* Corr desc: %s */\n",
529 correlation_type
== RPC_FC_TOP_LEVEL_CONFORMANCE
? "parameter" : "");
530 print_file(file
, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK
, "FC_CALLBACK");
531 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset
, callback_offset
);
536 static size_t fields_memsize(const var_t
*v
)
539 const var_t
*first
= v
;
541 while (NEXT_LINK(v
)) v
= NEXT_LINK(v
);
543 size
+= type_memsize(v
->type
, v
->ptr_level
, v
->array
);
544 if (v
== first
) break;
550 static size_t type_memsize(const type_t
*t
, int ptr_level
, const expr_t
*array
)
555 return sizeof(void *);
573 case RPC_FC_ERROR_STATUS_T
:
583 case RPC_FC_CVSTRUCT
:
584 case RPC_FC_CPSTRUCT
:
587 case RPC_FC_BOGUS_STRUCT
:
588 case RPC_FC_ENCAPSULATED_UNION
:
589 case RPC_FC_NON_ENCAPSULATED_UNION
:
590 size
= fields_memsize(t
->fields
);
593 error("type_memsize: Unknown type %d\n", t
->type
);
608 size_t get_type_memsize(const type_t
*type
)
610 return type_memsize(type
, 0, NULL
);
613 static int write_pointers(FILE *file
, const attr_t
*attrs
,
614 const type_t
*type
, int ptr_level
,
615 const expr_t
*array
, int level
,
616 unsigned int *typestring_offset
)
618 int pointers_written
= 0;
621 /* don't generate a pointer for first-level arrays since we want to
622 * descend into them to write their pointers, not stop here */
623 if ((level
== 0 || ptr_level
== 0) && is_array_type(attrs
, ptr_level
, array
))
625 return write_pointers(file
, NULL
, type
, 0, NULL
, level
+ 1, typestring_offset
);
630 /* FIXME: only general algorithm implemented, not the actual writing */
631 error("write_pointers: Writing type format string for pointer is unimplemented\n");
637 /* note: don't descend into complex structures or unions since these
638 * will always be generated as a separate type */
640 case RPC_FC_CVSTRUCT
:
641 case RPC_FC_CPSTRUCT
:
646 while (NEXT_LINK(v
)) v
= NEXT_LINK(v
);
647 for (; v
; v
= PREV_LINK(v
))
648 pointers_written
+= write_pointers(file
, v
->attrs
, v
->type
,
649 v
->ptr_level
, v
->array
,
660 return pointers_written
;
663 static size_t write_pointer_description(FILE *file
, const attr_t
*attrs
,
664 const type_t
*type
, int ptr_level
,
665 const expr_t
*array
, int level
,
666 size_t typestring_offset
)
671 /* don't generate a pointer for first-level arrays since we want to
672 * descend into them to write their pointers, not stop here */
673 if ((level
== 0 || ptr_level
== 0) && is_array_type(attrs
, ptr_level
, array
))
675 return write_pointer_description(file
, NULL
, type
, 0, NULL
,
676 level
+ 1, typestring_offset
);
681 /* FIXME: only general algorithm implemented, not the actual writing */
682 error("write_pointer_description: Writing pointer description is unimplemented\n");
686 /* FIXME: search through all refs for pointers too */
690 /* note: don't descend into complex structures or unions since these
691 * will always be generated as a separate type */
693 case RPC_FC_CVSTRUCT
:
694 case RPC_FC_CPSTRUCT
:
699 while (NEXT_LINK(v
)) v
= NEXT_LINK(v
);
700 for (; v
; v
= PREV_LINK(v
))
701 size
+= write_pointer_description(file
, v
->attrs
, v
->type
,
702 v
->ptr_level
, v
->array
,
716 static size_t write_string_tfs(FILE *file
, const attr_t
*attrs
,
717 const type_t
*type
, const expr_t
*array
,
718 const char *name
, unsigned int *typestring_offset
)
720 const expr_t
*size_is
= get_attrp(attrs
, ATTR_SIZEIS
);
721 int has_size
= size_is
&& (size_is
->type
!= EXPR_VOID
);
722 size_t start_offset
= *typestring_offset
;
723 unsigned char flags
= 0;
729 pointer_type
= type
->type
;
733 pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
736 pointer_type
= RPC_FC_RP
;
738 if (!get_attrp(attrs
, ATTR_SIZEIS
))
739 flags
|= RPC_FC_P_SIMPLEPOINTER
;
743 if ((rtype
!= RPC_FC_BYTE
) && (rtype
!= RPC_FC_CHAR
) && (rtype
!= RPC_FC_WCHAR
))
745 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype
, name
);
749 print_file(file
, 2,"0x%x, 0x%x, /* %s%s */\n",
751 pointer_type
== RPC_FC_FP
? "FC_FP" : (pointer_type
== RPC_FC_UP
? "FC_UP" : "FC_RP"),
752 (flags
& RPC_FC_P_SIMPLEPOINTER
) ? " [simple_pointer]" : "");
753 *typestring_offset
+= 2;
755 if (!(flags
& RPC_FC_P_SIMPLEPOINTER
))
757 print_file(file
, 2, "NdrFcShort(0x2),\n");
758 *typestring_offset
+= 2;
761 if (array
&& array
->is_const
)
763 if (array
->cval
> USHRT_MAX
)
764 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
765 name
, USHRT_MAX
, array
->cval
- USHRT_MAX
);
767 if (rtype
== RPC_FC_CHAR
)
768 WRITE_FCTYPE(file
, FC_CSTRING
, *typestring_offset
);
770 WRITE_FCTYPE(file
, FC_WSTRING
, *typestring_offset
);
771 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
772 *typestring_offset
+= 2;
774 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", array
->cval
, array
->cval
);
775 *typestring_offset
+= 2;
781 if (rtype
== RPC_FC_CHAR
)
782 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
784 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
785 print_file(file
, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED
);
786 *typestring_offset
+= 2;
788 *typestring_offset
+= write_conf_or_var_desc(file
, current_func
, NULL
, size_is
);
794 if (rtype
== RPC_FC_CHAR
)
795 WRITE_FCTYPE(file
, FC_C_CSTRING
, *typestring_offset
);
797 WRITE_FCTYPE(file
, FC_C_WSTRING
, *typestring_offset
);
798 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
799 *typestring_offset
+= 2;
805 static size_t write_array_tfs(FILE *file
, const attr_t
*attrs
,
806 const type_t
*type
, const expr_t
*array
,
807 const char *name
, unsigned int *typestring_offset
)
809 const expr_t
*length_is
= get_attrp(attrs
, ATTR_LENGTHIS
);
810 const expr_t
*size_is
= get_attrp(attrs
, ATTR_SIZEIS
);
811 int has_length
= length_is
&& (length_is
->type
!= EXPR_VOID
);
812 int has_size
= (size_is
&& (size_is
->type
!= EXPR_VOID
)) || !array
->is_const
;
814 int pointer_type
= get_attrv(attrs
, ATTR_POINTERTYPE
);
816 pointer_type
= RPC_FC_RP
;
818 print_file(file
, 2, "0x%x, 0x00, /* %s */\n",
820 pointer_type
== RPC_FC_FP
? "FC_FP" : (pointer_type
== RPC_FC_UP
? "FC_UP" : "FC_RP"));
821 print_file(file
, 2, "NdrFcShort(0x2),\n");
822 *typestring_offset
+= 4;
824 if (array
&& NEXT_LINK(array
)) /* multi-dimensional array */
826 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name
);
831 size_t pointer_start_offset
= *typestring_offset
;
834 if (write_pointers(file
, attrs
, type
, 0, array
, 0, typestring_offset
) > 0)
837 start_offset
= *typestring_offset
;
839 if (!has_length
&& !has_size
)
842 size_t size
= type_memsize(type
, 0, array
);
843 if (size
< USHRT_MAX
)
845 WRITE_FCTYPE(file
, FC_SMFARRAY
, *typestring_offset
);
847 print_file(file
, 2, "0x%x, /* 0 */\n", 0);
849 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", size
, size
);
850 *typestring_offset
+= 4;
854 WRITE_FCTYPE(file
, FC_LGFARRAY
, *typestring_offset
);
856 print_file(file
, 2, "0x%x, /* 0 */\n", 0);
858 print_file(file
, 2, "NdrFcLong(0x%x), /* %d */\n", size
, size
);
859 *typestring_offset
+= 6;
864 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
865 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
866 *typestring_offset
+= 2;
867 *typestring_offset
= write_pointer_description(file
, attrs
,
868 type
, 0, array
, 0, pointer_start_offset
);
869 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
870 *typestring_offset
+= 1;
873 print_file(file
, 2, "0x0, /* FIXME: write out conversion data */\n");
874 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
875 *typestring_offset
+= 2;
879 else if (has_length
&& !has_size
)
882 size_t element_size
= type_memsize(type
, 0, NULL
);
883 size_t elements
= array
->cval
;
884 size_t total_size
= element_size
* elements
;
886 if (total_size
< USHRT_MAX
)
888 WRITE_FCTYPE(file
, FC_SMVARRAY
, *typestring_offset
);
890 print_file(file
, 2, "0x%x, /* 0 */\n", 0);
892 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", total_size
, total_size
);
893 /* number of elements */
894 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", elements
, elements
);
895 *typestring_offset
+= 6;
899 WRITE_FCTYPE(file
, FC_LGVARRAY
, *typestring_offset
);
901 print_file(file
, 2, "0x%x, /* 0 */\n", 0);
903 print_file(file
, 2, "NdrFcLong(0x%x), /* %d */\n", total_size
, total_size
);
904 /* number of elements */
905 print_file(file
, 2, "NdrFcLong(0x%x), /* %d */\n", elements
, elements
);
906 *typestring_offset
+= 10;
909 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", element_size
, element_size
);
910 *typestring_offset
+= 2;
912 *typestring_offset
+= write_conf_or_var_desc(file
, current_func
,
918 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
919 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
920 *typestring_offset
+= 2;
921 *typestring_offset
+= write_pointer_description(file
, attrs
,
922 type
, 0, array
, 0, pointer_start_offset
);
923 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
924 *typestring_offset
+= 1;
927 print_file(file
, 2, "0x0, /* FIXME: write out conversion data */\n");
928 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
929 *typestring_offset
+= 2;
933 else if (!has_length
&& has_size
)
935 /* conformant array */
936 size_t element_size
= type_memsize(type
, 0, NULL
);
938 WRITE_FCTYPE(file
, FC_CARRAY
, *typestring_offset
);
940 print_file(file
, 2, "0x%x, /* 0 */\n", 0);
942 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", element_size
, element_size
);
943 *typestring_offset
+= 4;
945 *typestring_offset
+= write_conf_or_var_desc(file
, current_func
,
947 size_is
? size_is
: array
);
951 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
952 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
953 *typestring_offset
+= 2;
954 *typestring_offset
+= write_pointer_description(file
, attrs
,
955 type
, 0, array
, 0, pointer_start_offset
);
956 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
957 *typestring_offset
+= 1;
960 print_file(file
, 2, "0x%x, /* FIXME: write out conversion data */\n", type
->type
);
961 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
962 *typestring_offset
+= 2;
968 /* conformant varying array */
969 size_t element_size
= type_memsize(type
, 0, NULL
);
971 WRITE_FCTYPE(file
, FC_CVARRAY
, *typestring_offset
);
973 print_file(file
, 2, "0x%x, /* 0 */\n", 0);
975 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", element_size
, element_size
);
976 *typestring_offset
+= 4;
978 *typestring_offset
+= write_conf_or_var_desc(file
, current_func
,
980 size_is
? size_is
: array
);
981 *typestring_offset
+= write_conf_or_var_desc(file
, current_func
,
987 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
988 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
989 *typestring_offset
+= 2;
990 *typestring_offset
+= write_pointer_description(file
, attrs
,
991 type
, 0, array
, 0, pointer_start_offset
);
992 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
993 *typestring_offset
+= 1;
996 print_file(file
, 2, "0x0, /* FIXME: write out conversion data */\n");
997 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
998 *typestring_offset
+= 2;
1000 return start_offset
;
1005 static const var_t
*find_array_or_string_in_struct(const type_t
*type
)
1007 /* last field is the first in the fields linked list */
1008 const var_t
*last_field
= type
->fields
;
1009 if (is_array_type(last_field
->attrs
, last_field
->ptr_level
, last_field
->array
))
1012 assert((last_field
->type
->type
== RPC_FC_CSTRUCT
) ||
1013 (last_field
->type
->type
== RPC_FC_CPSTRUCT
) ||
1014 (last_field
->type
->type
== RPC_FC_CVSTRUCT
));
1016 return find_array_or_string_in_struct(last_field
->type
);
1019 static size_t write_struct_members(FILE *file
, const type_t
*type
)
1021 size_t typestring_size
= 0;
1024 field
= type
->fields
;
1025 while (NEXT_LINK(field
)) field
= NEXT_LINK(field
);
1026 for (; field
; field
= PREV_LINK(field
))
1028 unsigned char rtype
= field
->type
->type
;
1030 if (is_base_type(rtype
))
1034 #define CASE_BASETYPE(fctype) \
1035 case RPC_##fctype: \
1036 print_file(file, 2, "0x%02x,\t\t/* " #fctype " */\n", RPC_##fctype); \
1037 typestring_size++; \
1039 CASE_BASETYPE(FC_BYTE
);
1040 CASE_BASETYPE(FC_CHAR
);
1041 CASE_BASETYPE(FC_SMALL
);
1042 CASE_BASETYPE(FC_USMALL
);
1043 CASE_BASETYPE(FC_WCHAR
);
1044 CASE_BASETYPE(FC_SHORT
);
1045 CASE_BASETYPE(FC_USHORT
);
1046 CASE_BASETYPE(FC_LONG
);
1047 CASE_BASETYPE(FC_ULONG
);
1048 CASE_BASETYPE(FC_FLOAT
);
1049 CASE_BASETYPE(FC_HYPER
);
1050 CASE_BASETYPE(FC_DOUBLE
);
1051 CASE_BASETYPE(FC_ENUM16
);
1052 CASE_BASETYPE(FC_ENUM32
);
1053 CASE_BASETYPE(FC_IGNORE
);
1054 CASE_BASETYPE(FC_ERROR_STATUS_T
);
1057 #undef CASE_BASETYPE
1061 error("Unsupported member type 0x%x\n", rtype
);
1064 if (typestring_size
% 1)
1066 print_file(file
, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD
);
1070 print_file(file
, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END
);
1073 return typestring_size
;
1076 static size_t write_struct_tfs(FILE *file
, const type_t
*type
,
1077 const char *name
, unsigned int *typestring_offset
)
1079 unsigned int total_size
;
1081 size_t start_offset
;
1082 size_t array_offset
;
1083 size_t pointer_offset
;
1088 case RPC_FC_PSTRUCT
:
1089 total_size
= type_memsize(type
, 0, NULL
);
1091 if (total_size
> USHRT_MAX
)
1092 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1093 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1095 if (type
->type
== RPC_FC_PSTRUCT
)
1097 pointer_offset
= *typestring_offset
;
1098 write_pointers(file
, NULL
, type
, 0, NULL
, 0, typestring_offset
);
1100 else pointer_offset
= 0; /* silence warning */
1102 start_offset
= *typestring_offset
;
1103 if (type
->type
== RPC_FC_STRUCT
)
1104 WRITE_FCTYPE(file
, FC_STRUCT
, *typestring_offset
);
1106 WRITE_FCTYPE(file
, FC_PSTRUCT
, *typestring_offset
);
1108 print_file(file
, 2, "0x3,\n"); /* FIXME */
1110 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", total_size
, total_size
);
1111 *typestring_offset
+= 4;
1113 if (type
->type
== RPC_FC_PSTRUCT
)
1115 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1116 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1117 *typestring_offset
+= 2;
1118 *typestring_offset
+= write_pointer_description(file
, NULL
,
1119 type
, 0, NULL
, 0, pointer_offset
);
1120 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1121 *typestring_offset
+= 1;
1125 *typestring_offset
+= write_struct_members(file
, type
);
1126 return start_offset
;
1127 case RPC_FC_CSTRUCT
:
1128 case RPC_FC_CPSTRUCT
:
1129 total_size
= type_memsize(type
, 0, NULL
);
1131 if (total_size
> USHRT_MAX
)
1132 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1133 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1135 array
= find_array_or_string_in_struct(type
);
1136 current_structure
= type
;
1137 array_offset
= write_array_tfs(file
, array
->attrs
, array
->type
,
1138 array
->array
, array
->name
,
1140 current_structure
= NULL
;
1142 if (type
->type
== RPC_FC_CPSTRUCT
)
1144 pointer_offset
= *typestring_offset
;
1145 write_pointers(file
, NULL
, type
, 0, NULL
, 0, typestring_offset
);
1147 else pointer_offset
= 0; /* silence warning */
1149 start_offset
= *typestring_offset
;
1150 if (type
->type
== RPC_FC_CSTRUCT
)
1151 WRITE_FCTYPE(file
, FC_CSTRUCT
, *typestring_offset
);
1153 WRITE_FCTYPE(file
, FC_CPSTRUCT
, *typestring_offset
);
1155 print_file(file
, 2, "0x0,\n");
1157 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", total_size
, total_size
);
1158 *typestring_offset
+= 4;
1159 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1160 array_offset
- *typestring_offset
,
1161 array_offset
- *typestring_offset
,
1163 *typestring_offset
+= 2;
1165 if (type
->type
== RPC_FC_CPSTRUCT
)
1167 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1168 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1169 *typestring_offset
+= 2;
1170 *typestring_offset
+= write_pointer_description(file
, NULL
,
1171 type
, 0, NULL
, 0, pointer_offset
);
1172 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1173 *typestring_offset
+= 1;
1176 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1177 *typestring_offset
+= 1;
1179 return start_offset
;
1180 case RPC_FC_CVSTRUCT
:
1181 total_size
= type_memsize(type
, 0, NULL
);
1183 if (total_size
> USHRT_MAX
)
1184 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1185 name
, USHRT_MAX
, total_size
- USHRT_MAX
);
1187 array
= find_array_or_string_in_struct(type
);
1188 current_structure
= type
;
1189 if (is_attr(array
->attrs
, ATTR_STRING
))
1190 array_offset
= write_string_tfs(file
, array
->attrs
, array
->type
,
1191 array
->array
, array
->name
,
1194 array_offset
= write_array_tfs(file
, array
->attrs
, array
->type
,
1195 array
->array
, array
->name
,
1197 current_structure
= NULL
;
1199 pointer_offset
= *typestring_offset
;
1200 if (!write_pointers(file
, NULL
, type
, 0, NULL
, 0, typestring_offset
))
1203 start_offset
= *typestring_offset
;
1204 WRITE_FCTYPE(file
, FC_CVSTRUCT
, *typestring_offset
);
1206 print_file(file
, 2, "0x0,\n");
1208 print_file(file
, 2, "NdrFcShort(0x%x), /* %u */\n", total_size
, total_size
);
1209 *typestring_offset
+= 4;
1210 print_file(file
, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1211 array_offset
- *typestring_offset
,
1212 array_offset
- *typestring_offset
,
1214 *typestring_offset
+= 2;
1216 if (pointer_offset
!= 0)
1218 print_file(file
, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP
);
1219 print_file(file
, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD
);
1220 *typestring_offset
+= 2;
1221 *typestring_offset
+= write_pointer_description(file
, NULL
,
1222 type
, 0, NULL
, 0, pointer_offset
);
1223 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1224 *typestring_offset
+= 1;
1227 print_file(file
, 2, "0x%x, /* FC_END */\n", RPC_FC_END
);
1228 *typestring_offset
+= 1;
1230 return start_offset
;
1232 error("write_struct_tfs: Unimplemented for type 0x%x\n", type
->type
);
1233 return *typestring_offset
;
1237 static void write_pointer_only_tfs(FILE *file
, const attr_t
*attrs
, int pointer_type
,
1238 unsigned char flags
, size_t offset
,
1239 unsigned int *typeformat_offset
)
1241 int in_attr
, out_attr
;
1242 in_attr
= is_attr(attrs
, ATTR_IN
);
1243 out_attr
= is_attr(attrs
, ATTR_OUT
);
1244 if (!in_attr
&& !out_attr
) in_attr
= 1;
1246 if (out_attr
&& !in_attr
&& pointer_type
== RPC_FC_RP
)
1249 print_file(file
, 2, "0x%x, 0x%x,\t\t/* %s",
1252 pointer_type
== RPC_FC_FP
? "FC_FP" : (pointer_type
== RPC_FC_UP
? "FC_UP" : "FC_RP"));
1256 fprintf(file
, " [allocated_on_stack]");
1258 fprintf(file
, " [pointer_deref]");
1259 fprintf(file
, " */\n");
1262 print_file(file
, 2, "NdrFcShort(0x%x), /* %d */\n", offset
, offset
);
1263 *typeformat_offset
+= 4;
1266 static size_t write_union_tfs(FILE *file
, const attr_t
*attrs
,
1267 const type_t
*type
, const char *name
,
1268 unsigned int *typeformat_offset
)
1270 error("write_union_tfs: Unimplemented\n");
1271 return *typeformat_offset
;
1274 static size_t write_ip_tfs(FILE *file
, const attr_t
*attrs
,
1275 const char *name
, unsigned int *typeformat_offset
)
1278 size_t start_offset
= *typeformat_offset
;
1279 const UUID
*uuid
= get_attrp(attrs
, ATTR_UUID
);
1282 error("%s: interface %s missing UUID\n", __FUNCTION__
, name
);
1284 print_file(file
, 2, "0x2f,\t/* FC_IP */\n");
1285 print_file(file
, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1286 print_file(file
, 2, "NdrFcLong(0x%08lx),\n", uuid
->Data1
);
1287 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data2
);
1288 print_file(file
, 2, "NdrFcShort(0x%04x),\n", uuid
->Data3
);
1289 for (i
= 0; i
< 8; ++i
)
1290 print_file(file
, 2, "0x%02x,\n", uuid
->Data4
[i
]);
1293 fprintf(file
, "\n");
1295 *typeformat_offset
+= 18;
1296 return start_offset
;
1299 static int get_ptr_attr(const type_t
*t
, int def_type
)
1303 int ptr_attr
= get_attrv(t
->attrs
, ATTR_POINTERTYPE
);
1306 if (t
->kind
!= TKIND_ALIAS
)
1312 static size_t write_typeformatstring_var(FILE *file
, int indent
,
1313 const var_t
*var
, unsigned int *typeformat_offset
)
1315 const type_t
*type
= var
->type
;
1316 int var_ptrs
= var
->ptr_level
, type_ptrs
= 0;
1317 int is_str
= is_attr(var
->attrs
, ATTR_STRING
);
1319 chat("write_typeformatstring_var: %s\n", var
->name
);
1323 is_str
= is_str
|| is_attr(type
->attrs
, ATTR_STRING
);
1324 if (type
->kind
== TKIND_ALIAS
)
1326 else if (is_ptr(type
))
1340 int ptr_level
= var_ptrs
+ type_ptrs
;
1341 int pointer_type
= 0;
1343 chat("write_typeformatstring: type->type = 0x%x, type->name = %s, ptr_level = %d\n", type
->type
, type
->name
, ptr_level
);
1345 /* var attrs only effect the rightmost pointer */
1346 if ((0 < var
->ptr_level
&& var_ptrs
== var
->ptr_level
)
1347 || (var
->ptr_level
== 0 && type
== var
->type
))
1349 int pointer_attr
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
1353 error("'%s': pointer attribute applied to non-pointer type",
1355 pointer_type
= pointer_attr
;
1358 pointer_type
= RPC_FC_RP
;
1360 else /* pointers below other pointers default to unique */
1361 pointer_type
= var_ptrs
? RPC_FC_UP
: get_ptr_attr(type
, RPC_FC_UP
);
1363 if (is_str
&& ptr_level
+ (var
->array
!= NULL
) == 1)
1364 return write_string_tfs(file
, var
->attrs
, type
, var
->array
, var
->name
, typeformat_offset
);
1366 if (is_array_type(var
->attrs
, ptr_level
, var
->array
))
1367 return write_array_tfs(file
, var
->attrs
, type
, var
->array
, var
->name
, typeformat_offset
);
1371 /* basic types don't need a type format string */
1372 if (is_base_type(type
->type
))
1378 case RPC_FC_PSTRUCT
:
1379 case RPC_FC_CSTRUCT
:
1380 case RPC_FC_CPSTRUCT
:
1381 case RPC_FC_CVSTRUCT
:
1382 case RPC_FC_BOGUS_STRUCT
:
1383 return write_struct_tfs(file
, type
, var
->name
, typeformat_offset
);
1384 case RPC_FC_ENCAPSULATED_UNION
:
1385 case RPC_FC_NON_ENCAPSULATED_UNION
:
1386 return write_union_tfs(file
, var
->attrs
, type
, var
->name
, typeformat_offset
);
1388 case RPC_FC_BIND_PRIMITIVE
:
1392 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type
->type
, var
->name
);
1395 else if (ptr_level
== 1)
1397 size_t start_offset
= *typeformat_offset
;
1398 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
1399 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
1400 const type_t
*base
= is_ptr(type
) ? type
->ref
: type
;
1402 if (base
->type
== RPC_FC_IP
)
1404 return write_ip_tfs(file
, base
->attrs
, base
->name
, typeformat_offset
);
1407 /* special case for pointers to base types */
1410 #define CASE_BASETYPE(fctype) \
1411 case RPC_##fctype: \
1412 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n", \
1414 (!in_attr && out_attr) ? 0x0C : 0x08, \
1415 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"), \
1416 (!in_attr && out_attr) ? "[allocated_on_stack] " : ""); \
1417 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
1418 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
1419 *typeformat_offset += 4; \
1421 CASE_BASETYPE(FC_BYTE
);
1422 CASE_BASETYPE(FC_CHAR
);
1423 CASE_BASETYPE(FC_SMALL
);
1424 CASE_BASETYPE(FC_USMALL
);
1425 CASE_BASETYPE(FC_WCHAR
);
1426 CASE_BASETYPE(FC_SHORT
);
1427 CASE_BASETYPE(FC_USHORT
);
1428 CASE_BASETYPE(FC_LONG
);
1429 CASE_BASETYPE(FC_ULONG
);
1430 CASE_BASETYPE(FC_FLOAT
);
1431 CASE_BASETYPE(FC_HYPER
);
1432 CASE_BASETYPE(FC_DOUBLE
);
1433 CASE_BASETYPE(FC_ENUM16
);
1434 CASE_BASETYPE(FC_ENUM32
);
1435 CASE_BASETYPE(FC_IGNORE
);
1436 CASE_BASETYPE(FC_ERROR_STATUS_T
);
1442 assert(ptr_level
> 0);
1445 fprintf(file
, "/* %2u */\n", *typeformat_offset
);
1446 write_pointer_only_tfs(file
, var
->attrs
, pointer_type
,
1447 1 < ptr_level
? 0x10 : 0,
1448 2, typeformat_offset
);
1461 void write_typeformatstring(FILE *file
, const ifref_t
*ifaces
, int for_objects
)
1465 unsigned int typeformat_offset
;
1466 const ifref_t
*iface
= ifaces
;
1468 print_file(file
, indent
, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1469 print_file(file
, indent
, "{\n");
1471 print_file(file
, indent
, "0,\n");
1472 print_file(file
, indent
, "{\n");
1474 print_file(file
, indent
, "NdrFcShort(0x0),\n");
1475 typeformat_offset
= 2;
1479 for (; iface
; iface
= PREV_LINK(iface
))
1481 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
1484 if (iface
->iface
->funcs
)
1486 func_t
*func
= iface
->iface
->funcs
;
1487 while (NEXT_LINK(func
)) func
= NEXT_LINK(func
);
1488 for (; func
; func
= PREV_LINK(func
))
1490 current_func
= func
;
1494 while (NEXT_LINK(var
)) var
= NEXT_LINK(var
);
1497 write_typeformatstring_var(file
, indent
, var
,
1498 &typeformat_offset
);
1499 var
= PREV_LINK(var
);
1506 print_file(file
, indent
, "0x0\n");
1508 print_file(file
, indent
, "}\n");
1510 print_file(file
, indent
, "};\n");
1511 print_file(file
, indent
, "\n");
1514 static unsigned int get_required_buffer_size_type(
1515 const type_t
*type
, int ptr_level
, const expr_t
*array
,
1516 const char *name
, unsigned int *alignment
)
1519 if (ptr_level
== 0 && !array
)
1539 case RPC_FC_ERROR_STATUS_T
:
1549 case RPC_FC_BIND_PRIMITIVE
:
1556 for (field
= type
->fields
; field
; field
= NEXT_LINK(field
))
1558 unsigned int alignment
;
1559 size
+= get_required_buffer_size_type(
1560 field
->type
, field
->ptr_level
, field
->array
, field
->name
,
1567 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name
, type
->type
);
1574 unsigned int get_required_buffer_size(const var_t
*var
, unsigned int *alignment
, enum pass pass
)
1576 expr_t
*size_is
= get_attrp(var
->attrs
, ATTR_SIZEIS
);
1577 int has_size
= (size_is
&& (size_is
->type
!= EXPR_VOID
));
1578 int in_attr
= is_attr(var
->attrs
, ATTR_IN
);
1579 int out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
1581 if (!in_attr
&& !out_attr
)
1586 if (pass
== PASS_OUT
)
1588 if (out_attr
&& var
->ptr_level
> 0)
1590 type_t
*type
= var
->type
;
1592 if (type
->type
== RPC_FC_STRUCT
)
1595 unsigned int size
= 36;
1596 for (field
= type
->fields
; field
; field
= NEXT_LINK(field
))
1599 size
+= get_required_buffer_size_type(
1600 field
->type
, field
->ptr_level
, field
->array
, field
->name
,
1610 if ((!out_attr
|| in_attr
) && !has_size
&& !is_attr(var
->attrs
, ATTR_STRING
) && !var
->array
)
1612 if (var
->ptr_level
> 0)
1614 type_t
*type
= var
->type
;
1616 if (is_base_type(type
->type
))
1620 else if (type
->type
== RPC_FC_STRUCT
)
1622 unsigned int size
= 36;
1624 for (field
= type
->fields
; field
; field
= NEXT_LINK(field
))
1627 size
+= get_required_buffer_size_type(
1628 field
->type
, field
->ptr_level
, field
->array
, field
->name
,
1636 return get_required_buffer_size_type(var
->type
, var
->ptr_level
, var
->array
, var
->name
, alignment
);
1640 static void print_phase_function(FILE *file
, int indent
, const char *type
,
1641 enum remoting_phase phase
,
1642 const char *varname
, unsigned int type_offset
)
1644 const char *function
;
1647 case PHASE_BUFFERSIZE
:
1648 function
= "BufferSize";
1651 function
= "Marshall";
1653 case PHASE_UNMARSHAL
:
1654 function
= "Unmarshall";
1664 print_file(file
, indent
, "Ndr%s%s(\n", type
, function
);
1666 print_file(file
, indent
, "&_StubMsg,\n");
1667 print_file(file
, indent
, "%s%s,\n",
1668 (phase
== PHASE_UNMARSHAL
) ? "(unsigned char **)&" : "(unsigned char *)",
1670 print_file(file
, indent
, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
1671 type_offset
, (phase
== PHASE_UNMARSHAL
) ? "," : ");");
1672 if (phase
== PHASE_UNMARSHAL
)
1673 print_file(file
, indent
, "0);\n");
1677 void print_phase_basetype(FILE *file
, int indent
, enum remoting_phase phase
,
1678 enum pass pass
, const var_t
*var
,
1679 const char *varname
)
1681 const type_t
*type
= var
->type
;
1683 unsigned int alignment
= 0;
1684 unsigned char rtype
;
1686 /* no work to do for other phases, buffer sizing is done elsewhere */
1687 if (phase
!= PHASE_MARSHAL
&& phase
!= PHASE_UNMARSHAL
)
1712 case RPC_FC_ERROR_STATUS_T
:
1724 case RPC_FC_BIND_PRIMITIVE
:
1725 /* no marshalling needed */
1729 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var
->name
, rtype
);
1733 print_file(file
, indent
, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
1734 alignment
- 1, alignment
- 1);
1736 if (phase
== PHASE_MARSHAL
)
1738 print_file(file
, indent
, "*(");
1739 write_type(file
, var
->type
, NULL
, var
->tname
);
1741 fprintf(file
, " *)_StubMsg.Buffer = *");
1743 fprintf(file
, " *)_StubMsg.Buffer = ");
1744 fprintf(file
, varname
);
1745 fprintf(file
, ";\n");
1747 else if (phase
== PHASE_UNMARSHAL
)
1749 if (pass
== PASS_IN
|| pass
== PASS_RETURN
)
1750 print_file(file
, indent
, "");
1752 print_file(file
, indent
, "*");
1753 fprintf(file
, varname
);
1754 if (pass
== PASS_IN
&& var
->ptr_level
)
1755 fprintf(file
, " = (");
1757 fprintf(file
, " = *(");
1758 write_type(file
, var
->type
, NULL
, var
->tname
);
1759 fprintf(file
, " *)_StubMsg.Buffer;\n");
1762 print_file(file
, indent
, "_StubMsg.Buffer += sizeof(");
1763 write_type(file
, var
->type
, NULL
, var
->tname
);
1764 fprintf(file
, ");\n");
1767 /* returns whether the MaxCount, Offset or ActualCount members need to be
1768 * filled in for the specified phase */
1769 static inline int is_size_needed_for_phase(enum remoting_phase phase
)
1771 return (phase
!= PHASE_UNMARSHAL
);
1774 void write_remoting_arguments(FILE *file
, int indent
, const func_t
*func
,
1775 unsigned int *type_offset
, enum pass pass
,
1776 enum remoting_phase phase
)
1778 const expr_t
*length_is
;
1779 const expr_t
*size_is
;
1780 int in_attr
, out_attr
, has_length
, has_size
, pointer_type
;
1787 while (NEXT_LINK(var
)) var
= NEXT_LINK(var
);
1788 for (; var
; *type_offset
+= get_size_typeformatstring_var(var
), var
= PREV_LINK(var
))
1790 const type_t
*type
= var
->type
;
1791 unsigned char rtype
;
1793 length_is
= get_attrp(var
->attrs
, ATTR_LENGTHIS
);
1794 size_is
= get_attrp(var
->attrs
, ATTR_SIZEIS
);
1795 has_length
= length_is
&& (length_is
->type
!= EXPR_VOID
);
1796 has_size
= (size_is
&& (size_is
->type
!= EXPR_VOID
)) || (var
->array
&& !var
->array
->is_const
);
1798 pointer_type
= get_attrv(var
->attrs
, ATTR_POINTERTYPE
);
1800 pointer_type
= RPC_FC_RP
;
1802 in_attr
= is_attr(var
->attrs
, ATTR_IN
);
1803 out_attr
= is_attr(var
->attrs
, ATTR_OUT
);
1804 if (!in_attr
&& !out_attr
)
1823 if (is_string_type(var
->attrs
, var
->ptr_level
, var
->array
))
1825 if (var
->array
&& var
->array
->is_const
)
1826 print_phase_function(file
, indent
, "NonConformantString", phase
, var
->name
, *type_offset
);
1829 if (size_is
&& is_size_needed_for_phase(phase
))
1831 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
1832 write_expr(file
, size_is
, 1);
1833 fprintf(file
, ";\n");
1836 if ((phase
== PHASE_FREE
) || (pointer_type
== RPC_FC_UP
))
1837 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, *type_offset
);
1839 print_phase_function(file
, indent
, "ConformantString", phase
, var
->name
,
1840 *type_offset
+ (has_size
? 4 : 2));
1843 else if (is_array_type(var
->attrs
, var
->ptr_level
, var
->array
))
1845 const char *array_type
;
1847 if (var
->array
&& NEXT_LINK(var
->array
)) /* multi-dimensional array */
1848 array_type
= "ComplexArray";
1851 if (!has_length
&& !has_size
)
1852 array_type
= "FixedArray";
1853 else if (has_length
&& !has_size
)
1855 if (is_size_needed_for_phase(phase
))
1857 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1858 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
1859 write_expr(file
, length_is
, 1);
1860 fprintf(file
, ";\n\n");
1862 array_type
= "VaryingArray";
1864 else if (!has_length
&& has_size
)
1866 if (is_size_needed_for_phase(phase
) && phase
!= PHASE_FREE
)
1868 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
1869 write_expr(file
, size_is
? size_is
: var
->array
, 1);
1870 fprintf(file
, ";\n\n");
1872 array_type
= "ConformantArray";
1876 if (is_size_needed_for_phase(phase
))
1878 print_file(file
, indent
, "_StubMsg.MaxCount = (unsigned long)");
1879 write_expr(file
, size_is
? size_is
: var
->array
, 1);
1880 fprintf(file
, ";\n");
1881 print_file(file
, indent
, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1882 print_file(file
, indent
, "_StubMsg.ActualCount = (unsigned long)");
1883 write_expr(file
, length_is
, 1);
1884 fprintf(file
, ";\n\n");
1886 array_type
= "ConformantVaryingArray";
1890 if (!in_attr
&& phase
== PHASE_FREE
)
1892 print_file(file
, indent
, "if (%s)\n", var
->name
);
1894 print_file(file
, indent
, "_StubMsg.pfnFree(%s);\n", var
->name
);
1896 else if (phase
!= PHASE_FREE
)
1898 if (pointer_type
== RPC_FC_UP
)
1899 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, *type_offset
);
1901 print_phase_function(file
, indent
, array_type
, phase
, var
->name
, *type_offset
+ 4);
1904 else if (var
->ptr_level
== 0 && is_base_type(rtype
))
1906 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
1908 else if (var
->ptr_level
== 0)
1910 const char *ndrtype
;
1915 ndrtype
= "SimpleStruct";
1917 case RPC_FC_CSTRUCT
:
1918 case RPC_FC_CPSTRUCT
:
1919 ndrtype
= "ConformantStruct";
1921 case RPC_FC_CVSTRUCT
:
1922 ndrtype
= "ConformantVaryingStruct";
1924 case RPC_FC_BOGUS_STRUCT
:
1925 ndrtype
= "ComplexStruct";
1928 error("write_remoting_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1929 var
->name
, rtype
, var
->ptr_level
);
1933 print_phase_function(file
, indent
, ndrtype
, phase
, var
->name
, *type_offset
);
1937 if ((var
->ptr_level
== 1) && (pointer_type
== RPC_FC_RP
) && is_base_type(rtype
))
1939 print_phase_basetype(file
, indent
, phase
, pass
, var
, var
->name
);
1941 else if ((var
->ptr_level
== 1) && (pointer_type
== RPC_FC_RP
) && (rtype
== RPC_FC_STRUCT
))
1943 if (phase
!= PHASE_BUFFERSIZE
&& phase
!= PHASE_FREE
)
1944 print_phase_function(file
, indent
, "SimpleStruct", phase
, var
->name
, *type_offset
+ 4);
1948 print_phase_function(file
, indent
, "Pointer", phase
, var
->name
, *type_offset
);
1951 fprintf(file
, "\n");
1956 size_t get_size_procformatstring_var(const var_t
*var
)
1958 unsigned int type_offset
= 2;
1959 return write_procformatstring_var(NULL
, 0, var
, FALSE
, &type_offset
);
1963 size_t get_size_typeformatstring_var(const var_t
*var
)
1965 unsigned int type_offset
= 0;
1966 write_typeformatstring_var(NULL
, 0, var
, &type_offset
);
1970 size_t get_size_procformatstring(const ifref_t
*ifaces
, int for_objects
)
1972 const ifref_t
*iface
= ifaces
;
1979 for (; iface
; iface
= PREV_LINK(iface
))
1981 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
1984 if (iface
->iface
->funcs
)
1986 func
= iface
->iface
->funcs
;
1987 while (NEXT_LINK(func
)) func
= NEXT_LINK(func
);
1990 /* argument list size */
1994 while (NEXT_LINK(var
)) var
= NEXT_LINK(var
);
1997 size
+= get_size_procformatstring_var(var
);
1998 var
= PREV_LINK(var
);
2003 /* return value size */
2004 if (is_void(var
->type
, NULL
))
2007 size
+= get_size_procformatstring_var(var
);
2009 func
= PREV_LINK(func
);
2016 size_t get_size_typeformatstring(const ifref_t
*ifaces
, int for_objects
)
2018 const ifref_t
*iface
= ifaces
;
2025 for (; iface
; iface
= PREV_LINK(iface
))
2027 if (for_objects
!= is_object(iface
->iface
->attrs
) || is_local(iface
->iface
->attrs
))
2030 if (iface
->iface
->funcs
)
2032 func
= iface
->iface
->funcs
;
2033 while (NEXT_LINK(func
)) func
= NEXT_LINK(func
);
2036 /* argument list size */
2040 while (NEXT_LINK(var
)) var
= NEXT_LINK(var
);
2043 size
+= get_size_typeformatstring_var(var
);
2044 var
= PREV_LINK(var
);
2048 func
= PREV_LINK(func
);
2055 static void write_struct_expr(FILE *h
, const expr_t
*e
, int brackets
,
2056 const var_t
*fields
, const char *structvar
)
2062 fprintf(h
, "%ld", e
->u
.lval
);
2065 fprintf(h
, "0x%lx", e
->u
.lval
);
2067 case EXPR_TRUEFALSE
:
2069 fprintf(h
, "FALSE");
2073 case EXPR_IDENTIFIER
:
2076 for (field
= fields
; field
; field
= NEXT_LINK(field
))
2078 if (!strcmp(e
->u
.sval
, field
->name
))
2080 fprintf(h
, "%s->%s", structvar
, e
->u
.sval
);
2084 if (!field
) error("no field found for identifier %s\n", e
->u
.sval
);
2089 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2093 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2097 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2101 write_type(h
, e
->u
.tref
->ref
, NULL
, e
->u
.tref
->name
);
2103 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2106 fprintf(h
, "sizeof(");
2107 write_type(h
, e
->u
.tref
->ref
, NULL
, e
->u
.tref
->name
);
2118 if (brackets
) fprintf(h
, "(");
2119 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2121 case EXPR_SHL
: fprintf(h
, " << "); break;
2122 case EXPR_SHR
: fprintf(h
, " >> "); break;
2123 case EXPR_MUL
: fprintf(h
, " * "); break;
2124 case EXPR_DIV
: fprintf(h
, " / "); break;
2125 case EXPR_ADD
: fprintf(h
, " + "); break;
2126 case EXPR_SUB
: fprintf(h
, " - "); break;
2127 case EXPR_AND
: fprintf(h
, " & "); break;
2128 case EXPR_OR
: fprintf(h
, " | "); break;
2131 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
2132 if (brackets
) fprintf(h
, ")");
2135 if (brackets
) fprintf(h
, "(");
2136 write_struct_expr(h
, e
->ref
, 1, fields
, structvar
);
2138 write_struct_expr(h
, e
->u
.ext
, 1, fields
, structvar
);
2140 write_struct_expr(h
, e
->ext2
, 1, fields
, structvar
);
2141 if (brackets
) fprintf(h
, ")");
2146 int write_expr_eval_routines(FILE *file
, const char *iface
)
2149 struct expr_eval_routine
*eval
;
2150 unsigned short callback_offset
= 0;
2152 LIST_FOR_EACH_ENTRY(eval
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
2156 print_file(file
, indent
, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2157 iface
, eval
->structure
->name
, callback_offset
);
2158 print_file(file
, indent
, "{\n");
2160 print_file(file
, indent
, "struct %s *" STRUCT_EXPR_EVAL_VAR
" = (struct %s *)(pStubMsg->StackTop - %u);\n",
2161 eval
->structure
->name
, eval
->structure
->name
, eval
->structure_size
);
2162 fprintf(file
, "\n");
2163 print_file(file
, indent
, "pStubMsg->Offset = 0;\n"); /* FIXME */
2164 print_file(file
, indent
, "pStubMsg->MaxCount = (unsigned long)");
2165 write_struct_expr(file
, eval
->expr
, 1, eval
->structure
->fields
, STRUCT_EXPR_EVAL_VAR
);
2166 fprintf(file
, ";\n");
2168 print_file(file
, indent
, "}\n\n");
2174 void write_expr_eval_routine_list(FILE *file
, const char *iface
)
2176 struct expr_eval_routine
*eval
;
2177 struct expr_eval_routine
*cursor
;
2178 unsigned short callback_offset
= 0;
2180 fprintf(file
, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2181 fprintf(file
, "{\n");
2183 LIST_FOR_EACH_ENTRY_SAFE(eval
, cursor
, &expr_eval_routines
, struct expr_eval_routine
, entry
)
2185 print_file(file
, 1, "%s_%sExprEval_%04u,\n",
2186 iface
, eval
->structure
->name
, callback_offset
);
2189 list_remove(&eval
->entry
);
2193 fprintf(file
, "};\n\n");