zsh-workers
 help / color / mirror / code / Atom feed
From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: 'typeset -xp'/'export -p' shows unset exported variables as set & empty
Date: Sat, 22 Oct 2016 11:42:29 -0700	[thread overview]
Message-ID: <161022114229.ZM6231@torch.brasslantern.com> (raw)
In-Reply-To: <7c7d2198-bbec-0420-bd55-4f588a2767cf@inlv.org>

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


      reply	other threads:[~2016-10-22 18:42 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-22 15:29 Martijn Dekker
2016-10-22 18:42 ` Bart Schaefer [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=161022114229.ZM6231@torch.brasslantern.com \
    --to=schaefer@brasslantern.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).