summary refs log tree commit diff
diff options
context:
space:
mode:
authorBarton E. Schaefer <schaefer@zsh.org>2015-11-23 21:43:14 -0800
committerBarton E. Schaefer <schaefer@zsh.org>2015-11-23 21:43:14 -0800
commit4e90e27036d9bdaad71db895486f4895a5e6acf6 (patch)
tree0c3d92adf9c1585a08eecbb05f498a3e606aecf7
parentbc30d6bfca6f7b0a8578eecf468897975674d2b7 (diff)
downloadzsh-4e90e27036d9bdaad71db895486f4895a5e6acf6.tar.gz
zsh-4e90e27036d9bdaad71db895486f4895a5e6acf6.tar.xz
zsh-4e90e27036d9bdaad71db895486f4895a5e6acf6.zip
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
-rw-r--r--ChangeLog4
-rw-r--r--Src/Modules/param_private.c44
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  <schaefer@zsh.org>
 
+	* 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;
+	}
     }
 }