]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Add enum types to filter grammar
authorOndrej Zajicek <santiago@crfreenet.org>
Fri, 18 Oct 2024 14:39:42 +0000 (16:39 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Fri, 18 Oct 2024 14:39:42 +0000 (16:39 +0200)
Enum types existed on semantic level, but not on syntactic level,
so they could not be used in filter code.

Generate filter grammar for enum types based on CF_ENUM() declarations.

Thanks to lbz for the bugreport.

conf/cf-lex.l
conf/confbase.Y
conf/gen_keywords.m4
conf/gen_parser.m4
filter/config.Y
filter/data.c
filter/test.conf
nest/config.Y

index 2f95f2e137b2296c01e22b7805d2996ea65c0165..637a5d384f29005f4503e44055975e61d8fbdeb6 100644 (file)
@@ -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;
index cdbdf1ce29e7bbc269401fc5e0211e88690cc86e..1011a57c7c42cfe352a15325a1bfbf8af63bbcd5 100644 (file)
@@ -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 <i> NUM ENUM
+%token <i> NUM ENUM_TOKEN
 %token <ip4> IP4
 %token <ip6> IP6
 %token <i64> VPN_RD
index 4e8651f6d426d3914594e66ef445c21e146cc488..e81589dc8c3cb2be5217e76e8cad88ad4191451e 100644 (file)
@@ -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(`
index 48c2ca5085f03b86c837f512d9a8db53c348d643..e41eb7f76a8bcf6a19badd62062d1f9e78ebe3c0 100644 (file)
@@ -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<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(`
@@ -65,9 +67,11 @@ m4_undivert(1)DNL
 m4_undivert(2)DNL
 
 %type <s> KEYWORD
+%type <i> enum_type
 
 %%
 KEYWORD: CF_kw_rule;
+enum_type: CF_enum_type;
 
 m4_undivert(3)DNL
 
index d656a7268ae1b369c9c5b5d9b11967e890f3b87c..3b4d669f09d49eeac5c08bcd6f8b8f2b64995190 100644 (file)
@@ -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:
index 282206eb6e8a39d268de1539ad3a3174b8443679..100844481d1d2e82bb1ddded7d1ff2c35dfd8d7b 100644 (file)
@@ -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",
index 0361a1c9802fbc6c174531a1afc71ce9b409c00d..c27c04edb1256adbb4453c5369f926f33d683f62 100644 (file)
@@ -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");
index 6b89f5d853c5b41e013a7ae3af30c9fd72143217..118c112e421335343a60b7d5ecf2a7320b8314f0 100644 (file)
@@ -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 */