cmd.exe: Pass the command list through so it is available to built in commands.
[wine.git] / tools / widl / typegen.c
bloba1e4e6da11f7e96ac717e7fe82ef826de33967cc
1 /*
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
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <string.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <signal.h>
34 #include <limits.h>
36 #include "widl.h"
37 #include "utils.h"
38 #include "parser.h"
39 #include "header.h"
40 #include "windef.h"
41 #include "wine/list.h"
43 #include "widl.h"
44 #include "typegen.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
56 struct list entry;
57 const type_t *structure;
58 size_t structure_size;
59 const expr_t *expr;
62 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
63 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
64 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
65 const char *name, int write_ptr, unsigned int *tfsoff);
67 const char *string_of_type(unsigned char type)
69 switch (type)
71 case RPC_FC_BYTE: return "FC_BYTE";
72 case RPC_FC_CHAR: return "FC_CHAR";
73 case RPC_FC_SMALL: return "FC_SMALL";
74 case RPC_FC_USMALL: return "FC_USMALL";
75 case RPC_FC_WCHAR: return "FC_WCHAR";
76 case RPC_FC_SHORT: return "FC_SHORT";
77 case RPC_FC_USHORT: return "FC_USHORT";
78 case RPC_FC_LONG: return "FC_LONG";
79 case RPC_FC_ULONG: return "FC_ULONG";
80 case RPC_FC_FLOAT: return "FC_FLOAT";
81 case RPC_FC_HYPER: return "FC_HYPER";
82 case RPC_FC_DOUBLE: return "FC_DOUBLE";
83 case RPC_FC_ENUM16: return "FC_ENUM16";
84 case RPC_FC_ENUM32: return "FC_ENUM32";
85 case RPC_FC_IGNORE: return "FC_IGNORE";
86 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
87 case RPC_FC_RP: return "FC_RP";
88 case RPC_FC_UP: return "FC_UP";
89 case RPC_FC_OP: return "FC_OP";
90 case RPC_FC_FP: return "FC_FP";
91 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
92 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
93 case RPC_FC_STRUCT: return "FC_STRUCT";
94 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
95 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
96 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
97 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
98 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
99 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
100 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
101 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
102 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
103 case RPC_FC_CARRAY: return "FC_CARRAY";
104 case RPC_FC_CVARRAY: return "FC_CVARRAY";
105 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
106 default:
107 error("string_of_type: unknown type 0x%02x\n", type);
108 return NULL;
112 int is_struct(unsigned char type)
114 switch (type)
116 case RPC_FC_STRUCT:
117 case RPC_FC_PSTRUCT:
118 case RPC_FC_CSTRUCT:
119 case RPC_FC_CPSTRUCT:
120 case RPC_FC_CVSTRUCT:
121 case RPC_FC_BOGUS_STRUCT:
122 return 1;
123 default:
124 return 0;
128 int is_union(unsigned char type)
130 switch (type)
132 case RPC_FC_ENCAPSULATED_UNION:
133 case RPC_FC_NON_ENCAPSULATED_UNION:
134 return 1;
135 default:
136 return 0;
140 static unsigned short user_type_offset(const char *name)
142 user_type_t *ut;
143 unsigned short off = 0;
144 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
146 if (strcmp(name, ut->name) == 0)
147 return off;
148 ++off;
150 error("user_type_offset: couldn't find type (%s)\n", name);
151 return 0;
154 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
156 type->typestring_offset = offset;
157 if (file) type->tfswrite = FALSE;
160 static void guard_rec(type_t *type)
162 /* types that contain references to themselves (like a linked list),
163 need to be shielded from infinite recursion when writing embedded
164 types */
165 if (type->typestring_offset)
166 type->tfswrite = FALSE;
167 else
168 type->typestring_offset = 1;
171 static type_t *get_user_type(const type_t *t, const char **pname)
173 for (;;)
175 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
176 if (ut)
178 if (pname)
179 *pname = t->name;
180 return ut;
183 if (t->kind == TKIND_ALIAS)
184 t = t->orig;
185 else
186 return 0;
190 static int is_user_type(const type_t *t)
192 return get_user_type(t, NULL) != NULL;
195 static int is_embedded_complex(const type_t *type)
197 unsigned char tc = type->type;
198 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
199 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
202 static int compare_expr(const expr_t *a, const expr_t *b)
204 int ret;
206 if (a->type != b->type)
207 return a->type - b->type;
209 switch (a->type)
211 case EXPR_NUM:
212 case EXPR_HEXNUM:
213 case EXPR_TRUEFALSE:
214 return a->u.lval - b->u.lval;
215 case EXPR_IDENTIFIER:
216 return strcmp(a->u.sval, b->u.sval);
217 case EXPR_COND:
218 ret = compare_expr(a->ref, b->ref);
219 if (ret != 0)
220 return ret;
221 ret = compare_expr(a->u.ext, b->u.ext);
222 if (ret != 0)
223 return ret;
224 return compare_expr(a->ext2, b->ext2);
225 case EXPR_OR:
226 case EXPR_AND:
227 case EXPR_ADD:
228 case EXPR_SUB:
229 case EXPR_MUL:
230 case EXPR_DIV:
231 case EXPR_SHL:
232 case EXPR_SHR:
233 ret = compare_expr(a->ref, b->ref);
234 if (ret != 0)
235 return ret;
236 return compare_expr(a->u.ext, b->u.ext);
237 case EXPR_NOT:
238 case EXPR_NEG:
239 case EXPR_PPTR:
240 case EXPR_CAST:
241 case EXPR_SIZEOF:
242 return compare_expr(a->ref, b->ref);
243 case EXPR_VOID:
244 return 0;
246 return -1;
249 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
250 do { \
251 if (file) \
252 fprintf(file, "/* %2u */\n", typestring_offset); \
253 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
255 while (0)
257 static void print_file(FILE *file, int indent, const char *format, ...)
259 va_list va;
260 va_start(va, format);
261 print(file, indent, format, va);
262 va_end(va);
265 void print(FILE *file, int indent, const char *format, va_list va)
267 if (file)
269 if (format[0] != '\n')
270 while (0 < indent--)
271 fprintf(file, " ");
272 vfprintf(file, format, va);
276 void write_parameters_init(FILE *file, int indent, const func_t *func)
278 const var_t *var;
280 if (!func->args)
281 return;
283 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
285 const type_t *t = var->type;
286 const char *n = var->name;
287 if (decl_indirect(t))
288 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
289 else if (is_ptr(t) || is_array(t))
290 print_file(file, indent, "%s = 0;\n", n);
293 fprintf(file, "\n");
296 static void write_formatdesc(FILE *f, int indent, const char *str)
298 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
299 print_file(f, indent, "{\n");
300 print_file(f, indent + 1, "short Pad;\n");
301 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
302 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
303 print_file(f, indent, "\n");
306 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, int for_objects)
308 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
309 get_size_typeformatstring(ifaces, for_objects));
311 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
312 get_size_procformatstring(ifaces, for_objects));
314 fprintf(f, "\n");
315 write_formatdesc(f, indent, "TYPE");
316 write_formatdesc(f, indent, "PROC");
317 fprintf(f, "\n");
318 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
319 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
320 print_file(f, indent, "\n");
323 static inline int is_base_type(unsigned char type)
325 switch (type)
327 case RPC_FC_BYTE:
328 case RPC_FC_CHAR:
329 case RPC_FC_USMALL:
330 case RPC_FC_SMALL:
331 case RPC_FC_WCHAR:
332 case RPC_FC_USHORT:
333 case RPC_FC_SHORT:
334 case RPC_FC_ULONG:
335 case RPC_FC_LONG:
336 case RPC_FC_HYPER:
337 case RPC_FC_IGNORE:
338 case RPC_FC_FLOAT:
339 case RPC_FC_DOUBLE:
340 case RPC_FC_ENUM16:
341 case RPC_FC_ENUM32:
342 case RPC_FC_ERROR_STATUS_T:
343 case RPC_FC_BIND_PRIMITIVE:
344 return TRUE;
346 default:
347 return FALSE;
351 int decl_indirect(const type_t *t)
353 return is_user_type(t)
354 || (!is_base_type(t->type)
355 && !is_ptr(t)
356 && !is_array(t));
359 static size_t write_procformatstring_var(FILE *file, int indent,
360 const var_t *var, int is_return)
362 size_t size;
363 const type_t *type = var->type;
365 int is_in = is_attr(var->attrs, ATTR_IN);
366 int is_out = is_attr(var->attrs, ATTR_OUT);
368 if (!is_in && !is_out) is_in = TRUE;
370 if (!type->declarray && is_base_type(type->type))
372 if (is_return)
373 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
374 else
375 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
377 if (type->type == RPC_FC_BIND_PRIMITIVE)
379 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
380 size = 2; /* includes param type prefix */
382 else if (is_base_type(type->type))
384 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
385 size = 2; /* includes param type prefix */
387 else
389 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
390 size = 0;
393 else
395 if (is_return)
396 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
397 else if (is_in && is_out)
398 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
399 else if (is_out)
400 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
401 else
402 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
404 print_file(file, indent, "0x01,\n");
405 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
406 size = 4; /* includes param type prefix */
408 return size;
411 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
413 const ifref_t *iface;
414 int indent = 0;
415 const var_t *var;
417 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
418 print_file(file, indent, "{\n");
419 indent++;
420 print_file(file, indent, "0,\n");
421 print_file(file, indent, "{\n");
422 indent++;
424 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
426 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
427 continue;
429 if (iface->iface->funcs)
431 const func_t *func;
432 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
434 if (is_local(func->def->attrs)) continue;
435 /* emit argument data */
436 if (func->args)
438 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
439 write_procformatstring_var(file, indent, var, FALSE);
442 /* emit return value data */
443 var = func->def;
444 if (is_void(var->type))
446 print_file(file, indent, "0x5b, /* FC_END */\n");
447 print_file(file, indent, "0x5c, /* FC_PAD */\n");
449 else
450 write_procformatstring_var(file, indent, var, TRUE);
455 print_file(file, indent, "0x0\n");
456 indent--;
457 print_file(file, indent, "}\n");
458 indent--;
459 print_file(file, indent, "};\n");
460 print_file(file, indent, "\n");
463 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
465 if (is_base_type(type->type))
467 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
468 *typestring_offset += 1;
469 return 1;
472 return 0;
475 /* write conformance / variance descriptor */
476 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure,
477 unsigned int baseoff, const expr_t *expr)
479 unsigned char operator_type = 0;
480 const char *operator_string = "no operators";
481 const expr_t *subexpr;
482 unsigned char correlation_type;
484 if (!file) return 4; /* optimisation for sizing pass */
486 if (expr->is_const)
488 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
489 error("write_conf_or_var_desc: constant value %ld is greater than "
490 "the maximum constant size of %d\n", expr->cval,
491 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
493 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
494 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
495 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
496 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
498 return 4;
501 subexpr = expr;
502 switch (subexpr->type)
504 case EXPR_PPTR:
505 subexpr = subexpr->ref;
506 operator_type = RPC_FC_DEREFERENCE;
507 operator_string = "FC_DEREFERENCE";
508 break;
509 case EXPR_DIV:
510 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
512 subexpr = subexpr->ref;
513 operator_type = RPC_FC_DIV_2;
514 operator_string = "FC_DIV_2";
516 break;
517 case EXPR_MUL:
518 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
520 subexpr = subexpr->ref;
521 operator_type = RPC_FC_MULT_2;
522 operator_string = "FC_MULT_2";
524 break;
525 case EXPR_SUB:
526 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
528 subexpr = subexpr->ref;
529 operator_type = RPC_FC_SUB_1;
530 operator_string = "FC_SUB_1";
532 break;
533 case EXPR_ADD:
534 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
536 subexpr = subexpr->ref;
537 operator_type = RPC_FC_ADD_1;
538 operator_string = "FC_ADD_1";
540 break;
541 default:
542 break;
545 if (subexpr->type == EXPR_IDENTIFIER)
547 const type_t *correlation_variable = NULL;
548 unsigned char correlation_variable_type;
549 unsigned char param_type = 0;
550 const char *param_type_string = NULL;
551 size_t offset;
553 if (structure)
555 const var_t *var;
557 offset = 0;
558 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
560 unsigned int align = 0;
561 /* FIXME: take alignment into account */
562 if (!strcmp(var->name, subexpr->u.sval))
564 correlation_variable = var->type;
565 break;
567 offset += type_memsize(var->type, &align);
569 if (!correlation_variable)
570 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
571 subexpr->u.sval);
573 offset -= baseoff;
574 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
576 else
578 const var_t *var;
580 offset = sizeof(void *);
581 if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
583 if (!strcmp(var->name, subexpr->u.sval))
585 correlation_variable = var->type;
586 break;
588 /* FIXME: not all stack variables are sizeof(void *) */
589 offset += sizeof(void *);
591 if (!correlation_variable)
592 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
593 subexpr->u.sval);
595 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
598 correlation_variable_type = correlation_variable->type;
600 switch (correlation_variable_type)
602 case RPC_FC_CHAR:
603 case RPC_FC_SMALL:
604 param_type = RPC_FC_SMALL;
605 param_type_string = "FC_SMALL";
606 break;
607 case RPC_FC_BYTE:
608 case RPC_FC_USMALL:
609 param_type = RPC_FC_USMALL;
610 param_type_string = "FC_USMALL";
611 break;
612 case RPC_FC_WCHAR:
613 case RPC_FC_SHORT:
614 param_type = RPC_FC_SHORT;
615 param_type_string = "FC_SHORT";
616 break;
617 case RPC_FC_USHORT:
618 param_type = RPC_FC_USHORT;
619 param_type_string = "FC_USHORT";
620 break;
621 case RPC_FC_LONG:
622 param_type = RPC_FC_LONG;
623 param_type_string = "FC_LONG";
624 break;
625 case RPC_FC_ULONG:
626 param_type = RPC_FC_ULONG;
627 param_type_string = "FC_ULONG";
628 break;
629 case RPC_FC_RP:
630 case RPC_FC_UP:
631 case RPC_FC_OP:
632 case RPC_FC_FP:
633 if (sizeof(void *) == 4) /* FIXME */
635 param_type = RPC_FC_LONG;
636 param_type_string = "FC_LONG";
638 else
640 param_type = RPC_FC_HYPER;
641 param_type_string = "FC_HYPER";
643 break;
644 default:
645 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
646 correlation_variable_type);
649 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
650 correlation_type | param_type,
651 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
652 param_type_string);
653 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
654 print_file(file, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
655 offset,
656 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
657 offset);
659 else
661 unsigned int callback_offset = 0;
663 if (structure)
665 struct expr_eval_routine *eval;
666 int found = 0;
668 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
670 if (!strcmp(eval->structure->name, structure->name) &&
671 !compare_expr(eval->expr, expr))
673 found = 1;
674 break;
676 callback_offset++;
679 if (!found)
681 unsigned int align = 0;
682 eval = xmalloc(sizeof(*eval));
683 eval->structure = structure;
684 eval->structure_size = fields_memsize(structure->fields, &align);
685 eval->expr = expr;
686 list_add_tail(&expr_eval_routines, &eval->entry);
689 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
691 else
693 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
694 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
697 if (callback_offset > USHRT_MAX)
698 error("Maximum number of callback routines reached\n");
700 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
701 correlation_type,
702 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
703 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
704 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
706 return 4;
709 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
711 size_t size = 0;
712 const var_t *v;
714 if (!fields) return 0;
715 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
716 size += type_memsize(v->type, align);
718 return size;
721 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
723 size_t size, maxs = 0;
724 unsigned int align = *pmaxa;
725 const var_t *v;
727 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
729 /* we could have an empty default field with NULL type */
730 if (v->type)
732 size = type_memsize(v->type, &align);
733 if (maxs < size) maxs = size;
734 if (*pmaxa < align) *pmaxa = align;
738 return maxs;
741 size_t type_memsize(const type_t *t, unsigned int *align)
743 size_t size = 0;
745 if (t->declarray && is_conformant_array(t))
747 type_memsize(t->ref, align);
748 size = 0;
750 else if (is_ptr(t) || is_conformant_array(t))
752 size = sizeof(void *);
753 if (size > *align) *align = size;
755 else switch (t->type)
757 case RPC_FC_BYTE:
758 case RPC_FC_CHAR:
759 case RPC_FC_USMALL:
760 case RPC_FC_SMALL:
761 size = 1;
762 if (size > *align) *align = size;
763 break;
764 case RPC_FC_WCHAR:
765 case RPC_FC_USHORT:
766 case RPC_FC_SHORT:
767 case RPC_FC_ENUM16:
768 size = 2;
769 if (size > *align) *align = size;
770 break;
771 case RPC_FC_ULONG:
772 case RPC_FC_LONG:
773 case RPC_FC_ERROR_STATUS_T:
774 case RPC_FC_ENUM32:
775 case RPC_FC_FLOAT:
776 size = 4;
777 if (size > *align) *align = size;
778 break;
779 case RPC_FC_HYPER:
780 case RPC_FC_DOUBLE:
781 size = 8;
782 if (size > *align) *align = size;
783 break;
784 case RPC_FC_STRUCT:
785 case RPC_FC_CVSTRUCT:
786 case RPC_FC_CPSTRUCT:
787 case RPC_FC_CSTRUCT:
788 case RPC_FC_PSTRUCT:
789 case RPC_FC_BOGUS_STRUCT:
790 size = fields_memsize(t->fields, align);
791 break;
792 case RPC_FC_ENCAPSULATED_UNION:
793 case RPC_FC_NON_ENCAPSULATED_UNION:
794 size = union_memsize(t->fields, align);
795 break;
796 case RPC_FC_SMFARRAY:
797 case RPC_FC_LGFARRAY:
798 case RPC_FC_SMVARRAY:
799 case RPC_FC_LGVARRAY:
800 case RPC_FC_BOGUS_ARRAY:
801 size = t->dim * type_memsize(t->ref, align);
802 break;
803 default:
804 error("type_memsize: Unknown type %d\n", t->type);
805 size = 0;
808 return size;
811 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
813 short absoff = type->ref->typestring_offset;
814 short reloff = absoff - (offset + 2);
815 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
817 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
818 type->type, ptr_attr, string_of_type(type->type));
819 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
820 reloff, reloff, absoff);
821 return 4;
824 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
826 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
827 type->type, string_of_type(type->type));
828 print_file(file, 2, "0x%02x,\t/* %s */\n", type->ref->type,
829 string_of_type(type->ref->type));
830 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
831 return 4;
834 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
836 unsigned int offset = *typestring_offset;
838 print_file(file, 0, "/* %d */\n", offset);
839 update_tfsoff(type, offset, file);
841 if (type->ref->typestring_offset)
842 *typestring_offset += write_nonsimple_pointer(file, type, offset);
843 else if (is_base_type(type->ref->type))
844 *typestring_offset += write_simple_pointer(file, type);
846 return offset;
849 static int processed(const type_t *type)
851 return type->typestring_offset && !type->tfswrite;
854 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
856 unsigned int start, absoff, flags;
857 unsigned int align = 0, ualign = 0;
858 const char *name;
859 type_t *utype = get_user_type(type, &name);
860 size_t usize = type_memsize(utype, &ualign);
861 size_t size = type_memsize(type, &align);
862 unsigned short funoff = user_type_offset(name);
863 short reloff;
865 guard_rec(type);
867 if (is_base_type(utype->type))
869 absoff = *tfsoff;
870 print_file(file, 0, "/* %d */\n", absoff);
871 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
872 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
873 *tfsoff += 2;
875 else
877 if (!processed(utype))
878 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
879 absoff = utype->typestring_offset;
882 if (utype->type == RPC_FC_RP)
883 flags = 0x40;
884 else if (utype->type == RPC_FC_UP)
885 flags = 0x80;
886 else
887 flags = 0;
889 start = *tfsoff;
890 update_tfsoff(type, start, file);
891 print_file(file, 0, "/* %d */\n", start);
892 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
893 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
894 flags | (align - 1), align - 1, flags);
895 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
896 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
897 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
898 *tfsoff += 8;
899 reloff = absoff - *tfsoff;
900 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
901 *tfsoff += 2;
904 static void write_member_type(FILE *file, type_t *type, const var_t *field,
905 unsigned int *corroff, unsigned int *tfsoff)
907 if (is_embedded_complex(type))
909 size_t absoff;
910 short reloff;
912 if (is_union(type->type) && is_attr(field->attrs, ATTR_SWITCHIS))
914 absoff = *corroff;
915 *corroff += 8;
917 else
919 absoff = type->typestring_offset;
921 reloff = absoff - (*tfsoff + 2);
923 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
924 /* FIXME: actually compute necessary padding */
925 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
926 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
927 reloff, reloff, absoff);
928 *tfsoff += 4;
930 else if (is_ptr(type))
932 print_file(file, 2, "0x8,\t/* FC_LONG */\n");
933 *tfsoff += 1;
935 else if (!write_base_type(file, type, tfsoff))
936 error("Unsupported member type 0x%x\n", type->type);
939 static void write_end(FILE *file, unsigned int *tfsoff)
941 if (*tfsoff % 2 == 0)
943 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
944 *tfsoff += 1;
946 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
947 *tfsoff += 1;
950 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
952 unsigned int offset = 0;
953 var_list_t *fs = type->fields;
954 var_t *f;
956 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
958 unsigned int align = 0;
959 type_t *ft = f->type;
960 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
962 unsigned int absoff = ft->typestring_offset;
963 short reloff = absoff - (*tfsoff + 6);
964 print_file(file, 0, "/* %d */\n", *tfsoff);
965 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
966 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
967 write_conf_or_var_desc(file, current_func, current_structure, offset,
968 get_attrp(f->attrs, ATTR_SWITCHIS));
969 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
970 reloff, reloff, absoff);
971 *tfsoff += 8;
974 /* FIXME: take alignment into account */
975 offset += type_memsize(ft, &align);
979 static size_t write_pointer_description(FILE *file, type_t *type, size_t mem_offset,
980 int level, unsigned int *typestring_offset)
982 const var_t *v;
983 unsigned int align = 0;
985 /* don't generate a pointer for first-level arrays since we want to
986 * descend into them to write their pointers, not stop here */
987 if (level == 0 && is_array(type))
989 write_pointer_description(file, type->ref, mem_offset, level + 1,
990 typestring_offset);
992 else if (is_ptr(type))
994 print_file(file, 2, "0x46,\t/* FC_NO_REPEAT */\n");
995 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
996 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset);
997 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset);
998 *typestring_offset += 6;
1000 if (processed(type->ref) || is_base_type(type->ref->type))
1001 write_pointer_tfs(file, type, typestring_offset);
1002 else
1003 error("write_pointer_description: type format string unknown\n");
1005 else if (level == 0 && is_struct(type->type))
1007 if (type->fields)
1009 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1010 mem_offset
1011 += write_pointer_description(file, v->type, mem_offset,
1012 level + 1, typestring_offset);
1016 return type_memsize(type, &align);
1019 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1020 const type_t *type,
1021 const char *name, unsigned int *typestring_offset)
1023 size_t start_offset = *typestring_offset;
1024 unsigned char flags = 0;
1025 int pointer_type;
1026 unsigned char rtype;
1028 if (is_ptr(type))
1030 pointer_type = type->type;
1031 type = type->ref;
1033 else
1034 pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1036 if (!pointer_type)
1037 pointer_type = RPC_FC_RP;
1039 if (!get_attrp(attrs, ATTR_SIZEIS))
1040 flags |= RPC_FC_P_SIMPLEPOINTER;
1042 rtype = type->type;
1044 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1046 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1047 return start_offset;
1050 print_file(file, 2,"0x%x, 0x%x, /* %s%s */\n",
1051 pointer_type, flags,
1052 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"),
1053 (flags & RPC_FC_P_SIMPLEPOINTER) ? " [simple_pointer]" : "");
1054 *typestring_offset += 2;
1056 if (!(flags & RPC_FC_P_SIMPLEPOINTER))
1058 print_file(file, 2, "NdrFcShort(0x2),\n");
1059 *typestring_offset += 2;
1062 if (type->declarray && !is_conformant_array(type))
1064 /* FIXME: multi-dimensional array */
1065 if (0xffffuL < type->dim)
1066 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1067 name, 0xffffu, type->dim - 0xffffu);
1069 if (rtype == RPC_FC_CHAR)
1070 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1071 else
1072 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1073 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1074 *typestring_offset += 2;
1076 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1077 *typestring_offset += 2;
1079 return start_offset;
1081 else if (type->size_is)
1083 unsigned int align = 0;
1085 if (rtype == RPC_FC_CHAR)
1086 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1087 else
1088 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1089 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1090 *typestring_offset += 2;
1092 *typestring_offset += write_conf_or_var_desc(
1093 file, current_func, current_structure,
1094 (type->declarray && current_structure
1095 ? type_memsize(current_structure, &align)
1096 : 0),
1097 type->size_is);
1099 return start_offset;
1101 else
1103 if (rtype == RPC_FC_CHAR)
1104 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1105 else
1106 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1107 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1108 *typestring_offset += 2;
1110 return start_offset;
1114 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1115 const char *name, unsigned int *typestring_offset)
1117 const expr_t *length_is = type->length_is;
1118 const expr_t *size_is = type->size_is;
1119 unsigned int align = 0;
1120 size_t size;
1121 size_t start_offset;
1122 int has_pointer;
1123 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1124 if (!pointer_type)
1125 pointer_type = RPC_FC_RP;
1127 has_pointer = FALSE;
1128 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1129 has_pointer = TRUE;
1131 size = type_memsize(type, &align);
1132 if (size == 0) /* conformant array */
1133 size = type_memsize(type->ref, &align);
1135 start_offset = *typestring_offset;
1136 update_tfsoff(type, start_offset, file);
1137 print_file(file, 0, "/* %lu */\n", start_offset);
1138 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1139 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1140 *typestring_offset += 2;
1142 align = 0;
1143 if (type->type != RPC_FC_BOGUS_ARRAY)
1145 unsigned char tc = type->type;
1146 unsigned int baseoff
1147 = type->declarray && current_structure
1148 ? type_memsize(current_structure, &align)
1149 : 0;
1151 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1153 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1154 *typestring_offset += 4;
1156 else
1158 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1159 *typestring_offset += 2;
1162 if (is_conformant_array(type))
1163 *typestring_offset
1164 += write_conf_or_var_desc(file, current_func, current_structure,
1165 baseoff, size_is);
1167 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1169 unsigned int elalign = 0;
1170 size_t elsize = type_memsize(type->ref, &elalign);
1172 if (type->type == RPC_FC_LGVARRAY)
1174 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1175 *typestring_offset += 4;
1177 else
1179 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1180 *typestring_offset += 2;
1183 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1184 *typestring_offset += 2;
1187 if (length_is)
1188 *typestring_offset
1189 += write_conf_or_var_desc(file, current_func, current_structure,
1190 baseoff, length_is);
1192 if (has_pointer)
1194 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1195 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1196 *typestring_offset += 2;
1197 write_pointer_description(file, type, 0, 0, typestring_offset);
1198 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1199 *typestring_offset += 1;
1202 write_member_type(file, type->ref, NULL, NULL, typestring_offset);
1203 write_end(file, typestring_offset);
1205 else
1206 error("%s: complex arrays unimplemented\n", name);
1208 return start_offset;
1211 static const var_t *find_array_or_string_in_struct(const type_t *type)
1213 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1214 const type_t *ft = last_field->type;
1216 if (ft->declarray && is_conformant_array(ft))
1217 return last_field;
1219 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1220 return find_array_or_string_in_struct(last_field->type);
1221 else
1222 return NULL;
1225 static void write_struct_members(FILE *file, const type_t *type,
1226 unsigned int *corroff, unsigned int *typestring_offset)
1228 const var_t *field;
1230 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1232 type_t *ft = field->type;
1233 if (!ft->declarray || !is_conformant_array(ft))
1234 write_member_type(file, ft, field, corroff, typestring_offset);
1237 write_end(file, typestring_offset);
1240 static size_t write_struct_tfs(FILE *file, type_t *type,
1241 const char *name, unsigned int *tfsoff)
1243 const type_t *save_current_structure = current_structure;
1244 unsigned int total_size;
1245 const var_t *array;
1246 size_t start_offset;
1247 size_t array_offset;
1248 int has_pointers = 0;
1249 unsigned int align = 0;
1250 unsigned int corroff;
1251 var_t *f;
1253 guard_rec(type);
1254 current_structure = type;
1256 total_size = type_memsize(type, &align);
1257 if (total_size > USHRT_MAX)
1258 error("structure size for %s exceeds %d bytes by %d bytes\n",
1259 name, USHRT_MAX, total_size - USHRT_MAX);
1261 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1262 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1263 FALSE, tfsoff);
1265 array = find_array_or_string_in_struct(type);
1266 if (array && !processed(array->type))
1267 array_offset
1268 = is_attr(array->attrs, ATTR_STRING)
1269 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1270 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1272 corroff = *tfsoff;
1273 write_descriptors(file, type, tfsoff);
1275 start_offset = *tfsoff;
1276 update_tfsoff(type, start_offset, file);
1277 print_file(file, 0, "/* %d */\n", start_offset);
1278 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1279 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1280 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1281 *tfsoff += 4;
1283 if (array)
1285 unsigned int absoff = array->type->typestring_offset;
1286 short reloff = absoff - *tfsoff;
1287 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1288 reloff, reloff, absoff);
1289 *tfsoff += 2;
1291 else if (type->type == RPC_FC_BOGUS_STRUCT)
1293 print_file(file, 2, "NdrFcShort(0x0),\n");
1294 *tfsoff += 2;
1297 if (type->type == RPC_FC_BOGUS_STRUCT)
1300 print_file(file, 2, "NdrFcShort(0x0),\t/* FIXME: pointer stuff */\n");
1301 *tfsoff += 2;
1303 else if (has_pointers)
1305 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1306 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1307 *tfsoff += 2;
1308 write_pointer_description(file, type, 0, 0, tfsoff);
1309 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1310 *tfsoff += 1;
1313 write_struct_members(file, type, &corroff, tfsoff);
1315 current_structure = save_current_structure;
1316 return start_offset;
1319 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1320 unsigned char flags, size_t offset,
1321 unsigned int *typeformat_offset)
1323 size_t start_offset = *typeformat_offset;
1324 short reloff = offset - (*typeformat_offset + 2);
1325 int in_attr, out_attr;
1326 in_attr = is_attr(attrs, ATTR_IN);
1327 out_attr = is_attr(attrs, ATTR_OUT);
1328 if (!in_attr && !out_attr) in_attr = 1;
1330 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1331 flags |= 0x04;
1333 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1334 pointer_type,
1335 flags,
1336 string_of_type(pointer_type));
1337 if (file)
1339 if (flags & 0x04)
1340 fprintf(file, " [allocated_on_stack]");
1341 if (flags & 0x10)
1342 fprintf(file, " [pointer_deref]");
1343 fprintf(file, " */\n");
1346 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1347 *typeformat_offset += 4;
1349 return start_offset;
1352 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1354 if (t == NULL)
1356 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1358 else if (is_base_type(t->type))
1360 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1361 t->type, string_of_type(t->type));
1363 else if (t->typestring_offset)
1365 short reloff = t->typestring_offset - *tfsoff;
1366 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1367 reloff, reloff, t->typestring_offset);
1369 else
1370 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1372 *tfsoff += 2;
1375 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1377 unsigned int align = 0;
1378 unsigned int start_offset;
1379 size_t size = type_memsize(type, &align);
1380 var_list_t *fields;
1381 size_t nbranch = 0;
1382 type_t *deftype = NULL;
1383 short nodeftype = 0xffff;
1384 var_t *f;
1386 guard_rec(type);
1388 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1390 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1391 fields = uv->type->fields;
1393 else
1394 fields = type->fields;
1396 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1398 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1399 if (cases)
1400 nbranch += list_count(cases);
1401 if (f->type)
1402 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1405 start_offset = *tfsoff;
1406 update_tfsoff(type, start_offset, file);
1407 print_file(file, 0, "/* %d */\n", start_offset);
1408 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1410 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1411 const type_t *st = sv->type;
1412 size_t ss = type_memsize(st, &align);
1414 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1415 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1416 (ss << 4) | st->type, string_of_type(st->type));
1417 *tfsoff += 2;
1419 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1420 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1421 *tfsoff += 4;
1423 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1425 type_t *ft = f->type;
1426 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1427 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1428 expr_t *c;
1430 if (cases == NULL && !deflt)
1431 error("union field %s with neither case nor default attribute\n", f->name);
1433 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1435 /* MIDL doesn't check for duplicate cases, even though that seems
1436 like a reasonable thing to do, it just dumps them to the TFS
1437 like we're going to do here. */
1438 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1439 *tfsoff += 4;
1440 write_branch_type(file, ft, tfsoff);
1443 /* MIDL allows multiple default branches, even though that seems
1444 illogical, it just chooses the last one, which is what we will
1445 do. */
1446 if (deflt)
1448 deftype = ft;
1449 nodeftype = 0;
1453 if (deftype)
1455 write_branch_type(file, deftype, tfsoff);
1457 else
1459 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1460 *tfsoff += 2;
1463 return start_offset;
1466 static size_t write_ip_tfs(FILE *file, const func_t *func, const attr_list_t *attrs,
1467 type_t *type, unsigned int *typeformat_offset)
1469 size_t i;
1470 size_t start_offset = *typeformat_offset;
1471 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1473 if (iid)
1475 expr_t expr;
1477 expr.type = EXPR_IDENTIFIER;
1478 expr.ref = NULL;
1479 expr.u.sval = iid->name;
1480 expr.is_const = FALSE;
1481 print_file(file, 2, "0x2f, /* FC_IP */\n");
1482 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1483 *typeformat_offset += write_conf_or_var_desc(file, func, NULL, 0, &expr) + 2;
1485 else
1487 const type_t *base = is_ptr(type) ? type->ref : type;
1488 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1490 if (! uuid)
1491 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1493 update_tfsoff(type, start_offset, file);
1494 print_file(file, 0, "/* %d */\n", start_offset);
1495 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1496 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1497 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1498 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1499 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1500 for (i = 0; i < 8; ++i)
1501 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1503 if (file)
1504 fprintf(file, "\n");
1506 *typeformat_offset += 18;
1508 return start_offset;
1511 static int get_ptr_attr(const type_t *t, int def_type)
1513 while (TRUE)
1515 int ptr_attr = get_attrv(t->attrs, ATTR_POINTERTYPE);
1516 if (ptr_attr)
1517 return ptr_attr;
1518 if (t->kind != TKIND_ALIAS)
1519 return def_type;
1520 t = t->orig;
1524 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
1525 type_t *type, const var_t *var,
1526 unsigned int *typeformat_offset)
1528 int pointer_type;
1529 size_t offset;
1531 if (is_user_type(type))
1533 write_user_tfs(file, type, typeformat_offset);
1534 return type->typestring_offset;
1537 if (type == var->type) /* top-level pointers */
1539 int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE);
1540 if (pointer_attr != 0 && !is_ptr(type) && !is_array(type))
1541 error("'%s': pointer attribute applied to non-pointer type\n", var->name);
1543 if (pointer_attr == 0)
1544 pointer_attr = get_ptr_attr(type, RPC_FC_RP);
1546 pointer_type = pointer_attr;
1548 else
1549 pointer_type = get_ptr_attr(type, RPC_FC_UP);
1551 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
1552 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
1554 if (is_array(type))
1555 return write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
1557 if (!is_ptr(type))
1559 /* basic types don't need a type format string */
1560 if (is_base_type(type->type))
1561 return 0;
1563 switch (type->type)
1565 case RPC_FC_STRUCT:
1566 case RPC_FC_PSTRUCT:
1567 case RPC_FC_CSTRUCT:
1568 case RPC_FC_CPSTRUCT:
1569 case RPC_FC_CVSTRUCT:
1570 case RPC_FC_BOGUS_STRUCT:
1571 return write_struct_tfs(file, type, var->name, typeformat_offset);
1572 case RPC_FC_ENCAPSULATED_UNION:
1573 case RPC_FC_NON_ENCAPSULATED_UNION:
1574 return write_union_tfs(file, type, typeformat_offset);
1575 case RPC_FC_IGNORE:
1576 case RPC_FC_BIND_PRIMITIVE:
1577 /* nothing to do */
1578 return 0;
1579 default:
1580 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
1583 else if (last_ptr(type))
1585 size_t start_offset = *typeformat_offset;
1586 int in_attr = is_attr(var->attrs, ATTR_IN);
1587 int out_attr = is_attr(var->attrs, ATTR_OUT);
1588 const type_t *base = type->ref;
1590 if (base->type == RPC_FC_IP)
1592 return write_ip_tfs(file, func, var->attrs, type, typeformat_offset);
1595 /* special case for pointers to base types */
1596 if (is_base_type(base->type))
1598 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
1599 pointer_type, (!in_attr && out_attr) ? 0x0C : 0x08,
1600 string_of_type(pointer_type),
1601 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
1602 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
1603 print_file(file, indent, "0x5c, /* FC_PAD */\n");
1604 *typeformat_offset += 4;
1605 return start_offset;
1609 assert(is_ptr(type));
1611 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
1612 if (file)
1613 fprintf(file, "/* %2u */\n", *typeformat_offset);
1614 return write_pointer_only_tfs(file, var->attrs, pointer_type,
1615 !last_ptr(type) ? 0x10 : 0,
1616 offset, typeformat_offset);
1619 static void set_tfswrite(type_t *type, int val)
1621 while (type->tfswrite != val)
1623 type_t *utype = get_user_type(type, NULL);
1625 type->tfswrite = val;
1627 if (utype)
1628 set_tfswrite(utype, val);
1630 if (type->kind == TKIND_ALIAS)
1631 type = type->orig;
1632 else if (is_ptr(type) || is_array(type))
1633 type = type->ref;
1634 else
1636 if (type->fields)
1638 var_t *v;
1639 LIST_FOR_EACH_ENTRY( v, type->fields, var_t, entry )
1640 if (v->type)
1641 set_tfswrite(v->type, val);
1644 return;
1649 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
1650 const char *name, int write_ptr, unsigned int *tfsoff)
1652 int retmask = 0;
1654 if (is_user_type(type))
1656 write_user_tfs(file, type, tfsoff);
1658 else if (is_ptr(type))
1660 type_t *ref = type->ref;
1662 if (ref->type == RPC_FC_IP)
1664 write_ip_tfs(file, NULL, attrs, type, tfsoff);
1666 else
1668 if (!processed(ref) && !is_base_type(ref->type))
1669 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
1671 if (write_ptr)
1672 write_pointer_tfs(file, type, tfsoff);
1674 retmask |= 1;
1677 else if (type->declarray && is_conformant_array(type))
1678 ; /* conformant arrays and strings are handled specially */
1679 else if (is_array(type))
1681 write_array_tfs(file, attrs, type, name, tfsoff);
1683 else if (is_struct(type->type))
1685 if (!processed(type))
1686 write_struct_tfs(file, type, name, tfsoff);
1688 else if (is_union(type->type))
1690 if (!processed(type))
1691 write_union_tfs(file, type, tfsoff);
1693 else if (!is_base_type(type->type))
1694 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
1695 name, type->type);
1697 return retmask;
1700 static void set_all_tfswrite(const ifref_list_t *ifaces, int val)
1702 const ifref_t * iface;
1703 const func_t *func;
1704 const var_t *var;
1706 if (ifaces)
1707 LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
1708 if (iface->iface->funcs)
1709 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
1710 if (func->args)
1711 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1712 set_tfswrite(var->type, val);
1715 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, int for_objects)
1717 const var_t *var;
1718 const ifref_t *iface;
1719 unsigned int typeformat_offset = 2;
1721 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
1723 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
1724 continue;
1726 if (iface->iface->funcs)
1728 const func_t *func;
1729 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
1731 if (is_local(func->def->attrs)) continue;
1733 current_func = func;
1734 if (func->args)
1735 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1736 update_tfsoff(
1737 var->type,
1738 write_typeformatstring_var(
1739 file, 2, func, var->type, var,
1740 &typeformat_offset),
1741 file);
1746 return typeformat_offset + 1;
1750 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
1752 int indent = 0;
1754 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1755 print_file(file, indent, "{\n");
1756 indent++;
1757 print_file(file, indent, "0,\n");
1758 print_file(file, indent, "{\n");
1759 indent++;
1760 print_file(file, indent, "NdrFcShort(0x0),\n");
1762 set_all_tfswrite(ifaces, TRUE);
1763 process_tfs(file, ifaces, for_objects);
1765 print_file(file, indent, "0x0\n");
1766 indent--;
1767 print_file(file, indent, "}\n");
1768 indent--;
1769 print_file(file, indent, "};\n");
1770 print_file(file, indent, "\n");
1773 static unsigned int get_required_buffer_size_type(
1774 const type_t *type, const char *name, unsigned int *alignment)
1776 size_t size = 0;
1778 *alignment = 0;
1779 if (!is_ptr(type))
1781 switch (type->type)
1783 case RPC_FC_BYTE:
1784 case RPC_FC_CHAR:
1785 case RPC_FC_USMALL:
1786 case RPC_FC_SMALL:
1787 *alignment = 4;
1788 size = 1;
1789 break;
1791 case RPC_FC_WCHAR:
1792 case RPC_FC_USHORT:
1793 case RPC_FC_SHORT:
1794 *alignment = 4;
1795 size = 2;
1796 break;
1798 case RPC_FC_ULONG:
1799 case RPC_FC_LONG:
1800 case RPC_FC_FLOAT:
1801 case RPC_FC_ERROR_STATUS_T:
1802 *alignment = 4;
1803 size = 4;
1804 break;
1806 case RPC_FC_HYPER:
1807 case RPC_FC_DOUBLE:
1808 *alignment = 8;
1809 size = 8;
1810 break;
1812 case RPC_FC_IGNORE:
1813 case RPC_FC_BIND_PRIMITIVE:
1814 return 0;
1816 case RPC_FC_STRUCT:
1817 case RPC_FC_PSTRUCT:
1819 const var_t *field;
1820 if (!type->fields) return 0;
1821 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1823 unsigned int alignment;
1824 size += get_required_buffer_size_type(field->type, field->name,
1825 &alignment);
1827 break;
1830 case RPC_FC_RP:
1831 if (is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT)
1832 size = get_required_buffer_size_type( type->ref, name, alignment );
1833 break;
1835 case RPC_FC_SMFARRAY:
1836 case RPC_FC_LGFARRAY:
1837 size = type->dim * get_required_buffer_size_type(type->ref, name, alignment);
1838 break;
1840 case RPC_FC_SMVARRAY:
1841 case RPC_FC_LGVARRAY:
1842 get_required_buffer_size_type(type->ref, name, alignment);
1843 size = 0;
1844 break;
1846 case RPC_FC_CARRAY:
1847 case RPC_FC_CVARRAY:
1848 get_required_buffer_size_type(type->ref, name, alignment);
1849 size = sizeof(void *);
1850 break;
1852 default:
1853 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1854 return 0;
1857 return size;
1860 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
1862 int in_attr = is_attr(var->attrs, ATTR_IN);
1863 int out_attr = is_attr(var->attrs, ATTR_OUT);
1865 if (!in_attr && !out_attr)
1866 in_attr = 1;
1868 *alignment = 0;
1870 if (pass == PASS_OUT)
1872 if (out_attr && is_ptr(var->type))
1874 type_t *type = var->type;
1876 if (type->type == RPC_FC_STRUCT)
1878 const var_t *field;
1879 unsigned int size = 36;
1881 if (!type->fields) return size;
1882 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1884 unsigned int align;
1885 size += get_required_buffer_size_type(
1886 field->type, field->name, &align);
1888 return size;
1891 return 0;
1893 else
1895 if ((!out_attr || in_attr) && !var->type->size_is
1896 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
1898 if (is_ptr(var->type))
1900 type_t *type = var->type;
1902 if (is_base_type(type->type))
1904 return 25;
1906 else if (type->type == RPC_FC_STRUCT)
1908 unsigned int size = 36;
1909 const var_t *field;
1911 if (!type->fields) return size;
1912 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1914 unsigned int align;
1915 size += get_required_buffer_size_type(
1916 field->type, field->name, &align);
1918 return size;
1923 return get_required_buffer_size_type(var->type, var->name, alignment);
1927 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
1929 const var_t *var;
1930 unsigned int total_size = 0, alignment;
1932 if (func->args)
1934 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1936 total_size += get_required_buffer_size(var, &alignment, pass);
1937 total_size += alignment;
1941 if (pass == PASS_OUT && !is_void(func->def->type))
1943 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
1944 total_size += alignment;
1946 return total_size;
1949 static void print_phase_function(FILE *file, int indent, const char *type,
1950 enum remoting_phase phase,
1951 const var_t *var, unsigned int type_offset)
1953 const char *function;
1954 switch (phase)
1956 case PHASE_BUFFERSIZE:
1957 function = "BufferSize";
1958 break;
1959 case PHASE_MARSHAL:
1960 function = "Marshall";
1961 break;
1962 case PHASE_UNMARSHAL:
1963 function = "Unmarshall";
1964 break;
1965 case PHASE_FREE:
1966 function = "Free";
1967 break;
1968 default:
1969 assert(0);
1970 return;
1973 print_file(file, indent, "Ndr%s%s(\n", type, function);
1974 indent++;
1975 print_file(file, indent, "&_StubMsg,\n");
1976 print_file(file, indent, "%s%s%s%s,\n",
1977 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
1978 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
1979 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
1980 var->name);
1981 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
1982 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
1983 if (phase == PHASE_UNMARSHAL)
1984 print_file(file, indent, "0);\n");
1985 indent--;
1988 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
1989 enum pass pass, const var_t *var,
1990 const char *varname)
1992 type_t *type = var->type;
1993 unsigned int size;
1994 unsigned int alignment = 0;
1995 unsigned char rtype;
1997 /* no work to do for other phases, buffer sizing is done elsewhere */
1998 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
1999 return;
2001 rtype = is_ptr(type) ? type->ref->type : type->type;
2003 switch (rtype)
2005 case RPC_FC_BYTE:
2006 case RPC_FC_CHAR:
2007 case RPC_FC_SMALL:
2008 case RPC_FC_USMALL:
2009 size = 1;
2010 alignment = 1;
2011 break;
2013 case RPC_FC_WCHAR:
2014 case RPC_FC_USHORT:
2015 case RPC_FC_SHORT:
2016 size = 2;
2017 alignment = 2;
2018 break;
2020 case RPC_FC_ULONG:
2021 case RPC_FC_LONG:
2022 case RPC_FC_FLOAT:
2023 case RPC_FC_ERROR_STATUS_T:
2024 size = 4;
2025 alignment = 4;
2026 break;
2028 case RPC_FC_HYPER:
2029 case RPC_FC_DOUBLE:
2030 size = 8;
2031 alignment = 8;
2032 break;
2034 case RPC_FC_IGNORE:
2035 case RPC_FC_BIND_PRIMITIVE:
2036 /* no marshalling needed */
2037 return;
2039 default:
2040 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2041 size = 0;
2044 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2045 alignment - 1, alignment - 1);
2047 if (phase == PHASE_MARSHAL)
2049 print_file(file, indent, "*(");
2050 write_type(file, is_ptr(type) ? type->ref : type, FALSE, NULL);
2051 if (is_ptr(type))
2052 fprintf(file, " *)_StubMsg.Buffer = *");
2053 else
2054 fprintf(file, " *)_StubMsg.Buffer = ");
2055 fprintf(file, varname);
2056 fprintf(file, ";\n");
2058 else if (phase == PHASE_UNMARSHAL)
2060 if (pass == PASS_IN || pass == PASS_RETURN)
2061 print_file(file, indent, "");
2062 else
2063 print_file(file, indent, "*");
2064 fprintf(file, varname);
2065 if (pass == PASS_IN && is_ptr(type))
2066 fprintf(file, " = (");
2067 else
2068 fprintf(file, " = *(");
2069 write_type(file, is_ptr(type) ? type->ref : type, FALSE, NULL);
2070 fprintf(file, " *)_StubMsg.Buffer;\n");
2073 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2074 write_type(file, var->type, FALSE, NULL);
2075 fprintf(file, ");\n");
2078 /* returns whether the MaxCount, Offset or ActualCount members need to be
2079 * filled in for the specified phase */
2080 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2082 return (phase != PHASE_UNMARSHAL);
2085 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2086 enum pass pass, enum remoting_phase phase)
2088 int in_attr, out_attr, pointer_type;
2089 const var_t *var;
2091 if (!func->args)
2092 return;
2094 if (phase == PHASE_BUFFERSIZE)
2096 unsigned int size = get_function_buffer_size( func, pass );
2097 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2100 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2102 const type_t *type = var->type;
2103 unsigned char rtype;
2104 size_t start_offset = type->typestring_offset;
2106 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2107 if (!pointer_type)
2108 pointer_type = RPC_FC_RP;
2110 in_attr = is_attr(var->attrs, ATTR_IN);
2111 out_attr = is_attr(var->attrs, ATTR_OUT);
2112 if (!in_attr && !out_attr)
2113 in_attr = 1;
2115 switch (pass)
2117 case PASS_IN:
2118 if (!in_attr) continue;
2119 break;
2120 case PASS_OUT:
2121 if (!out_attr) continue;
2122 break;
2123 case PASS_RETURN:
2124 break;
2127 rtype = type->type;
2129 if (is_user_type(var->type))
2131 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2133 else if (is_string_type(var->attrs, var->type))
2135 if (is_array(type) && !is_conformant_array(type))
2136 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2137 else
2139 if (type->size_is && is_size_needed_for_phase(phase))
2141 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2142 write_expr(file, type->size_is, 1);
2143 fprintf(file, ";\n");
2146 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2147 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2148 else
2149 print_phase_function(file, indent, "ConformantString", phase, var,
2150 start_offset + (type->size_is ? 4 : 2));
2153 else if (is_array(type))
2155 unsigned char tc = type->type;
2156 const char *array_type;
2158 if (tc == RPC_FC_SMFARRAY || tc == RPC_FC_LGFARRAY)
2159 array_type = "FixedArray";
2160 else if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2162 if (is_size_needed_for_phase(phase))
2164 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2165 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2166 write_expr(file, type->length_is, 1);
2167 fprintf(file, ";\n\n");
2169 array_type = "VaryingArray";
2171 else if (tc == RPC_FC_CARRAY)
2173 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2175 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2176 write_expr(file, type->size_is, 1);
2177 fprintf(file, ";\n\n");
2179 array_type = "ConformantArray";
2181 else if (tc == RPC_FC_CVARRAY)
2183 if (is_size_needed_for_phase(phase))
2185 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2186 write_expr(file, type->size_is, 1);
2187 fprintf(file, ";\n");
2188 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2189 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2190 write_expr(file, type->length_is, 1);
2191 fprintf(file, ";\n\n");
2193 array_type = "ConformantVaryingArray";
2195 else
2196 array_type = "ComplexArray";
2198 if (!in_attr && phase == PHASE_FREE)
2200 print_file(file, indent, "if (%s)\n", var->name);
2201 indent++;
2202 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2204 else if (phase != PHASE_FREE)
2206 if (pointer_type == RPC_FC_UP)
2207 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2208 else
2209 print_phase_function(file, indent, array_type, phase, var, start_offset);
2212 else if (!is_ptr(var->type) && is_base_type(rtype))
2214 print_phase_basetype(file, indent, phase, pass, var, var->name);
2216 else if (!is_ptr(var->type))
2218 switch (rtype)
2220 case RPC_FC_STRUCT:
2221 case RPC_FC_PSTRUCT:
2222 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2223 break;
2224 case RPC_FC_CSTRUCT:
2225 case RPC_FC_CPSTRUCT:
2226 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2227 break;
2228 case RPC_FC_CVSTRUCT:
2229 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2230 break;
2231 case RPC_FC_BOGUS_STRUCT:
2232 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2233 break;
2234 case RPC_FC_RP:
2235 if (is_base_type( var->type->ref->type ))
2237 print_phase_basetype(file, indent, phase, pass, var, var->name);
2239 else if (var->type->ref->type == RPC_FC_STRUCT)
2241 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2242 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2244 else
2246 const var_t *iid;
2247 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2248 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2249 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2251 break;
2252 default:
2253 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2256 else
2258 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2260 print_phase_basetype(file, indent, phase, pass, var, var->name);
2262 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2264 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2265 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2267 else
2269 const var_t *iid;
2270 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2271 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2272 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2275 fprintf(file, "\n");
2280 size_t get_size_procformatstring_var(const var_t *var)
2282 return write_procformatstring_var(NULL, 0, var, FALSE);
2286 size_t get_size_procformatstring_func(const func_t *func)
2288 const var_t *var;
2289 size_t size = 0;
2291 /* argument list size */
2292 if (func->args)
2293 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2294 size += get_size_procformatstring_var(var);
2296 /* return value size */
2297 if (is_void(func->def->type))
2298 size += 2; /* FC_END and FC_PAD */
2299 else
2300 size += get_size_procformatstring_var(func->def);
2302 return size;
2305 size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects)
2307 const ifref_t *iface;
2308 size_t size = 1;
2309 const func_t *func;
2311 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2313 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2314 continue;
2316 if (iface->iface->funcs)
2317 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2318 if (!is_local(func->def->attrs))
2319 size += get_size_procformatstring_func( func );
2321 return size;
2324 size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects)
2326 set_all_tfswrite(ifaces, FALSE);
2327 return process_tfs(NULL, ifaces, for_objects);
2330 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2331 const var_list_t *fields, const char *structvar)
2333 switch (e->type) {
2334 case EXPR_VOID:
2335 break;
2336 case EXPR_NUM:
2337 fprintf(h, "%lu", e->u.lval);
2338 break;
2339 case EXPR_HEXNUM:
2340 fprintf(h, "0x%lx", e->u.lval);
2341 break;
2342 case EXPR_TRUEFALSE:
2343 if (e->u.lval == 0)
2344 fprintf(h, "FALSE");
2345 else
2346 fprintf(h, "TRUE");
2347 break;
2348 case EXPR_IDENTIFIER:
2350 const var_t *field;
2351 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2352 if (!strcmp(e->u.sval, field->name))
2354 fprintf(h, "%s->%s", structvar, e->u.sval);
2355 break;
2358 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2359 break;
2361 case EXPR_NEG:
2362 fprintf(h, "-");
2363 write_struct_expr(h, e->ref, 1, fields, structvar);
2364 break;
2365 case EXPR_NOT:
2366 fprintf(h, "~");
2367 write_struct_expr(h, e->ref, 1, fields, structvar);
2368 break;
2369 case EXPR_PPTR:
2370 fprintf(h, "*");
2371 write_struct_expr(h, e->ref, 1, fields, structvar);
2372 break;
2373 case EXPR_CAST:
2374 fprintf(h, "(");
2375 write_type(h, e->u.tref, FALSE, NULL);
2376 fprintf(h, ")");
2377 write_struct_expr(h, e->ref, 1, fields, structvar);
2378 break;
2379 case EXPR_SIZEOF:
2380 fprintf(h, "sizeof(");
2381 write_type(h, e->u.tref, FALSE, NULL);
2382 fprintf(h, ")");
2383 break;
2384 case EXPR_SHL:
2385 case EXPR_SHR:
2386 case EXPR_MUL:
2387 case EXPR_DIV:
2388 case EXPR_ADD:
2389 case EXPR_SUB:
2390 case EXPR_AND:
2391 case EXPR_OR:
2392 if (brackets) fprintf(h, "(");
2393 write_struct_expr(h, e->ref, 1, fields, structvar);
2394 switch (e->type) {
2395 case EXPR_SHL: fprintf(h, " << "); break;
2396 case EXPR_SHR: fprintf(h, " >> "); break;
2397 case EXPR_MUL: fprintf(h, " * "); break;
2398 case EXPR_DIV: fprintf(h, " / "); break;
2399 case EXPR_ADD: fprintf(h, " + "); break;
2400 case EXPR_SUB: fprintf(h, " - "); break;
2401 case EXPR_AND: fprintf(h, " & "); break;
2402 case EXPR_OR: fprintf(h, " | "); break;
2403 default: break;
2405 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2406 if (brackets) fprintf(h, ")");
2407 break;
2408 case EXPR_COND:
2409 if (brackets) fprintf(h, "(");
2410 write_struct_expr(h, e->ref, 1, fields, structvar);
2411 fprintf(h, " ? ");
2412 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2413 fprintf(h, " : ");
2414 write_struct_expr(h, e->ext2, 1, fields, structvar);
2415 if (brackets) fprintf(h, ")");
2416 break;
2421 void declare_stub_args( FILE *file, int indent, const func_t *func )
2423 int in_attr, out_attr;
2424 int i = 0;
2425 const var_t *def = func->def;
2426 const var_t *var;
2428 /* declare return value '_RetVal' */
2429 if (!is_void(def->type))
2431 print_file(file, indent, "");
2432 write_type_left(file, def->type);
2433 fprintf(file, " _RetVal;\n");
2436 if (!func->args)
2437 return;
2439 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2441 int is_string = is_attr(var->attrs, ATTR_STRING);
2443 in_attr = is_attr(var->attrs, ATTR_IN);
2444 out_attr = is_attr(var->attrs, ATTR_OUT);
2445 if (!out_attr && !in_attr)
2446 in_attr = 1;
2448 if (!in_attr && !var->type->size_is && !is_string)
2450 print_file(file, indent, "");
2451 write_type(file, var->type->ref, FALSE, "_W%u", i++);
2452 fprintf(file, ";\n");
2455 print_file(file, indent, "");
2456 write_type_left(file, var->type);
2457 fprintf(file, " ");
2458 if (var->type->declarray) {
2459 fprintf(file, "( *");
2460 write_name(file, var);
2461 fprintf(file, " )");
2462 } else
2463 write_name(file, var);
2464 write_type_right(file, var->type, FALSE);
2465 fprintf(file, ";\n");
2467 if (decl_indirect(var->type))
2468 print_file(file, indent, "void *_p_%s = &%s;\n",
2469 var->name, var->name);
2474 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
2476 int in_attr, out_attr;
2477 int i = 0, sep = 0;
2478 const var_t *var;
2480 if (!func->args)
2481 return;
2483 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2485 int is_string = is_attr(var->attrs, ATTR_STRING);
2486 in_attr = is_attr(var->attrs, ATTR_IN);
2487 out_attr = is_attr(var->attrs, ATTR_OUT);
2488 if (!out_attr && !in_attr)
2489 in_attr = 1;
2491 if (!in_attr)
2493 print_file(file, indent, "");
2494 write_name(file, var);
2496 if (var->type->size_is)
2498 unsigned int size, align = 0;
2499 type_t *type = var->type;
2501 fprintf(file, " = NdrAllocate(&_StubMsg, ");
2502 for ( ; type->size_is ; type = type->ref)
2504 write_expr(file, type->size_is, TRUE);
2505 fprintf(file, " * ");
2507 size = type_memsize(type, &align);
2508 fprintf(file, "%u);\n", size);
2510 else if (!is_string)
2512 fprintf(file, " = &_W%u;\n", i);
2513 if (is_ptr(var->type) && !last_ptr(var->type))
2514 print_file(file, indent, "_W%u = 0;\n", i);
2515 i++;
2518 sep = 1;
2521 if (sep)
2522 fprintf(file, "\n");
2526 int write_expr_eval_routines(FILE *file, const char *iface)
2528 int result = 0;
2529 struct expr_eval_routine *eval;
2530 unsigned short callback_offset = 0;
2532 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
2534 int indent = 0;
2535 result = 1;
2536 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2537 iface, eval->structure->name, callback_offset);
2538 print_file(file, indent, "{\n");
2539 indent++;
2540 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
2541 eval->structure->name, eval->structure->name, eval->structure_size);
2542 fprintf(file, "\n");
2543 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
2544 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
2545 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
2546 fprintf(file, ";\n");
2547 indent--;
2548 print_file(file, indent, "}\n\n");
2549 callback_offset++;
2551 return result;
2554 void write_expr_eval_routine_list(FILE *file, const char *iface)
2556 struct expr_eval_routine *eval;
2557 struct expr_eval_routine *cursor;
2558 unsigned short callback_offset = 0;
2560 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2561 fprintf(file, "{\n");
2563 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
2565 print_file(file, 1, "%s_%sExprEval_%04u,\n",
2566 iface, eval->structure->name, callback_offset);
2568 callback_offset++;
2569 list_remove(&eval->entry);
2570 free(eval);
2573 fprintf(file, "};\n\n");
2576 void write_user_quad_list(FILE *file)
2578 user_type_t *ut;
2580 if (list_empty(&user_type_list))
2581 return;
2583 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
2584 fprintf(file, "{\n");
2585 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
2587 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
2588 print_file(file, 1, "{\n");
2589 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
2590 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
2591 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
2592 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
2593 print_file(file, 1, "}%s\n", sep);
2595 fprintf(file, "};\n\n");
2598 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
2600 const struct str_list_entry_t *endpoint;
2601 const char *p;
2603 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
2604 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
2605 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
2607 print_file( f, 1, "{ (const unsigned char *)\"" );
2608 for (p = endpoint->str; *p && *p != ':'; p++)
2610 if (*p == '"' || *p == '\\') fputc( '\\', f );
2611 fputc( *p, f );
2613 if (!*p) goto error;
2614 if (p[1] != '[') goto error;
2616 fprintf( f, "\", (const unsigned char *)\"" );
2617 for (p += 2; *p && *p != ']'; p++)
2619 if (*p == '"' || *p == '\\') fputc( '\\', f );
2620 fputc( *p, f );
2622 if (*p != ']') goto error;
2623 fprintf( f, "\" },\n" );
2625 print_file( f, 0, "};\n\n" );
2626 return;
2628 error:
2629 error("Invalid endpoint syntax '%s'\n", endpoint->str);