summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorMaria Matejka <mq@jmq.cz>2019-07-03 01:23:49 +0200
committerMaria Matejka <mq@jmq.cz>2019-07-03 08:27:56 +0200
commit0206c070ace90c48a806a74fac52ba6e6ff9858b (patch)
tree51dbc4e6a42f66a923eeb4ba74d6ea65591c540d /filter
parent3265c9169dfc185ccdb787c6c83d9d8e2d0429c1 (diff)
Filter: Split printing and dying
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y51
-rw-r--r--filter/decl.m419
-rw-r--r--filter/f-inst.c43
-rw-r--r--filter/f-util.c8
4 files changed, 82 insertions, 39 deletions
diff --git a/filter/config.Y b/filter/config.Y
index ff2b966e..c40f28d4 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -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));
diff --git a/filter/decl.m4 b/filter/decl.m4
index 42515c13..9bd9a140 100644
--- a/filter/decl.m4
+++ b/filter/decl.m4
@@ -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.
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 5f30ee38..8d5c6656 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -173,7 +173,7 @@
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
@@ -320,11 +320,6 @@
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)
@@ -332,28 +327,37 @@
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:
@@ -361,7 +365,6 @@
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:
diff --git a/filter/f-util.c b/filter/f-util.c
index b4105aad..e61949f2 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -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 = {