Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: [PATCH] Fix bang flag in ${(!)ref::=var} substitutions
- X-seq: zsh-workers 54946
- From: Philippe Altherr <philippe.altherr@xxxxxxxxx>
- To: Mikael Magnusson <mikachu@xxxxxxxxx>
- Cc: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: Re: [PATCH] Fix bang flag in ${(!)ref::=var} substitutions
- Date: Fri, 10 Jul 2026 19:43:30 +0200
- Arc-authentication-results: i=1; mx.google.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:dkim-signature; bh=NyDRUTqWNoerXlgZwATUtoPMqR//Og1g3Fj4bqqQDf4=; fh=Y3JBIMmwgOmpZOcOb8CELThLb/H4UYtgQk0FmEzGwhA=; b=b1zh7Z/zQOVoi+mY02M0w1STLwQVT528yF91kDgG02PB1GKe9NIBvsh4EFjQ7z0XDY pUqgS7lF17t4ZNLuyFjn7aL5vIdfDkr92gM0JQg1WexyF+4oy67reUEAoyAEvv0Mr5k/ mj5XcY5X4TPPbPyQAm01BpC5nbgoSg0gHaXinTSN+RlVohYzHijCmM3TxM+RSQ43GUS6 ma8O3D5sL1FB5p/0TNg4m9sim+/gNhfUgVNMO6PeufMkCsdCXHGWnDpq8H39JkTthlbJ vHY7nA9tyXMsUst5LWc1937A+/UOI1hw5khzzUWUXSxm33aD2lJErC7qd0oXiIpSDL5j uCzw==; darn=zsh.org
- Arc-seal: i=1; a=rsa-sha256; t=1783705423; cv=none; d=google.com; s=arc-20260327; b=rUG/xBfF9HlqbwvhTK3YJMgo4PNrNZy5P4U4en3MWrRtg/weltv7hYv/VSAOHDw6jy FNET5y0Vu0rKVmobU1nx7zETt6eVZyy9eiuBENVl7acwnMBgIEh+ngVBuVvb13A0ecao F1Dot3VaBdeLjJYpQWTezbnB/rFNgpe13WPTFJXNkETeofQ/EHf+uQioT+1vn9jh4Skt 6gJXaVhDD6m1Yl+LFvaz3ZphD/0Su9qzr8YQx/nezCp5GZwShWRPdMQspWtsC+uycGrx MDODTvftIG6DOCbHaKzPc18H1wN+nadNeeDOOn8ClKRldeEFCn1NdUMuuG6fIkAll7RY mXYQ==
- Archived-at: <https://zsh.org/workers/54946>
- In-reply-to: <CAHYJk3RVq_=Kp34a-2sy4=0U5qvTbWFks9FvVVMo8O-zoc=coA@mail.gmail.com>
- List-id: <zsh-workers.zsh.org>
- References: <CAGdYchtt-6ybEWH0q70maUO2D3ZfieNdVN_68-F2MVohjdk77Q@mail.gmail.com> <CAHYJk3RVq_=Kp34a-2sy4=0U5qvTbWFks9FvVVMo8O-zoc=coA@mail.gmail.com>
You forgot to attach the patch for this one.
Oops, here it is.
Philippe
diff --git a/Src/params.c b/Src/params.c
index e111b28c7..8ea053035 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -3142,6 +3142,7 @@ assignsparam(char *s, char *val, int flags)
size_t lvar;
mnumber lhs, rhs;
int sstart, created = 0;
+ int scanflags = flags & ASSPM_NONAMEREF ? SCANPM_NONAMEREF : 0;
if (!isident(s)) {
zerr("not an identifier: %s", s);
@@ -3152,7 +3153,7 @@ assignsparam(char *s, char *val, int flags)
queue_signals();
if ((ss = strchr(s, '['))) {
*ss = '\0';
- if (!(v = getvalue(&vbuf, &s, 1))) {
+ if (!(v = fetchvalue(&vbuf, &s, 1, scanflags))) {
createparam(t, PM_ARRAY);
created = 1;
} else {
@@ -3173,7 +3174,7 @@ assignsparam(char *s, char *val, int flags)
*ss = '[';
v = NULL;
} else {
- if (!(v = getvalue(&vbuf, &s, 1))) {
+ if (!(v = fetchvalue(&vbuf, &s, 1, scanflags))) {
createparam(t, PM_SCALAR);
created = 1;
} else if ((((v->pm->node.flags & PM_ARRAY) &&
@@ -3191,7 +3192,7 @@ assignsparam(char *s, char *val, int flags)
v = NULL;
}
}
- if (!v && !(v = getvalue(&vbuf, &t, 1))) {
+ if (!v && !(v = fetchvalue(&vbuf, &t, 1, scanflags))) {
zsfree(val);
unqueue_signals();
/* errflag |= ERRFLAG_ERROR; */
@@ -3304,6 +3305,7 @@ assignaparam(char *s, char **val, int flags)
char *ss;
int created = 0;
int may_warn_about_nested_vars = 1;
+ int scanflags = flags & ASSPM_NONAMEREF ? SCANPM_NONAMEREF : 0;
if (!isident(s)) {
zerr("not an identifier: %s", s);
@@ -3314,7 +3316,7 @@ assignaparam(char *s, char **val, int flags)
queue_signals();
if ((ss = strchr(s, '['))) {
*ss = '\0';
- if (!(v = getvalue(&vbuf, &s, 1))) {
+ if (!(v = fetchvalue(&vbuf, &s, 1, scanflags))) {
createparam(t, PM_ARRAY);
created = 1;
} else {
@@ -3331,7 +3333,7 @@ assignaparam(char *s, char **val, int flags)
}
v = NULL;
} else {
- if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) {
+ if (!(v = fetchvalue(&vbuf, &s, 1, scanflags | SCANPM_ASSIGNING))) {
createparam(t, PM_ARRAY);
created = 1;
} else if (v->pm->node.flags & PM_NAMEREF) {
@@ -3362,7 +3364,7 @@ assignaparam(char *s, char **val, int flags)
}
}
if (!v)
- if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) {
+ if (!(v = fetchvalue(&vbuf, &t, 1, scanflags | SCANPM_ASSIGNING))) {
unqueue_signals();
freearray(val);
/* errflag |= ERRFLAG_ERROR; */
diff --git a/Src/subst.c b/Src/subst.c
index eef713a8c..3312da444 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -3248,6 +3248,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
if (vunset) {
char sav = *idend;
int l, split_flags;
+ int assign_flags = ASSPM_WARN |
+ (hkeys & SCANPM_NONAMEREF ? ASSPM_NONAMEREF : 0);
*idend = '\0';
val = dupstring(s);
@@ -3303,7 +3305,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
if (pm)
aval = paramvalarr(pm->gsu.h->getfn(pm), hkeys|hvals);
} else {
- Param pm = setaparam(idbeg, a);
+ Param pm = assignaparam(idbeg, a, assign_flags);
if (pm) {
struct value vbuf = { 0 };
char *p = idbeg;
@@ -3317,7 +3319,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
arrasg = 0;
} else {
untokenize(val);
- Param pm = setsparam(idbeg, ztrdup(val));
+ Param pm = assignsparam(idbeg, ztrdup(val), assign_flags);
if (pm) {
/* this check isn't needed for correctness, but array values
* aren't affected by SUBST flags anyway */
diff --git a/Src/zsh.h b/Src/zsh.h
index 1f1ecc3e6..720c664cc 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2140,7 +2140,9 @@ enum {
* This is normal for associative arrays but variant behaviour for
* normal arrays.
*/
- ASSPM_KEY_VALUE = 1 << 4
+ ASSPM_KEY_VALUE = 1 << 4,
+ /* Named references are not followed */
+ ASSPM_NONAMEREF = 1 << 5
};
/* node for named directory hash table (nameddirtab) */
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index 952bbd30c..7281be430 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -2348,4 +2348,48 @@ F:converting from association/array to string should work here too
>B:16#FF
>C:16#FF
+ show() { printf "%-13s: %-3s - %-3s - %-3s\n" "$@" }
+ typeset var=aaa
+ typeset -n refU refN="" refS=var
+ show '${refX}' ${(q!)refU} ${(q!)refN} ${(q!)refS}
+ show '${+refX}' ${(q!)+refU} ${(q!)+refN} ${(q!)+refS}
+ show '${refX+1}' ${(q!)refU+1} ${(q!)refN+1} ${(q!)refS+1}
+ show '${refX:+1}' ${(q!)refU:+1} ${(q!)refN:+1} ${(q!)refS:+1}
+ echo
+ show '${refX-bbb}' ${(q!)refU-bbb} ${(q!)refN-bbb} ${(q!)refS-bbb}
+ show '${refX=bbb}' ${(q!)refU=bbb} ${(q!)refN=bbb} ${(q!)refS=bbb}
+ show '${refX}' ${(q!)refU} ${(q!)refN} ${(q!)refS}
+ show '${var}' ${var}
+ echo
+ typeset -n refU refN="" refS=var
+ show '${refX:-ccc}' ${(q!)refU:-ccc} ${(q!)refN:-ccc} ${(q!)refS:-ccc}
+ show '${refX:=ccc}' ${(q!)refU:=ccc} ${(q!)refN:=ccc} ${(q!)refS:=ccc}
+ show '${refX}' ${(q!)refU} ${(q!)refN} ${(q!)refS}
+ show '${var}' ${var}
+ echo
+ typeset -n refU refN="" refS=var
+ show '${refX::=ddd}' ${(q!)refU::=ddd} ${(q!)refN::=ddd} ${(q!)refS::=ddd}
+ show '${refX}' ${(q!)refU} ${(q!)refN} ${(q!)refS}
+ show '${var}' ${var}
+ unfunction show
+0:reference itself is examined in substitutions with the ! flag
+>${refX} : '' - '' - var
+>${+refX} : 0 - 1 - 1
+>${refX+1} : '' - 1 - 1
+>${refX:+1} : '' - '' - 1
+>
+>${refX-bbb} : bbb - '' - var
+>${refX=bbb} : bbb - '' - var
+>${refX} : bbb - '' - var
+>${var} : aaa - -
+>
+>${refX:-ccc} : ccc - ccc - var
+>${refX:=ccc} : ccc - ccc - var
+>${refX} : ccc - ccc - var
+>${var} : aaa - -
+>
+>${refX::=ddd}: ddd - ddd - ddd
+>${refX} : ddd - ddd - ddd
+>${var} : aaa - -
+
%clean
Messages sorted by:
Reverse Date,
Date,
Thread,
Author