if (l > SYM_MAX_LEN)
cf_error("Symbol too long");
- cf_swap_soft_scope();
-
- s = cfg_allocz(sizeof(struct symbol) + l + 1);
- *s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
+ s = lp_alloc(lp, sizeof(struct symbol) + l + 1);
+ *s = (struct symbol) { .scope = scope, .class = SYM_VOID, };
- strcpy(s->name, c);
+ memcpy(s->name, c, l+1);
- if (!conf_this_scope->hash.data)
- HASH_INIT(conf_this_scope->hash, new_config->pool, SYM_ORDER);
+ if (!scope->hash.data)
+ HASH_INIT(scope->hash, p, SYM_ORDER);
- HASH_INSERT2(conf_this_scope->hash, SYM, new_config->pool, s);
+ HASH_INSERT2(scope->hash, SYM, p, s);
- if (conf_this_scope == new_config->root_scope)
+ if (new_config && (scope == new_config->root_scope))
add_tail(&(new_config->symbols), &(s->n));
return s;
}
}
- def->sym = cf_define_symbol(cf_root_symbol(def->name, &global_filter_scope), SYM_ATTRIBUTE, attribute, def);
+void
+ea_lex_register(struct ea_class *def)
+{
++ def->sym = cf_root_symbol(def->name, &global_filter_scope);
++ def->sym->class = SYM_ATTRIBUTE;
++ def->sym->attribute = def;
+}
+
+void
+ea_lex_unregister(struct ea_class *def)
+{
+ struct symbol *sym = def->sym;
+ HASH_REMOVE2(global_filter_scope.hash, SYM, &root_pool, sym);
+ mb_free(sym);
+ def->sym = NULL;
+}
+
+struct ea_class *
+ea_class_find_by_name(const char *name)
+{
+ if (!global_filter_scope.hash.data)
+ return NULL;
+
+ struct symbol *sym = HASH_FIND(global_filter_scope.hash, SYM, name);
+
+ if (!sym || (sym->class != SYM_ATTRIBUTE))
+ return NULL;
+ else
+ return sym->attribute;
+}
+
/**
* cf_lex_init - initialize the lexer
* @is_cli: true if we're going to parse CLI command, false for configuration
{
if (!global_root_scope_pool)
{
- global_root_scope_pool = rp_new(&root_pool, "Keywords pool");
- linpool *kwlp = lp_new(global_root_scope_pool);
- global_root_scope = lp_allocz(kwlp, sizeof(*global_root_scope));
+ global_root_scope_pool = rp_new(&root_pool, the_bird_domain.the_bird, "Keywords pool");
for (const struct keyword *k = keyword_list; k->name; k++)
- cf_define_symbol(cf_root_symbol(k->name, &global_root_scope), SYM_KEYWORD, keyword, k);
+ {
- struct symbol *sym = cf_new_symbol(global_root_scope, global_root_scope_pool, kwlp, k->name);
- sym->class = SYM_KEYWORD;
- sym->keyword = k;
++ struct symbol *s = cf_root_symbol(k->name, &global_root_scope);
++ s->class = SYM_KEYWORD;
++ s->keyword = k;
+ }
}
ifs_head = ifs = push_ifs(NULL);
else
BEGIN(INITIAL);
- c->root_scope = cfg_allocz(sizeof(struct sym_scope));
- conf_this_scope = c->root_scope;
- conf_this_scope->active = 1;
+ c->root_scope = c->current_scope = cfg_allocz(sizeof(struct sym_scope));
++ c->root_scope->active = 1;
if (is_cli)
- conf_this_scope->next = config->root_scope;
+ c->current_scope->next = config->root_scope;
else
- conf_this_scope->next = &global_filter_scope;
- c->current_scope->next = global_root_scope;
++ c->current_scope->next = &global_filter_scope;
}
/**
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 */
+ int thread_count; /* How many worker threads to prefork */
struct sym_scope *root_scope; /* Scope for root symbols */
- int obstacle_count; /* Number of items blocking freeing of this config */
+ struct sym_scope *current_scope; /* Current scope where we are actually in while parsing */
+ _Atomic int obstacle_count; /* Number of items blocking freeing of this config */
+ event done_event; /* Called when obstacle_count reaches zero */
int shutdown; /* This is a pseudo-config for daemon shutdown */
int gr_down; /* This is a pseudo-config for graceful restart */
btime load_time; /* When we've got this configuration */
definition:
DEFINE symbol '=' term ';' {
- struct f_val *val = cfg_allocz(sizeof(struct f_val));
- *val = cf_eval($4, T_VOID);
+ struct f_val *val = cf_eval($4, T_VOID);
- cf_define_symbol($2, SYM_CONSTANT | val->type, val, val);
+ cf_define_symbol(new_config, $2, SYM_CONSTANT | val->type, val, val);
}
;
CF_GRAMMAR
+conf: FILTER STACKS expr expr ';' {
+ new_config->filter_vstk = $3;
+ new_config->filter_estk = $4;
+ }
+ ;
+
conf: filter_def ;
filter_def:
- FILTER symbol { $2 = cf_define_symbol(new_config, $2, SYM_FILTER, filter, NULL); cf_push_scope( new_config, $2 ); }
- filter_body {
+ FILTER symbol {
- $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL);
++ $2 = cf_define_symbol(new_config, $2, SYM_FILTER, filter, NULL);
+ cf_enter_filters();
- cf_push_scope( $2 );
++ cf_push_scope( new_config, $2 );
+ } filter_body {
struct filter *f = cfg_alloc(sizeof(struct filter));
*f = (struct filter) { .sym = $2, .root = $4 };
$2->filter = f;
- cf_pop_scope();
+ cf_pop_scope(new_config);
+ cf_exit_filters();
}
;
conf: custom_attr ;
custom_attr: ATTRIBUTE type symbol ';' {
- cf_define_symbol(new_config, $3, SYM_ATTRIBUTE, attribute, ca_lookup(new_config->pool, $3->name, $2)->fda);
+ if (($3->class == SYM_ATTRIBUTE) && ($3->scope == new_config->root_scope))
+ cf_error("Duplicate attribute %s definition", $3->name);
+
- cf_define_symbol($3, SYM_ATTRIBUTE, attribute,
++ cf_define_symbol(new_config, $3, SYM_ATTRIBUTE, attribute,
+ ea_register_alloc(new_config->pool, (struct ea_class) {
+ .name = $3->name,
+ .type = $2,
+ })->class);
};
conf: bt_test_suite ;
cf_assert_symbol($1, SYM_FILTER);
$$ = $1->filter;
}
- | { cf_push_scope(new_config, NULL); } filter_body {
+ | {
+ cf_enter_filters();
- cf_push_scope(NULL);
++ cf_push_scope(new_config, NULL);
+ } filter_body {
struct filter *f = cfg_alloc(sizeof(struct filter));
*f = (struct filter) { .root = $2 };
$$ = f;
- cf_pop_scope();
+ cf_pop_scope(new_config);
+ cf_exit_filters();
}
;
function_def:
FUNCTION symbol {
DBG( "Beginning of function %s\n", $2->name );
- $2 = cf_define_symbol($2, SYM_FUNCTION, function, NULL);
+ $2 = cf_define_symbol(new_config, $2, SYM_FUNCTION, function, NULL);
+ cf_enter_filters();
- cf_push_scope($2);
+ cf_push_scope(new_config, $2);
} function_args {
/* Make dummy f_line for storing function prototype */
struct f_line *dummy = cfg_allocz(sizeof(struct f_line));
$6->args = $2->function->args;
$6->arg_list = $2->function->arg_list;
$2->function = $6;
- cf_pop_scope();
+ cf_pop_scope(new_config);
+ cf_exit_filters();
}
;
{
init_list(&c->tables);
- c->def_tables[NET_IP4] = cf_define_symbol(cf_get_symbol("master4"), SYM_TABLE, table, NULL);
- c->def_tables[NET_IP6] = cf_define_symbol(cf_get_symbol("master6"), SYM_TABLE, table, NULL);
- rt_new_table(cf_get_symbol(c, "master4"), NET_IP4);
- rt_new_table(cf_get_symbol(c, "master6"), NET_IP6);
++ c->def_tables[NET_IP4] = cf_define_symbol(c, cf_get_symbol(c, "master4"), SYM_TABLE, table, NULL);
++ c->def_tables[NET_IP6] = cf_define_symbol(c, cf_get_symbol(c, "master6"), SYM_TABLE, table, NULL);
}
void
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
- cf_define_symbol(new_config, s, SYM_TABLE, table, c);
+ if (s == new_config->def_tables[addr_type])
+ s->table = c;
+ else
- cf_define_symbol(s, SYM_TABLE, table, c);
++ cf_define_symbol(new_config, s, SYM_TABLE, table, c);
+
c->name = s->name;
c->addr_type = addr_type;
c->gc_threshold = 1000;