about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBart Schaefer <schaefer@zsh.org>2024-03-12 18:00:19 -0700
committerBart Schaefer <schaefer@zsh.org>2024-03-12 18:00:19 -0700
commit7c875adb0968b308e9b989ae5ac8d245b58810f2 (patch)
treec6f1d08a2ab28163985f7e7beb9f030439b49947
parent37f434498eb626a10e3009216afa306e5ae841c6 (diff)
downloadzsh-7c875adb0968b308e9b989ae5ac8d245b58810f2.tar.gz
zsh-7c875adb0968b308e9b989ae5ac8d245b58810f2.tar.xz
zsh-7c875adb0968b308e9b989ae5ac8d245b58810f2.zip
52742: fix bad interactions of "typeset -p" with GLOBAL_EXPORT
-rw-r--r--ChangeLog5
-rw-r--r--Src/builtin.c35
2 files changed, 32 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index f136bc6b4..c8935fb61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2024-03-12  Bart Schaefer  <schaefer@zsh.org>
+
+	* 52742: Src/builtin.c: fix bad interactions of "typeset -p" with
+	GLOBAL_EXPORT, plus some other inconsistencies.
+
 2024-03-13  Oliver Kiddle  <opk@zsh.org>
 
 	* 52724: Src/Modules/hlgroup.c: fix .zle.sgr for empty sequences
diff --git a/Src/builtin.c b/Src/builtin.c
index 829b899f8..7bfb1ce1d 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2059,7 +2059,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
      * POSIXBUILTINS horror: we need to retain the 'readonly' or 'export'
      * flags of an unset parameter.
      */
-    usepm = pm && (!(pm->node.flags & PM_UNSET) ||
+    usepm = pm && (!(pm->node.flags & PM_UNSET) || OPT_ISSET(ops, 'p') ||
 		   (isset(POSIXBUILTINS) &&
 		    (pm->node.flags & (PM_READONLY|PM_EXPORTED))));
 
@@ -2195,7 +2195,7 @@ typeset_single(char *cname, char *pname, Param pm, int func,
     else if (newspecial != NS_NONE && strcmp(pname, "SECONDS") == 0)
 	newspecial = NS_SECONDS;
 
-    if (isset(POSIXBUILTINS)) {
+    if (isset(POSIXBUILTINS) && !OPT_ISSET(ops,'p')) {
 	/*
 	 * Stricter rules about retaining readonly attribute in this case.
 	 */
@@ -2224,7 +2224,8 @@ typeset_single(char *cname, char *pname, Param pm, int func,
      *   ii. we are creating a new local parameter
      */
     if (usepm) {
-	if (OPT_MINUS(ops,'p') && on && !(on & pm->node.flags))
+	if (OPT_MINUS(ops,'p') && on &&
+	    !((on & pm->node.flags) || ((on & PM_LOCAL) && pm->level)))
 	    return NULL;
 	else if (OPT_PLUS(ops,'p') && off && !(off & pm->node.flags))
 	    return NULL;
@@ -2339,7 +2340,8 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	    return NULL;
 	pm->node.flags |= (on & PM_READONLY);
 	return pm;
-    }
+    } else if (OPT_ISSET(ops,'p'))
+	return NULL;	/* Nothing to print */
 
     if ((asg->flags & ASG_ARRAY) ?
 	!(on & (PM_ARRAY|PM_HASHED)) :
@@ -2686,6 +2688,15 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
     if (func == BIN_READONLY && isset(POSIXBUILTINS) && !OPT_PLUS(ops, 'g'))
 	ops->ind['g'] = 1;
 
+#if 0
+    /* "local" rejects -m, this should too ... what about +m ? */
+    if (locallevel && OPT_MINUS(ops, 'm') &&
+	!(OPT_MINUS(ops, 'g') || OPT_ISSET(ops, 'p'))) {
+	zerrnam(name, "bad option: -m");
+	return 1;
+    }
+#endif
+
     /* Translate the options into PM_* flags.   *
      * Unfortunately, this depends on the order *
      * these flags are defined in zsh.h         */
@@ -2788,10 +2799,18 @@ bin_typeset(char *name, char **argv, LinkList assigns, Options ops, int func)
 	return 0;
     }
 
-    if (!(OPT_ISSET(ops,'g') || OPT_ISSET(ops,'x') || OPT_ISSET(ops,'m')) ||
-	OPT_PLUS(ops,'g') || *name == 'l' ||
-	(!isset(GLOBALEXPORT) && !OPT_ISSET(ops,'g')))
-	on |= PM_LOCAL;
+    /* Using *name here is cheating, "local" allows no -g option */
+    if ((*name == 'l' || OPT_PLUS(ops,'g')))
+        on |= PM_LOCAL;
+    else if (!OPT_ISSET(ops,'g')) {
+        if (OPT_MINUS(ops, 'x')) {
+	    if (isset(GLOBALEXPORT))
+		ops->ind['g'] = 1;
+	    else if (locallevel)
+		on |= PM_LOCAL;
+        } else if (!(OPT_ISSET(ops,'x') || OPT_ISSET(ops,'m')))
+            on |= PM_LOCAL;
+    }
 
     if ((on & PM_TIED) && !OPT_ISSET(ops, 'p')) {
 	Param apm;