widl: Represent arrays with type_t.
[wine/wine64.git] / tools / widl / typegen.c
blob9583743311c7720730838120961e868cb7e6e506
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 level, 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 static 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 static 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 void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
142 type->typestring_offset = offset;
143 if (file) type->tfswrite = FALSE;
146 static void guard_rec(type_t *type)
148 /* types that contain references to themselves (like a linked list),
149 need to be shielded from infinite recursion when writing embedded
150 types */
151 if (type->typestring_offset)
152 type->tfswrite = FALSE;
153 else
154 type->typestring_offset = 1;
157 static int is_embedded_complex(const type_t *type)
159 unsigned char tc = type->type;
160 return is_struct(tc) || is_union(tc) || is_array(type);
163 static long field_offset(const type_t *strct, const char *name, var_t **pfield)
165 long offset = 0;
166 var_list_t *fields = strct->fields;
167 var_t *f;
169 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
171 unsigned int align = 0;
173 if (f->name != NULL && strcmp(name, f->name) == 0)
175 if (pfield) *pfield = f;
176 return offset;
178 else
180 /* FIXME: handle possible padding */
181 offset += type_memsize(f->type, &align);
185 if (pfield) *pfield = NULL;
186 return -1;
189 static int compare_expr(const expr_t *a, const expr_t *b)
191 int ret;
193 if (a->type != b->type)
194 return a->type - b->type;
196 switch (a->type)
198 case EXPR_NUM:
199 case EXPR_HEXNUM:
200 case EXPR_TRUEFALSE:
201 return a->u.lval - b->u.lval;
202 case EXPR_IDENTIFIER:
203 return strcmp(a->u.sval, b->u.sval);
204 case EXPR_COND:
205 ret = compare_expr(a->ref, b->ref);
206 if (ret != 0)
207 return ret;
208 ret = compare_expr(a->u.ext, b->u.ext);
209 if (ret != 0)
210 return ret;
211 return compare_expr(a->ext2, b->ext2);
212 case EXPR_OR:
213 case EXPR_AND:
214 case EXPR_ADD:
215 case EXPR_SUB:
216 case EXPR_MUL:
217 case EXPR_DIV:
218 case EXPR_SHL:
219 case EXPR_SHR:
220 ret = compare_expr(a->ref, b->ref);
221 if (ret != 0)
222 return ret;
223 return compare_expr(a->u.ext, b->u.ext);
224 case EXPR_NOT:
225 case EXPR_NEG:
226 case EXPR_PPTR:
227 case EXPR_CAST:
228 case EXPR_SIZEOF:
229 return compare_expr(a->ref, b->ref);
230 case EXPR_VOID:
231 return 0;
233 return -1;
236 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
237 do { \
238 if (file) \
239 fprintf(file, "/* %2u */\n", typestring_offset); \
240 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
242 while (0)
244 static int print_file(FILE *file, int indent, const char *format, ...)
246 va_list va;
247 int i, r;
249 if (!file) return 0;
251 va_start(va, format);
252 for (i = 0; i < indent; i++)
253 fprintf(file, " ");
254 r = vfprintf(file, format, va);
255 va_end(va);
256 return r;
259 static void write_formatdesc(FILE *f, int indent, const char *str)
261 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
262 print_file(f, indent, "{\n");
263 print_file(f, indent + 1, "short Pad;\n");
264 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
265 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
266 print_file(f, indent, "\n");
269 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, int for_objects)
271 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
272 get_size_typeformatstring(ifaces, for_objects));
274 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
275 get_size_procformatstring(ifaces, for_objects));
277 fprintf(f, "\n");
278 write_formatdesc(f, indent, "TYPE");
279 write_formatdesc(f, indent, "PROC");
280 fprintf(f, "\n");
281 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
282 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
283 print_file(f, indent, "\n");
286 static int is_user_derived(const var_t *v)
288 const type_t *type = v->type;
290 if (v->attrs && is_attr( v->attrs, ATTR_WIREMARSHAL )) return 1;
292 while (type)
294 if (type->attrs && is_attr( type->attrs, ATTR_WIREMARSHAL )) return 1;
295 type = type->ref;
297 return 0;
300 static inline int is_base_type(unsigned char type)
302 switch (type)
304 case RPC_FC_BYTE:
305 case RPC_FC_CHAR:
306 case RPC_FC_USMALL:
307 case RPC_FC_SMALL:
308 case RPC_FC_WCHAR:
309 case RPC_FC_USHORT:
310 case RPC_FC_SHORT:
311 case RPC_FC_ULONG:
312 case RPC_FC_LONG:
313 case RPC_FC_HYPER:
314 case RPC_FC_IGNORE:
315 case RPC_FC_FLOAT:
316 case RPC_FC_DOUBLE:
317 case RPC_FC_ENUM16:
318 case RPC_FC_ENUM32:
319 case RPC_FC_ERROR_STATUS_T:
320 case RPC_FC_BIND_PRIMITIVE:
321 return TRUE;
323 default:
324 return FALSE;
328 static size_t write_procformatstring_var(FILE *file, int indent,
329 const var_t *var, int is_return)
331 size_t size;
332 const type_t *type = var->type;
334 int is_in = is_attr(var->attrs, ATTR_IN);
335 int is_out = is_attr(var->attrs, ATTR_OUT);
337 if (!is_in && !is_out) is_in = TRUE;
339 if (!type->declarray && is_base_type(type->type))
341 if (is_return)
342 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
343 else
344 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
346 if (type->type == RPC_FC_BIND_PRIMITIVE)
348 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
349 size = 2; /* includes param type prefix */
351 else if (is_base_type(type->type))
353 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
354 size = 2; /* includes param type prefix */
356 else
358 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
359 size = 0;
362 else
364 if (is_return)
365 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
366 else if (is_in && is_out)
367 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
368 else if (is_out)
369 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
370 else
371 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
373 print_file(file, indent, "0x01,\n");
374 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
375 size = 4; /* includes param type prefix */
377 return size;
380 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
382 const ifref_t *iface;
383 int indent = 0;
384 const var_t *var;
386 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
387 print_file(file, indent, "{\n");
388 indent++;
389 print_file(file, indent, "0,\n");
390 print_file(file, indent, "{\n");
391 indent++;
393 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
395 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
396 continue;
398 if (iface->iface->funcs)
400 const func_t *func;
401 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
403 if (is_local(func->def->attrs)) continue;
404 /* emit argument data */
405 if (func->args)
407 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
408 write_procformatstring_var(file, indent, var, FALSE);
411 /* emit return value data */
412 var = func->def;
413 if (is_void(var->type))
415 print_file(file, indent, "0x5b, /* FC_END */\n");
416 print_file(file, indent, "0x5c, /* FC_PAD */\n");
418 else
419 write_procformatstring_var(file, indent, var, TRUE);
424 print_file(file, indent, "0x0\n");
425 indent--;
426 print_file(file, indent, "}\n");
427 indent--;
428 print_file(file, indent, "};\n");
429 print_file(file, indent, "\n");
432 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
434 if (is_base_type(type->type))
436 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
437 *typestring_offset += 1;
438 return 1;
441 return 0;
444 /* write conformance / variance descriptor */
445 static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_t *structure, const expr_t *expr)
447 unsigned char operator_type = 0;
448 const char *operator_string = "no operators";
449 const expr_t *subexpr;
450 unsigned char correlation_type;
452 if (!file) return 4; /* optimisation for sizing pass */
454 if (expr->is_const)
456 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
457 error("write_conf_or_var_desc: constant value %ld is greater than "
458 "the maximum constant size of %d\n", expr->cval,
459 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
461 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
462 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
463 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
464 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
466 return 4;
469 subexpr = expr;
470 switch (subexpr->type)
472 case EXPR_PPTR:
473 subexpr = subexpr->ref;
474 operator_type = RPC_FC_DEREFERENCE;
475 operator_string = "FC_DEREFERENCE";
476 break;
477 case EXPR_DIV:
478 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
480 subexpr = subexpr->ref;
481 operator_type = RPC_FC_DIV_2;
482 operator_string = "FC_DIV_2";
484 break;
485 case EXPR_MUL:
486 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
488 subexpr = subexpr->ref;
489 operator_type = RPC_FC_MULT_2;
490 operator_string = "FC_MULT_2";
492 break;
493 case EXPR_SUB:
494 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
496 subexpr = subexpr->ref;
497 operator_type = RPC_FC_SUB_1;
498 operator_string = "FC_SUB_1";
500 break;
501 case EXPR_ADD:
502 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
504 subexpr = subexpr->ref;
505 operator_type = RPC_FC_ADD_1;
506 operator_string = "FC_ADD_1";
508 break;
509 default:
510 break;
513 if (subexpr->type == EXPR_IDENTIFIER)
515 const type_t *correlation_variable = NULL;
516 unsigned char correlation_variable_type;
517 unsigned char param_type = 0;
518 const char *param_type_string = NULL;
519 size_t offset;
521 if (structure)
523 const var_t *var;
525 offset = 0;
526 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
528 unsigned int align = 0;
529 offset -= type_memsize(var->type, &align);
530 /* FIXME: take alignment into account */
531 if (!strcmp(var->name, subexpr->u.sval))
533 correlation_variable = var->type;
534 break;
537 if (!correlation_variable)
538 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
539 subexpr->u.sval);
541 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
543 else
545 const var_t *var;
547 offset = sizeof(void *);
548 if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
550 if (!strcmp(var->name, subexpr->u.sval))
552 correlation_variable = var->type;
553 break;
555 /* FIXME: not all stack variables are sizeof(void *) */
556 offset += sizeof(void *);
558 if (!correlation_variable)
559 error("write_conf_or_var_desc: couldn't find variable %s in function\n",
560 subexpr->u.sval);
562 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
565 correlation_variable_type = correlation_variable->type;
567 switch (correlation_variable_type)
569 case RPC_FC_CHAR:
570 case RPC_FC_SMALL:
571 param_type = RPC_FC_SMALL;
572 param_type_string = "FC_SMALL";
573 break;
574 case RPC_FC_BYTE:
575 case RPC_FC_USMALL:
576 param_type = RPC_FC_USMALL;
577 param_type_string = "FC_USMALL";
578 break;
579 case RPC_FC_WCHAR:
580 case RPC_FC_SHORT:
581 param_type = RPC_FC_SHORT;
582 param_type_string = "FC_SHORT";
583 break;
584 case RPC_FC_USHORT:
585 param_type = RPC_FC_USHORT;
586 param_type_string = "FC_USHORT";
587 break;
588 case RPC_FC_LONG:
589 param_type = RPC_FC_LONG;
590 param_type_string = "FC_LONG";
591 break;
592 case RPC_FC_ULONG:
593 param_type = RPC_FC_ULONG;
594 param_type_string = "FC_ULONG";
595 break;
596 case RPC_FC_RP:
597 case RPC_FC_UP:
598 case RPC_FC_OP:
599 case RPC_FC_FP:
600 if (sizeof(void *) == 4) /* FIXME */
602 param_type = RPC_FC_LONG;
603 param_type_string = "FC_LONG";
605 else
607 param_type = RPC_FC_HYPER;
608 param_type_string = "FC_HYPER";
610 break;
611 default:
612 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
613 correlation_variable_type);
616 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
617 correlation_type | param_type,
618 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter, " : "",
619 param_type_string);
620 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
621 print_file(file, 2, "NdrFcShort(0x%x), /* %soffset = %d */\n",
622 offset,
623 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "x86 stack size / " : "",
624 offset);
626 else
628 unsigned int callback_offset = 0;
630 if (structure)
632 struct expr_eval_routine *eval;
633 int found = 0;
635 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
637 if (!strcmp(eval->structure->name, structure->name) &&
638 !compare_expr(eval->expr, expr))
640 found = 1;
641 break;
643 callback_offset++;
646 if (!found)
648 unsigned int align = 0;
649 eval = xmalloc(sizeof(*eval));
650 eval->structure = structure;
651 eval->structure_size = fields_memsize(structure->fields, &align);
652 eval->expr = expr;
653 list_add_tail(&expr_eval_routines, &eval->entry);
656 correlation_type = RPC_FC_NORMAL_CONFORMANCE;
658 else
660 error("write_conf_or_var_desc: top-level callback conformance unimplemented\n");
661 correlation_type = RPC_FC_TOP_LEVEL_CONFORMANCE;
664 if (callback_offset > USHRT_MAX)
665 error("Maximum number of callback routines reached\n");
667 print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
668 correlation_type,
669 correlation_type == RPC_FC_TOP_LEVEL_CONFORMANCE ? "parameter" : "");
670 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
671 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
673 return 4;
676 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
678 size_t size = 0;
679 const var_t *v;
681 if (!fields) return 0;
682 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
683 size += type_memsize(v->type, align);
685 return size;
688 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
690 size_t size, maxs = 0;
691 unsigned int align = *pmaxa;
692 const var_t *v;
694 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
696 /* we could have an empty default field with NULL type */
697 if (v->type)
699 size = type_memsize(v->type, &align);
700 if (maxs < size) maxs = size;
701 if (*pmaxa < align) *pmaxa = align;
705 return maxs;
708 size_t type_memsize(const type_t *t, unsigned int *align)
710 size_t size = 0;
712 if (is_ptr(t))
714 size = sizeof(void *);
715 if (size > *align) *align = size;
717 else switch (t->type)
719 case RPC_FC_BYTE:
720 case RPC_FC_CHAR:
721 case RPC_FC_USMALL:
722 case RPC_FC_SMALL:
723 size = 1;
724 if (size > *align) *align = size;
725 break;
726 case RPC_FC_WCHAR:
727 case RPC_FC_USHORT:
728 case RPC_FC_SHORT:
729 case RPC_FC_ENUM16:
730 size = 2;
731 if (size > *align) *align = size;
732 break;
733 case RPC_FC_ULONG:
734 case RPC_FC_LONG:
735 case RPC_FC_ERROR_STATUS_T:
736 case RPC_FC_ENUM32:
737 case RPC_FC_FLOAT:
738 size = 4;
739 if (size > *align) *align = size;
740 break;
741 case RPC_FC_HYPER:
742 case RPC_FC_DOUBLE:
743 size = 8;
744 if (size > *align) *align = size;
745 break;
746 case RPC_FC_STRUCT:
747 case RPC_FC_CVSTRUCT:
748 case RPC_FC_CPSTRUCT:
749 case RPC_FC_CSTRUCT:
750 case RPC_FC_PSTRUCT:
751 case RPC_FC_BOGUS_STRUCT:
752 size = fields_memsize(t->fields, align);
753 break;
754 case RPC_FC_ENCAPSULATED_UNION:
755 case RPC_FC_NON_ENCAPSULATED_UNION:
756 size = union_memsize(t->fields, align);
757 break;
758 case RPC_FC_SMFARRAY:
759 case RPC_FC_LGFARRAY:
760 case RPC_FC_SMVARRAY:
761 case RPC_FC_LGVARRAY:
762 size = t->dim * type_memsize(t->ref, align);
763 break;
764 case RPC_FC_CARRAY:
765 case RPC_FC_CVARRAY:
766 case RPC_FC_BOGUS_ARRAY:
767 size = type_memsize(t->ref, align);
768 break;
769 default:
770 error("type_memsize: Unknown type %d\n", t->type);
771 size = 0;
774 return size;
777 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
779 short absoff = type->ref->typestring_offset;
780 short reloff = absoff - (offset + 2);
781 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
783 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
784 type->type, ptr_attr, string_of_type(type->type));
785 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
786 reloff, reloff, absoff);
787 return 4;
790 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
792 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
793 type->type, string_of_type(type->type));
794 print_file(file, 2, "0x%02x,\t/* %s */\n", type->ref->type,
795 string_of_type(type->ref->type));
796 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
797 return 4;
800 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
802 unsigned int offset = *typestring_offset;
804 print_file(file, 0, "/* %d */\n", offset);
805 update_tfsoff(type, offset, file);
807 if (type->ref->typestring_offset)
808 *typestring_offset += write_nonsimple_pointer(file, type, offset);
809 else if (is_base_type(type->ref->type))
810 *typestring_offset += write_simple_pointer(file, type);
812 return offset;
815 static int processed(const type_t *type)
817 return type->typestring_offset && !type->tfswrite;
820 static void write_member_type(FILE *file, type_t *type, const var_t *field,
821 unsigned int *tfsoff)
823 if (is_ptr(type))
825 print_file(file, 2, "0x8,\t/* FC_LONG */\n");
826 *tfsoff += 1;
828 else if (is_embedded_complex(type))
830 size_t absoff = (field && field->corrdesc
831 ? field->corrdesc
832 : type->typestring_offset);
833 short reloff = absoff - (*tfsoff + 2);
835 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
836 /* FIXME: actually compute necessary padding */
837 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
838 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
839 reloff, reloff, absoff);
840 *tfsoff += 4;
842 else if (!write_base_type(file, type, tfsoff))
843 error("Unsupported member type 0x%x\n", type->type);
846 static void write_end(FILE *file, unsigned int *tfsoff)
848 if (*tfsoff % 2 == 0)
850 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
851 *tfsoff += 1;
853 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
854 *tfsoff += 1;
857 static size_t write_pointer_description(FILE *file, type_t *type, size_t mem_offset,
858 int level, unsigned int *typestring_offset)
860 const var_t *v;
861 unsigned int align = 0;
863 /* don't generate a pointer for first-level arrays since we want to
864 * descend into them to write their pointers, not stop here */
865 if (level == 0 && is_array(type))
867 write_pointer_description(file, type->ref, mem_offset, level + 1,
868 typestring_offset);
870 else if (is_ptr(type))
872 print_file(file, 2, "0x46,\t/* FC_NO_REPEAT */\n");
873 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
874 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset);
875 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset);
876 *typestring_offset += 6;
878 if (processed(type->ref) || is_base_type(type->ref->type))
879 write_pointer_tfs(file, type, typestring_offset);
880 else
881 error("write_pointer_description: type format string unknown\n");
883 else if (level == 0 && is_struct(type->type))
885 if (type->fields)
887 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
888 mem_offset
889 += write_pointer_description(file, v->type, mem_offset,
890 level + 1, typestring_offset);
894 return type_memsize(type, &align);
897 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
898 const type_t *type,
899 const char *name, unsigned int *typestring_offset)
901 size_t start_offset = *typestring_offset;
902 unsigned char flags = 0;
903 int pointer_type;
904 unsigned char rtype;
906 if (is_ptr(type))
908 pointer_type = type->type;
909 type = type->ref;
911 else
912 pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
914 if (!pointer_type)
915 pointer_type = RPC_FC_RP;
917 if (!get_attrp(attrs, ATTR_SIZEIS))
918 flags |= RPC_FC_P_SIMPLEPOINTER;
920 rtype = type->type;
922 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
924 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
925 return start_offset;
928 print_file(file, 2,"0x%x, 0x%x, /* %s%s */\n",
929 pointer_type, flags,
930 pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"),
931 (flags & RPC_FC_P_SIMPLEPOINTER) ? " [simple_pointer]" : "");
932 *typestring_offset += 2;
934 if (!(flags & RPC_FC_P_SIMPLEPOINTER))
936 print_file(file, 2, "NdrFcShort(0x2),\n");
937 *typestring_offset += 2;
940 if (type->declarray && !is_conformant_array(type))
942 /* FIXME: multi-dimensional array */
943 if (0xffffuL < type->dim)
944 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
945 name, 0xffffu, type->dim - 0xffffu);
947 if (rtype == RPC_FC_CHAR)
948 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
949 else
950 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
951 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
952 *typestring_offset += 2;
954 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
955 *typestring_offset += 2;
957 return start_offset;
959 else if (type->size_is)
961 if (rtype == RPC_FC_CHAR)
962 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
963 else
964 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
965 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
966 *typestring_offset += 2;
968 *typestring_offset += write_conf_or_var_desc(file, current_func, NULL, type->size_is);
970 return start_offset;
972 else
974 if (rtype == RPC_FC_CHAR)
975 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
976 else
977 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
978 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
979 *typestring_offset += 2;
981 return start_offset;
985 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
986 const char *name, unsigned int *typestring_offset)
988 const expr_t *length_is = type->length_is;
989 const expr_t *size_is = type->size_is;
990 unsigned int align = 0;
991 size_t size;
992 size_t start_offset;
993 int has_pointer;
994 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
995 if (!pointer_type)
996 pointer_type = RPC_FC_RP;
998 has_pointer = FALSE;
999 if (write_embedded_types(file, attrs, type, name, 0, typestring_offset))
1000 has_pointer = TRUE;
1002 size = type_memsize(type, &align);
1004 start_offset = *typestring_offset;
1005 update_tfsoff(type, start_offset, file);
1006 print_file(file, 0, "/* %lu */\n", start_offset);
1007 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1008 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1009 *typestring_offset += 2;
1011 if (type->type != RPC_FC_BOGUS_ARRAY)
1013 unsigned char tc = type->type;
1015 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1017 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1018 *typestring_offset += 4;
1020 else
1022 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1023 *typestring_offset += 2;
1026 if (is_conformant_array(type))
1027 *typestring_offset
1028 += write_conf_or_var_desc(file, current_func,
1029 current_structure, size_is);
1031 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1033 unsigned int elalign = 0;
1034 size_t elsize = type_memsize(type->ref, &elalign);
1036 if (type->type == RPC_FC_LGVARRAY)
1038 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1039 *typestring_offset += 4;
1041 else
1043 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1044 *typestring_offset += 2;
1047 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1048 *typestring_offset += 2;
1051 if (length_is)
1052 *typestring_offset
1053 += write_conf_or_var_desc(file, current_func,
1054 current_structure, length_is);
1056 if (has_pointer)
1058 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1059 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1060 *typestring_offset += 2;
1061 write_pointer_description(file, type, 0, 0, typestring_offset);
1062 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1063 *typestring_offset += 1;
1066 write_member_type(file, type->ref, NULL, typestring_offset);
1067 write_end(file, typestring_offset);
1069 else
1070 error("%s: complex arrays unimplemented\n", name);
1072 return start_offset;
1075 static const var_t *find_array_or_string_in_struct(const type_t *type)
1077 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1079 if (last_field->type->declarray)
1080 return last_field;
1082 assert((last_field->type->type == RPC_FC_CSTRUCT) ||
1083 (last_field->type->type == RPC_FC_CPSTRUCT) ||
1084 (last_field->type->type == RPC_FC_CVSTRUCT));
1086 return find_array_or_string_in_struct(last_field->type);
1089 static void write_struct_members(FILE *file, const type_t *type, unsigned int *typestring_offset)
1091 const var_t *field;
1093 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1094 write_member_type(file, field->type, field, typestring_offset);
1096 write_end(file, typestring_offset);
1099 static size_t write_struct_tfs(FILE *file, type_t *type,
1100 const char *name, unsigned int *typestring_offset)
1102 unsigned int total_size;
1103 const var_t *array;
1104 size_t start_offset;
1105 size_t array_offset;
1106 int has_pointers;
1107 unsigned int align = 0;
1109 guard_rec(type);
1111 switch (type->type)
1113 case RPC_FC_STRUCT:
1114 case RPC_FC_PSTRUCT:
1115 total_size = type_memsize(type, &align);
1117 if (total_size > USHRT_MAX)
1118 error("structure size for %s exceeds %d bytes by %d bytes\n",
1119 name, USHRT_MAX, total_size - USHRT_MAX);
1121 if (type->type == RPC_FC_PSTRUCT)
1122 write_embedded_types(file, NULL, type, name, 0, typestring_offset);
1124 start_offset = *typestring_offset;
1125 update_tfsoff(type, start_offset, file);
1126 if (type->type == RPC_FC_STRUCT)
1127 WRITE_FCTYPE(file, FC_STRUCT, *typestring_offset);
1128 else
1129 WRITE_FCTYPE(file, FC_PSTRUCT, *typestring_offset);
1130 /* alignment */
1131 print_file(file, 2, "0x%02x,\n", align - 1);
1132 /* total size */
1133 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1134 *typestring_offset += 4;
1136 if (type->type == RPC_FC_PSTRUCT)
1138 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1139 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1140 *typestring_offset += 2;
1141 write_pointer_description(file, type, 0, 0, typestring_offset);
1142 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1143 *typestring_offset += 1;
1146 /* member layout */
1147 current_structure = type;
1148 write_struct_members(file, type, typestring_offset);
1149 current_structure = NULL;
1150 return start_offset;
1151 case RPC_FC_CSTRUCT:
1152 case RPC_FC_CPSTRUCT:
1153 total_size = type_memsize(type, &align);
1155 if (total_size > USHRT_MAX)
1156 error("structure size for %s exceeds %d bytes by %d bytes\n",
1157 name, USHRT_MAX, total_size - USHRT_MAX);
1159 array = find_array_or_string_in_struct(type);
1160 current_structure = type;
1161 array_offset = write_array_tfs(file, array->attrs, array->type,
1162 array->name, typestring_offset);
1163 current_structure = NULL;
1165 if (type->type == RPC_FC_CPSTRUCT)
1166 write_embedded_types(file, NULL, type, name, 0, typestring_offset);
1168 start_offset = *typestring_offset;
1169 update_tfsoff(type, start_offset, file);
1170 if (type->type == RPC_FC_CSTRUCT)
1171 WRITE_FCTYPE(file, FC_CSTRUCT, *typestring_offset);
1172 else
1173 WRITE_FCTYPE(file, FC_CPSTRUCT, *typestring_offset);
1174 /* alignment */
1175 print_file(file, 2, "0x%02x,\n", align - 1);
1176 /* total size */
1177 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1178 *typestring_offset += 4;
1179 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1180 array_offset - *typestring_offset,
1181 array_offset - *typestring_offset,
1182 array_offset);
1183 *typestring_offset += 2;
1185 if (type->type == RPC_FC_CPSTRUCT)
1187 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1188 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1189 *typestring_offset += 2;
1190 write_pointer_description(file, type, 0, 0, typestring_offset);
1191 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1192 *typestring_offset += 1;
1195 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1196 *typestring_offset += 1;
1198 return start_offset;
1199 case RPC_FC_CVSTRUCT:
1200 total_size = type_memsize(type, &align);
1202 if (total_size > USHRT_MAX)
1203 error("structure size for %s exceeds %d bytes by %d bytes\n",
1204 name, USHRT_MAX, total_size - USHRT_MAX);
1206 array = find_array_or_string_in_struct(type);
1207 current_structure = type;
1208 if (is_attr(array->attrs, ATTR_STRING))
1209 array_offset = write_string_tfs(file, array->attrs, array->type,
1210 array->name, typestring_offset);
1211 else
1212 array_offset = write_array_tfs(file, array->attrs, array->type,
1213 array->name, typestring_offset);
1214 current_structure = NULL;
1216 has_pointers = write_embedded_types(file, NULL, type, name, 0,
1217 typestring_offset);
1219 start_offset = *typestring_offset;
1220 update_tfsoff(type, start_offset, file);
1221 WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset);
1222 /* alignment */
1223 print_file(file, 2, "0x%02x,\n", align - 1);
1224 /* total size */
1225 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", total_size, total_size);
1226 *typestring_offset += 4;
1227 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d (%u) */\n",
1228 array_offset - *typestring_offset,
1229 array_offset - *typestring_offset,
1230 array_offset);
1231 *typestring_offset += 2;
1233 if (has_pointers)
1235 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1236 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1237 *typestring_offset += 2;
1238 write_pointer_description(file, type, 0, 0, typestring_offset);
1239 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1240 *typestring_offset += 1;
1243 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1244 *typestring_offset += 1;
1246 return start_offset;
1248 case RPC_FC_BOGUS_STRUCT:
1249 total_size = type_memsize(type, &align);
1250 if (total_size > USHRT_MAX)
1251 error("structure size for %s exceeds %d bytes by %d bytes\n",
1252 name, USHRT_MAX, total_size - USHRT_MAX);
1254 write_embedded_types(file, NULL, type, name, 0, typestring_offset);
1256 start_offset = *typestring_offset;
1257 update_tfsoff(type, start_offset, file);
1258 print_file(file, 0, "/* %d */\n", start_offset);
1259 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1260 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1261 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1263 /* do conformant array stuff */
1264 print_file(file, 2, "NdrFcShort(0x0),\t/* FIXME: conformant array stuff */\n");
1266 /* do pointer stuff here */
1267 print_file(file, 2, "NdrFcShort(0x0),\t/* FIXME: pointer stuff */\n");
1269 *typestring_offset += 8;
1270 current_structure = type;
1271 write_struct_members(file, type, typestring_offset);
1272 current_structure = NULL;
1274 return start_offset;
1276 default:
1277 error("write_struct_tfs: Unimplemented for type 0x%x\n", type->type);
1278 return *typestring_offset;
1282 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1283 unsigned char flags, size_t offset,
1284 unsigned int *typeformat_offset)
1286 size_t start_offset = *typeformat_offset;
1287 short reloff = offset - (*typeformat_offset + 2);
1288 int in_attr, out_attr;
1289 in_attr = is_attr(attrs, ATTR_IN);
1290 out_attr = is_attr(attrs, ATTR_OUT);
1291 if (!in_attr && !out_attr) in_attr = 1;
1293 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1294 flags |= 0x04;
1296 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1297 pointer_type,
1298 flags,
1299 string_of_type(pointer_type));
1300 if (file)
1302 if (flags & 0x04)
1303 fprintf(file, " [allocated_on_stack]");
1304 if (flags & 0x10)
1305 fprintf(file, " [pointer_deref]");
1306 fprintf(file, " */\n");
1309 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1310 *typeformat_offset += 4;
1312 return start_offset;
1315 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1317 if (is_base_type(t->type))
1319 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1320 t->type, string_of_type(t->type));
1322 else if (t->typestring_offset)
1324 short reloff = t->typestring_offset - *tfsoff;
1325 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1326 reloff, reloff, t->typestring_offset);
1328 else
1329 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1331 *tfsoff += 2;
1334 static size_t write_union_tfs(FILE *file, type_t *type, const char *name,
1335 unsigned int *tfsoff)
1337 unsigned int align = 0;
1338 unsigned int start_offset;
1339 size_t size = type_memsize(type, &align);
1340 var_list_t *fields = type->fields;
1341 size_t nbranch = 0;
1342 type_t *deftype = NULL;
1343 short nodeftype = 0xffff;
1344 var_t *f;
1346 guard_rec(type);
1348 /* use a level of 1 so pointers always get written */
1349 write_embedded_types(file, NULL, type, name, 1, tfsoff);
1351 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1353 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1354 if (cases)
1355 nbranch += list_count(cases);
1358 start_offset = *tfsoff;
1359 update_tfsoff(type, start_offset, file);
1360 print_file(file, 0, "/* %d */\n", start_offset);
1361 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1362 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1363 *tfsoff += 4;
1365 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1367 type_t *ft = f->type;
1368 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1369 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1370 expr_t *c;
1372 if (cases == NULL && !deflt)
1373 error("union field %s with neither case nor default attribute\n", f->name);
1375 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1377 /* MIDL doesn't check for duplicate cases, even though that seems
1378 like a reasonable thing to do, it just dumps them to the TFS
1379 like we're going to do here. */
1380 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1381 *tfsoff += 4;
1382 write_branch_type(file, ft, tfsoff);
1385 /* MIDL allows multiple default branches, even though that seems
1386 illogical, it just chooses the last one, which is what we will
1387 do. */
1388 if (deflt)
1390 deftype = ft;
1391 nodeftype = 0;
1395 if (deftype)
1397 write_branch_type(file, deftype, tfsoff);
1399 else
1401 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1402 *tfsoff += 2;
1405 return start_offset;
1408 static size_t write_ip_tfs(FILE *file, const func_t *func, const type_t *type, const var_t *var,
1409 unsigned int *typeformat_offset)
1411 size_t i;
1412 size_t start_offset = *typeformat_offset;
1413 const var_t *iid = get_attrp(var->attrs, ATTR_IIDIS);
1415 if (iid)
1417 expr_t expr;
1419 expr.type = EXPR_IDENTIFIER;
1420 expr.ref = NULL;
1421 expr.u.sval = iid->name;
1422 expr.is_const = FALSE;
1423 print_file(file, 2, "0x2f, /* FC_IP */\n");
1424 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1425 *typeformat_offset += write_conf_or_var_desc(file, func, NULL, &expr) + 2;
1427 else
1429 const type_t *base = is_ptr(type) ? type->ref : type;
1430 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1432 if (! uuid)
1433 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1435 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1436 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1437 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1438 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1439 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1440 for (i = 0; i < 8; ++i)
1441 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1443 if (file)
1444 fprintf(file, "\n");
1446 *typeformat_offset += 18;
1448 return start_offset;
1451 static int get_ptr_attr(const type_t *t, int def_type)
1453 while (TRUE)
1455 int ptr_attr = get_attrv(t->attrs, ATTR_POINTERTYPE);
1456 if (ptr_attr)
1457 return ptr_attr;
1458 if (t->kind != TKIND_ALIAS)
1459 return def_type;
1460 t = t->orig;
1464 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
1465 type_t *type, const var_t *var,
1466 unsigned int *typeformat_offset)
1468 int pointer_type;
1469 size_t offset;
1471 if (type == var->type) /* top-level pointers */
1473 int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE);
1474 if (pointer_attr != 0 && !is_ptr(type) && !is_array(type))
1475 error("'%s': pointer attribute applied to non-pointer type\n", var->name);
1477 if (pointer_attr == 0)
1478 pointer_attr = get_ptr_attr(type, RPC_FC_RP);
1480 pointer_type = pointer_attr;
1482 else
1483 pointer_type = get_ptr_attr(type, RPC_FC_UP);
1485 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
1486 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
1488 if (is_array(type))
1489 return write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
1491 if (!is_ptr(type))
1493 /* basic types don't need a type format string */
1494 if (is_base_type(type->type))
1495 return 0;
1497 switch (type->type)
1499 case RPC_FC_STRUCT:
1500 case RPC_FC_PSTRUCT:
1501 case RPC_FC_CSTRUCT:
1502 case RPC_FC_CPSTRUCT:
1503 case RPC_FC_CVSTRUCT:
1504 case RPC_FC_BOGUS_STRUCT:
1505 return write_struct_tfs(file, type, var->name, typeformat_offset);
1506 case RPC_FC_ENCAPSULATED_UNION:
1507 case RPC_FC_NON_ENCAPSULATED_UNION:
1508 return write_union_tfs(file, type, var->name, typeformat_offset);
1509 case RPC_FC_IGNORE:
1510 case RPC_FC_BIND_PRIMITIVE:
1511 /* nothing to do */
1512 return 0;
1513 default:
1514 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
1517 else if (last_ptr(type))
1519 size_t start_offset = *typeformat_offset;
1520 int in_attr = is_attr(var->attrs, ATTR_IN);
1521 int out_attr = is_attr(var->attrs, ATTR_OUT);
1522 const type_t *base = type->ref;
1524 if (base->type == RPC_FC_IP)
1526 return write_ip_tfs(file, func, type, var, typeformat_offset);
1529 /* special case for pointers to base types */
1530 if (is_base_type(base->type))
1532 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
1533 pointer_type, (!in_attr && out_attr) ? 0x0C : 0x08,
1534 string_of_type(pointer_type),
1535 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
1536 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
1537 print_file(file, indent, "0x5c, /* FC_PAD */\n");
1538 *typeformat_offset += 4;
1539 return start_offset;
1543 assert(is_ptr(type));
1545 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
1546 if (file)
1547 fprintf(file, "/* %2u */\n", *typeformat_offset);
1548 return write_pointer_only_tfs(file, var->attrs, pointer_type,
1549 !last_ptr(type) ? 0x10 : 0,
1550 offset, typeformat_offset);
1553 static void set_tfswrite(type_t *type, int val)
1555 while (type->tfswrite != val)
1557 type->tfswrite = val;
1559 if (type->kind == TKIND_ALIAS)
1560 type = type->orig;
1561 else if (is_ptr(type))
1562 type = type->ref;
1563 else
1565 if (type->fields)
1567 var_t *v;
1568 LIST_FOR_EACH_ENTRY( v, type->fields, var_t, entry )
1569 set_tfswrite(v->type, val);
1572 return;
1577 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
1578 const char *name, int level, unsigned int *tfsoff)
1580 var_list_t *fields = type->fields;
1581 int retmask = 0;
1582 size_t offset = 0;
1583 var_t *f;
1585 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1587 unsigned int align = 0;
1588 type_t *ft = f->type;
1590 if (!ft) continue;
1591 else if (ft->type == RPC_FC_NON_ENCAPSULATED_UNION)
1593 expr_t *swexp = get_attrp(f->attrs, ATTR_SWITCHIS);
1594 const char *swname;
1595 var_t *swvar;
1596 size_t corroff;
1597 unsigned char corrdesc, op = 0;
1598 short creloff, ureloff;
1600 if (swexp == NULL)
1601 error("union %s needs a switch_is attribute\n", f->name);
1602 if (swexp->type != EXPR_IDENTIFIER)
1603 error("%s: only identifiers are supported for switch_is at this time\n",
1604 f->name);
1606 if (!processed(ft))
1607 write_union_tfs(file, ft, f->name, tfsoff);
1609 swname = swexp->u.sval;
1610 corroff = field_offset(type, swname, &swvar);
1611 corrdesc = swvar->type->type;
1612 creloff = corroff - offset;
1614 f->corrdesc = *tfsoff;
1615 ureloff = ft->typestring_offset - (f->corrdesc + 6);
1616 print_file(file, 0, "/* %d */\n", f->corrdesc);
1617 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1618 print_file(file, 2, "0x8,\t/* FIXME: support other switch types */\n");
1619 print_file(file, 2, "0x%x,\t/* Corr desc: %s */\n",
1620 corrdesc, string_of_type(corrdesc & 0xf));
1621 print_file(file, 2, "0x%x,\n", op);
1622 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %hd */\n", creloff, creloff);
1623 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1624 ureloff, ureloff, ft->typestring_offset);
1625 *tfsoff += 8;
1627 else
1628 retmask |= write_embedded_types(file, attrs, ft, f->name,
1629 level + 1, tfsoff);
1631 /* FIXME: this doesn't take alignment/padding into account */
1632 offset += type_memsize(ft, &align);
1634 /* don't generate a pointer for first-level arrays since we want to
1635 descend into them to write their pointers, not stop here */
1636 else if (level == 0 && is_array(type))
1638 return write_embedded_types(file, NULL, type->ref, name, level + 1, tfsoff);
1640 else if (is_ptr(type))
1642 type_t *ref = type->ref;
1644 if (!processed(ref) && !is_base_type(ref->type))
1646 if (is_ptr(ref))
1648 retmask |= write_embedded_types(file, attrs, ref, name,
1649 level + 1, tfsoff);
1651 else if (is_struct(ref->type))
1653 write_struct_tfs(file, ref, name, tfsoff);
1655 else
1657 error("write_embedded_types: type format string unknown for %s (0x%x)\n",
1658 name, ref->type);
1662 /* top-level pointers are handled inline */
1663 if (1 < level)
1664 write_pointer_tfs(file, type, tfsoff);
1666 retmask |= 1;
1668 else if (is_array(type))
1670 retmask |= write_array_tfs(file, attrs, type, name, tfsoff);
1672 else if (!is_base_type(type->type))
1673 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
1674 name, type->type);
1676 return retmask;
1679 static void set_all_tfswrite(const ifref_list_t *ifaces, int val)
1681 const ifref_t * iface;
1682 const func_t *func;
1683 const var_t *var;
1685 if (ifaces)
1686 LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
1687 if (iface->iface->funcs)
1688 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
1689 if (func->args)
1690 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1691 set_tfswrite(var->type, val);
1694 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, int for_objects)
1696 const var_t *var;
1697 const ifref_t *iface;
1698 unsigned int typeformat_offset = 2;
1700 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
1702 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
1703 continue;
1705 if (iface->iface->funcs)
1707 const func_t *func;
1708 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
1710 if (is_local(func->def->attrs)) continue;
1712 current_func = func;
1713 if (func->args)
1714 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1715 update_tfsoff(
1716 var->type,
1717 write_typeformatstring_var(
1718 file, 2, func, var->type, var,
1719 &typeformat_offset),
1720 file);
1725 return typeformat_offset + 1;
1729 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_objects)
1731 int indent = 0;
1733 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
1734 print_file(file, indent, "{\n");
1735 indent++;
1736 print_file(file, indent, "0,\n");
1737 print_file(file, indent, "{\n");
1738 indent++;
1739 print_file(file, indent, "NdrFcShort(0x0),\n");
1741 set_all_tfswrite(ifaces, TRUE);
1742 process_tfs(file, ifaces, for_objects);
1744 print_file(file, indent, "0x0\n");
1745 indent--;
1746 print_file(file, indent, "}\n");
1747 indent--;
1748 print_file(file, indent, "};\n");
1749 print_file(file, indent, "\n");
1752 static unsigned int get_required_buffer_size_type(
1753 const type_t *type, const char *name, unsigned int *alignment)
1755 size_t size = 0;
1757 *alignment = 0;
1758 if (!is_ptr(type))
1760 switch (type->type)
1762 case RPC_FC_BYTE:
1763 case RPC_FC_CHAR:
1764 case RPC_FC_USMALL:
1765 case RPC_FC_SMALL:
1766 *alignment = 4;
1767 size = 1;
1768 break;
1770 case RPC_FC_WCHAR:
1771 case RPC_FC_USHORT:
1772 case RPC_FC_SHORT:
1773 *alignment = 4;
1774 size = 2;
1775 break;
1777 case RPC_FC_ULONG:
1778 case RPC_FC_LONG:
1779 case RPC_FC_FLOAT:
1780 case RPC_FC_ERROR_STATUS_T:
1781 *alignment = 4;
1782 size = 4;
1783 break;
1785 case RPC_FC_HYPER:
1786 case RPC_FC_DOUBLE:
1787 *alignment = 8;
1788 size = 8;
1789 break;
1791 case RPC_FC_IGNORE:
1792 case RPC_FC_BIND_PRIMITIVE:
1793 return 0;
1795 case RPC_FC_STRUCT:
1796 case RPC_FC_PSTRUCT:
1798 const var_t *field;
1799 if (!type->fields) return 0;
1800 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1802 unsigned int alignment;
1803 size += get_required_buffer_size_type(field->type, field->name,
1804 &alignment);
1806 break;
1809 case RPC_FC_RP:
1810 if (is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT)
1811 size = get_required_buffer_size_type( type->ref, name, alignment );
1812 break;
1814 case RPC_FC_SMFARRAY:
1815 case RPC_FC_LGFARRAY:
1816 size = type->dim * get_required_buffer_size_type(type->ref, name, alignment);
1817 break;
1819 case RPC_FC_SMVARRAY:
1820 case RPC_FC_LGVARRAY:
1821 get_required_buffer_size_type(type->ref, name, alignment);
1822 size = 0;
1823 break;
1825 case RPC_FC_CARRAY:
1826 case RPC_FC_CVARRAY:
1827 get_required_buffer_size_type(type->ref, name, alignment);
1828 size = sizeof(void *);
1829 break;
1831 default:
1832 error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
1833 return 0;
1836 return size;
1839 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
1841 int in_attr = is_attr(var->attrs, ATTR_IN);
1842 int out_attr = is_attr(var->attrs, ATTR_OUT);
1844 if (!in_attr && !out_attr)
1845 in_attr = 1;
1847 *alignment = 0;
1849 if (pass == PASS_OUT)
1851 if (out_attr && is_ptr(var->type))
1853 type_t *type = var->type;
1855 if (type->type == RPC_FC_STRUCT)
1857 const var_t *field;
1858 unsigned int size = 36;
1860 if (!type->fields) return size;
1861 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1863 unsigned int align;
1864 size += get_required_buffer_size_type(
1865 field->type, field->name, &align);
1867 return size;
1870 return 0;
1872 else
1874 if ((!out_attr || in_attr) && !var->type->size_is
1875 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
1877 if (is_ptr(var->type))
1879 type_t *type = var->type;
1881 if (is_base_type(type->type))
1883 return 25;
1885 else if (type->type == RPC_FC_STRUCT)
1887 unsigned int size = 36;
1888 const var_t *field;
1890 if (!type->fields) return size;
1891 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1893 unsigned int align;
1894 size += get_required_buffer_size_type(
1895 field->type, field->name, &align);
1897 return size;
1902 return get_required_buffer_size_type(var->type, var->name, alignment);
1906 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
1908 const var_t *var;
1909 unsigned int total_size = 0, alignment;
1911 if (func->args)
1913 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
1915 total_size += get_required_buffer_size(var, &alignment, pass);
1916 total_size += alignment;
1920 if (pass == PASS_OUT && !is_void(func->def->type))
1922 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
1923 total_size += alignment;
1925 return total_size;
1928 static void print_phase_function(FILE *file, int indent, const char *type,
1929 enum remoting_phase phase,
1930 const char *varname, unsigned int type_offset)
1932 const char *function;
1933 switch (phase)
1935 case PHASE_BUFFERSIZE:
1936 function = "BufferSize";
1937 break;
1938 case PHASE_MARSHAL:
1939 function = "Marshall";
1940 break;
1941 case PHASE_UNMARSHAL:
1942 function = "Unmarshall";
1943 break;
1944 case PHASE_FREE:
1945 function = "Free";
1946 break;
1947 default:
1948 assert(0);
1949 return;
1952 print_file(file, indent, "Ndr%s%s(\n", type, function);
1953 indent++;
1954 print_file(file, indent, "&_StubMsg,\n");
1955 print_file(file, indent, "%s%s,\n",
1956 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)&" : "(unsigned char *)",
1957 varname);
1958 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
1959 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
1960 if (phase == PHASE_UNMARSHAL)
1961 print_file(file, indent, "0);\n");
1962 indent--;
1965 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
1966 enum pass pass, const var_t *var,
1967 const char *varname)
1969 type_t *type = var->type;
1970 unsigned int size;
1971 unsigned int alignment = 0;
1972 unsigned char rtype;
1974 /* no work to do for other phases, buffer sizing is done elsewhere */
1975 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
1976 return;
1978 rtype = is_ptr(type) ? type->ref->type : type->type;
1980 switch (rtype)
1982 case RPC_FC_BYTE:
1983 case RPC_FC_CHAR:
1984 case RPC_FC_SMALL:
1985 case RPC_FC_USMALL:
1986 size = 1;
1987 alignment = 1;
1988 break;
1990 case RPC_FC_WCHAR:
1991 case RPC_FC_USHORT:
1992 case RPC_FC_SHORT:
1993 size = 2;
1994 alignment = 2;
1995 break;
1997 case RPC_FC_ULONG:
1998 case RPC_FC_LONG:
1999 case RPC_FC_FLOAT:
2000 case RPC_FC_ERROR_STATUS_T:
2001 size = 4;
2002 alignment = 4;
2003 break;
2005 case RPC_FC_HYPER:
2006 case RPC_FC_DOUBLE:
2007 size = 8;
2008 alignment = 8;
2009 break;
2011 case RPC_FC_IGNORE:
2012 case RPC_FC_BIND_PRIMITIVE:
2013 /* no marshalling needed */
2014 return;
2016 default:
2017 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2018 size = 0;
2021 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2022 alignment - 1, alignment - 1);
2024 if (phase == PHASE_MARSHAL)
2026 print_file(file, indent, "*(");
2027 write_type(file, is_ptr(type) ? type->ref : type, FALSE, NULL);
2028 if (is_ptr(type))
2029 fprintf(file, " *)_StubMsg.Buffer = *");
2030 else
2031 fprintf(file, " *)_StubMsg.Buffer = ");
2032 fprintf(file, varname);
2033 fprintf(file, ";\n");
2035 else if (phase == PHASE_UNMARSHAL)
2037 if (pass == PASS_IN || pass == PASS_RETURN)
2038 print_file(file, indent, "");
2039 else
2040 print_file(file, indent, "*");
2041 fprintf(file, varname);
2042 if (pass == PASS_IN && is_ptr(type))
2043 fprintf(file, " = (");
2044 else
2045 fprintf(file, " = *(");
2046 write_type(file, is_ptr(type) ? type->ref : type, FALSE, NULL);
2047 fprintf(file, " *)_StubMsg.Buffer;\n");
2050 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2051 write_type(file, var->type, FALSE, NULL);
2052 fprintf(file, ");\n");
2055 /* returns whether the MaxCount, Offset or ActualCount members need to be
2056 * filled in for the specified phase */
2057 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2059 return (phase != PHASE_UNMARSHAL);
2062 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2063 enum pass pass, enum remoting_phase phase)
2065 int in_attr, out_attr, pointer_type;
2066 const var_t *var;
2068 if (!func->args)
2069 return;
2071 if (phase == PHASE_BUFFERSIZE)
2073 unsigned int size = get_function_buffer_size( func, pass );
2074 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2077 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2079 const type_t *type = var->type;
2080 unsigned char rtype;
2081 size_t start_offset = type->typestring_offset;
2083 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2084 if (!pointer_type)
2085 pointer_type = RPC_FC_RP;
2087 in_attr = is_attr(var->attrs, ATTR_IN);
2088 out_attr = is_attr(var->attrs, ATTR_OUT);
2089 if (!in_attr && !out_attr)
2090 in_attr = 1;
2092 switch (pass)
2094 case PASS_IN:
2095 if (!in_attr) continue;
2096 break;
2097 case PASS_OUT:
2098 if (!out_attr) continue;
2099 break;
2100 case PASS_RETURN:
2101 break;
2104 rtype = type->type;
2106 if (is_user_derived( var ))
2108 print_phase_function(file, indent, "UserMarshal", phase, var->name, start_offset);
2110 else if (is_string_type(var->attrs, var->type))
2112 if (is_array(type) && !is_conformant_array(type))
2113 print_phase_function(file, indent, "NonConformantString", phase, var->name, start_offset);
2114 else
2116 if (type->size_is && is_size_needed_for_phase(phase))
2118 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2119 write_expr(file, type->size_is, 1);
2120 fprintf(file, ";\n");
2123 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2124 print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
2125 else
2126 print_phase_function(file, indent, "ConformantString", phase, var->name,
2127 start_offset + (type->size_is ? 4 : 2));
2130 else if (is_array(type))
2132 unsigned char tc = type->type;
2133 const char *array_type;
2135 if (tc == RPC_FC_SMFARRAY || tc == RPC_FC_LGFARRAY)
2136 array_type = "FixedArray";
2137 else if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2139 if (is_size_needed_for_phase(phase))
2141 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2142 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2143 write_expr(file, type->length_is, 1);
2144 fprintf(file, ";\n\n");
2146 array_type = "VaryingArray";
2148 else if (tc == RPC_FC_CARRAY)
2150 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2152 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2153 write_expr(file, type->size_is, 1);
2154 fprintf(file, ";\n\n");
2156 array_type = "ConformantArray";
2158 else if (tc == RPC_FC_CVARRAY)
2160 if (is_size_needed_for_phase(phase))
2162 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2163 write_expr(file, type->size_is, 1);
2164 fprintf(file, ";\n");
2165 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2166 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2167 write_expr(file, type->length_is, 1);
2168 fprintf(file, ";\n\n");
2170 array_type = "ConformantVaryingArray";
2172 else
2173 array_type = "ComplexArray";
2175 if (!in_attr && phase == PHASE_FREE)
2177 print_file(file, indent, "if (%s)\n", var->name);
2178 indent++;
2179 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2181 else if (phase != PHASE_FREE)
2183 if (pointer_type == RPC_FC_UP)
2184 print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
2185 else
2186 print_phase_function(file, indent, array_type, phase, var->name, start_offset);
2189 else if (!is_ptr(var->type) && is_base_type(rtype))
2191 print_phase_basetype(file, indent, phase, pass, var, var->name);
2193 else if (!is_ptr(var->type))
2195 switch (rtype)
2197 case RPC_FC_STRUCT:
2198 case RPC_FC_PSTRUCT:
2199 print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset);
2200 break;
2201 case RPC_FC_CSTRUCT:
2202 case RPC_FC_CPSTRUCT:
2203 print_phase_function(file, indent, "ConformantStruct", phase, var->name, start_offset);
2204 break;
2205 case RPC_FC_CVSTRUCT:
2206 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var->name, start_offset);
2207 break;
2208 case RPC_FC_BOGUS_STRUCT:
2209 print_phase_function(file, indent, "ComplexStruct", phase, var->name, start_offset);
2210 break;
2211 case RPC_FC_RP:
2212 if (is_base_type( var->type->ref->type ))
2214 print_phase_basetype(file, indent, phase, pass, var, var->name);
2216 else if (var->type->ref->type == RPC_FC_STRUCT)
2218 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2219 print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset + 4);
2221 else
2223 const var_t *iid;
2224 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2225 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2226 print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
2228 break;
2229 default:
2230 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2233 else
2235 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2237 print_phase_basetype(file, indent, phase, pass, var, var->name);
2239 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2241 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2242 print_phase_function(file, indent, "SimpleStruct", phase, var->name, 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->name, start_offset);
2252 fprintf(file, "\n");
2257 size_t get_size_procformatstring_var(const var_t *var)
2259 return write_procformatstring_var(NULL, 0, var, FALSE);
2263 size_t get_size_procformatstring_func(const func_t *func)
2265 const var_t *var;
2266 size_t size = 0;
2268 /* argument list size */
2269 if (func->args)
2270 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2271 size += get_size_procformatstring_var(var);
2273 /* return value size */
2274 if (is_void(func->def->type))
2275 size += 2; /* FC_END and FC_PAD */
2276 else
2277 size += get_size_procformatstring_var(func->def);
2279 return size;
2282 size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects)
2284 const ifref_t *iface;
2285 size_t size = 1;
2286 const func_t *func;
2288 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2290 if (for_objects != is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
2291 continue;
2293 if (iface->iface->funcs)
2294 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2295 if (!is_local(func->def->attrs))
2296 size += get_size_procformatstring_func( func );
2298 return size;
2301 size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects)
2303 set_all_tfswrite(ifaces, FALSE);
2304 return process_tfs(NULL, ifaces, for_objects);
2307 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2308 const var_list_t *fields, const char *structvar)
2310 switch (e->type) {
2311 case EXPR_VOID:
2312 break;
2313 case EXPR_NUM:
2314 fprintf(h, "%lu", e->u.lval);
2315 break;
2316 case EXPR_HEXNUM:
2317 fprintf(h, "0x%lx", e->u.lval);
2318 break;
2319 case EXPR_TRUEFALSE:
2320 if (e->u.lval == 0)
2321 fprintf(h, "FALSE");
2322 else
2323 fprintf(h, "TRUE");
2324 break;
2325 case EXPR_IDENTIFIER:
2327 const var_t *field;
2328 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2329 if (!strcmp(e->u.sval, field->name))
2331 fprintf(h, "%s->%s", structvar, e->u.sval);
2332 break;
2335 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2336 break;
2338 case EXPR_NEG:
2339 fprintf(h, "-");
2340 write_struct_expr(h, e->ref, 1, fields, structvar);
2341 break;
2342 case EXPR_NOT:
2343 fprintf(h, "~");
2344 write_struct_expr(h, e->ref, 1, fields, structvar);
2345 break;
2346 case EXPR_PPTR:
2347 fprintf(h, "*");
2348 write_struct_expr(h, e->ref, 1, fields, structvar);
2349 break;
2350 case EXPR_CAST:
2351 fprintf(h, "(");
2352 write_type(h, e->u.tref, FALSE, NULL);
2353 fprintf(h, ")");
2354 write_struct_expr(h, e->ref, 1, fields, structvar);
2355 break;
2356 case EXPR_SIZEOF:
2357 fprintf(h, "sizeof(");
2358 write_type(h, e->u.tref, FALSE, NULL);
2359 fprintf(h, ")");
2360 break;
2361 case EXPR_SHL:
2362 case EXPR_SHR:
2363 case EXPR_MUL:
2364 case EXPR_DIV:
2365 case EXPR_ADD:
2366 case EXPR_SUB:
2367 case EXPR_AND:
2368 case EXPR_OR:
2369 if (brackets) fprintf(h, "(");
2370 write_struct_expr(h, e->ref, 1, fields, structvar);
2371 switch (e->type) {
2372 case EXPR_SHL: fprintf(h, " << "); break;
2373 case EXPR_SHR: fprintf(h, " >> "); break;
2374 case EXPR_MUL: fprintf(h, " * "); break;
2375 case EXPR_DIV: fprintf(h, " / "); break;
2376 case EXPR_ADD: fprintf(h, " + "); break;
2377 case EXPR_SUB: fprintf(h, " - "); break;
2378 case EXPR_AND: fprintf(h, " & "); break;
2379 case EXPR_OR: fprintf(h, " | "); break;
2380 default: break;
2382 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2383 if (brackets) fprintf(h, ")");
2384 break;
2385 case EXPR_COND:
2386 if (brackets) fprintf(h, "(");
2387 write_struct_expr(h, e->ref, 1, fields, structvar);
2388 fprintf(h, " ? ");
2389 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2390 fprintf(h, " : ");
2391 write_struct_expr(h, e->ext2, 1, fields, structvar);
2392 if (brackets) fprintf(h, ")");
2393 break;
2398 void declare_stub_args( FILE *file, int indent, const func_t *func )
2400 int in_attr, out_attr;
2401 int i = 0;
2402 const var_t *def = func->def;
2403 const var_t *var;
2405 /* declare return value '_RetVal' */
2406 if (!is_void(def->type))
2408 print_file(file, indent, "");
2409 write_type_left(file, def->type);
2410 fprintf(file, " _RetVal;\n");
2413 if (!func->args)
2414 return;
2416 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2418 int is_string = is_attr(var->attrs, ATTR_STRING);
2420 in_attr = is_attr(var->attrs, ATTR_IN);
2421 out_attr = is_attr(var->attrs, ATTR_OUT);
2422 if (!out_attr && !in_attr)
2423 in_attr = 1;
2425 if (!in_attr && !var->type->size_is && !is_string)
2427 print_file(file, indent, "");
2428 write_type(file, var->type->ref, FALSE, "_W%u", i++);
2429 fprintf(file, ";\n");
2432 print_file(file, indent, "");
2433 write_type_left(file, var->type);
2434 fprintf(file, " ");
2435 if (var->type->declarray) {
2436 fprintf(file, "( *");
2437 write_name(file, var);
2438 fprintf(file, " )");
2439 } else
2440 write_name(file, var);
2441 write_type_right(file, var->type, FALSE);
2442 fprintf(file, ";\n");
2447 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
2449 int in_attr, out_attr;
2450 int i = 0, sep = 0;
2451 const var_t *var;
2453 if (!func->args)
2454 return;
2456 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2458 int is_string = is_attr(var->attrs, ATTR_STRING);
2459 in_attr = is_attr(var->attrs, ATTR_IN);
2460 out_attr = is_attr(var->attrs, ATTR_OUT);
2461 if (!out_attr && !in_attr)
2462 in_attr = 1;
2464 if (!in_attr)
2466 print_file(file, indent, "");
2467 write_name(file, var);
2469 if (var->type->size_is)
2471 unsigned int size, align = 0;
2472 type_t *type = var->type;
2474 fprintf(file, " = NdrAllocate(&_StubMsg, ");
2475 for ( ; type->size_is ; type = type->ref)
2477 write_expr(file, type->size_is, TRUE);
2478 fprintf(file, " * ");
2480 size = type_memsize(type, &align);
2481 fprintf(file, "%u);\n", size);
2483 else if (!is_string)
2485 fprintf(file, " = &_W%u;\n", i);
2486 if (is_ptr(var->type) && !last_ptr(var->type))
2487 print_file(file, indent, "_W%u = 0;\n", i);
2488 i++;
2491 sep = 1;
2494 if (sep)
2495 fprintf(file, "\n");
2499 int write_expr_eval_routines(FILE *file, const char *iface)
2501 int result = 0;
2502 struct expr_eval_routine *eval;
2503 unsigned short callback_offset = 0;
2505 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
2507 int indent = 0;
2508 result = 1;
2509 print_file(file, indent, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
2510 iface, eval->structure->name, callback_offset);
2511 print_file(file, indent, "{\n");
2512 indent++;
2513 print_file(file, indent, "struct %s *" STRUCT_EXPR_EVAL_VAR " = (struct %s *)(pStubMsg->StackTop - %u);\n",
2514 eval->structure->name, eval->structure->name, eval->structure_size);
2515 fprintf(file, "\n");
2516 print_file(file, indent, "pStubMsg->Offset = 0;\n"); /* FIXME */
2517 print_file(file, indent, "pStubMsg->MaxCount = (unsigned long)");
2518 write_struct_expr(file, eval->expr, 1, eval->structure->fields, STRUCT_EXPR_EVAL_VAR);
2519 fprintf(file, ";\n");
2520 indent--;
2521 print_file(file, indent, "}\n\n");
2522 callback_offset++;
2524 return result;
2527 void write_expr_eval_routine_list(FILE *file, const char *iface)
2529 struct expr_eval_routine *eval;
2530 struct expr_eval_routine *cursor;
2531 unsigned short callback_offset = 0;
2533 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
2534 fprintf(file, "{\n");
2536 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
2538 print_file(file, 1, "%s_%sExprEval_%04u,\n",
2539 iface, eval->structure->name, callback_offset);
2541 callback_offset++;
2542 list_remove(&eval->entry);
2543 free(eval);
2546 fprintf(file, "};\n\n");
2550 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
2552 const struct str_list_entry_t *endpoint;
2553 const char *p;
2555 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
2556 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
2557 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
2559 print_file( f, 1, "{ (const unsigned char *)\"" );
2560 for (p = endpoint->str; *p && *p != ':'; p++)
2562 if (*p == '"' || *p == '\\') fputc( '\\', f );
2563 fputc( *p, f );
2565 if (!*p) goto error;
2566 if (p[1] != '[') goto error;
2568 fprintf( f, "\", (const unsigned char *)\"" );
2569 for (p += 2; *p && *p != ']'; p++)
2571 if (*p == '"' || *p == '\\') fputc( '\\', f );
2572 fputc( *p, f );
2574 if (*p != ']') goto error;
2575 fprintf( f, "\" },\n" );
2577 print_file( f, 0, "};\n\n" );
2578 return;
2580 error:
2581 error("Invalid endpoint syntax '%s'\n", endpoint->str);