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 array_dims_t *array, unsigned int *align);
63 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
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_list_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 int is_user_derived(const var_t *v)
164 const type_t *type = v->type;
166 if (v->attrs && is_attr( v->attrs, ATTR_WIREMARSHAL )) return 1;
170 if (type->attrs && is_attr( type->attrs, ATTR_WIREMARSHAL )) return 1;
176 static inline int is_base_type(unsigned char type)
195 case RPC_FC_ERROR_STATUS_T:
196 case RPC_FC_BIND_PRIMITIVE:
204 static size_t write_procformatstring_var(FILE *file, int indent,
205 const var_t *var, int is_return, unsigned int *type_offset)
208 int ptr_level = var->ptr_level;
209 const type_t *type = var->type;
211 int is_in = is_attr(var->attrs, ATTR_IN);
212 int is_out = is_attr(var->attrs, ATTR_OUT);
214 if (!is_in && !is_out) is_in = TRUE;
216 if (ptr_level == 0 && !var->array && is_base_type(type->type))
219 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
221 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
225 #define CASE_BASETYPE(fctype) \
227 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
228 size = 2; /* includes param type prefix */ \
231 CASE_BASETYPE(FC_BYTE);
232 CASE_BASETYPE(FC_CHAR);
233 CASE_BASETYPE(FC_WCHAR);
234 CASE_BASETYPE(FC_USHORT);
235 CASE_BASETYPE(FC_SHORT);
236 CASE_BASETYPE(FC_ULONG);
237 CASE_BASETYPE(FC_LONG);
238 CASE_BASETYPE(FC_HYPER);
239 CASE_BASETYPE(FC_IGNORE);
240 CASE_BASETYPE(FC_USMALL);
241 CASE_BASETYPE(FC_SMALL);
242 CASE_BASETYPE(FC_FLOAT);
243 CASE_BASETYPE(FC_DOUBLE);
244 CASE_BASETYPE(FC_ERROR_STATUS_T);
247 case RPC_FC_BIND_PRIMITIVE:
248 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
249 size = 2; /* includes param type prefix */
253 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
260 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
261 else if (is_in && is_out)
262 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
264 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
266 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
268 print_file(file, indent, "0x01,\n");
269 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
270 size = 4; /* includes param type prefix */
272 *type_offset += get_size_typeformatstring_var(var);
276 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
278 const ifref_t *iface;
281 unsigned int type_offset = 2;
283 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
284 print_file(file, indent, "{\n");
286 print_file(file, indent, "0,\n");
287 print_file(file, indent, "{\n");
290 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
292 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
295 if (iface->iface->funcs)
298 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
300 if (is_local(func->def->attrs)) continue;
301 /* emit argument data */
304 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
305 write_procformatstring_var(file, indent, var, FALSE, &type_offset);
308 /* emit return value data */
310 if (is_void(var->type, NULL))
312 print_file(file, indent, "0x5b, /* FC_END */\n");
313 print_file(file, indent, "0x5c, /* FC_PAD */\n");
316 write_procformatstring_var(file, indent, var, TRUE,
322 print_file(file, indent, "0x0\n");
324 print_file(file, indent, "}\n");
326 print_file(file, indent, "};\n");
327 print_file(file, indent, "\n");
330 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
334 #define CASE_BASETYPE(fctype) \
336 print_file(file, 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
337 *typestring_offset += 1; \
340 CASE_BASETYPE(FC_BYTE);
341 CASE_BASETYPE(FC_CHAR);
342 CASE_BASETYPE(FC_SMALL);
343 CASE_BASETYPE(FC_USMALL);
344 CASE_BASETYPE(FC_WCHAR);
345 CASE_BASETYPE(FC_SHORT);
346 CASE_BASETYPE(FC_USHORT);
347 CASE_BASETYPE(FC_LONG);
348 CASE_BASETYPE(FC_ULONG);
349 CASE_BASETYPE(FC_FLOAT);
350 CASE_BASETYPE(FC_HYPER);
351 CASE_BASETYPE(FC_DOUBLE);
352 CASE_BASETYPE(FC_ENUM16);
353 CASE_BASETYPE(FC_ENUM32);
354 CASE_BASETYPE(FC_IGNORE);
355 CASE_BASETYPE(FC_ERROR_STATUS_T);
361 /* write conformance / variance descriptor */
362 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_list_t *expr_list)
364 unsigned char operator_type = 0;
365 const char *operator_string = "no operators";
366 const expr_t *expr, *subexpr;
367 unsigned char correlation_type;
369 if (!file) return 4; /* optimisation for sizing pass */
371 if (list_count(expr_list) > 1)
372 error("write_conf_or_var_desc: multi-dimensional arrays not supported yet\n");
374 expr = subexpr = LIST_ENTRY( list_head(expr_list), const expr_t, entry );
378 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
379 error("write_conf_or_var_desc: constant value %ld is greater than "
380 "the maximum constant size of %d\n", expr->cval,
381 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
383 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
384 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
385 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
386 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
391 switch (subexpr->type)
394 subexpr = subexpr->ref;
395 operator_type = RPC_FC_DEREFERENCE;
396 operator_string = "FC_DEREFERENCE";
399 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
401 subexpr = subexpr->ref;
402 operator_type = RPC_FC_DIV_2;
403 operator_string = "FC_DIV_2";
407 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
409 subexpr = subexpr->ref;
410 operator_type = RPC_FC_MULT_2;
411 operator_string = "FC_MULT_2";
415 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
417 subexpr = subexpr->ref;
418 operator_type = RPC_FC_SUB_1;
419 operator_string = "FC_SUB_1";
423 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
425 subexpr = subexpr->ref;
426 operator_type = RPC_FC_ADD_1;
427 operator_string = "FC_ADD_1";
434 if (subexpr->type == EXPR_IDENTIFIER)
436 const type_t *correlation_variable = NULL;
437 unsigned char correlation_variable_type;
438 unsigned char param_type = 0;
439 const char *param_type_string = NULL;
447 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
449 unsigned int align = 0;
450 offset -= type_memsize(var->type, var->ptr_level, var->array, &align);
451 /* FIXME: take alignment into account */
452 if (!strcmp(var->name, subexpr->u.sval))
454 correlation_variable = var->type;
458 if (!correlation_variable)
459 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
462 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
468 offset = sizeof(void *);
469 if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
471 if (!strcmp(var->name, subexpr->u.sval))
473 correlation_variable = var->type;
476 /* FIXME: not all stack variables are sizeof(void *) */
477 offset += sizeof(void *);
479 if (!correlation_variable)
480 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
483 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
486 correlation_variable_type = correlation_variable->type;
488 switch (correlation_variable_type)
492 param_type = RPC_FC_SMALL;
493 param_type_string = "FC_SMALL";
497 param_type = RPC_FC_USMALL;
498 param_type_string = "FC_USMALL";
502 param_type = RPC_FC_SHORT;
503 param_type_string = "FC_SHORT";
506 param_type = RPC_FC_USHORT;
507 param_type_string = "FC_USHORT";
510 param_type = RPC_FC_LONG;
511 param_type_string = "FC_LONG";
514 param_type = RPC_FC_ULONG;
515 param_type_string = "FC_ULONG";
521 if (sizeof(void *) == 4) /* FIXME */
523 param_type = RPC_FC_LONG;
524 param_type_string = "FC_LONG";
528 param_type = RPC_FC_HYPER;
529 param_type_string = "FC_HYPER";
533 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
534 correlation_variable_type);
537 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
538 correlation_type | param_type,
539 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
541 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
542 print_file(file, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
544 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
549 unsigned int callback_offset = 0;
553 struct expr_eval_routine *eval;
556 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
558 if (!strcmp(eval->structure->name, structure->name) &&
559 !compare_expr(eval->expr, expr))
569 unsigned int align = 0;
570 eval = xmalloc(sizeof(*eval));
571 eval->structure = structure;
572 eval->structure_size = fields_memsize(structure->fields, &align);
574 list_add_tail(&expr_eval_routines, &eval->entry);
577 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
581 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
582 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
585 if (callback_offset > USHRT_MAX)
586 error("Maximum number of callback routines reached\n");
588 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
590 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
591 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
592 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
597 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
602 if (!fields) return 0;
603 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
604 size += type_memsize(v->type, v->ptr_level, v->array, align);
609 static size_t get_array_size( const array_dims_t *array )
614 if (!array) return 0;
616 LIST_FOR_EACH_ENTRY( dim, array, expr_t, entry )
618 if (!dim->is_const) return 0;
625 static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *array, unsigned int *align)
631 size = sizeof(void *);
632 if (size > *align) *align = size;
634 else switch (t->type)
641 if (size > *align) *align = size;
648 if (size > *align) *align = size;
652 case RPC_FC_ERROR_STATUS_T:
656 if (size > *align) *align = size;
661 if (size > *align) *align = size;
664 case RPC_FC_CVSTRUCT:
665 case RPC_FC_CPSTRUCT:
668 case RPC_FC_BOGUS_STRUCT:
669 case RPC_FC_ENCAPSULATED_UNION:
670 case RPC_FC_NON_ENCAPSULATED_UNION:
671 size = fields_memsize(t->fields, align);
674 error("type_memsize: Unknown type %d\n", t->type);
678 if (array) size *= get_array_size( array );
682 static int write_pointers(FILE *file, const attr_list_t *attrs,
683 const type_t *type, int ptr_level,
684 const array_dims_t *array, int level,
685 unsigned int *typestring_offset)
687 int pointers_written = 0;
690 /* don't generate a pointer for first-level arrays since we want to
691 * descend into them to write their pointers, not stop here */
692 if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array))
694 return write_pointers(file, NULL, type, 0, NULL, level + 1, typestring_offset);
699 /* FIXME: only general algorithm implemented, not the actual writing */
700 error("write_pointers: Writing type format string for pointer is unimplemented\n");
706 /* note: don't descend into complex structures or unions since these
707 * will always be generated as a separate type */
709 case RPC_FC_CVSTRUCT:
710 case RPC_FC_CPSTRUCT:
713 if (!type->fields) break;
714 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
715 pointers_written += write_pointers(file, v->attrs, v->type,
716 v->ptr_level, v->array,
727 return pointers_written;
730 static size_t write_pointer_description(FILE *file, const attr_list_t *attrs,
731 const type_t *type, int ptr_level,
732 const array_dims_t *array, int level,
733 size_t typestring_offset)
738 /* don't generate a pointer for first-level arrays since we want to
739 * descend into them to write their pointers, not stop here */
740 if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array))
742 return write_pointer_description(file, NULL, type, 0, NULL,
743 level + 1, typestring_offset);
748 /* FIXME: only general algorithm implemented, not the actual writing */
749 error("write_pointer_description: Writing pointer description is unimplemented\n");
753 /* FIXME: search through all refs for pointers too */
757 /* note: don't descend into complex structures or unions since these
758 * will always be generated as a separate type */
760 case RPC_FC_CVSTRUCT:
761 case RPC_FC_CPSTRUCT:
764 if (!type->fields) break;
765 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
766 size += write_pointer_description(file, v->attrs, v->type,
767 v->ptr_level, v->array,
781 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
782 const type_t *type, const array_dims_t *array,
783 const char *name, unsigned int *typestring_offset)
785 const expr_list_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
786 int has_size = is_non_void(size_is);
787 size_t start_offset = *typestring_offset;
788 unsigned char flags = 0;
794 pointer_type = type->type;
798 pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
801 pointer_type = RPC_FC_RP;
803 if (!get_attrp(attrs, ATTR_SIZEIS))
804 flags |= RPC_FC_P_SIMPLEPOINTER;
808 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
810 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
814 print_file(file, 2,"0x%x, 0x%x, /* %s%s */\n",
816 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"),
817 (flags & RPC_FC_P_SIMPLEPOINTER) ? " [simple_pointer]" : "");
818 *typestring_offset += 2;
820 if (!(flags & RPC_FC_P_SIMPLEPOINTER))
822 print_file(file, 2, "NdrFcShort(0x2),\n");
823 *typestring_offset += 2;
826 if (array && !is_conformant_array(array))
828 /* FIXME: multi-dimensional array */
829 const expr_t *dim = LIST_ENTRY( list_head( array ), expr_t, entry );
830 if (dim->cval > USHRT_MAX)
831 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
832 name, USHRT_MAX, dim->cval - USHRT_MAX);
834 if (rtype == RPC_FC_CHAR)
835 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
837 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
838 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
839 *typestring_offset += 2;
841 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", dim->cval, dim->cval);
842 *typestring_offset += 2;
848 if (rtype == RPC_FC_CHAR)
849 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
851 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
852 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
853 *typestring_offset += 2;
855 *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, size_is);
861 if (rtype == RPC_FC_CHAR)
862 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
864 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
865 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
866 *typestring_offset += 2;
872 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs,
873 const type_t *type, const array_dims_t *array,
874 const char *name, unsigned int *typestring_offset)
876 const expr_list_t *length_is = get_attrp(attrs, ATTR_LENGTHIS);
877 const expr_list_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
878 int has_length = is_non_void(length_is);
879 int has_size = is_non_void(size_is) || is_conformant_array(array);
881 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
883 pointer_type = RPC_FC_RP;
885 print_file(file, 2, "0x%x, 0x00, /* %s */\n",
887 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
888 print_file(file, 2, "NdrFcShort(0x2),\n");
889 *typestring_offset += 4;
891 if (array && list_count(array) > 1) /* multi-dimensional array */
893 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name);
898 const expr_t *dim = array ? LIST_ENTRY( list_head( array ), expr_t, entry ) : NULL;
899 size_t pointer_start_offset = *typestring_offset;
902 if (write_pointers(file, attrs, type, 0, array, 0, typestring_offset) > 0)
905 start_offset = *typestring_offset;
907 if (!has_length && !has_size)
910 unsigned int align = 0;
911 size_t size = type_memsize(type, 0, array, &align);
912 if (size < USHRT_MAX)
914 WRITE_FCTYPE(file, FC_SMFARRAY, *typestring_offset);
916 print_file(file, 2, "0x%02x,\n", align - 1);
918 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", size, size);
919 *typestring_offset += 4;
923 WRITE_FCTYPE(file, FC_LGFARRAY, *typestring_offset);
925 print_file(file, 2, "0x%02x,\n", align - 1);
927 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", size, size);
928 *typestring_offset += 6;
933 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
934 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
935 *typestring_offset += 2;
936 *typestring_offset = write_pointer_description(file, attrs,
937 type, 0, array, 0, pointer_start_offset);
938 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
939 *typestring_offset += 1;
942 if (!write_base_type( file, type, typestring_offset ))
944 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
945 *typestring_offset += 1;
947 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
948 *typestring_offset += 1;
952 else if (has_length && !has_size)
955 unsigned int align = 0;
956 size_t element_size = type_memsize(type, 0, NULL, &align);
957 size_t elements = dim->cval;
958 size_t total_size = element_size * elements;
960 if (total_size < USHRT_MAX)
962 WRITE_FCTYPE(file, FC_SMVARRAY, *typestring_offset);
964 print_file(file, 2, "0x%02x,\n", align - 1);
966 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", total_size, total_size);
967 /* number of elements */
968 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", elements, elements);
969 *typestring_offset += 6;
973 WRITE_FCTYPE(file, FC_LGVARRAY, *typestring_offset);
975 print_file(file, 2, "0x%02x,\n", align - 1);
977 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", total_size, total_size);
978 /* number of elements */
979 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", elements, elements);
980 *typestring_offset += 10;
983 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
984 *typestring_offset += 2;
986 *typestring_offset += write_conf_or_var_desc(file, current_func,
992 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
993 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
994 *typestring_offset += 2;
995 *typestring_offset += write_pointer_description(file, attrs,
996 type, 0, array, 0, pointer_start_offset);
997 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
998 *typestring_offset += 1;
1001 if (!write_base_type( file, type, typestring_offset ))
1003 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
1004 *typestring_offset += 1;
1006 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1007 *typestring_offset += 1;
1009 return start_offset;
1011 else if (!has_length && has_size)
1013 /* conformant array */
1014 unsigned int align = 0;
1015 size_t element_size = type_memsize(type, 0, NULL, &align);
1017 WRITE_FCTYPE(file, FC_CARRAY, *typestring_offset);
1019 print_file(file, 2, "0x%02x,\n", align - 1);
1021 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
1022 *typestring_offset += 4;
1024 *typestring_offset += write_conf_or_var_desc(file, current_func,
1026 size_is ? size_is : array);
1030 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1031 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1032 *typestring_offset += 2;
1033 *typestring_offset += write_pointer_description(file, attrs,
1034 type, 0, array, 0, pointer_start_offset);
1035 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1036 *typestring_offset += 1;
1039 if (!write_base_type( file, type, typestring_offset ))
1041 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
1042 *typestring_offset += 1;
1044 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1045 *typestring_offset += 1;
1047 return start_offset;
1051 /* conformant varying array */
1052 unsigned int align = 0;
1053 size_t element_size = type_memsize(type, 0, NULL, &align);
1055 WRITE_FCTYPE(file, FC_CVARRAY, *typestring_offset);
1057 print_file(file, 2, "0x%02x,\n", align - 1);
1059 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
1060 *typestring_offset += 4;
1062 *typestring_offset += write_conf_or_var_desc(file, current_func,
1064 size_is ? size_is : array);
1065 *typestring_offset += write_conf_or_var_desc(file, current_func,
1071 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1072 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1073 *typestring_offset += 2;
1074 *typestring_offset += write_pointer_description(file, attrs,
1075 type, 0, array, 0, pointer_start_offset);
1076 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1077 *typestring_offset += 1;
1080 if (!write_base_type( file, type, typestring_offset ))
1082 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
1083 *typestring_offset += 1;
1085 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1086 *typestring_offset += 1;
1088 return start_offset;
1093 static const var_t *find_array_or_string_in_struct(const type_t *type)
1095 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1097 if (is_array_type(last_field->attrs, last_field->ptr_level, last_field->array))
1100 assert((last_field->type->type == RPC_FC_CSTRUCT) ||
1101 (last_field->type->type == RPC_FC_CPSTRUCT) ||
1102 (last_field->type->type == RPC_FC_CVSTRUCT));
1104 return find_array_or_string_in_struct(last_field->type);
1107 static void write_struct_members(FILE *file, const type_t *type, unsigned int *typestring_offset)
1111 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1113 unsigned char rtype = field->type->type;
1116 write_array_tfs( file, field->attrs, field->type, field->array,
1117 field->name, typestring_offset );
1118 else if (!write_base_type( file, field->type, typestring_offset ))
1119 error("Unsupported member type 0x%x\n", rtype);
1122 if (!(*typestring_offset % 2))
1124 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1125 *typestring_offset += 1;
1128 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1129 *typestring_offset += 1;
1132 static size_t write_struct_tfs(FILE *file, const type_t *type,
1133 const char *name, unsigned int *typestring_offset)
1135 unsigned int total_size;
1137 size_t start_offset;
1138 size_t array_offset;
1139 size_t pointer_offset;
1140 unsigned int align = 0;
1145 case RPC_FC_PSTRUCT:
1146 total_size = type_memsize(type, 0, NULL, &align);
1148 if (total_size > USHRT_MAX)
1149 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1150 name, USHRT_MAX, total_size - USHRT_MAX);
1152 if (type->type == RPC_FC_PSTRUCT)
1154 pointer_offset = *typestring_offset;
1155 write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset);
1157 else pointer_offset = 0; /* silence warning */
1159 start_offset = *typestring_offset;
1160 if (type->type == RPC_FC_STRUCT)
1161 WRITE_FCTYPE(file, FC_STRUCT, *typestring_offset);
1163 WRITE_FCTYPE(file, FC_PSTRUCT, *typestring_offset);
1165 print_file(file, 2, "0x%02x,\n", align - 1);
1167 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1168 *typestring_offset += 4;
1170 if (type->type == RPC_FC_PSTRUCT)
1172 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1173 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1174 *typestring_offset += 2;
1175 *typestring_offset += write_pointer_description(file, NULL,
1176 type, 0, NULL, 0, pointer_offset);
1177 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1178 *typestring_offset += 1;
1182 write_struct_members(file, type, typestring_offset);
1183 return start_offset;
1184 case RPC_FC_CSTRUCT:
1185 case RPC_FC_CPSTRUCT:
1186 total_size = type_memsize(type, 0, NULL, &align);
1188 if (total_size > USHRT_MAX)
1189 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1190 name, USHRT_MAX, total_size - USHRT_MAX);
1192 array = find_array_or_string_in_struct(type);
1193 current_structure = type;
1194 array_offset = write_array_tfs(file, array->attrs, array->type,
1195 array->array, array->name,
1197 current_structure = NULL;
1199 if (type->type == RPC_FC_CPSTRUCT)
1201 pointer_offset = *typestring_offset;
1202 write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset);
1204 else pointer_offset = 0; /* silence warning */
1206 start_offset = *typestring_offset;
1207 if (type->type == RPC_FC_CSTRUCT)
1208 WRITE_FCTYPE(file, FC_CSTRUCT, *typestring_offset);
1210 WRITE_FCTYPE(file, FC_CPSTRUCT, *typestring_offset);
1212 print_file(file, 2, "0x%02x,\n", align - 1);
1214 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1215 *typestring_offset += 4;
1216 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1217 array_offset - *typestring_offset,
1218 array_offset - *typestring_offset,
1220 *typestring_offset += 2;
1222 if (type->type == RPC_FC_CPSTRUCT)
1224 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1225 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1226 *typestring_offset += 2;
1227 *typestring_offset += write_pointer_description(file, NULL,
1228 type, 0, NULL, 0, pointer_offset);
1229 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1230 *typestring_offset += 1;
1233 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1234 *typestring_offset += 1;
1236 return start_offset;
1237 case RPC_FC_CVSTRUCT:
1238 total_size = type_memsize(type, 0, NULL, &align);
1240 if (total_size > USHRT_MAX)
1241 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1242 name, USHRT_MAX, total_size - USHRT_MAX);
1244 array = find_array_or_string_in_struct(type);
1245 current_structure = type;
1246 if (is_attr(array->attrs, ATTR_STRING))
1247 array_offset = write_string_tfs(file, array->attrs, array->type,
1248 array->array, array->name,
1251 array_offset = write_array_tfs(file, array->attrs, array->type,
1252 array->array, array->name,
1254 current_structure = NULL;
1256 pointer_offset = *typestring_offset;
1257 if (!write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset))
1260 start_offset = *typestring_offset;
1261 WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset);
1263 print_file(file, 2, "0x%02x,\n", align - 1);
1265 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1266 *typestring_offset += 4;
1267 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1268 array_offset - *typestring_offset,
1269 array_offset - *typestring_offset,
1271 *typestring_offset += 2;
1273 if (pointer_offset != 0)
1275 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1276 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1277 *typestring_offset += 2;
1278 *typestring_offset += write_pointer_description(file, NULL,
1279 type, 0, NULL, 0, pointer_offset);
1280 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1281 *typestring_offset += 1;
1284 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1285 *typestring_offset += 1;
1287 return start_offset;
1289 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
1290 return *typestring_offset;
1294 static void write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1295 unsigned char flags, size_t offset,
1296 unsigned int *typeformat_offset)
1298 int in_attr, out_attr;
1299 in_attr = is_attr(attrs, ATTR_IN);
1300 out_attr = is_attr(attrs, ATTR_OUT);
1301 if (!in_attr && !out_attr) in_attr = 1;
1303 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1306 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1309 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
1313 fprintf(file, " [allocated_on_stack]");
1315 fprintf(file, " [pointer_deref]");
1316 fprintf(file, " */\n");
1319 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", offset, offset);
1320 *typeformat_offset += 4;
1323 static size_t write_union_tfs(FILE *file, const attr_list_t *attrs,
1324 const type_t *type, const char *name,
1325 unsigned int *typeformat_offset)
1327 error("write_union_tfs: Unimplemented\n");
1328 return *typeformat_offset;
1331 static size_t write_ip_tfs(FILE *file, const func_t *func, const var_t *var,
1332 unsigned int *typeformat_offset)
1335 size_t start_offset = *typeformat_offset;
1336 const var_t *iid = get_attrp(var->attrs, ATTR_IIDIS);
1341 expr_list_t expr_list;
1343 expr.type = EXPR_IDENTIFIER;
1345 expr.u.sval = iid->name;
1346 expr.is_const = FALSE;
1347 list_init( &expr_list );
1348 list_add_head( &expr_list, &expr.entry );
1349 print_file(file, 2, "0x2f, /* FC_IP */\n");
1350 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1351 *typeformat_offset += write_conf_or_var_desc(file, func, NULL, &expr_list) + 2;
1355 const type_t *base = is_ptr(var->type) ? var->type->ref : var->type;
1356 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1359 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1361 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1362 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1363 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1364 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1365 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1366 for (i = 0; i < 8; ++i)
1367 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1370 fprintf(file, "\n");
1372 *typeformat_offset += 18;
1374 return start_offset;
1377 static int get_ptr_attr(const type_t *t, int def_type)
1381 int ptr_attr = get_attrv(t->attrs, ATTR_POINTERTYPE);
1384 if (t->kind != TKIND_ALIAS)
1390 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
1391 const var_t *var, unsigned int *typeformat_offset)
1393 const type_t *type = var->type;
1394 int var_ptrs = var->ptr_level, type_ptrs = 0;
1395 int is_str = is_attr(var->attrs, ATTR_STRING);
1397 chat("write_typeformatstring_var: %s\n", var->name);
1401 is_str = is_str || is_attr(type->attrs, ATTR_STRING);
1402 if (type->kind == TKIND_ALIAS)
1404 else if (is_ptr(type))
1418 int ptr_level = var_ptrs + type_ptrs;
1419 int pointer_type = 0;
1421 chat("write_typeformatstring: type->type = 0x%x, type->name = %s, ptr_level = %d\n", type->type, type->name, ptr_level);
1423 /* var attrs only effect the rightmost pointer */
1424 if ((0 < var->ptr_level && var_ptrs == var->ptr_level)
1425 || (var->ptr_level == 0 && type == var->type))
1427 int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE);
1431 error("'%s': pointer attribute applied to non-pointer type",
1433 pointer_type = pointer_attr;
1436 pointer_type = RPC_FC_RP;
1438 else /* pointers below other pointers default to unique */
1439 pointer_type = var_ptrs ? RPC_FC_UP : get_ptr_attr(type, RPC_FC_UP);
1441 if (is_str && ptr_level + (var->array != NULL) == 1)
1442 return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
1444 if (is_array_type(var->attrs, ptr_level, var->array))
1445 return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
1449 /* basic types don't need a type format string */
1450 if (is_base_type(type->type))
1456 case RPC_FC_PSTRUCT:
1457 case RPC_FC_CSTRUCT:
1458 case RPC_FC_CPSTRUCT:
1459 case RPC_FC_CVSTRUCT:
1460 case RPC_FC_BOGUS_STRUCT:
1461 return write_struct_tfs(file, type, var->name, typeformat_offset);
1462 case RPC_FC_ENCAPSULATED_UNION:
1463 case RPC_FC_NON_ENCAPSULATED_UNION:
1464 return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset);
1466 case RPC_FC_BIND_PRIMITIVE:
1470 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
1473 else if (ptr_level == 1)
1475 size_t start_offset = *typeformat_offset;
1476 int in_attr = is_attr(var->attrs, ATTR_IN);
1477 int out_attr = is_attr(var->attrs, ATTR_OUT);
1478 const type_t *base = is_ptr(type) ? type->ref : type;
1480 if (base->type == RPC_FC_IP)
1482 return write_ip_tfs(file, func, var, typeformat_offset);
1485 /* special case for pointers to base types */
1488 #define CASE_BASETYPE(fctype) \
1489 case RPC_##fctype: \
1490 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n", \
1492 (!in_attr && out_attr) ? 0x0C : 0x08, \
1493 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"), \
1494 (!in_attr && out_attr) ? "[allocated_on_stack] " : ""); \
1495 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
1496 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
1497 *typeformat_offset += 4; \
1499 CASE_BASETYPE(FC_BYTE);
1500 CASE_BASETYPE(FC_CHAR);
1501 CASE_BASETYPE(FC_SMALL);
1502 CASE_BASETYPE(FC_USMALL);
1503 CASE_BASETYPE(FC_WCHAR);
1504 CASE_BASETYPE(FC_SHORT);
1505 CASE_BASETYPE(FC_USHORT);
1506 CASE_BASETYPE(FC_LONG);
1507 CASE_BASETYPE(FC_ULONG);
1508 CASE_BASETYPE(FC_FLOAT);
1509 CASE_BASETYPE(FC_HYPER);
1510 CASE_BASETYPE(FC_DOUBLE);
1511 CASE_BASETYPE(FC_ENUM16);
1512 CASE_BASETYPE(FC_ENUM32);
1513 CASE_BASETYPE(FC_IGNORE);
1514 CASE_BASETYPE(FC_ERROR_STATUS_T);
1520 assert(ptr_level > 0);
1523 fprintf(file, "/* %2u */\n", *typeformat_offset);
1524 write_pointer_only_tfs(file, var->attrs, pointer_type,
1525 1 < ptr_level ? 0x10 : 0,
1526 2, typeformat_offset);
1539 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
1543 unsigned int typeformat_offset;
1544 const ifref_t *iface;
1546 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1547 print_file(file, indent, "{\n");
1549 print_file(file, indent, "0,\n");
1550 print_file(file, indent, "{\n");
1552 print_file(file, indent, "NdrFcShort(0x0),\n");
1553 typeformat_offset = 2;
1555 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
1557 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
1560 if (iface->iface->funcs)
1563 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
1565 if (is_local(func->def->attrs)) continue;
1566 current_func = func;
1568 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1569 write_typeformatstring_var(file, indent, func, var,
1570 &typeformat_offset);
1575 print_file(file, indent, "0x0\n");
1577 print_file(file, indent, "}\n");
1579 print_file(file, indent, "};\n");
1580 print_file(file, indent, "\n");
1583 static unsigned int get_required_buffer_size_type(
1584 const type_t *type, int ptr_level, const array_dims_t *array,
1585 const char *name, unsigned int *alignment)
1612 case RPC_FC_ERROR_STATUS_T:
1624 case RPC_FC_BIND_PRIMITIVE:
1630 if (!type->fields) return 0;
1631 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1633 unsigned int alignment;
1634 size += get_required_buffer_size_type(
1635 field->type, field->ptr_level, field->array, field->name,
1642 if (is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT)
1643 size = get_required_buffer_size_type( type->ref, 0, NULL, name, alignment );
1647 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1650 if (array) size *= get_array_size( array );
1655 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
1657 expr_list_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1658 int has_size = is_non_void(size_is);
1659 int in_attr = is_attr(var->attrs, ATTR_IN);
1660 int out_attr = is_attr(var->attrs, ATTR_OUT);
1662 if (!in_attr && !out_attr)
1667 if (pass == PASS_OUT)
1669 if (out_attr && var->ptr_level > 0)
1671 type_t *type = var->type;
1673 if (type->type == RPC_FC_STRUCT)
1676 unsigned int size = 36;
1678 if (!type->fields) return size;
1679 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1682 size += get_required_buffer_size_type(
1683 field->type, field->ptr_level, field->array, field->name,
1693 if ((!out_attr || in_attr) && !has_size && !is_attr(var->attrs, ATTR_STRING) && !var->array)
1695 if (var->ptr_level > 0)
1697 type_t *type = var->type;
1699 if (is_base_type(type->type))
1703 else if (type->type == RPC_FC_STRUCT)
1705 unsigned int size = 36;
1708 if (!type->fields) return size;
1709 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1712 size += get_required_buffer_size_type(
1713 field->type, field->ptr_level, field->array, field->name,
1721 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
1725 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
1728 unsigned int total_size = 0, alignment;
1732 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1734 total_size += get_required_buffer_size(var, &alignment, pass);
1735 total_size += alignment;
1739 if (pass == PASS_OUT && !is_void(func->def->type, NULL))
1741 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
1742 total_size += alignment;
1747 static void print_phase_function(FILE *file, int indent, const char *type,
1748 enum remoting_phase phase,
1749 const char *varname, unsigned int type_offset)
1751 const char *function;
1754 case PHASE_BUFFERSIZE:
1755 function = "BufferSize";
1758 function = "Marshall";
1760 case PHASE_UNMARSHAL:
1761 function = "Unmarshall";
1771 print_file(file, indent, "Ndr%s%s(\n", type, function);
1773 print_file(file, indent, "&_StubMsg,\n");
1774 print_file(file, indent, "%s%s,\n",
1775 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)&" : "(unsigned char *)",
1777 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
1778 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
1779 if (phase == PHASE_UNMARSHAL)
1780 print_file(file, indent, "0);\n");
1784 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
1785 enum pass pass, const var_t *var,
1786 const char *varname)
1788 const type_t *type = var->type;
1790 unsigned int alignment = 0;
1791 unsigned char rtype;
1793 /* no work to do for other phases, buffer sizing is done elsewhere */
1794 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
1819 case RPC_FC_ERROR_STATUS_T:
1831 case RPC_FC_BIND_PRIMITIVE:
1832 /* no marshalling needed */
1836 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
1840 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
1841 alignment - 1, alignment - 1);
1843 if (phase == PHASE_MARSHAL)
1845 print_file(file, indent, "*(");
1846 write_type(file, var->type, NULL, var->tname);
1848 fprintf(file, " *)_StubMsg.Buffer = *");
1850 fprintf(file, " *)_StubMsg.Buffer = ");
1851 fprintf(file, varname);
1852 fprintf(file, ";\n");
1854 else if (phase == PHASE_UNMARSHAL)
1856 if (pass == PASS_IN || pass == PASS_RETURN)
1857 print_file(file, indent, "");
1859 print_file(file, indent, "*");
1860 fprintf(file, varname);
1861 if (pass == PASS_IN && var->ptr_level)
1862 fprintf(file, " = (");
1864 fprintf(file, " = *(");
1865 write_type(file, var->type, NULL, var->tname);
1866 fprintf(file, " *)_StubMsg.Buffer;\n");
1869 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1870 write_type(file, var->type, NULL, var->tname);
1871 fprintf(file, ");\n");
1874 /* returns whether the MaxCount, Offset or ActualCount members need to be
1875 * filled in for the specified phase */
1876 static inline int is_size_needed_for_phase(enum remoting_phase phase)
1878 return (phase != PHASE_UNMARSHAL);
1881 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
1882 unsigned int *type_offset, enum pass pass,
1883 enum remoting_phase phase)
1885 const expr_list_t *length_is;
1886 const expr_list_t *size_is;
1887 int in_attr, out_attr, has_length, has_size, pointer_type;
1893 if (phase == PHASE_BUFFERSIZE)
1895 unsigned int size = get_function_buffer_size( func, pass );
1896 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
1899 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1901 const type_t *type = var->type;
1902 unsigned char rtype;
1904 length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1905 size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1906 has_length = is_non_void(length_is);
1907 has_size = is_non_void(size_is) || (var->array && is_conformant_array(var->array));
1909 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
1911 pointer_type = RPC_FC_RP;
1913 in_attr = is_attr(var->attrs, ATTR_IN);
1914 out_attr = is_attr(var->attrs, ATTR_OUT);
1915 if (!in_attr && !out_attr)
1921 if (!in_attr) goto next;
1924 if (!out_attr) goto next;
1932 if (is_user_derived( var ))
1934 print_phase_function(file, indent, "UserMarshal", phase, var->name, *type_offset);
1936 else if (is_string_type(var->attrs, var->ptr_level, var->array))
1938 if (var->array && !is_conformant_array(var->array))
1939 print_phase_function(file, indent, "NonConformantString", phase, var->name, *type_offset);
1942 if (size_is && is_size_needed_for_phase(phase))
1944 const expr_t *size = LIST_ENTRY( list_head(size_is), const expr_t, entry );
1945 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1946 write_expr(file, size, 1);
1947 fprintf(file, ";\n");
1950 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
1951 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
1953 print_phase_function(file, indent, "ConformantString", phase, var->name,
1954 *type_offset + (has_size ? 4 : 2));
1957 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1959 const char *array_type;
1961 if (var->array && list_count(var->array) > 1) /* multi-dimensional array */
1962 array_type = "ComplexArray";
1965 if (!has_length && !has_size)
1966 array_type = "FixedArray";
1967 else if (has_length && !has_size)
1969 if (is_size_needed_for_phase(phase))
1971 const expr_t *length = LIST_ENTRY( list_head(length_is), const expr_t, entry );
1972 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1973 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1974 write_expr(file, length, 1);
1975 fprintf(file, ";\n\n");
1977 array_type = "VaryingArray";
1979 else if (!has_length && has_size)
1981 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
1983 const expr_t *size = LIST_ENTRY( list_head(size_is ? size_is : var->array),
1984 const expr_t, entry );
1985 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1986 write_expr(file, size, 1);
1987 fprintf(file, ";\n\n");
1989 array_type = "ConformantArray";
1993 if (is_size_needed_for_phase(phase))
1995 const expr_t *length = LIST_ENTRY( list_head(length_is), const expr_t, entry );
1996 const expr_t *size = LIST_ENTRY( list_head(size_is ? size_is : var->array),
1997 const expr_t, entry );
1998 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1999 write_expr(file, size, 1);
2000 fprintf(file, ";\n");
2001 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2002 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2003 write_expr(file, length, 1);
2004 fprintf(file, ";\n\n");
2006 array_type = "ConformantVaryingArray";
2010 if (!in_attr && phase == PHASE_FREE)
2012 print_file(file, indent, "if (%s)\n", var->name);
2014 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2016 else if (phase != PHASE_FREE)
2018 if (pointer_type == RPC_FC_UP)
2019 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
2021 print_phase_function(file, indent, array_type, phase, var->name, *type_offset + 4);
2024 else if (var->ptr_level == 0 && is_base_type(rtype))
2026 print_phase_basetype(file, indent, phase, pass, var, var->name);
2028 else if (var->ptr_level == 0)
2033 print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset);
2035 case RPC_FC_CSTRUCT:
2036 case RPC_FC_CPSTRUCT:
2037 print_phase_function(file, indent, "ConformantStruct", phase, var->name, *type_offset);
2039 case RPC_FC_CVSTRUCT:
2040 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var->name, *type_offset);
2042 case RPC_FC_BOGUS_STRUCT:
2043 print_phase_function(file, indent, "ComplexStruct", phase, var->name, *type_offset);
2046 if (is_base_type( var->type->ref->type ))
2048 print_phase_basetype(file, indent, phase, pass, var, var->name);
2050 else if (var->type->ref->type == RPC_FC_STRUCT)
2052 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2053 print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset + 4);
2058 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2059 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2060 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
2064 error("write_remoting_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
2065 var->name, rtype, var->ptr_level);
2070 if ((var->ptr_level == 1) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2072 print_phase_basetype(file, indent, phase, pass, var, var->name);
2074 else if ((var->ptr_level == 1) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2076 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2077 print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset + 4);
2082 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2083 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2084 print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset);
2087 fprintf(file, "\n");
2089 *type_offset += get_size_typeformatstring_var(var);
2094 size_t get_size_procformatstring_var(const var_t *var)
2096 unsigned int type_offset = 2;
2097 return write_procformatstring_var(NULL, 0, var, FALSE, &type_offset);
2101 size_t get_size_procformatstring_func(const func_t *func)
2106 /* argument list size */
2108 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2109 size += get_size_procformatstring_var(var);
2111 /* return value size */
2112 if (is_void(func->def->type, NULL))
2113 size += 2; /* FC_END and FC_PAD */
2115 size += get_size_procformatstring_var(func->def);
2120 size_t get_size_typeformatstring_var(const var_t *var)
2122 unsigned int type_offset = 0;
2123 write_typeformatstring_var(NULL, 0, NULL, var, &type_offset);
2127 size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects)
2129 const ifref_t *iface;
2133 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2135 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2138 if (iface->iface->funcs)
2139 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2140 if (!is_local(func->def->attrs))
2141 size += get_size_procformatstring_func( func );
2146 size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects)
2148 const ifref_t *iface;
2153 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2155 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2158 if (iface->iface->funcs)
2160 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2162 if (is_local(func->def->attrs)) continue;
2163 /* argument list size */
2165 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2166 size += get_size_typeformatstring_var(var);
2173 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2174 const var_list_t *fields, const char *structvar)
2180 fprintf(h, "%ld", e->u.lval);
2183 fprintf(h, "0x%lx", e->u.lval);
2185 case EXPR_TRUEFALSE:
2187 fprintf(h, "FALSE");
2191 case EXPR_IDENTIFIER:
2194 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2195 if (!strcmp(e->u.sval, field->name))
2197 fprintf(h, "%s->%s", structvar, e->u.sval);
2201 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2206 write_struct_expr(h, e->ref, 1, fields, structvar);
2210 write_struct_expr(h, e->ref, 1, fields, structvar);
2214 write_struct_expr(h, e->ref, 1, fields, structvar);
2218 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
2220 write_struct_expr(h, e->ref, 1, fields, structvar);
2223 fprintf(h, "sizeof(");
2224 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
2235 if (brackets) fprintf(h, "(");
2236 write_struct_expr(h, e->ref, 1, fields, structvar);
2238 case EXPR_SHL: fprintf(h, " << "); break;
2239 case EXPR_SHR: fprintf(h, " >> "); break;
2240 case EXPR_MUL: fprintf(h, " * "); break;
2241 case EXPR_DIV: fprintf(h, " / "); break;
2242 case EXPR_ADD: fprintf(h, " + "); break;
2243 case EXPR_SUB: fprintf(h, " - "); break;
2244 case EXPR_AND: fprintf(h, " & "); break;
2245 case EXPR_OR: fprintf(h, " | "); break;
2248 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2249 if (brackets) fprintf(h, ")");
2252 if (brackets) fprintf(h, "(");
2253 write_struct_expr(h, e->ref, 1, fields, structvar);
2255 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2257 write_struct_expr(h, e->ext2, 1, fields, structvar);
2258 if (brackets) fprintf(h, ")");
2264 void declare_stub_args( FILE *file, int indent, const func_t *func )
2266 int in_attr, out_attr;
2268 const var_t *def = func->def;
2271 /* declare return value '_RetVal' */
2272 if (!is_void(def->type, NULL))
2274 print_file(file, indent, "");
2275 write_type(file, def->type, def, def->tname);
2276 fprintf(file, " _RetVal;\n");
2282 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2284 const expr_list_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
2285 int has_size = is_non_void(size_is);
2286 int is_string = is_attr(var->attrs, ATTR_STRING);
2288 in_attr = is_attr(var->attrs, ATTR_IN);
2289 out_attr = is_attr(var->attrs, ATTR_OUT);
2290 if (!out_attr && !in_attr)
2293 if (!in_attr && !has_size && !is_string)
2296 print_file(file, indent, "");
2297 write_type(file, var->type, NULL, var->tname);
2298 for (indirection = 0; indirection < var->ptr_level - 1; indirection++)
2300 fprintf(file, " _W%u;\n", i++);
2303 print_file(file, indent, "");
2304 write_type(file, var->type, var, var->tname);
2306 write_name(file, var);
2307 write_array(file, var->array, 0);
2308 fprintf(file, ";\n");
2313 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
2315 int in_attr, out_attr;
2318 const expr_list_t *size_is;
2324 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2326 int is_string = is_attr(var->attrs, ATTR_STRING);
2327 size_is = get_attrp(var->attrs, ATTR_SIZEIS);
2328 has_size = is_non_void(size_is);
2329 in_attr = is_attr(var->attrs, ATTR_IN);
2330 out_attr = is_attr(var->attrs, ATTR_OUT);
2331 if (!out_attr && !in_attr)
2336 print_file(file, indent, "");
2337 write_name(file, var);
2342 unsigned int size, align = 0;
2343 type_t *type = var->type;
2345 fprintf(file, " = NdrAllocate(&_StubMsg, ");
2346 LIST_FOR_EACH_ENTRY( expr, size_is, const expr_t, entry )
2348 if (expr->type == EXPR_VOID) continue;
2349 write_expr( file, expr, 1 );
2350 fprintf(file, " * ");
2352 size = type_memsize(type, 0, NULL, &align);
2353 fprintf(file, "%u);\n", size);
2355 else if (!is_string)
2357 fprintf(file, " = &_W%u;\n", i);
2358 if (var->ptr_level > 1)
2359 print_file(file, indent, "_W%u = 0;\n", i);
2367 fprintf(file, "\n");
2371 int write_expr_eval_routines(FILE *file, const char *iface)
2374 struct expr_eval_routine *eval;
2375 unsigned short callback_offset = 0;
2377 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
2381 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2382 iface, eval->structure->name, callback_offset);
2383 print_file(file, indent, "{\n");
2385 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
2386 eval->structure->name, eval->structure->name, eval->structure_size);
2387 fprintf(file, "\n");
2388 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
2389 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
2390 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
2391 fprintf(file, ";\n");
2393 print_file(file, indent, "}\n\n");
2399 void write_expr_eval_routine_list(FILE *file, const char *iface)
2401 struct expr_eval_routine *eval;
2402 struct expr_eval_routine *cursor;
2403 unsigned short callback_offset = 0;
2405 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2406 fprintf(file, "{\n");
2408 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
2410 print_file(file, 1, "%s_%sExprEval_%04u,\n",
2411 iface, eval->structure->name, callback_offset);
2414 list_remove(&eval->entry);
2418 fprintf(file, "};\n\n");