widl: Keep track of namespace in parser and beginning namespace lookup implementation.
This commit is contained in:
parent
14c0009add
commit
ddc493a805
|
@ -90,6 +90,9 @@ static type_t *find_type_or_error2(char *name, int t);
|
|||
|
||||
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 void check_arg_attrs(const var_t *arg);
|
||||
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 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 {
|
||||
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> dispinterface dispinterfacehdr dispinterfacedef
|
||||
%type <type> module modulehdr moduledef
|
||||
%type <type> namespacedef
|
||||
%type <str> namespacedef
|
||||
%type <type> base_type int_std
|
||||
%type <type> enumdef structdef uniondef typedecl
|
||||
%type <type> type
|
||||
|
@ -320,15 +329,15 @@ input: gbl_statements { fix_incomplete();
|
|||
;
|
||||
|
||||
gbl_statements: { $$ = NULL; }
|
||||
| gbl_statements namespacedef '{' gbl_statements '}'
|
||||
{ $$ = append_statements($1, $4); }
|
||||
| gbl_statements namespacedef '{' { push_namespace($2); } gbl_statements '}'
|
||||
{ pop_namespace($2); $$ = append_statements($1, $5); }
|
||||
| gbl_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); }
|
||||
| gbl_statements interfacedef { $$ = append_statement($1, make_statement_type_decl($2)); }
|
||||
| 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));
|
||||
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 librarydef { $$ = append_statement($1, make_statement_library($2)); }
|
||||
|
@ -337,12 +346,12 @@ gbl_statements: { $$ = NULL; }
|
|||
|
||||
imp_statements: { $$ = NULL; }
|
||||
| imp_statements interfacedec { $$ = append_statement($1, make_statement_reference($2)); }
|
||||
| imp_statements namespacedef '{' imp_statements '}'
|
||||
{ $$ = append_statements($1, $4); }
|
||||
| imp_statements namespacedef '{' { push_namespace($2); } imp_statements '}'
|
||||
{ pop_namespace($2); $$ = append_statements($1, $5); }
|
||||
| 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));
|
||||
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 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); }
|
||||
| tCOCLASS aKNOWNTYPE { $$ = find_type($2, 0);
|
||||
| tCOCLASS aKNOWNTYPE { $$ = find_type($2, NULL, 0);
|
||||
if (type_get_type_detect_alias($$) != TYPE_COCLASS)
|
||||
error_loc("%s was not declared a coclass at %s:%d\n",
|
||||
$2, $$->loc_info.input_name,
|
||||
|
@ -812,7 +821,7 @@ coclassdef: coclasshdr '{' coclass_ints '}' semicolon_opt
|
|||
{ $$ = type_coclass_define($1, $3); }
|
||||
;
|
||||
|
||||
namespacedef: tNAMESPACE aIDENTIFIER { $$ = NULL; }
|
||||
namespacedef: tNAMESPACE aIDENTIFIER { $$ = $2; }
|
||||
;
|
||||
|
||||
coclass_ints: { $$ = NULL; }
|
||||
|
@ -823,8 +832,8 @@ coclass_int:
|
|||
m_attributes interfacedec { $$ = make_ifref($2); $$->attrs = $1; }
|
||||
;
|
||||
|
||||
dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, 0); }
|
||||
| tDISPINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, 0); }
|
||||
dispinterface: tDISPINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
|
||||
| tDISPINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
|
||||
;
|
||||
|
||||
dispinterfacehdr: attributes dispinterface { attr_t *attrs;
|
||||
|
@ -860,8 +869,8 @@ inherit: { $$ = NULL; }
|
|||
| ':' aKNOWNTYPE { $$ = find_type_or_error2($2, 0); }
|
||||
;
|
||||
|
||||
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, 0); }
|
||||
| tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, 0); }
|
||||
interface: tINTERFACE aIDENTIFIER { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
|
||||
| tINTERFACE aKNOWNTYPE { $$ = get_type(TYPE_INTERFACE, $2, current_namespace, 0); }
|
||||
;
|
||||
|
||||
interfacehdr: attributes interface { $$.interface = $2;
|
||||
|
@ -1122,12 +1131,12 @@ version:
|
|||
static void decl_builtin_basic(const char *name, enum type_basic_type 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)
|
||||
{
|
||||
reg_type(type_new_alias(t, name), name, 0);
|
||||
reg_type(type_new_alias(t, name), name, NULL, 0);
|
||||
}
|
||||
|
||||
void init_types(void)
|
||||
|
@ -1731,8 +1740,6 @@ static typelib_t *make_library(const char *name, const attr_list_t *attrs)
|
|||
return typelib;
|
||||
}
|
||||
|
||||
#define HASHMAX 64
|
||||
|
||||
static int hash_ident(const char *name)
|
||||
{
|
||||
const char *p = name;
|
||||
|
@ -1747,6 +1754,41 @@ static int hash_ident(const char *name)
|
|||
|
||||
/***** 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(¤t_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 {
|
||||
const char *name;
|
||||
type_t *type;
|
||||
|
@ -1754,9 +1796,7 @@ struct rtype {
|
|||
struct rtype *next;
|
||||
};
|
||||
|
||||
struct rtype *type_hash[HASHMAX];
|
||||
|
||||
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)
|
||||
{
|
||||
struct rtype *nt;
|
||||
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");
|
||||
return type;
|
||||
}
|
||||
if (!namespace)
|
||||
namespace = &global_namespace;
|
||||
hash = hash_ident(name);
|
||||
nt = xmalloc(sizeof(struct rtype));
|
||||
nt->name = name;
|
||||
nt->type = type;
|
||||
nt->t = t;
|
||||
nt->next = type_hash[hash];
|
||||
type_hash[hash] = nt;
|
||||
nt->next = namespace->type_hash[hash];
|
||||
namespace->type_hash[hash] = nt;
|
||||
if ((t == tsSTRUCT || t == tsUNION))
|
||||
fix_incomplete_types(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;
|
||||
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.
|
||||
|
@ -1881,23 +1923,32 @@ static type_t *reg_typedefs(decl_spec_t *decl_spec, declarator_list_t *decls, at
|
|||
|
||||
if (is_incomplete(cur))
|
||||
add_incomplete(cur);
|
||||
reg_type(cur, cur->name, 0);
|
||||
reg_type(cur, cur->name, current_namespace, 0);
|
||||
}
|
||||
}
|
||||
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)];
|
||||
while (cur && (cur->t != t || strcmp(cur->name, name)))
|
||||
cur = cur->next;
|
||||
return cur ? cur->type : NULL;
|
||||
struct rtype *cur;
|
||||
|
||||
if(namespace && namespace != &global_namespace) {
|
||||
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)
|
||||
{
|
||||
type_t *type = find_type(name, t);
|
||||
type_t *type = find_type(name, NULL, t);
|
||||
if (!type) {
|
||||
error_loc("type '%s' not found\n", name);
|
||||
return NULL;
|
||||
|
@ -1914,14 +1965,14 @@ static type_t *find_type_or_error2(char *name, int t)
|
|||
|
||||
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;
|
||||
if (name) {
|
||||
tp = find_type(name, t);
|
||||
tp = find_type(name, namespace, t);
|
||||
if (tp) {
|
||||
free(name);
|
||||
return tp;
|
||||
|
@ -1930,7 +1981,7 @@ type_t *get_type(enum type_type type, char *name, int t)
|
|||
tp = make_type(type);
|
||||
tp->name = name;
|
||||
if (!name) return tp;
|
||||
return reg_type(tp, name, t);
|
||||
return reg_type(tp, name, namespace, t);
|
||||
}
|
||||
|
||||
/***** constant repository *****/
|
||||
|
|
|
@ -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 = get_type(TYPE_MODULE, name, 0);
|
||||
type_t *type = get_type(TYPE_MODULE, name, NULL, 0);
|
||||
if (type->type_type != TYPE_MODULE || type->defined)
|
||||
error_loc("%s: redefinition error; original definition was at %s:%d\n",
|
||||
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 = get_type(TYPE_COCLASS, name, 0);
|
||||
type_t *type = get_type(TYPE_COCLASS, name, NULL, 0);
|
||||
if (type->type_type != TYPE_COCLASS || type->defined)
|
||||
error_loc("%s: redefinition error; original definition was at %s:%d\n",
|
||||
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 *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);
|
||||
t->name = name;
|
||||
|
||||
|
@ -237,7 +237,7 @@ type_t *type_new_enum(const char *name, int defined, var_list_t *enums)
|
|||
if (name)
|
||||
{
|
||||
if (defined)
|
||||
reg_type(t, name, tsENUM);
|
||||
reg_type(t, name, NULL, tsENUM);
|
||||
else
|
||||
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 *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);
|
||||
t->name = name;
|
||||
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 (defined)
|
||||
reg_type(t, name, tsSTRUCT);
|
||||
reg_type(t, name, NULL, tsSTRUCT);
|
||||
else
|
||||
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 *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);
|
||||
t->name = name;
|
||||
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 (defined)
|
||||
reg_type(t, name, tsUNION);
|
||||
reg_type(t, name, NULL, tsUNION);
|
||||
else
|
||||
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 *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") );
|
||||
union_field->type = type_new_nonencapsulated_union(NULL, TRUE, cases);
|
||||
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_methods = methods;
|
||||
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");
|
||||
iface->defined = TRUE;
|
||||
compute_method_indexes(iface);
|
||||
|
|
|
@ -382,6 +382,16 @@ struct bitfield_details
|
|||
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
|
||||
{
|
||||
TYPE_VOID,
|
||||
|
@ -549,10 +559,10 @@ void clear_all_offsets(void);
|
|||
#define tsUNION 3
|
||||
|
||||
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 *get_type(enum type_type type, char *name, int t);
|
||||
type_t *reg_type(type_t *type, const 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, struct namespace *namespace, int t);
|
||||
void add_incomplete(type_t *t);
|
||||
|
||||
var_t *make_var(char *name);
|
||||
|
|
Loading…
Reference in New Issue