From ba91f4c831f057b81104d1453f99b012c01f9c9e Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Tue, 31 Oct 2023 12:03:49 +0100 Subject: [PATCH] Filters: allowing to return any number of values --- filter/filter.c | 31 ++++++++++++------------------- filter/filter.h | 2 +- proto/static/static.c | 2 +- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/filter/filter.c b/filter/filter.c index 4c0f6f12..396b7333 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -160,7 +160,7 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS; * TWOARGS macro to get both of them evaluated. */ static enum filter_return -interpret(struct filter_state *fs, const struct f_line *line, uint argc, const struct f_val *argv, struct f_val *val) +interpret(struct filter_state *fs, const struct f_line *line, uint argc, const struct f_val *argv, uint resc, struct f_val *resv) { /* Check of appropriate number of arguments */ ASSERT(line->args == argc); @@ -225,21 +225,14 @@ interpret(struct filter_state *fs, const struct f_line *line, uint argc, const s fstk->ecnt--; } - if (fstk->vcnt == 0) { - if (val) { - log_rl(&rl_runtime_err, L_ERR "filters: No value left on stack"); - return F_ERROR; - } - return F_NOP; + if (fstk->vcnt != resc) + { + log_rl(&rl_runtime_err, L_ERR "Filter expected to leave %d values on stack but %d left instead", resc, fstk->vcnt); + return F_ERROR; } - if (val && (fstk->vcnt == 1)) { - *val = fstk->vstk[0]; - return F_NOP; - } - - log_rl(&rl_runtime_err, L_ERR "Too many items left on stack: %u", fstk->vcnt); - return F_ERROR; + memcpy(resv, fstk->vstk, sizeof(struct f_val) * resc); + return F_NOP; } @@ -296,7 +289,7 @@ f_run_args(const struct filter *filter, struct rte **rte, struct linpool *tmp_po LOG_BUFFER_INIT(filter_state.buf); /* Run the interpreter itself */ - enum filter_return fret = interpret(&filter_state, filter->root, argc, argv, NULL); + enum filter_return fret = interpret(&filter_state, filter->root, argc, argv, 0, NULL); if (filter_state.old_rta) { /* @@ -348,7 +341,7 @@ f_run_args(const struct filter *filter, struct rte **rte, struct linpool *tmp_po */ enum filter_return -f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, struct f_val *pres) +f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, uint resc, struct f_val *resv) { filter_state = (struct filter_state) { .stack = &filter_stack, @@ -358,14 +351,14 @@ f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool LOG_BUFFER_INIT(filter_state.buf); - return interpret(&filter_state, expr, argc, argv, pres); + return interpret(&filter_state, expr, argc, argv, resc, resv); } /* * f_eval - get a value of a term * @expr: filter line containing the term * @tmp_pool: long data may get allocated from this pool - * @pres: here the output will be stored + * @pres: here the output will be stored if requested */ enum filter_return f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) @@ -377,7 +370,7 @@ f_eval(const struct f_line *expr, struct linpool *tmp_pool, struct f_val *pres) LOG_BUFFER_INIT(filter_state.buf); - enum filter_return fret = interpret(&filter_state, expr, 0, NULL, pres); + enum filter_return fret = interpret(&filter_state, expr, 0, NULL, !!pres, pres); return fret; } diff --git a/filter/filter.h b/filter/filter.h index 18ff0874..c4b1796d 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -53,7 +53,7 @@ struct rte; enum filter_return f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags); enum filter_return f_run_args(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, int flags); -enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, struct f_val *pres); +enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool, uint argc, const struct f_val *argv, uint resc, struct f_val *resv); enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf); struct f_val cf_eval(const struct f_inst *inst, int type); diff --git a/proto/static/static.c b/proto/static/static.c index cf7a4768..2d2ac310 100644 --- a/proto/static/static.c +++ b/proto/static/static.c @@ -113,7 +113,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r) net_copy(e->net->n.addr, r->net); /* Evaluate the filter */ - f_eval_rte(r->cmds, &e, static_lp, 0, NULL, NULL); + f_eval_rte(r->cmds, &e, static_lp, 0, NULL, 0, NULL); /* Remove the temporary node */ e->net = NULL;