From ef433e279295beeadcbec3f36016ffc3587834a3 Mon Sep 17 00:00:00 2001 From: Dan Hipschman Date: Wed, 9 May 2007 20:50:49 -0700 Subject: [PATCH] widl: Remove var_t's ptr_level field and start write_pointers. --- dlls/rpcrt4/tests/server.c | 40 +++ dlls/rpcrt4/tests/server.idl | 18 ++ tools/widl/client.c | 12 +- tools/widl/header.c | 81 +++--- tools/widl/header.h | 24 +- tools/widl/parser.y | 126 +++++--- tools/widl/proxy.c | 17 +- tools/widl/server.c | 4 +- tools/widl/typegen.c | 548 ++++++++++++++++++----------------- tools/widl/typegen.h | 2 +- tools/widl/widltypes.h | 12 +- tools/widl/write_msft.c | 30 +- 12 files changed, 529 insertions(+), 385 deletions(-) diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 51c570edccf..0086b97649c 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -114,6 +114,18 @@ s_sum_fixed_array(int a[5]) return a[0] + a[1] + a[2] + a[3] + a[4]; } +int +s_pints_sum(pints_t *pints) +{ + return *pints->pi + **pints->ppi + ***pints->pppi; +} + +double +s_ptypes_sum(ptypes_t *pt) +{ + return *pt->pc + *pt->ps + *pt->pl + *pt->pf + *pt->pd; +} + void s_stop(void) { @@ -155,9 +167,14 @@ basic_tests(void) static char string[] = "I am a string"; static int f[5] = {1, 3, 0, -2, -4}; static vector_t a = {1, 3, 7}; + pints_t pints; + ptypes_t ptypes; + int i1, i2, i3, *pi2, *pi3, **ppi3; double u, v; float s, t; long q, r; + short h; + char c; int x; ok(int_return() == INT_CODE, "RPC int_return\n"); @@ -191,6 +208,29 @@ basic_tests(void) ok(q == 9, "RPC square_half_long\n"); ok(r == 1, "RPC square_half_long\n"); + i1 = 19; + i2 = -3; + i3 = -29; + pi2 = &i2; + pi3 = &i3; + ppi3 = &pi3; + pints.pi = &i1; + pints.ppi = &pi2; + pints.pppi = &ppi3; + ok(pints_sum(&pints) == -13, "RPC pints_sum\n"); + + c = 10; + h = 3; + q = 14; + s = -5.0f; + u = 11.0; + ptypes.pc = &c; + ptypes.ps = &h; + ptypes.pl = &q; + ptypes.pf = &s; + ptypes.pd = &u; + ok(ptypes_sum(&ptypes) == 33.0, "RPC ptypes_sum\n"); + ok(sum_fixed_array(f) == -2, "RPC sum_fixed_array\n"); } diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl index c122870919f..4830e8c5f90 100644 --- a/dlls/rpcrt4/tests/server.idl +++ b/dlls/rpcrt4/tests/server.idl @@ -31,6 +31,22 @@ typedef struct tag_vector ] interface IServer { + typedef struct + { + int *pi; + int **ppi; + int ***pppi; + } pints_t; + + typedef struct + { + char *pc; + short *ps; + long *pl; + float *pf; + double *pd; + } ptypes_t; + int int_return(void); int square(int x); int sum(int x, int y); @@ -42,5 +58,7 @@ interface IServer float square_half_float(float x, [out] float *y); long square_half_long(long x, [out] long *y); int sum_fixed_array(int a[5]); + int pints_sum(pints_t *pints); + double ptypes_sum(ptypes_t *ptypes); void stop(void); } diff --git a/tools/widl/client.c b/tools/widl/client.c index 1652a3f0319..45747cf9fea 100644 --- a/tools/widl/client.c +++ b/tools/widl/client.c @@ -116,7 +116,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig } } - write_type(client, def->type, def); + write_type(client, def->type); fprintf(client, " "); write_prefix_name(client, prefix_client, def); fprintf(client, "(\n"); @@ -133,10 +133,10 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig indent++; /* declare return value '_RetVal' */ - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) { print_client(""); - write_type(client, def->type, def); + write_type(client, def->type); fprintf(client, " _RetVal;\n"); } @@ -226,7 +226,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig write_remoting_arguments(client, indent, func, type_offset, PASS_OUT, PHASE_UNMARSHAL); /* unmarshal return value */ - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) print_phase_basetype(client, indent, PHASE_UNMARSHAL, PASS_RETURN, def, "_RetVal"); /* update proc_offset */ @@ -235,7 +235,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) *proc_offset += get_size_procformatstring_var(var); } - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) *proc_offset += get_size_procformatstring_var(def); else *proc_offset += 2; /* FC_END and FC_PAD */ @@ -257,7 +257,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig /* emit return code */ - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) { fprintf(client, "\n"); print_client("return _RetVal;\n"); diff --git a/tools/widl/header.c b/tools/widl/header.c index 24ce8a07259..4f5b6b51091 100644 --- a/tools/widl/header.c +++ b/tools/widl/header.c @@ -46,6 +46,26 @@ static void indent(FILE *h, int delta) if (delta > 0) indentation += delta; } +int is_ptrchain_attr(const var_t *var, enum attr_type t) +{ + if (is_attr(var->attrs, t)) + return 1; + else + { + type_t *type = var->type; + for (;;) + { + if (is_attr(type->attrs, t)) + return 1; + else if (type->kind == TKIND_ALIAS) + type = type->orig; + else if (is_ptr(type)) + type = type->ref; + else return 0; + } + } +} + int is_attr(const attr_list_t *list, enum attr_type t) { const attr_t *attr; @@ -70,9 +90,8 @@ unsigned long get_attrv(const attr_list_t *list, enum attr_type t) return 0; } -int is_void(const type_t *t, const var_t *v) +int is_void(const type_t *t) { - if (v && v->ptr_level) return 0; if (!t->type && !t->ref) return 1; return 0; } @@ -105,15 +124,6 @@ void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID * uuid->Data4[6], uuid->Data4[7]); } -static void write_pident(FILE *h, const var_t *v) -{ - int c; - for (c=0; cptr_level; c++) { - fprintf(h, "*"); - } - if (v->name) fprintf(h, "%s", v->name); -} - void write_name(FILE *h, const var_t *v) { if (is_attr( v->attrs, ATTR_PROPGET )) @@ -159,11 +169,9 @@ static void write_field(FILE *h, var_t *v) if (!v) return; if (v->type) { indent(h, 0); - write_type(h, v->type, NULL); - if (get_name(v)) { - fprintf(h, " "); - write_pident(h, v); - } + write_type(h, v->type); + if (get_name(v)) + fprintf(h, " %s", v->name); else { /* not all C/C++ compilers support anonymous structs and unions */ switch (v->type->type) { @@ -220,10 +228,8 @@ static int needs_space_after(type_t *t) return t->kind == TKIND_ALIAS || ! is_ptr(t); } -void write_type(FILE *h, type_t *t, const var_t *v) +void write_type(FILE *h, type_t *t) { - int c; - if (t->is_const) fprintf(h, "const "); if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name); @@ -278,18 +284,13 @@ void write_type(FILE *h, type_t *t, const var_t *v) case RPC_FC_UP: case RPC_FC_FP: case RPC_FC_OP: - if (t->ref) write_type(h, t->ref, NULL); + if (t->ref) write_type(h, t->ref); fprintf(h, "%s*", needs_space_after(t->ref) ? " " : ""); break; default: fprintf(h, "%s", t->name); } } - if (v) { - for (c=0; cptr_level; c++) { - fprintf(h, "*"); - } - } } @@ -358,7 +359,7 @@ void write_user_types(void) void write_typedef(type_t *type) { fprintf(header, "typedef "); - write_type(header, type->orig, NULL); + write_type(header, type->orig); fprintf(header, "%s%s;\n", needs_space_after(type->orig) ? " " : "", type->name); } @@ -396,13 +397,13 @@ void write_expr(FILE *h, const expr_t *e, int brackets) break; case EXPR_CAST: fprintf(h, "("); - write_type(h, e->u.tref, NULL); + write_type(h, e->u.tref); fprintf(h, ")"); write_expr(h, e->ref, 1); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type(h, e->u.tref, NULL); + write_type(h, e->u.tref); fprintf(h, ")"); break; case EXPR_SHL: @@ -451,11 +452,9 @@ void write_constdef(const var_t *v) void write_externdef(const var_t *v) { fprintf(header, "extern const "); - write_type(header, v->type, NULL); - if (get_name(v)) { - fprintf(header, " "); - write_pident(header, v); - } + write_type(header, v->type); + if (get_name(v)) + fprintf(header, " %s", v->name); fprintf(header, ";\n\n"); } @@ -486,7 +485,7 @@ int has_out_arg_or_return(const func_t *func) { const var_t *var; - if (!is_void(func->def->type, NULL)) + if (!is_void(func->def->type)) return 1; if (!func->args) @@ -579,7 +578,7 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i } else fprintf(h, ","); } - write_type(h, arg->type, arg); + write_type(h, arg->type); if (arg->args) { fprintf(h, " (STDMETHODCALLTYPE *"); @@ -612,7 +611,7 @@ static void write_cpp_method_def(const type_t *iface) if (!is_callas(def->attrs)) { indent(header, 0); fprintf(header, "virtual "); - write_type(header, def->type, def); + write_type(header, def->type); fprintf(header, " STDMETHODCALLTYPE "); write_name(header, def); fprintf(header, "(\n"); @@ -637,7 +636,7 @@ static void do_write_c_method_def(const type_t *iface, const char *name) const var_t *def = cur->def; if (!is_callas(def->attrs)) { indent(header, 0); - write_type(header, def->type, def); + write_type(header, def->type); fprintf(header, " (STDMETHODCALLTYPE *"); write_name(header, def); fprintf(header, ")(\n"); @@ -670,7 +669,7 @@ static void write_method_proto(const type_t *iface) if (!is_local(def->attrs)) { /* proxy prototype */ - write_type(header, def->type, def); + write_type(header, def->type); fprintf(header, " CALLBACK %s_", iface->name); write_name(header, def); fprintf(header, "_Proxy(\n"); @@ -693,14 +692,14 @@ static void write_method_proto(const type_t *iface) if (&m->entry != iface->funcs) { const var_t *mdef = m->def; /* proxy prototype - use local prototype */ - write_type(header, mdef->type, mdef); + write_type(header, mdef->type); fprintf(header, " CALLBACK %s_", iface->name); write_name(header, mdef); fprintf(header, "_Proxy(\n"); write_args(header, m->args, iface->name, 1, TRUE); fprintf(header, ");\n"); /* stub prototype - use remotable prototype */ - write_type(header, def->type, def); + write_type(header, def->type); fprintf(header, " __RPC_STUB %s_", iface->name); write_name(header, mdef); fprintf(header, "_Stub(\n"); @@ -719,7 +718,7 @@ static void write_function_proto(const type_t *iface, const func_t *fun, const c var_t *def = fun->def; /* FIXME: do we need to handle call_as? */ - write_type(header, def->type, def); + write_type(header, def->type); fprintf(header, " "); write_prefix_name(header, prefix, def); fprintf(header, "(\n"); diff --git a/tools/widl/header.h b/tools/widl/header.h index 4de10262c40..57ae6b4a72d 100644 --- a/tools/widl/header.h +++ b/tools/widl/header.h @@ -21,16 +21,19 @@ #ifndef __WIDL_HEADER_H #define __WIDL_HEADER_H +#include "widltypes.h" + +extern int is_ptrchain_attr(const var_t *var, enum attr_type t); extern int is_attr(const attr_list_t *list, enum attr_type t); extern void *get_attrp(const attr_list_t *list, enum attr_type t); extern unsigned long get_attrv(const attr_list_t *list, enum attr_type t); -extern int is_void(const type_t *t, const var_t *v); +extern int is_void(const type_t *t); extern int is_conformant_array( const array_dims_t *array ); extern int is_non_void(const expr_list_t *list); extern void write_name(FILE *h, const var_t *v); extern void write_prefix_name(FILE *h, const char *prefix, const var_t *v); extern const char* get_name(const var_t *v); -extern void write_type(FILE *h, type_t *t, const var_t *v); +extern void write_type(FILE *h, type_t *t); extern int is_object(const attr_list_t *list); extern int is_local(const attr_list_t *list); extern const var_t *is_callas(const attr_list_t *list); @@ -52,16 +55,21 @@ extern int has_out_arg_or_return(const func_t *func); extern void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid); -static inline int is_string_type(const attr_list_t *attrs, int ptr_level, const array_dims_t *array) +static inline int last_ptr(const type_t *type) { - return (is_attr(attrs, ATTR_STRING) && - ((ptr_level == 1 && !array) || (ptr_level == 0 && array))); + return is_ptr(type) && !is_ptr(type->ref); } -static inline int is_array_type(const attr_list_t *attrs, int ptr_level, const array_dims_t *array) +static inline int is_string_type(const attr_list_t *attrs, const type_t *type, const array_dims_t *array) { - return ((ptr_level == 1 && !array && is_attr(attrs, ATTR_SIZEIS)) || - (ptr_level == 0 && array)); + return (is_attr(attrs, ATTR_STRING) && + ((last_ptr(type) && !array) || (!is_ptr(type) && array))); +} + +static inline int is_array_type(const attr_list_t *attrs, const type_t *type, const array_dims_t *array) +{ + return ((last_ptr(type) && !array && is_attr(attrs, ATTR_SIZEIS)) || + (!is_ptr(type) && array)); } #endif diff --git a/tools/widl/parser.y b/tools/widl/parser.y index b2f46916846..a74aab15ae5 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -79,11 +79,13 @@ static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, exp static type_t *make_type(unsigned char type, type_t *ref); static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); static array_dims_t *append_array(array_dims_t *list, expr_t *expr); -static void set_type(var_t *v, type_t *type, array_dims_t *arr); +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr); static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); static ifref_t *make_ifref(type_t *iface); static var_list_t *append_var(var_list_t *list, var_t *var); static var_t *make_var(char *name); +static pident_list_t *append_pident(pident_list_t *list, pident_t *p); +static pident_t *make_pident(var_t *var); static func_list_t *append_func(func_list_t *list, func_t *func); static func_t *make_func(var_t *def, var_list_t *args); static type_t *make_class(char *name); @@ -127,6 +129,8 @@ static void check_arg(var_t *arg); type_t *type; var_t *var; var_list_t *var_list; + pident_t *pident; + pident_list_t *pident_list; func_t *func; func_list_t *func_list; ifref_t *ifref; @@ -234,8 +238,10 @@ static void check_arg(var_t *arg); %type coclass_int %type gbl_statements coclass_ints %type arg field s_field case enum constdef externdef -%type m_args no_args args fields cases enums enum_list pident_list dispint_props -%type m_ident t_ident ident p_ident pident +%type m_args no_args args fields cases enums enum_list dispint_props +%type m_ident t_ident ident +%type p_ident pident +%type pident_list %type funcdef %type int_statements dispint_meths %type coclass coclasshdr coclassdef @@ -297,12 +303,12 @@ int_statements: { $$ = NULL; } statement: ';' {} | constdef ';' { if (!parse_only && do_header) { write_constdef($1); } } | cppquote {} - | enumdef ';' { if (!parse_only && do_header) { write_type(header, $1, NULL); fprintf(header, ";\n\n"); } } + | enumdef ';' { if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } } | externdef ';' { if (!parse_only && do_header) { write_externdef($1); } } | import {} - | structdef ';' { if (!parse_only && do_header) { write_type(header, $1, NULL); fprintf(header, ";\n\n"); } } + | structdef ';' { if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } } | typedef ';' {} - | uniondef ';' { if (!parse_only && do_header) { write_type(header, $1, NULL); fprintf(header, ";\n\n"); } } + | uniondef ';' { if (!parse_only && do_header) { write_type(header, $1); fprintf(header, ";\n\n"); } } ; cppquote: tCPPQUOTE '(' aSTRING ')' { if (!parse_only && do_header) fprintf(header, "%s\n", $3); } @@ -339,22 +345,24 @@ args: arg { check_arg($1); $$ = append_var( NULL, $1 ); } ; /* split into two rules to get bison to resolve a tVOID conflict */ -arg: attributes type pident array { $$ = $3; - set_type($$, $2, $4); +arg: attributes type pident array { $$ = $3->var; + set_type($$, $2, $3->ptr_level, $4); + free($3); $$->attrs = $1; } - | type pident array { $$ = $2; - set_type($$, $1, $3); + | type pident array { $$ = $2->var; + set_type($$, $1, $2->ptr_level, $3); + free($2); } - | attributes type pident '(' m_args ')' { $$ = $3; - $$->ptr_level--; - set_type($$, $2, NULL); + | attributes type pident '(' m_args ')' { $$ = $3->var; + set_type($$, $2, $3->ptr_level - 1, NULL); + free($3); $$->attrs = $1; $$->args = $5; } - | type pident '(' m_args ')' { $$ = $2; - $$->ptr_level--; - set_type($$, $1, NULL); + | type pident '(' m_args ')' { $$ = $2->var; + set_type($$, $1, $2->ptr_level - 1, NULL); + free($2); $$->args = $4; } ; @@ -482,7 +490,7 @@ case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, $2); ; constdef: tCONST type ident '=' expr_const { $$ = reg_const($3); - set_type($$, $2, NULL); + set_type($$, $2, 0, NULL); $$->eval = $5; } ; @@ -574,7 +582,7 @@ expr_const: expr { $$ = $1; ; externdef: tEXTERN tCONST type ident { $$ = $4; - set_type($$, $3, NULL); + set_type($$, $3, 0, NULL); } ; @@ -588,15 +596,21 @@ field: s_field ';' { $$ = $1; } | ';' { $$ = NULL; } ; -s_field: m_attributes type pident array { $$ = $3; set_type($$, $2, $4); $$->attrs = $1; } +s_field: m_attributes type pident array { $$ = $3->var; + set_type($$, $2, $3->ptr_level, $4); + free($3); + $$->attrs = $1; + } ; funcdef: m_attributes type callconv pident - '(' m_args ')' { set_type($4, $2, NULL); - $4->attrs = $1; - $$ = make_func($4, $6); - if (is_attr($4->attrs, ATTR_IN)) { + '(' m_args ')' { var_t *v = $4->var; + set_type(v, $2, $4->ptr_level, NULL); + free($4); + v->attrs = $1; + $$ = make_func(v, $6); + if (is_attr(v->attrs, ATTR_IN)) { yyerror("inapplicable attribute [in] for function '%s'",$$->def->name); } } @@ -792,14 +806,14 @@ p_ident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; } | tCONST p_ident { $$ = $2; /* FIXME */ } ; -pident: ident +pident: ident { $$ = make_pident($1); } | p_ident | '(' pident ')' { $$ = $2; } ; pident_list: - pident { $$ = append_var( NULL, $1 ); } - | pident_list ',' pident { $$ = append_var( $1, $3 ); } + pident { $$ = append_pident( NULL, $1 ); } + | pident_list ',' pident { $$ = append_pident( $1, $3 ); } ; pointer_type: @@ -1185,6 +1199,7 @@ static type_t *make_type(unsigned char type, type_t *ref) t->funcs = NULL; t->fields = NULL; t->ifaces = NULL; + t->typestring_offset = 0; t->ignore = parse_only; t->is_const = FALSE; t->sign = 0; @@ -1195,10 +1210,13 @@ static type_t *make_type(unsigned char type, type_t *ref) return t; } -static void set_type(var_t *v, type_t *type, array_dims_t *arr) +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr) { v->type = type; v->array = arr; + + for ( ; 0 < ptr_level; --ptr_level) + v->type = make_type(RPC_FC_RP, v->type); } static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface) @@ -1237,7 +1255,6 @@ static var_t *make_var(char *name) { var_t *v = xmalloc(sizeof(var_t)); v->name = name; - v->ptr_level = 0; v->type = NULL; v->args = NULL; v->attrs = NULL; @@ -1246,6 +1263,25 @@ static var_t *make_var(char *name) return v; } +static pident_list_t *append_pident(pident_list_t *list, pident_t *p) +{ + if (!p) return list; + if (!list) { + list = xmalloc(sizeof(*list)); + list_init(list); + } + list_add_tail(list, &p->entry); + return list; +} + +static pident_t *make_pident(var_t *var) +{ + pident_t *p = xmalloc(sizeof(*p)); + p->var = var; + p->ptr_level = 0; + return p; +} + static func_list_t *append_func(func_list_t *list, func_t *func) { if (!func) return list; @@ -1326,10 +1362,10 @@ static type_t *reg_type(type_t *type, const char *name, int t) return type; } -static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs) +static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *attrs) { type_t *ptr = type; - const var_t *name; + const pident_t *pident; int ptrc = 0; int is_str = is_attr(attrs, ATTR_STRING); unsigned char ptr_type = get_attrv(attrs, ATTR_POINTERTYPE); @@ -1345,9 +1381,9 @@ static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs) c = t->type; if (c != RPC_FC_CHAR && c != RPC_FC_BYTE && c != RPC_FC_WCHAR) { - name = LIST_ENTRY( list_head( names ), const var_t, entry ); + pident = LIST_ENTRY( list_head( pidents ), const pident_t, entry ); yyerror("'%s': [string] attribute is only valid on 'char', 'byte', or 'wchar_t' pointers and arrays", - name->name); + pident->var->name); } } @@ -1363,11 +1399,13 @@ static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs) type->name = gen_name(); } - LIST_FOR_EACH_ENTRY( name, names, const var_t, entry ) + LIST_FOR_EACH_ENTRY( pident, pidents, const pident_t, entry ) { + var_t *name = pident->var; + if (name->name) { type_t *cur = ptr; - int cptr = name->ptr_level; + int cptr = pident->ptr_level; if (cptr > ptrc) { while (cptr > ptrc) { cur = ptr = make_type(RPC_FC_RP, cur); @@ -1467,20 +1505,20 @@ static int get_struct_type(var_list_t *fields) { type_t *t = field->type; - if (field->ptr_level > 0) + if (is_ptr(field->type)) { has_pointer = 1; continue; } - if (is_string_type(field->attrs, 0, field->array)) + if (is_string_type(field->attrs, field->type, field->array)) { has_conformance = 1; has_variance = 1; continue; } - if (is_array_type(field->attrs, 0, field->array)) + if (is_array_type(field->attrs, field->type, field->array)) { if (field->array && is_conformant_array(field->array)) { @@ -1700,21 +1738,23 @@ static char *gen_name(void) return name; } -static void process_typedefs(var_list_t *names) +static void process_typedefs(pident_list_t *pidents) { - var_t *name, *next; + pident_t *pident, *next; - if (!names) return; - LIST_FOR_EACH_ENTRY_SAFE( name, next, names, var_t, entry ) + if (!pidents) return; + LIST_FOR_EACH_ENTRY_SAFE( pident, next, pidents, pident_t, entry ) { - type_t *type = find_type(name->name, 0); + var_t *var = pident->var; + type_t *type = find_type(var->name, 0); if (! parse_only && do_header) write_typedef(type); if (in_typelib && type->attrs) add_typelib_entry(type); - free(name); + free(pident); + free(var); } } diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c index 6e0817a0687..2eb9de116c1 100644 --- a/tools/widl/proxy.c +++ b/tools/widl/proxy.c @@ -138,7 +138,7 @@ static void clear_output_vars( const var_list_t *args ) int is_var_ptr(const var_t *v) { - return v->ptr_level || is_ptr(v->type); + return is_ptr(v->type); } int cant_be_null(const var_t *v) @@ -247,12 +247,17 @@ static void proxy_free_variables( var_list_t *args, unsigned int type_offset ) if (!args) return; LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) { + size_t start_offset; + size_t size_type = get_size_typeformatstring_var(arg, &start_offset); + start_offset += type_offset; + if (is_attr(arg->attrs, ATTR_OUT)) { free_variable( arg, type_offset ); fprintf(proxy, "\n"); } - type_offset += get_size_typeformatstring_var(arg); + + type_offset += size_type; } } @@ -260,11 +265,11 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, unsigned int proc_offset, unsigned int *type_offset) { var_t *def = cur->def; - int has_ret = !is_void(def->type, def); + int has_ret = !is_void(def->type); unsigned int offset; indent = 0; - write_type(proxy, def->type, def); + write_type(proxy, def->type); print_proxy( " STDMETHODCALLTYPE %s_", iface->name); write_name(proxy, def); print_proxy( "_Proxy(\n"); @@ -275,7 +280,7 @@ static void gen_proxy(type_t *iface, const func_t *cur, int idx, /* local variables */ if (has_ret) { print_proxy( "" ); - write_type(proxy, def->type, def); + write_type(proxy, def->type); print_proxy( " _RetVal;\n"); } print_proxy( "RPC_MESSAGE _RpcMessage;\n" ); @@ -355,7 +360,7 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas, { var_t *def = cur->def; const var_t *arg; - int has_ret = !is_void(def->type, def); + int has_ret = !is_void(def->type); unsigned int offset; indent = 0; diff --git a/tools/widl/server.c b/tools/widl/server.c index a51a69cf3ec..be366eabf05 100644 --- a/tools/widl/server.c +++ b/tools/widl/server.c @@ -192,7 +192,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig assign_stub_out_args(server, indent, func); /* Call the real server function */ - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) print_server("_RetVal = "); else print_server(""); @@ -246,7 +246,7 @@ static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsig write_remoting_arguments(server, indent, func, type_offset, PASS_OUT, PHASE_MARSHAL); /* marshall the return value */ - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) print_phase_basetype(server, indent, PHASE_MARSHAL, PASS_RETURN, def, "_RetVal"); indent--; diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index d3d2c1c23fd..e8385ec7ac1 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -59,7 +59,7 @@ struct expr_eval_routine const expr_t *expr; }; -static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *array, unsigned int *align); +static size_t type_memsize(const type_t *t, const array_dims_t *array, unsigned int *align); static size_t fields_memsize(const var_list_t *fields, unsigned int *align); const char *string_of_type(unsigned char type) @@ -235,7 +235,6 @@ static size_t write_procformatstring_var(FILE *file, int indent, const var_t *var, int is_return, unsigned int *type_offset) { size_t size; - int ptr_level = var->ptr_level; const type_t *type = var->type; int is_in = is_attr(var->attrs, ATTR_IN); @@ -243,7 +242,7 @@ static size_t write_procformatstring_var(FILE *file, int indent, if (!is_in && !is_out) is_in = TRUE; - if (ptr_level == 0 && !var->array && is_base_type(type->type)) + if (!var->array && is_base_type(type->type)) { if (is_return) print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n"); @@ -281,7 +280,7 @@ static size_t write_procformatstring_var(FILE *file, int indent, print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset); size = 4; /* includes param type prefix */ } - *type_offset += get_size_typeformatstring_var(var); + *type_offset += get_size_typeformatstring_var(var, NULL); return size; } @@ -319,7 +318,7 @@ void write_procformatstring(FILE *file, const ifref_list_t *ifaces, int for_obje /* emit return value data */ var = func->def; - if (is_void(var->type, NULL)) + if (is_void(var->type)) { print_file(file, indent, "0x5b, /* FC_END */\n"); print_file(file, indent, "0x5c, /* FC_PAD */\n"); @@ -347,6 +346,7 @@ static int write_base_type(FILE *file, const type_t *type, unsigned int *typestr *typestring_offset += 1; return 1; } + return 0; } @@ -439,7 +439,7 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_ if (structure->fields) LIST_FOR_EACH_ENTRY( var, structure->fields, const var_t, entry ) { unsigned int align = 0; - offset -= type_memsize(var->type, var->ptr_level, var->array, &align); + offset -= type_memsize(var->type, var->array, &align); /* FIXME: take alignment into account */ if (!strcmp(var->name, subexpr->u.sval)) { @@ -593,7 +593,7 @@ static size_t fields_memsize(const var_list_t *fields, unsigned int *align) if (!fields) return 0; LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) - size += type_memsize(v->type, v->ptr_level, v->array, align); + size += type_memsize(v->type, v->array, align); return size; } @@ -614,11 +614,11 @@ static size_t get_array_size( const array_dims_t *array ) return size; } -static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *array, unsigned int *align) +static size_t type_memsize(const type_t *t, const array_dims_t *array, unsigned int *align) { size_t size = 0; - if (ptr_level) + if (is_ptr(t)) { size = sizeof(void *); if (size > *align) *align = size; @@ -671,8 +671,29 @@ static size_t type_memsize(const type_t *t, int ptr_level, const array_dims_t *a return size; } +static size_t write_nonsimple_pointer(FILE *file, const type_t *type, size_t offset) +{ + short absoff = type->ref->typestring_offset; + short reloff = absoff - (offset + 2); + print_file(file, 2, "0x%02x, 0x10,\t/* %s */\n", + type->type, string_of_type(type->type)); + print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%hd) */\n", + reloff, reloff, absoff); + return 4; +} + +static size_t write_simple_pointer(FILE *file, const type_t *type) +{ + print_file(file, 2, "0x%02x, 0x8,\t/* %s [simple_pointer] */\n", + type->type, string_of_type(type->type)); + print_file(file, 2, "0x%02x,\t/* %s */\n", type->ref->type, + string_of_type(type->ref->type)); + print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); + return 4; +} + static int write_pointers(FILE *file, const attr_list_t *attrs, - const type_t *type, int ptr_level, + type_t *type, const array_dims_t *array, int level, unsigned int *typestring_offset) { @@ -681,15 +702,43 @@ static int write_pointers(FILE *file, const attr_list_t *attrs, /* don't generate a pointer for first-level arrays since we want to * descend into them to write their pointers, not stop here */ - if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array)) + if ((level == 0 || !is_ptr(type)) && is_array_type(attrs, type, array)) { - return write_pointers(file, NULL, type, 0, NULL, level + 1, typestring_offset); + return write_pointers(file, NULL, type, NULL, level + 1, typestring_offset); } - if (ptr_level != 0) + if (is_ptr(type)) { - /* FIXME: only general algorithm implemented, not the actual writing */ - error("write_pointers: Writing type format string for pointer is unimplemented\n"); + if (!is_ptr(type->ref) && 1 < level) + { + print_file(file, 0, "/* %d */\n", *typestring_offset); + if (type->ref->typestring_offset) + { + type->typestring_offset = *typestring_offset; + *typestring_offset += write_nonsimple_pointer(file, type, *typestring_offset); + } + else if (is_base_type(type->ref->type)) + { + type->typestring_offset = *typestring_offset; + *typestring_offset += write_simple_pointer(file, type); + } + else + error("write_pointers: pointer doesn't point to anything recognizable (0x%02x)\n", + type->ref->type); + } + else + { + pointers_written = write_pointers(file, attrs, type->ref, array, + level + 1, typestring_offset); + + if (1 < level) + { + print_file(file, 0, "/* %d */\n", *typestring_offset); + type->typestring_offset = *typestring_offset; + *typestring_offset += write_nonsimple_pointer(file, type, *typestring_offset); + } + } + return 1; } @@ -705,7 +754,7 @@ static int write_pointers(FILE *file, const attr_list_t *attrs, if (!type->fields) break; LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry ) pointers_written += write_pointers(file, v->attrs, v->type, - v->ptr_level, v->array, + v->array, level + 1, typestring_offset); @@ -720,34 +769,45 @@ static int write_pointers(FILE *file, const attr_list_t *attrs, } static size_t write_pointer_description(FILE *file, const attr_list_t *attrs, - const type_t *type, int ptr_level, + const type_t *type, size_t mem_offset, const array_dims_t *array, int level, - size_t typestring_offset) + size_t *typestring_offset) { - size_t size = 0; const var_t *v; + unsigned int align = 0; /* don't generate a pointer for first-level arrays since we want to * descend into them to write their pointers, not stop here */ - if ((level == 0 || ptr_level == 0) && is_array_type(attrs, ptr_level, array)) + if ((level == 0 || !is_ptr(type)) && is_array_type(attrs, type, array)) { - return write_pointer_description(file, NULL, type, 0, NULL, - level + 1, typestring_offset); + write_pointer_description(file, NULL, type, mem_offset, NULL, + level + 1, typestring_offset); } - - if (ptr_level != 0) + else if (is_ptr(type)) { - /* FIXME: only general algorithm implemented, not the actual writing */ - error("write_pointer_description: Writing pointer description is unimplemented\n"); - return 0; + print_file(file, 2, "0x46,\t/* FC_NO_REPEAT */\n"); + print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset); + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", mem_offset, mem_offset); + + if (type->ref->typestring_offset) + { + *typestring_offset + += 6 + write_nonsimple_pointer(file, type, 6 + *typestring_offset); + } + else if (is_base_type(type->ref->type)) + { + *typestring_offset += 6 + write_simple_pointer(file, type); + } + else + error("write_pointer_description: unimplemented\n"); } - - /* FIXME: search through all refs for pointers too */ - - switch (type->type) + else { - /* note: don't descend into complex structures or unions since these - * will always be generated as a separate type */ + switch (type->type) + { + /* note: don't descend into complex structures or unions since these + * will always be generated as a separate type */ case RPC_FC_STRUCT: case RPC_FC_CVSTRUCT: case RPC_FC_CPSTRUCT: @@ -755,19 +815,21 @@ static size_t write_pointer_description(FILE *file, const attr_list_t *attrs, case RPC_FC_PSTRUCT: if (!type->fields) break; LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry ) - size += write_pointer_description(file, v->attrs, v->type, - v->ptr_level, v->array, - level + 1, - typestring_offset); - + { + mem_offset + += write_pointer_description(file, v->attrs, v->type, + mem_offset, v->array, + level + 1, + typestring_offset); + } break; default: - /* nothing to do */ break; + } } - return size; + return type_memsize(type, array, &align); } static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, @@ -805,7 +867,7 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2,"0x%x, 0x%x, /* %s%s */\n", pointer_type, flags, - string_of_type(pointer_type), + pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP"), (flags & RPC_FC_P_SIMPLEPOINTER) ? " [simple_pointer]" : ""); *typestring_offset += 2; @@ -862,7 +924,7 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs, } static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, - const type_t *type, const array_dims_t *array, + type_t *type, const array_dims_t *array, const char *name, unsigned int *typestring_offset) { const expr_list_t *length_is = get_attrp(attrs, ATTR_LENGTHIS); @@ -876,7 +938,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, 0x00, /* %s */\n", pointer_type, - string_of_type(pointer_type)); + pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP")); print_file(file, 2, "NdrFcShort(0x2),\n"); *typestring_offset += 4; @@ -888,10 +950,9 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, else { const expr_t *dim = array ? LIST_ENTRY( list_head( array ), expr_t, entry ) : NULL; - size_t pointer_start_offset = *typestring_offset; int has_pointer = 0; - if (write_pointers(file, attrs, type, 0, array, 0, typestring_offset) > 0) + if (write_pointers(file, attrs, type, array, 0, typestring_offset) > 0) has_pointer = 1; start_offset = *typestring_offset; @@ -900,7 +961,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, { /* fixed array */ unsigned int align = 0; - size_t size = type_memsize(type, 0, array, &align); + size_t size = type_memsize(type, array, &align); if (size < USHRT_MAX) { WRITE_FCTYPE(file, FC_SMFARRAY, *typestring_offset); @@ -925,8 +986,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset = write_pointer_description(file, attrs, - type, 0, array, 0, pointer_start_offset); + write_pointer_description(file, attrs, type, 0, array, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -945,7 +1005,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, { /* varying array */ unsigned int align = 0; - size_t element_size = type_memsize(type, 0, NULL, &align); + size_t element_size = type_memsize(type, NULL, &align); size_t elements = dim->cval; size_t total_size = element_size * elements; @@ -984,8 +1044,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset += write_pointer_description(file, attrs, - type, 0, array, 0, pointer_start_offset); + write_pointer_description(file, attrs, type, 0, array, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -1004,7 +1063,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, { /* conformant array */ unsigned int align = 0; - size_t element_size = type_memsize(type, 0, NULL, &align); + size_t element_size = type_memsize(type, NULL, &align); WRITE_FCTYPE(file, FC_CARRAY, *typestring_offset); /* alignment */ @@ -1022,8 +1081,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset += write_pointer_description(file, attrs, - type, 0, array, 0, pointer_start_offset); + write_pointer_description(file, attrs, type, 0, array, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -1042,7 +1100,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, { /* conformant varying array */ unsigned int align = 0; - size_t element_size = type_memsize(type, 0, NULL, &align); + size_t element_size = type_memsize(type, NULL, &align); WRITE_FCTYPE(file, FC_CVARRAY, *typestring_offset); /* alignment */ @@ -1063,8 +1121,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset += write_pointer_description(file, attrs, - type, 0, array, 0, pointer_start_offset); + write_pointer_description(file, attrs, type, 0, array, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -1086,7 +1143,7 @@ static const var_t *find_array_or_string_in_struct(const type_t *type) { const var_t *last_field = LIST_ENTRY( list_tail(type->fields), const var_t, entry ); - if (is_array_type(last_field->attrs, last_field->ptr_level, last_field->array)) + if (is_array_type(last_field->attrs, last_field->type, last_field->array)) return last_field; assert((last_field->type->type == RPC_FC_CSTRUCT) || @@ -1107,6 +1164,12 @@ static void write_struct_members(FILE *file, const type_t *type, unsigned int *t if (field->array) write_array_tfs( file, field->attrs, field->type, field->array, field->name, typestring_offset ); + else if (is_ptr( field->type )) + { + /* pointers are handled in detail earlier, here just treat them like longs */ + print_file( file, 2, "0x8,\t/* FC_LONG */\n" ); + *typestring_offset += 1; + } else if (!write_base_type( file, field->type, typestring_offset )) error("Unsupported member type 0x%x\n", rtype); } @@ -1121,32 +1184,28 @@ static void write_struct_members(FILE *file, const type_t *type, unsigned int *t *typestring_offset += 1; } -static size_t write_struct_tfs(FILE *file, const type_t *type, +static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *typestring_offset) { unsigned int total_size; const var_t *array; size_t start_offset; size_t array_offset; - size_t pointer_offset; + int has_pointers; unsigned int align = 0; switch (type->type) { case RPC_FC_STRUCT: case RPC_FC_PSTRUCT: - total_size = type_memsize(type, 0, NULL, &align); + total_size = type_memsize(type, NULL, &align); if (total_size > USHRT_MAX) error("structure size for parameter %s exceeds %d bytes by %d bytes\n", name, USHRT_MAX, total_size - USHRT_MAX); if (type->type == RPC_FC_PSTRUCT) - { - pointer_offset = *typestring_offset; - write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset); - } - else pointer_offset = 0; /* silence warning */ + write_pointers(file, NULL, type, NULL, 0, typestring_offset); start_offset = *typestring_offset; if (type->type == RPC_FC_STRUCT) @@ -1164,8 +1223,7 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset += write_pointer_description(file, NULL, - type, 0, NULL, 0, pointer_offset); + write_pointer_description(file, NULL, type, 0, NULL, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -1175,7 +1233,7 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, return start_offset; case RPC_FC_CSTRUCT: case RPC_FC_CPSTRUCT: - total_size = type_memsize(type, 0, NULL, &align); + total_size = type_memsize(type, NULL, &align); if (total_size > USHRT_MAX) error("structure size for parameter %s exceeds %d bytes by %d bytes\n", @@ -1189,11 +1247,7 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, current_structure = NULL; if (type->type == RPC_FC_CPSTRUCT) - { - pointer_offset = *typestring_offset; - write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset); - } - else pointer_offset = 0; /* silence warning */ + write_pointers(file, NULL, type, NULL, 0, typestring_offset); start_offset = *typestring_offset; if (type->type == RPC_FC_CSTRUCT) @@ -1216,8 +1270,7 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset += write_pointer_description(file, NULL, - type, 0, NULL, 0, pointer_offset); + write_pointer_description(file, NULL, type, 0, NULL, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -1227,7 +1280,7 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, return start_offset; case RPC_FC_CVSTRUCT: - total_size = type_memsize(type, 0, NULL, &align); + total_size = type_memsize(type, NULL, &align); if (total_size > USHRT_MAX) error("structure size for parameter %s exceeds %d bytes by %d bytes\n", @@ -1245,9 +1298,7 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, typestring_offset); current_structure = NULL; - pointer_offset = *typestring_offset; - if (!write_pointers(file, NULL, type, 0, NULL, 0, typestring_offset)) - pointer_offset = 0; + has_pointers = write_pointers(file, NULL, type, NULL, 0, typestring_offset); start_offset = *typestring_offset; WRITE_FCTYPE(file, FC_CVSTRUCT, *typestring_offset); @@ -1262,13 +1313,12 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, array_offset); *typestring_offset += 2; - if (pointer_offset != 0) + if (has_pointers) { print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); *typestring_offset += 2; - *typestring_offset += write_pointer_description(file, NULL, - type, 0, NULL, 0, pointer_offset); + write_pointer_description(file, NULL, type, 0, NULL, 0, typestring_offset); print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); *typestring_offset += 1; } @@ -1283,10 +1333,12 @@ static size_t write_struct_tfs(FILE *file, const type_t *type, } } -static void write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type, - unsigned char flags, size_t offset, - unsigned int *typeformat_offset) +static size_t write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int pointer_type, + unsigned char flags, size_t offset, + unsigned int *typeformat_offset) { + size_t start_offset = *typeformat_offset; + short reloff = offset - (*typeformat_offset + 2); int in_attr, out_attr; in_attr = is_attr(attrs, ATTR_IN); out_attr = is_attr(attrs, ATTR_OUT); @@ -1298,7 +1350,7 @@ static void write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int poi print_file(file, 2, "0x%x, 0x%x,\t\t/* %s", pointer_type, flags, - string_of_type(pointer_type)); + pointer_type == RPC_FC_FP ? "FC_FP" : (pointer_type == RPC_FC_UP ? "FC_UP" : "FC_RP")); if (file) { if (flags & 0x04) @@ -1308,8 +1360,10 @@ static void write_pointer_only_tfs(FILE *file, const attr_list_t *attrs, int poi fprintf(file, " */\n"); } - print_file(file, 2, "NdrFcShort(0x%x), /* %d */\n", offset, offset); + print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", reloff, offset); *typeformat_offset += 4; + + return start_offset; } static size_t write_union_tfs(FILE *file, const attr_list_t *attrs, @@ -1320,7 +1374,7 @@ static size_t write_union_tfs(FILE *file, const attr_list_t *attrs, return *typeformat_offset; } -static size_t write_ip_tfs(FILE *file, const func_t *func, const var_t *var, +static size_t write_ip_tfs(FILE *file, const func_t *func, const type_t *type, const var_t *var, unsigned int *typeformat_offset) { size_t i; @@ -1344,7 +1398,7 @@ static size_t write_ip_tfs(FILE *file, const func_t *func, const var_t *var, } else { - const type_t *base = is_ptr(var->type) ? var->type->ref : var->type; + const type_t *base = is_ptr(type) ? type->ref : type; const UUID *uuid = get_attrp(base->attrs, ATTR_UUID); if (! uuid) @@ -1380,129 +1434,96 @@ static int get_ptr_attr(const type_t *t, int def_type) } static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func, - const var_t *var, unsigned int *typeformat_offset) + type_t *type, const var_t *var, + unsigned int *typeformat_offset) { - const type_t *type = var->type; - int var_ptrs = var->ptr_level, type_ptrs = 0; - int is_str = is_attr(var->attrs, ATTR_STRING); + int pointer_type; + size_t offset; - chat("write_typeformatstring_var: %s\n", var->name); - - while (TRUE) + if (type == var->type) /* top-level pointers */ { - is_str = is_str || is_attr(type->attrs, ATTR_STRING); - if (type->kind == TKIND_ALIAS) - type = type->orig; - else if (is_ptr(type)) + int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE); + if (pointer_attr != 0 && !is_ptr(type)) + error("'%s': pointer attribute applied to non-pointer type\n", var->name); + + if (pointer_attr == 0) + pointer_attr = get_ptr_attr(type, RPC_FC_RP); + + pointer_type = pointer_attr; + } + else + pointer_type = get_ptr_attr(type, RPC_FC_UP); + + if (((last_ptr(type) && var->array == NULL) + || (!is_ptr(type) && var->array != NULL)) + && is_ptrchain_attr(var, ATTR_STRING)) + { + return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset); + } + + if (is_array_type(var->attrs, type, var->array)) + return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset); + + if (!is_ptr(type)) + { + /* basic types don't need a type format string */ + if (is_base_type(type->type)) + return 0; + + switch (type->type) { - ++type_ptrs; - type = type->ref; + case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: + case RPC_FC_CSTRUCT: + case RPC_FC_CPSTRUCT: + case RPC_FC_CVSTRUCT: + case RPC_FC_BOGUS_STRUCT: + return write_struct_tfs(file, type, var->name, typeformat_offset); + case RPC_FC_ENCAPSULATED_UNION: + case RPC_FC_NON_ENCAPSULATED_UNION: + return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset); + case RPC_FC_IGNORE: + case RPC_FC_BIND_PRIMITIVE: + /* nothing to do */ + return 0; + default: + error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name); } - else + } + else if (last_ptr(type)) + { + size_t start_offset = *typeformat_offset; + int in_attr = is_attr(var->attrs, ATTR_IN); + int out_attr = is_attr(var->attrs, ATTR_OUT); + const type_t *base = type->ref; + + if (base->type == RPC_FC_IP) { - type = var->type; - break; + return write_ip_tfs(file, func, type, var, typeformat_offset); + } + + /* special case for pointers to base types */ + if (is_base_type(base->type)) + { + print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n", + pointer_type, (!in_attr && out_attr) ? 0x0C : 0x08, + string_of_type(pointer_type), + (!in_attr && out_attr) ? "[allocated_on_stack] " : ""); + print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type)); + print_file(file, indent, "0x5c, /* FC_PAD */\n"); + *typeformat_offset += 4; + return start_offset; } } - while (TRUE) - { - int ptr_level = var_ptrs + type_ptrs; - int pointer_type = 0; + assert(is_ptr(type)); - chat("write_typeformatstring: type->type = 0x%x, type->name = %s, ptr_level = %d\n", type->type, type->name, ptr_level); - - /* var attrs only effect the rightmost pointer */ - if ((0 < var->ptr_level && var_ptrs == var->ptr_level) - || (var->ptr_level == 0 && type == var->type)) - { - int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE); - if (pointer_attr) - { - if (! ptr_level) - error("'%s': pointer attribute applied to non-pointer type\n", var->name); - pointer_type = pointer_attr; - } - else - pointer_type = RPC_FC_RP; - } - else /* pointers below other pointers default to unique */ - pointer_type = var_ptrs ? RPC_FC_UP : get_ptr_attr(type, RPC_FC_UP); - - if (is_str && ptr_level + (var->array != NULL) == 1) - return write_string_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset); - - if (is_array_type(var->attrs, ptr_level, var->array)) - return write_array_tfs(file, var->attrs, type, var->array, var->name, typeformat_offset); - - if (ptr_level == 0) - { - /* basic types don't need a type format string */ - if (is_base_type(type->type)) - return 0; - - switch (type->type) - { - case RPC_FC_STRUCT: - case RPC_FC_PSTRUCT: - case RPC_FC_CSTRUCT: - case RPC_FC_CPSTRUCT: - case RPC_FC_CVSTRUCT: - case RPC_FC_BOGUS_STRUCT: - return write_struct_tfs(file, type, var->name, typeformat_offset); - case RPC_FC_ENCAPSULATED_UNION: - case RPC_FC_NON_ENCAPSULATED_UNION: - return write_union_tfs(file, var->attrs, type, var->name, typeformat_offset); - case RPC_FC_IGNORE: - case RPC_FC_BIND_PRIMITIVE: - /* nothing to do */ - return 0; - default: - error("write_typeformatstring_var: Unsupported type 0x%x for variable %s\n", type->type, var->name); - } - } - else if (ptr_level == 1) - { - size_t start_offset = *typeformat_offset; - int in_attr = is_attr(var->attrs, ATTR_IN); - int out_attr = is_attr(var->attrs, ATTR_OUT); - const type_t *base = is_ptr(type) ? type->ref : type; - - if (base->type == RPC_FC_IP) - { - return write_ip_tfs(file, func, var, typeformat_offset); - } - - /* special case for pointers to base types */ - if (is_base_type(base->type)) - { - print_file(file, indent, "0x%x, 0x%x, /* %s %s[simple_pointer] */\n", - pointer_type, (!in_attr && out_attr) ? 0x0C : 0x08, - string_of_type(pointer_type), - (!in_attr && out_attr) ? "[allocated_on_stack] " : ""); - print_file(file, indent, "0x%02x, /* %s */\n", base->type, string_of_type(base->type)); - print_file(file, indent, "0x5c, /* FC_PAD */\n"); - *typeformat_offset += 4; - return start_offset; - } - } - - assert(ptr_level > 0); - - if (file) - fprintf(file, "/* %2u */\n", *typeformat_offset); - write_pointer_only_tfs(file, var->attrs, pointer_type, - 1 < ptr_level ? 0x10 : 0, - 2, typeformat_offset); - - if (var_ptrs) - --var_ptrs; - else - { - --type_ptrs; - type = type->ref; - } - } + offset = write_typeformatstring_var(file, indent, func, type->ref, var, typeformat_offset); + if (file) + fprintf(file, "/* %2u */\n", *typeformat_offset); + return write_pointer_only_tfs(file, var->attrs, pointer_type, + !last_ptr(type) ? 0x10 : 0, + offset, typeformat_offset); } @@ -1536,7 +1557,7 @@ void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_obje current_func = func; if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) - write_typeformatstring_var(file, indent, func, var, + write_typeformatstring_var(file, indent, func, var->type, var, &typeformat_offset); } } @@ -1551,13 +1572,13 @@ void write_typeformatstring(FILE *file, const ifref_list_t *ifaces, int for_obje } static unsigned int get_required_buffer_size_type( - const type_t *type, int ptr_level, const array_dims_t *array, + const type_t *type, const array_dims_t *array, const char *name, unsigned int *alignment) { size_t size = 0; *alignment = 0; - if (ptr_level == 0) + if (!is_ptr(type)) { switch (type->type) { @@ -1595,6 +1616,7 @@ static unsigned int get_required_buffer_size_type( return 0; case RPC_FC_STRUCT: + case RPC_FC_PSTRUCT: { const var_t *field; if (!type->fields) return 0; @@ -1602,7 +1624,7 @@ static unsigned int get_required_buffer_size_type( { unsigned int alignment; size += get_required_buffer_size_type( - field->type, field->ptr_level, field->array, field->name, + field->type, field->array, field->name, &alignment); } break; @@ -1610,7 +1632,7 @@ static unsigned int get_required_buffer_size_type( case RPC_FC_RP: if (is_base_type( type->ref->type ) || type->ref->type == RPC_FC_STRUCT) - size = get_required_buffer_size_type( type->ref, 0, NULL, name, alignment ); + size = get_required_buffer_size_type( type->ref, NULL, name, alignment ); break; default: @@ -1636,7 +1658,7 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali if (pass == PASS_OUT) { - if (out_attr && var->ptr_level > 0) + if (out_attr && is_ptr(var->type)) { type_t *type = var->type; @@ -1650,7 +1672,7 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali { unsigned int align; size += get_required_buffer_size_type( - field->type, field->ptr_level, field->array, field->name, + field->type, field->array, field->name, &align); } return size; @@ -1662,7 +1684,7 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali { if ((!out_attr || in_attr) && !has_size && !is_attr(var->attrs, ATTR_STRING) && !var->array) { - if (var->ptr_level > 0) + if (is_ptr(var->type)) { type_t *type = var->type; @@ -1680,7 +1702,7 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali { unsigned int align; size += get_required_buffer_size_type( - field->type, field->ptr_level, field->array, field->name, + field->type, field->array, field->name, &align); } return size; @@ -1688,7 +1710,7 @@ static unsigned int get_required_buffer_size(const var_t *var, unsigned int *ali } } - return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment); + return get_required_buffer_size_type(var->type, var->array, var->name, alignment); } } @@ -1706,7 +1728,7 @@ static unsigned int get_function_buffer_size( const func_t *func, enum pass pass } } - if (pass == PASS_OUT && !is_void(func->def->type, NULL)) + if (pass == PASS_OUT && !is_void(func->def->type)) { total_size += get_required_buffer_size(func->def, &alignment, PASS_RETURN); total_size += alignment; @@ -1755,7 +1777,7 @@ void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, enum pass pass, const var_t *var, const char *varname) { - const type_t *type = var->type; + type_t *type = var->type; unsigned int size; unsigned int alignment = 0; unsigned char rtype; @@ -1764,7 +1786,7 @@ void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL) return; - rtype = type->type; + rtype = is_ptr(type) ? type->ref->type : type->type; switch (rtype) { @@ -1813,8 +1835,8 @@ void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, if (phase == PHASE_MARSHAL) { print_file(file, indent, "*("); - write_type(file, var->type, NULL); - if (var->ptr_level) + write_type(file, is_ptr(type) ? type->ref : type); + if (is_ptr(type)) fprintf(file, " *)_StubMsg.Buffer = *"); else fprintf(file, " *)_StubMsg.Buffer = "); @@ -1828,16 +1850,16 @@ void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, else print_file(file, indent, "*"); fprintf(file, varname); - if (pass == PASS_IN && var->ptr_level) + if (pass == PASS_IN && is_ptr(type)) fprintf(file, " = ("); else fprintf(file, " = *("); - write_type(file, var->type, NULL); + write_type(file, is_ptr(type) ? type->ref : type); fprintf(file, " *)_StubMsg.Buffer;\n"); } print_file(file, indent, "_StubMsg.Buffer += sizeof("); - write_type(file, var->type, NULL); + write_type(file, var->type); fprintf(file, ");\n"); } @@ -1870,6 +1892,9 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, { const type_t *type = var->type; unsigned char rtype; + size_t start_offset; + size_t size_type = get_size_typeformatstring_var(var, &start_offset); + start_offset += *type_offset; length_is = get_attrp(var->attrs, ATTR_LENGTHIS); size_is = get_attrp(var->attrs, ATTR_SIZEIS); @@ -1901,12 +1926,12 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, if (is_user_derived( var )) { - print_phase_function(file, indent, "UserMarshal", phase, var->name, *type_offset); + print_phase_function(file, indent, "UserMarshal", phase, var->name, start_offset); } - else if (is_string_type(var->attrs, var->ptr_level, var->array)) + else if (is_string_type(var->attrs, var->type, var->array)) { if (var->array && !is_conformant_array(var->array)) - print_phase_function(file, indent, "NonConformantString", phase, var->name, *type_offset); + print_phase_function(file, indent, "NonConformantString", phase, var->name, start_offset); else { if (size_is && is_size_needed_for_phase(phase)) @@ -1918,13 +1943,13 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, } if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP)) - print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset); + print_phase_function(file, indent, "Pointer", phase, var->name, start_offset); else print_phase_function(file, indent, "ConformantString", phase, var->name, - *type_offset + (has_size ? 4 : 2)); + start_offset + (has_size ? 4 : 2)); } } - else if (is_array_type(var->attrs, var->ptr_level, var->array)) + else if (is_array_type(var->attrs, var->type, var->array)) { const char *array_type; @@ -1986,31 +2011,32 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, else if (phase != PHASE_FREE) { if (pointer_type == RPC_FC_UP) - print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset); + print_phase_function(file, indent, "Pointer", phase, var->name, start_offset); else - print_phase_function(file, indent, array_type, phase, var->name, *type_offset + 4); + print_phase_function(file, indent, array_type, phase, var->name, start_offset); } } - else if (var->ptr_level == 0 && is_base_type(rtype)) + else if (!is_ptr(var->type) && is_base_type(rtype)) { print_phase_basetype(file, indent, phase, pass, var, var->name); } - else if (var->ptr_level == 0) + else if (!is_ptr(var->type)) { switch (rtype) { case RPC_FC_STRUCT: - print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset); + case RPC_FC_PSTRUCT: + print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset); break; case RPC_FC_CSTRUCT: case RPC_FC_CPSTRUCT: - print_phase_function(file, indent, "ConformantStruct", phase, var->name, *type_offset); + print_phase_function(file, indent, "ConformantStruct", phase, var->name, start_offset); break; case RPC_FC_CVSTRUCT: - print_phase_function(file, indent, "ConformantVaryingStruct", phase, var->name, *type_offset); + print_phase_function(file, indent, "ConformantVaryingStruct", phase, var->name, start_offset); break; case RPC_FC_BOGUS_STRUCT: - print_phase_function(file, indent, "ComplexStruct", phase, var->name, *type_offset); + print_phase_function(file, indent, "ComplexStruct", phase, var->name, start_offset); break; case RPC_FC_RP: if (is_base_type( var->type->ref->type )) @@ -2020,43 +2046,42 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func, else if (var->type->ref->type == RPC_FC_STRUCT) { if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE) - print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset + 4); + print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset + 4); } else { const var_t *iid; if ((iid = get_attrp( var->attrs, ATTR_IIDIS ))) print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name ); - print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset); + print_phase_function(file, indent, "Pointer", phase, var->name, start_offset); } break; default: - error("write_remoting_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n", - var->name, rtype, var->ptr_level); + error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, rtype); } } else { - if ((var->ptr_level == 1) && (pointer_type == RPC_FC_RP) && is_base_type(rtype)) + if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && is_base_type(rtype)) { print_phase_basetype(file, indent, phase, pass, var, var->name); } - else if ((var->ptr_level == 1) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT)) + else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT)) { if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE) - print_phase_function(file, indent, "SimpleStruct", phase, var->name, *type_offset + 4); + print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset + 4); } else { const var_t *iid; if ((iid = get_attrp( var->attrs, ATTR_IIDIS ))) print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name ); - print_phase_function(file, indent, "Pointer", phase, var->name, *type_offset); + print_phase_function(file, indent, "Pointer", phase, var->name, start_offset); } } fprintf(file, "\n"); next: - *type_offset += get_size_typeformatstring_var(var); + *type_offset += size_type; } } @@ -2079,7 +2104,7 @@ size_t get_size_procformatstring_func(const func_t *func) size += get_size_procformatstring_var(var); /* return value size */ - if (is_void(func->def->type, NULL)) + if (is_void(func->def->type)) size += 2; /* FC_END and FC_PAD */ else size += get_size_procformatstring_var(func->def); @@ -2087,11 +2112,15 @@ size_t get_size_procformatstring_func(const func_t *func) return size; } -size_t get_size_typeformatstring_var(const var_t *var) +size_t get_size_typeformatstring_var(const var_t *var, size_t *pstart_offset) { - unsigned int type_offset = 0; - write_typeformatstring_var(NULL, 0, NULL, var, &type_offset); - return type_offset; + unsigned int type_offset = 2; /* 0 is used as an invalid offset */ + size_t start_offset = write_typeformatstring_var(NULL, 0, NULL, var->type, + var, &type_offset); + if (pstart_offset) + *pstart_offset = start_offset - 2; + + return type_offset - 2; } size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects) @@ -2133,7 +2162,7 @@ size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects) /* argument list size */ if (func->args) LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry ) - size += get_size_typeformatstring_var(var); + size += get_size_typeformatstring_var(var, NULL); } } } @@ -2185,13 +2214,13 @@ static void write_struct_expr(FILE *h, const expr_t *e, int brackets, break; case EXPR_CAST: fprintf(h, "("); - write_type(h, e->u.tref, NULL); + write_type(h, e->u.tref); fprintf(h, ")"); write_struct_expr(h, e->ref, 1, fields, structvar); break; case EXPR_SIZEOF: fprintf(h, "sizeof("); - write_type(h, e->u.tref, NULL); + write_type(h, e->u.tref); fprintf(h, ")"); break; case EXPR_SHL: @@ -2239,10 +2268,10 @@ void declare_stub_args( FILE *file, int indent, const func_t *func ) const var_t *var; /* declare return value '_RetVal' */ - if (!is_void(def->type, NULL)) + if (!is_void(def->type)) { print_file(file, indent, ""); - write_type(file, def->type, def); + write_type(file, def->type); fprintf(file, " _RetVal;\n"); } @@ -2262,16 +2291,13 @@ void declare_stub_args( FILE *file, int indent, const func_t *func ) if (!in_attr && !has_size && !is_string) { - int indirection; print_file(file, indent, ""); - write_type(file, var->type, NULL); - for (indirection = 0; indirection < var->ptr_level - 1; indirection++) - fprintf(file, "*"); + write_type(file, var->type->ref); fprintf(file, " _W%u;\n", i++); } print_file(file, indent, ""); - write_type(file, var->type, var); + write_type(file, var->type); fprintf(file, " "); if (var->array) { fprintf(file, "( *"); @@ -2324,13 +2350,13 @@ void assign_stub_out_args( FILE *file, int indent, const func_t *func ) write_expr( file, expr, 1 ); fprintf(file, " * "); } - size = type_memsize(type, 0, NULL, &align); + size = type_memsize(type, NULL, &align); fprintf(file, "%u);\n", size); } else if (!is_string) { fprintf(file, " = &_W%u;\n", i); - if (var->ptr_level > 1) + if (is_ptr(var->type) && !last_ptr(var->type)) print_file(file, indent, "_W%u = 0;\n", i); i++; } diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h index eda259b11b2..9c9e5c08d63 100644 --- a/tools/widl/typegen.h +++ b/tools/widl/typegen.h @@ -42,7 +42,7 @@ void print_phase_basetype(FILE *file, int indent, enum remoting_phase phase, enu void write_remoting_arguments(FILE *file, int indent, const func_t *func, unsigned int *type_offset, enum pass pass, enum remoting_phase phase); size_t get_size_procformatstring_var(const var_t *var); size_t get_size_procformatstring_func(const func_t *func); -size_t get_size_typeformatstring_var(const var_t *var); +size_t get_size_typeformatstring_var(const var_t *var, size_t *start_offset); size_t get_size_procformatstring(const ifref_list_t *ifaces, int for_objects); size_t get_size_typeformatstring(const ifref_list_t *ifaces, int for_objects); void assign_stub_out_args( FILE *file, int indent, const func_t *func ); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 15c5c1a717a..18a976a8752 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -39,6 +39,7 @@ typedef struct _expr_t expr_t; typedef struct _type_t type_t; typedef struct _typeref_t typeref_t; typedef struct _var_t var_t; +typedef struct _pident_t pident_t; typedef struct _func_t func_t; typedef struct _ifref_t ifref_t; typedef struct _typelib_entry_t typelib_entry_t; @@ -51,6 +52,7 @@ typedef struct list str_list_t; typedef struct list func_list_t; typedef struct list expr_list_t; typedef struct list var_list_t; +typedef struct list pident_list_t; typedef struct list ifref_list_t; typedef struct list array_dims_t; @@ -205,6 +207,7 @@ struct _type_t { var_list_t *fields; /* interfaces, structures and enumerations */ ifref_list_t *ifaces; /* coclasses */ type_t *orig; /* dup'd types */ + unsigned int typestring_offset; int ignore, is_const, sign; int defined, written, user_types_registered; int typelib_idx; @@ -212,7 +215,6 @@ struct _type_t { struct _var_t { char *name; - int ptr_level; array_dims_t *array; type_t *type; var_list_t *args; /* for function pointers */ @@ -223,6 +225,14 @@ struct _var_t { struct list entry; }; +struct _pident_t { + var_t *var; + int ptr_level; + + /* parser-internal */ + struct list entry; +}; + struct _func_t { var_t *def; var_list_t *args; diff --git a/tools/widl/write_msft.c b/tools/widl/write_msft.c index 439d7be4e56..02422e75865 100644 --- a/tools/widl/write_msft.c +++ b/tools/widl/write_msft.c @@ -1049,7 +1049,8 @@ static void dump_type(type_t *t) static int encode_var( msft_typelib_t *typelib, /* [I] The type library in which to encode the TYPEDESC. */ - var_t *var, /* [I] The type description to encode. */ + type_t *type, /* [I] The type description to encode. */ + var_t *var, /* [I] The var to encode. */ int *encoded_type, /* [O] The encoded type description. */ int *width, /* [O] The width of the type, or NULL. */ int *alignment, /* [O] The alignment of the type, or NULL. */ @@ -1061,20 +1062,18 @@ static int encode_var( int child_size; int vt; int scratch; - type_t *type; if (!width) width = &scratch; if (!alignment) alignment = &scratch; if (!decoded_size) decoded_size = &scratch; *decoded_size = 0; - chat("encode_var: var %p var->type %p var->type->name %s var->ptr_level %d var->type->ref %p\n", - var, var->type, var->type->name ? var->type->name : "NULL", var->ptr_level, var->type->ref); - if(var->ptr_level) { - int skip_ptr; - var->ptr_level--; - skip_ptr = encode_var(typelib, var, &target_type, NULL, NULL, &child_size); - var->ptr_level++; + chat("encode_var: var %p type %p type->name %s type->ref %p\n", + var, type, type->name ? type->name : "NULL", type->ref); + + vt = get_type_vt(type); + if (vt == VT_PTR) { + int skip_ptr = encode_var(typelib, type->ref, var, &target_type, NULL, NULL, &child_size); if(skip_ptr == 2) { chat("encode_var: skipping ptr\n"); @@ -1124,7 +1123,7 @@ static int encode_var( chat("array with %d dimensions\n", num_dims); array_save = var->array; var->array = NULL; - encode_var(typelib, var, &target_type, width, alignment, NULL); + encode_var(typelib, type, var, &target_type, width, alignment, NULL); var->array = array_save; arrayoffset = ctl2_alloc_segment(typelib, MSFT_SEG_ARRAYDESC, (2 + 2 * num_dims) * sizeof(long), 0); arraydata = (void *)&typelib->typelib_segment_data[MSFT_SEG_ARRAYDESC][arrayoffset]; @@ -1153,10 +1152,8 @@ static int encode_var( *decoded_size = 20 /*sizeof(ARRAYDESC)*/ + (num_dims - 1) * 8 /*sizeof(SAFEARRAYBOUND)*/; return 0; } - dump_type(var->type); + dump_type(type); - vt = get_type_vt(var->type); - type = var->type; encode_type(typelib, vt, type, encoded_type, width, alignment, decoded_size); if(type->type == RPC_FC_IP) return 2; return 0; @@ -1177,6 +1174,7 @@ static void write_value(msft_typelib_t* typelib, int *out, int vt, void *value) case VT_INT: case VT_UINT: case VT_HRESULT: + case VT_PTR: { unsigned long *lv = value; if((*lv & 0x3ffffff) == *lv) { @@ -1389,7 +1387,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int /* fill out the basic type information */ typedata[0] = typedata_size | (index << 16); - encode_var(typeinfo->typelib, func->def, &typedata[1], NULL, NULL, &decoded_size); + encode_var(typeinfo->typelib, func->def->type, func->def, &typedata[1], NULL, NULL, &decoded_size); typedata[2] = funcflags; typedata[3] = ((52 /*sizeof(FUNCDESC)*/ + decoded_size) << 16) | typeinfo->typeinfo->cbSizeVft; typedata[4] = (next_idx << 16) | (callconv << 8) | (invokekind << 3) | funckind; @@ -1427,7 +1425,7 @@ static HRESULT add_func_desc(msft_typeinfo_t* typeinfo, const func_t *func, int if(defaultdata) *defaultdata = -1; - encode_var(typeinfo->typelib, arg, paramdata, NULL, NULL, &decoded_size); + encode_var(typeinfo->typelib, arg->type, arg, paramdata, NULL, NULL, &decoded_size); if (arg->attrs) LIST_FOR_EACH_ENTRY( attr, arg->attrs, const attr_t, entry ) { switch(attr->type) { case ATTR_DEFAULTVALUE_EXPR: @@ -1629,7 +1627,7 @@ static HRESULT add_var_desc(msft_typeinfo_t *typeinfo, UINT index, var_t* var) typeinfo->var_offsets[var_num] = offset; /* figure out type widths and whatnot */ - encode_var(typeinfo->typelib, var, &typedata[1], &var_datawidth, + encode_var(typeinfo->typelib, var->type, var, &typedata[1], &var_datawidth, &var_alignment, &var_type_size); /* pad out starting position to data width */