From 8bc64084a46c79be5659ef42c746a3b806816c7f Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 31 Aug 2010 19:32:56 +0000 Subject: 28220 plus some comments: fix "HELLO=$HELLO shellfunc" --- ChangeLog | 7 ++++++- Src/exec.c | 26 +++++++++++++++++++++++--- Src/params.c | 27 ++++++++++++++++++--------- Test/A06assign.ztst | 15 +++++++++++++++ 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b4c85f7e..b704d2968 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2010-08-31 Peter Stephenson + * 28220: Src/exec.c (plus comments), Src/params.c, + Test/A06assign.ztst: "HELLO=$HELLO shellfunc" failed because + we removed HELLO from the parameter table to save it. Copy it + instead. + * Mikael: 28202: Src/Zle/complist.c: need line unmetafied for reversemenucomplete(). @@ -13576,5 +13581,5 @@ ***************************************************** * This is used by the shell to define $ZSH_PATCHLEVEL -* $Revision: 1.5065 $ +* $Revision: 1.5066 $ ***************************************************** diff --git a/Src/exec.c b/Src/exec.c index 3ab4aa90b..e866639b9 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -3313,13 +3313,32 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p) while (wc_code(ac = *pc) == WC_ASSIGN) { s = ecrawstr(state->prog, pc + 1, NULL); if ((pm = (Param) paramtab->getnode(paramtab, s))) { + Param tpm; if (pm->env) delenv(pm); if (!(pm->node.flags & PM_SPECIAL)) { - paramtab->removenode(paramtab, s); + /* + * We used to remove ordinary parameters from the + * table, but that meant "HELLO=$HELLO shellfunc" + * failed because the expansion of $HELLO hasn't + * been done at this point. Instead, copy the + * parameter: in this case, we'll insert the + * copied parameter straight back into the parameter + * table so we wan't to be sure everything is + * properly set up and in permanent memory. + */ + tpm = (Param) zshcalloc(sizeof *tpm); + tpm->node.nam = ztrdup(pm->node.nam); + copyparam(tpm, pm, 0); + pm = tpm; } else if (!(pm->node.flags & PM_READONLY) && (unset(RESTRICTED) || !(pm->node.flags & PM_RESTRICTED))) { - Param tpm = (Param) hcalloc(sizeof *tpm); + /* + * In this case we're just saving parts of + * the parameter in a tempory, so use heap allocation + * and don't bother copying every detail. + */ + tpm = (Param) hcalloc(sizeof *tpm); tpm->node.nam = pm->node.nam; copyparam(tpm, pm, 1); pm = tpm; @@ -3383,8 +3402,9 @@ restore_params(LinkList restorelist, LinkList removelist) break; } pm = tpm; - } else + } else { paramtab->addnode(paramtab, pm->node.nam, pm); + } if ((pm->node.flags & PM_EXPORTED) && ((s = getsparam(pm->node.nam)))) addenv(pm, s); } diff --git a/Src/params.c b/Src/params.c index 8a34618fe..9a9f45893 100644 --- a/Src/params.c +++ b/Src/params.c @@ -927,11 +927,17 @@ createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan, int flags) } -/* Copy a parameter */ +/* + * Copy a parameter + * + * If fakecopy is set, we are just saving the details of a special + * parameter. Otherwise, the result will be used as a real parameter + * and we need to do more work. + */ /**/ void -copyparam(Param tpm, Param pm, int toplevel) +copyparam(Param tpm, Param pm, int fakecopy) { /* * Note that tpm, into which we're copying, may not be in permanent @@ -942,7 +948,8 @@ copyparam(Param tpm, Param pm, int toplevel) tpm->node.flags = pm->node.flags; tpm->base = pm->base; tpm->width = pm->width; - if (!toplevel) + tpm->level = pm->level; + if (!fakecopy) tpm->node.flags &= ~PM_SPECIAL; switch (PM_TYPE(pm->node.flags)) { case PM_SCALAR: @@ -963,13 +970,15 @@ copyparam(Param tpm, Param pm, int toplevel) break; } /* - * If called from inside an associative array, that array is later going - * to be passed as a real parameter, so we need the gets and sets - * functions to be useful. However, the saved associated array is - * not itself special, so we just use the standard ones. - * This is also why we switch off PM_SPECIAL. + * If the value is going to be passed as a real parameter (e.g. this is + * called from inside an associative array), we need the gets and sets + * functions to be useful. + * + * In this case we assume the the saved parameter is not itself special, + * so we just use the standard functions. This is also why we switch off + * PM_SPECIAL. */ - if (!toplevel) + if (!fakecopy) assigngetset(tpm); } diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst index bbed909c5..44c8e3193 100644 --- a/Test/A06assign.ztst +++ b/Test/A06assign.ztst @@ -277,3 +277,18 @@ > > > + + call() { print $HELLO; } + export HELLO=world + call + HELLO=universe call + call + HELLO=${HELLO}liness call + call + unset HELLO +0:save and restore when using original value in temporary +>world +>universe +>world +>worldliness +>world -- cgit 1.4.1