about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Src/builtin.c1
-rw-r--r--Src/params.c15
-rw-r--r--Src/zsh.h2
-rw-r--r--Test/runtests.zsh2
-rwxr-xr-xTest/ztst.zsh2
5 files changed, 17 insertions, 5 deletions
diff --git a/Src/builtin.c b/Src/builtin.c
index 26335a2e8..691734221 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2491,6 +2491,7 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
 		return NULL;
 	    }
 	}
+	pm->node.flags |= PM_DECLAREDNULL;
     } else {
 	if (idigit(*pname))
 	    zerrnam(cname, "not an identifier: %s", pname);
diff --git a/Src/params.c b/Src/params.c
index 122f5da7d..a0d4caf52 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2093,7 +2093,8 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
 	if (sav)
 	    *s = sav;
 	*pptr = s;
-	if (!pm || (pm->node.flags & PM_UNSET))
+	if (!pm || ((pm->node.flags & PM_UNSET) &&
+		    !(pm->node.flags & PM_DECLARED)))
 	    return NULL;
 	if (v)
 	    memset(v, 0, sizeof(*v));
@@ -3055,6 +3056,7 @@ assignsparam(char *s, char *val, int flags)
 	     * Don't warn about anything.
 	     */
 	    flags &= ~ASSPM_WARN;
+	    v->pm->node.flags &= ~PM_DECLAREDNULL;
 	}
 	*ss = '[';
 	v = NULL;
@@ -3080,6 +3082,7 @@ assignsparam(char *s, char *val, int flags)
     }
     if (flags & ASSPM_WARN)
 	check_warn_pm(v->pm, "scalar", created, 1);
+    v->pm->node.flags &= ~PM_DECLAREDNULL;
     if (flags & ASSPM_AUGMENT) {
 	if (v->start == 0 && v->end == -1) {
 	    switch (PM_TYPE(v->pm->node.flags)) {
@@ -3232,6 +3235,7 @@ assignaparam(char *s, char **val, int flags)
 
     if (flags & ASSPM_WARN)
 	check_warn_pm(v->pm, "array", created, may_warn_about_nested_vars);
+    v->pm->node.flags &= ~PM_DECLAREDNULL;
 
     /*
      * At this point, we may have array entries consisting of
@@ -3444,6 +3448,7 @@ sethparam(char *s, char **val)
 	    return NULL;
 	}
     check_warn_pm(v->pm, "associative array", checkcreate, 1);
+    v->pm->node.flags &= ~PM_DECLAREDNULL;
     setarrvalue(v, val);
     unqueue_signals();
     return v->pm;
@@ -3515,6 +3520,7 @@ assignnparam(char *s, mnumber val, int flags)
 	if (flags & ASSPM_WARN)
 	    check_warn_pm(v->pm, "numeric", 0, 1);
     }
+    v->pm->node.flags &= ~PM_DECLAREDNULL;
     setnumvalue(v, val);
     unqueue_signals();
     return v->pm;
@@ -3619,6 +3625,7 @@ unsetparam_pm(Param pm, int altflag, int exp)
     else
 	altremove = NULL;
 
+    pm->node.flags &= ~PM_DECLARED;	/* like ksh, not like bash */
     if (!(pm->node.flags & PM_UNSET))
 	pm->gsu.s->unsetfn(pm, exp);
     if (pm->env)
@@ -5035,6 +5042,7 @@ arrfixenv(char *s, char **t)
 
     if (isset(ALLEXPORT))
 	pm->node.flags |= PM_EXPORTED;
+    pm->node.flags &= ~PM_DECLAREDNULL;
 
     /*
      * Do not "fix" parameters that were not exported
@@ -5839,8 +5847,9 @@ printparamnode(HashNode hn, int printflags)
     Param peer = NULL;
 
     if (p->node.flags & PM_UNSET) {
-	if (printflags & (PRINT_POSIX_READONLY|PRINT_POSIX_EXPORT) &&
-	    p->node.flags & (PM_READONLY|PM_EXPORTED)) {
+	if ((printflags & (PRINT_POSIX_READONLY|PRINT_POSIX_EXPORT) &&
+	     p->node.flags & (PM_READONLY|PM_EXPORTED)) ||
+	    (p->node.flags & PM_DECLAREDNULL) == PM_DECLAREDNULL) {
 	    /*
 	     * Special POSIX rules: show the parameter as readonly/exported
 	     * even though it's unset, but with no value.
diff --git a/Src/zsh.h b/Src/zsh.h
index d70a4017c..e98f3e328 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1931,6 +1931,8 @@ struct tieddata {
 #define PM_DONTIMPORT	(1<<22)	/* do not import this variable              */
 #define PM_RESTRICTED	(1<<23) /* cannot be changed in restricted mode     */
 #define PM_UNSET	(1<<24)	/* has null value                           */
+#define PM_DECLARED	(1<<17) /* */
+#define PM_DECLAREDNULL (PM_DECLARED|PM_UNSET)
 #define PM_REMOVABLE	(1<<25)	/* special can be removed from paramtab     */
 #define PM_AUTOLOAD	(1<<26) /* autoloaded from module                   */
 #define PM_NORESTORE	(1<<27)	/* do not restore value of local special    */
diff --git a/Test/runtests.zsh b/Test/runtests.zsh
index 562234d91..b66d579b6 100644
--- a/Test/runtests.zsh
+++ b/Test/runtests.zsh
@@ -7,7 +7,7 @@ emulate zsh
 # protect from catastrophic failure of an individual test.
 # We could probably do that with subshells instead.
 
-integer success failure skipped retval
+integer success=0 failure=0 skipped=0 retval
 for file in "${(f)ZTST_testlist}"; do
   $ZTST_exe +Z -f $ZTST_srcdir/ztst.zsh $file
   retval=$?
diff --git a/Test/ztst.zsh b/Test/ztst.zsh
index e668ae942..a59c06dcf 100755
--- a/Test/ztst.zsh
+++ b/Test/ztst.zsh
@@ -60,7 +60,7 @@ ZTST_mainopts=(${(kv)options})
 ZTST_testdir=$PWD
 ZTST_testname=$1
 
-integer ZTST_testfailed
+integer ZTST_testfailed=0
 
 # This is POSIX nonsense.  Because of the vague feeling someone, somewhere
 # may one day need to examine the arguments of "tail" using a standard