Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
[PATCH 4/3] Fixes for named references (code and tests)
- X-seq: zsh-workers 51374
- From: Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx>
- To: Zsh hackers list <zsh-workers@xxxxxxx>
- Subject: [PATCH 4/3] Fixes for named references (code and tests)
- Date: Tue, 7 Feb 2023 18:44:02 -0800
- Archived-at: <https://zsh.org/workers/51374>
- List-id: <zsh-workers.zsh.org>
Named references, a trilogy in five parts.
Based on discussion with Daniel, here are code and test updates to
applied following the first three named reference patches I sent on
Feb 5th. Some notes:
The zsh/parameter module has been updated to be able to "see" named
references. That is, whereas
typeset -n nameref=var
print ${(t)nameref}
outputs the same string as ${(t)var}, using
print ${parameters[nameref]}
outputs the equivalent of
nameref-${(t)var}
The "bad substitution" error on
typeset -n nr='ary[2]'
print ${nr}
has been fixed, and a problem with find the correct scope for a local
nameref also corrected.
Tests for these have been added, based on the examples Daniel provided
and a couple more. I also changed the autoload test to be skipped if
the module isn't loadable.
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 5bf675e2a..a659300fd 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -105,10 +105,15 @@ getpmparameter(UNUSED(HashTable ht), const char *name)
pm->node.nam = dupstring(name);
pm->node.flags = PM_SCALAR | PM_READONLY;
pm->gsu.s = &nullsetscalar_gsu;
- if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
- !(rpm->node.flags & PM_UNSET))
+ if ((rpm = (Param) realparamtab->getnode2(realparamtab, name)) &&
+ !(rpm->node.flags & PM_UNSET)) {
pm->u.str = paramtypestr(rpm);
- else {
+ if ((rpm->node.flags & PM_NAMEREF) &&
+ (rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
+ !(rpm->node.flags & PM_UNSET)) {
+ pm->u.str = zhtricat(pm->u.str, "-", paramtypestr(rpm));
+ }
+ } else {
pm->u.str = dupstring("");
pm->node.flags |= (PM_UNSET|PM_SPECIAL);
}
diff --git a/Src/params.c b/Src/params.c
index 69b7f484f..98950d88f 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2155,7 +2155,7 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
return NULL;
if (ss)
*ss = sav;
- s = ss;
+ s = dyncat(ss,*pptr);
}
if (PM_TYPE(pm->node.flags) & (PM_ARRAY|PM_HASHED)) {
/* Overload v->isarr as the flag bits for hashed arrays. */
@@ -6170,6 +6170,7 @@ setscope(Param pm)
{
if (pm->node.flags & PM_NAMEREF) {
Param basepm;
+ struct asgment stop;
char *t = pm->u.str ? itype_end(pm->u.str, IIDENT, 0) : NULL;
/* Temporarily change nameref to array parameter itself */
@@ -6177,7 +6178,12 @@ setscope(Param pm)
*t = 0;
else
t = 0;
- basepm = (Param)resolve_nameref(pm, NULL);
+ stop.name = "";
+ stop.value.scalar = NULL;
+ stop.flags = PM_NAMEREF;
+ if (locallevel)
+ stop.flags |= PM_LOCAL;
+ basepm = (Param)resolve_nameref(pm, &stop);
if (t) {
pm->width = t - pm->u.str;
*t = '[';
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index b38831100..a663194a7 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -1,11 +1,11 @@
-# Tests for the zsh/param/private module
+# Tests for named references
%prep
# Required in order to declare an unset hash for substitution test
setopt TYPESET_TO_UNSET
- : ${ZTST_continue:=1}
+ : ${ZTST_continue::=1}
%test
@@ -53,7 +53,13 @@ F:Other type changes are fatal errors, should this also be?
typeset var=value
typeset -n ptr=var
print $ptr
-0:basic nameref expansion
+0:basic nameref expansion, no braces
+>value
+
+ typeset var=value
+ typeset -n ptr=var
+ print ${ptr}
+0:basic nameref expansion, braces
>value
typeset var=(val1 val2)
@@ -115,9 +121,10 @@ F:Other type changes are fatal errors, should this also be?
>typeset -n ptr=var
>typeset -a var=( new1 new2 )
- typeset -p ptr1 ptr2 var
+ typeset -p ptr ptr1 ptr2 var
1:check state of paramtab ONE
F:unexpected side-effects of previous tests
+*?*no such variable: ptr
*?*no such variable: ptr1
*?*no such variable: ptr2
*?*no such variable: var
@@ -247,13 +254,24 @@ F:unexpected side-effects of previous tests
typeset -n ptr2='path[2]'
print -r -- $ptr2
-0d:nameref to array element
+0q:nameref to array element, no braces
+>${path[2]}
+
+ typeset -n ptr2='path[2]'
+ print -r -- ${ptr2}
+0q:nameref to array element, with braces
>${path[2]}
typeset -A hash=(x MISS y HIT)
typeset -n ptr1='hash[y]'
print -r -- $ptr1
-0:nameref to hash element
+0:nameref to hash element, no braces
+>HIT
+
+ typeset -A hash=(x MISS y HIT)
+ typeset -n ptr1='hash[y]'
+ print -r -- ${ptr1}
+0:nameref to hash element, with braces
>HIT
typeset -a ary=(1 2)
@@ -362,16 +380,16 @@ F:unexpected side-effects of previous tests
>typeset -n ptr=lval
>typeset -n ptr=gval
+ typeset -A var=(myself outside)
() {
- zmodload -u zsh/parameter
- typeset -n myself=parameters[myself]
- local -h parameters
+ typeset -n myself=var[myself]
+ local -h var
print -r -- $myself
- typeset -p parameters
+ typeset -p var
}
-0:up-reference part 3, autoloading with hidden special
->nameref-local
->typeset parameters
+0:up-reference part 3, hidden global
+>outside
+>typeset var
() {
typeset notdef
@@ -401,7 +419,7 @@ F:unexpected side-effects of previous tests
1:up-reference part 5, stacked namerefs, end not in scope
F:What is the correct behavior for the scope of ptr1?
>typeset -n ptr1=ptr2
->typeset -n ptr2=''
+>typeset -n ptr2
>ptr1=ptr2
>ptr2=val
>ptr1=LOCAL
@@ -427,13 +445,68 @@ F:What is the correct behavior for the scope of ptr1?
0:up-reference part 6, stacked namerefs, end is in scope
F:Same test, should part 5 output look like this?
>typeset -n ptr1=ptr2
->typeset -n ptr2=''
+>typeset -n ptr2
>ptr1=ptr2
->ptr2=''
+>ptr2
>ptr1=val
>ptr2=
>typeset -n ptr1=ptr2
>typeset -n ptr2=''
>typeset ptr2=val
+ if zmodload zsh/parameter; then
+ () {
+ zmodload -u zsh/parameter
+ typeset -n myself=parameters[myself]
+ local -h parameters
+ print -r -- $myself
+ typeset -p parameters
+ }
+ else ZTST_skip='Cannot zmodload zsh/parameter, skipping autoload test'
+ fi
+0:up-reference part 3, autoloading with hidden special
+>nameref-local-nameref-local
+>typeset parameters
+
+ typeset ptr2=var2
+ typeset var2=GLOBAL
+ () {
+ typeset -n ptr1=ptr2
+ typeset ptr2=var1
+ typeset var1=VAR1
+ typeset var2=VAR2
+ print -r -- ${(P)ptr1}
+ }
+0:
+>VAR2
+
+ ary=(one two three four)
+ typeset -n ptr=ary
+ print -r ${(j.:.)ptr//o/0}
+0:expansion flags and string replacement
+>0ne:tw0:three:f0ur
+
+ var=value
+ typeset -n ptr=var
+ myscalar=ptr
+ echo ${(P)myscalar}
+0:named references with (P), as ${(P)name_of_nameref}
+>value
+
+ var=value
+ myscalar=var
+ typeset -n ptr=myscalar
+ echo ${(P)ptr}
+0:named references with (P), as ${(P)nameref}
+>value
+
+ ary=( 'bry[1]' 'bry[2]' )
+ bry=( lorem ipsum )
+ typeset -n ptr='ary[2]'
+ print -r -- ${ptr}
+ print -r -- ${(P)ptr}
+0:named references with (P), array element to array element
+>bry[2]
+>ipsum
+
%clean
diff --git a/Test/README b/Test/README
index 670434ac3..b9d393d7c 100644
--- a/Test/README
+++ b/Test/README
@@ -6,6 +6,7 @@ scripts names:
C: shell commands with special syntax
D: substititution
E: options
+ K: features adopted from ksh
P: privileged (needs super-user privileges)
V: modules
W: builtin interactive commands and constructs
Messages sorted by:
Reverse Date,
Date,
Thread,
Author