mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
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.
This commit is contained in:
parent
cf07d8ad79
commit
165156beeb
@ -77,18 +77,18 @@ static uint cf_hash(const byte *c);
|
|||||||
#define SYM_NEXT(n) n->next
|
#define SYM_NEXT(n) n->next
|
||||||
#define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2
|
#define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2
|
||||||
#define SYM_FN(k,s) cf_hash(k)
|
#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_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_DEFINE_REHASH_FN(SYM, struct symbol)
|
||||||
|
|
||||||
HASH(struct keyword) kw_hash;
|
HASH(struct keyword) kw_hash;
|
||||||
|
|
||||||
|
|
||||||
struct sym_scope *conf_this_scope;
|
struct sym_scope *conf_this_scope;
|
||||||
|
struct sym_scope *global_root_scope;
|
||||||
|
|
||||||
linpool *cfg_mem;
|
linpool *cfg_mem;
|
||||||
|
|
||||||
@ -587,41 +587,39 @@ cf_new_symbol(const byte *c)
|
|||||||
*s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
|
*s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
|
||||||
strcpy(s->name, c);
|
strcpy(s->name, c);
|
||||||
|
|
||||||
if (!new_config->sym_hash.data)
|
if (!conf_this_scope->hash.data)
|
||||||
HASH_INIT(new_config->sym_hash, new_config->pool, SYM_ORDER);
|
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;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cf_find_symbol - find a symbol by name
|
* cf_find_symbol_scope - find a symbol by name
|
||||||
* @cfg: specificed config
|
* @scope: config scope
|
||||||
* @c: symbol name
|
* @c: symbol name
|
||||||
*
|
*
|
||||||
* This functions searches the symbol table in the config @cfg for a symbol of
|
* This functions searches the symbol table in the scope @scope for a symbol of
|
||||||
* given name. First it examines the current scope, then the second recent one
|
* 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
|
* 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
|
* &symbol structure or reaches the end of the scope chain and returns %NULL to
|
||||||
* signify no match.
|
* signify no match.
|
||||||
*/
|
*/
|
||||||
struct symbol *
|
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;
|
struct symbol *s;
|
||||||
|
|
||||||
if (cfg->sym_hash.data &&
|
/* Find the symbol here or anywhere below */
|
||||||
(s = HASH_FIND(cfg->sym_hash, SYM, c, 1)))
|
while (scope)
|
||||||
return s;
|
if (scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c, 1)))
|
||||||
|
return s;
|
||||||
/* In CLI command parsing, fallback points to the current config, otherwise it is NULL. */
|
else
|
||||||
if (cfg->fallback &&
|
scope = scope->next;
|
||||||
cfg->fallback->sym_hash.data &&
|
|
||||||
(s = HASH_FIND(cfg->fallback->sym_hash, SYM, c, 1)))
|
|
||||||
return s;
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -638,7 +636,7 @@ cf_find_symbol(const struct config *cfg, const byte *c)
|
|||||||
struct symbol *
|
struct symbol *
|
||||||
cf_get_symbol(const byte *c)
|
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;
|
struct keyword *k;
|
||||||
for (k=keyword_list; k->name; k++)
|
for (k=keyword_list; k->name; k++)
|
||||||
HASH_INSERT(kw_hash, KW, 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));
|
c->root_scope = cfg_allocz(sizeof(struct sym_scope));
|
||||||
conf_this_scope = c->root_scope;
|
conf_this_scope = c->root_scope;
|
||||||
conf_this_scope->active = 1;
|
conf_this_scope->active = 1;
|
||||||
|
|
||||||
|
if (is_cli)
|
||||||
|
conf_this_scope->next = config->root_scope;
|
||||||
|
else
|
||||||
|
conf_this_scope->next = global_root_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -168,7 +168,6 @@ int
|
|||||||
cli_parse(struct config *c)
|
cli_parse(struct config *c)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
c->fallback = config;
|
|
||||||
new_config = c;
|
new_config = c;
|
||||||
cfg_mem = c->mem;
|
cfg_mem = c->mem;
|
||||||
if (setjmp(conf_jmpbuf))
|
if (setjmp(conf_jmpbuf))
|
||||||
@ -179,7 +178,6 @@ cli_parse(struct config *c)
|
|||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
c->fallback = NULL;
|
|
||||||
new_config = NULL;
|
new_config = NULL;
|
||||||
cfg_mem = NULL;
|
cfg_mem = NULL;
|
||||||
return done;
|
return done;
|
||||||
@ -522,7 +520,6 @@ order_shutdown(int gr)
|
|||||||
init_list(&c->tables);
|
init_list(&c->tables);
|
||||||
init_list(&c->symbols);
|
init_list(&c->symbols);
|
||||||
memset(c->def_tables, 0, sizeof(c->def_tables));
|
memset(c->def_tables, 0, sizeof(c->def_tables));
|
||||||
HASH_INIT(c->sym_hash, c->pool, 4);
|
|
||||||
c->shutdown = 1;
|
c->shutdown = 1;
|
||||||
c->gr_down = gr;
|
c->gr_down = gr;
|
||||||
|
|
||||||
|
18
conf/conf.h
18
conf/conf.h
@ -16,7 +16,6 @@
|
|||||||
#include "lib/timer.h"
|
#include "lib/timer.h"
|
||||||
|
|
||||||
/* Configuration structure */
|
/* Configuration structure */
|
||||||
|
|
||||||
struct config {
|
struct config {
|
||||||
pool *pool; /* Pool the configuration is stored in */
|
pool *pool; /* Pool the configuration is stored in */
|
||||||
linpool *mem; /* Linear pool containing configuration data */
|
linpool *mem; /* Linear pool containing configuration data */
|
||||||
@ -54,8 +53,7 @@ struct config {
|
|||||||
char *err_file_name; /* File name containing error */
|
char *err_file_name; /* File name containing error */
|
||||||
char *file_name; /* Name of main configuration file */
|
char *file_name; /* Name of main configuration file */
|
||||||
int file_fd; /* File descriptor 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 */
|
struct sym_scope *root_scope; /* Scope for root symbols */
|
||||||
int obstacle_count; /* Number of items blocking freeing of this config */
|
int obstacle_count; /* Number of items blocking freeing of this config */
|
||||||
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
||||||
@ -133,10 +131,15 @@ struct symbol {
|
|||||||
struct sym_scope {
|
struct sym_scope {
|
||||||
struct sym_scope *next; /* Next on scope stack */
|
struct sym_scope *next; /* Next on scope stack */
|
||||||
struct symbol *name; /* Name of this scope */
|
struct symbol *name; /* Name of this scope */
|
||||||
|
|
||||||
|
HASH(struct symbol) hash; /* Local symbol hash */
|
||||||
|
|
||||||
uint slots; /* Variable slots */
|
uint slots; /* Variable slots */
|
||||||
int active; /* Currently entered */
|
int active; /* Currently entered */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct sym_scope *global_root_scope;
|
||||||
|
|
||||||
struct bytestring {
|
struct bytestring {
|
||||||
size_t length;
|
size_t length;
|
||||||
byte data[];
|
byte data[];
|
||||||
@ -185,7 +188,14 @@ int cf_lex(void);
|
|||||||
void cf_lex_init(int is_cli, struct config *c);
|
void cf_lex_init(int is_cli, struct config *c);
|
||||||
void cf_lex_unwind(void);
|
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_get_symbol(const byte *c);
|
||||||
struct symbol *cf_default_name(char *template, int *counter);
|
struct symbol *cf_default_name(char *template, int *counter);
|
||||||
|
19
nest/cmds.c
19
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));
|
cli_msg(1010, "%-8s\t%s", sd->sym->name, cf_symbol_class_name(sd->sym));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HASH_WALK(config->sym_hash, next, sym)
|
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 (!sym->scope->active)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (sd->type && (sym->class != sd->type))
|
if (sd->type && (sym->class != sd->type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cli_msg(-1010, "%-8s\t%s", sym->name, cf_symbol_class_name(sym));
|
cli_msg(-1010, "%-8s\t%s", sym->name, cf_symbol_class_name(sym));
|
||||||
}
|
}
|
||||||
HASH_WALK_END;
|
HASH_WALK_END;
|
||||||
|
|
||||||
cli_msg(0, "");
|
cli_msg(0, "");
|
||||||
}
|
}
|
||||||
|
@ -638,7 +638,7 @@ r_args:
|
|||||||
$$ = cfg_allocz(sizeof(struct rt_show_data));
|
$$ = cfg_allocz(sizeof(struct rt_show_data));
|
||||||
init_list(&($$->tables));
|
init_list(&($$->tables));
|
||||||
$$->filter = FILTER_ACCEPT;
|
$$->filter = FILTER_ACCEPT;
|
||||||
$$->running_on_config = new_config->fallback;
|
$$->running_on_config = config;
|
||||||
}
|
}
|
||||||
| r_args net_any {
|
| r_args net_any {
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
|
Loading…
Reference in New Issue
Block a user