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); }
|
'(' term ',' term ')' { $$ = f_new_inst(FI_PAIR_CONSTRUCT, $2, $4); }
|
||||||
| '(' ec_kind ',' term ',' term ')' { $$ = f_new_inst(FI_EC_CONSTRUCT, $4, $6, $2); }
|
| '(' 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); }
|
| '(' 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
|
const $1 $2 = whati->$2
|
||||||
FID_INTERPRET_BODY')
|
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.
|
# Instruction arguments are needed only until linearization is done.
|
||||||
# This puts the arguments into the filter line to be executed before
|
# This puts the arguments into the filter line to be executed before
|
||||||
# the instruction itself.
|
# the instruction itself.
|
||||||
|
@ -136,6 +117,48 @@ FID_LINEARIZE_BODY
|
||||||
pos = linearize(dest, whati->f$1, pos);
|
pos = linearize(dest, whati->f$1, pos);
|
||||||
FID_INTERPRET_BODY()')
|
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.
|
# Some arguments need to check their type. After that, ARG_ANY is called.
|
||||||
m4_define(ARG, `ARG_ANY($1)
|
m4_define(ARG, `ARG_ANY($1)
|
||||||
FID_INTERPRET_EXEC()m4_dnl
|
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 v1 whati->f1->i_FI_CONSTANT.val
|
||||||
#define v2 whati->f2->i_FI_CONSTANT.val
|
#define v2 whati->f2->i_FI_CONSTANT.val
|
||||||
#define v3 whati->f3->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 runtime(fmt, ...) cf_error("filter preevaluation, line %d: " fmt, ifs->lino, ##__VA_ARGS__)
|
||||||
#define fpool cfg_mem
|
#define fpool cfg_mem
|
||||||
#define falloc(size) cfg_alloc(size)
|
#define falloc(size) cfg_alloc(size)
|
||||||
|
@ -418,6 +442,7 @@ FID_WR_PUT(3)
|
||||||
#undef v1
|
#undef v1
|
||||||
#undef v2
|
#undef v2
|
||||||
#undef v3
|
#undef v3
|
||||||
|
#undef vv
|
||||||
|
|
||||||
/* Line dumpers */
|
/* Line dumpers */
|
||||||
#define INDENT (((const char *) f_dump_line_indent_str) + sizeof(f_dump_line_indent_str) - (indent) - 1)
|
#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?
|
* What is the syntax here?
|
||||||
* m4_dnl INST(FI_NOP, in, out) { enum value, input args, output args
|
* 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(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
|
* 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 LINE(num, unused); this argument has to be converted to its own f_line
|
||||||
* m4_dnl SYMBOL; symbol handed from config
|
* m4_dnl SYMBOL; symbol handed from config
|
||||||
* m4_dnl STATIC_ATTR; static attribute definition
|
* m4_dnl STATIC_ATTR; static attribute definition
|
||||||
|
@ -297,45 +298,19 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_PATHMASK_CONSTRUCT, 0, 1) {
|
INST(FI_PATHMASK_CONSTRUCT, 0, 1) {
|
||||||
ARG_ANY(1);
|
VARARG;
|
||||||
FID_MEMBER(uint, count, f1->count != f2->count, number of items %u, item->count);
|
|
||||||
|
|
||||||
FID_NEW_BODY
|
struct f_path_mask *pm = falloc(sizeof(struct f_path_mask) + whati->varcount * sizeof(struct f_path_mask_item));
|
||||||
uint len = 0;
|
pm->len = whati->varcount;
|
||||||
for (const struct f_inst *tt = f1; tt; tt = tt->next, len++);
|
|
||||||
|
|
||||||
whati->count = len;
|
for (uint i=0; i<whati->varcount; i++) {
|
||||||
struct f_inst **items;
|
switch (vv(i).type) {
|
||||||
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) {
|
|
||||||
case T_PATH_MASK_ITEM:
|
case T_PATH_MASK_ITEM:
|
||||||
pm->item[i] = pv(i).val.pmi;
|
pm->item[i] = vv(i).val.pmi;
|
||||||
break;
|
break;
|
||||||
case T_INT:
|
case T_INT:
|
||||||
pm->item[i] = (struct f_path_mask_item) {
|
pm->item[i] = (struct f_path_mask_item) {
|
||||||
.asn = pv(i).val.i,
|
.asn = vv(i).val.i,
|
||||||
.kind = PM_ASN,
|
.kind = PM_ASN,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -343,13 +318,7 @@
|
||||||
runtime( "Error resolving path mask template: value not an integer" );
|
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);
|
RESULT(T_PATH_MASK, path_mask, pm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,24 +448,11 @@
|
||||||
|
|
||||||
INST(FI_PRINT, 0, 0) {
|
INST(FI_PRINT, 0, 0) {
|
||||||
NEVER_CONSTANT;
|
NEVER_CONSTANT;
|
||||||
ARG_ANY(1);
|
VARARG;
|
||||||
FID_MEMBER_IN(uint, count, f1->count != f2->count, number of items %u, item->count);
|
|
||||||
|
|
||||||
FID_NEW_BODY
|
if (whati->varcount && !(fs->flags & FF_SILENT))
|
||||||
uint len = 0;
|
for (uint i=0; i<whati->varcount; i++)
|
||||||
for (const struct f_inst *tt = f1; tt; tt = tt->next, len++)
|
val_format(&(vv(i)), &fs->buf);
|
||||||
;
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INST(FI_DIE, 0, 0) {
|
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) {
|
switch (what->fi_code) {
|
||||||
#define res fstk->vstk[fstk->vcnt]
|
#define res fstk->vstk[fstk->vcnt]
|
||||||
#define v1 fstk->vstk[fstk->vcnt]
|
#define vv(i) fstk->vstk[fstk->vcnt + (i)]
|
||||||
#define v2 fstk->vstk[fstk->vcnt + 1]
|
#define v1 vv(0)
|
||||||
#define v3 fstk->vstk[fstk->vcnt + 2]
|
#define v2 vv(1)
|
||||||
|
#define v3 vv(2)
|
||||||
|
|
||||||
#define runtime(fmt, ...) do { \
|
#define runtime(fmt, ...) do { \
|
||||||
if (!(fs->flags & FF_SILENT)) \
|
if (!(fs->flags & FF_SILENT)) \
|
||||||
|
|
Loading…
Reference in a new issue