]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Conf: Symbols are properly scoped
authorMaria Matejka <mq@ucw.cz>
Mon, 2 May 2022 18:29:03 +0000 (20:29 +0200)
committerMaria Matejka <mq@ucw.cz>
Wed, 4 May 2022 13:38:42 +0000 (15:38 +0200)
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.

conf/cf-lex.l
conf/conf.c
conf/conf.h
nest/cmds.c
nest/config.Y

index 75e1ceebd7159f8592217cba418cf227622c9f7c..bd424c69be492c10efcc8e60140b5883a097f140 100644 (file)
@@ -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;
 }
 
 /**
index 0230053b884277e5d4a3c0418c581672f429037e..580a6472bcab57e8e31a35af26c5d151450bec53 100644 (file)
@@ -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;
 
index 55cb9c58780617007bdcb8b1bbe37cfbe39e7928..2700295b112f2fcb528f0e2d57f0c34a33122d28 100644 (file)
@@ -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);
index 99a7bbfe95964e87de67f867c69260198f3b6978..092be48a51dbadb0d6f07e049581146da90ec1a8 100644 (file)
@@ -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, "");
   }
index b597b332ad358b63b1107391cadf8f6c2ca1557f..12fd01a24f5c76e8420fec27d8715eb33a15c49a 100644 (file)
@@ -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;