From 72f3189ca590c362fae1fd85f5abc27f9af50ea0 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Fri, 9 Jun 2023 12:49:19 +0200 Subject: [PATCH] Conf: Keywords have their default symbols This avoids unnecessary collapsed soft scopes caused by keyword symbol multiallocation. --- conf/cf-lex.l | 65 ++++++++++++++++++-------------------------- conf/conf.h | 2 ++ conf/gen_keywords.m4 | 8 +++--- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/conf/cf-lex.l b/conf/cf-lex.l index cd7695fc..bc7703a3 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -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) diff --git a/conf/conf.h b/conf/conf.h index fe8ee5bf..12f1a6b3 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -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) diff --git a/conf/gen_keywords.m4 b/conf/gen_keywords.m4 index 53226e4d..a1be5847 100644 --- a/conf/gen_keywords.m4 +++ b/conf/gen_keywords.m4 @@ -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