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.
This commit is contained in:
Rob Shearman 2008-04-30 15:23:13 +01:00 committed by Alexandre Julliard
parent a2073f2979
commit d64e4c26ee
2 changed files with 87 additions and 23 deletions

View File

@ -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 <str> aIDENTIFIER
@ -286,17 +295,18 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%token tWCHAR tWIREMARSHAL
%type <attr> attribute type_qualifier function_specifier
%type <attr_list> m_attributes attributes attrib_list m_type_qual_list decl_spec_no_type m_decl_spec_no_type
%type <attr_list> m_attributes attributes attrib_list m_type_qual_list
%type <str_list> str_list
%type <expr> m_expr expr expr_const expr_int_const array
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <ifinfo> interfacehdr
%type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
%type <type> inherit interface interfacedef interfacedec
%type <type> dispinterface dispinterfacehdr dispinterfacedef
%type <type> module modulehdr moduledef
%type <type> base_type int_std
%type <type> enumdef structdef uniondef
%type <type> type decl_spec
%type <type> type
%type <ifref> coclass_int
%type <ifref_list> coclass_ints
%type <var> 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;

View File

@ -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;