about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Kiddle <opk@users.sourceforge.net>2002-10-17 09:11:33 +0000
committerOliver Kiddle <opk@users.sourceforge.net>2002-10-17 09:11:33 +0000
commit35b617afb498d692729ae0689f96991c4672d822 (patch)
tree20b7896a05a820a82924db78e31e7d011a6ae3a2
parent4aea39d960ea29da0c68f9d5f8d089a9be2dafab (diff)
downloadzsh-35b617afb498d692729ae0689f96991c4672d822.tar.gz
zsh-35b617afb498d692729ae0689f96991c4672d822.tar.xz
zsh-35b617afb498d692729ae0689f96991c4672d822.zip
17794: fix bugs with tied parameters
-rw-r--r--ChangeLog6
-rw-r--r--Src/builtin.c5
-rw-r--r--Src/params.c15
3 files changed, 25 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 43c106c37..608c7a3d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,12 @@
         * 17810 (Martin Waitz): Src/utils.c: bung up memory leak with
         POSIX.1e capabilities.
 
+2002-10-10  Oliver Kiddle  <opk@zsh.org>
+
+	* 17794: Src/builtin.c, Src/params.c: fix bugs with tied parameters
+	(prevent tying array elements and find correct parameter under
+	alternate name for unsetting)
+
 2002-10-06  Bart Schaefer  <schaefer@zsh.org>
 
 	* 17760: Src/lex.c Src/parse.c: Fix case-pattern parsing bug in sh
diff --git a/Src/builtin.c b/Src/builtin.c
index dd553cf1c..cb7c82052 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2006,6 +2006,11 @@ bin_typeset(char *name, char **argv, char *ops, int func)
 	    zerrnam(name, "can't tie a variable to itself", NULL, 0);
 	    return 1;
 	}
+	if (strchr(asg0.name, '[') || strchr(asg->name, '[')) {
+	    unqueue_signals();
+	    zerrnam(name, "can't tie array elements", NULL, 0);
+	    return 1;
+	}
 	/*
 	 * Keep the old value of the scalar.  We need to do this
 	 * here as if it is already tied to the same array it
diff --git a/Src/params.c b/Src/params.c
index f39f1012d..f461c15e0 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2111,8 +2111,21 @@ unsetparam_pm(Param pm, int altflag, int exp)
     /* remove it under its alternate name if necessary */
     if (pm->ename && !altflag) {
 	altpm = (Param) paramtab->getnode(paramtab, pm->ename);
-	if (altpm)
+	/* tied parameters are at the same local level as each other */
+	oldpm = NULL;
+	while (altpm && altpm->level > pm->level) {
+	    /* param under alternate name hidden by a local */
+	    oldpm = altpm;
+	    altpm = altpm->old;
+	}
+	if (altpm) {
+	    if (oldpm && !altpm->level) {
+		oldpm->old = NULL;
+		/* fudge things so removenode isn't called */
+		altpm->level = 1;
+	    }
 	    unsetparam_pm(altpm, 1, exp);
+	}
     }
 
     /*