diff options
Diffstat (limited to 'conf')
-rw-r--r-- | conf/cf-lex.l | 59 | ||||
-rw-r--r-- | conf/conf.c | 2 | ||||
-rw-r--r-- | conf/conf.h | 3 |
3 files changed, 38 insertions, 26 deletions
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,10 +255,25 @@ cf_define_symbol(struct symbol *sym, int type, void *def) sym->def = def; } +static void +cf_lex_init_kh(void) +{ + struct keyword *k; + + for(k=keyword_list; k->name; k++) + { + unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1); + k->next = kw_hash[h]; + kw_hash[h] = k; + } + kw_hash_inited = 1; +} + void cf_lex_init(int is_cli) { - sym_hash = NULL; + if (!kw_hash_inited) + cf_lex_init_kh(); conf_lino = 1; yyrestart(NULL); if (is_cli) @@ -261,19 +285,6 @@ cf_lex_init(int is_cli) } void -cf_lex_init_tables(void) -{ - struct keyword *k; - - for(k=keyword_list; k->name; k++) - { - unsigned h = cf_hash(k->name) & (KW_HASH_SIZE-1); - k->next = kw_hash[h]; - kw_hash[h] = k; - } -} - -void cf_push_scope(struct symbol *sym) { struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope)); 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); |