Filter: Converted FI_PRINT and FI_PATHMASK_CONSTRUCT to VARARG
This commit is contained in:
parent
c29d73a06a
commit
c0999a149c
4 changed files with 63 additions and 81 deletions
|
@ -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); }
|
||||
;
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
VARARG;
|
||||
|
||||
FID_NEW_BODY
|
||||
uint len = 0;
|
||||
for (const struct f_inst *tt = f1; tt; tt = tt->next, len++);
|
||||
struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->varcount * sizeof(struct f_path_mask_item));
|
||||
pm->len = whati->varcount;
|
||||
|
||||
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)]
|
||||
|
||||
FID_INTERPRET_NEW
|
||||
#define pv(i) items[i]->i_FI_CONSTANT.val
|
||||
|
||||
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);
|
||||
VARARG;
|
||||
|
||||
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
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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)) \
|
||||
|
|
Loading…
Reference in a new issue