diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 5959e701..dadc833a 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -29,12 +29,12 @@ static struct keyword { { NULL, -1 } }; #define KW_HASH_SIZE 64 +static struct keyword *kw_hash[KW_HASH_SIZE]; +static int kw_hash_inited; + #define SYM_HASH_SIZE 128 #define SYM_MAX_LEN 32 -static struct keyword *kw_hash[KW_HASH_SIZE]; -static struct symbol **sym_hash; - struct sym_scope { struct sym_scope *next; /* Next on scope stack */ struct symbol *name; /* Name of this scope */ @@ -192,21 +192,30 @@ static struct symbol * cf_find_sym(byte *c, unsigned int h0) { unsigned int h = h0 & (SYM_HASH_SIZE-1); - struct symbol *s; + struct symbol *s, **ht; int l; - if (!sym_hash) - sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *)); - else - for(s = sym_hash[h]; s; s=s->next) + if (ht = new_config->sym_hash) + { + for(s = ht[h]; s; s=s->next) if (!strcmp(s->name, c) && s->scope->active) return s; + } + if (new_config->sym_fallback) + { + /* We know only top-level scope is active */ + for(s = new_config->sym_fallback[h]; s; s=s->next) + if (!strcmp(s->name, c) && s->scope->active) + return s; + } + if (!ht) + ht = new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *)); l = strlen(c); if (l > SYM_MAX_LEN) cf_error("Symbol too long"); s = cfg_alloc(sizeof(struct symbol) + l); - s->next = sym_hash[h]; - sym_hash[h] = s; + s->next = ht[h]; + ht[h] = s; s->scope = conf_this_scope; s->class = SYM_VOID; s->def = NULL; @@ -246,22 +255,8 @@ cf_define_symbol(struct symbol *sym, int type, void *def) sym->def = def; } -void -cf_lex_init(int is_cli) -{ - sym_hash = NULL; - conf_lino = 1; - yyrestart(NULL); - if (is_cli) - BEGIN(CLI); - else - BEGIN(INITIAL); - conf_this_scope = cfg_allocz(sizeof(struct sym_scope)); - conf_this_scope->active = 1; -} - -void -cf_lex_init_tables(void) +static void +cf_lex_init_kh(void) { struct keyword *k; @@ -271,6 +266,22 @@ cf_lex_init_tables(void) k->next = kw_hash[h]; kw_hash[h] = k; } + kw_hash_inited = 1; +} + +void +cf_lex_init(int is_cli) +{ + if (!kw_hash_inited) + cf_lex_init_kh(); + conf_lino = 1; + yyrestart(NULL); + if (is_cli) + BEGIN(CLI); + else + BEGIN(INITIAL); + conf_this_scope = cfg_allocz(sizeof(struct sym_scope)); + conf_this_scope->active = 1; } void diff --git a/conf/conf.c b/conf/conf.c index 47d4db4e..4e2f920d 100644 --- a/conf/conf.c +++ b/conf/conf.c @@ -45,7 +45,6 @@ config_parse(struct config *c) if (setjmp(conf_jmpbuf)) return 0; cf_lex_init(0); - cf_lex_init_tables(); protos_preconfig(c); rt_preconfig(c); cf_parse(); @@ -62,6 +61,7 @@ int cli_parse(struct config *c) { new_config = c; + c->sym_fallback = config->sym_hash; cfg_mem = c->mem; if (setjmp(conf_jmpbuf)) return 0; diff --git a/conf/conf.h b/conf/conf.h index ec8be407..957ce443 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -23,6 +23,8 @@ struct config { char *err_msg; /* Parser error message */ int err_lino; /* Line containing error */ char *file_name; /* Name of configuration file */ + struct symbol **sym_hash; /* Lexer: symbol hash table */ + struct symbol **sym_fallback; /* Lexer: fallback symbol hash table */ }; extern struct config *config, *new_config; @@ -69,7 +71,6 @@ struct symbol { extern int conf_lino; -void cf_lex_init_tables(void); int cf_lex(void); void cf_lex_init(int is_cli); struct symbol *cf_find_symbol(byte *c);