Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: 'typeset -xp'/'export -p' shows unset exported variables as set & empty



On Oct 22,  5:29pm, Martijn Dekker wrote:
} Subject: 'typeset -xp'/'export -p' shows unset exported variables as set &
}
} $ unset -v foo
} $ export foo
} $ typeset -xp foo
} typeset -x foo=''
} 
} Expected output:
} typeset -x foo

This is a sticky one.  "export foo" causes it to become set again:

torch% unset -v foo
torch% print $+foo
0
torch% export foo
torch% print $+foo
1
torch% 

And unsetting it after exporting it causes it to no longer be exported.

There has previously been discussion of the fact that zsh differs in
this regard -- namely, that declaring a variable implies that it has
become set, and you must thereafter explicitly unset it -- but zsh
also handles environment variables differently, in that the value is
not actually exported until it is explicitly assigned, even though
the variable appears to be set.

There's also the issue that zsh is able to declare local exports, but
"export" is equivalent to "typeset -gx", which encompasses the further
oddball case that

  () { local foo; () { export foo } }

*does* cause the empty value of foo to be exported into the environment,
for the duration of the outer scope where foo was declared.

The following patch faithfully reports that latter condition without any
attempt to "correct" it, and also changes the command name per 39701.  It
further adds the -g option to typeset when invoked from a function scope
and the parameter is not local.

Also moves the handling of autoloaded parameters from printparamvalue()
to printparamnode() because that seemed to make more sense.

There are a whole lot of possible combinations here so it's possible that
I have missed some.  Tests updated.


diff --git a/Src/params.c b/Src/params.c
index 1418021..3084b1f 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -5225,7 +5225,7 @@ printparamvalue(Param p, int printflags)
 {
     char *t, **u;
 
-    if (p->node.flags & PM_AUTOLOAD) {
+    if ((p->node.flags & PM_EXPORTED) && !p->env) {
 	putchar('\n');
 	return;
     }
@@ -5312,9 +5312,13 @@ printparamnode(HashNode hn, int printflags)
 	     */
 	    printflags |= PRINT_NAMEONLY;
 	}
+	else if (p->node.flags & PM_EXPORTED)
+	    printflags |= PRINT_NAMEONLY;
 	else
 	    return;
     }
+    if (p->node.flags & PM_AUTOLOAD)
+	printflags |= PRINT_NAMEONLY;
 
     if (printflags & PRINT_TYPESET) {
 	if ((p->node.flags & (PM_READONLY|PM_SPECIAL)) ==
@@ -5326,7 +5330,14 @@ printparamnode(HashNode hn, int printflags)
 	     */
 	    return;
 	}
-	printf("typeset ");
+	if (locallevel && p->level >= locallevel) {
+	    printf("typeset ");	    /* printf("local "); */
+	} else if (p->node.flags & PM_EXPORTED) {
+	    printf("export ");
+	} else if (locallevel) {
+	    printf("typeset -g ");
+	} else
+	    printf("typeset ");
     }
 
     /* Print the attributes of the parameter */
@@ -5339,7 +5350,9 @@ printparamnode(HashNode hn, int printflags)
 	    if (pmptr->flags & PMTF_TEST_LEVEL) {
 		if (p->level)
 		    doprint = 1;
-	    } else if (p->node.flags & pmptr->binflag)
+	    } else if ((pmptr->binflag != PM_EXPORTED ||
+			((p->node.flags & PM_LOCAL) || p->level)) &&
+		       (p->node.flags & pmptr->binflag))
 		doprint = 1;
 
 	    if (doprint) {
@@ -5351,9 +5364,8 @@ printparamnode(HashNode hn, int printflags)
 			}
 			putchar(pmptr->typeflag);
 		    }
-		} else {
+		} else
 		    printf("%s ", pmptr->string);
-		}
 		if ((pmptr->flags & PMTF_USE_BASE) && p->base) {
 		    printf("%d ", p->base);
 		    doneminus = 0;
diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst
index d6d2421..6d85a63 100644
--- a/Test/B02typeset.ztst
+++ b/Test/B02typeset.ztst
@@ -454,7 +454,7 @@
  fn() { typeset -p array nonexistent; }
  fn
 1:declare -p shouldn't create scoped values
->typeset -a array=( foo bar )
+>typeset -g -a array=( foo bar )
 ?fn:typeset: no such variable: nonexistent
 
  unsetopt typesetsilent
@@ -490,7 +490,7 @@
 ?0
 ?(eval):5: read-only variable: pbro
 ?(eval):6: read-only variable: pbro
-?typeset -r pbro
+?typeset -g -r pbro
 ?0
 ?(eval):10: read-only variable: pbro
 
diff --git a/Test/B03print.ztst b/Test/B03print.ztst
index befe2f2..a4431cb 100644
--- a/Test/B03print.ztst
+++ b/Test/B03print.ztst
@@ -308,5 +308,5 @@
  printf -v foo "%s\0%s-" into the breach
  typeset -p foo
 0:print and printf into a variable
->typeset foo='once more'
->typeset foo=$'into\C-@the-breach\C-@-'
+>typeset -g foo='once more'
+>typeset -g foo=$'into\C-@the-breach\C-@-'
diff --git a/Test/V10private.ztst b/Test/V10private.ztst
index 320e357..7ebf5a8 100644
--- a/Test/V10private.ztst
+++ b/Test/V10private.ztst
@@ -129,7 +129,7 @@
 0:private hides value from surrounding scope in nested scope
 >typeset -a hash_test=( top level )
 >typeset -A hash_test=( in function )
->typeset -a hash_test=( top level )
+>typeset -g -a hash_test=( top level )
 >array-local top level
 >top level
 F:note "typeset" rather than "private" in output from outer



Messages sorted by: Reverse Date, Date, Thread, Author