]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Conf: Keywords have their default symbols
authorMaria Matejka <mq@ucw.cz>
Fri, 9 Jun 2023 10:49:19 +0000 (12:49 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 12 Sep 2023 13:21:14 +0000 (15:21 +0200)
This avoids unnecessary collapsed soft scopes caused by keyword symbol multiallocation.

conf/cf-lex.l
conf/conf.h
conf/gen_keywords.m4

index 8637de4015bcf394ffd39ba49b423268829d08b9..fb2ffb325745ef553853ff3039ef3e583d8917ce 100644 (file)
@@ -54,7 +54,6 @@
 struct keyword {
   byte *name;
   int value;
-  struct keyword *next;
 };
 
 #include "conf/keywords.h"
@@ -67,12 +66,6 @@ struct keyword {
 
 static uint cf_hash(const byte *c);
 
-#define KW_KEY(n)              n->name
-#define KW_NEXT(n)             n->next
-#define KW_EQ(a,b)             !strcmp(a,b)
-#define KW_FN(k)               cf_hash(k)
-#define KW_ORDER               8 /* Fixed */
-
 #define SYM_KEY(n)             n->name
 #define SYM_NEXT(n)            n->next
 #define SYM_EQ(a,b)            !strcmp(a,b)
@@ -85,10 +78,9 @@ static uint cf_hash(const byte *c);
 
 HASH_DEFINE_REHASH_FN(SYM, struct symbol)
 
-HASH(struct keyword) kw_hash;
-
 struct sym_scope *conf_this_scope;
 struct sym_scope *global_root_scope;
+static pool *global_root_scope_pool;
 
 linpool *cfg_mem;
 
@@ -576,14 +568,19 @@ cf_new_symbol(const byte *c)
 
   cf_swap_soft_scope();
 
-  s = cfg_allocz(sizeof(struct symbol) + l + 1);
+  pool *p = new_config->pool;
+
+  if (conf_this_scope == global_root_scope)
+    s = mb_allocz(p = global_root_scope_pool, sizeof(struct symbol) + l + 1);
+  else
+    s = cfg_allocz(sizeof(struct symbol) + l + 1);
   *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
   strcpy(s->name, c);
 
   if (!conf_this_scope->hash.data)
-    HASH_INIT(conf_this_scope->hash, new_config->pool, SYM_ORDER);
+    HASH_INIT(conf_this_scope->hash, p, SYM_ORDER);
 
-  HASH_INSERT2(conf_this_scope->hash, SYM, new_config->pool, s);
+  HASH_INSERT2(conf_this_scope->hash, SYM, p, s);
 
   if (conf_this_scope == new_config->root_scope)
     add_tail(&(new_config->symbols), &(s->n));
@@ -684,36 +681,20 @@ cf_lex_symbol(const char *data)
   struct symbol *sym = cf_get_symbol(data);
   cf_lval.s = sym;
 
-  /* Is it a keyword? Prefer the keyword. */
-  struct keyword *k = HASH_FIND(kw_hash, KW, data);
-  if (k)
+  switch (sym->class)
   {
-    if (k->value > 0)
-      return k->value;
-    else
+    case SYM_KEYWORD:
     {
-      cf_lval.i = -k->value;
+      int val = sym->keyword->value;
+      if (val > 0) return val;
+      cf_lval.i = -val;
       return ENUM;
     }
+    case SYM_VOID:
+      return CF_SYM_UNDEFINED;
+    default:
+      return CF_SYM_KNOWN;
   }
-
-  /* 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, &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));
 }
 
 /**
@@ -727,8 +708,14 @@ cf_lex_init_kh(void)
 void
 cf_lex_init(int is_cli, struct config *c)
 {
-  if (!kw_hash.data)
-    cf_lex_init_kh();
+  if (!global_root_scope_pool)
+  {
+    global_root_scope_pool = rp_new(&root_pool, "Keywords pool");
+    conf_this_scope = global_root_scope = mb_allocz(global_root_scope_pool, sizeof(*global_root_scope));
+
+    for (const struct keyword *k = keyword_list; k->name; k++)
+      cf_define_symbol(cf_get_symbol(k->name), SYM_KEYWORD, keyword, k);
+  }
 
   ifs_head = ifs = push_ifs(NULL);
   if (!is_cli)
index fe8ee5bf2f31aa8863256cec4b4397fe55665cb2..12f1a6b3948d5c9fc5b8b783279d42686a9597f1 100644 (file)
@@ -123,6 +123,7 @@ struct symbol {
     struct f_dynamic_attr *attribute;  /* For SYM_ATTRIBUTE */
     struct f_val *val;                 /* For SYM_CONSTANT */
     uint offset;                       /* For SYM_VARIABLE */
+    const struct keyword *keyword;     /* For SYM_KEYWORD */
   };
 
   char name[0];
@@ -157,6 +158,7 @@ struct bytestring {
 #define SYM_FILTER 4
 #define SYM_TABLE 5
 #define SYM_ATTRIBUTE 6
+#define SYM_KEYWORD 7
 
 #define SYM_VARIABLE 0x100     /* 0x100-0x1ff are variable types */
 #define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff)
index 4ab6d50dbac13451ea71ff24609bae81ba01d8fd..4e8651f6d426d3914594e66ef445c21e146cc488 100644 (file)
@@ -23,7 +23,7 @@ m4_define(CF_DECLS, `m4_divert(-1)')
 m4_define(CF_DEFINES, `m4_divert(-1)')
 
 # Keywords are translated to C initializers
-m4_define(CF_handle_kw, `m4_divert(1){ "m4_translit($1,[[A-Z]],[[a-z]])", $1, NULL },
+m4_define(CF_handle_kw, `m4_divert(1){ "m4_translit($1,[[A-Z]],[[a-z]])", $1 },
 m4_divert(-1)')
 m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)CF_handle_kw($1)]])')
 m4_define(CF_KEYWORDS, `CF_iterate([[CF_keywd]], [[$@]])DNL')
@@ -35,7 +35,7 @@ m4_define(CF_CLI, `CF_KEYWORDS(m4_translit($1, [[ ]], [[,]]))
 
 # Enums are translated to C initializers: use CF_ENUM(typename, prefix, values)
 # For different prefix: CF_ENUM_PX(typename, external prefix, C prefix, values)
-m4_define(CF_enum, `m4_divert(1){ "CF_enum_prefix_ext[[]]$1", -((CF_enum_type<<16) | CF_enum_prefix_int[[]]$1), NULL },
+m4_define(CF_enum, `m4_divert(1){ "CF_enum_prefix_ext[[]]$1", -((CF_enum_type<<16) | CF_enum_prefix_int[[]]$1) },
 m4_divert(-1)')
 m4_define(CF_ENUM, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$2)CF_iterate([[CF_enum]], [[m4_shift(m4_shift($@))]])DNL')
 m4_define(CF_ENUM_PX, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_ext]],$2)m4_define([[CF_enum_prefix_int]],$3)CF_iterate([[CF_enum]], [[m4_shift(m4_shift(m4_shift($@)))]])DNL')
@@ -43,8 +43,8 @@ m4_define(CF_ENUM_PX, `m4_define([[CF_enum_type]],$1)m4_define([[CF_enum_prefix_
 # After all configuration templates end, we generate the 
 m4_m4wrap(`
 m4_divert(0)
-static struct keyword keyword_list[] = {
-m4_undivert(1){ NULL, -1, NULL } };
+static const struct keyword keyword_list[] = {
+m4_undivert(1){ NULL, -1 } };
 ')
 
 # As we are processing C source, we must access all M4 primitives via