summaryrefslogtreecommitdiff
path: root/conf
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2023-04-27 18:20:49 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2023-04-27 18:41:01 +0200
commita8a64ca0fed41c78376b27880e934296bd3c3a7f (patch)
treeb07dce29bd01d67438438278bc8af89879faba12 /conf
parent9b471e72d75c154f3b8c4fa134c7c9f1a55fe27f (diff)
Conf: Improve handling of keywords
For whatever reason, parser allocated a symbol for every parsed keyword in each scope. That wasted time and memory. The effect is worsened with recent changes allowing local scopes, so keywords often promote soft scopes (with no symbols) to real scopes. Do not allocate a symbol for a keyword. Take care of keywords that could be promoted to symbols (kw_sym) and do it explicitly.
Diffstat (limited to 'conf')
-rw-r--r--conf/cf-lex.l17
-rw-r--r--conf/conf.h3
-rw-r--r--conf/confbase.Y4
-rw-r--r--conf/gen_parser.m44
4 files changed, 21 insertions, 7 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 0a02dd73..9555949d 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -601,6 +601,10 @@ 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_local_symbol - find a symbol by name
* @cfg: specificed config
@@ -692,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;
@@ -712,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 cb47e7d0..d40f955e 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -191,6 +191,9 @@ struct symbol *cf_find_local_symbol(const struct config *cfg, const struct sym_s
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);
struct symbol *cf_localize_symbol(struct symbol *sym);
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