Re: [PATCH] Remove support for named references to subscripted variables

Philippe Altherr <[email protected]>
Newsgroups gmane.comp.shells.zsh.devel
Message-ID <CAGdYchs98dmcAsFGL+vWU3Sa-wUuqfcqqje6OcmhW08u8gsnNA@mail.gmail.com>
Here is an updated patch.

- Remove support for named references to subscripted variables
<https://github.com/zsh-users/zsh/compare/master...paltherr:zsh:kill-subscripted-refs>

Philippe
kill-subscripted-refs.txt (text/plain, 29 KB)
diff --git a/Src/builtin.c b/Src/builtin.c
index 96bfd64cb..773a55b54 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2038,13 +2038,8 @@ typeset_single(char *cname, char *pname, Param pm, int func,
 	    (on & ~(PM_NAMEREF|PM_LOCAL|PM_READONLY))) {
 	    /* Changing type of PM_SPECIAL|PM_AUTOLOAD is a fatal error.  *
 	     * Should this be a fatal error as well, rather than warning? */
-	    if (pm->width)
-		zwarnnam(cname,
-			 "%s: can't change type via subscript reference",
-			 pm->u.str);
-	    else
-		zwarnnam(cname, "%s: can't change type of a named reference",
-			 pname);
+	    zwarnnam(cname, "%s: can't change type of a named reference",
+		     pname);
 	    return NULL;
 	}
     }
@@ -3894,8 +3889,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
 	if (!pm)
 	    continue;
 	else if (ss) {
-	    if ((pm->node.flags & PM_NAMEREF) &&
-		(!(pm = resolve_nameref(pm)) || pm->width)) {
+	    if ((pm->node.flags & PM_NAMEREF) && !(pm = resolve_nameref(pm))) {
 		/* warning? */
 		continue;
 	    }
diff --git a/Src/params.c b/Src/params.c
index 68d4c0bc3..2ce1800c8 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2225,7 +2225,6 @@ fetchvalue(Value v, char **pptr, int bracks, int scanflags)
     } else {
 	Param pm;
 	int isvarat;
-	int isrefslice = 0;
 
         isvarat = (t[0] == '@' && !t[1]);
 	if (scanflags & SCANPM_NONAMEREF)
@@ -2243,32 +2242,6 @@ fetchvalue(Value v, char **pptr, int bracks, int scanflags)
 	if (!pm || ((pm->node.flags & PM_UNSET) &&
 		    !(pm->node.flags & PM_DECLARED)))
 	    return NULL;
-	if ((pm->node.flags & PM_NAMEREF) && !(scanflags & SCANPM_NONAMEREF)) {
-	    char *refname = GETREFNAME(pm);
-	    if (refname && *refname) {
-		/* only happens for namerefs pointing to array elements */
-		char *ref = dupstring(refname);
-		char *ss = pm->width ? ref + pm->width : NULL;
-		if (ss) {
-		    sav = *ss;
-		    *ss = 0;
-		}
-		Param p1 = (Param)gethashnode2(paramtab, ref);
-		if (p1)
-		    pm = loadparamnode(paramtab, upscope(p1, pm), ref);
-		if (!(p1 && pm) ||
-		    ((pm->node.flags & PM_UNSET) &&
-		     !(pm->node.flags & PM_DECLARED)))
-		    return NULL;
-		if (ss) {
-		    scanflags |= SCANPM_NOEXEC;
-		    *ss = sav;
-		    s = dyncat(ss,*pptr);
-		    isrefslice = 1;
-		} else
-		    s = *pptr;
-	    }
-	}
 	if (!v)
 	    v = (Value) zhalloc(sizeof *v);
 	memset(v, 0, sizeof(*v));
@@ -2282,8 +2255,6 @@ fetchvalue(Value v, char **pptr, int bracks, int scanflags)
 		v->scanflags = SCANPM_ARRONLY;
 	}
 	v->pm = pm;
-	if (isrefslice)
-	    v->valflags = VALFLAG_REFSLICE;
 	v->end = -1;
 	if (bracks > 0 && (*s == '[' || *s == Inbrack)) {
 	    if (getindex(&s, v, scanflags)) {
@@ -3226,7 +3197,6 @@ assignsparam(char *s, char *val, int flags)
 	    createparam(t, PM_SCALAR);
 	    created = 1;
 	} else if ((((v->pm->node.flags & PM_ARRAY) &&
-		     !(v->valflags & VALFLAG_REFSLICE) &&
 		     !(flags & ASSPM_AUGMENT)) ||
 		    (v->pm->node.flags & PM_HASHED)) &&
 		   !(v->pm->node.flags & (PM_SPECIAL|PM_TIED)) &&
@@ -3389,7 +3359,6 @@ assignaparam(char *s, char **val, int flags)
 	    unqueue_signals();
 	    return NULL;
 	} else if (!(PM_TYPE(v->pm->node.flags) & (PM_ARRAY|PM_HASHED)) &&
-		   !(v->valflags & VALFLAG_REFSLICE) &&
 		   !(v->pm->node.flags & (PM_SPECIAL|PM_TIED))) {
 	    int uniq = v->pm->node.flags & PM_UNIQUE;
 	    if ((flags & ASSPM_AUGMENT) && !(v->pm->node.flags & PM_UNSET)) {
@@ -3616,8 +3585,7 @@ sethparam(char *s, char **val)
     if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) {
 	createparam(t, PM_HASHED);
 	checkcreate = 1;
-    } else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED) &&
-	       !(v->valflags & VALFLAG_REFSLICE)) {
+    } else if (!(PM_TYPE(v->pm->node.flags) & PM_HASHED)) {
 	if (!(v->pm->node.flags & PM_SPECIAL)) {
 	    if (resetparam(v->pm, PM_HASHED)) {
 		unqueue_signals();
@@ -6320,9 +6288,7 @@ resolve_nameref_rec(Param pm, const Param stop, int keep_lastref)
     Param ref = pm;
     char *refname;
     if (!pm || !(pm->node.flags & PM_NAMEREF) || (pm->node.flags & PM_UNSET)
-	/* pm->width is the offset of any subscript */
-	/* If present, it has to be the end of any chain, see fetchvalue() */
-	|| pm->width || !(refname = GETREFNAME(pm)) || !*refname)
+	|| !(refname = GETREFNAME(pm)) || !*refname)
 	return pm;
     queue_signals();
     if ((pm = (Param)gethashnode2(realparamtab, refname))) {
@@ -6351,7 +6317,7 @@ setloopvar(char *name, char *value)
 	  zerr("invalid variable name: %s", value);
 	  return;
       }
-      pm->base = pm->width = 0;
+      pm->base = 0;
       SETREFNAME(pm, ztrdup(value));
       pm->node.flags &= ~PM_UNSET;
       setscope(pm);
@@ -6367,21 +6333,8 @@ setscope(Param pm)
     if (pm->node.flags & PM_NAMEREF) {
 	Param basepm = NULL;
 	char *refname = GETREFNAME(pm);
-	char *t = refname ? itype_end(refname, INAMESPC, 0) : NULL;
 	int q = queue_signal_level();
 
-	/* Compute pm->width */
-	/* Temporarily change nameref to array parameter itself */
-	if (t && *t == '[')
-	    *t = 0;
-	else
-	    t = 0;
-	if (t) {
-	    pm->width = t - refname;
-	    *t = '[';
-	    refname = dupstrpfx(refname, pm->width);
-	}
-
 	/* Compute pm->base */
 	if (!(pm->node.flags & PM_UPPER) && refname &&
 	    (basepm = (Param)gethashnode2(realparamtab, refname)) &&
@@ -6400,7 +6353,7 @@ setscope(Param pm)
 	}
 
 	/* Check for self references */
-	if (refname && *refname && !pm->width && basepm != pm) {
+	if (refname && *refname && basepm != pm) {
 	    dont_queue_signals();	/* Prevent unkillable loops */
 	    basepm = resolve_nameref_rec(pm, pm, 0);
 	    restore_queue_signals(q);
@@ -6447,47 +6400,14 @@ upscope(Param pm, const Param ref)
 static int
 valid_refname(char *val, int flags)
 {
-    char *t;
-
     if (flags & PM_UPPER) {
 	/* Upward reference to positionals is doomed to fail */
-	if (idigit(*val))
-	    return 0;
-	t = itype_end(val, INAMESPC, 0);
-	if ((t - val == 4) &&
-	    (!strncmp(val, "argv", 4) ||
-	     !strncmp(val, "ARGC", 4)))
-	    return 0;
-    } else if (idigit(*val)) {
-	t = val;
-	while (*++t)
-	    if (!idigit(*t))
-		break;
-	if (*t && *t != '[')	/* Need to test Inbrack here too? */
+	if (idigit(*val) || !strcmp(val, "argv") || !strcmp(val, "ARGC"))
 	    return 0;
-    } else
-	t = itype_end(val, INAMESPC, 0);
-
-    if (t == val) {
-	if (!(*t == '!' || *t == '?' ||
-	      *t == '$' || *t == '-' ||
-	      *t == '_'))
-	    return 0;
-	++t;
-    }
-    if (*t == '[') {
-	/* Another bit of isident() to emulate */
-	tokenize(t = dupstring(t+1));
-	while ((t = parse_subscript(t, 0, ']')) && *t++ == Outbrack) {
-	    if (*t == Inbrack)
-		++t;
-	    else
-		break;
-	}
-	if (t && *t) {
-	    /* zwarn("%s: stuff after subscript: %s", val, t); */
-	    return 0;
-	}
     }
-    return !*t;
+
+    if (*val == '!' || *val == '?' || *val == '$' || *val == '-')
+    	return !*(++val);
+
+    return !*itype_end(val, INAMESPC, 0) && isident(val);
 }
diff --git a/Src/zsh.h b/Src/zsh.h
index 2858b46aa..69f647323 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -758,7 +758,6 @@ enum {
     VALFLAG_INV =	0x0001,	/* We are performing inverse subscripting */
     VALFLAG_EMPTY =	0x0002,	/* Subscripted range is empty */
     VALFLAG_SUBST =	0x0004,	/* Substitution, so apply padding, case flags */
-    VALFLAG_REFSLICE=	0x0008	/* Value is a reference to an array slice */
 };
 
 #define MAX_ARRLEN    262144
diff --git a/Test/K01nameref.ztst b/Test/K01nameref.ztst
index 77a01ea48..be4c635db 100644
--- a/Test/K01nameref.ztst
+++ b/Test/K01nameref.ztst
@@ -33,44 +33,44 @@
    }
 
    function g() {
-     if (($2)); then local -n $1 rs ra rs1 ra1;
-     else local -n $1 rs=s ra=a rs1="s[1]" ra1="a[1]"; fi;
-     if (($2 == 1)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
-     echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     if (($2)); then local -n $1 rs ra;
+     else local -n $1 rs=s ra=a; fi;
+     if (($2 == 1)); then rs=s; ra=a; fi;
+     echo "$0:1: rs=$rs - ra=$ra";
      local s=$0 a=($0);
-     if (($2 == 2)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
-     echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     if (($2 == 2)); then rs=s; ra=a; fi;
+     echo "$0:2: rs=$rs - ra=$ra";
      h "$@";
-     echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     echo "$0:3: rs=$rs - ra=$ra";
    }
 
    function h() {
-     if (($2 == 3)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
-     echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     if (($2 == 3)); then rs=s; ra=a; fi;
+     echo "$0:1: rs=$rs - ra=$ra";
      local s=$0 a=($0);
-     if (($2 == 4)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
-     echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     if (($2 == 4)); then rs=s; ra=a; fi;
+     echo "$0:2: rs=$rs - ra=$ra";
      i "$@";
-     echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     echo "$0:3: rs=$rs - ra=$ra";
      # Check that re-entering the same scope doesn't undo scope exit
      k "$@"
    }
 
    function i() {
-     if (($2 == 5)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
-     echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     if (($2 == 5)); then rs=s; ra=a; fi;
+     echo "$0:1: rs=$rs - ra=$ra";
      local s=$0 a=($0);
-     if (($2 == 6)); then rs=s; ra=a; rs1="s[1]"; ra1="a[1]"; fi;
-     echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     if (($2 == 6)); then rs=s; ra=a; fi;
+     echo "$0:2: rs=$rs - ra=$ra";
      j "$@";
-     echo "$0:3: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     echo "$0:3: rs=$rs - ra=$ra";
      k "$@";
    }
 
    function j() {
-     echo "$0:1: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     echo "$0:1: rs=$rs - ra=$ra";
      local s=$0 a=($0);
-     echo "$0:2: rs=$rs - ra=$ra - rs1=$rs1 - ra1=$ra1";
+     echo "$0:2: rs=$rs - ra=$ra";
    }
 
    functions -c j k
@@ -276,11 +276,6 @@ F:note this causes "var" to become set
 >typeset -n ptr=var
 >typeset -t var
 
- typeset -n ptr=var[2]
- typeset -t ptr
-1:change type of referenced array element
-*?*var\[2\]: can't change type via subscript reference
-
  typeset -n ptr[1]=var
 1:illegal nameref name
 *?*reference variable cannot be an array
@@ -288,82 +283,191 @@ F:note this causes "var" to become set
  typeset var=value
  typeset -n ptr=var
  print $ptr
-0:basic nameref expansion, no braces
+ print $ptr[2,4]
+0:nameref expansion, no braces
 >value
+>alu
 
  typeset var=value
  typeset -n ptr=var
  print ${ptr}
-0:basic nameref expansion, braces
+ print ${(U)ptr}
+ print ${ptr[2,5][1,3]}
+ print ${(U)ptr[2,5][1,3]}
+0:nameref expansion, braces
 >value
+>VALUE
+>alu
+>ALU
 
  typeset var=(val1 val2)
  typeset -n ptr=var
  print $ptr
-0:nameref array expansion
+ print $ptr[2]
+0:nameref array expansion, no braces
 >val1 val2
+>val2
 
- typeset -A var=(val1 val2)
+ typeset var=(val1 val2)
  typeset -n ptr=var
- print ${(kv)ptr}
-0:nameref hash expansion
+ print ${ptr}
+ print ${(O)ptr}
+ print ${ptr[2]}
+ print ${(U)ptr[2]}
+ print ${ptr[2][2,4]}
+ print ${(U)ptr[2][2,4]}
+0:nameref array expansion, braces
 >val1 val2
+>val2 val1
+>val2
+>VAL2
+>al2
+>AL2
 
+ typeset -A var=(key1 val1 key2 val2)
  typeset -n ptr=var
+ print $ptr
+ print $ptr[key2]
+0:nameref hash expansion, no braces
+>val1 val2
+>val2
+
+ typeset -A var=(key1 val1 key2 val2)
+ typeset -n ptr=var
+ print ${ptr}
+ print ${(kv)ptr}
+ print ${ptr[key2]}
+ print ${(U)ptr[key2]}
+ print ${ptr[key2][2,4]}
+ print ${(U)ptr[key2][2,4]}
+0:nameref hash expansion, braces
+>val1 val2
+>key1 val1 key2 val2
+>val2
+>VAL2
+>al2
+>AL2
+
  typeset var=value
- typeset -p ptr var
+ typeset -n ptr=var
  ptr=newvalue
- typeset -p ptr var
-0:assign existing scalar via nameref
->typeset -n ptr=var
->typeset var=value
->typeset -n ptr=var
+ typeset -p var
+ ptr[3]=xt
+ typeset -p var
+ typeset ptr=newvalue
+ typeset -p var
+ typeset ptr[3]=xt
+ typeset -p var
+0:assign/typeset existing scalar via nameref
 >typeset var=newvalue
+>typeset var=nextvalue
+>typeset var=newvalue
+>typeset var=nextvalue
 
+ typeset var=(val1 val2)
  typeset -n ptr=var
+ ptr=(new1 new2 new3 new4 new5)
+ typeset -p var
+ ptr[3]=new6
+ typeset -p var
+ ptr[2,4]=(new7 new8)
+ typeset -p var
+ typeset ptr=(new1 new2 new3 new4 new5)
+ typeset -p var
+ typeset ptr[3]=new6
+ typeset -p var
+ typeset ptr[2,4]=(new7 new8)
+ typeset -p var
+0:assign/typeset existing array via nameref
+>typeset -a var=( new1 new2 new3 new4 new5 )
+>typeset -a var=( new1 new2 new6 new4 new5 )
+>typeset -a var=( new1 new7 new8 new5 )
+>typeset -a var=( new1 new2 new3 new4 new5 )
+>typeset -a var=( new1 new2 new6 new4 new5 )
+>typeset -a var=( new1 new7 new8 new5 )
+
+ typeset -A var=(key1 val1)
+ typeset -n ptr=var
+ ptr=(key2 val2 key3 val3)
+ typeset -p var
+ ptr[key3]=VAL3
+ ptr[key4]=val4
+ typeset -p var
+ typeset ptr=(key2 val2 key3 val3)
+ typeset -p var
+ typeset ptr[key3]=VAL3
+ typeset ptr[key4]=val4
+ typeset -p var
+0:assign/typeset existing array via nameref
+>typeset -A var=( [key2]=val2 [key3]=val3 )
+>typeset -A var=( [key2]=val2 [key3]=VAL3 [key4]=val4 )
+>typeset -A var=( [key2]=val2 [key3]=val3 )
+>typeset -A var=( [key2]=val2 [key3]=VAL3 [key4]=val4 )
+
+ () {
+   unset var
+   typeset -n ptr=var
+   ptr=value
+   typeset -p var
+   unset var
+   typeset ptr=value
+   typeset -p var
+ }
+ typeset -p var
+1:assign/typeset new scalar via nameref
+>typeset -g var=value
+>typeset var=value
+*?*no such variable: var
+
+ () {
+   unset var
+   typeset -n ptr=var
+   ptr=(val1 val2)
+   typeset -p var
+   unset var
+   typeset ptr=(val1 val2)
+   typeset -p var
+ }
+ typeset -p var
+1:assign/typeset new array via nameref
+>typeset -g -a var=( val1 val2 )
+>typeset -a var=( val1 val2 )
+*?*no such variable: var
+
  typeset var=value
+ typeset -n ptr=var
+ unset "ptr[3]"
+ typeset -p var
+ unset "ptr[2,3]"
+ typeset -p var
+ unset ptr
+ typeset -p var
+ typeset var=(val1 val2 val3 val4 val5)
+ unset "ptr[3]"
+ typeset -p var
+ unset "ptr[2,4]"
+ typeset -p var
+ unset ptr
+ typeset -p var
+ typeset -A var=(key1 val1 key2 val2)
+ unset "ptr[key2]"
+ typeset -p var
  unset ptr
  typeset -p var
 0:unset via nameref
+>typeset var=vaue
+>typeset var=ve
+>typeset -a var=( val1 val2 '' val4 val5 )
+>typeset -a var=( val1 '' val5 )
+>typeset -A var=( [key1]=val1 )
 
- typeset -n ptr=var
  typeset var=value
+ typeset -n ptr=var
  unset -n ptr
  typeset -p var ptr
 0:unset of the nameref itself
-F:If earlier tests change, might get "no such variable" here
 >typeset var=value
 
- typeset -n ptr=var
- typeset var=value
- typeset -p ptr var
- typeset ptr=newvalue
- typeset -p ptr var
-0:typeset existing scalar via nameref
->typeset -n ptr=var
->typeset var=value
->typeset -n ptr=var
->typeset var=newvalue
-
- typeset -n ptr=var
- ptr=value
- typeset -p var ptr
-0:assign new scalar via nameref
->typeset -g var=value
->typeset -n ptr=var
-
- unset var
- typeset -n ptr=var
- typeset var=(val1 val2)
- typeset -p ptr var
- ptr=(new1 new2)
- typeset -p ptr var
-0:assign existing array via nameref
->typeset -n ptr=var
->typeset -a var=( val1 val2 )
->typeset -n ptr=var
->typeset -a var=( new1 new2 )
-
  typeset -p ptr ptr1 ptr2 var
 1:check state of paramtab ONE
 F:unexpected side-effects of previous tests
@@ -372,13 +476,6 @@ F:unexpected side-effects of previous tests
 *?*no such variable: ptr2
 *?*no such variable: var
 
- typeset -n ptr=var
- ptr=(val1 val2)
- typeset -p var ptr
-0:assign new array via nameref
->typeset -g -a var=( val1 val2 )
->typeset -n ptr=var
-
  unset var
  typeset -n ptr2=var
  typeset -n ptr1=ptr2
@@ -540,82 +637,11 @@ F:unexpected side-effects of previous tests
  }
 0:regression: not a self reference (test 3)
 
-
- unset -n ptr2
- typeset -n ptr2='path[2]'
- print -r -- $ptr2
-0q:nameref to array element, no braces
->${path[2]}
-
- unset -n ptr2
- typeset -n ptr2='path[2]'
- print -r -- ${ptr2}
-0q:nameref to array element, with braces
->${path[2]}
-
- unset -n ptr1
- typeset -A hash=(x MISS y HIT)
- typeset -n ptr1='hash[y]'
- print -r -- $ptr1
-0:nameref to hash element, no braces
->HIT
-
- unset -n ptr1
- typeset -A hash=(x MISS y HIT)
- typeset -n ptr1='hash[y]'
- print -r -- ${ptr1}
-0:nameref to hash element, with braces
->HIT
-
- unset -n ptr2
- typeset -a ary=(1 2)
- typeset -n ptr2='ary[2]'
- ptr2=TWO
- typeset -p ary
-0:assign array element by nameref
->typeset -a ary=( 1 TWO )
-
- unset -n ptr2
- typeset -n ptr2='ary[2]'
- ptr2=TWO
- typeset -p ary
-0f:create array element by nameref
-F:ksh93 does not implement this either
->typeset -a ary=( '' TWO )
-
- unset -n ptr1
- typeset -A hash=(x MISS y MISS)
- typeset -n ptr1='hash[y]'
- ptr1=HIT
- typeset -p hash
-0:assign to hash element by nameref
->typeset -A hash=( [x]=MISS [y]=HIT )
-
- unset -n ptr1
- typeset -A hash
- typeset -n ptr1='hash[y]'
- ptr1=HIT
- typeset -p hash
-0f:create hash by element nameref
-F:ksh93 does not implement this either
->typeset -A hash=( [y]=HIT )
-
  unset -n ptr1
  typeset -n ptr1='not[2]good'
 1:invalid nameref
 *?*invalid variable name: not\[2\]good
 
- unset -n ptr1
- unset hash
- typeset -A hash
- typeset -n ptr1='hash[y]'
- print ${ptr1::=HIT}
- typeset -p ptr1 hash
-0f:create hash by element substitution
->HIT
->typeset -n ptr1='hash[y]'
->typeset -A hash=( [y]=HIT )
-
  unset -n ptr
  unset gval
  typeset -n ptr=gval
@@ -683,9 +709,9 @@ F:unexpected side-effects of previous tests
 
  typeset -A var=(myself outside)
  () {
-   typeset -n myself=var[myself]
+   typeset -n myself=var
    local -h var
-   print -r -- $myself
+   print -r -- $myself[myself]
    typeset -p var
  }
 0:up-reference part 3, hidden global
@@ -800,15 +826,15 @@ F:Same test, should part 5 output look like this?
  if zmodload zsh/parameter; then
  () {
    zmodload -u zsh/parameter
-   typeset -n myself=parameters[myself]
+   typeset -n myself=parameters
    local -h parameters
-   print -r -- $myself
+   print -r -- $myself[myself]
    typeset -p parameters
  }
  else ZTST_skip='Cannot zmodload zsh/parameter, skipping autoload test'
  fi
 0:up-reference part 9, autoloading with hidden special
->nameref-local-nameref-local
+>nameref-local-association-readonly-hide-hideval-special
 >typeset -h parameters
 
  (
@@ -909,15 +935,6 @@ F:Checking for a bug in zmodload that affects later tests
 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
-
  unset -n ref
  unset var
  typeset -n ref=var
@@ -1078,13 +1095,6 @@ F:Checking for a bug in zmodload that affects later tests
 >typeset -n ref=inner
 *?*reference ref*to local variable inner
 
- typeset -n ptr='ary[$(echo 2)]'
- typeset -a ary=(one two three)
- print $ptr
-1:attempt deferred command substitution in subscript
-F:runs in `setopt noexec` so $(...) returns nothing
-*?*bad math expression: empty string
-
  unset -n ref
  typeset -n ref=GLOBAL
  () {
@@ -1168,93 +1178,93 @@ F:previously this could create an infinite recursion and crash
 
  e -u 0
 0:assignment at different scope than declaration, -u 0
->g:1: rs=f - ra=f - rs1=f - ra1=f
->g:2: rs=f - ra=f - rs1=f - ra1=f
->h:1: rs=f - ra=f - rs1=f - ra1=f
->h:2: rs=f - ra=f - rs1=f - ra1=f
->i:1: rs=f - ra=f - rs1=f - ra1=f
->i:2: rs=f - ra=f - rs1=f - ra1=f
->j:1: rs=f - ra=f - rs1=f - ra1=f
->j:2: rs=f - ra=f - rs1=f - ra1=f
->i:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->h:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->g:3: rs=f - ra=f - rs1=f - ra1=f
+>g:1: rs=f - ra=f
+>g:2: rs=f - ra=f
+>h:1: rs=f - ra=f
+>h:2: rs=f - ra=f
+>i:1: rs=f - ra=f
+>i:2: rs=f - ra=f
+>j:1: rs=f - ra=f
+>j:2: rs=f - ra=f
+>i:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>h:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>g:3: rs=f - ra=f
 
  e '' 0
 0:assignment at different scope than declaration, '' 0
->g:1: rs=f - ra=f - rs1=f - ra1=f
->g:2: rs=f - ra=f - rs1=f - ra1=f
->h:1: rs=f - ra=f - rs1=f - ra1=f
->h:2: rs=f - ra=f - rs1=f - ra1=f
->i:1: rs=f - ra=f - rs1=f - ra1=f
->i:2: rs=f - ra=f - rs1=f - ra1=f
->j:1: rs=f - ra=f - rs1=f - ra1=f
->j:2: rs=f - ra=f - rs1=f - ra1=f
->i:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->h:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->g:3: rs=f - ra=f - rs1=f - ra1=f
+>g:1: rs=f - ra=f
+>g:2: rs=f - ra=f
+>h:1: rs=f - ra=f
+>h:2: rs=f - ra=f
+>i:1: rs=f - ra=f
+>i:2: rs=f - ra=f
+>j:1: rs=f - ra=f
+>j:2: rs=f - ra=f
+>i:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>h:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>g:3: rs=f - ra=f
 
  e -u 2
 0:assignment at different scope than declaration, -u 2
->g:1: rs= - ra= - rs1= - ra1=
->g:2: rs=f - ra=f - rs1=f - ra1=f
->h:1: rs=f - ra=f - rs1=f - ra1=f
->h:2: rs=f - ra=f - rs1=f - ra1=f
->i:1: rs=f - ra=f - rs1=f - ra1=f
->i:2: rs=f - ra=f - rs1=f - ra1=f
->j:1: rs=f - ra=f - rs1=f - ra1=f
->j:2: rs=f - ra=f - rs1=f - ra1=f
->i:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->h:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->g:3: rs=f - ra=f - rs1=f - ra1=f
+>g:1: rs= - ra=
+>g:2: rs=f - ra=f
+>h:1: rs=f - ra=f
+>h:2: rs=f - ra=f
+>i:1: rs=f - ra=f
+>i:2: rs=f - ra=f
+>j:1: rs=f - ra=f
+>j:2: rs=f - ra=f
+>i:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>h:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>g:3: rs=f - ra=f
 
  e -u 6
 0:assignment at different scope than declaration, -u 6
->g:1: rs= - ra= - rs1= - ra1=
->g:2: rs= - ra= - rs1= - ra1=
->h:1: rs= - ra= - rs1= - ra1=
->h:2: rs= - ra= - rs1= - ra1=
->i:1: rs= - ra= - rs1= - ra1=
->i:2: rs=f - ra=f - rs1=f - ra1=f
->j:1: rs=f - ra=f - rs1=f - ra1=f
->j:2: rs=f - ra=f - rs1=f - ra1=f
->i:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->h:3: rs=f - ra=f - rs1=f - ra1=f
->k:1: rs=f - ra=f - rs1=f - ra1=f
->k:2: rs=f - ra=f - rs1=f - ra1=f
->g:3: rs=f - ra=f - rs1=f - ra1=f
+>g:1: rs= - ra=
+>g:2: rs= - ra=
+>h:1: rs= - ra=
+>h:2: rs= - ra=
+>i:1: rs= - ra=
+>i:2: rs=f - ra=f
+>j:1: rs=f - ra=f
+>j:2: rs=f - ra=f
+>i:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>h:3: rs=f - ra=f
+>k:1: rs=f - ra=f
+>k:2: rs=f - ra=f
+>g:3: rs=f - ra=f
 
  e '' 6
 0:assignment at different scope than declaration, '' 6
->g:1: rs= - ra= - rs1= - ra1=
->g:2: rs= - ra= - rs1= - ra1=
->h:1: rs= - ra= - rs1= - ra1=
->h:2: rs= - ra= - rs1= - ra1=
->i:1: rs= - ra= - rs1= - ra1=
->i:2: rs=i - ra=i - rs1=i - ra1=i
->j:1: rs=i - ra=i - rs1=i - ra1=i
->j:2: rs=i - ra=i - rs1=i - ra1=i
->i:3: rs=i - ra=i - rs1=i - ra1=i
->k:1: rs=i - ra=i - rs1=i - ra1=i
->k:2: rs=i - ra=i - rs1=i - ra1=i
->h:3: rs=h - ra=h - rs1=h - ra1=h
->k:1: rs=h - ra=h - rs1=h - ra1=h
->k:2: rs=h - ra=h - rs1=h - ra1=h
->g:3: rs=g - ra=g - rs1=g - ra1=g
+>g:1: rs= - ra=
+>g:2: rs= - ra=
+>h:1: rs= - ra=
+>h:2: rs= - ra=
+>i:1: rs= - ra=
+>i:2: rs=i - ra=i
+>j:1: rs=i - ra=i
+>j:2: rs=i - ra=i
+>i:3: rs=i - ra=i
+>k:1: rs=i - ra=i
+>k:2: rs=i - ra=i
+>h:3: rs=h - ra=h
+>k:1: rs=h - ra=h
+>k:2: rs=h - ra=h
+>g:3: rs=g - ra=g
 
  f1
 0:Transitive references with scoping changes
@@ -1346,91 +1356,119 @@ F:previously this could create an infinite recursion and crash
 >B8: ref1=l2 ref2=l2
 >B9: ref1=l1 ref2=l1
 
-#
-# The following two tests are linked, do not separate
-#
+ check-valid-referent-name() {
+   local -n ref=$1
+   [[ $ref = $2 ]] || echo "Unexpected expansion result: ref=$1, \$ref=$ref != $2"
+ }
+ check-invalid-variable-name() {
+   {
+     local -- $1=value-$1 2>/dev/null
+     echo "Unexpected valid variable name: $1"
+   } always {
+     TRY_BLOCK_ERROR=0
+   }
+ }
+ check-invalid-referent-name() {
+   {
+     local -n -- ref=$1 2>/dev/null
+     echo "Unexpected valid referent name: $1"
+   } always {
+     TRY_BLOCK_ERROR=0
+   }
+ }
+ local name value;
+ # Test valid variable names.
+ for name in \
+    foo  foo.  foo.bar  foo.456  foo.4ar \
+   .foo       .foo.bar .foo.456
+ do
+   local $name=value-$name
+   check-valid-referent-name "$name" value-$name
+   check-invalid-referent-name "$name"@
+   check-invalid-referent-name "$name""[1]"
+ done
+ # Test valid builtin variable names
+ for name value in 123 "" \! 0 \? 0 \$ $$ - 569X _ -n; do
+   check-valid-referent-name "$name" $value
+   check-invalid-referent-name "$name"@
+   check-invalid-referent-name "$name""[1]"
+ done
+ # Test invalid variable names.
+ for name in \
+        .foo.                   .foo.4ar  .  foo.. \
+         123.  123.bar  123.456  123.4ar .. .foo.. \
+   .123 .123. .123.bar .123.456 .123.4ar \
+    1oo  1oo.  1oo.bar  1oo.456  1oo.4ar \
+   .1oo .1oo. .1oo.bar .1oo.456 .1oo.4ar
+ do
+   check-invalid-variable-name "$name"
+   check-invalid-referent-name "$name"
+   check-invalid-referent-name "$name"@
+   check-invalid-referent-name "$name""[1]"
+ done
+ # Any variable name with more than one non-leading '.' is invalid.
+ for name in {,.}{foo,123,1oo}.{bar,456,4ar}.{,baz,789,7az}; do
+   check-invalid-variable-name "$name"
+   check-invalid-referent-name "$name"
+ done
+ unfunction check-valid-referent-name
+ unfunction check-invalid-variable-name
+ unfunction check-invalid-referent-name
+ unset name value
+0:references to invalid variable names
 
  edgelocal() ( local -n x=$1; typeset -p x; print -r $x )
  edgeupper() ( local -nu x=$1; typeset -p x; print -r $x )
- for edge in argv ARGC \@ \* \# 0 1 01 \! \? - _
+ for edge in argv ARGC \@ \* \# 0 1 01 \! \? \$ - _
  do
   edgelocal $edge
-  edgelocal "$edge""[1]"
   edgeupper $edge
  done
-0:references to builtin specials
-F:Subscripting on 1 01 ! ? - should print first character but do not
+ unfunction edgelocal edgeupper
+0q:references to builtin specials
+F:BUG:References to 1, 2, ... are supported but don't work (always expand to "")
 >typeset -n x=argv
 >argv
->typeset -n x='argv[1]'
->argv[1]
 >typeset -n x=ARGC
 >1
->typeset -n x='ARGC[1]'
->1
 >typeset -n x=0
 >edgelocal
->typeset -n x='0[1]'
->e
 >typeset -n x=1
 >
->typeset -n x='1[1]'
->
 >typeset -n x=01
 >
->typeset -n x='01[1]'
->
 >typeset -n x=!
 >0
->typeset -n x='![1]'
->
 >typeset -un x=!
 >0
 >typeset -n x='?'
 >0
->typeset -n x='?[1]'
->
 >typeset -un x='?'
 >0
+>typeset -n x='$'
+>$$
+>typeset -un x='$'
+>$$
 >typeset -n x=-
 >569X
->typeset -n x='-[1]'
->
 >typeset -un x=-
 >569X
 >typeset -n x=_
 >x
->typeset -n x='_[1]'
->x
 >typeset -un x=_
 >x
 ?edgeupper: invalid variable name: argv
 ?edgeupper: invalid variable name: ARGC
 ?edgelocal: invalid variable name: @
-?edgelocal: invalid variable name: @[1]
 ?edgeupper: invalid variable name: @
 ?edgelocal: invalid variable name: *
-?edgelocal: invalid variable name: *[1]
 ?edgeupper: invalid variable name: *
 ?edgelocal: invalid variable name: #
-?edgelocal: invalid variable name: #[1]
 ?edgeupper: invalid variable name: #
 ?edgeupper: invalid variable name: 0
 ?edgeupper: invalid variable name: 1
 ?edgeupper: invalid variable name: 01
 
- edgelocal \$
- edgelocal '$[1]'
- edgeupper \$
- unfunction edgelocal edgeupper
-0qf:references to $$
-F:$$[1] reference should print the first digit of $$ but prints nothing
->typeset -n x='$'
->$$
->typeset -n x='\$[1]'
->$$[1]
->$$
-
 #
 # The following tests are run in interactive mode, using PS1 as an
 # assignable special with side-effects.  This crashed at one time.
@@ -1498,22 +1536,7 @@ F:$$[1] reference should print the first digit of $$ but prints nothing
  zmodload -u zsh/random
  echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
  echo v=${ref/<->/integer}
-0:Referring and dereferring an autoload variable loads it (direct)
->z=SRANDOM (zsh/random)
->z=
->v=integer
->z=SRANDOM (zsh/random)
->v=integer
-
- zmodload -u zsh/random
- echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
- typeset -n ref=SRANDOM[1,20]
- echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
- echo v=${ref/<->/integer}
- zmodload -u zsh/random
- echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
- echo v=${ref/<->/integer}
-0:Referring and dereferring an autoload variable loads it (subscript)
+0:Referring and dereferring an autoload variable loads it
 >z=SRANDOM (zsh/random)
 >z=
 >v=integer
@@ -1527,21 +1550,7 @@ F:$$[1] reference should print the first digit of $$ but prints nothing
  typeset -h SRANDOM=local-variable
  echo v=${ref/<->/integer}
  echo NOT REACHED
-1:Dereferring an autoload variable fails to load it if its hidden (direct)
->v=integer
->z=SRANDOM (zsh/random)
-?(eval):6: Can't add module parameter `SRANDOM': local parameter exists
-?(eval):zsh/random:6: error when adding parameter `SRANDOM'
-?(eval):6: autoloading module zsh/random failed to define parameter: SRANDOM
-
- typeset -n ref=SRANDOM[1,20]
- echo v=${ref/<->/integer}
- zmodload -u zsh/random
- echo z=${(M)${(f)${ zmodload -ap}}:#*SRANDOM*}
- typeset -h SRANDOM=local-variable
- echo v=${ref/<->/integer}
- echo NOT REACHED
-1:Dereferring an autoload variable fails to load it if its hidden (subscript)
+1:Dereferring an autoload variable fails to load it if its hidden
 >v=integer
 >z=SRANDOM (zsh/random)
 ?(eval):6: Can't add module parameter `SRANDOM': local parameter exists
@@ -1760,10 +1769,6 @@ F:converting from association/array to string should work here too
 1:regression: reference loop with same name enclosing variable
 ?(anon):3: ptr2: invalid self reference
 
- typeset -n ref=ref[1]
-1:self reference with subscript
-*?*: ref: invalid self reference
-
  typeset var=foo
  typeset -n ref=var
  () {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.