Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

[PATCH] Remove support for named references to subscripted variables



Here is a patch to remove support for named references to subscripted variables. While working on this I discovered a number of new issues. Two of them are addressed in the path:

- The functions isident and valid_refname disagree on what are valid variable names.
- For loops don't check the validity of variable names that they assign to named references.

For reviewing the patch, it might be easier to review on GitHub the 6 commits it consists of:

Remove support for named references to subscripted variables

Philippe

diff --git a/Src/builtin.c b/Src/builtin.c
index c269dc1c6..6a855ccbf 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2041,13 +2041,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;
 	}
     }
@@ -3915,8 +3910,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
 	    zerrnam(name, "%s: restricted", pm->node.nam);
 	    returnval = 1;
 	} 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 3199fd17b..2a6f16a04 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -2206,7 +2206,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)
@@ -2224,32 +2223,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));
@@ -2263,8 +2236,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)) {
@@ -3228,7 +3199,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)) &&
@@ -3387,7 +3357,6 @@ assignaparam(char *s, char **val, int flags)
 	    createparam(t, PM_ARRAY);
 	    created = 1;
 	} 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)) {
@@ -3614,8 +3583,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();
@@ -6332,9 +6300,7 @@ resolve_nameref_rec(Param pm, const Param stop, int keep_lastref)
 	    pm->node.flags &= ~PM_UNSET;
 	    return pm;
 	}
-	/* pm->width is the offset of any subscript */
-	/* If present, it has to be the end of any chain, see fetchvalue() */
-	if (refname && *refname && !pm->width) {
+	if (refname && *refname) {
 	    queue_signals();
 	    if ((hn = (Param)gethashnode2(realparamtab, refname))) {
 		if ((hn = loadparamnode(paramtab, upscope(hn, pm), refname)) &&
@@ -6364,7 +6330,11 @@ setloopvar(char *name, char *value)
 	  zerr("read-only reference: %s", pm->node.nam);
 	  return;
       }
-      pm->base = pm->width = 0;
+      if (!valid_refname(value, pm->node.flags)) {
+	  zerr("invalid name reference: %s", value);
+	  return;
+      }
+      pm->base = 0;
       SETREFNAME(pm, ztrdup(value));
       pm->node.flags &= ~PM_UNSET;
       setscope(pm);
@@ -6380,21 +6350,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)) &&
@@ -6413,7 +6370,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);
@@ -6441,47 +6398,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? */
-	    return 0;
-    } else
-	t = itype_end(val, INAMESPC, 0);
-
-    if (t == val) {
-	if (!(*t == '!' || *t == '?' ||
-	      *t == '$' || *t == '-' ||
-	      *t == '_'))
+	if (idigit(*val) || !strcmp(val, "argv") || !strcmp(val, "ARGC"))
 	    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 0dc83ded4..0c47f5ef0 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 e0f7b1879..801378703 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
@@ -212,11 +212,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
@@ -224,82 +219,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
@@ -308,13 +412,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
@@ -476,82 +573,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 name reference: 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
@@ -619,9 +645,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
@@ -736,15 +762,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
 
  (
@@ -845,15 +871,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
@@ -989,6 +1006,19 @@ F:Checking for a bug in zmodload that affects later tests
 >
 *?*reference ref*to local variable one
 
+ typeset -n ref=var
+ {
+   for ref in valid1 inv@lid valid2; do typeset -p ref; done
+ } always { TRY_BLOCK_ERROR=0 }
+ typeset -nr ref=var
+ {
+   for ref in valid3 valid4; do typeset -p ref; done
+ } always { TRY_BLOCK_ERROR=0 }
+1:for-loop variable is a reference, part 5, errors
+>typeset -n ref=valid1
+*?*invalid name reference: inv@lid
+*?*read-only reference: ref
+
  unset -n ref
  typeset -n ref
  () {
@@ -1001,13 +1031,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
  () {
@@ -1091,93 +1114,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
@@ -1194,91 +1217,119 @@ F:previously this could create an infinite recursion and crash
 >h2: ref1=f1 ref2=f1 ref3=f1
 >f1: ref1=f1 ref2=f1 ref3=f1
 
-#
-# 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 name reference: argv
 ?edgeupper: invalid name reference: ARGC
 ?edgelocal: invalid name reference: @
-?edgelocal: invalid name reference: @[1]
 ?edgeupper: invalid name reference: @
 ?edgelocal: invalid name reference: *
-?edgelocal: invalid name reference: *[1]
 ?edgeupper: invalid name reference: *
 ?edgelocal: invalid name reference: #
-?edgelocal: invalid name reference: #[1]
 ?edgeupper: invalid name reference: #
 ?edgeupper: invalid name reference: 0
 ?edgeupper: invalid name reference: 1
 ?edgeupper: invalid name reference: 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.
@@ -1346,22 +1397,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
@@ -1375,21 +1411,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
@@ -1635,10 +1657,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
  () {


Messages sorted by: Reverse Date, Date, Thread, Author