From 4e90e27036d9bdaad71db895486f4895a5e6acf6 Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Mon, 23 Nov 2015 21:43:14 -0800 Subject: 37208: assignment in a nested scope should not change private parameters in the outer scope from unset to set Bug remains that the attempt does not generate a warning --- ChangeLog | 4 ++++ Src/Modules/param_private.c | 44 ++++++++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 87fac0917..3a0eab704 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2015-11-23 Barton E. Schaefer + * 37208: Src/Modules/param_private.c: assignment in a nested scope + should not change private parameters in the outer scope from unset + to set; bug remains that the attempt does not generate a warning + * 37206: Src/subst.c: fix ${(t)param} for "typeset -H param" * 37205: Test/B01cd.ztst: update documentary comment diff --git a/Src/Modules/param_private.c b/Src/Modules/param_private.c index 7f9aa7921..7d1ba9c87 100644 --- a/Src/Modules/param_private.c +++ b/Src/Modules/param_private.c @@ -218,8 +218,10 @@ setfn_error(Param pm) * The unsetfn family compare locallevel and restore the old GSU before * calling the original unsetfn. This assures that if the old unsetfn * wants to use its getfn or setfn, they're unconditionally present. + * The "explicit" flag indicates that "unset" was called, if zero the + * parameter is going out of scope (see params.c). * - */ + */ /**/ static char * @@ -248,13 +250,15 @@ pps_setfn(Param pm, char *x) /**/ static void -pps_unsetfn(Param pm, int x) +pps_unsetfn(Param pm, int explicit) { struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.s); GsuScalar gsu = (GsuScalar)(c->g); pm->gsu.s = gsu; if (locallevel <= pm->level) - gsu->unsetfn(pm, x); + gsu->unsetfn(pm, explicit); + if (explicit) + pm->gsu.s = (GsuScalar)c; } /**/ @@ -283,13 +287,15 @@ ppi_setfn(Param pm, zlong x) /**/ static void -ppi_unsetfn(Param pm, int x) +ppi_unsetfn(Param pm, int explicit) { struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.i); GsuInteger gsu = (GsuInteger)(c->g); pm->gsu.i = gsu; if (locallevel <= pm->level) - gsu->unsetfn(pm, x); + gsu->unsetfn(pm, explicit); + if (explicit) + pm->gsu.i = (GsuInteger)c; } /**/ @@ -318,13 +324,15 @@ ppf_setfn(Param pm, double x) /**/ static void -ppf_unsetfn(Param pm, int x) +ppf_unsetfn(Param pm, int explicit) { struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.f); GsuFloat gsu = (GsuFloat)(c->g); pm->gsu.f = gsu; if (locallevel <= pm->level) - gsu->unsetfn(pm, x); + gsu->unsetfn(pm, explicit); + if (explicit) + pm->gsu.f = (GsuFloat)c; } /**/ @@ -354,13 +362,15 @@ ppa_setfn(Param pm, char **x) /**/ static void -ppa_unsetfn(Param pm, int x) +ppa_unsetfn(Param pm, int explicit) { struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.a); GsuArray gsu = (GsuArray)(c->g); pm->gsu.a = gsu; if (locallevel <= pm->level) - gsu->unsetfn(pm, x); + gsu->unsetfn(pm, explicit); + if (explicit) + pm->gsu.a = (GsuArray)c; } static HashTable emptytable; @@ -391,13 +401,15 @@ pph_setfn(Param pm, HashTable x) /**/ static void -pph_unsetfn(Param pm, int x) +pph_unsetfn(Param pm, int explicit) { struct gsu_closure *c = (struct gsu_closure *)(pm->gsu.h); GsuHash gsu = (GsuHash)(c->g); pm->gsu.h = gsu; if (locallevel <= pm->level) - gsu->unsetfn(pm, x); + gsu->unsetfn(pm, explicit); + if (explicit) + pm->gsu.h = (GsuHash)c; } /* @@ -425,9 +437,13 @@ scopeprivate(HashNode hn, int onoff) pm->node.flags |= PM_NORESTORE; else pm->node.flags |= PM_UNSET; - else if (!(pm->node.flags & PM_NORESTORE)) - pm->node.flags &= ~PM_UNSET; - pm->node.flags &= ~PM_NORESTORE; + else { + if (pm->node.flags & PM_NORESTORE) + pm->node.flags |= PM_UNSET; /* createparam() may frob */ + else + pm->node.flags &= ~PM_UNSET; + pm->node.flags &= ~PM_NORESTORE; + } } } -- cgit 1.4.1