From: Jacek Caban Subject: [PATCH 1/6] widl: Keep track of namespace in parser and beginning namespace lookup implementation. Message-Id: <55BB5E04.3020304@codeweavers.com> Date: Fri, 31 Jul 2015 13:37:40 +0200 --- tools/widl/parser.y | 123 ++++++++++++++++++++++++++++++++++--------------- tools/widl/typetree.c | 20 ++++---- tools/widl/widltypes.h | 16 +++++-- 3 files changed, 110 insertions(+), 49 deletions(-) diff --git a/tools/widl/parser.y b/tools/widl/parser.y index c0c77d7..f3c250a 100644 --- a/tools/widl/parser.y +++ b/tools/widl/parser.y @@ -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 inherit interface interfacedef interfacedec %type dispinterface dispinterfacehdr dispinterfacedef %type module modulehdr moduledef -%type namespacedef +%type namespacedef %type base_type int_std %type enumdef structdef uniondef typedecl %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 *****/ diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index a9e71be..6c09806 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -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); diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h index 47c8844..2e89ddb 100644 --- a/tools/widl/widltypes.h +++ b/tools/widl/widltypes.h @@ -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);