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., 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:
159 case RPC_FC_BIND_PRIMITIVE:
167 static size_t write_procformatstring_var(FILE *file, int indent,
168 const var_t *var, int is_return, unsigned int *type_offset)
171 int ptr_level = var->ptr_level;
172 const type_t *type = var->type;
174 int is_in = is_attr(var->attrs, ATTR_IN);
175 int is_out = is_attr(var->attrs, ATTR_OUT);
177 if (!is_in && !is_out) is_in = TRUE;
179 if (ptr_level == 0 && type_has_ref(type))
182 if (ptr_level == 0 && !var->array && is_base_type(type->type))
185 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
187 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
191 #define CASE_BASETYPE(fctype) \
193 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
194 size = 2; /* includes param type prefix */ \
197 CASE_BASETYPE(FC_BYTE);
198 CASE_BASETYPE(FC_CHAR);
199 CASE_BASETYPE(FC_WCHAR);
200 CASE_BASETYPE(FC_USHORT);
201 CASE_BASETYPE(FC_SHORT);
202 CASE_BASETYPE(FC_ULONG);
203 CASE_BASETYPE(FC_LONG);
204 CASE_BASETYPE(FC_HYPER);
205 CASE_BASETYPE(FC_IGNORE);
206 CASE_BASETYPE(FC_USMALL);
207 CASE_BASETYPE(FC_SMALL);
208 CASE_BASETYPE(FC_FLOAT);
209 CASE_BASETYPE(FC_DOUBLE);
210 CASE_BASETYPE(FC_ERROR_STATUS_T);
213 case RPC_FC_BIND_PRIMITIVE:
214 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
215 size = 2; /* includes param type prefix */
219 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
226 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
227 else if (is_in && is_out)
228 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
230 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
232 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
234 print_file(file, indent, "0x01,\n");
235 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
236 size = 4; /* includes param type prefix */
238 *type_offset += get_size_typeformatstring_var(var);
242 void write_procformatstring(FILE *file, type_t *iface)
246 unsigned int type_offset = 2;
248 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
249 print_file(file, indent, "{\n");
251 print_file(file, indent, "0,\n");
252 print_file(file, indent, "{\n");
257 func_t *func = iface->funcs;
258 while (NEXT_LINK(func)) func = NEXT_LINK(func);
259 for (; func; func = PREV_LINK(func))
261 /* emit argument data */
265 while (NEXT_LINK(var)) var = NEXT_LINK(var);
268 write_procformatstring_var(file, indent, var, FALSE,
271 var = PREV_LINK(var);
275 /* emit return value data */
277 if (is_void(var->type, NULL))
279 print_file(file, indent, "0x5b, /* FC_END */\n");
280 print_file(file, indent, "0x5c, /* FC_PAD */\n");
283 write_procformatstring_var(file, indent, var, TRUE,
288 print_file(file, indent, "0x0\n");
290 print_file(file, indent, "}\n");
292 print_file(file, indent, "};\n");
293 print_file(file, indent, "\n");
296 /* write conformance / variance descriptor */
297 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr)
299 unsigned char operator_type = 0;
300 const char *operator_string = "no operators";
301 const expr_t *subexpr = expr;
302 unsigned char correlation_type;
304 if (!file) return 4; /* optimisation for sizing pass */
308 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
309 error("write_conf_or_var_desc: constant value %ld is greater than "
310 "the maximum constant size of %d\n", expr->cval,
311 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
313 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
314 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
315 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
316 print_file(file, 2, "NdrShort(0x%x),\n", expr->cval & USHRT_MAX);
321 switch (subexpr->type)
324 subexpr = subexpr->ref;
325 operator_type = RPC_FC_DEREFERENCE;
326 operator_string = "FC_DEREFERENCE";
329 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
331 subexpr = subexpr->ref;
332 operator_type = RPC_FC_DIV_2;
333 operator_string = "FC_DIV_2";
337 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
339 subexpr = subexpr->ref;
340 operator_type = RPC_FC_MULT_2;
341 operator_string = "FC_MULT_2";
345 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
347 subexpr = subexpr->ref;
348 operator_type = RPC_FC_SUB_1;
349 operator_string = "FC_SUB_1";
353 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
355 subexpr = subexpr->ref;
356 operator_type = RPC_FC_ADD_1;
357 operator_string = "FC_ADD_1";
364 if (subexpr->type == EXPR_IDENTIFIER)
366 const type_t *correlation_variable = NULL;
367 unsigned char param_type = 0;
368 const char *param_type_string = NULL;
375 for (offset = 0, var = structure->fields; var; var = NEXT_LINK(var))
377 offset -= type_memsize(var->type, var->ptr_level, var->array);
378 if (!strcmp(var->name, subexpr->u.sval))
380 correlation_variable = var->type;
384 if (!correlation_variable)
385 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
388 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
392 const var_t *var = func->args;
394 while (NEXT_LINK(var)) var = NEXT_LINK(var);
395 /* FIXME: not all stack variables are sizeof(void *) */
396 for (offset = 0; var; offset += sizeof(void *), var = PREV_LINK(var))
398 if (!strcmp(var->name, subexpr->u.sval))
400 correlation_variable = var->type;
404 if (!correlation_variable)
405 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
408 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
411 while (type_has_ref(correlation_variable))
412 correlation_variable = correlation_variable->ref;
414 switch (correlation_variable->type)
418 param_type = RPC_FC_SMALL;
419 param_type_string = "FC_SMALL";
423 param_type = RPC_FC_USMALL;
424 param_type_string = "FC_USMALL";
428 param_type = RPC_FC_SHORT;
429 param_type_string = "FC_SHORT";
432 param_type = RPC_FC_USHORT;
433 param_type_string = "FC_USHORT";
436 param_type = RPC_FC_LONG;
437 param_type_string = "FC_LONG";
440 param_type = RPC_FC_ULONG;
441 param_type_string = "FC_ULONG";
444 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
445 correlation_variable->type);
448 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
449 correlation_type | param_type,
450 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
452 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
453 print_file(file, 2, "NdrShort(0x%x), /* %soffset = %d */\n",
455 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
460 unsigned int callback_offset = 0;
464 struct expr_eval_routine *eval;
467 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
469 if (!strcmp(eval->structure->name, structure->name) &&
470 !compare_expr(eval->expr, expr))
480 eval = xmalloc(sizeof(*eval));
481 eval->structure = structure;
482 eval->structure_size = fields_memsize(structure->fields);
484 list_add_tail(&expr_eval_routines, &eval->entry);
487 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
491 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
492 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
495 if (callback_offset > USHRT_MAX)
496 error("Maximum number of callback routines reached\n");
498 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
500 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
501 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
502 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", callback_offset, callback_offset);
507 static size_t fields_memsize(const var_t *v)
510 const var_t *first = v;
512 while (NEXT_LINK(v)) v = NEXT_LINK(v);
514 size += type_memsize(v->type, v->ptr_level, v->array);
515 if (v == first) break;
521 static size_t type_memsize(const type_t *t, int ptr_level, const expr_t *array)
526 return sizeof(void *);
544 case RPC_FC_ERROR_STATUS_T:
554 case RPC_FC_CVSTRUCT:
555 case RPC_FC_CPSTRUCT:
558 case RPC_FC_BOGUS_STRUCT:
559 case RPC_FC_ENCAPSULATED_UNION:
560 case RPC_FC_NON_ENCAPSULATED_UNION:
561 size = fields_memsize(t->fields);
564 error("type_memsize: Unknown type %d", t->type);
579 static int write_pointers(FILE *file, const attr_t *attrs,
580 const type_t *type, int ptr_level,
581 const expr_t *array, int level,
582 size_t *typestring_offset)
584 int pointers_written = 0;
587 /* don't generate a pointer for first-level arrays since we want to
588 * descend into them to write their pointers, not stop here */
589 if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array))
591 return write_pointers(file, NULL, type, 0, NULL, level + 1, typestring_offset);
596 /* FIXME: only general algorithm implemented, not the actual writing */
597 error("write_pointers: Writing type format string for pointer is unimplemented\n");
601 /* FIXME: search through all refs for pointers too */
602 while(type_has_ref(type))
607 /* note: don't descend into complex structures or unions since these
608 * will always be generated as a separate type */
610 case RPC_FC_CVSTRUCT:
611 case RPC_FC_CPSTRUCT:
616 while (NEXT_LINK(v)) v = NEXT_LINK(v);
617 for (; v; v = PREV_LINK(v))
618 pointers_written += write_pointers(file, v->attrs, v->type,
619 v->ptr_level, v->array,
630 return pointers_written;
633 static size_t write_pointer_description(FILE *file, const attr_t *attrs,
634 const type_t *type, int ptr_level,
635 const expr_t *array, int level,
636 size_t typestring_offset)
641 /* don't generate a pointer for first-level arrays since we want to
642 * descend into them to write their pointers, not stop here */
643 if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array))
645 return write_pointer_description(file, NULL, type, 0, NULL,
646 level + 1, typestring_offset);
651 /* FIXME: only general algorithm implemented, not the actual writing */
652 error("write_pointer_description: Writing pointer description is unimplemented\n");
656 /* FIXME: search through all refs for pointers too */
660 /* note: don't descend into complex structures or unions since these
661 * will always be generated as a separate type */
663 case RPC_FC_CVSTRUCT:
664 case RPC_FC_CPSTRUCT:
669 while (NEXT_LINK(v)) v = NEXT_LINK(v);
670 for (; v; v = PREV_LINK(v))
671 size += write_pointer_description(file, v->attrs, v->type,
672 v->ptr_level, v->array,
686 static size_t write_string_tfs(FILE *file, const attr_t *attrs,
687 const type_t *type, const expr_t *array,
688 const char *name, size_t *typestring_offset)
690 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
691 int has_size = size_is && (size_is->type != EXPR_VOID);
692 size_t start_offset = *typestring_offset;
694 if ((type->type != RPC_FC_BYTE) && (type->type != RPC_FC_CHAR) && (type->type != RPC_FC_WCHAR))
696 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", type->type, name);
700 if (array && array->is_const)
702 if (array->cval > USHRT_MAX)
703 error("array size for parameter %s exceeds %d bytes by %ld bytes\n",
704 name, USHRT_MAX, array->cval - USHRT_MAX);
706 if (type->type == RPC_FC_CHAR)
707 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
709 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
710 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
711 *typestring_offset += 2;
713 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", array->cval, array->cval);
714 *typestring_offset += 2;
720 if (type->type == RPC_FC_CHAR)
721 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
723 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
724 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
725 *typestring_offset += 2;
727 *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, size_is);
733 if (type->type == RPC_FC_CHAR)
734 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
736 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
737 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
738 *typestring_offset += 2;
744 static size_t write_array_tfs(FILE *file, const attr_t *attrs,
745 const type_t *type, const expr_t *array,
746 const char *name, size_t *typestring_offset)
748 const expr_t *length_is = get_attrp(attrs, ATTR_LENGTHIS);
749 const expr_t *size_is = get_attrp(attrs, ATTR_SIZEIS);
750 int has_length = length_is && (length_is->type != EXPR_VOID);
751 int has_size = (size_is && (size_is->type != EXPR_VOID)) || !array->is_const;
754 if (array && NEXT_LINK(array)) /* multi-dimensional array */
756 error("write_array_tfs: Multi-dimensional arrays not implemented yet (param %s)\n", name);
761 size_t pointer_start_offset = *typestring_offset;
764 if (write_pointers(file, attrs, type, 0, array, 0, typestring_offset) > 0)
767 start_offset = *typestring_offset;
769 if (!has_length && !has_size)
772 size_t size = type_memsize(type, 0, array);
773 if (size < USHRT_MAX)
775 WRITE_FCTYPE(file, FC_SMFARRAY, *typestring_offset);
777 print_file(file, 2, "0x%x, /* 0 */\n", 0);
779 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", size, size);
780 *typestring_offset += 4;
784 WRITE_FCTYPE(file, FC_LGFARRAY, *typestring_offset);
786 print_file(file, 2, "0x%x, /* 0 */\n", 0);
788 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", size, size);
789 *typestring_offset += 6;
794 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
795 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
796 *typestring_offset += 2;
797 *typestring_offset = write_pointer_description(file, attrs,
798 type, 0, array, 0, pointer_start_offset);
799 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
800 *typestring_offset += 1;
803 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
804 print_file(file, 2, "FC_END,\n");
805 *typestring_offset += 2;
809 else if (has_length && !has_size)
812 size_t element_size = type_memsize(type, 0, NULL);
813 size_t elements = array->cval;
814 size_t total_size = element_size * elements;
816 if (total_size < USHRT_MAX)
818 WRITE_FCTYPE(file, FC_SMVARRAY, *typestring_offset);
820 print_file(file, 2, "0x%x, /* 0 */\n", 0);
822 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", total_size, total_size);
823 /* number of elements */
824 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", elements, elements);
825 *typestring_offset += 6;
829 WRITE_FCTYPE(file, FC_LGVARRAY, *typestring_offset);
831 print_file(file, 2, "0x%x, /* 0 */\n", 0);
833 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", total_size, total_size);
834 /* number of elements */
835 print_file(file, 2, "NdrFcLong(0x%x), /* %d */\n", elements, elements);
836 *typestring_offset += 10;
839 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
840 *typestring_offset += 2;
842 *typestring_offset += write_conf_or_var_desc(file, current_func,
848 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
849 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
850 *typestring_offset += 2;
851 *typestring_offset += write_pointer_description(file, attrs,
852 type, 0, array, 0, pointer_start_offset);
853 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
854 *typestring_offset += 1;
857 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
858 print_file(file, 2, "FC_END,\n");
859 *typestring_offset += 2;
863 else if (!has_length && has_size)
865 /* conformant array */
866 size_t element_size = type_memsize(type, 0, NULL);
868 WRITE_FCTYPE(file, FC_CARRAY, *typestring_offset);
870 print_file(file, 2, "0x%x, /* 0 */\n", 0);
872 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
873 *typestring_offset += 4;
875 *typestring_offset += write_conf_or_var_desc(file, current_func,
877 size_is ? size_is : array);
881 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
882 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
883 *typestring_offset += 2;
884 *typestring_offset += write_pointer_description(file, attrs,
885 type, 0, array, 0, pointer_start_offset);
886 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
887 *typestring_offset += 1;
890 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
891 print_file(file, 2, "FC_END,\n");
892 *typestring_offset += 2;
898 /* conformant varying array */
899 size_t element_size = type_memsize(type, 0, NULL);
901 WRITE_FCTYPE(file, FC_CVARRAY, *typestring_offset);
903 print_file(file, 2, "0x%x, /* 0 */\n", 0);
905 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", element_size, element_size);
906 *typestring_offset += 4;
908 *typestring_offset += write_conf_or_var_desc(file, current_func,
910 size_is ? size_is : array);
911 *typestring_offset += write_conf_or_var_desc(file, current_func,
917 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
918 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
919 *typestring_offset += 2;
920 *typestring_offset += write_pointer_description(file, attrs,
921 type, 0, array, 0, pointer_start_offset);
922 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
923 *typestring_offset += 1;
926 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
927 print_file(file, 2, "FC_END,\n");
928 *typestring_offset += 2;
935 static const var_t *find_array_or_string_in_struct(const type_t *type)
937 /* last field is the first in the fields linked list */
938 const var_t *last_field = type->fields;
939 if (is_array_type(last_field->attrs, last_field->ptr_level, last_field->array))
942 assert((last_field->type->type == RPC_FC_CSTRUCT) ||
943 (last_field->type->type == RPC_FC_CPSTRUCT) ||
944 (last_field->type->type == RPC_FC_CVSTRUCT));
946 return find_array_or_string_in_struct(last_field->type);
949 static size_t write_struct_tfs(FILE *file, const type_t *type,
950 const char *name, size_t *typestring_offset)
956 size_t pointer_offset;
962 total_size = type_memsize(type, 0, NULL);
964 if (total_size > USHRT_MAX)
965 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
966 name, USHRT_MAX, total_size - USHRT_MAX);
968 if (type->type == RPC_FC_PSTRUCT)
970 pointer_offset = *typestring_offset;
971 write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset);
973 else pointer_offset = 0; /* silence warning */
975 start_offset = *typestring_offset;
976 if (type->type == RPC_FC_STRUCT)
977 WRITE_FCTYPE(file, FC_STRUCT, *typestring_offset);
979 WRITE_FCTYPE(file, FC_PSTRUCT, *typestring_offset);
981 print_file(file, 2, "0x0,\n");
983 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
984 *typestring_offset += 4;
986 if (type->type == RPC_FC_PSTRUCT)
988 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
989 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
990 *typestring_offset += 2;
991 *typestring_offset += write_pointer_description(file, NULL,
992 type, 0, NULL, 0, pointer_offset);
993 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
994 *typestring_offset += 1;
998 print_file(file, 2, "0x0, /* FIXME: write out conversion data */\n");
999 print_file(file, 2, "FC_END,\n");
1001 *typestring_offset += 2;
1002 return start_offset;
1003 case RPC_FC_CSTRUCT:
1004 case RPC_FC_CPSTRUCT:
1005 total_size = type_memsize(type, 0, NULL);
1007 if (total_size > USHRT_MAX)
1008 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1009 name, USHRT_MAX, total_size - USHRT_MAX);
1011 array = find_array_or_string_in_struct(type);
1012 current_structure = type;
1013 array_offset = write_array_tfs(file, array->attrs, array->type,
1014 array->array, array->name,
1016 current_structure = NULL;
1018 if (type->type == RPC_FC_CPSTRUCT)
1020 pointer_offset = *typestring_offset;
1021 write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset);
1023 else pointer_offset = 0; /* silence warning */
1025 start_offset = *typestring_offset;
1026 if (type->type == RPC_FC_CSTRUCT)
1027 WRITE_FCTYPE(file, FC_CSTRUCT, *typestring_offset);
1029 WRITE_FCTYPE(file, FC_CPSTRUCT, *typestring_offset);
1031 print_file(file, 2, "0x0,\n");
1033 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
1034 *typestring_offset += 4;
1035 print_file(file, 2, "NdrShort(0x%x), /* offset = %d (%u) */\n",
1036 array_offset - *typestring_offset,
1037 array_offset - *typestring_offset,
1039 *typestring_offset += 2;
1041 if (type->type == RPC_FC_CPSTRUCT)
1043 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1044 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1045 *typestring_offset += 2;
1046 *typestring_offset += write_pointer_description(file, NULL,
1047 type, 0, NULL, 0, pointer_offset);
1048 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1049 *typestring_offset += 1;
1052 print_file(file, 2, "FC_END,\n");
1053 *typestring_offset += 1;
1055 return start_offset;
1056 case RPC_FC_CVSTRUCT:
1057 total_size = type_memsize(type, 0, NULL);
1059 if (total_size > USHRT_MAX)
1060 error("structure size for parameter %s exceeds %d bytes by %d bytes\n",
1061 name, USHRT_MAX, total_size - USHRT_MAX);
1063 array = find_array_or_string_in_struct(type);
1064 current_structure = type;
1065 if (is_attr(array->attrs, ATTR_STRING))
1066 array_offset = write_string_tfs(file, array->attrs, array->type,
1067 array->array, array->name,
1070 array_offset = write_array_tfs(file, array->attrs, array->type,
1071 array->array, array->name,
1073 current_structure = NULL;
1075 pointer_offset = *typestring_offset;
1076 if (!write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset))
1079 start_offset = *typestring_offset;
1080 WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset);
1082 print_file(file, 2, "0x0,\n");
1084 print_file(file, 2, "NdrShort(0x%x), /* %u */\n", total_size, total_size);
1085 *typestring_offset += 4;
1086 print_file(file, 2, "NdrShort(0x%x), /* offset = %d (%u) */\n",
1087 array_offset - *typestring_offset,
1088 array_offset - *typestring_offset,
1090 *typestring_offset += 2;
1092 if (pointer_offset != 0)
1094 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1095 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1096 *typestring_offset += 2;
1097 *typestring_offset += write_pointer_description(file, NULL,
1098 type, 0, NULL, 0, pointer_offset);
1099 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1100 *typestring_offset += 1;
1103 print_file(file, 2, "FC_END,\n");
1104 *typestring_offset += 1;
1106 return start_offset;
1108 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
1109 return *typestring_offset;
1113 static void write_pointer_only_tfs(FILE *file, const attr_t *attrs, size_t offset, size_t *typeformat_offset)
1115 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1116 if (!pointer_type) pointer_type = RPC_FC_RP;
1118 print_file(file, 2, "0x%x, 0x00, /* %s */\n",
1120 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"));
1121 print_file(file, 2, "NdrShort(0x%x), /* %d */\n", offset, offset);
1122 *typeformat_offset += 4;
1125 static size_t write_union_tfs(FILE *file, const attr_t *attrs,
1126 const type_t *type, const char *name,
1127 size_t *typeformat_offset)
1129 error("write_union_tfs: Unimplemented\n");
1130 return *typeformat_offset;
1133 static size_t write_typeformatstring_var(FILE *file, int indent,
1134 const var_t *var, size_t *typeformat_offset)
1136 const type_t *type = var->type;
1137 int ptr_level = var->ptr_level;
1141 if (is_string_type(var->attrs, ptr_level, var->array))
1142 return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
1144 if (is_array_type(var->attrs, ptr_level, var->array))
1145 return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset);
1149 /* follow reference if the type has one */
1150 if (type_has_ref(type))
1153 /* FIXME: get new ptr_level from type */
1157 /* basic types don't need a type format string */
1158 if (is_base_type(type->type))
1164 case RPC_FC_PSTRUCT:
1165 case RPC_FC_CSTRUCT:
1166 case RPC_FC_CPSTRUCT:
1167 case RPC_FC_CVSTRUCT:
1168 case RPC_FC_BOGUS_STRUCT:
1169 return write_struct_tfs(file, type, var->name, typeformat_offset);
1170 case RPC_FC_ENCAPSULATED_UNION:
1171 case RPC_FC_NON_ENCAPSULATED_UNION:
1172 return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset);
1174 case RPC_FC_BIND_PRIMITIVE:
1178 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
1181 else if (ptr_level == 1 && !type_has_ref(type))
1183 size_t start_offset = *typeformat_offset;
1184 int pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
1185 if (!pointer_type) pointer_type = RPC_FC_RP;
1187 /* special case for pointers to base types */
1190 #define CASE_BASETYPE(fctype) \
1191 case RPC_##fctype: \
1192 print_file(file, indent, "0x%x, 0x08, /* %s [simple_pointer] */\n", \
1194 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP")); \
1195 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
1196 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
1197 *typeformat_offset += 4; \
1199 CASE_BASETYPE(FC_BYTE);
1200 CASE_BASETYPE(FC_CHAR);
1201 CASE_BASETYPE(FC_SMALL);
1202 CASE_BASETYPE(FC_USMALL);
1203 CASE_BASETYPE(FC_WCHAR);
1204 CASE_BASETYPE(FC_SHORT);
1205 CASE_BASETYPE(FC_USHORT);
1206 CASE_BASETYPE(FC_LONG);
1207 CASE_BASETYPE(FC_ULONG);
1208 CASE_BASETYPE(FC_FLOAT);
1209 CASE_BASETYPE(FC_HYPER);
1210 CASE_BASETYPE(FC_DOUBLE);
1211 CASE_BASETYPE(FC_ENUM16);
1212 CASE_BASETYPE(FC_ENUM32);
1213 CASE_BASETYPE(FC_IGNORE);
1214 CASE_BASETYPE(FC_ERROR_STATUS_T);
1220 assert(ptr_level > 0);
1223 fprintf(file, "/* %2u */\n", *typeformat_offset);
1224 write_pointer_only_tfs(file, var->attrs, 2, typeformat_offset);
1231 void write_typeformatstring(FILE *file, type_t *iface)
1235 size_t typeformat_offset;
1237 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1238 print_file(file, indent, "{\n");
1240 print_file(file, indent, "0,\n");
1241 print_file(file, indent, "{\n");
1243 print_file(file, indent, "NdrFcShort(0x0),\n");
1244 typeformat_offset = 2;
1248 func_t *func = iface->funcs;
1249 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1250 for (; func; func = PREV_LINK(func))
1252 current_func = func;
1256 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1259 write_typeformatstring_var(file, indent, var,
1260 &typeformat_offset);
1261 var = PREV_LINK(var);
1267 print_file(file, indent, "0x0\n");
1269 print_file(file, indent, "}\n");
1271 print_file(file, indent, "};\n");
1272 print_file(file, indent, "\n");
1275 static unsigned int get_required_buffer_size_type(
1276 const type_t *type, int ptr_level, const expr_t *array,
1277 const char *name, unsigned int *alignment)
1280 if (ptr_level == 0 && !array && !type_has_ref(type))
1300 case RPC_FC_ERROR_STATUS_T:
1310 case RPC_FC_BIND_PRIMITIVE:
1317 for (field = type->fields; field; field = NEXT_LINK(field))
1319 unsigned int alignment;
1320 size += get_required_buffer_size_type(
1321 field->type, field->ptr_level, field->array, field->name,
1328 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1332 if (ptr_level == 0 && type_has_ref(type))
1333 return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
1337 unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
1339 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
1342 static inline const char *function_from_phase(enum remoting_phase phase)
1346 case PHASE_BUFFERSIZE:
1347 return "BufferSize";
1350 case PHASE_UNMARSHAL:
1351 return "Unmarshall";
1358 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
1359 unsigned int *type_offset, enum pass pass,
1360 enum remoting_phase phase)
1368 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1369 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
1371 int in_attr = is_attr(var->attrs, ATTR_IN);
1372 int out_attr = is_attr(var->attrs, ATTR_OUT);
1374 if (!in_attr && !out_attr)
1391 if (is_string_type(var->attrs, var->ptr_level, var->array))
1393 if (var->array && var->array->is_const)
1394 print_file(file, indent,
1395 "NdrNonConformantString%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1396 function_from_phase(phase), var->name, *type_offset);
1398 print_file(file, indent,
1399 "NdrConformantString%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1400 function_from_phase(phase), var->name, *type_offset);
1402 else if (is_array_type(var->attrs, var->ptr_level, var->array))
1404 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
1405 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
1406 const char *array_type;
1407 int has_length = length_is && (length_is->type != EXPR_VOID);
1408 int has_size = (size_is && (size_is->type != EXPR_VOID)) || !var->array->is_const;
1410 if (var->array && NEXT_LINK(var->array)) /* multi-dimensional array */
1411 array_type = "ComplexArray";
1414 if (!has_length && !has_size)
1415 array_type = "FixedArray";
1416 else if (has_length && !has_size)
1418 if (phase == PHASE_MARSHAL)
1420 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1421 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1422 write_expr(file, length_is, 1);
1423 fprintf(file, ";\n\n");
1425 array_type = "VaryingArray";
1427 else if (!has_length && has_size)
1429 if (phase == PHASE_MARSHAL)
1431 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1432 write_expr(file, size_is ? size_is : var->array, 1);
1433 fprintf(file, ";\n\n");
1435 array_type = "ConformantArray";
1439 if (phase == PHASE_MARSHAL)
1441 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
1442 write_expr(file, size_is ? size_is : var->array, 1);
1443 fprintf(file, ";\n");
1444 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
1445 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
1446 write_expr(file, length_is, 1);
1447 fprintf(file, ";\n\n");
1449 array_type = "ConformantVaryingArray";
1453 print_file(file, indent,
1454 "Ndr%s%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1455 array_type, function_from_phase(phase), var->name,
1458 else if (var->ptr_level == 0 && is_base_type(var->type->type))
1461 unsigned int alignment = 0;
1462 switch (var->type->type)
1482 case RPC_FC_ERROR_STATUS_T:
1494 case RPC_FC_BIND_PRIMITIVE:
1495 /* no marshalling needed */
1499 error("write_remoting_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
1503 print_file(file, indent, "_StubMsg.Buffer += (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
1504 alignment - 1, alignment - 1);
1506 if (phase == PHASE_MARSHAL)
1508 print_file(file, indent, "*(");
1509 write_type(file, var->type, var, var->tname);
1510 fprintf(file, " *)_StubMsg.Buffer = ");
1511 write_name(file, var);
1512 fprintf(file, ";\n");
1514 else if (phase == PHASE_UNMARSHAL)
1516 print_file(file, indent, "");
1517 write_name(file, var);
1518 fprintf(file, " = *(");
1519 write_type(file, var->type, var, var->tname);
1520 fprintf(file, " *)_StubMsg.Buffer;\n");
1523 error("write_remoting_arguments: Unimplemented for base types for phase %d\n", phase);
1525 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
1526 write_type(file, var->type, var, var->tname);
1527 fprintf(file, ");\n");
1529 else if (var->ptr_level == 0)
1531 const char *ndrtype;
1533 switch (var->type->type)
1536 ndrtype = "SimpleStruct";
1538 case RPC_FC_CSTRUCT:
1539 case RPC_FC_CPSTRUCT:
1540 ndrtype = "ConformantStruct";
1542 case RPC_FC_CVSTRUCT:
1543 ndrtype = "ConformantVaryingStruct";
1545 case RPC_FC_BOGUS_STRUCT:
1546 ndrtype = "ComplexStruct";
1549 error("write_remoting_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
1550 var->name, var->type->type, var->ptr_level);
1554 print_file(file, indent,
1555 "Ndr%s%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1556 ndrtype, function_from_phase(phase), var->name, *type_offset);
1560 print_file(file, indent,
1561 "NdrPointer%s(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
1562 function_from_phase(phase), var->name, *type_offset);
1564 fprintf(file, "\n");
1569 size_t get_size_procformatstring_var(const var_t *var)
1571 unsigned int type_offset = 2;
1572 return write_procformatstring_var(NULL, 0, var, FALSE, &type_offset);
1576 size_t get_size_typeformatstring_var(const var_t *var)
1578 size_t type_offset = 0;
1579 write_typeformatstring_var(NULL, 0, var, &type_offset);
1583 size_t get_size_procformatstring(const type_t *iface)
1591 func = iface->funcs;
1592 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1595 /* argument list size */
1599 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1602 size += get_size_procformatstring_var(var);
1603 var = PREV_LINK(var);
1607 /* return value size */
1608 size += 2; /* FIXME: determine real size */
1609 func = PREV_LINK(func);
1615 size_t get_size_typeformatstring(const type_t *iface)
1623 func = iface->funcs;
1624 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1627 /* argument list size */
1631 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1634 size += get_size_typeformatstring_var(var);
1635 var = PREV_LINK(var);
1639 func = PREV_LINK(func);
1645 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
1646 const var_t *fields, const char *structvar)
1652 fprintf(h, "%ld", e->u.lval);
1655 fprintf(h, "0x%lx", e->u.lval);
1657 case EXPR_IDENTIFIER:
1660 for (field = fields; field; field = NEXT_LINK(field))
1662 if (!strcmp(e->u.sval, field->name))
1664 fprintf(h, "%s->%s", structvar, e->u.sval);
1668 if (!field) error("no field found for identifier %s\n", e->u.sval);
1673 write_struct_expr(h, e->ref, 1, fields, structvar);
1677 write_struct_expr(h, e->ref, 1, fields, structvar);
1681 write_struct_expr(h, e->ref, 1, fields, structvar);
1685 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
1687 write_struct_expr(h, e->ref, 1, fields, structvar);
1690 fprintf(h, "sizeof(");
1691 write_type(h, e->u.tref->ref, NULL, e->u.tref->name);
1702 if (brackets) fprintf(h, "(");
1703 write_struct_expr(h, e->ref, 1, fields, structvar);
1705 case EXPR_SHL: fprintf(h, " << "); break;
1706 case EXPR_SHR: fprintf(h, " >> "); break;
1707 case EXPR_MUL: fprintf(h, " * "); break;
1708 case EXPR_DIV: fprintf(h, " / "); break;
1709 case EXPR_ADD: fprintf(h, " + "); break;
1710 case EXPR_SUB: fprintf(h, " - "); break;
1711 case EXPR_AND: fprintf(h, " & "); break;
1712 case EXPR_OR: fprintf(h, " | "); break;
1715 write_struct_expr(h, e->u.ext, 1, fields, structvar);
1716 if (brackets) fprintf(h, ")");
1719 if (brackets) fprintf(h, "(");
1720 write_struct_expr(h, e->ref, 1, fields, structvar);
1722 write_struct_expr(h, e->u.ext, 1, fields, structvar);
1724 write_struct_expr(h, e->ext2, 1, fields, structvar);
1725 if (brackets) fprintf(h, ")");
1730 int write_expr_eval_routines(FILE *file, const char *iface)
1733 struct expr_eval_routine *eval;
1734 unsigned short callback_offset = 0;
1736 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
1740 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
1741 iface, eval->structure->name, callback_offset);
1742 print_file(file, indent, "{\n");
1744 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
1745 eval->structure->name, eval->structure->name, eval->structure_size);
1746 fprintf(file, "\n");
1747 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
1748 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
1749 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
1750 fprintf(file, ";\n");
1752 print_file(file, indent, "}\n\n");
1758 void write_expr_eval_routine_list(FILE *file, const char *iface)
1760 struct expr_eval_routine *eval;
1761 struct expr_eval_routine *cursor;
1762 unsigned short callback_offset = 0;
1764 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
1765 fprintf(file, "{\n");
1767 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
1769 print_file(file, 1, "%s_%sExprEval_%04u,\n",
1770 iface, eval->structure->name, callback_offset);
1773 list_remove(&eval->entry);
1777 fprintf(file, "};\n\n");