]> git.ipfire.org Git - thirdparty/bird.git/blobdiff - filter/config.Y
Conf: Allow keywords to be redefined by user symbols
[thirdparty/bird.git] / filter / config.Y
index 68ee1a847c9de0168e8b4f720437e9cf9763f6ea..3bf3a2b6d67846406631be0642510ee6ce896171 100644 (file)
@@ -298,14 +298,15 @@ assert_assign(struct f_lval *lval, struct f_inst *expr, const char *start, const
 
 CF_DECLS
 
+CF_KEYWORDS_EXCLUSIVE(IN)
 CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
        ACCEPT, REJECT, ERROR,
        INT, BOOL, IP, TYPE, PREFIX, RD, PAIR, QUAD, EC, LC,
-       SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
+       SET, STRING, BYTESTRING, BGPMASK, BGPPATH, CLIST, ECLIST, LCLIST,
        IF, THEN, ELSE, CASE,
-       FOR, IN, DO,
+       FOR, DO,
        TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
-       FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS,
+       FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX, WEIGHT, GW_MPLS, ONLINK,
        PREFERENCE,
        ROA_CHECK, ASN, SRC, DST,
        IS_V4, IS_V6,
@@ -317,13 +318,14 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
        MIN, MAX,
        EMPTY,
        FILTER, WHERE, EVAL, ATTRIBUTE,
+       FROM_HEX,
        BT_ASSERT, BT_TEST_SUITE, BT_CHECK_ASSIGN, BT_TEST_SAME, FORMAT)
 
 %nonassoc THEN
 %nonassoc ELSE
 
 %type <xp> cmds_int cmd_prep
-%type <x> term cmd cmd_var cmds cmds_scoped constant constructor print_list var var_init var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
+%type <x> term term_bs cmd cmd_var cmds cmds_scoped constant constructor print_list var var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
 %type <fda> dynamic_attr
 %type <fsa> static_attr
 %type <f> filter where_filter
@@ -357,7 +359,7 @@ filter_def:
 
 conf: filter_eval ;
 filter_eval:
-   EVAL term { f_eval_int(f_linearize($2, 1)); }
+   EVAL term { cf_eval_int($2); }
  ;
 
 conf: custom_attr ;
@@ -404,6 +406,7 @@ type:
  | EC { $$ = T_EC; }
  | LC { $$ = T_LC; }
  | STRING { $$ = T_STRING; }
+ | BYTESTRING { $$ = T_BYTESTRING; }
  | BGPMASK { $$ = T_PATH_MASK; }
  | BGPPATH { $$ = T_PATH; }
  | CLIST { $$ = T_CLIST; }
@@ -571,7 +574,7 @@ set_atom:
  | VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
  | ENUM   { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  | '(' term ')' {
-     if (f_eval(f_linearize($2, 1), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
+     $$ = cf_eval($2, T_VOID);
      if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
    }
  | CF_SYM_KNOWN {
@@ -583,13 +586,13 @@ set_atom:
 
 switch_atom:
    NUM   { $$.type = T_INT; $$.val.i = $1; }
- | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2, 1)); }
+ | '(' term ')' { $$ = cf_eval($2, T_INT); }
  | fipa  { $$ = $1; }
  | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  ;
 
 cnum:
-   term { $$ = f_eval_int(f_linearize($1, 1)); }
+   term { $$ = cf_eval_int($1); }
 
 pair_item:
    '(' cnum ',' cnum ')'               { $$ = f_new_pair_item($2, $2, $4, $4); }
@@ -676,16 +679,15 @@ switch_body: /* EMPTY */ { $$ = NULL; }
  | switch_body switch_items ':' cmds_scoped  {
      /* Fill data fields */
      struct f_tree *t;
-     struct f_line *line = f_linearize($4, 0);
      for (t = $2; t; t = t->left)
-       t->data = line;
+       t->data = $4;
      $$ = f_merge_items($1, $2);
    }
  | switch_body ELSECOL cmds_scoped {
      struct f_tree *t = f_new_tree();
      t->from.type = t->to.type = T_VOID;
      t->right = t;
-     t->data = f_linearize($3, 0);
+     t->data = $3;
      $$ = f_merge_items($1, t);
  }
  ;
@@ -715,13 +717,14 @@ bgp_path_tail:
  ;
 
 constant:
-   NUM    { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = $1, }); }
- | TRUE   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 1, }); }
- | FALSE  { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 0, }); }
- | TEXT   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); }
- | fipa          { $$ = f_new_inst(FI_CONSTANT, $1); }
- | VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
- | net_   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
+   NUM      { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_INT, .val.i = $1, }); }
+ | TRUE     { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 1, }); }
+ | FALSE    { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BOOL, .val.i = 0, }); }
+ | TEXT     { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); }
+ | BYTETEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BYTESTRING, .val.bs = $1, }); }
+ | fipa     { $$ = f_new_inst(FI_CONSTANT, $1); }
+ | VPN_RD   { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
+ | net_     { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
  | '[' ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = NULL, }); }
  | '[' set_items ']' {
      DBG( "We've got a set here..." );
@@ -796,6 +799,7 @@ static_attr:
  | WEIGHT  { $$ = f_new_static_attr(T_INT,        SA_WEIGHT,   0); }
  | PREFERENCE { $$ = f_new_static_attr(T_INT,    SA_PREF,      0); }
  | GW_MPLS { $$ = f_new_static_attr(T_INT,        SA_GW_MPLS,  0); }
+ | ONLINK  { $$ = f_new_static_attr(T_BOOL,       SA_ONLINK,   0); }
  ;
 
 term:
@@ -868,9 +872,14 @@ term:
 
 /* | term '.' LEN { $$->code = P('P','l'); } */
 
+ | term_bs
  | function_call
  ;
 
+term_bs:
+   FROM_HEX '(' term ')' { $$ = f_new_inst(FI_FROM_HEX, $3); }
+ ;
+
 break_command:
    ACCEPT { $$ = F_ACCEPT; }
  | REJECT { $$ = F_REJECT; }
@@ -887,16 +896,16 @@ print_list: /* EMPTY */ { $$ = NULL; }
    }
  ;
 
-var_init:
-   /* empty */ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { }); }
- | '=' term { $$ = $2; }
- ;
-
 var:
-   type symbol var_init ';' {
+   type symbol '=' term ';' {
      struct symbol *sym = cf_define_symbol($2, SYM_VARIABLE | $1, offset, f_new_var(sym_->scope));
-     $$ = f_new_inst(FI_VAR_INIT, $3, sym);
+     $$ = f_new_inst(FI_VAR_INIT, $4, sym);
    }
+ | type symbol ';' {
+     struct symbol *sym = cf_define_symbol($2, SYM_VARIABLE | $1, offset, f_new_var(sym_->scope));
+     $$ = f_new_inst(FI_VAR_INIT0, sym);
+   }
+ ;
 
 for_var:
    type symbol { $$ = cf_define_symbol($2, SYM_VARIABLE | $1, offset, f_new_var(sym_->scope)); }
@@ -972,7 +981,7 @@ cmd:
    }
  | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); }
  | CASE term '{' switch_body '}' {
-      $$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
+      $$ = f_new_inst(FI_SWITCH, $2, $4);
    }
 
  | dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($1); }