push 1fb51685cfc6ddbce546c9614143e4d38b5f030b
[wine/hacks.git] / tools / widl / typegen.c
blobbf24d3f23d9cac511ae97eed296ad0e9576c3140
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 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
50 struct expr_eval_routine
52 struct list entry;
53 const type_t *structure;
54 unsigned int baseoff;
55 const expr_t *expr;
58 static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
59 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
60 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
61 const char *name, int write_ptr, unsigned int *tfsoff);
62 static const var_t *find_array_or_string_in_struct(const type_t *type);
64 const char *string_of_type(unsigned char type)
66 switch (type)
68 case RPC_FC_BYTE: return "FC_BYTE";
69 case RPC_FC_CHAR: return "FC_CHAR";
70 case RPC_FC_SMALL: return "FC_SMALL";
71 case RPC_FC_USMALL: return "FC_USMALL";
72 case RPC_FC_WCHAR: return "FC_WCHAR";
73 case RPC_FC_SHORT: return "FC_SHORT";
74 case RPC_FC_USHORT: return "FC_USHORT";
75 case RPC_FC_LONG: return "FC_LONG";
76 case RPC_FC_ULONG: return "FC_ULONG";
77 case RPC_FC_FLOAT: return "FC_FLOAT";
78 case RPC_FC_HYPER: return "FC_HYPER";
79 case RPC_FC_DOUBLE: return "FC_DOUBLE";
80 case RPC_FC_ENUM16: return "FC_ENUM16";
81 case RPC_FC_ENUM32: return "FC_ENUM32";
82 case RPC_FC_IGNORE: return "FC_IGNORE";
83 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
84 case RPC_FC_RP: return "FC_RP";
85 case RPC_FC_UP: return "FC_UP";
86 case RPC_FC_OP: return "FC_OP";
87 case RPC_FC_FP: return "FC_FP";
88 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
89 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
90 case RPC_FC_STRUCT: return "FC_STRUCT";
91 case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
92 case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
93 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
94 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
95 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
96 case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
97 case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
98 case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
99 case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
100 case RPC_FC_CARRAY: return "FC_CARRAY";
101 case RPC_FC_CVARRAY: return "FC_CVARRAY";
102 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
103 case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
104 case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
105 case RPC_FC_POINTER: return "FC_POINTER";
106 case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
107 case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
108 case RPC_FC_CSTRING: return "FC_CSTRING";
109 case RPC_FC_WSTRING: return "FC_WSTRING";
110 default:
111 error("string_of_type: unknown type 0x%02x\n", type);
112 return NULL;
116 int is_struct(unsigned char type)
118 switch (type)
120 case RPC_FC_STRUCT:
121 case RPC_FC_PSTRUCT:
122 case RPC_FC_CSTRUCT:
123 case RPC_FC_CPSTRUCT:
124 case RPC_FC_CVSTRUCT:
125 case RPC_FC_BOGUS_STRUCT:
126 return 1;
127 default:
128 return 0;
132 static int is_non_complex_struct(const type_t *type)
134 switch (type->type)
136 case RPC_FC_STRUCT:
137 case RPC_FC_PSTRUCT:
138 case RPC_FC_CSTRUCT:
139 case RPC_FC_CPSTRUCT:
140 case RPC_FC_CVSTRUCT:
141 return 1;
142 default:
143 return 0;
147 int is_union(unsigned char type)
149 switch (type)
151 case RPC_FC_ENCAPSULATED_UNION:
152 case RPC_FC_NON_ENCAPSULATED_UNION:
153 return 1;
154 default:
155 return 0;
159 static unsigned short user_type_offset(const char *name)
161 user_type_t *ut;
162 unsigned short off = 0;
163 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
165 if (strcmp(name, ut->name) == 0)
166 return off;
167 ++off;
169 error("user_type_offset: couldn't find type (%s)\n", name);
170 return 0;
173 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
175 type->typestring_offset = offset;
176 if (file) type->tfswrite = FALSE;
179 static void guard_rec(type_t *type)
181 /* types that contain references to themselves (like a linked list),
182 need to be shielded from infinite recursion when writing embedded
183 types */
184 if (type->typestring_offset)
185 type->tfswrite = FALSE;
186 else
187 type->typestring_offset = 1;
190 static type_t *get_user_type(const type_t *t, const char **pname)
192 for (;;)
194 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
195 if (ut)
197 if (pname)
198 *pname = t->name;
199 return ut;
202 if (t->kind == TKIND_ALIAS)
203 t = t->orig;
204 else
205 return 0;
209 int is_user_type(const type_t *t)
211 return get_user_type(t, NULL) != NULL;
214 static int is_embedded_complex(const type_t *type)
216 unsigned char tc = type->type;
217 return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type)
218 || (is_ptr(type) && type->ref->type == RPC_FC_IP);
221 static const char *get_context_handle_type_name(const type_t *type)
223 const type_t *t;
224 for (t = type; is_ptr(t); t = t->ref)
225 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
226 return t->name;
227 assert(0);
228 return NULL;
231 static int compare_expr(const expr_t *a, const expr_t *b)
233 int ret;
235 if (a->type != b->type)
236 return a->type - b->type;
238 switch (a->type)
240 case EXPR_NUM:
241 case EXPR_HEXNUM:
242 case EXPR_TRUEFALSE:
243 return a->u.lval - b->u.lval;
244 case EXPR_DOUBLE:
245 return a->u.dval - b->u.dval;
246 case EXPR_IDENTIFIER:
247 return strcmp(a->u.sval, b->u.sval);
248 case EXPR_COND:
249 ret = compare_expr(a->ref, b->ref);
250 if (ret != 0)
251 return ret;
252 ret = compare_expr(a->u.ext, b->u.ext);
253 if (ret != 0)
254 return ret;
255 return compare_expr(a->ext2, b->ext2);
256 case EXPR_OR:
257 case EXPR_AND:
258 case EXPR_ADD:
259 case EXPR_SUB:
260 case EXPR_MUL:
261 case EXPR_DIV:
262 case EXPR_SHL:
263 case EXPR_SHR:
264 ret = compare_expr(a->ref, b->ref);
265 if (ret != 0)
266 return ret;
267 return compare_expr(a->u.ext, b->u.ext);
268 case EXPR_NOT:
269 case EXPR_NEG:
270 case EXPR_PPTR:
271 case EXPR_CAST:
272 case EXPR_SIZEOF:
273 return compare_expr(a->ref, b->ref);
274 case EXPR_VOID:
275 return 0;
277 return -1;
280 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
281 do { \
282 if (file) \
283 fprintf(file, "/* %2u */\n", typestring_offset); \
284 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \
286 while (0)
288 static void print_file(FILE *file, int indent, const char *format, ...)
290 va_list va;
291 va_start(va, format);
292 print(file, indent, format, va);
293 va_end(va);
296 void print(FILE *file, int indent, const char *format, va_list va)
298 if (file)
300 if (format[0] != '\n')
301 while (0 < indent--)
302 fprintf(file, " ");
303 vfprintf(file, format, va);
307 void write_parameters_init(FILE *file, int indent, const func_t *func)
309 const var_t *var;
311 if (!func->args)
312 return;
314 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
316 const type_t *t = var->type;
317 const char *n = var->name;
318 if (decl_indirect(t))
319 print_file(file, indent, "MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
320 else if (is_ptr(t) || is_array(t))
321 print_file(file, indent, "%s = 0;\n", n);
324 fprintf(file, "\n");
327 static void write_formatdesc(FILE *f, int indent, const char *str)
329 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
330 print_file(f, indent, "{\n");
331 print_file(f, indent + 1, "short Pad;\n");
332 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
333 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
334 print_file(f, indent, "\n");
337 void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, type_pred_t pred)
339 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
340 get_size_typeformatstring(ifaces, pred));
342 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
343 get_size_procformatstring(ifaces, pred));
345 fprintf(f, "\n");
346 write_formatdesc(f, indent, "TYPE");
347 write_formatdesc(f, indent, "PROC");
348 fprintf(f, "\n");
349 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
350 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
351 print_file(f, indent, "\n");
354 static inline int is_base_type(unsigned char type)
356 switch (type)
358 case RPC_FC_BYTE:
359 case RPC_FC_CHAR:
360 case RPC_FC_USMALL:
361 case RPC_FC_SMALL:
362 case RPC_FC_WCHAR:
363 case RPC_FC_USHORT:
364 case RPC_FC_SHORT:
365 case RPC_FC_ULONG:
366 case RPC_FC_LONG:
367 case RPC_FC_HYPER:
368 case RPC_FC_IGNORE:
369 case RPC_FC_FLOAT:
370 case RPC_FC_DOUBLE:
371 case RPC_FC_ENUM16:
372 case RPC_FC_ENUM32:
373 case RPC_FC_ERROR_STATUS_T:
374 case RPC_FC_BIND_PRIMITIVE:
375 return TRUE;
377 default:
378 return FALSE;
382 int decl_indirect(const type_t *t)
384 return is_user_type(t)
385 || (!is_base_type(t->type)
386 && !is_ptr(t)
387 && !is_array(t));
390 static size_t write_procformatstring_var(FILE *file, int indent,
391 const var_t *var, int is_return)
393 size_t size;
394 const type_t *type = var->type;
396 int is_in = is_attr(var->attrs, ATTR_IN);
397 int is_out = is_attr(var->attrs, ATTR_OUT);
399 if (!is_in && !is_out) is_in = TRUE;
401 if (!type->declarray && is_base_type(type->type))
403 if (is_return)
404 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
405 else
406 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
408 if (type->type == RPC_FC_BIND_PRIMITIVE)
410 print_file(file, indent, "0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
411 size = 2; /* includes param type prefix */
413 else if (is_base_type(type->type))
415 print_file(file, indent, "0x%02x, /* %s */\n", type->type, string_of_type(type->type));
416 size = 2; /* includes param type prefix */
418 else
420 error("Unknown/unsupported type: %s (0x%02x)\n", var->name, type->type);
421 size = 0;
424 else
426 if (is_return)
427 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
428 else if (is_in && is_out)
429 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
430 else if (is_out)
431 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
432 else
433 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
435 print_file(file, indent, "0x01,\n");
436 print_file(file, indent, "NdrFcShort(0x%x),\n", type->typestring_offset);
437 size = 4; /* includes param type prefix */
439 return size;
442 void write_procformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
444 const ifref_t *iface;
445 int indent = 0;
446 const var_t *var;
448 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
449 print_file(file, indent, "{\n");
450 indent++;
451 print_file(file, indent, "0,\n");
452 print_file(file, indent, "{\n");
453 indent++;
455 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
457 if (!pred(iface->iface))
458 continue;
460 if (iface->iface->funcs)
462 const func_t *func;
463 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
465 if (is_local(func->def->attrs)) continue;
466 /* emit argument data */
467 if (func->args)
469 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
470 write_procformatstring_var(file, indent, var, FALSE);
473 /* emit return value data */
474 var = func->def;
475 if (is_void(var->type))
477 print_file(file, indent, "0x5b, /* FC_END */\n");
478 print_file(file, indent, "0x5c, /* FC_PAD */\n");
480 else
481 write_procformatstring_var(file, indent, var, TRUE);
486 print_file(file, indent, "0x0\n");
487 indent--;
488 print_file(file, indent, "}\n");
489 indent--;
490 print_file(file, indent, "};\n");
491 print_file(file, indent, "\n");
494 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
496 if (is_base_type(type->type))
498 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
499 *typestring_offset += 1;
500 return 1;
503 return 0;
506 /* write conformance / variance descriptor */
507 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
508 unsigned int baseoff, const type_t *type,
509 const expr_t *expr)
511 unsigned char operator_type = 0;
512 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
513 const char *conftype_string = "";
514 const char *operator_string = "no operators";
515 const expr_t *subexpr;
517 if (!expr)
519 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
520 return 4;
523 if (!structure)
525 /* Top-level conformance calculations are done inline. */
526 print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
527 RPC_FC_TOP_LEVEL_CONFORMANCE);
528 print_file (file, 2, "0x0,\n");
529 print_file (file, 2, "NdrFcShort(0x0),\n");
530 return 4;
533 if (expr->is_const)
535 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
536 error("write_conf_or_var_desc: constant value %ld is greater than "
537 "the maximum constant size of %d\n", expr->cval,
538 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
540 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %ld */\n",
541 RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
542 print_file(file, 2, "0x%x,\n", expr->cval & ~USHRT_MAX);
543 print_file(file, 2, "NdrFcShort(0x%x),\n", expr->cval & USHRT_MAX);
545 return 4;
548 if (is_ptr(type) || (is_array(type) && !type->declarray))
550 conftype = RPC_FC_POINTER_CONFORMANCE;
551 conftype_string = "field pointer, ";
554 subexpr = expr;
555 switch (subexpr->type)
557 case EXPR_PPTR:
558 subexpr = subexpr->ref;
559 operator_type = RPC_FC_DEREFERENCE;
560 operator_string = "FC_DEREFERENCE";
561 break;
562 case EXPR_DIV:
563 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
565 subexpr = subexpr->ref;
566 operator_type = RPC_FC_DIV_2;
567 operator_string = "FC_DIV_2";
569 break;
570 case EXPR_MUL:
571 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
573 subexpr = subexpr->ref;
574 operator_type = RPC_FC_MULT_2;
575 operator_string = "FC_MULT_2";
577 break;
578 case EXPR_SUB:
579 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
581 subexpr = subexpr->ref;
582 operator_type = RPC_FC_SUB_1;
583 operator_string = "FC_SUB_1";
585 break;
586 case EXPR_ADD:
587 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
589 subexpr = subexpr->ref;
590 operator_type = RPC_FC_ADD_1;
591 operator_string = "FC_ADD_1";
593 break;
594 default:
595 break;
598 if (subexpr->type == EXPR_IDENTIFIER)
600 const type_t *correlation_variable = NULL;
601 unsigned char correlation_variable_type;
602 unsigned char param_type = 0;
603 size_t offset = 0;
604 const var_t *var;
606 if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry )
608 unsigned int align = 0;
609 /* FIXME: take alignment into account */
610 if (var->name && !strcmp(var->name, subexpr->u.sval))
612 correlation_variable = var->type;
613 break;
615 offset += type_memsize(var->type, &align);
617 if (!correlation_variable)
618 error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
619 subexpr->u.sval);
621 offset -= baseoff;
622 correlation_variable_type = correlation_variable->type;
624 switch (correlation_variable_type)
626 case RPC_FC_CHAR:
627 case RPC_FC_SMALL:
628 param_type = RPC_FC_SMALL;
629 break;
630 case RPC_FC_BYTE:
631 case RPC_FC_USMALL:
632 param_type = RPC_FC_USMALL;
633 break;
634 case RPC_FC_WCHAR:
635 case RPC_FC_SHORT:
636 case RPC_FC_ENUM16:
637 param_type = RPC_FC_SHORT;
638 break;
639 case RPC_FC_USHORT:
640 param_type = RPC_FC_USHORT;
641 break;
642 case RPC_FC_LONG:
643 case RPC_FC_ENUM32:
644 param_type = RPC_FC_LONG;
645 break;
646 case RPC_FC_ULONG:
647 param_type = RPC_FC_ULONG;
648 break;
649 case RPC_FC_RP:
650 case RPC_FC_UP:
651 case RPC_FC_OP:
652 case RPC_FC_FP:
653 if (sizeof(void *) == 4) /* FIXME */
654 param_type = RPC_FC_LONG;
655 else
656 param_type = RPC_FC_HYPER;
657 break;
658 default:
659 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
660 correlation_variable_type);
663 print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
664 conftype | param_type, conftype_string, string_of_type(param_type));
665 print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
666 print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
667 offset, offset);
669 else
671 unsigned int callback_offset = 0;
672 struct expr_eval_routine *eval;
673 int found = 0;
675 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
677 if (!strcmp (eval->structure->name, structure->name)
678 && !compare_expr (eval->expr, expr))
680 found = 1;
681 break;
683 callback_offset++;
686 if (!found)
688 eval = xmalloc (sizeof(*eval));
689 eval->structure = structure;
690 eval->baseoff = baseoff;
691 eval->expr = expr;
692 list_add_tail (&expr_eval_routines, &eval->entry);
695 if (callback_offset > USHRT_MAX)
696 error("Maximum number of callback routines reached\n");
698 print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
699 print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
700 print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
702 return 4;
705 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
707 int have_align = FALSE;
708 size_t size = 0;
709 const var_t *v;
711 if (!fields) return 0;
712 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
714 unsigned int falign = 0;
715 size_t fsize = type_memsize(v->type, &falign);
716 if (!have_align)
718 *align = falign;
719 have_align = TRUE;
721 size = (size + (falign - 1)) & ~(falign - 1);
722 size += fsize;
725 size = (size + (*align - 1)) & ~(*align - 1);
726 return size;
729 static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
731 size_t size, maxs = 0;
732 unsigned int align = *pmaxa;
733 const var_t *v;
735 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
737 /* we could have an empty default field with NULL type */
738 if (v->type)
740 size = type_memsize(v->type, &align);
741 if (maxs < size) maxs = size;
742 if (*pmaxa < align) *pmaxa = align;
746 return maxs;
749 int get_padding(const var_list_t *fields)
751 unsigned short offset = 0;
752 int salign = -1;
753 const var_t *f;
755 if (!fields)
756 return 0;
758 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
760 type_t *ft = f->type;
761 unsigned int align = 0;
762 size_t size = type_memsize(ft, &align);
763 if (salign == -1)
764 salign = align;
765 offset = (offset + (align - 1)) & ~(align - 1);
766 offset += size;
769 return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
772 size_t type_memsize(const type_t *t, unsigned int *align)
774 size_t size = 0;
776 if (t->declarray && is_conformant_array(t))
778 type_memsize(t->ref, align);
779 size = 0;
781 else if (is_ptr(t) || is_conformant_array(t))
783 size = sizeof(void *);
784 if (size > *align) *align = size;
786 else switch (t->type)
788 case RPC_FC_BYTE:
789 case RPC_FC_CHAR:
790 case RPC_FC_USMALL:
791 case RPC_FC_SMALL:
792 size = 1;
793 if (size > *align) *align = size;
794 break;
795 case RPC_FC_WCHAR:
796 case RPC_FC_USHORT:
797 case RPC_FC_SHORT:
798 case RPC_FC_ENUM16:
799 size = 2;
800 if (size > *align) *align = size;
801 break;
802 case RPC_FC_ULONG:
803 case RPC_FC_LONG:
804 case RPC_FC_ERROR_STATUS_T:
805 case RPC_FC_ENUM32:
806 case RPC_FC_FLOAT:
807 size = 4;
808 if (size > *align) *align = size;
809 break;
810 case RPC_FC_HYPER:
811 case RPC_FC_DOUBLE:
812 size = 8;
813 if (size > *align) *align = size;
814 break;
815 case RPC_FC_STRUCT:
816 case RPC_FC_CVSTRUCT:
817 case RPC_FC_CPSTRUCT:
818 case RPC_FC_CSTRUCT:
819 case RPC_FC_PSTRUCT:
820 case RPC_FC_BOGUS_STRUCT:
821 size = fields_memsize(t->fields, align);
822 break;
823 case RPC_FC_ENCAPSULATED_UNION:
824 case RPC_FC_NON_ENCAPSULATED_UNION:
825 size = union_memsize(t->fields, align);
826 break;
827 case RPC_FC_SMFARRAY:
828 case RPC_FC_LGFARRAY:
829 case RPC_FC_SMVARRAY:
830 case RPC_FC_LGVARRAY:
831 case RPC_FC_BOGUS_ARRAY:
832 size = t->dim * type_memsize(t->ref, align);
833 break;
834 default:
835 error("type_memsize: Unknown type %d\n", t->type);
836 size = 0;
839 return size;
842 static unsigned int write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset)
844 short absoff = type->ref->typestring_offset;
845 short reloff = absoff - (offset + 2);
846 int ptr_attr = is_ptr(type->ref) ? 0x10 : 0x0;
848 print_file(file, 2, "0x%02x, 0x%x,\t/* %s */\n",
849 type->type, ptr_attr, string_of_type(type->type));
850 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n",
851 reloff, reloff, absoff);
852 return 4;
855 static unsigned char conf_string_type_of_char_type(unsigned char t)
857 switch (t)
859 case RPC_FC_BYTE:
860 case RPC_FC_CHAR:
861 return RPC_FC_C_CSTRING;
862 case RPC_FC_WCHAR:
863 return RPC_FC_C_WSTRING;
866 error("string_type_of_char_type: unrecognized type %d", t);
867 return 0;
870 static unsigned int write_simple_pointer(FILE *file, const type_t *type)
872 unsigned char fc
873 = is_string_type(type->attrs, type)
874 ? conf_string_type_of_char_type(type->ref->type)
875 : type->ref->type;
876 print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n",
877 type->type, string_of_type(type->type));
878 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
879 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
880 return 4;
883 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
885 print_file(file, 0, "/* %u (", tfsoff);
886 write_type_decl(file, t, NULL);
887 print_file(file, 0, ") */\n");
890 static size_t write_pointer_tfs(FILE *file, type_t *type, unsigned int *typestring_offset)
892 unsigned int offset = *typestring_offset;
894 print_start_tfs_comment(file, type, offset);
895 update_tfsoff(type, offset, file);
897 if (type->ref->typestring_offset)
898 *typestring_offset += write_nonsimple_pointer(file, type, offset);
899 else if (is_base_type(type->ref->type))
900 *typestring_offset += write_simple_pointer(file, type);
902 return offset;
905 static int processed(const type_t *type)
907 return type->typestring_offset && !type->tfswrite;
910 static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
912 unsigned int start, absoff, flags;
913 unsigned int align = 0, ualign = 0;
914 const char *name;
915 type_t *utype = get_user_type(type, &name);
916 size_t usize = type_memsize(utype, &ualign);
917 size_t size = type_memsize(type, &align);
918 unsigned short funoff = user_type_offset(name);
919 short reloff;
921 guard_rec(type);
923 if (is_base_type(utype->type))
925 absoff = *tfsoff;
926 print_start_tfs_comment(file, utype, absoff);
927 print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
928 print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
929 *tfsoff += 2;
931 else
933 if (!processed(utype))
934 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
935 absoff = utype->typestring_offset;
938 if (utype->type == RPC_FC_RP)
939 flags = 0x40;
940 else if (utype->type == RPC_FC_UP)
941 flags = 0x80;
942 else
943 flags = 0;
945 start = *tfsoff;
946 update_tfsoff(type, start, file);
947 print_start_tfs_comment(file, type, start);
948 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
949 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
950 flags | (align - 1), align - 1, flags);
951 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
952 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
953 print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
954 *tfsoff += 8;
955 reloff = absoff - *tfsoff;
956 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
957 *tfsoff += 2;
960 static void write_member_type(FILE *file, const type_t *cont,
961 const attr_list_t *attrs, const type_t *type,
962 unsigned int *corroff, unsigned int *tfsoff)
964 if (is_embedded_complex(type) && !is_conformant_array(type))
966 size_t absoff;
967 short reloff;
969 if (is_union(type->type) && is_attr(attrs, ATTR_SWITCHIS))
971 absoff = *corroff;
972 *corroff += 8;
974 else
976 absoff = type->typestring_offset;
978 reloff = absoff - (*tfsoff + 2);
980 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
981 /* FIXME: actually compute necessary padding */
982 print_file(file, 2, "0x0,\t/* FIXME: padding */\n");
983 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
984 reloff, reloff, absoff);
985 *tfsoff += 4;
987 else if (is_ptr(type) || is_conformant_array(type))
989 unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
990 ? RPC_FC_POINTER
991 : RPC_FC_LONG);
992 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
993 *tfsoff += 1;
995 else if (!write_base_type(file, type, tfsoff))
996 error("Unsupported member type 0x%x\n", type->type);
999 static void write_end(FILE *file, unsigned int *tfsoff)
1001 if (*tfsoff % 2 == 0)
1003 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1004 *tfsoff += 1;
1006 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1007 *tfsoff += 1;
1010 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1012 unsigned int offset = 0;
1013 var_list_t *fs = type->fields;
1014 var_t *f;
1016 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1018 unsigned int align = 0;
1019 type_t *ft = f->type;
1020 if (is_union(ft->type) && is_attr(f->attrs, ATTR_SWITCHIS))
1022 unsigned int absoff = ft->typestring_offset;
1023 short reloff = absoff - (*tfsoff + 6);
1024 print_file(file, 0, "/* %d */\n", *tfsoff);
1025 print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
1026 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1027 write_conf_or_var_desc(file, current_structure, offset, ft,
1028 get_attrp(f->attrs, ATTR_SWITCHIS));
1029 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1030 reloff, reloff, absoff);
1031 *tfsoff += 8;
1034 /* FIXME: take alignment into account */
1035 offset += type_memsize(ft, &align);
1039 static int write_no_repeat_pointer_descriptions(
1040 FILE *file, type_t *type,
1041 size_t *offset_in_memory, size_t *offset_in_buffer,
1042 unsigned int *typestring_offset)
1044 int written = 0;
1045 unsigned int align;
1047 if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
1049 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
1050 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1052 /* pointer instance */
1053 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1054 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1055 *typestring_offset += 6;
1057 if (is_ptr(type))
1058 write_pointer_tfs(file, type, typestring_offset);
1059 else
1061 unsigned absoff = type->typestring_offset;
1062 short reloff = absoff - (*typestring_offset + 2);
1063 /* FIXME: get pointer attributes from field */
1064 print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
1065 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1066 reloff, reloff, absoff);
1067 *typestring_offset += 4;
1070 align = 0;
1071 *offset_in_memory += type_memsize(type, &align);
1072 /* FIXME: is there a case where these two are different? */
1073 align = 0;
1074 *offset_in_buffer += type_memsize(type, &align);
1076 return 1;
1079 if (is_non_complex_struct(type))
1081 const var_t *v;
1082 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1083 written += write_no_repeat_pointer_descriptions(
1084 file, v->type,
1085 offset_in_memory, offset_in_buffer, typestring_offset);
1087 else
1089 align = 0;
1090 *offset_in_memory += type_memsize(type, &align);
1091 /* FIXME: is there a case where these two are different? */
1092 align = 0;
1093 *offset_in_buffer += type_memsize(type, &align);
1096 return written;
1099 static int write_pointer_description_offsets(
1100 FILE *file, const attr_list_t *attrs, type_t *type,
1101 size_t *offset_in_memory, size_t *offset_in_buffer,
1102 unsigned int *typestring_offset)
1104 int written = 0;
1105 unsigned int align;
1107 if (is_ptr(type) && type->ref->type != RPC_FC_IP)
1109 if (offset_in_memory && offset_in_buffer)
1111 /* pointer instance */
1112 /* FIXME: sometimes from end of structure, sometimes from beginning */
1113 print_file(file, 2, "NdrFcShort(0x%x), /* Memory offset = %d */\n", *offset_in_memory, *offset_in_memory);
1114 print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
1116 align = 0;
1117 *offset_in_memory += type_memsize(type, &align);
1118 /* FIXME: is there a case where these two are different? */
1119 align = 0;
1120 *offset_in_buffer += type_memsize(type, &align);
1122 *typestring_offset += 4;
1124 if (processed(type->ref) || is_base_type(type->ref->type))
1125 write_pointer_tfs(file, type, typestring_offset);
1126 else
1127 error("write_pointer_description_offsets: type format string unknown\n");
1129 return 1;
1132 if (is_array(type))
1134 return write_pointer_description_offsets(
1135 file, attrs, type->ref, offset_in_memory, offset_in_buffer,
1136 typestring_offset);
1138 else if (is_non_complex_struct(type))
1140 /* otherwise search for interesting fields to parse */
1141 const var_t *v;
1142 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1144 written += write_pointer_description_offsets(
1145 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1146 typestring_offset);
1149 else
1151 align = 0;
1152 if (offset_in_memory)
1153 *offset_in_memory += type_memsize(type, &align);
1154 /* FIXME: is there a case where these two are different? */
1155 align = 0;
1156 if (offset_in_buffer)
1157 *offset_in_buffer += type_memsize(type, &align);
1160 return written;
1163 /* Note: if file is NULL return value is number of pointers to write, else
1164 * it is the number of type format characters written */
1165 static int write_fixed_array_pointer_descriptions(
1166 FILE *file, const attr_list_t *attrs, type_t *type,
1167 size_t *offset_in_memory, size_t *offset_in_buffer,
1168 unsigned int *typestring_offset)
1170 unsigned int align;
1171 int pointer_count = 0;
1173 if (type->type == RPC_FC_SMFARRAY || type->type == RPC_FC_LGFARRAY)
1175 unsigned int temp = 0;
1176 /* unfortunately, this needs to be done in two passes to avoid
1177 * writing out redundant FC_FIXED_REPEAT descriptions */
1178 pointer_count = write_pointer_description_offsets(
1179 NULL, attrs, type->ref, NULL, NULL, &temp);
1180 if (pointer_count > 0)
1182 unsigned int increment_size;
1183 size_t offset_of_array_pointer_mem = 0;
1184 size_t offset_of_array_pointer_buf = 0;
1186 align = 0;
1187 increment_size = type_memsize(type->ref, &align);
1189 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
1190 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
1191 print_file(file, 2, "NdrFcShort(0x%x), /* Iterations = %d */\n", type->dim, type->dim);
1192 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1193 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1194 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1195 *typestring_offset += 10;
1197 pointer_count = write_pointer_description_offsets(
1198 file, attrs, type, &offset_of_array_pointer_mem,
1199 &offset_of_array_pointer_buf, typestring_offset);
1202 else if (is_struct(type->type))
1204 const var_t *v;
1205 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1207 pointer_count += write_fixed_array_pointer_descriptions(
1208 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1209 typestring_offset);
1212 else
1214 align = 0;
1215 if (offset_in_memory)
1216 *offset_in_memory += type_memsize(type, &align);
1217 /* FIXME: is there a case where these two are different? */
1218 align = 0;
1219 if (offset_in_buffer)
1220 *offset_in_buffer += type_memsize(type, &align);
1223 return pointer_count;
1226 /* Note: if file is NULL return value is number of pointers to write, else
1227 * it is the number of type format characters written */
1228 static int write_conformant_array_pointer_descriptions(
1229 FILE *file, const attr_list_t *attrs, type_t *type,
1230 size_t offset_in_memory, unsigned int *typestring_offset)
1232 unsigned int align;
1233 int pointer_count = 0;
1235 if (is_conformant_array(type) && !type->length_is)
1237 unsigned int temp = 0;
1238 /* unfortunately, this needs to be done in two passes to avoid
1239 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1240 pointer_count = write_pointer_description_offsets(
1241 NULL, attrs, type->ref, NULL, NULL, &temp);
1242 if (pointer_count > 0)
1244 unsigned int increment_size;
1245 size_t offset_of_array_pointer_mem = offset_in_memory;
1246 size_t offset_of_array_pointer_buf = offset_in_memory;
1248 align = 0;
1249 increment_size = type_memsize(type->ref, &align);
1251 if (increment_size > USHRT_MAX)
1252 error("array size of %u bytes is too large\n", increment_size);
1254 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1255 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
1256 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1257 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
1258 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1259 *typestring_offset += 8;
1261 pointer_count = write_pointer_description_offsets(
1262 file, attrs, type->ref, &offset_of_array_pointer_mem,
1263 &offset_of_array_pointer_buf, typestring_offset);
1267 return pointer_count;
1270 /* Note: if file is NULL return value is number of pointers to write, else
1271 * it is the number of type format characters written */
1272 static int write_varying_array_pointer_descriptions(
1273 FILE *file, const attr_list_t *attrs, type_t *type,
1274 size_t *offset_in_memory, size_t *offset_in_buffer,
1275 unsigned int *typestring_offset)
1277 unsigned int align;
1278 int pointer_count = 0;
1280 /* FIXME: do varying array searching here, but pointer searching in write_pointer_description_offsets */
1282 if (is_array(type) && type->length_is)
1284 unsigned int temp = 0;
1285 /* unfortunately, this needs to be done in two passes to avoid
1286 * writing out redundant FC_VARIABLE_REPEAT descriptions */
1287 pointer_count = write_pointer_description_offsets(
1288 NULL, attrs, type->ref, NULL, NULL, &temp);
1289 if (pointer_count > 0)
1291 unsigned int increment_size;
1292 size_t offset_of_array_pointer_mem = 0;
1293 size_t offset_of_array_pointer_buf = 0;
1295 align = 0;
1296 increment_size = type_memsize(type->ref, &align);
1298 if (increment_size > USHRT_MAX)
1299 error("array size of %u bytes is too large\n", increment_size);
1301 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
1302 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
1303 print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
1304 print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
1305 print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
1306 *typestring_offset += 8;
1308 pointer_count = write_pointer_description_offsets(
1309 file, attrs, type, &offset_of_array_pointer_mem,
1310 &offset_of_array_pointer_buf, typestring_offset);
1313 else if (is_struct(type->type))
1315 const var_t *v;
1316 LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
1318 pointer_count += write_varying_array_pointer_descriptions(
1319 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
1320 typestring_offset);
1323 else
1325 align = 0;
1326 if (offset_in_memory)
1327 *offset_in_memory += type_memsize(type, &align);
1328 /* FIXME: is there a case where these two are different? */
1329 align = 0;
1330 if (offset_in_buffer)
1331 *offset_in_buffer += type_memsize(type, &align);
1334 return pointer_count;
1337 static void write_pointer_description(FILE *file, type_t *type,
1338 unsigned int *typestring_offset)
1340 size_t offset_in_buffer;
1341 size_t offset_in_memory;
1343 /* pass 1: search for single instance of a pointer (i.e. don't descend
1344 * into arrays) */
1345 if (!is_array(type))
1347 offset_in_memory = 0;
1348 offset_in_buffer = 0;
1349 write_no_repeat_pointer_descriptions(
1350 file, type,
1351 &offset_in_memory, &offset_in_buffer, typestring_offset);
1354 /* pass 2: search for pointers in fixed arrays */
1355 offset_in_memory = 0;
1356 offset_in_buffer = 0;
1357 write_fixed_array_pointer_descriptions(
1358 file, NULL, type,
1359 &offset_in_memory, &offset_in_buffer, typestring_offset);
1361 /* pass 3: search for pointers in conformant only arrays (but don't descend
1362 * into conformant varying or varying arrays) */
1363 if ((!type->declarray || !current_structure) && is_conformant_array(type))
1364 write_conformant_array_pointer_descriptions(
1365 file, NULL, type, 0, typestring_offset);
1366 else if (type->type == RPC_FC_CPSTRUCT)
1368 unsigned int align = 0;
1369 type_t *carray = find_array_or_string_in_struct(type)->type;
1370 write_conformant_array_pointer_descriptions(
1371 file, NULL, carray,
1372 type_memsize(type, &align),
1373 typestring_offset);
1376 /* pass 4: search for pointers in varying arrays */
1377 offset_in_memory = 0;
1378 offset_in_buffer = 0;
1379 write_varying_array_pointer_descriptions(
1380 file, NULL, type,
1381 &offset_in_memory, &offset_in_buffer, typestring_offset);
1384 static int is_declptr(const type_t *t)
1386 return is_ptr(t) || (is_conformant_array(t) && !t->declarray);
1389 static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
1390 type_t *type,
1391 const char *name, unsigned int *typestring_offset)
1393 size_t start_offset = *typestring_offset;
1394 unsigned char rtype;
1396 update_tfsoff(type, start_offset, file);
1398 if (is_declptr(type))
1400 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
1401 int pointer_type = is_ptr(type) ? type->type : get_attrv(attrs, ATTR_POINTERTYPE);
1402 if (!pointer_type)
1403 pointer_type = RPC_FC_RP;
1404 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
1405 pointer_type, flag, string_of_type(pointer_type),
1406 flag ? " [simple_pointer]" : "");
1407 *typestring_offset += 2;
1408 if (!flag)
1410 print_file(file, 2, "NdrFcShort(0x2),\n");
1411 *typestring_offset += 2;
1413 rtype = type->ref->type;
1415 else
1416 rtype = type->ref->type;
1418 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
1420 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
1421 return start_offset;
1424 if (type->declarray && !is_conformant_array(type))
1426 /* FIXME: multi-dimensional array */
1427 if (0xffffuL < type->dim)
1428 error("array size for parameter %s exceeds %u bytes by %lu bytes\n",
1429 name, 0xffffu, type->dim - 0xffffu);
1431 if (rtype == RPC_FC_CHAR)
1432 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
1433 else
1434 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
1435 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1436 *typestring_offset += 2;
1438 print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", type->dim, type->dim);
1439 *typestring_offset += 2;
1441 return start_offset;
1443 else if (type->size_is)
1445 unsigned int align = 0;
1447 if (rtype == RPC_FC_CHAR)
1448 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1449 else
1450 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1451 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
1452 *typestring_offset += 2;
1454 *typestring_offset += write_conf_or_var_desc(
1455 file, current_structure,
1456 (type->declarray && current_structure
1457 ? type_memsize(current_structure, &align)
1458 : 0),
1459 type, type->size_is);
1461 return start_offset;
1463 else
1465 if (rtype == RPC_FC_WCHAR)
1466 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
1467 else
1468 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
1469 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1470 *typestring_offset += 2;
1472 return start_offset;
1476 static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1477 const char *name, unsigned int *typestring_offset)
1479 const expr_t *length_is = type->length_is;
1480 const expr_t *size_is = type->size_is;
1481 unsigned int align = 0;
1482 size_t size;
1483 size_t start_offset;
1484 int has_pointer;
1485 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
1486 unsigned int baseoff
1487 = type->declarray && current_structure
1488 ? type_memsize(current_structure, &align)
1489 : 0;
1491 if (!pointer_type)
1492 pointer_type = RPC_FC_RP;
1494 has_pointer = FALSE;
1495 if (write_embedded_types(file, attrs, type->ref, name, FALSE, typestring_offset))
1496 has_pointer = TRUE;
1498 align = 0;
1499 size = type_memsize(type, &align);
1500 if (size == 0) /* conformant array */
1501 size = type_memsize(type->ref, &align);
1503 start_offset = *typestring_offset;
1504 update_tfsoff(type, start_offset, file);
1505 print_start_tfs_comment(file, type, start_offset);
1506 print_file(file, 2, "0x%02x,\t/* %s */\n", type->type, string_of_type(type->type));
1507 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1508 *typestring_offset += 2;
1510 align = 0;
1511 if (type->type != RPC_FC_BOGUS_ARRAY)
1513 unsigned char tc = type->type;
1515 if (tc == RPC_FC_LGFARRAY || tc == RPC_FC_LGVARRAY)
1517 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", size, size);
1518 *typestring_offset += 4;
1520 else
1522 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", size, size);
1523 *typestring_offset += 2;
1526 if (is_conformant_array(type))
1527 *typestring_offset
1528 += write_conf_or_var_desc(file, current_structure, baseoff,
1529 type, size_is);
1531 if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
1533 unsigned int elalign = 0;
1534 size_t elsize = type_memsize(type->ref, &elalign);
1536 if (type->type == RPC_FC_LGVARRAY)
1538 print_file(file, 2, "NdrFcLong(0x%x),\t/* %lu */\n", type->dim, type->dim);
1539 *typestring_offset += 4;
1541 else
1543 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", type->dim, type->dim);
1544 *typestring_offset += 2;
1547 print_file(file, 2, "NdrFcShort(0x%x),\t/* %lu */\n", elsize, elsize);
1548 *typestring_offset += 2;
1551 if (length_is)
1552 *typestring_offset
1553 += write_conf_or_var_desc(file, current_structure, baseoff,
1554 type, length_is);
1556 if (has_pointer && (!type->declarray || !current_structure))
1558 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1559 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1560 *typestring_offset += 2;
1561 write_pointer_description(file, type, typestring_offset);
1562 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1563 *typestring_offset += 1;
1566 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1567 write_end(file, typestring_offset);
1569 else
1571 unsigned int dim = size_is ? 0 : type->dim;
1572 print_file(file, 2, "NdrFcShort(0x%x),\t/* %u */\n", dim, dim);
1573 *typestring_offset += 2;
1574 *typestring_offset
1575 += write_conf_or_var_desc(file, current_structure, baseoff,
1576 type, size_is);
1577 *typestring_offset
1578 += write_conf_or_var_desc(file, current_structure, baseoff,
1579 type, length_is);
1580 write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
1581 write_end(file, typestring_offset);
1584 return start_offset;
1587 static const var_t *find_array_or_string_in_struct(const type_t *type)
1589 const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry );
1590 const type_t *ft = last_field->type;
1592 if (ft->declarray && is_conformant_array(ft))
1593 return last_field;
1595 if (ft->type == RPC_FC_CSTRUCT || ft->type == RPC_FC_CPSTRUCT || ft->type == RPC_FC_CVSTRUCT)
1596 return find_array_or_string_in_struct(last_field->type);
1597 else
1598 return NULL;
1601 static void write_struct_members(FILE *file, const type_t *type,
1602 unsigned int *corroff, unsigned int *typestring_offset)
1604 const var_t *field;
1605 unsigned short offset = 0;
1606 int salign = -1;
1607 int padding;
1609 if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
1611 type_t *ft = field->type;
1612 if (!ft->declarray || !is_conformant_array(ft))
1614 unsigned int align = 0;
1615 size_t size = type_memsize(ft, &align);
1616 if (salign == -1)
1617 salign = align;
1618 if ((align - 1) & offset)
1620 unsigned char fc = 0;
1621 switch (align)
1623 case 4:
1624 fc = RPC_FC_ALIGNM4;
1625 break;
1626 case 8:
1627 fc = RPC_FC_ALIGNM8;
1628 break;
1629 default:
1630 error("write_struct_members: cannot align type %d\n", ft->type);
1632 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1633 offset = (offset + (align - 1)) & ~(align - 1);
1634 *typestring_offset += 1;
1636 write_member_type(file, type, field->attrs, field->type, corroff,
1637 typestring_offset);
1638 offset += size;
1642 padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
1643 if (padding)
1645 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
1646 RPC_FC_STRUCTPAD1 + padding - 1,
1647 padding);
1648 *typestring_offset += 1;
1651 write_end(file, typestring_offset);
1654 static size_t write_struct_tfs(FILE *file, type_t *type,
1655 const char *name, unsigned int *tfsoff)
1657 const type_t *save_current_structure = current_structure;
1658 unsigned int total_size;
1659 const var_t *array;
1660 size_t start_offset;
1661 size_t array_offset;
1662 int has_pointers = 0;
1663 unsigned int align = 0;
1664 unsigned int corroff;
1665 var_t *f;
1667 guard_rec(type);
1668 current_structure = type;
1670 total_size = type_memsize(type, &align);
1671 if (total_size > USHRT_MAX)
1672 error("structure size for %s exceeds %d bytes by %d bytes\n",
1673 name, USHRT_MAX, total_size - USHRT_MAX);
1675 if (type->fields) LIST_FOR_EACH_ENTRY(f, type->fields, var_t, entry)
1676 has_pointers |= write_embedded_types(file, f->attrs, f->type, f->name,
1677 FALSE, tfsoff);
1679 array = find_array_or_string_in_struct(type);
1680 if (array && !processed(array->type))
1681 array_offset
1682 = is_attr(array->attrs, ATTR_STRING)
1683 ? write_string_tfs(file, array->attrs, array->type, array->name, tfsoff)
1684 : write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
1686 corroff = *tfsoff;
1687 write_descriptors(file, type, tfsoff);
1689 start_offset = *tfsoff;
1690 update_tfsoff(type, start_offset, file);
1691 print_start_tfs_comment(file, type, start_offset);
1692 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1693 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
1694 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", total_size, total_size);
1695 *tfsoff += 4;
1697 if (array)
1699 unsigned int absoff = array->type->typestring_offset;
1700 short reloff = absoff - *tfsoff;
1701 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n",
1702 reloff, reloff, absoff);
1703 *tfsoff += 2;
1705 else if (type->type == RPC_FC_BOGUS_STRUCT)
1707 print_file(file, 2, "NdrFcShort(0x0),\n");
1708 *tfsoff += 2;
1711 if (type->type == RPC_FC_BOGUS_STRUCT)
1713 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
1714 nothing is written to file yet. On the actual writing pass,
1715 this will have been updated. */
1716 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
1717 short reloff = absoff - *tfsoff;
1718 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1719 reloff, reloff, absoff);
1720 *tfsoff += 2;
1722 else if ((type->type == RPC_FC_PSTRUCT) ||
1723 (type->type == RPC_FC_CPSTRUCT) ||
1724 (type->type == RPC_FC_CVSTRUCT && has_pointers))
1726 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
1727 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
1728 *tfsoff += 2;
1729 write_pointer_description(file, type, tfsoff);
1730 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
1731 *tfsoff += 1;
1734 write_struct_members(file, type, &corroff, tfsoff);
1736 if (type->type == RPC_FC_BOGUS_STRUCT)
1738 const var_list_t *fs = type->fields;
1739 const var_t *f;
1741 type->ptrdesc = *tfsoff;
1742 if (fs) LIST_FOR_EACH_ENTRY(f, fs, const var_t, entry)
1744 type_t *ft = f->type;
1745 if (is_ptr(ft))
1746 write_pointer_tfs(file, ft, tfsoff);
1748 if (type->ptrdesc == *tfsoff)
1749 type->ptrdesc = 0;
1752 current_structure = save_current_structure;
1753 return start_offset;
1756 static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type,
1757 unsigned char flags, size_t offset,
1758 unsigned int *typeformat_offset)
1760 size_t start_offset = *typeformat_offset;
1761 short reloff = offset - (*typeformat_offset + 2);
1762 int in_attr, out_attr;
1763 in_attr = is_attr(attrs, ATTR_IN);
1764 out_attr = is_attr(attrs, ATTR_OUT);
1765 if (!in_attr && !out_attr) in_attr = 1;
1767 if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1768 flags |= 0x04;
1770 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1771 pointer_type,
1772 flags,
1773 string_of_type(pointer_type));
1774 if (file)
1776 if (flags & 0x04)
1777 fprintf(file, " [allocated_on_stack]");
1778 if (flags & 0x10)
1779 fprintf(file, " [pointer_deref]");
1780 fprintf(file, " */\n");
1783 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset);
1784 *typeformat_offset += 4;
1786 return start_offset;
1789 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
1791 if (t == NULL)
1793 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
1795 else if (is_base_type(t->type))
1797 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
1798 t->type, string_of_type(t->type));
1800 else if (t->typestring_offset)
1802 short reloff = t->typestring_offset - *tfsoff;
1803 print_file(file, 2, "NdrFcShort(0x%x),\t/* Offset= %d (%d) */\n",
1804 reloff, reloff, t->typestring_offset);
1806 else
1807 error("write_branch_type: type unimplemented (0x%x)\n", t->type);
1809 *tfsoff += 2;
1812 static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1814 unsigned int align = 0;
1815 unsigned int start_offset;
1816 size_t size = type_memsize(type, &align);
1817 var_list_t *fields;
1818 size_t nbranch = 0;
1819 type_t *deftype = NULL;
1820 short nodeftype = 0xffff;
1821 var_t *f;
1823 guard_rec(type);
1825 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1827 const var_t *uv = LIST_ENTRY(list_tail(type->fields), const var_t, entry);
1828 fields = uv->type->fields;
1830 else
1831 fields = type->fields;
1833 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1835 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1836 if (cases)
1837 nbranch += list_count(cases);
1838 if (f->type)
1839 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
1842 start_offset = *tfsoff;
1843 update_tfsoff(type, start_offset, file);
1844 print_start_tfs_comment(file, type, start_offset);
1845 if (type->type == RPC_FC_ENCAPSULATED_UNION)
1847 const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry);
1848 const type_t *st = sv->type;
1850 switch (st->type)
1852 case RPC_FC_CHAR:
1853 case RPC_FC_SMALL:
1854 case RPC_FC_USMALL:
1855 case RPC_FC_SHORT:
1856 case RPC_FC_USHORT:
1857 case RPC_FC_LONG:
1858 case RPC_FC_ULONG:
1859 case RPC_FC_ENUM16:
1860 case RPC_FC_ENUM32:
1861 print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type));
1862 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
1863 0x40 | st->type, string_of_type(st->type));
1864 *tfsoff += 2;
1865 break;
1866 default:
1867 error("union switch type must be an integer, char, or enum\n");
1870 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size);
1871 print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);
1872 *tfsoff += 4;
1874 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
1876 type_t *ft = f->type;
1877 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
1878 int deflt = is_attr(f->attrs, ATTR_DEFAULT);
1879 expr_t *c;
1881 if (cases == NULL && !deflt)
1882 error("union field %s with neither case nor default attribute\n", f->name);
1884 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
1886 /* MIDL doesn't check for duplicate cases, even though that seems
1887 like a reasonable thing to do, it just dumps them to the TFS
1888 like we're going to do here. */
1889 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
1890 *tfsoff += 4;
1891 write_branch_type(file, ft, tfsoff);
1894 /* MIDL allows multiple default branches, even though that seems
1895 illogical, it just chooses the last one, which is what we will
1896 do. */
1897 if (deflt)
1899 deftype = ft;
1900 nodeftype = 0;
1904 if (deftype)
1906 write_branch_type(file, deftype, tfsoff);
1908 else
1910 print_file(file, 2, "NdrFcShort(0x%x),\n", nodeftype);
1911 *tfsoff += 2;
1914 return start_offset;
1917 static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
1918 unsigned int *typeformat_offset)
1920 size_t i;
1921 size_t start_offset = *typeformat_offset;
1922 const var_t *iid = get_attrp(attrs, ATTR_IIDIS);
1924 if (iid)
1926 expr_t expr;
1928 expr.type = EXPR_IDENTIFIER;
1929 expr.ref = NULL;
1930 expr.u.sval = iid->name;
1931 expr.is_const = FALSE;
1932 print_file(file, 2, "0x2f, /* FC_IP */\n");
1933 print_file(file, 2, "0x5c, /* FC_PAD */\n");
1934 *typeformat_offset
1935 += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
1937 else
1939 const type_t *base = is_ptr(type) ? type->ref : type;
1940 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
1942 if (! uuid)
1943 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
1945 update_tfsoff(type, start_offset, file);
1946 print_start_tfs_comment(file, type, start_offset);
1947 print_file(file, 2, "0x2f,\t/* FC_IP */\n");
1948 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
1949 print_file(file, 2, "NdrFcLong(0x%08lx),\n", uuid->Data1);
1950 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
1951 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
1952 for (i = 0; i < 8; ++i)
1953 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
1955 if (file)
1956 fprintf(file, "\n");
1958 *typeformat_offset += 18;
1960 return start_offset;
1963 static size_t write_contexthandle_tfs(FILE *file, const type_t *type,
1964 const var_t *var,
1965 unsigned int *typeformat_offset)
1967 size_t start_offset = *typeformat_offset;
1968 unsigned char flags = 0x08 /* strict */;
1970 if (is_ptr(type))
1972 flags |= 0x80;
1973 if (type->type != RPC_FC_RP)
1974 flags |= 0x01;
1976 if (is_attr(var->attrs, ATTR_IN))
1977 flags |= 0x40;
1978 if (is_attr(var->attrs, ATTR_OUT))
1979 flags |= 0x20;
1981 WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
1982 print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
1983 if (((flags & 0x21) != 0x21) && (flags & 0x01))
1984 print_file(file, 0, "can't be null, ");
1985 if (flags & 0x02)
1986 print_file(file, 0, "serialize, ");
1987 if (flags & 0x04)
1988 print_file(file, 0, "no serialize, ");
1989 if (flags & 0x08)
1990 print_file(file, 0, "strict, ");
1991 if ((flags & 0x21) == 0x20)
1992 print_file(file, 0, "out, ");
1993 if ((flags & 0x21) == 0x21)
1994 print_file(file, 0, "return, ");
1995 if (flags & 0x40)
1996 print_file(file, 0, "in, ");
1997 if (flags & 0x80)
1998 print_file(file, 0, "via ptr, ");
1999 print_file(file, 0, "*/\n");
2000 print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
2001 print_file(file, 2, "0, /* FIXME: param num */\n");
2002 *typeformat_offset += 4;
2004 return start_offset;
2007 static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func,
2008 type_t *type, const var_t *var,
2009 unsigned int *typeformat_offset)
2011 size_t offset;
2013 if (is_context_handle(type))
2014 return write_contexthandle_tfs(file, type, var, typeformat_offset);
2016 if (is_user_type(type))
2018 write_user_tfs(file, type, typeformat_offset);
2019 return type->typestring_offset;
2022 if ((last_ptr(type) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING))
2023 return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset);
2025 if (is_array(type))
2027 int ptr_type;
2028 size_t off;
2029 off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset);
2030 ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2031 if (ptr_type && ptr_type != RPC_FC_RP)
2033 unsigned int absoff = type->typestring_offset;
2034 short reloff = absoff - (*typeformat_offset + 2);
2035 off = *typeformat_offset;
2036 print_file(file, 0, "/* %d */\n", off);
2037 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
2038 string_of_type(ptr_type));
2039 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2040 reloff, reloff, absoff);
2041 *typeformat_offset += 4;
2043 return off;
2046 if (!is_ptr(type))
2048 /* basic types don't need a type format string */
2049 if (is_base_type(type->type))
2050 return 0;
2052 switch (type->type)
2054 case RPC_FC_STRUCT:
2055 case RPC_FC_PSTRUCT:
2056 case RPC_FC_CSTRUCT:
2057 case RPC_FC_CPSTRUCT:
2058 case RPC_FC_CVSTRUCT:
2059 case RPC_FC_BOGUS_STRUCT:
2060 return write_struct_tfs(file, type, var->name, typeformat_offset);
2061 case RPC_FC_ENCAPSULATED_UNION:
2062 case RPC_FC_NON_ENCAPSULATED_UNION:
2063 return write_union_tfs(file, type, typeformat_offset);
2064 case RPC_FC_IGNORE:
2065 case RPC_FC_BIND_PRIMITIVE:
2066 /* nothing to do */
2067 return 0;
2068 default:
2069 error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name);
2072 else if (last_ptr(type))
2074 size_t start_offset = *typeformat_offset;
2075 int in_attr = is_attr(var->attrs, ATTR_IN);
2076 int out_attr = is_attr(var->attrs, ATTR_OUT);
2077 const type_t *base = type->ref;
2079 if (base->type == RPC_FC_IP)
2081 return write_ip_tfs(file, var->attrs, type, typeformat_offset);
2084 /* special case for pointers to base types */
2085 if (is_base_type(base->type))
2087 print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n",
2088 type->type, (!in_attr && out_attr) ? 0x0C : 0x08,
2089 string_of_type(type->type),
2090 (!in_attr && out_attr) ? "[allocated_on_stack] " : "");
2091 print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type));
2092 print_file(file, indent, "0x5c, /* FC_PAD */\n");
2093 *typeformat_offset += 4;
2094 return start_offset;
2098 assert(is_ptr(type));
2100 offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset);
2101 if (file)
2102 fprintf(file, "/* %2u */\n", *typeformat_offset);
2103 return write_pointer_only_tfs(file, var->attrs, type->type,
2104 !last_ptr(type) ? 0x10 : 0,
2105 offset, typeformat_offset);
2108 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
2109 const char *name, int write_ptr, unsigned int *tfsoff)
2111 int retmask = 0;
2113 if (is_user_type(type))
2115 write_user_tfs(file, type, tfsoff);
2117 else if (is_ptr(type))
2119 type_t *ref = type->ref;
2121 if (ref->type == RPC_FC_IP)
2123 write_ip_tfs(file, attrs, type, tfsoff);
2125 else
2127 if (!processed(ref) && !is_base_type(ref->type))
2128 retmask |= write_embedded_types(file, NULL, ref, name, TRUE, tfsoff);
2130 if (write_ptr)
2131 write_pointer_tfs(file, type, tfsoff);
2133 retmask |= 1;
2136 else if (last_array(type) && is_attr(attrs, ATTR_STRING))
2138 write_string_tfs(file, attrs, type, name, tfsoff);
2140 else if (type->declarray && is_conformant_array(type))
2141 ; /* conformant arrays and strings are handled specially */
2142 else if (is_array(type))
2144 write_array_tfs(file, attrs, type, name, tfsoff);
2145 if (is_conformant_array(type))
2146 retmask |= 1;
2148 else if (is_struct(type->type))
2150 if (!processed(type))
2151 write_struct_tfs(file, type, name, tfsoff);
2153 else if (is_union(type->type))
2155 if (!processed(type))
2156 write_union_tfs(file, type, tfsoff);
2158 else if (!is_base_type(type->type))
2159 error("write_embedded_types: unknown embedded type for %s (0x%x)\n",
2160 name, type->type);
2162 return retmask;
2165 static size_t process_tfs(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2167 const var_t *var;
2168 const ifref_t *iface;
2169 unsigned int typeformat_offset = 2;
2171 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2173 if (!pred(iface->iface))
2174 continue;
2176 if (iface->iface->funcs)
2178 const func_t *func;
2179 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2181 if (is_local(func->def->attrs)) continue;
2183 current_func = func;
2184 if (func->args)
2185 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2186 update_tfsoff(
2187 var->type,
2188 write_typeformatstring_var(
2189 file, 2, func, var->type, var,
2190 &typeformat_offset),
2191 file);
2196 return typeformat_offset + 1;
2200 void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, type_pred_t pred)
2202 int indent = 0;
2204 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
2205 print_file(file, indent, "{\n");
2206 indent++;
2207 print_file(file, indent, "0,\n");
2208 print_file(file, indent, "{\n");
2209 indent++;
2210 print_file(file, indent, "NdrFcShort(0x0),\n");
2212 set_all_tfswrite(TRUE);
2213 process_tfs(file, ifaces, pred);
2215 print_file(file, indent, "0x0\n");
2216 indent--;
2217 print_file(file, indent, "}\n");
2218 indent--;
2219 print_file(file, indent, "};\n");
2220 print_file(file, indent, "\n");
2223 static unsigned int get_required_buffer_size_type(
2224 const type_t *type, const char *name, unsigned int *alignment)
2226 *alignment = 0;
2227 if (is_user_type(type))
2229 const char *uname;
2230 const type_t *utype = get_user_type(type, &uname);
2231 return get_required_buffer_size_type(utype, uname, alignment);
2233 else
2235 switch (type->type)
2237 case RPC_FC_BYTE:
2238 case RPC_FC_CHAR:
2239 case RPC_FC_USMALL:
2240 case RPC_FC_SMALL:
2241 *alignment = 4;
2242 return 1;
2244 case RPC_FC_WCHAR:
2245 case RPC_FC_USHORT:
2246 case RPC_FC_SHORT:
2247 case RPC_FC_ENUM16:
2248 *alignment = 4;
2249 return 2;
2251 case RPC_FC_ULONG:
2252 case RPC_FC_LONG:
2253 case RPC_FC_ENUM32:
2254 case RPC_FC_FLOAT:
2255 case RPC_FC_ERROR_STATUS_T:
2256 *alignment = 4;
2257 return 4;
2259 case RPC_FC_HYPER:
2260 case RPC_FC_DOUBLE:
2261 *alignment = 8;
2262 return 8;
2264 case RPC_FC_IGNORE:
2265 case RPC_FC_BIND_PRIMITIVE:
2266 return 0;
2268 case RPC_FC_STRUCT:
2269 case RPC_FC_PSTRUCT:
2271 size_t size = 0;
2272 const var_t *field;
2273 if (!type->fields) return 0;
2274 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2276 unsigned int alignment;
2277 size += get_required_buffer_size_type(field->type, field->name,
2278 &alignment);
2280 return size;
2283 case RPC_FC_RP:
2284 return
2285 is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT
2286 ? get_required_buffer_size_type( type->ref, name, alignment )
2287 : 0;
2289 case RPC_FC_SMFARRAY:
2290 case RPC_FC_LGFARRAY:
2291 return type->dim * get_required_buffer_size_type(type->ref, name, alignment);
2293 default:
2294 return 0;
2299 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
2301 int in_attr = is_attr(var->attrs, ATTR_IN);
2302 int out_attr = is_attr(var->attrs, ATTR_OUT);
2303 const type_t *t;
2305 if (!in_attr && !out_attr)
2306 in_attr = 1;
2308 *alignment = 0;
2310 for (t = var->type; is_ptr(t); t = t->ref)
2311 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
2313 *alignment = 4;
2314 return 20;
2317 if (pass == PASS_OUT)
2319 if (out_attr && is_ptr(var->type))
2321 type_t *type = var->type;
2323 if (type->type == RPC_FC_STRUCT)
2325 const var_t *field;
2326 unsigned int size = 36;
2328 if (!type->fields) return size;
2329 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2331 unsigned int align;
2332 size += get_required_buffer_size_type(
2333 field->type, field->name, &align);
2335 return size;
2338 return 0;
2340 else
2342 if ((!out_attr || in_attr) && !var->type->size_is
2343 && !is_attr(var->attrs, ATTR_STRING) && !var->type->declarray)
2345 if (is_ptr(var->type))
2347 type_t *type = var->type;
2349 if (is_base_type(type->type))
2351 return 25;
2353 else if (type->type == RPC_FC_STRUCT)
2355 unsigned int size = 36;
2356 const var_t *field;
2358 if (!type->fields) return size;
2359 LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
2361 unsigned int align;
2362 size += get_required_buffer_size_type(
2363 field->type, field->name, &align);
2365 return size;
2370 return get_required_buffer_size_type(var->type, var->name, alignment);
2374 static unsigned int get_function_buffer_size( const func_t *func, enum pass pass )
2376 const var_t *var;
2377 unsigned int total_size = 0, alignment;
2379 if (func->args)
2381 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2383 total_size += get_required_buffer_size(var, &alignment, pass);
2384 total_size += alignment;
2388 if (pass == PASS_OUT && !is_void(func->def->type))
2390 total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN);
2391 total_size += alignment;
2393 return total_size;
2396 static void print_phase_function(FILE *file, int indent, const char *type,
2397 enum remoting_phase phase,
2398 const var_t *var, unsigned int type_offset)
2400 const char *function;
2401 switch (phase)
2403 case PHASE_BUFFERSIZE:
2404 function = "BufferSize";
2405 break;
2406 case PHASE_MARSHAL:
2407 function = "Marshall";
2408 break;
2409 case PHASE_UNMARSHAL:
2410 function = "Unmarshall";
2411 break;
2412 case PHASE_FREE:
2413 function = "Free";
2414 break;
2415 default:
2416 assert(0);
2417 return;
2420 print_file(file, indent, "Ndr%s%s(\n", type, function);
2421 indent++;
2422 print_file(file, indent, "&_StubMsg,\n");
2423 print_file(file, indent, "%s%s%s%s,\n",
2424 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
2425 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
2426 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
2427 var->name);
2428 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
2429 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
2430 if (phase == PHASE_UNMARSHAL)
2431 print_file(file, indent, "0);\n");
2432 indent--;
2435 void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase,
2436 enum pass pass, const var_t *var,
2437 const char *varname)
2439 type_t *type = var->type;
2440 unsigned int size;
2441 unsigned int alignment = 0;
2442 unsigned char rtype;
2444 /* no work to do for other phases, buffer sizing is done elsewhere */
2445 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
2446 return;
2448 rtype = is_ptr(type) ? type->ref->type : type->type;
2450 switch (rtype)
2452 case RPC_FC_BYTE:
2453 case RPC_FC_CHAR:
2454 case RPC_FC_SMALL:
2455 case RPC_FC_USMALL:
2456 size = 1;
2457 alignment = 1;
2458 break;
2460 case RPC_FC_WCHAR:
2461 case RPC_FC_USHORT:
2462 case RPC_FC_SHORT:
2463 case RPC_FC_ENUM16:
2464 size = 2;
2465 alignment = 2;
2466 break;
2468 case RPC_FC_ULONG:
2469 case RPC_FC_LONG:
2470 case RPC_FC_ENUM32:
2471 case RPC_FC_FLOAT:
2472 case RPC_FC_ERROR_STATUS_T:
2473 size = 4;
2474 alignment = 4;
2475 break;
2477 case RPC_FC_HYPER:
2478 case RPC_FC_DOUBLE:
2479 size = 8;
2480 alignment = 8;
2481 break;
2483 case RPC_FC_IGNORE:
2484 case RPC_FC_BIND_PRIMITIVE:
2485 /* no marshalling needed */
2486 return;
2488 default:
2489 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, rtype);
2490 size = 0;
2493 print_file(file, indent, "_StubMsg.Buffer = (unsigned char *)(((long)_StubMsg.Buffer + %u) & ~0x%x);\n",
2494 alignment - 1, alignment - 1);
2496 if (phase == PHASE_MARSHAL)
2498 print_file(file, indent, "*(");
2499 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2500 if (is_ptr(type))
2501 fprintf(file, " *)_StubMsg.Buffer = *");
2502 else
2503 fprintf(file, " *)_StubMsg.Buffer = ");
2504 fprintf(file, varname);
2505 fprintf(file, ";\n");
2507 else if (phase == PHASE_UNMARSHAL)
2509 if (pass == PASS_IN || pass == PASS_RETURN)
2510 print_file(file, indent, "");
2511 else
2512 print_file(file, indent, "*");
2513 fprintf(file, varname);
2514 if (pass == PASS_IN && is_ptr(type))
2515 fprintf(file, " = (");
2516 else
2517 fprintf(file, " = *(");
2518 write_type_decl(file, is_ptr(type) ? type->ref : type, NULL);
2519 fprintf(file, " *)_StubMsg.Buffer;\n");
2522 print_file(file, indent, "_StubMsg.Buffer += sizeof(");
2523 write_type_decl(file, var->type, NULL);
2524 fprintf(file, ");\n");
2527 /* returns whether the MaxCount, Offset or ActualCount members need to be
2528 * filled in for the specified phase */
2529 static inline int is_size_needed_for_phase(enum remoting_phase phase)
2531 return (phase != PHASE_UNMARSHAL);
2534 static int needs_freeing(const attr_list_t *attrs, const type_t *t, int out)
2536 return
2537 (is_user_type(t)
2538 || (is_ptr(t)
2539 && (t->ref->type == RPC_FC_IP
2540 || is_ptr(t->ref))))
2541 || (out && (is_string_type(attrs, t)
2542 || is_array(t)));
2545 void write_remoting_arguments(FILE *file, int indent, const func_t *func,
2546 enum pass pass, enum remoting_phase phase)
2548 int in_attr, out_attr, pointer_type;
2549 const var_t *var;
2551 if (!func->args)
2552 return;
2554 if (phase == PHASE_BUFFERSIZE)
2556 unsigned int size = get_function_buffer_size( func, pass );
2557 print_file(file, indent, "_StubMsg.BufferLength = %u;\n", size);
2560 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2562 const type_t *type = var->type;
2563 unsigned char rtype;
2564 size_t start_offset = type->typestring_offset;
2566 pointer_type = get_attrv(var->attrs, ATTR_POINTERTYPE);
2567 if (!pointer_type)
2568 pointer_type = RPC_FC_RP;
2570 in_attr = is_attr(var->attrs, ATTR_IN);
2571 out_attr = is_attr(var->attrs, ATTR_OUT);
2572 if (!in_attr && !out_attr)
2573 in_attr = 1;
2575 if (phase == PHASE_FREE)
2577 if (!needs_freeing(var->attrs, type, out_attr))
2578 continue;
2580 else
2581 switch (pass)
2583 case PASS_IN:
2584 if (!in_attr) continue;
2585 break;
2586 case PASS_OUT:
2587 if (!out_attr) continue;
2588 break;
2589 case PASS_RETURN:
2590 break;
2593 rtype = type->type;
2595 if (is_context_handle(type))
2597 if (phase == PHASE_MARSHAL)
2599 if (pass == PASS_IN)
2601 print_file(file, indent, "NdrClientContextMarshall(\n");
2602 print_file(file, indent + 1, "&_StubMsg,\n");
2603 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s,\n", is_ptr(type) ? "*" : "", var->name);
2604 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
2606 else
2608 print_file(file, indent, "NdrServerContextMarshall(\n");
2609 print_file(file, indent + 1, "&_StubMsg,\n");
2610 print_file(file, indent + 1, "(NDR_SCONTEXT)%s,\n", var->name);
2611 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown);\n", get_context_handle_type_name(var->type));
2614 else if (phase == PHASE_UNMARSHAL)
2616 if (pass == PASS_OUT)
2618 print_file(file, indent, "NdrClientContextUnmarshall(\n");
2619 print_file(file, indent + 1, "&_StubMsg,\n");
2620 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s,\n", var->name);
2621 print_file(file, indent + 1, "_Handle);\n");
2623 else
2624 print_file(file, indent, "%s = NdrServerContextUnmarshall(&_StubMsg);\n", var->name);
2627 else if (is_user_type(var->type))
2629 print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
2631 else if (is_string_type(var->attrs, var->type))
2633 if (is_array(type) && !is_conformant_array(type))
2634 print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
2635 else
2637 if (type->size_is && is_size_needed_for_phase(phase))
2639 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2640 write_expr(file, type->size_is, 1);
2641 fprintf(file, ";\n");
2644 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
2645 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2646 else
2647 print_phase_function(file, indent, "ConformantString", phase, var,
2648 start_offset + (type->size_is ? 4 : 2));
2651 else if (is_array(type))
2653 unsigned char tc = type->type;
2654 const char *array_type = "FixedArray";
2656 if (tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY)
2658 if (is_size_needed_for_phase(phase))
2660 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2661 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2662 write_expr(file, type->length_is, 1);
2663 fprintf(file, ";\n\n");
2665 array_type = "VaryingArray";
2667 else if (tc == RPC_FC_CARRAY)
2669 if (is_size_needed_for_phase(phase) && phase != PHASE_FREE)
2671 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2672 write_expr(file, type->size_is, 1);
2673 fprintf(file, ";\n\n");
2675 array_type = "ConformantArray";
2677 else if (tc == RPC_FC_CVARRAY || tc == RPC_FC_BOGUS_ARRAY)
2679 if (is_size_needed_for_phase(phase))
2681 if (type->size_is)
2683 print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
2684 write_expr(file, type->size_is, 1);
2685 fprintf(file, ";\n");
2687 if (type->length_is)
2689 print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
2690 print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
2691 write_expr(file, type->length_is, 1);
2692 fprintf(file, ";\n\n");
2695 array_type = (tc == RPC_FC_BOGUS_ARRAY
2696 ? "ComplexArray"
2697 : "ConformantVaryingArray");
2700 if (!in_attr && phase == PHASE_FREE)
2702 print_file(file, indent, "if (%s)\n", var->name);
2703 indent++;
2704 print_file(file, indent, "_StubMsg.pfnFree(%s);\n", var->name);
2706 else if (phase != PHASE_FREE)
2708 const char *t = pointer_type == RPC_FC_RP ? array_type : "Pointer";
2709 print_phase_function(file, indent, t, phase, var, start_offset);
2712 else if (!is_ptr(var->type) && is_base_type(rtype))
2714 print_phase_basetype(file, indent, phase, pass, var, var->name);
2716 else if (!is_ptr(var->type))
2718 switch (rtype)
2720 case RPC_FC_STRUCT:
2721 case RPC_FC_PSTRUCT:
2722 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
2723 break;
2724 case RPC_FC_CSTRUCT:
2725 case RPC_FC_CPSTRUCT:
2726 print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
2727 break;
2728 case RPC_FC_CVSTRUCT:
2729 print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
2730 break;
2731 case RPC_FC_BOGUS_STRUCT:
2732 print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
2733 break;
2734 case RPC_FC_RP:
2735 if (is_base_type( var->type->ref->type ))
2737 print_phase_basetype(file, indent, phase, pass, var, var->name);
2739 else if (var->type->ref->type == RPC_FC_STRUCT)
2741 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2742 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2744 else
2746 const var_t *iid;
2747 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2748 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2749 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2751 break;
2752 default:
2753 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype);
2756 else
2758 if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype))
2760 print_phase_basetype(file, indent, phase, pass, var, var->name);
2762 else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
2764 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
2765 print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
2767 else
2769 const var_t *iid;
2770 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
2771 print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
2772 if (var->type->ref->type == RPC_FC_IP)
2773 print_phase_function(file, indent, "InterfacePointer", phase, var, start_offset);
2774 else
2775 print_phase_function(file, indent, "Pointer", phase, var, start_offset);
2778 fprintf(file, "\n");
2783 size_t get_size_procformatstring_var(const var_t *var)
2785 return write_procformatstring_var(NULL, 0, var, FALSE);
2789 size_t get_size_procformatstring_func(const func_t *func)
2791 const var_t *var;
2792 size_t size = 0;
2794 /* argument list size */
2795 if (func->args)
2796 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2797 size += get_size_procformatstring_var(var);
2799 /* return value size */
2800 if (is_void(func->def->type))
2801 size += 2; /* FC_END and FC_PAD */
2802 else
2803 size += get_size_procformatstring_var(func->def);
2805 return size;
2808 size_t get_size_procformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2810 const ifref_t *iface;
2811 size_t size = 1;
2812 const func_t *func;
2814 if (ifaces) LIST_FOR_EACH_ENTRY( iface, ifaces, const ifref_t, entry )
2816 if (!pred(iface->iface))
2817 continue;
2819 if (iface->iface->funcs)
2820 LIST_FOR_EACH_ENTRY( func, iface->iface->funcs, const func_t, entry )
2821 if (!is_local(func->def->attrs))
2822 size += get_size_procformatstring_func( func );
2824 return size;
2827 size_t get_size_typeformatstring(const ifref_list_t *ifaces, type_pred_t pred)
2829 set_all_tfswrite(FALSE);
2830 return process_tfs(NULL, ifaces, pred);
2833 static void write_struct_expr(FILE *h, const expr_t *e, int brackets,
2834 const var_list_t *fields, const char *structvar)
2836 switch (e->type) {
2837 case EXPR_VOID:
2838 break;
2839 case EXPR_NUM:
2840 fprintf(h, "%lu", e->u.lval);
2841 break;
2842 case EXPR_HEXNUM:
2843 fprintf(h, "0x%lx", e->u.lval);
2844 break;
2845 case EXPR_DOUBLE:
2846 fprintf(h, "%#.15g", e->u.dval);
2847 break;
2848 case EXPR_TRUEFALSE:
2849 if (e->u.lval == 0)
2850 fprintf(h, "FALSE");
2851 else
2852 fprintf(h, "TRUE");
2853 break;
2854 case EXPR_IDENTIFIER:
2856 const var_t *field;
2857 LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2858 if (!strcmp(e->u.sval, field->name))
2860 fprintf(h, "%s->%s", structvar, e->u.sval);
2861 break;
2864 if (&field->entry == fields) error("no field found for identifier %s\n", e->u.sval);
2865 break;
2867 case EXPR_NEG:
2868 fprintf(h, "-");
2869 write_struct_expr(h, e->ref, 1, fields, structvar);
2870 break;
2871 case EXPR_NOT:
2872 fprintf(h, "~");
2873 write_struct_expr(h, e->ref, 1, fields, structvar);
2874 break;
2875 case EXPR_PPTR:
2876 fprintf(h, "*");
2877 write_struct_expr(h, e->ref, 1, fields, structvar);
2878 break;
2879 case EXPR_CAST:
2880 fprintf(h, "(");
2881 write_type_decl(h, e->u.tref, NULL);
2882 fprintf(h, ")");
2883 write_struct_expr(h, e->ref, 1, fields, structvar);
2884 break;
2885 case EXPR_SIZEOF:
2886 fprintf(h, "sizeof(");
2887 write_type_decl(h, e->u.tref, NULL);
2888 fprintf(h, ")");
2889 break;
2890 case EXPR_SHL:
2891 case EXPR_SHR:
2892 case EXPR_MUL:
2893 case EXPR_DIV:
2894 case EXPR_ADD:
2895 case EXPR_SUB:
2896 case EXPR_AND:
2897 case EXPR_OR:
2898 if (brackets) fprintf(h, "(");
2899 write_struct_expr(h, e->ref, 1, fields, structvar);
2900 switch (e->type) {
2901 case EXPR_SHL: fprintf(h, " << "); break;
2902 case EXPR_SHR: fprintf(h, " >> "); break;
2903 case EXPR_MUL: fprintf(h, " * "); break;
2904 case EXPR_DIV: fprintf(h, " / "); break;
2905 case EXPR_ADD: fprintf(h, " + "); break;
2906 case EXPR_SUB: fprintf(h, " - "); break;
2907 case EXPR_AND: fprintf(h, " & "); break;
2908 case EXPR_OR: fprintf(h, " | "); break;
2909 default: break;
2911 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2912 if (brackets) fprintf(h, ")");
2913 break;
2914 case EXPR_COND:
2915 if (brackets) fprintf(h, "(");
2916 write_struct_expr(h, e->ref, 1, fields, structvar);
2917 fprintf(h, " ? ");
2918 write_struct_expr(h, e->u.ext, 1, fields, structvar);
2919 fprintf(h, " : ");
2920 write_struct_expr(h, e->ext2, 1, fields, structvar);
2921 if (brackets) fprintf(h, ")");
2922 break;
2927 void declare_stub_args( FILE *file, int indent, const func_t *func )
2929 int in_attr, out_attr;
2930 int i = 0;
2931 const var_t *def = func->def;
2932 const var_t *var;
2934 /* declare return value '_RetVal' */
2935 if (!is_void(def->type))
2937 print_file(file, indent, "");
2938 write_type_decl_left(file, def->type);
2939 fprintf(file, " _RetVal;\n");
2942 if (!func->args)
2943 return;
2945 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2947 int is_string = is_attr(var->attrs, ATTR_STRING);
2949 in_attr = is_attr(var->attrs, ATTR_IN);
2950 out_attr = is_attr(var->attrs, ATTR_OUT);
2951 if (!out_attr && !in_attr)
2952 in_attr = 1;
2954 if (is_context_handle(var->type))
2955 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
2956 else
2958 if (!in_attr && !var->type->size_is && !is_string)
2960 print_file(file, indent, "");
2961 write_type_decl(file, var->type->ref, "_W%u", i++);
2962 fprintf(file, ";\n");
2965 print_file(file, indent, "");
2966 write_type_decl_left(file, var->type);
2967 fprintf(file, " ");
2968 if (var->type->declarray) {
2969 fprintf(file, "( *");
2970 write_name(file, var);
2971 fprintf(file, " )");
2972 } else
2973 write_name(file, var);
2974 write_type_right(file, var->type, FALSE);
2975 fprintf(file, ";\n");
2977 if (decl_indirect(var->type))
2978 print_file(file, indent, "void *_p_%s = &%s;\n",
2979 var->name, var->name);
2985 void assign_stub_out_args( FILE *file, int indent, const func_t *func )
2987 int in_attr, out_attr;
2988 int i = 0, sep = 0;
2989 const var_t *var;
2991 if (!func->args)
2992 return;
2994 LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
2996 int is_string = is_attr(var->attrs, ATTR_STRING);
2997 in_attr = is_attr(var->attrs, ATTR_IN);
2998 out_attr = is_attr(var->attrs, ATTR_OUT);
2999 if (!out_attr && !in_attr)
3000 in_attr = 1;
3002 if (!in_attr)
3004 print_file(file, indent, "");
3005 write_name(file, var);
3007 if (var->type->size_is)
3009 unsigned int size, align = 0;
3010 type_t *type = var->type;
3012 fprintf(file, " = NdrAllocate(&_StubMsg, ");
3013 for ( ; type->size_is ; type = type->ref)
3015 write_expr(file, type->size_is, TRUE);
3016 fprintf(file, " * ");
3018 size = type_memsize(type, &align);
3019 fprintf(file, "%u);\n", size);
3021 else if (!is_string)
3023 fprintf(file, " = &_W%u;\n", i);
3024 if (is_ptr(var->type) && !last_ptr(var->type))
3025 print_file(file, indent, "_W%u = 0;\n", i);
3026 i++;
3029 sep = 1;
3032 if (sep)
3033 fprintf(file, "\n");
3037 int write_expr_eval_routines(FILE *file, const char *iface)
3039 static const char *var_name = "pS";
3040 int result = 0;
3041 struct expr_eval_routine *eval;
3042 unsigned short callback_offset = 0;
3044 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
3046 const char *name = eval->structure->name;
3047 const var_list_t *fields = eval->structure->fields;
3048 result = 1;
3050 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
3051 iface, name, callback_offset);
3052 print_file(file, 0, "{\n");
3053 print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
3054 name, var_name, name, eval->baseoff);
3055 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
3056 print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
3057 write_struct_expr(file, eval->expr, 1, fields, var_name);
3058 fprintf(file, ";\n");
3059 print_file(file, 0, "}\n\n");
3060 callback_offset++;
3062 return result;
3065 void write_expr_eval_routine_list(FILE *file, const char *iface)
3067 struct expr_eval_routine *eval;
3068 struct expr_eval_routine *cursor;
3069 unsigned short callback_offset = 0;
3071 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
3072 fprintf(file, "{\n");
3074 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
3076 const char *name = eval->structure->name;
3077 print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
3078 callback_offset++;
3079 list_remove(&eval->entry);
3080 free(eval);
3083 fprintf(file, "};\n\n");
3086 void write_user_quad_list(FILE *file)
3088 user_type_t *ut;
3090 if (list_empty(&user_type_list))
3091 return;
3093 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
3094 fprintf(file, "{\n");
3095 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
3097 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
3098 print_file(file, 1, "{\n");
3099 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
3100 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
3101 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
3102 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
3103 print_file(file, 1, "}%s\n", sep);
3105 fprintf(file, "};\n\n");
3108 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
3110 const struct str_list_entry_t *endpoint;
3111 const char *p;
3113 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
3114 print_file( f, 0, "static const unsigned char * %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
3115 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
3117 print_file( f, 1, "{ (const unsigned char *)\"" );
3118 for (p = endpoint->str; *p && *p != ':'; p++)
3120 if (*p == '"' || *p == '\\') fputc( '\\', f );
3121 fputc( *p, f );
3123 if (!*p) goto error;
3124 if (p[1] != '[') goto error;
3126 fprintf( f, "\", (const unsigned char *)\"" );
3127 for (p += 2; *p && *p != ']'; p++)
3129 if (*p == '"' || *p == '\\') fputc( '\\', f );
3130 fputc( *p, f );
3132 if (*p != ']') goto error;
3133 fprintf( f, "\" },\n" );
3135 print_file( f, 0, "};\n\n" );
3136 return;
3138 error:
3139 error("Invalid endpoint syntax '%s'\n", endpoint->str);