From d64e4c26eee73ebb1c73241bad89cae05c384642 Mon Sep 17 00:00:00 2001 From: Rob Shearman Date: Wed, 30 Apr 2008 15:23:13 +0100 Subject: [PATCH] widl: Prepare for supporting storage classes in declaration statements. Return a decl_spec_t structure from decl_spec rules so that the storage class and type qualifiers can both be returned. --- tools/widl/parser.y | 101 +++++++++++++++++++++++++++++++---------- tools/widl/widltypes.h | 9 ++++ 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/tools/widl/parser.y b/tools/widl/parser.y index 6d5f497c39d..42ce54d13b0 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -84,6 +84,13 @@ struct _import_t int import_performed; }; +typedef struct _decl_spec_t +{ + type_t *type; + attr_list_t *attrs; + enum storage_class stgclass; +} decl_spec_t; + typelist_t incomplete_types = LIST_INIT(incomplete_types); static void add_incomplete(type_t *t); @@ -92,14 +99,14 @@ static void fix_incomplete(void); static str_list_t *append_str(str_list_t *list, char *str); static attr_list_t *append_attr(attr_list_t *list, attr_t *attr); static attr_list_t *append_attr_list(attr_list_t *new_list, attr_list_t *old_list); -static type_t *apply_decl_spec(type_t *type, attr_list_t *list1, attr_list_t *list2); +static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass); static attr_t *make_attr(enum attr_type type); static attr_t *make_attrv(enum attr_type type, unsigned long val); static attr_t *make_attrp(enum attr_type type, void *val); 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, const declarator_t *decl, int top); -static var_list_t *set_var_types(attr_list_t *attrs, type_t *type, declarator_list_t *decls); +static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl, int top); +static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls); 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); @@ -119,7 +126,7 @@ static type_t *make_pointer_type(type_t *ref, attr_list_t *attrs); static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type); static type_t *reg_type(type_t *type, const char *name, int t); -static type_t *reg_typedefs(type_t *type, var_list_t *names, attr_list_t *attrs); +static type_t *reg_typedefs(decl_spec_t *decl_spec, var_list_t *names, attr_list_t *attrs); static type_t *find_type2(char *name, int t); static type_t *get_type(unsigned char type, char *name, int t); static type_t *get_typev(unsigned char type, var_t *name, int t); @@ -191,6 +198,8 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s interface_info_t ifinfo; typelib_t *typelib; struct _import_t *import; + struct _decl_spec_t *declspec; + enum storage_class stgclass; } %token aIDENTIFIER @@ -286,17 +295,18 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s %token tWCHAR tWIREMARSHAL %type attribute type_qualifier function_specifier -%type m_attributes attributes attrib_list m_type_qual_list decl_spec_no_type m_decl_spec_no_type +%type m_attributes attributes attrib_list m_type_qual_list %type str_list %type m_expr expr expr_const expr_int_const array %type m_exprs /* exprs expr_list */ expr_list_int_const %type interfacehdr +%type decl_spec decl_spec_no_type m_decl_spec_no_type %type inherit interface interfacedef interfacedec %type dispinterface dispinterfacehdr dispinterfacedef %type module modulehdr moduledef %type base_type int_std %type enumdef structdef uniondef -%type type decl_spec +%type type %type coclass_int %type coclass_ints %type arg ne_union_field union_field s_field case enum constdef externdef @@ -466,10 +476,14 @@ args: arg { check_arg($1); $$ = append_var( NULL, $1 ); } /* split into two rules to get bison to resolve a tVOID conflict */ arg: attributes decl_spec declarator { $$ = $3->var; $$->attrs = $1; + if ($2->stgclass != STG_NONE && $2->stgclass != STG_REGISTER) + error_loc("invalid storage class for function parameter\n"); set_type($$, $2, $3, TRUE); free($3); } | decl_spec declarator { $$ = $2->var; + if ($1->stgclass != STG_NONE && $1->stgclass != STG_REGISTER) + error_loc("invalid storage class for function parameter\n"); set_type($$, $1, $2, TRUE); free($2); } @@ -982,9 +996,9 @@ m_type_qual_list: { $$ = NULL; } | m_type_qual_list type_qualifier { $$ = append_attr($1, $2); } ; -decl_spec: type m_decl_spec_no_type { $$ = apply_decl_spec($1, $2, NULL); } +decl_spec: type m_decl_spec_no_type { $$ = make_decl_spec($1, $2, NULL, NULL, STG_NONE); } | decl_spec_no_type type m_decl_spec_no_type - { $$ = apply_decl_spec($2, $1, $3); } + { $$ = make_decl_spec($2, $1, $3, NULL, STG_NONE); } ; m_decl_spec_no_type: { $$ = NULL; } @@ -992,8 +1006,8 @@ m_decl_spec_no_type: { $$ = NULL; } ; decl_spec_no_type: - type_qualifier m_decl_spec_no_type { $$ = append_attr($2, $1); } - | function_specifier m_decl_spec_no_type { $$ = append_attr($2, $1); } + type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } + | function_specifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } ; declarator: @@ -1210,18 +1224,55 @@ static attr_list_t *dupattrs(const attr_list_t *list) return new_list; } -static type_t *apply_decl_spec(type_t *type, attr_list_t *list1, attr_list_t *list2) +static decl_spec_t *make_decl_spec(type_t *type, decl_spec_t *left, decl_spec_t *right, attr_t *attr, enum storage_class stgclass) { - if (list1 || list2) + decl_spec_t *declspec = left ? left : right; + if (!declspec) + { + declspec = xmalloc(sizeof(*declspec)); + declspec->type = NULL; + declspec->attrs = NULL; + declspec->stgclass = STG_NONE; + } + declspec->type = type; + if (left && declspec != left) + { + declspec->attrs = append_attr_list(declspec->attrs, left->attrs); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = left->stgclass; + else if (left->stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); + assert(!left->type); + free(left); + } + if (right && declspec != right) + { + declspec->attrs = append_attr_list(declspec->attrs, right->attrs); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = right->stgclass; + else if (right->stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); + assert(!right->type); + free(right); + } + + declspec->attrs = append_attr(declspec->attrs, attr); + if (declspec->stgclass == STG_NONE) + declspec->stgclass = stgclass; + else if (stgclass != STG_NONE) + error_loc("only one storage class can be specified\n"); + + /* apply attributes to type */ + if (type && declspec->attrs) { attr_list_t *attrs; - type = duptype(type, 1); + declspec->type = duptype(type, 1); attrs = dupattrs(type->attrs); - attrs = append_attr_list(attrs, list1); - attrs = append_attr_list(attrs, list2); - type->attrs = attrs; + declspec->type->attrs = append_attr_list(attrs, declspec->attrs); + declspec->attrs = NULL; } - return type; + + return declspec; } static attr_t *make_attr(enum attr_type type) @@ -1347,7 +1398,7 @@ static type_t *append_ptrchain_type(type_t *ptrchain, type_t *type) return ptrchain; } -static void set_type(var_t *v, type_t *type, const declarator_t *decl, +static void set_type(var_t *v, decl_spec_t *decl_spec, const declarator_t *decl, int top) { expr_list_t *sizes = get_attrp(v->attrs, ATTR_SIZEIS); @@ -1358,6 +1409,7 @@ static void set_type(var_t *v, type_t *type, const declarator_t *decl, type_t *atype, **ptype; array_dims_t *arr = decl ? decl->array : NULL; type_t *func_type = decl ? decl->func_type : NULL; + type_t *type = decl_spec->type; if (is_attr(type->attrs, ATTR_INLINE)) { @@ -1375,6 +1427,7 @@ static void set_type(var_t *v, type_t *type, const declarator_t *decl, /* add type onto the end of the pointers in pident->type */ v->type = append_ptrchain_type(decl ? decl->type : NULL, type); + v->stgclass = decl_spec->stgclass; /* the highest level of pointer specified should default to the var's ptr attr * or (RPC_FC_RP if not specified and it's a top level ptr), not @@ -1551,7 +1604,7 @@ static void set_type(var_t *v, type_t *type, const declarator_t *decl, } } -static var_list_t *set_var_types(attr_list_t *attrs, type_t *type, declarator_list_t *decls) +static var_list_t *set_var_types(attr_list_t *attrs, decl_spec_t *decl_spec, declarator_list_t *decls) { declarator_t *decl, *next; var_list_t *var_list = NULL; @@ -1561,7 +1614,7 @@ static var_list_t *set_var_types(attr_list_t *attrs, type_t *type, declarator_li var_t *var = decl->var; var->attrs = attrs; - set_type(var, type, decl, 0); + set_type(var, decl_spec, decl, 0); var_list = append_var(var_list, var); free(decl); } @@ -1619,6 +1672,7 @@ static var_t *make_var(char *name) v->type = NULL; v->attrs = NULL; v->eval = NULL; + v->stgclass = STG_NONE; v->loc_info.input_name = input_name ? input_name : "stdin"; v->loc_info.line_number = line_number; v->loc_info.near_text = parser_text; @@ -1769,14 +1823,15 @@ static void fix_incomplete(void) } } -static type_t *reg_typedefs(type_t *type, declarator_list_t *decls, attr_list_t *attrs) +static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, attr_list_t *attrs) { const declarator_t *decl; int is_str = is_attr(attrs, ATTR_STRING); + type_t *type = decl_spec->type; if (is_str) { - type_t *t = type; + type_t *t = decl_spec->type; unsigned char c; while (is_ptr(t)) @@ -1813,7 +1868,7 @@ static type_t *reg_typedefs(type_t *type, declarator_list_t *decls, attr_list_t /* set the attributes to allow set_type to do some checks on them */ name->attrs = attrs; - set_type(name, type, decl, 0); + set_type(name, decl_spec, decl, 0); cur = alias(name->type, name->name); cur->attrs = attrs; diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index e96040753b3..111ea63037a 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -198,6 +198,14 @@ enum type_kind TKIND_MAX }; +enum storage_class +{ + STG_NONE, + STG_STATIC, + STG_EXTERN, + STG_REGISTER, +}; + enum statement_type { STMT_LIBRARY, @@ -282,6 +290,7 @@ struct _var_t { type_t *type; attr_list_t *attrs; expr_t *eval; + enum storage_class stgclass; struct _loc_info_t loc_info;