]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Split printing and dying
authorMaria Matejka <mq@jmq.cz>
Tue, 2 Jul 2019 23:23:49 +0000 (01:23 +0200)
committerMaria Matejka <mq@jmq.cz>
Wed, 3 Jul 2019 06:27:56 +0000 (08:27 +0200)
conf/confbase.Y
filter/config.Y
filter/decl.m4
filter/f-inst.c
filter/f-util.c

index bcfd3f1a4a79b45bd0e5365446f68e77430132f9..775af22d7cdb5602b3054e32de2fa17f93ce0854 100644 (file)
@@ -64,7 +64,9 @@ CF_DECLS
   struct rtable_config *r;
   struct channel_config *cc;
   struct f_inst *x;
-  struct f_inst *xp[2];
+  struct {
+    struct f_inst *begin, *end;
+  } xp;
   enum filter_return fret;
   enum ec_subtype ecs;
   struct f_dynamic_attr fda;
index ff2b966e53a96b9c6601d9ee2d8db59447300605..c40f28d4292bc981d5ab4fd5bd232f9a1775554b 100644 (file)
@@ -447,7 +447,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
 %nonassoc ELSE
 
 %type <xp> cmds_int
-%type <x> term block cmd cmds constant constructor print_one print_list var_list function_call symbol_value bgp_path_expr bgp_path bgp_path_tail
+%type <x> term block cmd cmds constant constructor print_list 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
@@ -621,11 +621,21 @@ function_def:
 /* Programs */
 
 cmds: /* EMPTY */ { $$ = NULL; }
- | cmds_int { $$ = $1[0]; }
+ | cmds_int { $$ = $1.begin; }
  ;
 
-cmds_int: cmd { $$[0] = $$[1] = $1; }
- | cmds_int cmd { $$[1] = $2; $1[1]->next = $2; $$[0] = $1[0]; }
+cmds_int: cmd {
+  $$.begin = $$.end = $1;
+  while ($$.end->next)
+    $$.end = $$.end->next;
+  }
+ | cmds_int cmd {
+  $$.begin = $1.begin;
+  $1.end->next = $2;
+  $$.end = $2;
+  while ($$.end->next)
+    $$.end = $$.end->next;
+ }
  ;
 
 block:
@@ -960,17 +970,13 @@ break_command:
  | PRINTN { $$ = F_NONL; }
  ;
 
-print_one:
-   term { $$ = f_new_inst(FI_PRINT, $1); }
- ;
-
 print_list: /* EMPTY */ { $$ = NULL; }
- | print_one { $$ = $1; }
- | print_one ',' print_list {
-     if ($1) {
-       $1->next = $3;
-       $$ = $1;
-     } else $$ = $3;
+ | term { $$ = $1; }
+ | term ',' print_list {
+     ASSERT($1);
+     ASSERT($1->next == NULL);
+     $1->next = $3;
+     $$ = $1;
    }
  ;
 
@@ -1011,7 +1017,22 @@ cmd:
  | UNSET '(' dynamic_attr ')' ';' {
      $$ = f_new_inst(FI_EA_UNSET, $3);
    }
- | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE, $2, $1); }
+ | break_command print_list ';' {
+    struct f_inst *breaker = NULL;
+    struct f_inst *printer = NULL;
+    if ($2)
+      printer = f_new_inst(FI_PRINT, $2);
+    if ($1 != F_NONL)
+      breaker = f_new_inst(FI_DIE, $1);
+
+    if (printer && breaker)
+      printer->next = breaker;
+
+    if (printer)
+      $$ = printer;
+    else
+      $$ = breaker;
+   }
  | function_call ';' { $$ = f_new_inst(FI_DROP_RESULT, $1); } 
  | CASE term '{' switch_body '}' {
       $$ = f_new_inst(FI_SWITCH, $2, build_tree($4));
index 42515c13b3d99c99c684dbb156873e8dfa43e5e9..9bd9a140977d53d7cff7370fd944bc30ff37d8d7 100644 (file)
@@ -93,6 +93,25 @@ FID_INTERPRET_EXEC()m4_dnl
 const $1 $2 = whati->$2
 FID_INTERPRET_BODY')
 
+m4_define(FID_MEMBER_IN, `m4_dnl
+FID_LINE_IN()m4_dnl
+      $1 $2;
+FID_STRUCT_IN()m4_dnl
+      $1 $2;
+FID_LINEARIZE_BODY()m4_dnl
+item->$2 = whati->$2;
+m4_ifelse($3,,,[[
+FID_SAME_BODY()m4_dnl
+if ($3) return 0;
+]])
+m4_ifelse($4,,,[[
+FID_DUMP_BODY()m4_dnl
+debug("%s$4\n", INDENT, $5);
+]])
+FID_INTERPRET_EXEC()m4_dnl
+const $1 $2 = whati->$2
+FID_INTERPRET_BODY')
+
 #      Instruction arguments are needed only until linearization is done.
 #      This puts the arguments into the filter line to be executed before
 #      the instruction itself.
index 5f30ee3802e6b10b718c378beb2b63feade720da..8d5c6656f37cad1eee033e29bd21c7ef33c7305e 100644 (file)
     if (fstk->vcnt < whati->count) /* TODO: make this check systematic */
       runtime("Construction of BGP path mask from %u elements must have at least that number of elements", whati->count);
 
-#define pv fstk->vstk[fstk->vcnt - count + i]
+#define pv fstk->vstk[fstk->vcnt - whati->count + i]
 
     FID_INTERPRET_NEW
 #define pv items[i]->i_FI_CONSTANT.val
 
     RESULT_VAL(val);
   }
-  INST(FI_PRINT, 1, 0) {
-    NEVER_CONSTANT;
-    ARG_ANY(1);
-    val_format(&(v1), &fs->buf);
-  }
   INST(FI_CONDITION, 1, 0) {
     ARG(1, T_BOOL);
     if (v1.val.i)
     else
       LINE(3,1);
   }
-  INST(FI_PRINT_AND_DIE, 0, 0) {
-    NEVER_CONSTANT;
-    FID_LINEARIZE_BODY
-    {
-      uint opos = pos;
-      FID_INTERPRET_BODY
 
+  INST(FI_PRINT, 0, 0) {
+    NEVER_CONSTANT;
     ARG_ANY(1);
+    FID_MEMBER_IN(uint, count, f1->count != f2->count, number of items %u, item->count);
+
+    FID_NEW_BODY
+      uint len = 0;
+      for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
+       ;
+      whati->count = len;
 
-      FID_LINEARIZE_BODY
-      if (opos < pos)
-       dest->items[pos].flags |= FIF_PRINTED;
-    }
     FID_INTERPRET_BODY
 
+#define pv fstk->vstk[fstk->vcnt - whati->count + i]
+    if (whati->count)
+      for (uint i=0; i<whati->count; i++)
+       val_format(&(pv), &fs->buf);
+#undef pv
+
+    fstk->vcnt -= whati->count;
+  }
+
+  INST(FI_DIE, 0, 0) {
+    NEVER_CONSTANT;
     FID_MEMBER(enum filter_return, fret, f1->fret != f2->fret, %s, filter_return_str(item->fret));
 
-    if ((fret == F_NOP || (fret != F_NONL && (what->flags & FIF_PRINTED))) &&
-       !(fs->flags & FF_SILENT))
+    if (fs->buf.start < fs->buf.pos)
       log_commit(*L_INFO, &fs->buf);
 
-    switch (fret) {
+    switch (whati->fret) {
     case F_QUITBIRD:
       die( "Filter asked me to die" );
     case F_ACCEPT:
     case F_ERROR:
     case F_REJECT:     /* FIXME (noncritical) Should print complete route along with reason to reject route */
       return fret;     /* We have to return now, no more processing. */
-    case F_NONL:
     case F_NOP:
       break;
     default:
index b4105aadec1bf0216cef6a0c9e36fa3677d06bb1..e61949f241cf058fb75446f1c2db7f8952bc1b1b 100644 (file)
@@ -33,17 +33,17 @@ filter_name(const struct filter *filter)
 struct filter *f_new_where(struct f_inst *where)
 {
   struct f_inst acc = {
-    .fi_code = FI_PRINT_AND_DIE,
+    .fi_code = FI_DIE,
     .lineno = ifs->lino,
     .size = 1,
-    .i_FI_PRINT_AND_DIE = { .fret = F_ACCEPT, },
+    .i_FI_DIE = { .fret = F_ACCEPT, },
   };
 
   struct f_inst rej = {
-    .fi_code = FI_PRINT_AND_DIE,
+    .fi_code = FI_DIE,
     .lineno = ifs->lino,
     .size = 1,
-    .i_FI_PRINT_AND_DIE = { .fret = F_REJECT, },
+    .i_FI_DIE = { .fret = F_REJECT, },
   };
 
   struct f_inst i = {