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"); fprintf(header, ";\n");
} }
void write_constdef(const var_t *v) int is_const_decl(const var_t *var)
{ {
fprintf(header, "#define %s (", v->name); const type_t *t;
write_expr(header, v->eval, 0, 1, NULL, NULL); /* strangely, MIDL accepts a const attribute on any pointer in the
fprintf(header, ")\n\n"); * 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 "); if (is_const_decl(v) && v->eval)
write_type_def_or_decl(header, v->type, FALSE, "%s", v->name); {
fprintf(header, ";\n\n"); 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) 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(type_t *cocl);
extern void write_coclass_forward(type_t *cocl); extern void write_coclass_forward(type_t *cocl);
extern void write_typedef(type_t *type); extern void write_typedef(type_t *type);
extern void write_constdef(const var_t *v); extern void write_declaration(const var_t *v, int is_in_interface);
extern void write_externdef(const var_t *v);
extern void write_library(const typelib_t *typelib); extern void write_library(const typelib_t *typelib);
extern void write_user_types(void); extern void write_user_types(void);
extern void write_context_handle_rundowns(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 int has_out_arg_or_return(const func_t *func);
extern void write_guid(FILE *f, const char *guid_prefix, const char *name, extern void write_guid(FILE *f, const char *guid_prefix, const char *name,
const UUID *uuid); const UUID *uuid);
extern int is_const_decl(const var_t *var);
static inline int last_ptr(const type_t *type) static inline int last_ptr(const type_t *type)
{ {

View file

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

View file

@ -68,6 +68,7 @@
#define YYERROR_VERBOSE #define YYERROR_VERBOSE
unsigned char pointer_default = RPC_FC_UP; unsigned char pointer_default = RPC_FC_UP;
static int is_in_interface = FALSE;
static int is_object_interface = FALSE; static int is_object_interface = FALSE;
/* are we inside a library block? */ /* are we inside a library block? */
static int is_inside_library = FALSE; 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(enum statement_type type);
static statement_t *make_statement_type_decl(type_t *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_reference(type_t *type);
static statement_t *make_statement_init_decl(var_t *var); static statement_t *make_statement_declaration(var_t *var);
static statement_t *make_statement_extern(var_t *var);
static statement_t *make_statement_library(typelib_t *typelib); static statement_t *make_statement_library(typelib_t *typelib);
static statement_t *make_statement_cppquote(const char *str); static statement_t *make_statement_cppquote(const char *str);
static statement_t *make_statement_importlib(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_module(type_t *type);
static statement_t *make_statement_import(const char *str); static statement_t *make_statement_import(const char *str);
static statement_list_t *append_statement(statement_list_t *list, statement_t *stmt); 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 tsENUM 1
#define tsSTRUCT 2 #define tsSTRUCT 2
@ -267,6 +268,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%token tPUBLIC %token tPUBLIC
%token tRANGE %token tRANGE
%token tREADONLY tREF %token tREADONLY tREF
%token tREGISTER
%token tREQUESTEDIT %token tREQUESTEDIT
%token tRESTRICTED %token tRESTRICTED
%token tRETVAL %token tRETVAL
@ -277,6 +279,7 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
%token tSIZEIS tSIZEOF %token tSIZEIS tSIZEOF
%token tSMALL %token tSMALL
%token tSOURCE %token tSOURCE
%token tSTATIC
%token tSTDCALL %token tSTDCALL
%token tSTRICTCONTEXTHANDLE %token tSTRICTCONTEXTHANDLE
%token tSTRING tSTRUCT %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> m_expr expr expr_const expr_int_const array
%type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const %type <expr_list> m_exprs /* exprs expr_list */ expr_list_int_const
%type <ifinfo> interfacehdr %type <ifinfo> interfacehdr
%type <stgclass> storage_cls_spec
%type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type %type <declspec> decl_spec decl_spec_no_type m_decl_spec_no_type
%type <type> inherit interface interfacedef interfacedec %type <type> inherit interface interfacedef interfacedec
%type <type> dispinterface dispinterfacehdr dispinterfacedef %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 <type> type
%type <ifref> coclass_int %type <ifref> coclass_int
%type <ifref_list> coclass_ints %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_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 <var> m_ident t_ident ident
%type <declarator> declarator direct_declarator %type <declarator> declarator direct_declarator init_declarator
%type <declarator_list> declarator_list %type <declarator_list> declarator_list
%type <func> funcdef %type <func> funcdef
%type <func_list> int_statements dispint_meths %type <func_list> int_statements dispint_meths
@ -386,26 +390,23 @@ imp_statements: { $$ = NULL; }
; ;
int_statements: { $$ = NULL; } int_statements: { $$ = NULL; }
| int_statements funcdef ';' { $$ = append_func( $1, $2 ); } | int_statements statement { $$ = append_func_from_statement( $1, $2 ); }
| int_statements statement { $$ = $1; }
; ;
semicolon_opt: semicolon_opt:
| ';' | ';'
; ;
statement: constdef ';' { $$ = make_statement_init_decl($1); statement:
if (!parse_only && do_header) { write_constdef($1); } cppquote { $$ = make_statement_cppquote($1); }
}
| cppquote { $$ = make_statement_cppquote($1); }
| enumdef ';' { $$ = make_statement_type_decl($1); | enumdef ';' { $$ = make_statement_type_decl($1);
if (!parse_only && do_header) { if (!parse_only && do_header) {
write_type_def_or_decl(header, $1, FALSE, NULL); write_type_def_or_decl(header, $1, FALSE, NULL);
fprintf(header, ";\n\n"); fprintf(header, ";\n\n");
} }
} }
| externdef ';' { $$ = make_statement_extern($1); | declaration ';' { $$ = make_statement_declaration($1);
if (!parse_only && do_header) write_externdef($1); if (!parse_only && do_header) write_declaration($1, is_in_interface);
} }
| import { $$ = make_statement_import($1); } | import { $$ = make_statement_import($1); }
| structdef ';' { $$ = make_statement_type_decl($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; } enums: { $$ = NULL; }
| enum_list ',' { $$ = $1; } | enum_list ',' { $$ = $1; }
| enum_list | 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: { $$ = NULL; }
| fields field { $$ = append_var_list($1, $2); } | 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; } m_ident: { $$ = NULL; }
| ident | ident
; ;
@ -877,6 +877,7 @@ dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(0, $2, 0); $$->kind =
; ;
dispinterfacehdr: attributes dispinterface { attr_t *attrs; dispinterfacehdr: attributes dispinterface { attr_t *attrs;
is_in_interface = TRUE;
is_object_interface = TRUE; is_object_interface = TRUE;
$$ = $2; $$ = $2;
if ($$->defined) error_loc("multiple definition error\n"); if ($$->defined) error_loc("multiple definition error\n");
@ -905,6 +906,7 @@ dispinterfacedef: dispinterfacehdr '{'
$$->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($$);
is_in_interface = FALSE;
} }
| dispinterfacehdr | dispinterfacehdr
'{' interface ';' '}' { $$ = $1; '{' interface ';' '}' { $$ = $1;
@ -912,6 +914,7 @@ dispinterfacedef: dispinterfacehdr '{'
$$->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($$);
is_in_interface = FALSE;
} }
; ;
@ -928,6 +931,7 @@ interfacehdr: attributes interface { $$.interface = $2;
if (is_attr($1, ATTR_POINTERDEFAULT)) if (is_attr($1, ATTR_POINTERDEFAULT))
pointer_default = get_attrv($1, ATTR_POINTERDEFAULT); pointer_default = get_attrv($1, ATTR_POINTERDEFAULT);
is_object_interface = is_object($1); is_object_interface = is_object($1);
is_in_interface = TRUE;
if ($2->defined) error_loc("multiple definition error\n"); if ($2->defined) error_loc("multiple definition error\n");
$2->attrs = check_iface_attrs($2->name, $1); $2->attrs = check_iface_attrs($2->name, $1);
$2->defined = TRUE; $2->defined = TRUE;
@ -945,6 +949,7 @@ interfacedef: interfacehdr inherit
if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE); if (!parse_only && local_stubs) write_locals(local_stubs, $$, TRUE);
if (!parse_only && do_idfile) write_iid($$); if (!parse_only && do_idfile) write_iid($$);
pointer_default = $1.old_pointer_default; pointer_default = $1.old_pointer_default;
is_in_interface = FALSE;
} }
/* MIDL is able to import the definition of a base class from inside the /* 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 */ * 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 && local_stubs) write_locals(local_stubs, $$, TRUE);
if (!parse_only && do_idfile) write_iid($$); if (!parse_only && do_idfile) write_iid($$);
pointer_default = $1.old_pointer_default; pointer_default = $1.old_pointer_default;
is_in_interface = FALSE;
} }
| dispinterfacedef semicolon_opt { $$ = $1; } | 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: function_specifier:
tINLINE { $$ = make_attr(ATTR_INLINE); } tINLINE { $$ = make_attr(ATTR_INLINE); }
; ;
@ -1008,6 +1020,7 @@ m_decl_spec_no_type: { $$ = NULL; }
decl_spec_no_type: decl_spec_no_type:
type_qualifier m_decl_spec_no_type { $$ = make_decl_spec(NULL, $2, NULL, $1, STG_NONE); } 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); } | 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: declarator:
@ -1032,6 +1045,11 @@ declarator_list:
| declarator_list ',' declarator { $$ = append_declarator( $1, $3 ); } | declarator_list ',' declarator { $$ = append_declarator( $1, $3 ); }
; ;
init_declarator:
declarator { $$ = $1; }
| declarator '=' expr_const { $$ = $1; $1->var->eval = $3; }
;
pointer_type: pointer_type:
tREF { $$ = RPC_FC_RP; } tREF { $$ = RPC_FC_RP; }
| tUNIQUE { $$ = RPC_FC_UP; } | 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_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_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_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_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_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" }, /* 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; 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); statement_t *stmt = make_statement(STMT_DECLARATION);
stmt->u.var = var;
return stmt;
}
static statement_t *make_statement_extern(var_t *var)
{
statement_t *stmt = make_statement(STMT_EXTERN);
stmt->u.var = var; 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; 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 ); list_add_tail( list, &stmt->entry );
return list; 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 enum statement_type
{ {
STMT_LIBRARY, STMT_LIBRARY,
STMT_INITDECL, STMT_DECLARATION,
STMT_EXTERN,
STMT_TYPE, STMT_TYPE,
STMT_TYPEREF, STMT_TYPEREF,
STMT_MODULE, STMT_MODULE,