widl: Keep track of namespace in parser and beginning namespace lookup implementation.

This commit is contained in:
Jacek Caban 2015-07-31 13:37:40 +02:00 committed by Alexandre Julliard
parent 14c0009add
commit ddc493a805
3 changed files with 110 additions and 49 deletions

View File

@ -90,6 +90,9 @@ static type_t *find_type_or_error2(char *name, int t);
static var_t *reg_const(var_t *var); static var_t *reg_const(var_t *var);
static void push_namespace(const char *name);
static void pop_namespace(const char *name);
static char *gen_name(void); static char *gen_name(void);
static void check_arg_attrs(const var_t *arg); static void check_arg_attrs(const var_t *arg);
static void check_statements(const statement_list_t *stmts, int is_inside_library); static void check_statements(const statement_list_t *stmts, int is_inside_library);
@ -125,6 +128,12 @@ static statement_list_t *append_statement(statement_list_t *list, statement_t *s
static statement_list_t *append_statements(statement_list_t *, statement_list_t *); static statement_list_t *append_statements(statement_list_t *, statement_list_t *);
static attr_list_t *append_attribs(attr_list_t *, attr_list_t *); static attr_list_t *append_attribs(attr_list_t *, attr_list_t *);
static struct namespace global_namespace = {
NULL, NULL, LIST_INIT(global_namespace.entry), LIST_INIT(global_namespace.children)
};
static struct namespace *current_namespace = &global_namespace;
%} %}
%union { %union {
attr_t *attr; attr_t *attr;
@ -262,7 +271,7 @@ static attr_list_t *append_attribs(attr_list_t *, attr_list_t *);
%type <type> inherit interface interfacedef interfacedec %type <type> inherit interface interfacedef interfacedec
%type <type> dispinterface dispinterfacehdr dispinterfacedef %type <type> dispinterface dispinterfacehdr dispinterfacedef
%type <type> module modulehdr moduledef %type <type> module modulehdr moduledef
%type <type> namespacedef %type <str> namespacedef
%type <type> base_type int_std %type <type> base_type int_std
%type <type> enumdef structdef uniondef typedecl %type <type> enumdef structdef uniondef typedecl
%type <type> type %type <type> type
@ -320,15 +329,15 @@ input: gbl_statements { fix_incomplete();
; ;
gbl_statements: { $$ = NULL; } gbl_statements: { $$ = NULL; }
| gbl_statements namespacedef '{' gbl_statements '}' | gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}'
{ $$ = append_statements($1, $4); } { pop_namespace($2); $$ = append_statements($1, $5); }
| gbl_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); } | gbl_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); }
| gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } | gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); }
| gbl_statements coclass ';' { $$ = $1; | gbl_statements coclass ';' { $$ = $1;
reg_type($2, $2->name, 0); reg_type($2, $2->name, current_namespace, 0);
} }
| gbl_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); | gbl_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2));
reg_type($2, $2->name, 0); reg_type($2, $2->name, current_namespace, 0);
} }
| gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | gbl_statements moduledef { $$ = append_statement($1, make_statement_module($2)); }
| gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); } | gbl_statements librarydef { $$ = append_statement($1, make_statement_library($2)); }
@ -337,12 +346,12 @@ gbl_statements: { $$ = NULL; }
imp_statements: { $$ = NULL; } imp_statements: { $$ = NULL; }
| imp_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); } | imp_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); }
| imp_statements namespacedef '{' imp_statements '}' | imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}'
{ $$ = append_statements($1, $4); } { pop_namespace($2); $$ = append_statements($1, $5); }
| imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); } | imp_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); }
| imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, 0); } | imp_statements coclass ';' { $$ = $1; reg_type($2, $2->name, current_namespace, 0); }
| imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2)); | imp_statements coclassdef { $$ = append_statement($1, make_statement_type_decl($2));
reg_type($2, $2->name, 0); reg_type($2, $2->name, current_namespace, 0);
} }
| imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); } | imp_statements moduledef { $$ = append_statement($1, make_statement_module($2)); }
| imp_statements statement { $$ = append_statement($1, $2); } | imp_statements statement { $$ = append_statement($1, $2); }
@ -794,7 +803,7 @@ int_std: tINT { $$ = type_new_int(TYPE_BASIC_INT, 0); }
; ;
coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); } coclass: tCOCLASS aIDENTIFIER { $$ = type_new_coclass($2); }
| tCOCLASS aKNOWNTYPE { $$ = find_type($2, 0); | tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0);
if (type_get_type_detect_alias($$) != TYPE_COCLASS) if (type_get_type_detect_alias($$) != TYPE_COCLASS)
error_loc("%s was not declared a coclass at %s:%d\n", error_loc("%s was not declared a coclass at %s:%d\n",
$2, $$->loc_info.input_name, $2, $$->loc_info.input_name,
@ -812,7 +821,7 @@ coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt
{ $$ = type_coclass_define($1, $3); } { $$ = type_coclass_define($1, $3); }
; ;
namespacedef: tNAMESPACE aIDENTIFIER { $$ = NULL; } namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; }
; ;
coclass_ints: { $$ = NULL; } coclass_ints: { $$ = NULL; }
@ -823,8 +832,8 @@ coclass_int:
m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; } m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; }
; ;
dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, 0); } dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
| tDISPINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, 0); } | tDISPINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
; ;
dispinterfacehdr: attributes dispinterface { attr_t *attrs; dispinterfacehdr: attributes dispinterface { attr_t *attrs;
@ -860,8 +869,8 @@ inherit: { $$ = NULL; }
| ':' aKNOWNTYPE { $$ = find_type_or_error2($2, 0); } | ':' aKNOWNTYPE { $$ = find_type_or_error2($2, 0); }
; ;
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, 0); } interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
| tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, 0); } | tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
; ;
interfacehdr: attributes interface { $$.interface = $2; interfacehdr: attributes interface { $$.interface = $2;
@ -1122,12 +1131,12 @@ version:
static void decl_builtin_basic(const char *name, enum type_basic_type type) static void decl_builtin_basic(const char *name, enum type_basic_type type)
{ {
type_t *t = type_new_basic(type); type_t *t = type_new_basic(type);
reg_type(t, name, 0); reg_type(t, name, NULL, 0);
} }
static void decl_builtin_alias(const char *name, type_t *t) static void decl_builtin_alias(const char *name, type_t *t)
{ {
reg_type(type_new_alias(t, name), name, 0); reg_type(type_new_alias(t, name), name, NULL, 0);
} }
void init_types(void) void init_types(void)
@ -1731,8 +1740,6 @@ static typelib_t *make_library(const char *name, const attr_list_t *attrs)
return typelib; return typelib;
} }
#define HASHMAX 64
static int hash_ident(const char *name) static int hash_ident(const char *name)
{ {
const char *p = name; const char *p = name;
@ -1747,6 +1754,41 @@ static int hash_ident(const char *name)
/***** type repository *****/ /***** type repository *****/
static struct namespace *find_sub_namespace(struct namespace *namespace, const char *name)
{
struct namespace *cur;
LIST_FOR_EACH_ENTRY(cur, &namespace->children, struct namespace, entry) {
if(!strcmp(cur->name, name))
return cur;
}
return NULL;
}
static void push_namespace(const char *name)
{
struct namespace *namespace;
namespace = find_sub_namespace(current_namespace, name);
if(!namespace) {
namespace = xmalloc(sizeof(*namespace));
namespace->name = xstrdup(name);
namespace->parent = current_namespace;
list_add_tail(&current_namespace->children, &namespace->entry);
list_init(&namespace->children);
memset(namespace->type_hash, 0, sizeof(namespace->type_hash));
}
current_namespace = namespace;
}
static void pop_namespace(const char *name)
{
assert(!strcmp(current_namespace->name, name) && current_namespace->parent);
current_namespace = current_namespace->parent;
}
struct rtype { struct rtype {
const char *name; const char *name;
type_t *type; type_t *type;
@ -1754,9 +1796,7 @@ struct rtype {
struct rtype *next; struct rtype *next;
}; };
struct rtype *type_hash[HASHMAX]; type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, int t)
type_t *reg_type(type_t *type, const char *name, int t)
{ {
struct rtype *nt; struct rtype *nt;
int hash; int hash;
@ -1764,13 +1804,15 @@ type_t *reg_type(type_t *type, const char *name, int t)
error_loc("registering named type without name\n"); error_loc("registering named type without name\n");
return type; return type;
} }
if (!namespace)
namespace = &global_namespace;
hash = hash_ident(name); hash = hash_ident(name);
nt = xmalloc(sizeof(struct rtype)); nt = xmalloc(sizeof(struct rtype));
nt->name = name; nt->name = name;
nt->type = type; nt->type = type;
nt->t = t; nt->t = t;
nt->next = type_hash[hash]; nt->next = namespace->type_hash[hash];
type_hash[hash] = nt; namespace->type_hash[hash] = nt;
if ((t == tsSTRUCT || t == tsUNION)) if ((t == tsSTRUCT || t == tsUNION))
fix_incomplete_types(type); fix_incomplete_types(type);
return type; return type;
@ -1859,7 +1901,7 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
type_t *cur; type_t *cur;
var_t *name; var_t *name;
cur = find_type(decl->var->name, 0); cur = find_type(decl->var->name, current_namespace, 0);
/* /*
* MIDL allows shadowing types that are declared in imported files. * MIDL allows shadowing types that are declared in imported files.
@ -1881,23 +1923,32 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
if (is_incomplete(cur)) if (is_incomplete(cur))
add_incomplete(cur); add_incomplete(cur);
reg_type(cur, cur->name, 0); reg_type(cur, cur->name, current_namespace, 0);
} }
} }
return type; return type;
} }
type_t *find_type(const char *name, int t) type_t *find_type(const char *name, struct namespace *namespace, int t)
{ {
struct rtype *cur = type_hash[hash_ident(name)]; struct rtype *cur;
while (cur && (cur->t != t || strcmp(cur->name, name)))
cur = cur->next; if(namespace && namespace != &global_namespace) {
return cur ? cur->type : NULL; for(cur = namespace->type_hash[hash_ident(name)]; cur; cur = cur->next) {
if(cur->t == t && !strcmp(cur->name, name))
return cur->type;
}
}
for(cur = global_namespace.type_hash[hash_ident(name)]; cur; cur = cur->next) {
if(cur->t == t && !strcmp(cur->name, name))
return cur->type;
}
return NULL;
} }
static type_t *find_type_or_error(const char *name, int t) static type_t *find_type_or_error(const char *name, int t)
{ {
type_t *type = find_type(name, t); type_t *type = find_type(name, NULL, t);
if (!type) { if (!type) {
error_loc("type '%s' not found\n", name); error_loc("type '%s' not found\n", name);
return NULL; return NULL;
@ -1914,14 +1965,14 @@ static type_t *find_type_or_error2(char *name, int t)
int is_type(const char *name) int is_type(const char *name)
{ {
return find_type(name, 0) != NULL; return find_type(name, current_namespace, 0) != NULL;
} }
type_t *get_type(enum type_type type, char *name, int t) type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t)
{ {
type_t *tp; type_t *tp;
if (name) { if (name) {
tp = find_type(name, t); tp = find_type(name, namespace, t);
if (tp) { if (tp) {
free(name); free(name);
return tp; return tp;
@ -1930,7 +1981,7 @@ type_t *get_type(enum type_type type, char *name, int t)
tp = make_type(type); tp = make_type(type);
tp->name = name; tp->name = name;
if (!name) return tp; if (!name) return tp;
return reg_type(tp, name, t); return reg_type(tp, name, namespace, t);
} }
/***** constant repository *****/ /***** constant repository *****/

View File

@ -152,7 +152,7 @@ type_t *type_new_alias(type_t *t, const char *name)
type_t *type_new_module(char *name) type_t *type_new_module(char *name)
{ {
type_t *type = get_type(TYPE_MODULE, name, 0); type_t *type = get_type(TYPE_MODULE, name, NULL, 0);
if (type->type_type != TYPE_MODULE || type->defined) if (type->type_type != TYPE_MODULE || type->defined)
error_loc("%s: redefinition error; original definition was at %s:%d\n", error_loc("%s: redefinition error; original definition was at %s:%d\n",
type->name, type->loc_info.input_name, type->loc_info.line_number); type->name, type->loc_info.input_name, type->loc_info.line_number);
@ -162,7 +162,7 @@ type_t *type_new_module(char *name)
type_t *type_new_coclass(char *name) type_t *type_new_coclass(char *name)
{ {
type_t *type = get_type(TYPE_COCLASS, name, 0); type_t *type = get_type(TYPE_COCLASS, name, NULL, 0);
if (type->type_type != TYPE_COCLASS || type->defined) if (type->type_type != TYPE_COCLASS || type->defined)
error_loc("%s: redefinition error; original definition was at %s:%d\n", error_loc("%s: redefinition error; original definition was at %s:%d\n",
type->name, type->loc_info.input_name, type->loc_info.line_number); type->name, type->loc_info.input_name, type->loc_info.line_number);
@ -221,7 +221,7 @@ type_t *type_new_void(void)
type_t *type_new_enum(const char *name, int defined, var_list_t *enums) type_t *type_new_enum(const char *name, int defined, var_list_t *enums)
{ {
type_t *tag_type = name ? find_type(name, tsENUM) : NULL; type_t *tag_type = name ? find_type(name, NULL, tsENUM) : NULL;
type_t *t = make_type(TYPE_ENUM); type_t *t = make_type(TYPE_ENUM);
t->name = name; t->name = name;
@ -237,7 +237,7 @@ type_t *type_new_enum(const char *name, int defined, var_list_t *enums)
if (name) if (name)
{ {
if (defined) if (defined)
reg_type(t, name, tsENUM); reg_type(t, name, NULL, tsENUM);
else else
add_incomplete(t); add_incomplete(t);
} }
@ -246,7 +246,7 @@ type_t *type_new_enum(const char *name, int defined, var_list_t *enums)
type_t *type_new_struct(char *name, int defined, var_list_t *fields) type_t *type_new_struct(char *name, int defined, var_list_t *fields)
{ {
type_t *tag_type = name ? find_type(name, tsSTRUCT) : NULL; type_t *tag_type = name ? find_type(name, NULL, tsSTRUCT) : NULL;
type_t *t = make_type(TYPE_STRUCT); type_t *t = make_type(TYPE_STRUCT);
t->name = name; t->name = name;
if (tag_type && tag_type->details.structure) if (tag_type && tag_type->details.structure)
@ -260,7 +260,7 @@ type_t *type_new_struct(char *name, int defined, var_list_t *fields)
if (name) if (name)
{ {
if (defined) if (defined)
reg_type(t, name, tsSTRUCT); reg_type(t, name, NULL, tsSTRUCT);
else else
add_incomplete(t); add_incomplete(t);
} }
@ -269,7 +269,7 @@ type_t *type_new_struct(char *name, int defined, var_list_t *fields)
type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields) type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t *fields)
{ {
type_t *tag_type = name ? find_type(name, tsUNION) : NULL; type_t *tag_type = name ? find_type(name, NULL, tsUNION) : NULL;
type_t *t = make_type(TYPE_UNION); type_t *t = make_type(TYPE_UNION);
t->name = name; t->name = name;
if (tag_type && tag_type->details.structure) if (tag_type && tag_type->details.structure)
@ -283,7 +283,7 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t
if (name) if (name)
{ {
if (defined) if (defined)
reg_type(t, name, tsUNION); reg_type(t, name, NULL, tsUNION);
else else
add_incomplete(t); add_incomplete(t);
} }
@ -292,7 +292,7 @@ type_t *type_new_nonencapsulated_union(const char *name, int defined, var_list_t
type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases) type_t *type_new_encapsulated_union(char *name, var_t *switch_field, var_t *union_field, var_list_t *cases)
{ {
type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, tsUNION); type_t *t = get_type(TYPE_ENCAPSULATED_UNION, name, NULL, tsUNION);
if (!union_field) union_field = make_var( xstrdup("tagged_union") ); if (!union_field) union_field = make_var( xstrdup("tagged_union") );
union_field->type = type_new_nonencapsulated_union(NULL, TRUE, cases); union_field->type = type_new_nonencapsulated_union(NULL, TRUE, cases);
t->details.structure = xmalloc(sizeof(*t->details.structure)); t->details.structure = xmalloc(sizeof(*t->details.structure));
@ -392,7 +392,7 @@ void type_dispinterface_define(type_t *iface, var_list_t *props, var_list_t *met
iface->details.iface->disp_props = props; iface->details.iface->disp_props = props;
iface->details.iface->disp_methods = methods; iface->details.iface->disp_methods = methods;
iface->details.iface->stmts = NULL; iface->details.iface->stmts = NULL;
iface->details.iface->inherit = find_type("IDispatch", 0); iface->details.iface->inherit = find_type("IDispatch", NULL, 0);
if (!iface->details.iface->inherit) error_loc("IDispatch is undefined\n"); if (!iface->details.iface->inherit) error_loc("IDispatch is undefined\n");
iface->defined = TRUE; iface->defined = TRUE;
compute_method_indexes(iface); compute_method_indexes(iface);

View File

@ -382,6 +382,16 @@ struct bitfield_details
const expr_t *bits; const expr_t *bits;
}; };
#define HASHMAX 64
struct namespace {
const char *name;
struct namespace *parent;
struct list entry;
struct list children;
struct rtype *type_hash[HASHMAX];
};
enum type_type enum type_type
{ {
TYPE_VOID, TYPE_VOID,
@ -549,10 +559,10 @@ void clear_all_offsets(void);
#define tsUNION 3 #define tsUNION 3
var_t *find_const(const char *name, int f); var_t *find_const(const char *name, int f);
type_t *find_type(const char *name, int t); type_t *find_type(const char *name, struct namespace *namespace, int t);
type_t *make_type(enum type_type type); type_t *make_type(enum type_type type);
type_t *get_type(enum type_type type, char *name, int t); type_t *get_type(enum type_type type, char *name, struct namespace *namespace, int t);
type_t *reg_type(type_t *type, const char *name, int t); type_t *reg_type(type_t *type, const char *name, struct namespace *namespace, int t);
void add_incomplete(type_t *t); void add_incomplete(type_t *t);
var_t *make_var(char *name); var_t *make_var(char *name);