diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 59bc6e109b4..8799e89b762 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -65,6 +65,8 @@ # endif #endif +unsigned char pointer_default = RPC_FC_UP; + typedef struct list typelist_t; struct typenode { type_t *type; @@ -92,7 +94,7 @@ 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, int ptr_level, array_dims_t *arr); +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, int top); 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); @@ -380,21 +382,21 @@ 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->var; $$->attrs = $1; - set_type($$, $2, $3->ptr_level, $4); + set_type($$, $2, $3->ptr_level, $4, TRUE); free($3); } | type pident array { $$ = $2->var; - set_type($$, $1, $2->ptr_level, $3); + set_type($$, $1, $2->ptr_level, $3, TRUE); free($2); } | attributes type pident '(' m_args ')' { $$ = $3->var; $$->attrs = $1; - set_type($$, $2, $3->ptr_level - 1, NULL); + set_type($$, $2, $3->ptr_level - 1, NULL, TRUE); free($3); $$->args = $5; } | type pident '(' m_args ')' { $$ = $2->var; - set_type($$, $1, $2->ptr_level - 1, NULL); + set_type($$, $1, $2->ptr_level - 1, NULL, TRUE); free($2); $$->args = $4; } @@ -523,7 +525,7 @@ case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, append_expr( ; constdef: tCONST type ident '=' expr_const { $$ = reg_const($3); - set_type($$, $2, 0, NULL); + set_type($$, $2, 0, NULL, FALSE); $$->eval = $5; } ; @@ -616,7 +618,7 @@ expr_const: expr { $$ = $1; ; externdef: tEXTERN tCONST type ident { $$ = $4; - set_type($$, $3, 0, NULL); + set_type($$, $3, 0, NULL, FALSE); } ; @@ -632,7 +634,7 @@ field: s_field ';' { $$ = $1; } s_field: m_attributes type pident array { $$ = $3->var; $$->attrs = $1; - set_type($$, $2, $3->ptr_level, $4); + set_type($$, $2, $3->ptr_level, $4, FALSE); free($3); } ; @@ -641,7 +643,7 @@ funcdef: m_attributes type callconv pident '(' m_args ')' { var_t *v = $4->var; v->attrs = $1; - set_type(v, $2, $4->ptr_level, NULL); + set_type(v, $2, $4->ptr_level, NULL, FALSE); free($4); $$ = make_func(v, $6); if (is_attr(v->attrs, ATTR_IN)) { @@ -1262,20 +1264,25 @@ static type_t *make_type(unsigned char type, type_t *ref) return t; } -static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr) +static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, + int top) { expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS); expr_list_t *lengs = get_attrp(v->attrs, ATTR_LENGTHIS); - int ptr_type = get_attrv(v->attrs, ATTR_POINTERTYPE); + int ptr_attr = get_attrv(v->attrs, ATTR_POINTERTYPE); + int ptr_type = ptr_attr; int sizeless, has_varconf; expr_t *dim; type_t *atype, **ptype; v->type = type; + if (!ptr_type && top) + ptr_type = RPC_FC_RP; + for ( ; 0 < ptr_level; --ptr_level) { - v->type = make_type(RPC_FC_RP, v->type); + v->type = make_type(pointer_default, v->type); if (ptr_level == 1 && ptr_type && !arr) { v->type->type = ptr_type; @@ -1287,10 +1294,13 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr) { if (is_ptr(v->type)) { - v->type = duptype(v->type, 1); - v->type->type = ptr_type; + if (v->type->type != ptr_type) + { + v->type = duptype(v->type, 1); + v->type->type = ptr_type; + } } - else if (!arr) + else if (!arr && ptr_attr) error("%s: pointer attribute applied to non-pointer type\n", v->name); } @@ -1504,7 +1514,7 @@ static type_t *make_safearray(type_t *type) { type_t *sa = duptype(find_type("SAFEARRAY", 0), 1); sa->ref = type; - return make_type(RPC_FC_FP, sa); + return make_type(pointer_default, sa); } #define HASHMAX 64 @@ -1628,7 +1638,7 @@ static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *a int cptr = pident->ptr_level; if (cptr > ptrc) { while (cptr > ptrc) { - cur = ptr = make_type(RPC_FC_RP, cur); + cur = ptr = make_type(pointer_default, cur); ptrc++; } } else { diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index a91fd132115..ba2c98354f0 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -1994,24 +1994,10 @@ static size_t write_contexthandle_tfs(FILE *file, const type_t *type, return start_offset; } -static int get_ptr_attr(const type_t *t, int def_type) -{ - while (TRUE) - { - int ptr_attr = get_attrv(t->attrs, ATTR_POINTERTYPE); - if (ptr_attr) - return ptr_attr; - if (t->kind != TKIND_ALIAS) - return def_type; - t = t->orig; - } -} - static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *func, type_t *type, const var_t *var, unsigned int *typeformat_offset) { - int pointer_type; size_t offset; if (is_context_handle(type)) @@ -2023,35 +2009,23 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f return type->typestring_offset; } - if (type == var->type) /* top-level pointers */ - { - int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE); - if (pointer_attr != 0 && !is_ptr(type) && !is_array(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) || last_array(type)) && is_ptrchain_attr(var, ATTR_STRING)) return write_string_tfs(file, var->attrs, type, var->name, typeformat_offset); if (is_array(type)) { + int ptr_type; size_t off; off = write_array_tfs(file, var->attrs, type, var->name, typeformat_offset); - if (pointer_type != RPC_FC_RP) + ptr_type = get_attrv(var->attrs, ATTR_POINTERTYPE); + if (ptr_type && ptr_type != RPC_FC_RP) { unsigned int absoff = type->typestring_offset; short reloff = absoff - (*typeformat_offset + 2); off = *typeformat_offset; print_file(file, 0, "/* %d */\n", off); - print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", pointer_type, - string_of_type(pointer_type)); + print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type, + string_of_type(ptr_type)); print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff); *typeformat_offset += 4; @@ -2101,8 +2075,8 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f 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), + type->type, (!in_attr && out_attr) ? 0x0C : 0x08, + string_of_type(type->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"); @@ -2116,7 +2090,7 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f 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, + return write_pointer_only_tfs(file, var->attrs, type->type, !last_ptr(type) ? 0x10 : 0, offset, typeformat_offset); }