Commit 6a0c5a4f authored by Rob Shearman's avatar Rob Shearman Committed by Alexandre Julliard

widl: Store function and function pointer types completely within type_t type.

parent a04b1508
...@@ -227,7 +227,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) ...@@ -227,7 +227,7 @@ void write_type_left(FILE *h, type_t *t, int declonly)
else fprintf(h, "enum {\n"); else fprintf(h, "enum {\n");
t->written = TRUE; t->written = TRUE;
indentation++; indentation++;
write_enums(h, t->fields); write_enums(h, t->fields_or_args);
indent(h, -1); indent(h, -1);
fprintf(h, "}"); fprintf(h, "}");
} }
...@@ -245,7 +245,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) ...@@ -245,7 +245,7 @@ void write_type_left(FILE *h, type_t *t, int declonly)
else fprintf(h, "struct {\n"); else fprintf(h, "struct {\n");
t->written = TRUE; t->written = TRUE;
indentation++; indentation++;
write_fields(h, t->fields); write_fields(h, t->fields_or_args);
indent(h, -1); indent(h, -1);
fprintf(h, "}"); fprintf(h, "}");
} }
...@@ -257,7 +257,7 @@ void write_type_left(FILE *h, type_t *t, int declonly) ...@@ -257,7 +257,7 @@ void write_type_left(FILE *h, type_t *t, int declonly)
else fprintf(h, "union {\n"); else fprintf(h, "union {\n");
t->written = TRUE; t->written = TRUE;
indentation++; indentation++;
write_fields(h, t->fields); write_fields(h, t->fields_or_args);
indent(h, -1); indent(h, -1);
fprintf(h, "}"); fprintf(h, "}");
} }
...@@ -402,7 +402,7 @@ void check_for_additional_prototype_types(const var_list_t *list) ...@@ -402,7 +402,7 @@ void check_for_additional_prototype_types(const var_list_t *list)
} }
else else
{ {
check_for_additional_prototype_types(type->fields); check_for_additional_prototype_types(type->fields_or_args);
} }
} }
} }
...@@ -690,13 +690,13 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i ...@@ -690,13 +690,13 @@ void write_args(FILE *h, const var_list_t *args, const char *name, int method, i
} }
else fprintf(h, ","); else fprintf(h, ",");
} }
if (arg->args) if (arg->type->type == RPC_FC_FUNCTION)
{ {
write_type_decl_left(h, arg->type); write_type_decl_left(h, arg->type->ref);
fprintf(h, " (STDMETHODCALLTYPE *"); fprintf(h, " (STDMETHODCALLTYPE *");
write_name(h,arg); write_name(h,arg);
fprintf(h, ")("); fprintf(h, ")(");
write_args(h, arg->args, NULL, 0, FALSE); write_args(h, arg->type->fields_or_args, NULL, 0, FALSE);
fprintf(h, ")"); fprintf(h, ")");
} }
else else
......
...@@ -92,7 +92,7 @@ static expr_t *make_expr3(enum expr_type type, expr_t *expr1, expr_t *expr2, exp ...@@ -92,7 +92,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 type_t *make_type(unsigned char type, type_t *ref);
static expr_list_t *append_expr(expr_list_t *list, expr_t *expr); 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 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, int top); static void set_type(var_t *v, type_t *type, const pident_t *pident, array_dims_t *arr, int top);
static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface); static ifref_list_t *append_ifref(ifref_list_t *list, ifref_t *iface);
static ifref_t *make_ifref(type_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_list_t *append_var(var_list_t *list, var_t *var);
...@@ -100,7 +100,7 @@ static var_t *make_var(char *name); ...@@ -100,7 +100,7 @@ static var_t *make_var(char *name);
static pident_list_t *append_pident(pident_list_t *list, pident_t *p); static pident_list_t *append_pident(pident_list_t *list, pident_t *p);
static pident_t *make_pident(var_t *var); static pident_t *make_pident(var_t *var);
static func_list_t *append_func(func_list_t *list, func_t *func); static func_list_t *append_func(func_list_t *list, func_t *func);
static func_t *make_func(var_t *def); static func_t *make_func(var_t *def, var_list_t *args);
static type_t *make_class(char *name); static type_t *make_class(char *name);
static type_t *make_safearray(type_t *type); static type_t *make_safearray(type_t *type);
static type_t *make_builtin(char *name); static type_t *make_builtin(char *name);
...@@ -397,11 +397,11 @@ args: arg { check_arg($1); $$ = append_var( NULL, $1 ); } ...@@ -397,11 +397,11 @@ args: arg { check_arg($1); $$ = append_var( NULL, $1 ); }
/* split into two rules to get bison to resolve a tVOID conflict */ /* split into two rules to get bison to resolve a tVOID conflict */
arg: attributes type pident array { $$ = $3->var; arg: attributes type pident array { $$ = $3->var;
$$->attrs = $1; $$->attrs = $1;
set_type($$, $2, $3->ptr_level, $4, TRUE); set_type($$, $2, $3, $4, TRUE);
free($3); free($3);
} }
| type pident array { $$ = $2->var; | type pident array { $$ = $2->var;
set_type($$, $1, $2->ptr_level, $3, TRUE); set_type($$, $1, $2, $3, TRUE);
free($2); free($2);
} }
; ;
...@@ -537,7 +537,7 @@ case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, append_expr( ...@@ -537,7 +537,7 @@ case: tCASE expr ':' field { attr_t *a = make_attrp(ATTR_CASE, append_expr(
; ;
constdef: tCONST type ident '=' expr_const { $$ = reg_const($3); constdef: tCONST type ident '=' expr_const { $$ = reg_const($3);
set_type($$, $2, 0, NULL, FALSE); set_type($$, $2, NULL, NULL, FALSE);
$$->eval = $5; $$->eval = $5;
} }
; ;
...@@ -571,7 +571,7 @@ enum: ident '=' expr_const { $$ = reg_const($1); ...@@ -571,7 +571,7 @@ enum: ident '=' expr_const { $$ = reg_const($1);
enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM); enumdef: tENUM t_ident '{' enums '}' { $$ = get_typev(RPC_FC_ENUM16, $2, tsENUM);
$$->kind = TKIND_ENUM; $$->kind = TKIND_ENUM;
$$->fields = $4; $$->fields_or_args = $4;
$$->defined = TRUE; $$->defined = TRUE;
if(in_typelib) if(in_typelib)
add_typelib_entry($$); add_typelib_entry($$);
...@@ -631,7 +631,7 @@ expr_const: expr { $$ = $1; ...@@ -631,7 +631,7 @@ expr_const: expr { $$ = $1;
; ;
externdef: tEXTERN tCONST type ident { $$ = $4; externdef: tEXTERN tCONST type ident { $$ = $4;
set_type($$, $3, 0, NULL, FALSE); set_type($$, $3, NULL, NULL, FALSE);
} }
; ;
...@@ -647,17 +647,18 @@ field: s_field ';' { $$ = $1; } ...@@ -647,17 +647,18 @@ field: s_field ';' { $$ = $1; }
s_field: m_attributes type pident array { $$ = $3->var; s_field: m_attributes type pident array { $$ = $3->var;
$$->attrs = $1; $$->attrs = $1;
set_type($$, $2, $3->ptr_level, $4, FALSE); set_type($$, $2, $3, $4, FALSE);
free($3); free($3);
} }
; ;
funcdef: funcdef:
m_attributes type callconv pident { var_t *v = $4->var; m_attributes type callconv pident { var_t *v = $4->var;
var_list_t *args = $4->args;
v->attrs = $1; v->attrs = $1;
set_type(v, $2, $4->ptr_level, NULL, FALSE); set_type(v, $2, $4, NULL, FALSE);
free($4); free($4);
$$ = make_func(v); $$ = make_func(v, args);
if (is_attr(v->attrs, ATTR_IN)) { if (is_attr(v->attrs, ATTR_IN)) {
error_loc("inapplicable attribute [in] for function '%s'\n",$$->def->name); error_loc("inapplicable attribute [in] for function '%s'\n",$$->def->name);
} }
...@@ -779,14 +780,14 @@ dispinterfacedef: dispinterfacehdr '{' ...@@ -779,14 +780,14 @@ dispinterfacedef: dispinterfacehdr '{'
dispint_props dispint_props
dispint_meths dispint_meths
'}' { $$ = $1; '}' { $$ = $1;
$$->fields = $3; $$->fields_or_args = $3;
$$->funcs = $4; $$->funcs = $4;
if (!parse_only && do_header) write_dispinterface($$); if (!parse_only && do_header) write_dispinterface($$);
if (!parse_only && do_idfile) write_diid($$); if (!parse_only && do_idfile) write_diid($$);
} }
| dispinterfacehdr | dispinterfacehdr
'{' interface ';' '}' { $$ = $1; '{' interface ';' '}' { $$ = $1;
$$->fields = $3->fields; $$->fields_or_args = $3->fields_or_args;
$$->funcs = $3->funcs; $$->funcs = $3->funcs;
if (!parse_only && do_header) write_dispinterface($$); if (!parse_only && do_header) write_dispinterface($$);
if (!parse_only && do_idfile) write_diid($$); if (!parse_only && do_idfile) write_diid($$);
...@@ -865,7 +866,7 @@ pident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; } ...@@ -865,7 +866,7 @@ pident: '*' pident %prec PPTR { $$ = $2; $$->ptr_level++; }
| direct_ident | direct_ident
; ;
func_ident: direct_ident '(' m_args ')' { $$ = $1; $1->var->args = $3; } func_ident: direct_ident '(' m_args ')' { $$ = $1; $1->args = $3; $1->is_func = TRUE; }
direct_ident: ident { $$ = make_pident($1); } direct_ident: ident { $$ = make_pident($1); }
| '(' pident ')' { $$ = $2; } | '(' pident ')' { $$ = $2; }
...@@ -890,7 +891,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, ts ...@@ -890,7 +891,7 @@ structdef: tSTRUCT t_ident '{' fields '}' { $$ = get_typev(RPC_FC_STRUCT, $2, ts
/* overwrite RPC_FC_STRUCT with a more exact type */ /* overwrite RPC_FC_STRUCT with a more exact type */
$$->type = get_struct_type( $4 ); $$->type = get_struct_type( $4 );
$$->kind = TKIND_RECORD; $$->kind = TKIND_RECORD;
$$->fields = $4; $$->fields_or_args = $4;
$$->defined = TRUE; $$->defined = TRUE;
if(in_typelib) if(in_typelib)
add_typelib_entry($$); add_typelib_entry($$);
...@@ -917,7 +918,7 @@ typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs($3, $4, $2); ...@@ -917,7 +918,7 @@ typedef: tTYPEDEF m_attributes type pident_list { reg_typedefs($3, $4, $2);
uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION); uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATED_UNION, $2, tsUNION);
$$->kind = TKIND_UNION; $$->kind = TKIND_UNION;
$$->fields = $4; $$->fields_or_args = $4;
$$->defined = TRUE; $$->defined = TRUE;
} }
| tUNION t_ident | tUNION t_ident
...@@ -928,10 +929,10 @@ uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATE ...@@ -928,10 +929,10 @@ uniondef: tUNION t_ident '{' fields '}' { $$ = get_typev(RPC_FC_NON_ENCAPSULATE
if (!u) u = make_var( xstrdup("tagged_union") ); if (!u) u = make_var( xstrdup("tagged_union") );
u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL); u->type = make_type(RPC_FC_NON_ENCAPSULATED_UNION, NULL);
u->type->kind = TKIND_UNION; u->type->kind = TKIND_UNION;
u->type->fields = $9; u->type->fields_or_args = $9;
u->type->defined = TRUE; u->type->defined = TRUE;
$$->fields = append_var( $$->fields, $5 ); $$->fields_or_args = append_var( $$->fields_or_args, $5 );
$$->fields = append_var( $$->fields, u ); $$->fields_or_args = append_var( $$->fields_or_args, u );
$$->defined = TRUE; $$->defined = TRUE;
} }
; ;
...@@ -1296,7 +1297,7 @@ static type_t *make_type(unsigned char type, type_t *ref) ...@@ -1296,7 +1297,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
t->attrs = NULL; t->attrs = NULL;
t->orig = NULL; t->orig = NULL;
t->funcs = NULL; t->funcs = NULL;
t->fields = NULL; t->fields_or_args = NULL;
t->ifaces = NULL; t->ifaces = NULL;
t->dim = 0; t->dim = 0;
t->size_is = NULL; t->size_is = NULL;
...@@ -1315,7 +1316,7 @@ static type_t *make_type(unsigned char type, type_t *ref) ...@@ -1315,7 +1316,7 @@ static type_t *make_type(unsigned char type, type_t *ref)
return t; 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, const pident_t *pident, array_dims_t *arr,
int top) int top)
{ {
expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS); expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS);
...@@ -1325,6 +1326,7 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, ...@@ -1325,6 +1326,7 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr,
int sizeless, has_varconf; int sizeless, has_varconf;
expr_t *dim; expr_t *dim;
type_t *atype, **ptype; type_t *atype, **ptype;
int ptr_level = (pident ? pident->ptr_level : 0);
v->type = type; v->type = type;
...@@ -1355,6 +1357,16 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr, ...@@ -1355,6 +1357,16 @@ static void set_type(var_t *v, type_t *type, int ptr_level, array_dims_t *arr,
error("%s: pointer attribute applied to non-pointer type\n", v->name); error("%s: pointer attribute applied to non-pointer type\n", v->name);
} }
if (pident && pident->is_func) {
int func_ptr_level = pident->func_ptr_level;
/* function pointers always have one implicit level of pointer */
if (func_ptr_level == 1) func_ptr_level = 0;
v->type = make_type(RPC_FC_FUNCTION, v->type);
v->type->fields_or_args = pident->args;
for (; func_ptr_level > 0; func_ptr_level--)
v->type = make_type(ptr_type, v->type);
}
sizeless = FALSE; sizeless = FALSE;
if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry) if (arr) LIST_FOR_EACH_ENTRY_REV(dim, arr, expr_t, entry)
{ {
...@@ -1506,7 +1518,6 @@ static var_t *make_var(char *name) ...@@ -1506,7 +1518,6 @@ static var_t *make_var(char *name)
var_t *v = xmalloc(sizeof(var_t)); var_t *v = xmalloc(sizeof(var_t));
v->name = name; v->name = name;
v->type = NULL; v->type = NULL;
v->args = NULL;
v->attrs = NULL; v->attrs = NULL;
v->eval = NULL; v->eval = NULL;
return v; return v;
...@@ -1527,8 +1538,10 @@ static pident_t *make_pident(var_t *var) ...@@ -1527,8 +1538,10 @@ static pident_t *make_pident(var_t *var)
{ {
pident_t *p = xmalloc(sizeof(*p)); pident_t *p = xmalloc(sizeof(*p));
p->var = var; p->var = var;
p->is_func = FALSE;
p->ptr_level = 0; p->ptr_level = 0;
p->func_ptr_level = 0; p->func_ptr_level = 0;
p->args = NULL;
return p; return p;
} }
...@@ -1544,12 +1557,11 @@ static func_list_t *append_func(func_list_t *list, func_t *func) ...@@ -1544,12 +1557,11 @@ static func_list_t *append_func(func_list_t *list, func_t *func)
return list; return list;
} }
static func_t *make_func(var_t *def) static func_t *make_func(var_t *def, var_list_t *args)
{ {
func_t *f = xmalloc(sizeof(func_t)); func_t *f = xmalloc(sizeof(func_t));
f->def = def; f->def = def;
f->args = def->args; f->args = args;
def->args = NULL;
f->ignore = parse_only; f->ignore = parse_only;
f->idx = -1; f->idx = -1;
return f; return f;
...@@ -1630,7 +1642,7 @@ static void fix_type(type_t *t) ...@@ -1630,7 +1642,7 @@ static void fix_type(type_t *t)
if (t->kind == TKIND_ALIAS && is_incomplete(t)) { if (t->kind == TKIND_ALIAS && is_incomplete(t)) {
type_t *ot = t->orig; type_t *ot = t->orig;
fix_type(ot); fix_type(ot);
t->fields = ot->fields; t->fields_or_args = ot->fields_or_args;
t->defined = ot->defined; t->defined = ot->defined;
} }
} }
...@@ -1700,6 +1712,15 @@ static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *a ...@@ -1700,6 +1712,15 @@ static type_t *reg_typedefs(type_t *type, pident_list_t *pidents, attr_list_t *a
cptr++; cptr++;
} }
} }
if (pident->is_func) {
int func_ptr_level = pident->func_ptr_level;
/* function pointers always have one implicit level of pointer */
if (func_ptr_level == 1) func_ptr_level = 0;
cur = make_type(RPC_FC_FUNCTION, cur);
cur->fields_or_args = pident->args;
for (; func_ptr_level > 0; func_ptr_level--)
cur = make_type(pointer_default, cur);
}
cur = alias(cur, name->name); cur = alias(cur, name->name);
cur->attrs = attrs; cur->attrs = attrs;
if (ptr_type) if (ptr_type)
......
...@@ -34,6 +34,8 @@ typedef GUID UUID; ...@@ -34,6 +34,8 @@ typedef GUID UUID;
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
#define RPC_FC_FUNCTION 0xfe
typedef struct _attr_t attr_t; typedef struct _attr_t attr_t;
typedef struct _expr_t expr_t; typedef struct _expr_t expr_t;
typedef struct _type_t type_t; typedef struct _type_t type_t;
...@@ -212,7 +214,7 @@ struct _type_t { ...@@ -212,7 +214,7 @@ struct _type_t {
struct _type_t *ref; struct _type_t *ref;
const attr_list_t *attrs; const attr_list_t *attrs;
func_list_t *funcs; /* interfaces and modules */ func_list_t *funcs; /* interfaces and modules */
var_list_t *fields; /* interfaces, structures and enumerations */ var_list_t *fields_or_args; /* interfaces, structures, enumerations and functions (for args) */
ifref_list_t *ifaces; /* coclasses */ ifref_list_t *ifaces; /* coclasses */
unsigned long dim; /* array dimension */ unsigned long dim; /* array dimension */
expr_t *size_is, *length_is; expr_t *size_is, *length_is;
...@@ -233,7 +235,6 @@ struct _type_t { ...@@ -233,7 +235,6 @@ struct _type_t {
struct _var_t { struct _var_t {
char *name; char *name;
type_t *type; type_t *type;
var_list_t *args; /* for function pointers */
attr_list_t *attrs; attr_list_t *attrs;
expr_t *eval; expr_t *eval;
...@@ -244,8 +245,11 @@ struct _var_t { ...@@ -244,8 +245,11 @@ struct _var_t {
struct _pident_t { struct _pident_t {
var_t *var; var_t *var;
int ptr_level; int ptr_level;
int is_func;
/* levels of indirection for function pointers */ /* levels of indirection for function pointers */
int func_ptr_level; int func_ptr_level;
var_list_t *args;
/* parser-internal */ /* parser-internal */
struct list entry; struct list entry;
...@@ -332,7 +336,7 @@ int is_union(unsigned char tc); ...@@ -332,7 +336,7 @@ int is_union(unsigned char tc);
static inline type_t *get_func_return_type(const func_t *func) static inline type_t *get_func_return_type(const func_t *func)
{ {
return func->def->type; return func->def->type->ref;
} }
#endif #endif
...@@ -1948,8 +1948,8 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte ...@@ -1948,8 +1948,8 @@ static void add_dispinterface_typeinfo(msft_typelib_t *typelib, type_t *dispinte
if (dispinterface->funcs) if (dispinterface->funcs)
LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) idx++; LIST_FOR_EACH_ENTRY( func, dispinterface->funcs, const func_t, entry ) idx++;
if (dispinterface->fields) if (dispinterface->fields_or_args)
LIST_FOR_EACH_ENTRY( var, dispinterface->fields, var_t, entry ) LIST_FOR_EACH_ENTRY( var, dispinterface->fields_or_args, var_t, entry )
add_var_desc(msft_typeinfo, idx++, var); add_var_desc(msft_typeinfo, idx++, var);
if (dispinterface->funcs) if (dispinterface->funcs)
...@@ -2032,8 +2032,8 @@ static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure) ...@@ -2032,8 +2032,8 @@ static void add_structure_typeinfo(msft_typelib_t *typelib, type_t *structure)
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs); msft_typeinfo = create_msft_typeinfo(typelib, TKIND_RECORD, structure->name, structure->attrs);
msft_typeinfo->typeinfo->size = 0; msft_typeinfo->typeinfo->size = 0;
if (structure->fields) if (structure->fields_or_args)
LIST_FOR_EACH_ENTRY( cur, structure->fields, var_t, entry ) LIST_FOR_EACH_ENTRY( cur, structure->fields_or_args, var_t, entry )
add_var_desc(msft_typeinfo, idx++, cur); add_var_desc(msft_typeinfo, idx++, cur);
} }
...@@ -2047,8 +2047,8 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration) ...@@ -2047,8 +2047,8 @@ static void add_enum_typeinfo(msft_typelib_t *typelib, type_t *enumeration)
msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs); msft_typeinfo = create_msft_typeinfo(typelib, TKIND_ENUM, enumeration->name, enumeration->attrs);
msft_typeinfo->typeinfo->size = 0; msft_typeinfo->typeinfo->size = 0;
if (enumeration->fields) if (enumeration->fields_or_args)
LIST_FOR_EACH_ENTRY( cur, enumeration->fields, var_t, entry ) LIST_FOR_EACH_ENTRY( cur, enumeration->fields_or_args, var_t, entry )
add_var_desc(msft_typeinfo, idx++, cur); add_var_desc(msft_typeinfo, idx++, cur);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment