summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2022-03-09 02:32:29 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2022-06-27 21:13:32 +0200
commita2527ee53d9d8fe7a1c29b56f8450b9ef1f9c7bc (patch)
treea4dbac6cea35ef3c675c9a12b37dc67719b1b5ac /filter
parentf31f4e6eef1762a4b9bf54a274f1ba9e9e161802 (diff)
Filter: Improve handling of stack frames in filter bytecode
When f_line is done, we have to pop the stack frame. The old code just removed nominal number of args/vars. Change it to use stored ventry value modified by number of returned values. This allows to allocate variables on a stack frame during execution of f_lines instead of just at start. But we need to know the number of returned values for a f_line. It is 1 for term, 0 for cmd. Store that to f_line during linearization.
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y14
-rw-r--r--filter/decl.m46
-rw-r--r--filter/f-inst.c8
-rw-r--r--filter/f-inst.h7
-rw-r--r--filter/f-util.c2
-rw-r--r--filter/filter.c3
6 files changed, 21 insertions, 19 deletions
diff --git a/filter/config.Y b/filter/config.Y
index a3acf245..b67ca925 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -329,7 +329,7 @@ filter_def:
conf: filter_eval ;
filter_eval:
- EVAL term { f_eval_int(f_linearize($2)); }
+ EVAL term { f_eval_int(f_linearize($2, 1)); }
;
conf: custom_attr ;
@@ -453,7 +453,7 @@ where_filter:
function_body:
function_vars '{' cmds '}' {
- $$ = f_linearize($3);
+ $$ = f_linearize($3, 0);
$$->vars = $1;
}
;
@@ -537,7 +537,7 @@ set_atom:
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' {
- if (f_eval(f_linearize($2), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
+ if (f_eval(f_linearize($2, 1), cfg_mem, &($$)) > F_RETURN) cf_error("Runtime error");
if (!f_valid_set_type($$.type)) cf_error("Set-incompatible type");
}
| CF_SYM_KNOWN {
@@ -549,13 +549,13 @@ set_atom:
switch_atom:
NUM { $$.type = T_INT; $$.val.i = $1; }
- | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2)); }
+ | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int(f_linearize($2, 1)); }
| fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
;
cnum:
- term { $$ = f_eval_int(f_linearize($1)); }
+ term { $$ = f_eval_int(f_linearize($1, 1)); }
pair_item:
'(' cnum ',' cnum ')' { $$ = f_new_pair_item($2, $2, $4, $4); }
@@ -642,7 +642,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
| switch_body switch_items ':' cmds {
/* Fill data fields */
struct f_tree *t;
- struct f_line *line = f_linearize($4);
+ struct f_line *line = f_linearize($4, 0);
for (t = $2; t; t = t->left)
t->data = line;
$$ = f_merge_items($1, $2);
@@ -651,7 +651,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
struct f_tree *t = f_new_tree();
t->from.type = t->to.type = T_VOID;
t->right = t;
- t->data = f_linearize($3);
+ t->data = f_linearize($3, 0);
$$ = f_merge_items($1, t);
}
;
diff --git a/filter/decl.m4 b/filter/decl.m4
index 3d118e34..4c56cd9c 100644
--- a/filter/decl.m4
+++ b/filter/decl.m4
@@ -216,7 +216,7 @@ whati->f$1 = f$1;
FID_DUMP_BODY()m4_dnl
f_dump_line(item->fl$1, indent + 1);
FID_LINEARIZE_BODY()m4_dnl
-item->fl$1 = f_linearize(whati->f$1);
+item->fl$1 = f_linearize(whati->f$1, $2);
FID_SAME_BODY()m4_dnl
if (!f_same(f1->fl$1, f2->fl$1)) return 0;
FID_ITERATE_BODY()m4_dnl
@@ -568,7 +568,7 @@ FID_WR_PUT(8)
}
struct f_line *
-f_linearize_concat(const struct f_inst * const inst[], uint count)
+f_linearize_concat(const struct f_inst * const inst[], uint count, uint results)
{
uint len = 0;
for (uint i=0; i<count; i++)
@@ -580,6 +580,8 @@ f_linearize_concat(const struct f_inst * const inst[], uint count)
for (uint i=0; i<count; i++)
out->len = linearize(out, inst[i], out->len);
+ out->results = results;
+
#ifdef LOCAL_DEBUG
f_dump_line(out, 0);
#endif
diff --git a/filter/f-inst.c b/filter/f-inst.c
index e75b5e01..5b8310c3 100644
--- a/filter/f-inst.c
+++ b/filter/f-inst.c
@@ -64,7 +64,7 @@
* m4_dnl ARG_ANY(num); argument with no type check accessible by v1, v2, v3
* m4_dnl ARG_TYPE(num, type); just declare the type of argument
* 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, out); 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
* m4_dnl DYNAMIC_ATTR; dynamic attribute definition
@@ -298,7 +298,7 @@
RESULT_TYPE(T_BOOL);
if (v1.val.i)
- LINE(2,0);
+ LINE(2,1);
else
RESULT_VAL(v1);
}
@@ -308,7 +308,7 @@
RESULT_TYPE(T_BOOL);
if (!v1.val.i)
- LINE(2,0);
+ LINE(2,1);
else
RESULT_VAL(v1);
}
@@ -536,7 +536,7 @@
if (v1.val.i)
LINE(2,0);
else
- LINE(3,1);
+ LINE(3,0);
}
INST(FI_PRINT, 0, 0) {
diff --git a/filter/f-inst.h b/filter/f-inst.h
index 58563c79..e35f71c6 100644
--- a/filter/f-inst.h
+++ b/filter/f-inst.h
@@ -46,14 +46,15 @@ struct f_line {
uint len; /* Line length */
u8 args; /* Function: Args required */
u8 vars;
+ u8 results; /* Results left on stack: cmd -> 0, term -> 1 */
struct f_arg *arg_list;
struct f_line_item items[0]; /* The items themselves */
};
/* Convert the f_inst infix tree to the f_line structures */
-struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count);
-static inline struct f_line *f_linearize(const struct f_inst *root)
-{ return f_linearize_concat(&root, 1); }
+struct f_line *f_linearize_concat(const struct f_inst * const inst[], uint count, uint results);
+static inline struct f_line *f_linearize(const struct f_inst *root, uint results)
+{ return f_linearize_concat(&root, 1, results); }
void f_dump_line(const struct f_line *, uint indent);
diff --git a/filter/f-util.c b/filter/f-util.c
index 410999a6..fdb314b5 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -37,7 +37,7 @@ struct filter *f_new_where(struct f_inst *where)
f_new_inst(FI_DIE, F_REJECT));
struct filter *f = cfg_allocz(sizeof(struct filter));
- f->root = f_linearize(cond);
+ f->root = f_linearize(cond, 0);
return f;
}
diff --git a/filter/filter.c b/filter/filter.c
index e505d570..20a380dc 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -215,8 +215,7 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
}
/* End of current line. Drop local variables before exiting. */
- fstk->vcnt -= curline.line->vars;
- fstk->vcnt -= curline.line->args;
+ fstk->vcnt = curline.ventry + curline.line->results;
fstk->ecnt--;
}