widl: Add the parsing of storage classes into declaration-specifiers.

Support the static and register keywords.

This consolidates externdef and constdef rules into one declaration rule.
This commit is contained in:
Rob Shearman 2008-04-30 15:23:23 +01:00 committed by Alexandre Julliard
parent d64e4c26ee
commit e71219e66e
5 changed files with 115 additions and 48 deletions

View File

@ -477,18 +477,49 @@ void write_typedef(type_t *type)
fprintf(header, ";\n");
}
void write_constdef(const var_t *v)
int is_const_decl(const var_t *var)
{
fprintf(header, "#define %s (", v->name);
write_expr(header, v->eval, 0, 1, NULL, NULL);
fprintf(header, ")\n\n");
const type_t *t;
/* strangely, MIDL accepts a const attribute on any pointer in the
* declaration to mean that data isn't being instantiated. this appears
* to be a bug, but there is no benefit to being incompatible with MIDL,
* so we'll do the same thing */
for (t = var->type; ; )
{
if (is_attr(t->attrs, ATTR_CONST))
return TRUE;
else if (is_ptr(t))
t = t->ref;
else break;
}
return FALSE;
}
void write_externdef(const var_t *v)
void write_declaration(const var_t *v, int is_in_interface)
{
fprintf(header, "extern const ");
write_type_def_or_decl(header, v->type, FALSE, "%s", v->name);
fprintf(header, ";\n\n");
if (is_const_decl(v) && v->eval)
{
fprintf(header, "#define %s (", v->name);
write_expr(header, v->eval, 0, 1, NULL, NULL);
fprintf(header, ")\n\n");
}
else if (v->type->type != RPC_FC_FUNCTION || !is_in_interface)
{
switch (v->stgclass)
{
case STG_NONE:
case STG_REGISTER: /* ignored */
break;
case STG_STATIC:
fprintf(header, "static ");
break;
case STG_EXTERN:
fprintf(header, "extern ");
break;
}
write_type_def_or_decl(header, v->type, FALSE, "%s", v->name);
fprintf(header, ";\n\n");
}
}
void write_library(const typelib_t *typelib)

View File

@ -57,8 +57,7 @@ extern void write_locals(FILE *fp, const type_t *iface, int body);
extern void write_coclass(type_t *cocl);
extern void write_coclass_forward(type_t *cocl);
extern void write_typedef(type_t *type);
extern void write_constdef(const var_t *v);
extern void write_externdef(const var_t *v);
extern void write_declaration(const var_t *v, int is_in_interface);
extern void write_library(const typelib_t *typelib);
extern void write_user_types(void);
extern void write_context_handle_rundowns(void);
@ -70,6 +69,7 @@ extern const var_t* get_context_handle_var(const func_t* func);
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);
extern int is_const_decl(const var_t *var);
static inline int last_ptr(const type_t *type)
{

View File

@ -239,10 +239,12 @@ static const struct keyword keywords[] = {
{"module", tMODULE},
{"pascal", tPASCAL},
{"properties", tPROPERTIES},
{"register", tREGISTER},
{"short", tSHORT},
{"signed", tSIGNED},
{"sizeof", tSIZEOF},
{"small", tSMALL},
{"static", tSTATIC},
{"stdcall", tSTDCALL},
{"struct", tSTRUCT},
{"switch", tSWITCH},

View File

@ -68,6 +68,7 @@
#define YYERROR_VERBOSE
unsigned char pointer_default = RPC_FC_UP;
static int is_in_interface = FALSE;
static int is_object_interface = FALSE;
/* are we inside a library block? */
static int is_inside_library = FALSE;
@ -159,14 +160,14 @@ static void add_explicit_handle_if_necessary(func_t *func);
static statement_t *make_statement(enum statement_type type);
static statement_t *make_statement_type_decl(type_t *type);
static statement_t *make_statement_reference(type_t *type);
static statement_t *make_statement_init_decl(var_t *var);
static statement_t *make_statement_extern(var_t *var);
static statement_t *make_statement_declaration(var_t *var);
static statement_t *make_statement_library(typelib_t *typelib);
static statement_t *make_statement_cppquote(const char *str);
static statement_t *make_statement_importlib(const char *str);
static statement_t *make_statement_module(type_t *type);
static statement_t *make_statement_import(const char *str);
static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt);
static func_list_t *append_func_from_statement(func_list_t *list, statement_t *stmt);
#define tsENUM 1
#define tsSTRUCT 2
@ -267,6 +268,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%token tPUBLIC
%token tRANGE
%token tREADONLY tREF
%token tREGISTER
%token tREQUESTEDIT
%token tRESTRICTED
%token tRETVAL
@ -277,6 +279,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%token tSIZEIS tSIZEOF
%token tSMALL
%token tSOURCE
%token tSTATIC
%token tSTDCALL
%token tSTRICTCONTEXTHANDLE
%token tSTRING tSTRUCT
@ -300,6 +303,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%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 <stgclass> storage_cls_spec
%type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
%type <type> inherit interface interfacedef interfacedec
%type <type> dispinterface dispinterfacehdr dispinterfacedef
@ -309,10 +313,10 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%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
%type <var> arg ne_union_field union_field s_field case enum declaration
%type <var_list> m_args no_args args fields ne_union_fields cases enums enum_list dispint_props field
%type <var> m_ident t_ident ident
%type <declarator> declarator direct_declarator
%type <declarator> declarator direct_declarator init_declarator
%type <declarator_list> declarator_list
%type <func> funcdef
%type <func_list> int_statements dispint_meths
@ -386,26 +390,23 @@ imp_statements: { $$ = NULL; }
;
int_statements: { $$ = NULL; }
| int_statements funcdef ';' { $$ = append_func( $1, $2 ); }
| int_statements statement { $$ = $1; }
| int_statements statement { $$ = append_func_from_statement( $1, $2 ); }
;
semicolon_opt:
| ';'
;
statement: constdef ';' { $$ = make_statement_init_decl($1);
if (!parse_only && do_header) { write_constdef($1); }
}
| cppquote { $$ = make_statement_cppquote($1); }
statement:
cppquote { $$ = make_statement_cppquote($1); }
| enumdef ';' { $$ = make_statement_type_decl($1);
if (!parse_only && do_header) {
write_type_def_or_decl(header, $1, FALSE, NULL);
fprintf(header, ";\n\n");
}
}
| externdef ';' { $$ = make_statement_extern($1);
if (!parse_only && do_header) write_externdef($1);
| declaration ';' { $$ = make_statement_declaration($1);
if (!parse_only && do_header) write_declaration($1, is_in_interface);
}
| import { $$ = make_statement_import($1); }
| structdef ';' { $$ = make_statement_type_decl($1);
@ -616,14 +617,6 @@ case: tCASE expr_int_const ':' union_field { attr_t *a = make_attrp(ATTR_CASE,
}
;
constdef: tCONST decl_spec declarator '=' expr_const
{ $$ = reg_const($3->var);
set_type($$, $2, $3, FALSE);
$$->eval = $5;
free($3);
}
;
enums: { $$ = NULL; }
| enum_list ',' { $$ = $1; }
| enum_list
@ -736,12 +729,6 @@ expr_const: expr { $$ = $1;
}
;
externdef: tEXTERN tCONST decl_spec declarator { $$ = $4->var;
set_type($$, $3, $4, FALSE);
free($4);
}
;
fields: { $$ = NULL; }
| fields field { $$ = append_var_list($1, $2); }
;
@ -785,6 +772,19 @@ funcdef:
}
;
declaration:
attributes decl_spec init_declarator
{ $$ = $3->var;
$$->attrs = $1;
set_type($$, $2, $3, FALSE);
free($3);
}
| decl_spec init_declarator { $$ = $2->var;
set_type($$, $1, $2, FALSE);
free($2);
}
;
m_ident: { $$ = NULL; }
| ident
;
@ -877,6 +877,7 @@ dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(0, $2, 0); $$->kind =
;
dispinterfacehdr: attributes dispinterface { attr_t *attrs;
is_in_interface = TRUE;
is_object_interface = TRUE;
$$ = $2;
if ($$->defined) error_loc("multiple definition error\n");
@ -905,6 +906,7 @@ dispinterfacedef: dispinterfacehdr '{'
$$->funcs = $4;
if (!parse_only && do_header) write_dispinterface($$);
if (!parse_only && do_idfile) write_diid($$);
is_in_interface = FALSE;
}
| dispinterfacehdr
'{' interface ';' '}' { $$ = $1;
@ -912,6 +914,7 @@ dispinterfacedef: dispinterfacehdr '{'
$$->funcs = $3->funcs;
if (!parse_only && do_header) write_dispinterface($$);
if (!parse_only && do_idfile) write_diid($$);
is_in_interface = FALSE;
}
;
@ -928,6 +931,7 @@ interfacehdr: attributes interface { $$.interface = $2;
if (is_attr($1, ATTR_POINTERDEFAULT))
pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
is_object_interface = is_object($1);
is_in_interface = TRUE;
if ($2->defined) error_loc("multiple definition error\n");
$2->attrs = check_iface_attrs($2->name, $1);
$2->defined = TRUE;
@ -945,6 +949,7 @@ interfacedef: interfacehdr inherit
if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
if (!parse_only && do_idfile) write_iid($$);
pointer_default = $1.old_pointer_default;
is_in_interface = FALSE;
}
/* MIDL is able to import the definition of a base class from inside the
* definition of a derived class, I'll try to support it with this rule */
@ -959,6 +964,7 @@ interfacedef: interfacehdr inherit
if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
if (!parse_only && do_idfile) write_iid($$);
pointer_default = $1.old_pointer_default;
is_in_interface = FALSE;
}
| dispinterfacedef semicolon_opt { $$ = $1; }
;
@ -984,6 +990,12 @@ moduledef: modulehdr '{' int_statements '}'
}
;
storage_cls_spec:
tEXTERN { $$ = STG_EXTERN; }
| tSTATIC { $$ = STG_STATIC; }
| tREGISTER { $$ = STG_REGISTER; }
;
function_specifier:
tINLINE { $$ = make_attr(ATTR_INLINE); }
;
@ -1008,6 +1020,7 @@ m_decl_spec_no_type: { $$ = NULL; }
decl_spec_no_type:
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); }
| storage_cls_spec m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, NULL, $1); }
;
declarator:
@ -1032,6 +1045,11 @@ declarator_list:
| declarator_list ',' declarator { $$ = append_declarator( $1, $3 ); }
;
init_declarator:
declarator { $$ = $1; }
| declarator '=' expr_const { $$ = $1; $1->var->eval = $3; }
;
pointer_type:
tREF { $$ = RPC_FC_RP; }
| tUNIQUE { $$ = RPC_FC_UP; }
@ -2228,7 +2246,7 @@ struct allowed_attr allowed_attr[] =
/* ATTR_BINDABLE */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "bindable" },
/* ATTR_BROADCAST */ { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "broadcast" },
/* ATTR_CALLAS */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "call_as" },
/* ATTR_CALLCONV */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL },
/* ATTR_CALLCONV */ { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, NULL },
/* ATTR_CASE */ { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "case" },
/* ATTR_CONST */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "const" },
/* ATTR_CONTEXTHANDLE */ { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, "context_handle" },
@ -2754,17 +2772,20 @@ static statement_t *make_statement_reference(type_t *type)
return stmt;
}
static statement_t *make_statement_init_decl(var_t *var)
static statement_t *make_statement_declaration(var_t *var)
{
statement_t *stmt = make_statement(STMT_INITDECL);
stmt->u.var = var;
return stmt;
}
static statement_t *make_statement_extern(var_t *var)
{
statement_t *stmt = make_statement(STMT_EXTERN);
statement_t *stmt = make_statement(STMT_DECLARATION);
stmt->u.var = var;
if (var->stgclass == STG_EXTERN && var->eval)
warning("'%s' initialised and declared extern\n", var->name);
if (is_const_decl(var))
{
if (var->eval)
reg_const(var);
}
else if ((var->stgclass == STG_NONE || var->stgclass == STG_REGISTER) &&
var->type->type != RPC_FC_FUNCTION)
error_loc("instantiation of data is illegal\n");
return stmt;
}
@ -2847,3 +2868,17 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
list_add_tail( list, &stmt->entry );
return list;
}
static func_list_t *append_func_from_statement(func_list_t *list, statement_t *stmt)
{
if (stmt->type == STMT_DECLARATION)
{
var_t *var = stmt->u.var;
if (var->stgclass == STG_NONE && var->type->type == RPC_FC_FUNCTION)
{
check_function_attrs(var->name, var->type->attrs);
return append_func(list, make_func(stmt->u.var));
}
}
return list;
}

View File

@ -209,8 +209,7 @@ enum storage_class
enum statement_type
{
STMT_LIBRARY,
STMT_INITDECL,
STMT_EXTERN,
STMT_DECLARATION,
STMT_TYPE,
STMT_TYPEREF,
STMT_MODULE,