diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2022-10-18 03:58:19 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2022-10-18 03:58:19 +0200 |
commit | e471f9e0fb7ade475dd3eb8b230bcb440877ee7e (patch) | |
tree | 5d9c5a23474b9a9464e75cadf3e872042fa9097e | |
parent | 324252975004154cc70623c94f05083bff100209 (diff) |
Filter: Fix handling of variables in anonymous filters
Define scope for anonymous filters, and also explicitly distinguish block
scopes and function/filter scopes instead of using anonymous / named
distinction.
Anonymous filters forgot to push scope, so variables for them were in
fact defined in the top scope and therefore they shared a frame. This got
broken after rework of variables, which assumed that there is a named
scope for every function/filter.
-rw-r--r-- | conf/cf-lex.l | 6 | ||||
-rw-r--r-- | conf/conf.h | 7 | ||||
-rw-r--r-- | filter/config.Y | 16 |
3 files changed, 19 insertions, 10 deletions
diff --git a/conf/cf-lex.l b/conf/cf-lex.l index d6f46223..28d9ba50 100644 --- a/conf/cf-lex.l +++ b/conf/cf-lex.l @@ -812,7 +812,7 @@ cf_push_soft_scope(void) if (conf_this_scope->soft_scopes < 0xfe) conf_this_scope->soft_scopes++; else - cf_push_scope(NULL); + cf_push_block_scope(); } /** @@ -826,7 +826,7 @@ cf_pop_soft_scope(void) if (conf_this_scope->soft_scopes) conf_this_scope->soft_scopes--; else - cf_pop_scope(); + cf_pop_block_scope(); } /** @@ -841,7 +841,7 @@ cf_swap_soft_scope(void) if (conf_this_scope->soft_scopes) { conf_this_scope->soft_scopes--; - cf_push_scope(NULL); + cf_push_block_scope(); } } diff --git a/conf/conf.h b/conf/conf.h index be46f172..96c873df 100644 --- a/conf/conf.h +++ b/conf/conf.h @@ -134,6 +134,7 @@ struct sym_scope { struct symbol *name; /* Name of this scope */ uint slots; /* Variable slots */ byte active; /* Currently entered */ + byte block; /* No independent stack frame */ byte soft_scopes; /* Number of soft scopes above */ }; @@ -220,6 +221,12 @@ void cf_pop_scope(void); void cf_push_soft_scope(void); void cf_pop_soft_scope(void); +static inline void cf_push_block_scope(void) +{ cf_push_scope(NULL); conf_this_scope->block = 1; } + +static inline void cf_pop_block_scope(void) +{ ASSERT(conf_this_scope->block); cf_pop_scope(); } + char *cf_symbol_class_name(struct symbol *sym); /* Parser */ diff --git a/filter/config.Y b/filter/config.Y index f9d9b0b3..68ee1a84 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -28,9 +28,9 @@ f_new_var(struct sym_scope *s) /* * - A variable is an offset on vstack from vbase. * - Vbase is set on filter start / function call. - * - Scopes contain anonymous scopes (blocks) inside filter/function scope + * - Scopes contain (non-frame) block scopes inside filter/function scope * - Each scope knows number of vars in that scope - * - Offset is therefore a sum of 'slots' up to named scope + * - Offset is therefore a sum of 'slots' up to filter/function scope * - New variables are added on top of vstk, so intermediate values cannot * be there during FI_VAR_INIT. I.e. no 'var' inside 'term'. * - Also, each f_line must always have its scope, otherwise a variable may @@ -39,7 +39,7 @@ f_new_var(struct sym_scope *s) int offset = s->slots++; - while (!s->name) + while (s->block) { s = s->next; ASSERT(s); @@ -465,10 +465,12 @@ filter: cf_assert_symbol($1, SYM_FILTER); $$ = $1->filter; } - | filter_body { + | { cf_push_scope(NULL); } filter_body { struct filter *f = cfg_alloc(sizeof(struct filter)); - *f = (struct filter) { .root = $1 }; + *f = (struct filter) { .root = $2 }; $$ = f; + + cf_pop_scope(); } ; @@ -913,13 +915,13 @@ cmd: } | FOR { /* Reserve space for walk data on stack */ - cf_push_scope(NULL); + cf_push_block_scope(); conf_this_scope->slots += 2; } for_var IN /* Parse term in the parent scope */ { conf_this_scope->active = 0; } term { conf_this_scope->active = 1; } DO cmd { - cf_pop_scope(); + cf_pop_block_scope(); $$ = f_new_inst(FI_FOR_INIT, $6, $3); $$->next = f_new_inst(FI_FOR_NEXT, $3, $9); } |