mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +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
117
conf/cf-lex.l
117
conf/cf-lex.l
@ -54,7 +54,6 @@
|
|||||||
struct keyword {
|
struct keyword {
|
||||||
byte *name;
|
byte *name;
|
||||||
int value;
|
int value;
|
||||||
struct keyword *next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "conf/keywords.h"
|
#include "conf/keywords.h"
|
||||||
@ -67,16 +66,10 @@ struct keyword {
|
|||||||
|
|
||||||
static uint cf_hash(const byte *c);
|
static uint cf_hash(const byte *c);
|
||||||
|
|
||||||
#define KW_KEY(n) n->name
|
#define SYM_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_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,b) !strcmp(a,b)
|
||||||
#define SYM_FN(k,s) cf_hash(k)
|
#define SYM_FN(k) cf_hash(k)
|
||||||
#define SYM_ORDER 4 /* Initial */
|
#define SYM_ORDER 4 /* Initial */
|
||||||
|
|
||||||
#define SYM_REHASH sym_rehash
|
#define SYM_REHASH sym_rehash
|
||||||
@ -85,14 +78,20 @@ static uint cf_hash(const byte *c);
|
|||||||
|
|
||||||
HASH_DEFINE_REHASH_FN(SYM, struct symbol)
|
HASH_DEFINE_REHASH_FN(SYM, struct symbol)
|
||||||
|
|
||||||
HASH(struct keyword) kw_hash;
|
/* Global symbol scopes */
|
||||||
HASH(struct ea_class) ea_name_hash;
|
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;
|
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;
|
linpool *cfg_mem;
|
||||||
|
|
||||||
int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
|
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 = cfg_allocz(sizeof(struct symbol) + l + 1);
|
||||||
*s = (struct symbol) { .scope = conf_this_scope, .class = SYM_VOID, };
|
*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)
|
if (!conf_this_scope->hash.data)
|
||||||
HASH_INIT(conf_this_scope->hash, new_config->pool, SYM_ORDER);
|
HASH_INIT(conf_this_scope->hash, new_config->pool, SYM_ORDER);
|
||||||
@ -595,20 +594,20 @@ cf_new_symbol(const byte *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct symbol *
|
static struct symbol *
|
||||||
cf_root_symbol(const byte *c)
|
cf_root_symbol(const byte *c, struct sym_scope *ss)
|
||||||
{
|
{
|
||||||
uint l = strlen(c);
|
uint l = strlen(c);
|
||||||
if (l > SYM_MAX_LEN)
|
if (l > SYM_MAX_LEN)
|
||||||
bug("Root symbol %s too long", c);
|
bug("Root symbol %s too long", c);
|
||||||
|
|
||||||
struct symbol *s = mb_alloc(&root_pool, sizeof(struct symbol) + l + 1);
|
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);
|
memcpy(s->name, c, l+1);
|
||||||
|
|
||||||
if (!global_root_scope->hash.data)
|
if (!ss->hash.data)
|
||||||
HASH_INIT(global_root_scope->hash, &root_pool, SYM_ORDER);
|
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;
|
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 */
|
/* Find the symbol here or anywhere below */
|
||||||
while (scope)
|
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;
|
return s;
|
||||||
else
|
else
|
||||||
scope = scope->next;
|
scope = scope->next;
|
||||||
@ -702,50 +701,34 @@ cf_lex_symbol(const char *data)
|
|||||||
struct symbol *sym = cf_get_symbol(data);
|
struct symbol *sym = cf_get_symbol(data);
|
||||||
cf_lval.s = sym;
|
cf_lval.s = sym;
|
||||||
|
|
||||||
/* Is it a keyword? Prefer the keyword. */
|
switch (sym->class)
|
||||||
struct keyword *k = HASH_FIND(kw_hash, KW, data);
|
|
||||||
if (k)
|
|
||||||
{
|
{
|
||||||
if (k->value > 0)
|
case SYM_KEYWORD:
|
||||||
return k->value;
|
if (sym->keyword->value > 0)
|
||||||
|
return sym->keyword->value;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cf_lval.i = -k->value;
|
cf_lval.i = -sym->keyword->value;
|
||||||
return ENUM;
|
return ENUM;
|
||||||
}
|
}
|
||||||
}
|
case SYM_VOID:
|
||||||
|
|
||||||
/* OK, only a symbol. */
|
|
||||||
if (sym->class == SYM_VOID)
|
|
||||||
return CF_SYM_UNDEFINED;
|
return CF_SYM_UNDEFINED;
|
||||||
else
|
default:
|
||||||
return CF_SYM_KNOWN;
|
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
|
void
|
||||||
ea_lex_register(struct ea_class *def)
|
ea_lex_register(struct ea_class *def)
|
||||||
{
|
{
|
||||||
struct symbol *sym = cf_root_symbol(def->name);
|
def->sym = cf_define_symbol(cf_root_symbol(def->name, &global_filter_scope), SYM_ATTRIBUTE, attribute, def);
|
||||||
sym->class = SYM_ATTRIBUTE;
|
|
||||||
sym->attribute = def;
|
|
||||||
def->sym = sym;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ea_lex_unregister(struct ea_class *def)
|
ea_lex_unregister(struct ea_class *def)
|
||||||
{
|
{
|
||||||
struct symbol *sym = def->sym;
|
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);
|
mb_free(sym);
|
||||||
def->sym = NULL;
|
def->sym = NULL;
|
||||||
}
|
}
|
||||||
@ -753,7 +736,11 @@ ea_lex_unregister(struct ea_class *def)
|
|||||||
struct ea_class *
|
struct ea_class *
|
||||||
ea_class_find_by_name(const char *name)
|
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))
|
if (!sym || (sym->class != SYM_ATTRIBUTE))
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
@ -771,8 +758,13 @@ ea_class_find_by_name(const char *name)
|
|||||||
void
|
void
|
||||||
cf_lex_init(int is_cli, struct config *c)
|
cf_lex_init(int is_cli, struct config *c)
|
||||||
{
|
{
|
||||||
if (!kw_hash.data)
|
if (!global_root_scope_pool)
|
||||||
cf_lex_init_kh();
|
{
|
||||||
|
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);
|
ifs_head = ifs = push_ifs(NULL);
|
||||||
if (!is_cli)
|
if (!is_cli)
|
||||||
@ -797,7 +789,7 @@ cf_lex_init(int is_cli, struct config *c)
|
|||||||
if (is_cli)
|
if (is_cli)
|
||||||
conf_this_scope->next = config->root_scope;
|
conf_this_scope->next = config->root_scope;
|
||||||
else
|
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
|
* cf_symbol_class_name - get name of a symbol class
|
||||||
* @sym: symbol
|
* @sym: symbol
|
||||||
@ -912,6 +925,8 @@ cf_symbol_class_name(struct symbol *sym)
|
|||||||
return "routing table";
|
return "routing table";
|
||||||
case SYM_ATTRIBUTE:
|
case SYM_ATTRIBUTE:
|
||||||
return "custom attribute";
|
return "custom attribute";
|
||||||
|
case SYM_KEYWORD:
|
||||||
|
return "symbol";
|
||||||
case SYM_CONSTANT_RANGE:
|
case SYM_CONSTANT_RANGE:
|
||||||
return "constant";
|
return "constant";
|
||||||
case SYM_VARIABLE_RANGE:
|
case SYM_VARIABLE_RANGE:
|
||||||
|
@ -127,6 +127,7 @@ struct symbol {
|
|||||||
struct ea_class *attribute; /* For SYM_ATTRIBUTE */
|
struct ea_class *attribute; /* For SYM_ATTRIBUTE */
|
||||||
struct f_val *val; /* For SYM_CONSTANT */
|
struct f_val *val; /* For SYM_CONSTANT */
|
||||||
uint offset; /* For SYM_VARIABLE */
|
uint offset; /* For SYM_VARIABLE */
|
||||||
|
const struct keyword *keyword; /* For SYM_KEYWORD */
|
||||||
};
|
};
|
||||||
|
|
||||||
char name[0];
|
char name[0];
|
||||||
@ -144,7 +145,8 @@ struct sym_scope {
|
|||||||
byte soft_scopes; /* Number of soft scopes above */
|
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 {
|
struct bytestring {
|
||||||
size_t length;
|
size_t length;
|
||||||
@ -161,6 +163,7 @@ struct bytestring {
|
|||||||
#define SYM_FILTER 4
|
#define SYM_FILTER 4
|
||||||
#define SYM_TABLE 5
|
#define SYM_TABLE 5
|
||||||
#define SYM_ATTRIBUTE 6
|
#define SYM_ATTRIBUTE 6
|
||||||
|
#define SYM_KEYWORD 7
|
||||||
|
|
||||||
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
|
#define SYM_VARIABLE 0x100 /* 0x100-0x1ff are variable types */
|
||||||
#define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff)
|
#define SYM_VARIABLE_RANGE SYM_VARIABLE ... (SYM_VARIABLE | 0xff)
|
||||||
|
@ -121,7 +121,7 @@ CF_DECLS
|
|||||||
|
|
||||||
%type <t> text opttext
|
%type <t> text opttext
|
||||||
%type <bs> bytestring
|
%type <bs> bytestring
|
||||||
%type <s> symbol symbol_known toksym
|
%type <s> symbol
|
||||||
|
|
||||||
%type <v> bytestring_text text_or_ipa
|
%type <v> bytestring_text text_or_ipa
|
||||||
%type <x> bytestring_expr
|
%type <x> bytestring_expr
|
||||||
@ -169,7 +169,7 @@ definition:
|
|||||||
expr:
|
expr:
|
||||||
NUM
|
NUM
|
||||||
| '(' term ')' { $$ = cf_eval_int($2); }
|
| '(' term ')' { $$ = cf_eval_int($2); }
|
||||||
| symbol_known {
|
| CF_SYM_KNOWN {
|
||||||
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
|
if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number constant expected");
|
||||||
$$ = SYM_VAL($1).i; }
|
$$ = SYM_VAL($1).i; }
|
||||||
;
|
;
|
||||||
@ -180,9 +180,7 @@ expr_us:
|
|||||||
| expr US { $$ = $1 US_; }
|
| expr US { $$ = $1 US_; }
|
||||||
;
|
;
|
||||||
|
|
||||||
toksym: FROM | PREFERENCE ;
|
symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN ;
|
||||||
symbol: CF_SYM_UNDEFINED | CF_SYM_KNOWN | toksym ;
|
|
||||||
symbol_known: CF_SYM_KNOWN | toksym ;
|
|
||||||
|
|
||||||
/* Switches */
|
/* Switches */
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ m4_define(CF_DECLS, `m4_divert(-1)')
|
|||||||
m4_define(CF_DEFINES, `m4_divert(-1)')
|
m4_define(CF_DEFINES, `m4_divert(-1)')
|
||||||
|
|
||||||
# Keywords are translated to C initializers
|
# 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_divert(-1)')
|
||||||
m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)CF_handle_kw($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')
|
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)
|
# Enums are translated to C initializers: use CF_ENUM(typename, prefix, values)
|
||||||
# For different prefix: CF_ENUM_PX(typename, external prefix, C 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_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, `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')
|
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_m4wrap(`
|
||||||
m4_divert(0)
|
m4_divert(0)
|
||||||
static struct keyword keyword_list[] = {
|
static const struct keyword keyword_list[] = {
|
||||||
m4_undivert(1){ NULL, -1, NULL } };
|
m4_undivert(1){ NULL, -1 } };
|
||||||
')
|
')
|
||||||
|
|
||||||
# As we are processing C source, we must access all M4 primitives via
|
# 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 ;
|
conf: filter_def ;
|
||||||
filter_def:
|
filter_def:
|
||||||
FILTER symbol { $2 = cf_define_symbol($2, SYM_FILTER, filter, NULL); cf_push_scope( $2 ); }
|
FILTER symbol {
|
||||||
filter_body {
|
$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));
|
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||||
*f = (struct filter) { .sym = $2, .root = $4 };
|
*f = (struct filter) { .sym = $2, .root = $4 };
|
||||||
$2->filter = f;
|
$2->filter = f;
|
||||||
|
|
||||||
cf_pop_scope();
|
cf_pop_scope();
|
||||||
|
cf_exit_filters();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -393,7 +397,7 @@ custom_attr: ATTRIBUTE type symbol ';' {
|
|||||||
|
|
||||||
conf: bt_test_suite ;
|
conf: bt_test_suite ;
|
||||||
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);
|
cf_assert_symbol($3, SYM_FUNCTION);
|
||||||
struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite));
|
struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite));
|
||||||
t->fn = $3->function;
|
t->fn = $3->function;
|
||||||
@ -406,7 +410,7 @@ bt_test_suite:
|
|||||||
|
|
||||||
conf: bt_test_same ;
|
conf: bt_test_same ;
|
||||||
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($3, SYM_FUNCTION);
|
||||||
cf_assert_symbol($5, SYM_FUNCTION);
|
cf_assert_symbol($5, SYM_FUNCTION);
|
||||||
struct f_bt_test_suite *t = cfg_allocz(sizeof(struct f_bt_test_suite));
|
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_body: function_body ;
|
||||||
|
|
||||||
filter:
|
filter:
|
||||||
symbol_known {
|
CF_SYM_KNOWN {
|
||||||
cf_assert_symbol($1, SYM_FILTER);
|
cf_assert_symbol($1, SYM_FILTER);
|
||||||
$$ = $1->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));
|
struct filter *f = cfg_alloc(sizeof(struct filter));
|
||||||
*f = (struct filter) { .root = $2 };
|
*f = (struct filter) { .root = $2 };
|
||||||
$$ = f;
|
$$ = f;
|
||||||
|
|
||||||
cf_pop_scope();
|
cf_pop_scope();
|
||||||
|
cf_exit_filters();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
where_filter:
|
where_filter:
|
||||||
WHERE term {
|
WHERE {
|
||||||
|
cf_enter_filters();
|
||||||
|
} term {
|
||||||
/* Construct 'IF term THEN { ACCEPT; } ELSE { REJECT; }' */
|
/* 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 {
|
FUNCTION symbol {
|
||||||
DBG( "Beginning of function %s\n", $2->name );
|
DBG( "Beginning of function %s\n", $2->name );
|
||||||
$2 = cf_define_symbol($2, SYM_FUNCTION, function, NULL);
|
$2 = cf_define_symbol($2, SYM_FUNCTION, function, NULL);
|
||||||
|
cf_enter_filters();
|
||||||
cf_push_scope($2);
|
cf_push_scope($2);
|
||||||
} function_args {
|
} function_args {
|
||||||
/* Make dummy f_line for storing function prototype */
|
/* Make dummy f_line for storing function prototype */
|
||||||
@ -540,6 +552,7 @@ function_def:
|
|||||||
$6->arg_list = $2->function->arg_list;
|
$6->arg_list = $2->function->arg_list;
|
||||||
$2->function = $6;
|
$2->function = $6;
|
||||||
cf_pop_scope();
|
cf_pop_scope();
|
||||||
|
cf_exit_filters();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -601,7 +614,7 @@ set_atom:
|
|||||||
$$ = cf_eval_tmp($2, T_VOID);
|
$$ = cf_eval_tmp($2, T_VOID);
|
||||||
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
|
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
|
||||||
}
|
}
|
||||||
| symbol_known {
|
| CF_SYM_KNOWN {
|
||||||
cf_assert_symbol($1, SYM_CONSTANT);
|
cf_assert_symbol($1, SYM_CONSTANT);
|
||||||
if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name);
|
if (!f_valid_set_type(SYM_TYPE($1))) cf_error("%s: set-incompatible type", $1->name);
|
||||||
$$ = *$1->val;
|
$$ = *$1->val;
|
||||||
@ -773,7 +786,7 @@ var_list: /* EMPTY */ { $$ = NULL; }
|
|||||||
| var_list ',' term { $$ = $3; $$->next = $1; }
|
| var_list ',' term { $$ = $3; $$->next = $1; }
|
||||||
|
|
||||||
function_call:
|
function_call:
|
||||||
symbol_known '(' var_list ')'
|
CF_SYM_KNOWN '(' var_list ')'
|
||||||
{
|
{
|
||||||
if ($1->class != SYM_FUNCTION)
|
if ($1->class != SYM_FUNCTION)
|
||||||
cf_error("You can't call something which is not a function. Really.");
|
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) {
|
switch ($1->class) {
|
||||||
case SYM_CONSTANT_RANGE:
|
case SYM_CONSTANT_RANGE:
|
||||||
@ -951,7 +964,7 @@ cmd:
|
|||||||
$$ = f_new_inst(FI_FOR_INIT, $6, $3);
|
$$ = f_new_inst(FI_FOR_INIT, $6, $3);
|
||||||
$$->next = f_new_inst(FI_FOR_NEXT, $3, $9);
|
$$->next = f_new_inst(FI_FOR_NEXT, $3, $9);
|
||||||
}
|
}
|
||||||
| symbol_known '=' term ';' {
|
| CF_SYM_KNOWN '=' term ';' {
|
||||||
switch ($1->class) {
|
switch ($1->class) {
|
||||||
case SYM_VARIABLE_RANGE:
|
case SYM_VARIABLE_RANGE:
|
||||||
$$ = f_new_inst(FI_VAR_SET, $3, $1);
|
$$ = f_new_inst(FI_VAR_SET, $3, $1);
|
||||||
@ -974,7 +987,7 @@ cmd:
|
|||||||
cf_error( "This static attribute is read-only.");
|
cf_error( "This static attribute is read-only.");
|
||||||
$$ = f_new_inst(FI_RTA_SET, $3, $1);
|
$$ = f_new_inst(FI_RTA_SET, $3, $1);
|
||||||
}
|
}
|
||||||
| UNSET '(' symbol_known ')' ';' {
|
| UNSET '(' CF_SYM_KNOWN ')' ';' {
|
||||||
if ($3->class != SYM_ATTRIBUTE)
|
if ($3->class != SYM_ATTRIBUTE)
|
||||||
cf_error("Can't unset %s", $3->name);
|
cf_error("Can't unset %s", $3->name);
|
||||||
if ($3->attribute->readonly)
|
if ($3->attribute->readonly)
|
||||||
@ -1004,11 +1017,11 @@ cmd:
|
|||||||
$$ = f_new_inst(FI_SWITCH, $2, $4);
|
$$ = f_new_inst(FI_SWITCH, $2, $4);
|
||||||
}
|
}
|
||||||
|
|
||||||
| symbol_known '.' EMPTY ';' { $$ = f_generate_empty($1); }
|
| CF_SYM_KNOWN '.' EMPTY ';' { $$ = f_generate_empty($1); }
|
||||||
| symbol_known '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex_sym( FI_PATH_PREPEND, $1, $5 ); }
|
| CF_SYM_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 ); }
|
| CF_SYM_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 ); }
|
| CF_SYM_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 '.' 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_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); }
|
| 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:
|
lvalue:
|
||||||
symbol_known {
|
CF_SYM_KNOWN {
|
||||||
switch ($1->class) {
|
switch ($1->class) {
|
||||||
case SYM_VARIABLE_RANGE:
|
case SYM_VARIABLE_RANGE:
|
||||||
$$ = (struct f_lval) { .type = F_LVAL_VARIABLE, .sym = $1 };
|
$$ = (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
|
CF_GRAMMAR
|
||||||
|
|
||||||
toksym: MIN | MAX ;
|
|
||||||
|
|
||||||
/* Setting of router ID */
|
/* Setting of router ID */
|
||||||
|
|
||||||
conf: rtrid ;
|
conf: rtrid ;
|
||||||
@ -694,7 +692,7 @@ r_args:
|
|||||||
$$->addr = $3;
|
$$->addr = $3;
|
||||||
$$->addr_mode = TE_ADDR_IN;
|
$$->addr_mode = TE_ADDR_IN;
|
||||||
}
|
}
|
||||||
| r_args TABLE symbol_known {
|
| r_args TABLE CF_SYM_KNOWN {
|
||||||
cf_assert_symbol($3, SYM_TABLE);
|
cf_assert_symbol($3, SYM_TABLE);
|
||||||
if (!$3->table) cf_error("Table %s not configured", $3->name);
|
if (!$3->table) cf_error("Table %s not configured", $3->name);
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
@ -741,7 +739,7 @@ r_args:
|
|||||||
$$ = $1;
|
$$ = $1;
|
||||||
$$->filtered = 1;
|
$$->filtered = 1;
|
||||||
}
|
}
|
||||||
| r_args export_mode symbol_known {
|
| r_args export_mode CF_SYM_KNOWN {
|
||||||
cf_assert_symbol($3, SYM_PROTO);
|
cf_assert_symbol($3, SYM_PROTO);
|
||||||
struct proto_config *c = (struct proto_config *) $3->proto;
|
struct proto_config *c = (struct proto_config *) $3->proto;
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
@ -758,7 +756,7 @@ r_args:
|
|||||||
$$->export_channel = $3;
|
$$->export_channel = $3;
|
||||||
$$->tables_defined_by = RSD_TDB_INDIRECT;
|
$$->tables_defined_by = RSD_TDB_INDIRECT;
|
||||||
}
|
}
|
||||||
| r_args PROTOCOL symbol_known {
|
| r_args PROTOCOL CF_SYM_KNOWN {
|
||||||
cf_assert_symbol($3, SYM_PROTO);
|
cf_assert_symbol($3, SYM_PROTO);
|
||||||
struct proto_config *c = (struct proto_config *) $3->proto;
|
struct proto_config *c = (struct proto_config *) $3->proto;
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
@ -870,7 +868,7 @@ sym_args:
|
|||||||
| sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
|
| sym_args FILTER { $$ = $1; $$->type = SYM_FILTER; }
|
||||||
| sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
|
| sym_args PROTOCOL { $$ = $1; $$->type = SYM_PROTO; }
|
||||||
| sym_args TEMPLATE { $$ = $1; $$->type = SYM_TEMPLATE; }
|
| 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
|
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 '}' ;
|
proto: bgp_proto '}' ;
|
||||||
|
|
||||||
bgp_proto_start: proto_start BGP {
|
bgp_proto_start: proto_start BGP {
|
||||||
|
@ -153,7 +153,7 @@ stat_route_opts:
|
|||||||
|
|
||||||
stat_route_opt_list:
|
stat_route_opt_list:
|
||||||
/* empty */
|
/* empty */
|
||||||
| '{' stat_route_opts '}'
|
| '{' { cf_enter_filters(); } stat_route_opts '}' { cf_exit_filters(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user