aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-04-11 21:08:06 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-04-11 21:08:06 -0700
commit97294a20f0121b5edd0e709375a5c18d013d258e (patch)
tree6b27697bf15fb4a3e2a136d7ac667118658c3037
parent5a0d83f4b42b9ca28cc6b8dd190a570c47b203c8 (diff)
downloadegawk-97294a20f0121b5edd0e709375a5c18d013d258e.tar.gz
egawk-97294a20f0121b5edd0e709375a5c18d013d258e.tar.bz2
egawk-97294a20f0121b5edd0e709375a5c18d013d258e.zip
@let: bugfix: two free lists are needed.
When functions containing let are compiled, they leave nodes on the let_free list. These nodes are of the wrong type for re-use by the compilation of an external @let. That causes a crash. Secondly, when we compile a function, we free the let_free list. This is also bad, because if it contains nodes allocated by the compilation of external lets, we would like those to be re-used for subsequent external lets after that function, and not to allocate new variables. * awkgram.y (let_gfree): New static variable. (statement): In the aftermath of the @let statement, when returning the variable nodes to the free list, we now choose which of the two free lists to return to based on whether we are inside a function. (add_let): Try to allocate from let_free if a function is being compiled, otherwise from let_gfree.
-rw-r--r--awkgram.y18
1 files changed, 12 insertions, 6 deletions
diff --git a/awkgram.y b/awkgram.y
index 44a4a48c..285c233a 100644
--- a/awkgram.y
+++ b/awkgram.y
@@ -126,7 +126,8 @@ static enum {
} want_param_names = DONT_CHECK; /* ditto */
static INSTRUCTION *in_function; /* parsing kludge */
static int in_loop; /* parsing kludge */
-static NODE *let_free; /* free list of lexical vars */
+static NODE *let_free; /* free list of function lexical vars */
+static NODE *let_gfree; /* free list of external lexical vars */
static NODE *let_stack; /* stack of allocated lexicals */
static int rule = 0;
@@ -1066,6 +1067,8 @@ regular_loop:
let_var_list_opt r_paren opt_nls statement
{
NODE *old_let_stack = $2->memory;
+ NODE **pfreelist = in_function ? &let_free : &let_gfree;
+ NODE *freelist = *pfreelist;
if ($7 != NULL) {
merge_comments($7, NULL);
@@ -1085,12 +1088,14 @@ regular_loop:
/* pop from let stack */
let_stack = let->nxparam;
/* push onto free list */
- let->nxparam = let_free;
- let_free = let;
+ let->nxparam = freelist;
+ freelist = let;
/* scrub from symbol table */
remove_let(let);
}
+ *pfreelist = freelist;
+
yyerrok;
}
| non_compound_stmt
@@ -5240,6 +5245,7 @@ add_let(INSTRUCTION *fi, INSTRUCTION *local)
NODE *f = fi != NULL ? fi->func_body : NULL;
const char *fname = f != NULL ? f->vname : NULL;
const char *name = estrdup(local->lextok, strlen(local->lextok));
+ NODE **pfreelist = in_function ? &let_free : &let_gfree;
/* Basic checks:*/
check_local(fname, name, local);
@@ -5249,10 +5255,10 @@ add_let(INSTRUCTION *fi, INSTRUCTION *local)
/*
* Try to get lexical from the free list.
*/
- if (let_free) {
+ if (*pfreelist) {
/* pop let from stack */
- NODE *let = let_free;
- let_free = let_free->nxparam;
+ NODE *let = *pfreelist;
+ *pfreelist = let->nxparam;
/* register in param or alias table under the given name */
install_let(let, name);
/* push onto let stack */