2 * Format String Generator for IDL Compiler
4 * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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;
76 return a->u.lval - b->u.lval;
78 return strcmp(a->u.sval, b->u.sval);
80 ret = compare_expr(a->ref, b->ref);
83 ret = compare_expr(a->u.ext, b->u.ext);
86 return compare_expr(a->ext2, b->ext2);
95 ret = compare_expr(a->ref, b->ref);
98 return compare_expr(a->u.ext, b->u.ext);
104 return compare_expr(a->ref, b->ref);
111 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
114 fprintf(file, "/* %2u */\n", typestring_offset); \
115 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
119 static int print_file(FILE *file, int indent, const char *format, ...)
126 va_start(va, format);
127 for (i = 0; i < indent; i++)
129 r = vfprintf(file, format, va);
134 static inline int type_has_ref(const type_t *type)
136 return (type->type == 0 && type->ref);
139 static inline int is_base_type(unsigned char type)
158 case RPC_FC_ERROR_STATUS_T:
166 static size_t write_procformatstring_var(FILE *file, int indent,
167 const var_t *var, int is_return, unsigned int *type_offset)
170 int ptr_level = var->ptr_level;
171 const type_t *type = var->type;
173 int is_in = is_attr(var->attrs, ATTR_IN);
174 int is_out = is_attr(var->attrs, ATTR_OUT);
176 if (!is_in && !is_out) is_in = TRUE;
178 if (ptr_level == 0 && type_has_ref(type))
181 if (ptr_level == 0 && !var->array && is_base_type(type->type))
184 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
186 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
190 #define CASE_BASETYPE(fctype) \
192 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
193 size = 2; /* includes param type prefix */ \
196 CASE_BASETYPE(FC_BYTE);
197 CASE_BASETYPE(FC_CHAR);
198 CASE_BASETYPE(FC_WCHAR);
199 CASE_BASETYPE(FC_USHORT);
200 CASE_BASETYPE(FC_SHORT);
201 CASE_BASETYPE(FC_ULONG);
202 CASE_BASETYPE(FC_LONG);
203 CASE_BASETYPE(FC_HYPER);
204 CASE_BASETYPE(FC_IGNORE);
205 CASE_BASETYPE(FC_USMALL);
206 CASE_BASETYPE(FC_SMALL);
207 CASE_BASETYPE(FC_FLOAT);
208 CASE_BASETYPE(FC_DOUBLE);
209 CASE_BASETYPE(FC_ERROR_STATUS_T);
212 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
219 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
220 else if (is_in && is_out)
221 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
223 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
225 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
227 print_file(file, indent, "0x01,\n");
228 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
229 size = 4; /* includes param type prefix */
231 *type_offset += get_size_typeformatstring_var(var);
235 void write_procformatstring(FILE *file, type_t *iface)
239 unsigned int type_offset = 2;
241 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
242 print_file(file, indent, "{\n");
244 print_file(file, indent, "0,\n");
245 print_file(file, indent, "{\n");
250 func_t *func = iface->funcs;
251 while (NEXT_LINK(func)) func = NEXT_LINK(func);
252 for (; func; func = PREV_LINK(func))
254 /* emit argument data */
258 while (NEXT_LINK(var)) var = NEXT_LINK(var);
261 write_procformatstring_var(file, indent, var, FALSE,
264 var = PREV_LINK(var);
268 /* emit return value data */
270 if (is_void(var->type, NULL))
272 print_file(file, indent, "0x5b, /* FC_END */\n");
273 print_file(file, indent, "0x5c, /* FC_PAD */\n");
276 write_procformatstring_var(file, indent, var, TRUE,
281 print_file(file, indent, "0x0\n");
283 print_file(file, indent, "}\n");
285 print_file(file, indent, "};\n");
286 print_file(file, indent, "\n");
289 /* write conformance / variance descriptor */
290 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr)
292 unsigned char operator_type = 0;
293 const char *operator_string = "no operators";
294 const expr_t *subexpr = expr;
295 unsigned char correlation_type;
297 if (!file) return 4; /* optimisation for sizing pass */
301 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
302 error("write_conf_or_var_desc: constant value %ld is greater than "
303 "the maximum constant size of %d\n", expr->cval,
304 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
306 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
307 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
308 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
309 print_file(file, 2, "NdrShort(0x%x),\n", expr->cval & USHRT_MAX);
314 switch (subexpr->type)
317 subexpr = subexpr->ref;
318 operator_type = RPC_FC_DEREFERENCE;
319 operator_string = "FC_DEREFERENCE";
322 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
324 subexpr = subexpr->ref;
325 operator_type = RPC_FC_DIV_2;
326 operator_string = "FC_DIV_2";
330 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
332 subexpr = subexpr->ref;
333 operator_type = RPC_FC_MULT_2;
334 operator_string = "FC_MULT_2";
338 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
340 subexpr = subexpr->ref;
341 operator_type = RPC_FC_SUB_1;
342 operator_string = "FC_SUB_1";
346 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
348 subexpr = subexpr->ref;
349 operator_type = RPC_FC_ADD_1;
350 operator_string = "FC_ADD_1";
357 if (subexpr->type == EXPR_IDENTIFIER)
359 const type_t *correlation_variable = NULL;
360 unsigned char param_type = 0;
361 const char *param_type_string = NULL;
368 for (offset = 0, var = structure->fields; var; var = NEXT_LINK(var))
370 offset -= type_memsize(var->type, var->ptr_level, var->array);
371 if (!strcmp(var->name, subexpr->u.sval))
373 correlation_variable = var->type;
377 if (!correlation_variable)
378 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
381 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
385 const var_t *var = func->args;
387 while (NEXT_LINK(var)) var = NEXT_LINK(var);
388 /* FIXME: not all stack variables are sizeof(void *) */
389 for (offset = 0; var; offset += sizeof(void *), var = PREV_LINK(var))
391 if (!strcmp(var->name, subexpr->u.sval))
393 correlation_variable = var->type;
397 if (!correlation_variable)
398 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
401 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
404 while (type_has_ref(correlation_variable))
405 correlation_variable = correlation_variable->ref;
407 switch (correlation_variable->type)
411 param_type = RPC_FC_SMALL;
412 param_type_string = "FC_SMALL";
416 param_type = RPC_FC_USMALL;
417 param_type_string = "FC_USMALL";
421 param_type = RPC_FC_SHORT;
422 param_type_string = "FC_SHORT";
425 param_type = RPC_FC_USHORT;
426 param_type_string = "FC_USHORT";
429 param_type = RPC_FC_LONG;
430 param_type_string = "FC_LONG";
433 param_type = RPC_FC_ULONG;
434 param_type_string = "FC_ULONG";
437 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
438 correlation_variable->type);
441 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
442 correlation_type | param_type,
443 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
445 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
446 print_file(file, 2, "NdrShort(0x%x), /* %soffset = %d */\n",
448 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
453 unsigned int callback_offset = 0;
457 struct expr_eval_routine *eval;
460 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
462 if (!strcmp(eval->structure->name, structure->name) &&
463 !compare_expr(eval->expr, expr))
473 eval = xmalloc(sizeof(*eval));
474 eval->structure = structure;
475 eval->structure_size = fields_memsize(structure->fields);
477 list_add_tail(&expr_eval_routines, &eval->entry);
480 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
484 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
485 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
488 if (callback_offset > USHRT_MAX)
489 error("Maximum number of callback routines reached\n");
491 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
493 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
494 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
495 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", callback_offset, callback_offset);
500 static size_t fields_memsize(const var_t *v)
503 const var_t *first = v;
505 while (NEXT_LINK(v)) v = NEXT_LINK(v);
507 size += type_memsize(v->type, v->ptr_level, v->array);
508 if (v == first) break;
514 static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array)
519 return sizeof(void *);
537 case RPC_FC_ERROR_STATUS_T:
547 case RPC_FC_CVSTRUCT:
548 case RPC_FC_CPSTRUCT:
551 case RPC_FC_BOGUS_STRUCT:
552 case RPC_FC_ENCAPSULATED_UNION:
553 case RPC_FC_NON_ENCAPSULATED_UNION:
554 size = fields_memsize(t->fields);
557 error("type_memsize: Unknown type %d", t->type);
572 static size_t write_string_tfs(FILE *file, const attr_t *attrs,
573 const type_t *type, const expr_t *array,
574 const char *name, size_t *typestring_offset)
576 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
577 int has_size = size_is && (size_is->type != EXPR_VOID);
578 size_t start_offset = *typestring_offset;
580 if ((type->type != RPC_FC_CHAR) && (type->type != RPC_FC_WCHAR))
582 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", type->type, name);
586 if (array && array->is_const)
588 if (array->cval > USHRT_MAX)
589 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
590 name, USHRT_MAX, array->cval - USHRT_MAX);
592 if (type->type == RPC_FC_CHAR)
593 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
595 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
596 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
597 *typestring_offset += 2;
599 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", array->cval, array->cval);
600 *typestring_offset += 2;
606 if (type->type == RPC_FC_CHAR)
607 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
609 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
610 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
611 *typestring_offset += 2;
613 *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, size_is);
619 if (type->type == RPC_FC_CHAR)
620 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
622 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
623 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
624 *typestring_offset += 2;
630 static size_t write_array_tfs(FILE *file, const attr_t *attrs,
631 const type_t *type, const expr_t *array,
632 const char *name, size_t *typestring_offset)
634 const expr_t *length_is = get_attrp(attrs, ATTR_LENGTHIS);
635 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
636 int has_length = length_is && (length_is->type != EXPR_VOID);
637 int has_size = (size_is && (size_is->type != EXPR_VOID)) || !array->is_const;
638 size_t start_offset = *typestring_offset;
640 /* FIXME: need to analyse type for pointers */
642 if (NEXT_LINK(array)) /* multi-dimensional array */
644 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name);
649 if (!has_length && !has_size)
652 size_t size = type_memsize(type, 0, array);
653 if (size < USHRT_MAX)
655 WRITE_FCTYPE(file, FC_SMFARRAY, *typestring_offset);
657 print_file(file, 2, "0x%x, /* 0 */\n", 0);
659 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", size, size);
660 *typestring_offset += 4;
664 WRITE_FCTYPE(file, FC_LGFARRAY, *typestring_offset);
666 print_file(file, 2, "0x%x, /* 0 */\n", 0);
668 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", size, size);
669 *typestring_offset += 6;
672 /* FIXME: write out pointer descriptor if necessary */
674 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
675 print_file(file, 2, "FC_END,\n");
676 *typestring_offset += 2;
680 else if (has_length && !has_size)
683 size_t element_size = type_memsize(type, 0, NULL);
684 size_t elements = array->cval;
685 size_t total_size = element_size * elements;
687 if (total_size < USHRT_MAX)
689 WRITE_FCTYPE(file, FC_SMVARRAY, *typestring_offset);
691 print_file(file, 2, "0x%x, /* 0 */\n", 0);
693 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", total_size, total_size);
694 /* number of elements */
695 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", elements, elements);
696 *typestring_offset += 6;
700 WRITE_FCTYPE(file, FC_LGVARRAY, *typestring_offset);
702 print_file(file, 2, "0x%x, /* 0 */\n", 0);
704 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", total_size, total_size);
705 /* number of elements */
706 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", elements, elements);
707 *typestring_offset += 10;
710 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
711 *typestring_offset += 2;
713 *typestring_offset += write_conf_or_var_desc(file, current_func,
717 /* FIXME: write out pointer descriptor if necessary */
719 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
720 print_file(file, 2, "FC_END,\n");
721 *typestring_offset += 2;
725 else if (!has_length && has_size)
727 /* conformant array */
728 size_t element_size = type_memsize(type, 0, NULL);
730 WRITE_FCTYPE(file, FC_CARRAY, *typestring_offset);
732 print_file(file, 2, "0x%x, /* 0 */\n", 0);
734 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
735 *typestring_offset += 4;
737 *typestring_offset += write_conf_or_var_desc(file, current_func,
739 size_is ? size_is : array);
741 /* FIXME: write out pointer descriptor if necessary */
743 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
744 print_file(file, 2, "FC_END,\n");
745 *typestring_offset += 2;
751 /* conformant varying array */
752 size_t element_size = type_memsize(type, 0, NULL);
754 WRITE_FCTYPE(file, FC_CVARRAY, *typestring_offset);
756 print_file(file, 2, "0x%x, /* 0 */\n", 0);
758 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
759 *typestring_offset += 4;
761 *typestring_offset += write_conf_or_var_desc(file, current_func,
763 size_is ? size_is : array);
764 *typestring_offset += write_conf_or_var_desc(file, current_func,
768 /* FIXME: write out pointer descriptor if necessary */
770 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
771 print_file(file, 2, "FC_END,\n");
772 *typestring_offset += 2;
779 static const var_t *find_array_or_string_in_struct(const type_t *type)
781 /* last field is the first in the fields linked list */
782 const var_t *last_field = type->fields;
783 if (is_array_type(last_field->attrs, last_field->ptr_level, last_field->array))
786 assert((last_field->type->type == RPC_FC_CSTRUCT) ||
787 (last_field->type->type == RPC_FC_CPSTRUCT) ||
788 (last_field->type->type == RPC_FC_CVSTRUCT));
790 return find_array_or_string_in_struct(last_field->type);
793 static size_t write_struct_tfs(FILE *file, const type_t *type,
794 const char *name, size_t *typestring_offset)
804 total_size = type_memsize(type, 0, NULL);
806 if (total_size > USHRT_MAX)
807 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
808 name, USHRT_MAX, total_size - USHRT_MAX);
810 start_offset = *typestring_offset;
811 WRITE_FCTYPE(file, FC_STRUCT, *typestring_offset);
813 print_file(file, 2, "0x0,\n");
815 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
816 *typestring_offset += 4;
819 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
820 print_file(file, 2, "FC_END,\n");
822 *typestring_offset += 2;
825 total_size = type_memsize(type, 0, NULL);
827 if (total_size > USHRT_MAX)
828 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
829 name, USHRT_MAX, total_size - USHRT_MAX);
831 array = find_array_or_string_in_struct(type);
832 current_structure = type;
833 array_offset = write_array_tfs(file, array->attrs, array->type,
834 array->array, array->name,
836 current_structure = NULL;
838 start_offset = *typestring_offset;
839 WRITE_FCTYPE(file, FC_CSTRUCT, *typestring_offset);
841 print_file(file, 2, "0x0,\n");
843 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
844 *typestring_offset += 4;
845 print_file(file, 2, "NdrShort(0x%x), /* offset = %d (%u) */\n",
846 array_offset - *typestring_offset,
847 array_offset - *typestring_offset,
849 *typestring_offset += 2;
850 print_file(file, 2, "FC_END,\n");
851 *typestring_offset += 1;
854 case RPC_FC_CVSTRUCT:
855 total_size = type_memsize(type, 0, NULL);
857 if (total_size > USHRT_MAX)
858 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
859 name, USHRT_MAX, total_size - USHRT_MAX);
861 array = find_array_or_string_in_struct(type);
862 current_structure = type;
863 if (is_attr(array->attrs, ATTR_STRING))
864 array_offset = write_string_tfs(file, array->attrs, array->type,
865 array->array, array->name,
868 array_offset = write_array_tfs(file, array->attrs, array->type,
869 array->array, array->name,
871 current_structure = NULL;
873 start_offset = *typestring_offset;
874 WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset);
876 print_file(file, 2, "0x0,\n");
878 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
879 *typestring_offset += 4;
880 print_file(file, 2, "NdrShort(0x%x), /* offset = %d (%u) */\n",
881 array_offset - *typestring_offset,
882 array_offset - *typestring_offset,
884 *typestring_offset += 2;
885 print_file(file, 2, "FC_END,\n");
886 *typestring_offset += 1;
890 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
891 return *typestring_offset;
895 static size_t write_union_tfs(FILE *file, const attr_t *attrs,
896 const type_t *type, const char *name,
897 size_t *typeformat_offset)
899 error("write_union_tfs: Unimplemented\n");
900 return *typeformat_offset;
903 static size_t write_typeformatstring_var(FILE *file, int indent,
904 const var_t *var, size_t *typeformat_offset)
906 const type_t *type = var->type;
907 int ptr_level = var->ptr_level;
913 if (is_string_type(var->attrs, ptr_level, var->array))
914 return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
916 if (is_array_type(var->attrs, ptr_level, var->array))
917 return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
921 /* follow reference if the type has one */
922 if (type_has_ref(type))
925 /* FIXME: get new ptr_level from type */
929 /* basic types don't need a type format string */
930 if (is_base_type(type->type))
938 case RPC_FC_CPSTRUCT:
939 case RPC_FC_CVSTRUCT:
940 case RPC_FC_BOGUS_STRUCT:
941 return write_struct_tfs(file, type, var->name, typeformat_offset);
942 case RPC_FC_ENCAPSULATED_UNION:
943 case RPC_FC_NON_ENCAPSULATED_UNION:
944 return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset);
946 case RPC_FC_BIND_PRIMITIVE:
950 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
953 else if (ptr_level == 1 && !type_has_ref(type))
955 size_t start_offset = *typeformat_offset;
956 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
957 if (!pointer_type) pointer_type = RPC_FC_RP;
959 /* special case for pointers to base types */
962 #define CASE_BASETYPE(fctype) \
964 print_file(file, indent, "0x%x, 0x08, /* %s [simple_pointer] */\n", \
966 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP")); \
967 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
968 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
969 *typeformat_offset += 4; \
971 CASE_BASETYPE(FC_BYTE);
972 CASE_BASETYPE(FC_CHAR);
973 CASE_BASETYPE(FC_SMALL);
974 CASE_BASETYPE(FC_USMALL);
975 CASE_BASETYPE(FC_WCHAR);
976 CASE_BASETYPE(FC_SHORT);
977 CASE_BASETYPE(FC_USHORT);
978 CASE_BASETYPE(FC_LONG);
979 CASE_BASETYPE(FC_ULONG);
980 CASE_BASETYPE(FC_FLOAT);
981 CASE_BASETYPE(FC_HYPER);
982 CASE_BASETYPE(FC_DOUBLE);
983 CASE_BASETYPE(FC_ENUM16);
984 CASE_BASETYPE(FC_ENUM32);
985 CASE_BASETYPE(FC_IGNORE);
986 CASE_BASETYPE(FC_ERROR_STATUS_T);
992 assert(ptr_level > 0);
994 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
995 if (!pointer_type) pointer_type = RPC_FC_RP;
998 fprintf(file, "/* %2u */\n", *typeformat_offset);
999 print_file(file, indent, "0x%x, 0x00, /* %s */\n",
1001 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
1002 print_file(file, indent, "NdrShort(0x2), /* 2 */\n");
1003 *typeformat_offset += 4;
1010 void write_typeformatstring(FILE *file, type_t *iface)
1014 size_t typeformat_offset;
1016 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1017 print_file(file, indent, "{\n");
1019 print_file(file, indent, "0,\n");
1020 print_file(file, indent, "{\n");
1022 print_file(file, indent, "NdrFcShort(0x0),\n");
1023 typeformat_offset = 2;
1027 func_t *func = iface->funcs;
1028 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1029 for (; func; func = PREV_LINK(func))
1031 current_func = func;
1035 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1038 write_typeformatstring_var(file, indent, var,
1039 &typeformat_offset);
1040 var = PREV_LINK(var);
1046 print_file(file, indent, "0x0\n");
1048 print_file(file, indent, "}\n");
1050 print_file(file, indent, "};\n");
1051 print_file(file, indent, "\n");
1054 static unsigned int get_required_buffer_size_type(
1055 const type_t *type, int ptr_level, const expr_t *array,
1056 const char *name, unsigned int *alignment)
1059 if (ptr_level == 0 && !array && !type_has_ref(type))
1078 case RPC_FC_ERROR_STATUS_T:
1088 case RPC_FC_BIND_PRIMITIVE:
1095 for (field = type->fields; field; field = NEXT_LINK(field))
1097 unsigned int alignment;
1098 size += get_required_buffer_size_type(
1099 field->type, field->ptr_level, field->array, field->name,
1106 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1110 if (ptr_level == 0 && type_has_ref(type))
1111 return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
1115 unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
1117 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
1120 void marshall_arguments(FILE *file, int indent, func_t *func,
1121 unsigned int *type_offset, enum pass pass)
1123 unsigned int last_size = 0;
1130 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1131 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
1133 int in_attr = is_attr(var->attrs, ATTR_IN);
1134 int out_attr = is_attr(var->attrs, ATTR_OUT);
1136 if (!in_attr && !out_attr)
1153 if (is_string_type(var->attrs, var->ptr_level, var->array))
1155 if (var->array && var->array->is_const)
1156 print_file(file, indent,
1157 "NdrNonConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1158 var->name, *type_offset);
1160 print_file(file, indent,
1161 "NdrConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1162 var->name, *type_offset);
1165 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1167 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1168 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1169 const char *array_type;
1170 int has_length = length_is && (length_is->type != EXPR_VOID);
1171 int has_size = (size_is && (size_is->type != EXPR_VOID)) || !var->array->is_const;
1173 if (NEXT_LINK(var->array)) /* multi-dimensional array */
1174 array_type = "ComplexArray";
1177 if (!has_length && !has_size)
1178 array_type = "FixedArray";
1179 else if (has_length && !has_size)
1181 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1182 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1183 write_expr(file, length_is, 1);
1184 fprintf(file, ";\n\n");
1185 array_type = "VaryingArray";
1187 else if (!has_length && has_size)
1189 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1190 write_expr(file, size_is ? size_is : var->array, 1);
1191 fprintf(file, ";\n\n");
1192 array_type = "ConformantArray";
1196 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1197 write_expr(file, size_is ? size_is : var->array, 1);
1198 fprintf(file, ";\n");
1199 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1200 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1201 write_expr(file, length_is, 1);
1202 fprintf(file, ";\n\n");
1203 array_type = "ConformantVaryingArray";
1207 print_file(file, indent,
1208 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1209 array_type, var->name, *type_offset);
1212 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1215 unsigned int alignment = 0;
1216 switch (var->type->type)
1230 if (last_size != 0 && last_size < 2)
1231 alignment = (2 - last_size);
1237 case RPC_FC_ERROR_STATUS_T:
1239 if (last_size != 0 && last_size < 4)
1240 alignment = (4 - last_size);
1246 if (last_size != 0 && last_size < 4)
1247 alignment = (4 - last_size);
1251 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1256 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
1258 print_file(file, indent, "*(");
1259 write_type(file, var->type, var, var->tname);
1260 fprintf(file, " *)_StubMsg.Buffer = ");
1261 write_name(file, var);
1262 fprintf(file, ";\n");
1263 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1264 write_type(file, var->type, var, var->tname);
1265 fprintf(file, ");\n");
1269 else if (var->ptr_level == 0)
1271 const char *ndrtype;
1273 switch (var->type->type)
1276 ndrtype = "SimpleStruct";
1278 case RPC_FC_CSTRUCT:
1279 case RPC_FC_CPSTRUCT:
1280 ndrtype = "ConformantStruct";
1282 case RPC_FC_CVSTRUCT:
1283 ndrtype = "ConformantVaryingStruct";
1285 case RPC_FC_BOGUS_STRUCT:
1286 ndrtype = "ComplexStruct";
1289 case RPC_FC_BIND_PRIMITIVE:
1290 /* no marshalling needed */
1293 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1294 var->name, var->type->type, var->ptr_level);
1298 print_file(file, indent,
1299 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1300 ndrtype, var->name, *type_offset);
1305 print_file(file, indent,
1306 "NdrPointerMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1307 var->name, *type_offset);
1310 fprintf(file, "\n");
1314 void unmarshall_arguments(FILE *file, int indent, func_t *func,
1315 unsigned int *type_offset, enum pass pass)
1317 unsigned int last_size = 0;
1324 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1325 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
1327 int in_attr = is_attr(var->attrs, ATTR_IN);
1328 int out_attr = is_attr(var->attrs, ATTR_OUT);
1330 if (!in_attr && !out_attr)
1347 if (is_string_type(var->attrs, var->ptr_level, var->array))
1349 if (var->array && var->array->is_const)
1350 print_file(file, indent,
1351 "NdrNonConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1352 var->name, *type_offset);
1354 print_file(file, indent,
1355 "NdrConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1356 var->name, *type_offset);
1359 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1361 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1362 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1363 const char *array_type;
1364 int has_length = length_is && (length_is->type != EXPR_VOID);
1365 int has_size = (size_is && (size_is->type != EXPR_VOID)) || !var->array->is_const;
1367 if (NEXT_LINK(var->array)) /* multi-dimensional array */
1368 array_type = "ComplexArray";
1371 if (!has_length && !has_size)
1372 array_type = "FixedArray";
1373 else if (has_length && !has_size)
1374 array_type = "VaryingArray";
1375 else if (!has_length && has_size)
1376 array_type = "ConformantArray";
1378 array_type = "ConformantVaryingArray";
1381 print_file(file, indent,
1382 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1383 array_type, var->name, *type_offset);
1386 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1389 unsigned int alignment = 0;
1391 switch (var->type->type)
1405 if (last_size != 0 && last_size < 2)
1406 alignment = (2 - last_size);
1412 case RPC_FC_ERROR_STATUS_T:
1414 if (last_size != 0 && last_size < 4)
1415 alignment = (4 - last_size);
1421 if (last_size != 0 && last_size < 4)
1422 alignment = (4 - last_size);
1426 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1431 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
1433 print_file(file, indent, "");
1434 write_name(file, var);
1435 fprintf(file, " = *(");
1436 write_type(file, var->type, var, var->tname);
1437 fprintf(file, " *)_StubMsg.Buffer;\n");
1438 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1439 write_type(file, var->type, var, var->tname);
1440 fprintf(file, ");\n");
1444 else if (var->ptr_level == 0)
1446 const char *ndrtype;
1448 switch (var->type->type)
1451 ndrtype = "SimpleStruct";
1453 case RPC_FC_CSTRUCT:
1454 case RPC_FC_CPSTRUCT:
1455 ndrtype = "ConformantStruct";
1457 case RPC_FC_CVSTRUCT:
1458 ndrtype = "ConformantVaryingStruct";
1460 case RPC_FC_BOGUS_STRUCT:
1461 ndrtype = "ComplexStruct";
1464 case RPC_FC_BIND_PRIMITIVE:
1465 /* no unmarshalling needed */
1468 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1469 var->name, var->type->type, var->ptr_level);
1473 print_file(file, indent,
1474 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1475 ndrtype, var->name, *type_offset);
1480 print_file(file, indent,
1481 "NdrPointerUnmarshall(&_StubMsg, (unsigned char **)&%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
1482 var->name, *type_offset);
1485 fprintf(file, "\n");
1490 size_t get_size_procformatstring_var(const var_t *var)
1492 unsigned int type_offset = 2;
1493 return write_procformatstring_var(NULL, 0, var, FALSE, &type_offset);
1497 size_t get_size_typeformatstring_var(const var_t *var)
1499 unsigned int type_offset = 0;
1500 write_typeformatstring_var(NULL, 0, var, &type_offset);
1504 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
1505 const var_t *fields, const char *structvar)
1511 fprintf(h, "%ld", e->u.lval);
1514 fprintf(h, "0x%lx", e->u.lval);
1516 case EXPR_IDENTIFIER:
1519 for (field = fields; field; field = NEXT_LINK(field))
1521 if (!strcmp(e->u.sval, field->name))
1523 fprintf(h, "%s->%s", structvar, e->u.sval);
1527 if (!field) error("no field found for identifier %s\n", e->u.sval);
1532 write_struct_expr(h, e->ref, 1, fields, structvar);
1536 write_struct_expr(h, e->ref, 1, fields, structvar);
1540 write_struct_expr(h, e->ref, 1, fields, structvar);
1544 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
1546 write_struct_expr(h, e->ref, 1, fields, structvar);
1549 fprintf(h, "sizeof(");
1550 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
1561 if (brackets) fprintf(h, "(");
1562 write_struct_expr(h, e->ref, 1, fields, structvar);
1564 case EXPR_SHL: fprintf(h, " << "); break;
1565 case EXPR_SHR: fprintf(h, " >> "); break;
1566 case EXPR_MUL: fprintf(h, " * "); break;
1567 case EXPR_DIV: fprintf(h, " / "); break;
1568 case EXPR_ADD: fprintf(h, " + "); break;
1569 case EXPR_SUB: fprintf(h, " - "); break;
1570 case EXPR_AND: fprintf(h, " & "); break;
1571 case EXPR_OR: fprintf(h, " | "); break;
1574 write_struct_expr(h, e->u.ext, 1, fields, structvar);
1575 if (brackets) fprintf(h, ")");
1578 if (brackets) fprintf(h, "(");
1579 write_struct_expr(h, e->ref, 1, fields, structvar);
1581 write_struct_expr(h, e->u.ext, 1, fields, structvar);
1583 write_struct_expr(h, e->ext2, 1, fields, structvar);
1584 if (brackets) fprintf(h, ")");
1589 int write_expr_eval_routines(FILE *file, const char *iface)
1592 struct expr_eval_routine *eval;
1593 unsigned short callback_offset = 0;
1595 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
1599 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
1600 iface, eval->structure->name, callback_offset);
1601 print_file(file, indent, "{\n");
1603 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
1604 eval->structure->name, eval->structure->name, eval->structure_size);
1605 fprintf(file, "\n");
1606 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
1607 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
1608 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
1609 fprintf(file, ";\n");
1611 print_file(file, indent, "}\n\n");
1617 void write_expr_eval_routine_list(FILE *file, const char *iface)
1619 struct expr_eval_routine *eval;
1620 struct expr_eval_routine *cursor;
1621 unsigned short callback_offset = 0;
1623 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
1624 fprintf(file, "{\n");
1626 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
1628 print_file(file, 1, "%s_%sExprEval_%04u,\n",
1629 iface, eval->structure->name, callback_offset);
1632 list_remove(&eval->entry);
1636 fprintf(file, "};\n\n");