diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2022-04-11 21:08:06 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2022-04-11 21:08:06 -0700 |
commit | 97294a20f0121b5edd0e709375a5c18d013d258e (patch) | |
tree | 6b27697bf15fb4a3e2a136d7ac667118658c3037 | |
parent | 5a0d83f4b42b9ca28cc6b8dd190a570c47b203c8 (diff) | |
download | egawk-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.y | 18 |
1 files changed, 12 insertions, 6 deletions
@@ -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 */ |