2 * Format String Generator for IDL Compiler
4 * Copyright 2005 Eric Kohl
5 * Copyright 2005 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"
44 static size_t get_size_typeformatstring_type(const type_t *type, int ptr_level,
45 const expr_t *array, const char *name);
47 static int print_file(FILE *file, int indent, const char *format, ...)
55 for (i = 0; i < indent; i++)
57 r = vfprintf(file, format, va);
62 static inline int type_has_ref(const type_t *type)
64 return (type->type == 0 && type->ref);
67 static inline int is_base_type(unsigned char type)
86 case RPC_FC_ERROR_STATUS_T:
94 static size_t write_procformatstring_type(FILE *file, int indent,
95 const type_t *type, int ptr_level, const expr_t *array, const char *name,
96 int is_in, int is_out, int is_return, unsigned int *type_offset)
100 if (ptr_level == 0 && type_has_ref(type))
101 return write_procformatstring_type(file, indent, type->ref, ptr_level,
102 array, name, is_in, is_out,
103 is_return, type_offset);
105 if (ptr_level == 0 && !array && is_base_type(type->type))
108 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
110 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
114 #define CASE_BASETYPE(fctype) \
116 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
117 size = 2; /* includes param type prefix */ \
120 CASE_BASETYPE(FC_BYTE);
121 CASE_BASETYPE(FC_CHAR);
122 CASE_BASETYPE(FC_WCHAR);
123 CASE_BASETYPE(FC_USHORT);
124 CASE_BASETYPE(FC_SHORT);
125 CASE_BASETYPE(FC_ULONG);
126 CASE_BASETYPE(FC_LONG);
127 CASE_BASETYPE(FC_HYPER);
128 CASE_BASETYPE(FC_IGNORE);
129 CASE_BASETYPE(FC_USMALL);
130 CASE_BASETYPE(FC_SMALL);
131 CASE_BASETYPE(FC_FLOAT);
132 CASE_BASETYPE(FC_DOUBLE);
133 CASE_BASETYPE(FC_ERROR_STATUS_T);
136 error("Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
143 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
144 else if (is_in && is_out)
145 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
147 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
149 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
151 print_file(file, indent, "0x01,\n");
152 print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
153 size = 4; /* includes param type prefix */
155 *type_offset += get_size_typeformatstring_type(type, ptr_level, array, name);
159 void write_procformatstring(FILE *file, type_t *iface)
163 unsigned int type_offset = 2;
165 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
166 print_file(file, indent, "{\n");
168 print_file(file, indent, "0,\n");
169 print_file(file, indent, "{\n");
174 func_t *func = iface->funcs;
175 while (NEXT_LINK(func)) func = NEXT_LINK(func);
176 for (; func; func = PREV_LINK(func))
178 /* emit argument data */
182 while (NEXT_LINK(var)) var = NEXT_LINK(var);
185 int is_in = is_attr(var->attrs, ATTR_IN);
186 int is_out = is_attr(var->attrs, ATTR_OUT);
188 if (!is_in && !is_out) is_in = TRUE;
189 write_procformatstring_type(file, indent, var->type,
190 var->ptr_level, var->array, var->name,
191 is_in, is_out, FALSE, &type_offset);
193 var = PREV_LINK(var);
197 /* emit return value data */
199 if (is_void(var->type, NULL))
201 print_file(file, indent, "0x5b, /* FC_END */\n");
202 print_file(file, indent, "0x5c, /* FC_PAD */\n");
205 write_procformatstring_type(file, indent, var->type,
206 var->ptr_level, var->array, var->name, FALSE, FALSE, TRUE,
211 print_file(file, indent, "0x0\n");
213 print_file(file, indent, "}\n");
215 print_file(file, indent, "};\n");
216 print_file(file, indent, "\n");
220 static size_t write_typeformatstring_type(FILE *file, int indent,
221 const type_t *type, int ptr_level, const expr_t *array, const char *name)
223 if (ptr_level == 0 && type_has_ref(type))
224 return write_typeformatstring_type(file, indent,
225 type->ref, 0 /* FIXME */, array, name);
227 /* basic types don't need a type format string */
228 if (ptr_level == 0 && !array && is_base_type(type->type))
231 if ((ptr_level == 1 && !type_has_ref(type)) ||
232 (ptr_level == 0 && array && !NEXT_LINK(array)))
236 #define CASE_BASETYPE(fctype) \
238 print_file(file, indent, "0x11, 0x08, /* FC_RP [simple_pointer] */\n"); \
239 print_file(file, indent, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
240 print_file(file, indent, "0x5c, /* FC_PAD */\n"); \
242 CASE_BASETYPE(FC_BYTE);
243 CASE_BASETYPE(FC_CHAR);
244 CASE_BASETYPE(FC_SMALL);
245 CASE_BASETYPE(FC_USMALL);
246 CASE_BASETYPE(FC_WCHAR);
247 CASE_BASETYPE(FC_SHORT);
248 CASE_BASETYPE(FC_USHORT);
249 CASE_BASETYPE(FC_LONG);
250 CASE_BASETYPE(FC_ULONG);
251 CASE_BASETYPE(FC_FLOAT);
252 CASE_BASETYPE(FC_HYPER);
253 CASE_BASETYPE(FC_DOUBLE);
254 CASE_BASETYPE(FC_ENUM16);
255 CASE_BASETYPE(FC_ENUM32);
256 CASE_BASETYPE(FC_IGNORE);
257 CASE_BASETYPE(FC_ERROR_STATUS_T);
259 error("write_typeformatstring_var: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
262 error("write_typeformatstring_var: Pointer level %d not supported for variable %s\n", ptr_level, name);
267 void write_typeformatstring(FILE *file, type_t *iface)
272 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
273 print_file(file, indent, "{\n");
275 print_file(file, indent, "0,\n");
276 print_file(file, indent, "{\n");
278 print_file(file, indent, "NdrFcShort(0x0),\n");
282 func_t *func = iface->funcs;
283 while (NEXT_LINK(func)) func = NEXT_LINK(func);
284 for (; func; func = PREV_LINK(func))
289 while (NEXT_LINK(var)) var = NEXT_LINK(var);
292 write_typeformatstring_type(file, indent, var->type,
293 var->ptr_level, var->array, var->name);
294 var = PREV_LINK(var);
300 print_file(file, indent, "0x0\n");
302 print_file(file, indent, "}\n");
304 print_file(file, indent, "};\n");
305 print_file(file, indent, "\n");
308 static unsigned int get_required_buffer_size_type(
309 const type_t *type, int ptr_level, const expr_t *array,
310 const char *name, unsigned int *alignment)
313 if (ptr_level == 0 && !array && !type_has_ref(type))
332 case RPC_FC_ERROR_STATUS_T:
345 for (field = type->fields; field; field = NEXT_LINK(field))
347 unsigned int alignment;
348 size += get_required_buffer_size_type(
349 field->type, field->ptr_level, field->array, field->name,
356 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
360 if (ptr_level == 0 && type_has_ref(type))
361 return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
365 unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
367 return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
370 void marshall_arguments(FILE *file, int indent, func_t *func,
371 unsigned int *type_offset, enum pass pass)
373 unsigned int last_size = 0;
380 while (NEXT_LINK(var)) var = NEXT_LINK(var);
381 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
383 int in_attr = is_attr(var->attrs, ATTR_IN);
384 int out_attr = is_attr(var->attrs, ATTR_OUT);
386 if (!in_attr && !out_attr)
403 if (var->ptr_level == 0 && !var->array)
406 unsigned int alignment = 0;
407 switch (var->type->type)
421 if (last_size != 0 && last_size < 2)
422 alignment = (2 - last_size);
428 case RPC_FC_ERROR_STATUS_T:
430 if (last_size != 0 && last_size < 4)
431 alignment = (4 - last_size);
437 if (last_size != 0 && last_size < 4)
438 alignment = (4 - last_size);
442 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
447 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
449 print_file(file, indent, "*(");
450 write_type(file, var->type, var, var->tname);
451 fprintf(file, " *)_StubMsg.Buffer = ");
452 write_name(file, var);
453 fprintf(file, ";\n");
454 fprintf(file, "_StubMsg.Buffer += sizeof(");
455 write_type(file, var->type, var, var->tname);
456 fprintf(file, ");\n");
460 else if ((var->ptr_level == 1 && !var->array) ||
461 (var->ptr_level == 0 && var->array))
463 if (is_attr(var->attrs, ATTR_STRING))
465 switch (var->type->type)
469 print_file(file, indent,
470 "NdrConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
471 var->name, *type_offset);
474 error("marshall_arguments: Unsupported [string] type: %s (0x%02x, ptr_level: 1)\n", var->name, var->type->type);
479 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
480 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
481 const char *array_type;
482 int has_length = length_is && (length_is->type != EXPR_VOID);
483 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
485 if (NEXT_LINK(var->array)) /* multi-dimensional array */
486 array_type = "ComplexArray";
489 if (!has_length && !has_size)
490 array_type = "FixedArray";
491 else if (has_length && !has_size)
493 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
494 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
495 write_expr(file, length_is, 1);
496 fprintf(file, ";\n\n");
497 array_type = "VaryingArray";
499 else if (!has_length && has_size)
501 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
502 write_expr(file, size_is ? size_is : var->array, 1);
503 fprintf(file, ";\n\n");
504 array_type = "ConformantArray";
508 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
509 write_expr(file, size_is ? size_is : var->array, 1);
510 fprintf(file, ";\n");
511 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
512 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
513 write_expr(file, length_is, 1);
514 fprintf(file, ";\n\n");
515 array_type = "ConformantVaryingArray";
519 print_file(file, indent,
520 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
521 array_type, var->name, *type_offset);
527 switch (var->type->type)
530 ndrtype = "SimpleStruct";
533 case RPC_FC_CPSTRUCT:
534 ndrtype = "ConformantStruct";
536 case RPC_FC_CVSTRUCT:
537 ndrtype = "ConformantVaryingStruct";
539 case RPC_FC_BOGUS_STRUCT:
540 ndrtype = "ComplexStruct";
543 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
544 var->name, var->type->type, var->ptr_level);
548 print_file(file, indent,
549 "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
550 ndrtype, var->name, *type_offset);
556 error("marshall_arguments: Pointer level %d not supported for variable %s\n", var->ptr_level, var->name);
563 void unmarshall_arguments(FILE *file, int indent, func_t *func,
564 unsigned int *type_offset, enum pass pass)
566 unsigned int last_size = 0;
573 while (NEXT_LINK(var)) var = NEXT_LINK(var);
574 for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
576 int in_attr = is_attr(var->attrs, ATTR_IN);
577 int out_attr = is_attr(var->attrs, ATTR_OUT);
579 if (!in_attr && !out_attr)
596 if (var->ptr_level == 0 && !var->array)
599 unsigned int alignment = 0;
601 switch (var->type->type)
615 if (last_size != 0 && last_size < 2)
616 alignment = (2 - last_size);
622 case RPC_FC_ERROR_STATUS_T:
624 if (last_size != 0 && last_size < 4)
625 alignment = (4 - last_size);
631 if (last_size != 0 && last_size < 4)
632 alignment = (4 - last_size);
636 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
641 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
643 print_file(file, indent, "");
644 write_name(file, var);
645 fprintf(file, " = *(");
646 write_type(file, var->type, var, var->tname);
647 fprintf(file, " *)_StubMsg.Buffer;\n");
648 fprintf(file, "_StubMsg.Buffer += sizeof(");
649 write_type(file, var->type, var, var->tname);
650 fprintf(file, ");\n");
654 else if ((var->ptr_level == 1 && !var->array) ||
655 (var->ptr_level == 0 && var->array))
657 if (is_attr(var->attrs, ATTR_STRING))
659 switch (var->type->type)
663 print_file(file, indent,
664 "NdrConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
665 var->name, *type_offset);
668 error("unmarshall_arguments: Unsupported [string] type: %s (0x%02x, ptr_level: %d)\n",
669 var->name, var->type->type, var->ptr_level);
674 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
675 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
676 const char *array_type;
677 int has_length = length_is && (length_is->type != EXPR_VOID);
678 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
680 if (NEXT_LINK(var->array)) /* multi-dimensional array */
681 array_type = "ComplexArray";
684 if (!has_length && !has_size)
685 array_type = "FixedArray";
686 else if (has_length && !has_size)
687 array_type = "VaryingArray";
688 else if (!has_length && has_size)
689 array_type = "ConformantArray";
691 array_type = "ConformantVaryingArray";
694 print_file(file, indent,
695 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
696 array_type, var->name, *type_offset);
702 switch (var->type->type)
705 ndrtype = "SimpleStruct";
708 case RPC_FC_CPSTRUCT:
709 ndrtype = "ConformantStruct";
711 case RPC_FC_CVSTRUCT:
712 ndrtype = "ConformantVaryingStruct";
714 case RPC_FC_BOGUS_STRUCT:
715 ndrtype = "ComplexStruct";
718 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
719 var->name, var->type->type, var->ptr_level);
723 print_file(file, indent,
724 "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
725 ndrtype, var->name, *type_offset);
731 error("unmarshall_arguments: Pointer level %d not supported for variable %s\n", var->ptr_level, var->name);
739 static size_t get_size_typeformatstring_type(const type_t *type, int ptr_level,
740 const expr_t *array, const char *name)
742 return write_typeformatstring_type(NULL, 0, type, ptr_level, array, name);
746 size_t get_size_procformatstring_var(var_t *var)
748 unsigned int type_offset = 2;
749 return write_procformatstring_type(NULL, 0, var->type,
750 var->ptr_level, var->array, var->name, FALSE, FALSE, FALSE, &type_offset);
754 size_t get_size_typeformatstring_var(var_t *var)
756 return write_typeformatstring_type(NULL, 0, var->type, var->ptr_level,
757 var->array, var->name);