diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 04a6c994..9d5890ed 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -54,6 +54,7 @@ struct keyword { byte *name; int value; + enum keyword_scope scope; }; #include "conf/keywords.h" @@ -718,16 +719,17 @@ cf_lex_init(int is_cli, struct config *c) { 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 = lp_allocz(kwlp, sizeof(*global_root_scope) * CFK__MAX); for (const struct keyword *k = keyword_list; k->name; k++) { - struct symbol *sym = cf_new_symbol(global_root_scope, global_root_scope_pool, kwlp, k->name); + struct symbol *sym = cf_new_symbol(&global_root_scope[k->scope], global_root_scope_pool, kwlp, k->name); sym->class = SYM_KEYWORD; sym->keyword = k; } - global_root_scope->readonly = 1; + for (int s = 0; s < CFK__MAX; s++) + global_root_scope[s].readonly = 1; } ifs_head = ifs = push_ifs(NULL); @@ -751,7 +753,7 @@ cf_lex_init(int is_cli, struct config *c) if (is_cli) c->current_scope->next = config->root_scope; else - c->current_scope->next = global_root_scope; + c->current_scope->next = &global_root_scope[CFK_KEYWORDS]; } /** diff --git a/conf/conf.h b/conf/conf.h index 8558fcba..f91d7039 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -143,6 +143,12 @@ struct sym_scope { byte readonly:1; /* Do not add new symbols */ }; +enum keyword_scope { + CFK_KEYWORDS, + CFK_METHODS, + CFK__MAX +}; + extern struct sym_scope *global_root_scope; struct bytestring { diff --git a/conf/confbase.Y b/conf/confbase.Y index fbc6df62..a6f038fe 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -129,7 +129,7 @@ CF_DECLS %start config -CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM) +CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM, MAX, AS) CF_GRAMMAR diff --git a/conf/gen_keywords.m4 b/conf/gen_keywords.m4 index a1be5847..0d7c5d4d 100644 --- a/conf/gen_keywords.m4 +++ b/conf/gen_keywords.m4 @@ -23,10 +23,12 @@ 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 }, +m4_define(CF_handle_kw, `m4_divert(1){ "m4_translit($1,[[A-Z]],[[a-z]])", $1, CF_keywd_target }, 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') +m4_define(CF_keywd, `m4_ifdef([[CF_tok_]]CF_keywd_target[[_$1]],,[[m4_define([[CF_tok_]]CF_keywd_target[[_$1]],1)CF_handle_kw($1)]])') +m4_define(CF_KEYWORDS, `m4_define([[CF_keywd_target]],CFK_KEYWORDS)CF_iterate([[CF_keywd]], [[$@]])DNL') +m4_define(CF_METHODS, `m4_define([[CF_keywd_target]],CFK_METHODS)CF_iterate([[CF_keywd]], [[$@]])DNL') + # CLI commands generate keywords as well m4_define(CF_CLI, `CF_KEYWORDS(m4_translit($1, [[ ]], [[,]])) diff --git a/conf/gen_parser.m4 b/conf/gen_parser.m4 index c4791218..993320c4 100644 --- a/conf/gen_parser.m4 +++ b/conf/gen_parser.m4 @@ -33,6 +33,8 @@ m4_define(CF_iterate, `m4_define([[CF_iter]], m4_defn([[$1]]))CF_itera($2)') m4_define(CF_keywd, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)m4_define([[CF_toks]],CF_toks $1)]])') m4_define(CF_KEYWORDS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks )DNL') +m4_define(CF_METHODS, `m4_define([[CF_toks]],[[]])CF_iterate([[CF_keywd]], [[$@]])m4_ifelse(CF_toks,,,%token[[]]CF_toks +)DNL') # CLI commands m4_define(CF_CLI, `m4_define([[CF_cmd]], cmd_[[]]m4_translit($1, [[ ]], _))DNL diff --git a/filter/config.Y b/filter/config.Y index bf2aa469..a4acd729 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -21,6 +21,7 @@ static inline u32 pair_b(u32 p) { return p & 0xFFFF; } static struct f_method_scope { struct f_inst *object; + struct sym_scope scope; } f_method_scope_stack[32]; static int f_method_scope_pos = -1; @@ -32,12 +33,24 @@ static inline void f_push_method_scope(struct f_inst *object) cf_error("Too many nested method calls"); FM = (struct f_method_scope) { .object = object, + .scope = { + .next = new_config->current_scope, + .hash = global_root_scope[CFK_METHODS].hash, + .active = 1, + .block = 1, + .readonly = 1, + }, }; + new_config->current_scope = &FM.scope; } static inline void f_pop_method_scope(void) { ASSERT_DIE(f_method_scope_pos >= 0); + + ASSERT_DIE(&FM.scope == new_config->current_scope); + new_config->current_scope = FM.scope.next; + f_method_scope_pos--; } @@ -330,25 +343,25 @@ CF_DECLS CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, ACCEPT, REJECT, ERROR, - INT, BOOL, IP, TYPE, PREFIX, RD, PAIR, QUAD, EC, LC, + INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC, SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST, IF, THEN, ELSE, CASE, FOR, IN, DO, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, - FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, ONLINK, + FROM, GW, NET, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, ONLINK, PREFERENCE, - ROA_CHECK, ASN, SRC, DST, - IS_V4, IS_V6, - LEN, MAXLEN, - DATA, DATA1, DATA2, + ROA_CHECK, DEFINED, ADD, DELETE, RESET, - PREPEND, FIRST, LAST, LAST_NONAGGREGATED, - MIN, MAX, + PREPEND, EMPTY, FILTER, WHERE, EVAL, ATTRIBUTE, BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT) +CF_METHODS(IS_V4, TYPE, IP, RD, LEN, MAXLEN, ASN, SRC, DST, MASK, + FIRST, LAST, LAST_NONAGGREGATED, DATA, DATA1, DATA2, MIN, MAX, + EMPTY, PREPEND, ADD, DELETE, FILTER) + %nonassoc THEN %nonassoc ELSE