diff options
author | Maria Matejka <mq@ucw.cz> | 2022-05-02 20:29:03 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2023-09-12 15:20:50 +0200 |
commit | 8e177cf35b582ec973c1abce4709c80847adb711 (patch) | |
tree | fcf14a0c11d2ae7d5ae67229c658d579e61c32fc /conf/cf-lex.l | |
parent | a5a6de581b79641b21b26277580cb4cc118da7ea (diff) |
Conf: Symbol hashes for all scopes
This is a backport cherry-pick of commits
165156beeb2926472bbceca3c103aacc3f81a8cc
cce974e8ea992d0e6d2f649eca7880b436d91d71
from the v3.0 branch as we need symbol hashes directly inside their
scopes for more general usage than before.
Diffstat (limited to 'conf/cf-lex.l')
-rw-r--r-- | conf/cf-lex.l | 81 |
1 files changed, 39 insertions, 42 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l index e789e864..8637de40 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -73,22 +73,22 @@ static uint cf_hash(const byte *c); #define KW_FN(k) cf_hash(k) #define KW_ORDER 8 /* Fixed */ -#define SYM_KEY(n) n->name, n->scope +#define SYM_KEY(n) n->name #define SYM_NEXT(n) n->next -#define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2 -#define SYM_FN(k,s) cf_hash(k) ^ ptr_hash(s) -#define SYM_ORDER 6 /* Initial */ +#define SYM_EQ(a,b) !strcmp(a,b) +#define SYM_FN(k) cf_hash(k) +#define SYM_ORDER 4 /* Initial */ #define SYM_REHASH sym_rehash -#define SYM_PARAMS /8, *1, 2, 2, 6, 20 +#define SYM_PARAMS /8, *1, 2, 2, 4, 20 HASH_DEFINE_REHASH_FN(SYM, struct symbol) HASH(struct keyword) kw_hash; - struct sym_scope *conf_this_scope; +struct sym_scope *global_root_scope; linpool *cfg_mem; @@ -580,12 +580,13 @@ cf_new_symbol(const byte *c) *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, }; strcpy(s->name, c); - if (!new_config->sym_hash.data) - HASH_INIT(new_config->sym_hash, new_config->pool, SYM_ORDER); + if (!conf_this_scope->hash.data) + HASH_INIT(conf_this_scope->hash, new_config->pool, SYM_ORDER); - HASH_INSERT2(new_config->sym_hash, SYM, new_config->pool, s); + HASH_INSERT2(conf_this_scope->hash, SYM, new_config->pool, s); - add_tail(&(new_config->symbols), &(s->n)); + if (conf_this_scope == new_config->root_scope) + add_tail(&(new_config->symbols), &(s->n)); return s; } @@ -595,32 +596,27 @@ cf_symbol_from_keyword(const struct keyword *kw) { return cf_new_symbol(kw->name); } /** - * cf_find_local_symbol - find a symbol by name - * @cfg: specificed config - * @scope: specified symbol scope + * cf_find_symbol_scope - find a symbol by name + * @scope: config scope * @c: symbol name * - * This functions searches the symbol table in the config @cfg for a symbol of - * given name. First it examines the scope @scope, then the parent scope + * This functions searches the symbol table in the scope @scope for a symbol of + * given name. First it examines the current scope, then the underlying one * and so on until it either finds the symbol and returns a pointer to its * &symbol structure or reaches the end of the scope chain and returns %NULL to * signify no match. */ struct symbol * -cf_find_local_symbol(const struct config *cfg, const struct sym_scope *scope, const byte *c) +cf_find_symbol_scope(const struct sym_scope *scope, const byte *c) { struct symbol *s; - if (cfg->sym_hash.data) - for (; scope; scope = scope->next) - if (s = HASH_FIND(cfg->sym_hash, SYM, c, scope)) - return s; - - /* In CLI command parsing, fallback points to the current config, otherwise it is NULL. */ - if (cfg->fallback && - cfg->fallback->sym_hash.data && - (s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, cfg->fallback->root_scope))) - return s; + /* Find the symbol here or anywhere below */ + while (scope) + if (scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c))) + return s; + else + scope = scope->next; return NULL; } @@ -637,7 +633,7 @@ cf_find_local_symbol(const struct config *cfg, const struct sym_scope *scope, co struct symbol * cf_get_symbol(const byte *c) { - return cf_find_local_symbol(new_config, conf_this_scope, c) ?: cf_new_symbol(c); + return cf_find_symbol_scope(conf_this_scope, c) ?: cf_new_symbol(c); } /** @@ -685,23 +681,15 @@ static enum yytokentype cf_lex_symbol(const char *data) { /* Have we defined such a symbol? */ - struct symbol *sym = cf_find_local_symbol(new_config, conf_this_scope, data); - - if (sym && (sym->class != SYM_VOID)) - { - cf_lval.s = sym; - return CF_SYM_KNOWN; - } + struct symbol *sym = cf_get_symbol(data); + cf_lval.s = sym; - /* Is it a keyword? */ + /* Is it a keyword? Prefer the keyword. */ struct keyword *k = HASH_FIND(kw_hash, KW, data); if (k) { if (k->value > 0) - { - cf_lval.kw = k; return k->value; - } else { cf_lval.i = -k->value; @@ -709,19 +697,23 @@ cf_lex_symbol(const char *data) } } - /* OK, undefined symbol */ - cf_lval.s = cf_new_symbol(data); - return CF_SYM_UNDEFINED; + /* OK, only a symbol. */ + if (sym->class == SYM_VOID) + return CF_SYM_UNDEFINED; + else + return CF_SYM_KNOWN; } static void cf_lex_init_kh(void) { - HASH_INIT(kw_hash, config_pool, KW_ORDER); + HASH_INIT(kw_hash, &root_pool, KW_ORDER); struct keyword *k; for (k=keyword_list; k->name; k++) HASH_INSERT(kw_hash, KW, k); + + global_root_scope = mb_allocz(&root_pool, sizeof(*global_root_scope)); } /** @@ -757,6 +749,11 @@ cf_lex_init(int is_cli, struct config *c) c->root_scope = cfg_allocz(sizeof(struct sym_scope)); conf_this_scope = c->root_scope; conf_this_scope->active = 1; + + if (is_cli) + conf_this_scope->next = config->root_scope; + else + conf_this_scope->next = global_root_scope; } /** |