diff options
Diffstat (limited to 'conf')
-rw-r--r-- | conf/cf-lex.l | 39 | ||||
-rw-r--r-- | conf/conf.h | 7 | ||||
-rw-r--r-- | conf/confbase.Y | 4 | ||||
-rw-r--r-- | conf/gen_parser.m4 | 4 |
4 files changed, 36 insertions, 18 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l index ceedee8a..9555949d 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -73,10 +73,10 @@ 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->active +#define SYM_KEY(n) n->name, n->scope #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) +#define SYM_FN(k,s) cf_hash(k) ^ ptr_hash(s) #define SYM_ORDER 6 /* Initial */ #define SYM_REHASH sym_rehash @@ -601,30 +601,36 @@ cf_new_symbol(const byte *c) return s; } +struct symbol * +cf_symbol_from_keyword(const struct keyword *kw) +{ return cf_new_symbol(kw->name); } + /** - * cf_find_symbol - find a symbol by name + * cf_find_local_symbol - find a symbol by name * @cfg: specificed config + * @scope: specified symbol scope * @c: symbol name * * This functions searches the symbol table in the config @cfg for a symbol of - * given name. First it examines the current scope, then the second recent one + * given name. First it examines the scope @scope, then the parent scope * 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_symbol(const struct config *cfg, const byte *c) +cf_find_local_symbol(const struct config *cfg, const struct sym_scope *scope, const byte *c) { struct symbol *s; - if (cfg->sym_hash.data && - (s = HASH_FIND(cfg->sym_hash, SYM, c, 1))) - return 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, 1))) + (s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, cfg->fallback->root_scope))) return s; return NULL; @@ -642,7 +648,7 @@ cf_find_symbol(const struct config *cfg, const byte *c) struct symbol * cf_get_symbol(const byte *c) { - return cf_find_symbol(new_config, c) ?: cf_new_symbol(c); + return cf_find_local_symbol(new_config, conf_this_scope, c) ?: cf_new_symbol(c); } /** @@ -690,18 +696,23 @@ static enum yytokentype cf_lex_symbol(const char *data) { /* Have we defined such a symbol? */ - struct symbol *sym = cf_get_symbol(data); - cf_lval.s = sym; + struct symbol *sym = cf_find_local_symbol(new_config, conf_this_scope, data); - if (sym->class != SYM_VOID) + if (sym && (sym->class != SYM_VOID)) + { + cf_lval.s = sym; return CF_SYM_KNOWN; + } /* Is it a 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; @@ -710,7 +721,7 @@ cf_lex_symbol(const char *data) } /* OK, undefined symbol */ - cf_lval.s = sym; + cf_lval.s = cf_new_symbol(data); return CF_SYM_UNDEFINED; } diff --git a/conf/conf.h b/conf/conf.h index b409750e..d40f955e 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -187,7 +187,12 @@ int cf_lex(void); void cf_lex_init(int is_cli, struct config *c); void cf_lex_unwind(void); -struct symbol *cf_find_symbol(const struct config *cfg, const byte *c); +struct symbol *cf_find_local_symbol(const struct config *cfg, const struct sym_scope *scope, const byte *c); +static inline struct symbol *cf_find_symbol(const struct config *cfg, const byte *c) +{ return cf_find_local_symbol(cfg, cfg->root_scope, c); } + +struct keyword; +struct symbol *cf_symbol_from_keyword(const struct keyword *kw); struct symbol *cf_get_symbol(const byte *c); struct symbol *cf_default_name(char *template, int *counter); diff --git a/conf/confbase.Y b/conf/confbase.Y index 1d5738ff..3e8f5807 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -61,6 +61,7 @@ CF_DECLS net_addr net; net_addr *net_ptr; struct symbol *s; + struct keyword *kw; const char *t; struct rtable_config *r; struct channel_config *cc; @@ -117,6 +118,7 @@ CF_DECLS %type <t> text opttext %type <s> symbol +%type <kw> kw_sym %nonassoc PREFIX_DUMMY %left AND OR @@ -172,7 +174,7 @@ expr_us: | expr US { $$ = $1 US_; } ; -symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN ; +symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN | kw_sym { $$ = cf_symbol_from_keyword($1); } ; /* Switches */ diff --git a/conf/gen_parser.m4 b/conf/gen_parser.m4 index af4b1455..7a2a9de4 100644 --- a/conf/gen_parser.m4 +++ b/conf/gen_parser.m4 @@ -29,9 +29,9 @@ m4_define(CF_END, `m4_divert(-1)') m4_define(CF_itera, `m4_ifelse($#, 1, [[CF_iter($1)]], [[CF_iter($1)[[]]CF_itera(m4_shift($@))]])') m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)') -# Keywords act as untyped %token +# Keywords act as %token<kw> m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])') -m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token<s>[[]]CF_toks +m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token<kw>[[]]CF_toks )DNL') # CLI commands |