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;
%token END CLI_MARKER INVALID_TOKEN ELSECOL DDOT
%token GEQ LEQ NEQ AND OR IMP
%token PO PC
-%token <i> NUM ENUM
+%token <i> NUM ENUM_TOKEN
%token <ip4> IP4
%token <ip6> IP6
%token <i64> VPN_RD
# 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(`
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<s> $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(`
m4_undivert(2)DNL
%type <s> KEYWORD
+%type <i> enum_type
%%
KEYWORD: CF_kw_rule;
+enum_type: CF_enum_type;
m4_undivert(3)DNL
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,
case T_INT:
case T_PAIR:
case T_QUAD:
+ case T_ENUM:
case T_EC:
case T_LC:
case T_RD:
cf_error( "You can't create sets of this type." );
}
}
+ | ENUM enum_type { $$ = $2; };
;
function_argsn:
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))
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:
[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",
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");
/* 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)
| 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 */