diff --git a/conf/cf-lex.l b/conf/cf-lex.l index 2f95f2e1..637a5d38 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -680,7 +680,7 @@ cf_lex_symbol(const char *data) int val = sym->keyword->value; if (val > 0) return val; cf_lval.i = -val; - return ENUM; + return ENUM_TOKEN; } case SYM_METHOD: return (sym->method->arg_num > 1) ? CF_SYM_METHOD_ARGS : CF_SYM_METHOD_BARE; diff --git a/conf/confbase.Y b/conf/confbase.Y index cdbdf1ce..1011a57c 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -105,7 +105,7 @@ CF_DECLS %token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT %token GEQ LEQ NEQ AND OR IMP %token PO PC -%token NUM ENUM +%token NUM ENUM_TOKEN %token IP4 %token IP6 %token VPN_RD diff --git a/conf/gen_keywords.m4 b/conf/gen_keywords.m4 index 4e8651f6..e81589dc 100644 --- a/conf/gen_keywords.m4 +++ b/conf/gen_keywords.m4 @@ -35,10 +35,11 @@ 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) +# The typename is converted to a keyword by removing T_ENUM_ prefix 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') +m4_define(CF_ENUM, `CF_keywd(m4_substr($1, 7))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, `CF_keywd(m4_substr($1, 7))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 m4_m4wrap(` diff --git a/conf/gen_parser.m4 b/conf/gen_parser.m4 index 48c2ca50..e41eb7f7 100644 --- a/conf/gen_parser.m4 +++ b/conf/gen_parser.m4 @@ -52,8 +52,10 @@ m4_define(CF_CLI_OPT, `') m4_define(CF_CLI_HELP, `') # ENUM declarations are ignored -m4_define(CF_ENUM, `') -m4_define(CF_ENUM_PX, `') +m4_define(CF_token, `m4_ifdef([[CF_tok_$1]],,[[m4_define([[CF_tok_$1]],1)%token $1]])') +m4_define(CF_enum, `CF_append([[CF_enum_type]],[[$1 { $$ = $2; }]],[[ | ]])CF_token($1)') +m4_define(CF_ENUM, `CF_enum(m4_substr($1, 7), $1)') +m4_define(CF_ENUM_PX, `CF_enum(m4_substr($1, 7), $1)') # After all configuration templates end, we finally generate the grammar file. m4_m4wrap(` @@ -65,9 +67,11 @@ m4_undivert(1)DNL m4_undivert(2)DNL %type KEYWORD +%type enum_type %% KEYWORD: CF_kw_rule; +enum_type: CF_enum_type; m4_undivert(3)DNL diff --git a/filter/config.Y b/filter/config.Y index d656a726..3b4d669f 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -357,7 +357,7 @@ CF_DECLS CF_KEYWORDS_EXCLUSIVE(IN) CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, ACCEPT, REJECT, ERROR, - INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC, + INT, BOOL, IP, PREFIX, RD, PAIR, QUAD, EC, LC, ENUM, SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST, IF, THEN, ELSE, CASE, FOR, DO, @@ -473,6 +473,7 @@ type: case T_INT: case T_PAIR: case T_QUAD: + case T_ENUM: case T_EC: case T_LC: case T_RD: @@ -488,6 +489,7 @@ type: cf_error( "You can't create sets of this type." ); } } + | ENUM enum_type { $$ = $2; }; ; function_argsn: @@ -640,7 +642,7 @@ set_atom0: NUM { $$.type = T_INT; $$.val.i = $1; } | fipa { $$ = $1; } | VPN_RD { $$.type = T_RD; $$.val.ec = $1; } - | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } + | ENUM_TOKEN { $$.type = pair_a($1); $$.val.i = pair_b($1); } | '(' term ')' { $$ = cf_eval($2, T_VOID); if (!f_valid_set_type($$.type)) @@ -808,7 +810,7 @@ constant: DBG( "ook\n" ); } | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_PREFIX_SET, .val.ti = $2, }); } - | ENUM { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }); } + | ENUM_TOKEN { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = $1 >> 16, .val.i = $1 & 0xffff, }); } ; constructor: diff --git a/filter/data.c b/filter/data.c index 282206eb..10084448 100644 --- a/filter/data.c +++ b/filter/data.c @@ -44,6 +44,7 @@ static const char * const f_type_str[] = { [T_ENUM_NETTYPE] = "enum nettype", [T_ENUM_RA_PREFERENCE] = "enum ra_preference", [T_ENUM_AF] = "enum af", + [T_ENUM_MPLS_POLICY] = "enum mpls_policy", [T_IP] = "ip", [T_NET] = "prefix", diff --git a/filter/test.conf b/filter/test.conf index 0361a1c9..c27c04ed 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -471,12 +471,31 @@ bt_test_suite(t_ip_set, "Testing sets of ip address"); function t_enum() { + enum rts ev0 = RTS_STATIC; + enum rtd ev1 = RTD_UNICAST; + enum scope ev2 = SCOPE_UNIVERSE; + enum roa ev3 = ROA_VALID; + enum aspa ev4 = ASPA_VALID; + enum af ev5 = AF_IPV6; + enum nettype ev6 = NET_IP6; + enum bgp_origin ev7 = ORIGIN_IGP; + enum ra_preference ev8 = RA_PREF_LOW; + enum mpls_policy ev9 = MPLS_POLICY_STATIC; + + enum nettype set es = [NET_IP6, NET_VPN6]; + bt_assert(format(RTS_STATIC) = "(enum 30)1"); bt_assert(format(NET_IP4) = "(enum 36)1"); bt_assert(format(NET_VPN6) = "(enum 36)4"); + bt_assert(format(ev6) = "(enum 36)2"); + + bt_assert(ev0 = RTS_STATIC); + bt_assert(ev6 = NET_IP6); bt_assert(RTS_STATIC ~ [RTS_STATIC, RTS_DEVICE]); bt_assert(RTS_BGP !~ [RTS_STATIC, RTS_DEVICE]); + bt_assert(NET_IP6 ~ es); + bt_assert(NET_IP4 !~ es); } bt_test_suite(t_enum, "Testing enums"); diff --git a/nest/config.Y b/nest/config.Y index 6b89f5d8..118c112e 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -132,6 +132,7 @@ CF_KEYWORDS(ASPA_PROVIDERS) /* For r_args_channel */ CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC, ASPA) +CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR, MPLS, ASPA) CF_ENUM(T_ENUM_RTS, RTS_, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL, RPKI, L3VPN, AGGREGATED) @@ -211,8 +212,6 @@ net_type: | MPLS { $$ = NET_MPLS; } ; -CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR, MPLS, ASPA) - /* Creation of routing tables */