summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--filter/config.Y2
-rw-r--r--filter/decl.m463
-rw-r--r--filter/f-inst.c72
-rw-r--r--filter/filter.c7
4 files changed, 63 insertions, 81 deletions
diff --git a/filter/config.Y b/filter/config.Y
index f3e83cfd..9a240763 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -828,7 +828,7 @@ constructor:
'(' term ',' term ')' { $$ = f_new_inst(FI_PAIR_CONSTRUCT, $2, $4); }
| '(' ec_kind ',' term ',' term ')' { $$ = f_new_inst(FI_EC_CONSTRUCT, $4, $6, $2); }
| '(' term ',' term ',' term ')' { $$ = f_new_inst(FI_LC_CONSTRUCT, $2, $4, $6); }
- | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1, 0); }
+ | bgp_path { $$ = f_new_inst(FI_PATHMASK_CONSTRUCT, $1); }
;
diff --git a/filter/decl.m4 b/filter/decl.m4
index b1cdaf0d..d8bbf2bc 100644
--- a/filter/decl.m4
+++ b/filter/decl.m4
@@ -93,25 +93,6 @@ 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.
@@ -136,6 +117,48 @@ FID_LINEARIZE_BODY
pos = linearize(dest, whati->f$1, pos);
FID_INTERPRET_BODY()')
+# Some instructions accept variable number of arguments.
+m4_define(VARARG, `
+FID_NEW_ARGS()m4_dnl
+ , struct f_inst * fvar
+FID_STRUCT_IN()m4_dnl
+ struct f_inst * fvar;
+ uint varcount;
+FID_LINE_IN()m4_dnl
+ uint varcount;
+FID_NEW_BODY()m4_dnl
+whati->varcount = 0;
+whati->fvar = fvar;
+for (const struct f_inst *child = fvar; child; child = child->next, whati->varcount++) {
+ what->size += child->size;
+FID_IFCONST([[
+ if (child->fi_code != FI_CONSTANT)
+ constargs = 0;
+]])
+}
+FID_IFCONST([[
+ const struct f_inst **items = NULL;
+ if (constargs) {
+ items = alloca(whati->varcount * sizeof(struct f_inst *));
+ const struct f_inst *child = fvar;
+ for (uint i=0; child; i++)
+ child = (items[i] = child)->next;
+ }
+]])
+FID_LINEARIZE_BODY()m4_dnl
+ pos = linearize(dest, whati->fvar, pos);
+ item->varcount = whati->varcount;
+FID_DUMP_BODY()m4_dnl
+ debug("%snumber of varargs %u\n", INDENT, item->varcount);
+FID_SAME_BODY()m4_dnl
+ if (f1->varcount != f2->varcount) return 0;
+FID_INTERPRET_BODY()
+FID_HIC(,[[
+ if (fstk->vcnt < whati->varcount) runtime("Stack underflow");
+ fstk->vcnt -= whati->varcount;
+]],)
+')
+
# Some arguments need to check their type. After that, ARG_ANY is called.
m4_define(ARG, `ARG_ANY($1)
FID_INTERPRET_EXEC()m4_dnl
@@ -410,6 +433,7 @@ fi_constant(struct f_inst *what, struct f_val val)
#define v1 whati->f1->i_FI_CONSTANT.val
#define v2 whati->f2->i_FI_CONSTANT.val
#define v3 whati->f3->i_FI_CONSTANT.val
+#define vv(i) items[i]->i_FI_CONSTANT.val
#define runtime(fmt, ...) cf_error("filter preevaluation, line %d: " fmt, ifs->lino, ##__VA_ARGS__)
#define fpool cfg_mem
#define falloc(size) cfg_alloc(size)
@@ -418,6 +442,7 @@ FID_WR_PUT(3)
#undef v1
#undef v2
#undef v3
+#undef vv
/* Line dumpers */
#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
diff --git a/filter/f-inst.c b/filter/f-inst.c
index 7d41efe6..f1304833 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -60,8 +60,9 @@
*
* What is the syntax here?
* m4_dnl INST(FI_NOP, in, out) { enum value, input args, output args
- * m4_dnl ARG(num, type); argument, its id (in data fields) and type
- * m4_dnl ARG_ANY(num); argument with no type check
+ * m4_dnl ARG(num, type); argument, its id (in data fields) and type accessible by v1, v2, v3
+ * m4_dnl ARG_ANY(num); argument with no type check accessible by v1, v2, v3
+ * m4_dnl VARARG; variable-length argument list; accessible by vv(i) and whati->varcount
* m4_dnl LINE(num, unused); this argument has to be converted to its own f_line
* m4_dnl SYMBOL; symbol handed from config
* m4_dnl STATIC_ATTR; static attribute definition
@@ -297,45 +298,19 @@
}
INST(FI_PATHMASK_CONSTRUCT, 0, 1) {
- ARG_ANY(1);
- FID_MEMBER(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;
- struct f_inst **items;
- if (constargs) {
- items = alloca(len * sizeof(struct f_inst *));
- for (uint i=0; f1; i++) {
- items[i] = f1;
- f1 = f1->next;
- items[i]->next = 0;
- }
- whati->f1 = NULL;
- }
- FID_INTERPRET_BODY
-
- FID_INTERPRET_EXEC
- 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(i) fstk->vstk[fstk->vcnt - whati->count + (i)]
+ VARARG;
- FID_INTERPRET_NEW
-#define pv(i) items[i]->i_FI_CONSTANT.val
+ struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->varcount * sizeof(struct f_path_mask_item));
+ pm->len = whati->varcount;
- FID_INTERPRET_BODY
- struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->count * sizeof(struct f_path_mask_item));
- for (uint i=0; i<whati->count; i++) {
- switch (pv(i).type) {
+ for (uint i=0; i<whati->varcount; i++) {
+ switch (vv(i).type) {
case T_PATH_MASK_ITEM:
- pm->item[i] = pv(i).val.pmi;
+ pm->item[i] = vv(i).val.pmi;
break;
case T_INT:
pm->item[i] = (struct f_path_mask_item) {
- .asn = pv(i).val.i,
+ .asn = vv(i).val.i,
.kind = PM_ASN,
};
break;
@@ -343,13 +318,7 @@
runtime( "Error resolving path mask template: value not an integer" );
}
}
-#undef pv
- FID_INTERPRET_EXEC
- fstk->vcnt -= whati->count;
- FID_INTERPRET_BODY
-
- pm->len = whati->count;
RESULT(T_PATH_MASK, path_mask, pm);
}
@@ -479,24 +448,11 @@
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_INTERPRET_BODY
-
-#define pv(i) fstk->vstk[fstk->vcnt - whati->count + (i)]
- if (whati->count && !(fs->flags & FF_SILENT))
- for (uint i=0; i<whati->count; i++)
- val_format(&(pv(i)), &fs->buf);
-#undef pv
+ VARARG;
- fstk->vcnt -= whati->count;
+ if (whati->varcount && !(fs->flags & FF_SILENT))
+ for (uint i=0; i<whati->varcount; i++)
+ val_format(&(vv(i)), &fs->buf);
}
INST(FI_DIE, 0, 0) {
diff --git a/filter/filter.c b/filter/filter.c
index 0d727449..2aa2f629 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -190,9 +190,10 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
switch (what->fi_code) {
#define res fstk->vstk[fstk->vcnt]
-#define v1 fstk->vstk[fstk->vcnt]
-#define v2 fstk->vstk[fstk->vcnt + 1]
-#define v3 fstk->vstk[fstk->vcnt + 2]
+#define vv(i) fstk->vstk[fstk->vcnt + (i)]
+#define v1 vv(0)
+#define v2 vv(1)
+#define v3 vv(2)
#define runtime(fmt, ...) do { \
if (!(fs->flags & FF_SILENT)) \