0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-08 12:18:42 +00:00

Conf: Keywords have their default symbols

This avoids unnecessary collapsed soft scopes caused by keyword symbol multiallocation.
This commit is contained in:
Maria Matejka 2023-06-09 12:49:19 +02:00 committed by Igor Putovny
parent 51e8996fff
commit 7e6a8392ce
3 changed files with 32 additions and 43 deletions

View 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;
@ -587,14 +579,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));
@ -695,36 +692,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));
}
/**
@ -738,8 +719,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)

View 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)

View 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')
@ -34,7 +34,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')
@ -42,8 +42,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