mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Merge commit '58efa944' into thread-next
Conflicts: conf/cf-lex.l conf/conf.h conf/confbase.Y conf/gen_keywords.m4 conf/gen_parser.m4 filter/config.Y nest/config.Y proto/bgp/config.Y proto/static/config.Y Keywords and attributes are split to separate namespaces, to avoid collisions between regular keyword use and attribute overlay.
This commit is contained in:
commit
da52d66177
119
conf/cf-lex.l
119
conf/cf-lex.l
@ -54,7 +54,6 @@
|
||||
struct keyword {
|
||||
byte *name;
|
||||
int value;
|
||||
struct keyword *next;
|
||||
};
|
||||
|
||||
#include "conf/keywords.h"
|
||||
@ -67,16 +66,10 @@ 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, n->scope->active
|
||||
#define SYM_KEY(n) n->name
|
||||
#define SYM_NEXT(n) n->next
|
||||
#define SYM_EQ(a,s1,b,s2) !strcmp(a,b) && s1 == s2
|
||||
#define SYM_FN(k,s) cf_hash(k)
|
||||
#define SYM_EQ(a,b) !strcmp(a,b)
|
||||
#define SYM_FN(k) cf_hash(k)
|
||||
#define SYM_ORDER 4 /* Initial */
|
||||
|
||||
#define SYM_REHASH sym_rehash
|
||||
@ -85,14 +78,20 @@ static uint cf_hash(const byte *c);
|
||||
|
||||
HASH_DEFINE_REHASH_FN(SYM, struct symbol)
|
||||
|
||||
HASH(struct keyword) kw_hash;
|
||||
HASH(struct ea_class) ea_name_hash;
|
||||
/* Global symbol scopes */
|
||||
static pool *global_root_scope_pool;
|
||||
static struct sym_scope
|
||||
global_root_scope = {
|
||||
.active = 1,
|
||||
},
|
||||
global_filter_scope = {
|
||||
.active = 0,
|
||||
.next = &global_root_scope,
|
||||
};
|
||||
|
||||
/* Local symbol scope: TODO this isn't thread-safe */
|
||||
struct sym_scope *conf_this_scope;
|
||||
|
||||
static struct sym_scope global_root_scope__init = { .active = 1, };
|
||||
struct sym_scope *global_root_scope = &global_root_scope__init;
|
||||
|
||||
linpool *cfg_mem;
|
||||
|
||||
int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
|
||||
@ -581,7 +580,7 @@ cf_new_symbol(const byte *c)
|
||||
|
||||
s = cfg_allocz(sizeof(struct symbol) + l + 1);
|
||||
*s = (struct symbol) { .scope = conf_this_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);
|
||||
@ -595,20 +594,20 @@ cf_new_symbol(const byte *c)
|
||||
}
|
||||
|
||||
static struct symbol *
|
||||
cf_root_symbol(const byte *c)
|
||||
cf_root_symbol(const byte *c, struct sym_scope *ss)
|
||||
{
|
||||
uint l = strlen(c);
|
||||
if (l > SYM_MAX_LEN)
|
||||
bug("Root symbol %s too long", c);
|
||||
|
||||
struct symbol *s = mb_alloc(&root_pool, sizeof(struct symbol) + l + 1);
|
||||
*s = (struct symbol) { .scope = global_root_scope, .class = SYM_VOID, };
|
||||
*s = (struct symbol) { .scope = ss, .class = SYM_VOID, };
|
||||
memcpy(s->name, c, l+1);
|
||||
|
||||
if (!global_root_scope->hash.data)
|
||||
HASH_INIT(global_root_scope->hash, &root_pool, SYM_ORDER);
|
||||
if (!ss->hash.data)
|
||||
HASH_INIT(ss->hash, &root_pool, SYM_ORDER);
|
||||
|
||||
HASH_INSERT2(global_root_scope->hash, SYM, &root_pool, s);
|
||||
HASH_INSERT2(ss->hash, SYM, &root_pool, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -631,7 +630,7 @@ cf_find_symbol_scope(const struct sym_scope *scope, const byte *c)
|
||||
|
||||
/* Find the symbol here or anywhere below */
|
||||
while (scope)
|
||||
if (scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c, 1)))
|
||||
if (scope->active && scope->hash.data && (s = HASH_FIND(scope->hash, SYM, c)))
|
||||
return s;
|
||||
else
|
||||
scope = scope->next;
|
||||
@ -702,50 +701,34 @@ 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;
|
||||
case SYM_KEYWORD:
|
||||
if (sym->keyword->value > 0)
|
||||
return sym->keyword->value;
|
||||
else
|
||||
{
|
||||
cf_lval.i = -k->value;
|
||||
cf_lval.i = -sym->keyword->value;
|
||||
return ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, only a symbol. */
|
||||
if (sym->class == SYM_VOID)
|
||||
case SYM_VOID:
|
||||
return CF_SYM_UNDEFINED;
|
||||
else
|
||||
default:
|
||||
return CF_SYM_KNOWN;
|
||||
}
|
||||
|
||||
static void
|
||||
cf_lex_init_kh(void)
|
||||
{
|
||||
HASH_INIT(kw_hash, config_pool, KW_ORDER);
|
||||
|
||||
struct keyword *k;
|
||||
for (k=keyword_list; k->name; k++)
|
||||
HASH_INSERT(kw_hash, KW, k);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ea_lex_register(struct ea_class *def)
|
||||
{
|
||||
struct symbol *sym = cf_root_symbol(def->name);
|
||||
sym->class = SYM_ATTRIBUTE;
|
||||
sym->attribute = def;
|
||||
def->sym = sym;
|
||||
def->sym = cf_define_symbol(cf_root_symbol(def->name, &global_filter_scope), SYM_ATTRIBUTE, attribute, def);
|
||||
}
|
||||
|
||||
void
|
||||
ea_lex_unregister(struct ea_class *def)
|
||||
{
|
||||
struct symbol *sym = def->sym;
|
||||
HASH_REMOVE2(global_root_scope->hash, SYM, &root_pool, sym);
|
||||
HASH_REMOVE2(global_filter_scope.hash, SYM, &root_pool, sym);
|
||||
mb_free(sym);
|
||||
def->sym = NULL;
|
||||
}
|
||||
@ -753,7 +736,11 @@ ea_lex_unregister(struct ea_class *def)
|
||||
struct ea_class *
|
||||
ea_class_find_by_name(const char *name)
|
||||
{
|
||||
struct symbol *sym = cf_find_symbol(global_root_scope, 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
|
||||
@ -771,8 +758,13 @@ ea_class_find_by_name(const char *name)
|
||||
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, 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);
|
||||
}
|
||||
|
||||
ifs_head = ifs = push_ifs(NULL);
|
||||
if (!is_cli)
|
||||
@ -797,7 +789,7 @@ cf_lex_init(int is_cli, struct config *c)
|
||||
if (is_cli)
|
||||
conf_this_scope->next = config->root_scope;
|
||||
else
|
||||
conf_this_scope->next = global_root_scope;
|
||||
conf_this_scope->next = &global_filter_scope;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -886,6 +878,27 @@ cf_swap_soft_scope(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cf_enter_filters - enable filter / route attributes namespace
|
||||
*/
|
||||
void
|
||||
cf_enter_filters(void)
|
||||
{
|
||||
ASSERT_DIE(!global_filter_scope.active);
|
||||
global_filter_scope.active = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* cf_exit_filters - disable filter / route attributes namespace
|
||||
*/
|
||||
void
|
||||
cf_exit_filters(void)
|
||||
{
|
||||
ASSERT_DIE(global_filter_scope.active);
|
||||
global_filter_scope.active = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cf_symbol_class_name - get name of a symbol class
|
||||
* @sym: symbol
|
||||
@ -912,6 +925,8 @@ cf_symbol_class_name(struct symbol *sym)
|
||||
return "routing table";
|
||||
case SYM_ATTRIBUTE:
|
||||
return "custom attribute";
|
||||
case SYM_KEYWORD:
|
||||
return "symbol";
|
||||
case SYM_CONSTANT_RANGE:
|
||||
return "constant";
|
||||
case SYM_VARIABLE_RANGE:
|
||||
|
@ -127,6 +127,7 @@ struct symbol {
|
||||
struct ea_class *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];
|
||||
@ -144,7 +145,8 @@ struct sym_scope {
|
||||
byte soft_scopes; /* Number of soft scopes above */
|
||||
};
|
||||
|
||||
extern struct sym_scope *global_root_scope;
|
||||
void cf_enter_filters(void);
|
||||
void cf_exit_filters(void);
|
||||
|
||||
struct bytestring {
|
||||
size_t length;
|
||||
@ -161,6 +163,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)
|
||||
|
@ -121,7 +121,7 @@ CF_DECLS
|
||||
|
||||
%type <t> text opttext
|
||||
%type <bs> bytestring
|
||||
%type <s> symbol symbol_known toksym
|
||||
%type <s> symbol
|
||||
|
||||
%type <v> bytestring_text text_or_ipa
|
||||
%type <x> bytestring_expr
|
||||
@ -169,7 +169,7 @@ definition:
|
||||
expr:
|
||||
NUM
|
||||
| '(' term ')' { $$ = cf_eval_int($2); }
|
||||
| symbol_known {
|
||||
| CF_SYM_KNOWN {
|
||||
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
|
||||
$$ = SYM_VAL($1).i; }
|
||||
;
|
||||
@ -180,9 +180,7 @@ expr_us:
|
||||
| expr US { $$ = $1 US_; }
|
||||
;
|
||||
|
||||
toksym: FROM | PREFERENCE ;
|
||||
symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN | toksym ;
|
||||
symbol_known: CF_SYM_KNOWN | toksym ;
|
||||
symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN ;
|
||||
|
||||
/* Switches */
|
||||
|
||||
|
@ -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,16 +34,16 @@ 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')
|
||||
|
||||
# After all configuration templates end, we generate the
|
||||
# After all configuration templates end, we generate the keyword list
|
||||
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
|
||||
|
@ -364,13 +364,17 @@ conf: FILTER STACKS expr expr ';' {
|
||||
|
||||
conf: filter_def ;
|
||||
filter_def:
|
||||
FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); }
|
||||
filter_body {
|
||||
FILTER symbol {
|
||||
$2 = cf_define_symbol($2, SYM_FILTER, filter, NULL);
|
||||
cf_enter_filters();
|
||||
cf_push_scope( $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_exit_filters();
|
||||
}
|
||||
;
|
||||
|
||||
@ -393,7 +397,7 @@ custom_attr: ATTRIBUTE type symbol ';' {
|
||||
|
||||
conf: bt_test_suite ;
|
||||
bt_test_suite:
|
||||
BT_TEST_SUITE '(' symbol_known ',' text ')' {
|
||||
BT_TEST_SUITE '(' CF_SYM_KNOWN ',' text ')' {
|
||||
cf_assert_symbol($3, SYM_FUNCTION);
|
||||
struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite));
|
||||
t->fn = $3->function;
|
||||
@ -406,7 +410,7 @@ bt_test_suite:
|
||||
|
||||
conf: bt_test_same ;
|
||||
bt_test_same:
|
||||
BT_TEST_SAME '(' symbol_known ',' symbol_known ',' NUM ')' {
|
||||
BT_TEST_SAME '(' CF_SYM_KNOWN ',' CF_SYM_KNOWN ',' NUM ')' {
|
||||
cf_assert_symbol($3, SYM_FUNCTION);
|
||||
cf_assert_symbol($5, SYM_FUNCTION);
|
||||
struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite));
|
||||
@ -488,23 +492,30 @@ function_vars:
|
||||
filter_body: function_body ;
|
||||
|
||||
filter:
|
||||
symbol_known {
|
||||
CF_SYM_KNOWN {
|
||||
cf_assert_symbol($1, SYM_FILTER);
|
||||
$$ = $1->filter;
|
||||
}
|
||||
| { cf_push_scope(NULL); } filter_body {
|
||||
| {
|
||||
cf_enter_filters();
|
||||
cf_push_scope(NULL);
|
||||
} filter_body {
|
||||
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||
*f = (struct filter) { .root = $2 };
|
||||
$$ = f;
|
||||
|
||||
cf_pop_scope();
|
||||
cf_exit_filters();
|
||||
}
|
||||
;
|
||||
|
||||
where_filter:
|
||||
WHERE term {
|
||||
WHERE {
|
||||
cf_enter_filters();
|
||||
} term {
|
||||
/* Construct 'IF term THEN { ACCEPT; } ELSE { REJECT; }' */
|
||||
$$ = f_new_where($2);
|
||||
$$ = f_new_where($3);
|
||||
cf_exit_filters();
|
||||
}
|
||||
;
|
||||
|
||||
@ -520,6 +531,7 @@ function_def:
|
||||
FUNCTION symbol {
|
||||
DBG( "Beginning of function %s\n", $2->name );
|
||||
$2 = cf_define_symbol($2, SYM_FUNCTION, function, NULL);
|
||||
cf_enter_filters();
|
||||
cf_push_scope($2);
|
||||
} function_args {
|
||||
/* Make dummy f_line for storing function prototype */
|
||||
@ -540,6 +552,7 @@ function_def:
|
||||
$6->arg_list = $2->function->arg_list;
|
||||
$2->function = $6;
|
||||
cf_pop_scope();
|
||||
cf_exit_filters();
|
||||
}
|
||||
;
|
||||
|
||||
@ -601,7 +614,7 @@ set_atom:
|
||||
$$ = cf_eval_tmp($2, T_VOID);
|
||||
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
|
||||
}
|
||||
| symbol_known {
|
||||
| CF_SYM_KNOWN {
|
||||
cf_assert_symbol($1, SYM_CONSTANT);
|
||||
if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name);
|
||||
$$ = *$1->val;
|
||||
@ -773,7 +786,7 @@ var_list: /* EMPTY */ { $$ = NULL; }
|
||||
| var_list ',' term { $$ = $3; $$->next = $1; }
|
||||
|
||||
function_call:
|
||||
symbol_known '(' var_list ')'
|
||||
CF_SYM_KNOWN '(' var_list ')'
|
||||
{
|
||||
if ($1->class != SYM_FUNCTION)
|
||||
cf_error("You can't call something which is not a function. Really.");
|
||||
@ -792,7 +805,7 @@ function_call:
|
||||
}
|
||||
;
|
||||
|
||||
symbol_value: symbol_known
|
||||
symbol_value: CF_SYM_KNOWN
|
||||
{
|
||||
switch ($1->class) {
|
||||
case SYM_CONSTANT_RANGE:
|
||||
@ -951,7 +964,7 @@ cmd:
|
||||
$$ = f_new_inst(FI_FOR_INIT, $6, $3);
|
||||
$$->next = f_new_inst(FI_FOR_NEXT, $3, $9);
|
||||
}
|
||||
| symbol_known '=' term ';' {
|
||||
| CF_SYM_KNOWN '=' term ';' {
|
||||
switch ($1->class) {
|
||||
case SYM_VARIABLE_RANGE:
|
||||
$$ = f_new_inst(FI_VAR_SET, $3, $1);
|
||||
@ -974,7 +987,7 @@ cmd:
|
||||
cf_error( "This static attribute is read-only.");
|
||||
$$ = f_new_inst(FI_RTA_SET, $3, $1);
|
||||
}
|
||||
| UNSET '(' symbol_known ')' ';' {
|
||||
| UNSET '(' CF_SYM_KNOWN ')' ';' {
|
||||
if ($3->class != SYM_ATTRIBUTE)
|
||||
cf_error("Can't unset %s", $3->name);
|
||||
if ($3->attribute->readonly)
|
||||
@ -1004,11 +1017,11 @@ cmd:
|
||||
$$ = f_new_inst(FI_SWITCH, $2, $4);
|
||||
}
|
||||
|
||||
| symbol_known '.' EMPTY ';' { $$ = f_generate_empty($1); }
|
||||
| symbol_known '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex_sym( FI_PATH_PREPEND, $1, $5 ); }
|
||||
| symbol_known '.' ADD '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_ADD, $1, $5 ); }
|
||||
| symbol_known '.' DELETE '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_DEL, $1, $5 ); }
|
||||
| symbol_known '.' FILTER '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_FILTER, $1, $5 ); }
|
||||
| CF_SYM_KNOWN '.' EMPTY ';' { $$ = f_generate_empty($1); }
|
||||
| CF_SYM_KNOWN '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex_sym( FI_PATH_PREPEND, $1, $5 ); }
|
||||
| CF_SYM_KNOWN '.' ADD '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_ADD, $1, $5 ); }
|
||||
| CF_SYM_KNOWN '.' DELETE '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_DEL, $1, $5 ); }
|
||||
| CF_SYM_KNOWN '.' FILTER '(' term ')' ';' { $$ = f_generate_complex_sym( FI_CLIST_FILTER, $1, $5 ); }
|
||||
| BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); }
|
||||
| BT_CHECK_ASSIGN '(' get_cf_position lvalue get_cf_position ',' term ')' ';' { $$ = assert_assign(&$4, $7, $3 + 1, $5 - 1); }
|
||||
;
|
||||
@ -1019,7 +1032,7 @@ get_cf_position:
|
||||
};
|
||||
|
||||
lvalue:
|
||||
symbol_known {
|
||||
CF_SYM_KNOWN {
|
||||
switch ($1->class) {
|
||||
case SYM_VARIABLE_RANGE:
|
||||
$$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 };
|
||||
|
@ -154,8 +154,6 @@ CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6)
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
toksym: MIN | MAX ;
|
||||
|
||||
/* Setting of router ID */
|
||||
|
||||
conf: rtrid ;
|
||||
@ -694,7 +692,7 @@ r_args:
|
||||
$$->addr = $3;
|
||||
$$->addr_mode = TE_ADDR_IN;
|
||||
}
|
||||
| r_args TABLE symbol_known {
|
||||
| r_args TABLE CF_SYM_KNOWN {
|
||||
cf_assert_symbol($3, SYM_TABLE);
|
||||
if (!$3->table) cf_error("Table %s not configured", $3->name);
|
||||
$$ = $1;
|
||||
@ -741,7 +739,7 @@ r_args:
|
||||
$$ = $1;
|
||||
$$->filtered = 1;
|
||||
}
|
||||
| r_args export_mode symbol_known {
|
||||
| r_args export_mode CF_SYM_KNOWN {
|
||||
cf_assert_symbol($3, SYM_PROTO);
|
||||
struct proto_config *c = (struct proto_config *) $3->proto;
|
||||
$$ = $1;
|
||||
@ -758,7 +756,7 @@ r_args:
|
||||
$$->export_channel = $3;
|
||||
$$->tables_defined_by = RSD_TDB_INDIRECT;
|
||||
}
|
||||
| r_args PROTOCOL symbol_known {
|
||||
| r_args PROTOCOL CF_SYM_KNOWN {
|
||||
cf_assert_symbol($3, SYM_PROTO);
|
||||
struct proto_config *c = (struct proto_config *) $3->proto;
|
||||
$$ = $1;
|
||||
@ -870,7 +868,7 @@ sym_args:
|
||||
| sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
|
||||
| sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
|
||||
| sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; }
|
||||
| sym_args symbol { $$ = $1; $$->sym = $2; }
|
||||
| sym_args CF_SYM_KNOWN { $$ = $1; $$->sym = $2; }
|
||||
;
|
||||
|
||||
|
||||
|
@ -44,10 +44,6 @@ CF_KEYWORDS(CEASE, PREFIX, LIMIT, HIT, ADMINISTRATIVE, SHUTDOWN, RESET, PEER,
|
||||
|
||||
CF_GRAMMAR
|
||||
|
||||
/* Workaround for collisions between keywords and symbols */
|
||||
toksym: ROLE | PEER | PROVIDER | CUSTOMER | RS_SERVER | RS_CLIENT ;
|
||||
toksym: BGP_MED | BGP_LOCAL_PREF | SOURCE ;
|
||||
|
||||
proto: bgp_proto '}' ;
|
||||
|
||||
bgp_proto_start: proto_start BGP {
|
||||
|
@ -153,7 +153,7 @@ stat_route_opts:
|
||||
|
||||
stat_route_opt_list:
|
||||
/* empty */
|
||||
| '{' stat_route_opts '}'
|
||||
| '{' { cf_enter_filters(); } stat_route_opts '}' { cf_exit_filters(); }
|
||||
;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user