summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaria Matejka <mq@ucw.cz>2022-05-02 20:29:03 +0200
committerMaria Matejka <mq@ucw.cz>2022-05-04 15:38:42 +0200
commit165156beeb2926472bbceca3c103aacc3f81a8cc (patch)
tree483ee32846c8758ded4b8c4bfeea3d3ae07a21d2
parentcf07d8ad79273a3bbf0617c17e438602e4b64ece (diff)
Conf: Symbols are properly scoped
Now there is a persistent root symbol scope and all scopes have their symbol hashes to store local symbols and not leak any symbol out.
-rw-r--r--conf/cf-lex.l49
-rw-r--r--conf/conf.c3
-rw-r--r--conf/conf.h18
-rw-r--r--nest/cmds.c23
-rw-r--r--nest/config.Y2
5 files changed, 54 insertions, 41 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 75e1ceeb..bd424c69 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -77,18 +77,18 @@ static uint cf_hash(const byte *c);
#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_ORDER 6 /* Initial */
+#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;
@@ -587,41 +587,39 @@ 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;
}
/**
- * cf_find_symbol - find a symbol by name
- * @cfg: specificed config
+ * 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 current scope, then the second recent one
+ * 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_symbol(const struct config *cfg, const byte *c)
+cf_find_symbol_scope(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;
-
- /* 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)))
- return s;
+ /* Find the symbol here or anywhere below */
+ while (scope)
+ if (scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c, 1)))
+ return s;
+ else
+ scope = scope->next;
return NULL;
}
@@ -638,7 +636,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_symbol_scope(conf_this_scope, c) ?: cf_new_symbol(c);
}
/**
@@ -718,6 +716,8 @@ cf_lex_init_kh(void)
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));
}
/**
@@ -753,6 +753,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;
}
/**
diff --git a/conf/conf.c b/conf/conf.c
index 0230053b..580a6472 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -168,7 +168,6 @@ int
cli_parse(struct config *c)
{
int done = 0;
- c->fallback = config;
new_config = c;
cfg_mem = c->mem;
if (setjmp(conf_jmpbuf))
@@ -179,7 +178,6 @@ cli_parse(struct config *c)
done = 1;
cleanup:
- c->fallback = NULL;
new_config = NULL;
cfg_mem = NULL;
return done;
@@ -522,7 +520,6 @@ order_shutdown(int gr)
init_list(&c->tables);
init_list(&c->symbols);
memset(c->def_tables, 0, sizeof(c->def_tables));
- HASH_INIT(c->sym_hash, c->pool, 4);
c->shutdown = 1;
c->gr_down = gr;
diff --git a/conf/conf.h b/conf/conf.h
index 55cb9c58..2700295b 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -16,7 +16,6 @@
#include "lib/timer.h"
/* Configuration structure */
-
struct config {
pool *pool; /* Pool the configuration is stored in */
linpool *mem; /* Linear pool containing configuration data */
@@ -54,8 +53,7 @@ struct config {
char *err_file_name; /* File name containing error */
char *file_name; /* Name of main configuration file */
int file_fd; /* File descriptor of main configuration file */
- HASH(struct symbol) sym_hash; /* Lexer: symbol hash table */
- struct config *fallback; /* Link to regular config for CLI parsing */
+
struct sym_scope *root_scope; /* Scope for root symbols */
int obstacle_count; /* Number of items blocking freeing of this config */
int shutdown; /* This is a pseudo-config for daemon shutdown */
@@ -133,10 +131,15 @@ struct symbol {
struct sym_scope {
struct sym_scope *next; /* Next on scope stack */
struct symbol *name; /* Name of this scope */
+
+ HASH(struct symbol) hash; /* Local symbol hash */
+
uint slots; /* Variable slots */
int active; /* Currently entered */
};
+extern struct sym_scope *global_root_scope;
+
struct bytestring {
size_t length;
byte data[];
@@ -185,7 +188,14 @@ 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_symbol_scope(const struct sym_scope *scope, const byte *c);
+static inline struct symbol *cf_find_symbol_cfg(const struct config *cfg, const byte *c)
+{ return cf_find_symbol_scope(cfg->root_scope, c); }
+
+#define cf_find_symbol(where, what) _Generic(*(where), \
+ struct config: cf_find_symbol_cfg, \
+ struct sym_scope: cf_find_symbol_scope \
+ )((where), (what))
struct symbol *cf_get_symbol(const byte *c);
struct symbol *cf_default_name(char *template, int *counter);
diff --git a/nest/cmds.c b/nest/cmds.c
index 99a7bbfe..092be48a 100644
--- a/nest/cmds.c
+++ b/nest/cmds.c
@@ -51,17 +51,18 @@ cmd_show_symbols(struct sym_show_data *sd)
cli_msg(1010, "%-8s\t%s", sd->sym->name, cf_symbol_class_name(sd->sym));
else
{
- HASH_WALK(config->sym_hash, next, sym)
- {
- if (!sym->scope->active)
- continue;
-
- if (sd->type && (sym->class != sd->type))
- continue;
-
- cli_msg(-1010, "%-8s\t%s", sym->name, cf_symbol_class_name(sym));
- }
- HASH_WALK_END;
+ for (const struct sym_scope *scope = config->root_scope; scope; scope = scope->next)
+ HASH_WALK(scope->hash, next, sym)
+ {
+ if (!sym->scope->active)
+ continue;
+
+ if (sd->type && (sym->class != sd->type))
+ continue;
+
+ cli_msg(-1010, "%-8s\t%s", sym->name, cf_symbol_class_name(sym));
+ }
+ HASH_WALK_END;
cli_msg(0, "");
}
diff --git a/nest/config.Y b/nest/config.Y
index b597b332..12fd01a2 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -638,7 +638,7 @@ r_args:
$$ = cfg_allocz(sizeof(struct rt_show_data));
init_list(&($$->tables));
$$->filter = FILTER_ACCEPT;
- $$->running_on_config = new_config->fallback;
+ $$->running_on_config = config;
}
| r_args net_any {
$$ = $1;