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

Re: PATCH: Assorted parameter stuff



On Apr 19,  9:34am, Bart Schaefer wrote:
}
} On Apr 19,  9:05am, Sven Wischnowsky wrote:
} }
} } Anyway, about 14008: I only found one problem with a complicated
} } subscript in _arguments, line 81, which can be seen by completing after
} } `./configure --<TAB>'.
} 
} Fortunately, I think I've fixed that (including the parse error in (( ))
} though I haven't checked yet).

I've tried replacing the `let' at _arguments line 81 with a (( )), and I
don't get a parse error.

But then, I don't get a parse error in 4.0.1-pre-2, either.

The only problem seems to be that when the entire $tmpargv[...] expression
resolves to the empty string, (( )) gives

    zsh: bad math expression: operand expected at `'

whereas `let' just ignores the empty string and returns false, which is
the desired effect.  Maybe that's what the comment on line 79 meant all
along.

Extremely strange things happen if I try (( "$tmpargv[...]" )) but those
strange things don't seem to have to do with my changes (the same odd
things happen in -pre-2) so I'm not going to worry about that just now.

} D06subscript.ztst, which I've just finished

Here it is, to demonstrate what works after my changes.  I've included
the diff for the last several tweaks that grew out of making the tests
all work; this patch goes on top of 14008, replacing 14016.  I added
several comments about what is going on.

In particular I direct your attention to the test for "Scalar pattern
subscripts that do not match".  This corresponds to some of the changes
that Michal suggested on the Debian bug list, to wit, (i) and (r) on
scalars work more like they do on arrays.  This means that in the
example tested, $s[(r)x,(R)x] yields the empty string and $s[(R)x,(r)x]
yields the entire $s, whereas before the patch both yielded `T'.  This
is the smallest but most potentially controversial item.

The test for "Array pattern subscripts with multiple backslashes" shows
that the subscript syntax is the same whether or not braces or double
quotes are used.

Index: Test/D06subscript.ztst
===================================================================
diff -N D06subscript.ztst
--- /dev/null	Mon Dec 11 17:26:27 2000
+++ Test/D06subscript.ztst	Thu Apr 19 21:50:36 2001
@@ -0,0 +1,130 @@
+# Test parameter subscripting.
+
+%prep
+
+  s='Twinkle, twinkle, little *, [how] I [wonder] what?  You are!'
+  a=('1' ']'  '?' '\2'  '\]' '\?'  '\\3' '\\]'  '\\?' '\\\4'  '\\\]' '\\\?')
+  typeset -g -A A
+  A=($a)
+
+%test
+
+  x=','
+  print $s[(i)winkle] $s[(I)winkle]
+  print ${s[(i)You are]} $#s
+  print ${s[(r)$x,(R)$x]}
+0:Scalar pattern subscripts without wildcards
+>2 11
+>53 60
+>, twinkle, little *,
+
+  x='*'
+  print $s[(i)*] $s[(i)\*] $s[(i)$x*] $s[(i)${(q)x}*] $s[(I)$x\*]
+  print $s[(r)?,(R)\?] $s[(r)\?,(R)?]
+  print $s[(r)\*,(R)*]
+  print $s[(r)\],(R)\[]
+0:Scalar pattern subscripts with wildcards
+>1 26 1 26 26
+>Twinkle, twinkle, little *, [how] I [wonder] what? ?  You are!
+>*, [how] I [wonder] what?  You are!
+>] I [
+
+  # $s[(R)x] actually is $s[0], but zsh treats 0 as 1 for subscripting.
+  print $s[(i)x] : $s[(I)x]
+  print $s[(r)x] : $s[(R)x]
+0:Scalar pattern subscripts that do not match
+>61 : 0
+>: T
+
+  print -R $s[$s[(i)\[]] $s[(i)$s[(r)\*]] $s[(i)${(q)s[(r)\]]}]
+0:Scalar subscripting using a pattern subscript to get the index
+>[ 1 33
+
+  print -R $a[(r)?] $a[(R)?]
+  print $a[(n:2:i)?] $a[(n:2:I)?]
+  print $a[(i)\?] $a[(I)\?]
+  print $a[(i)*] $a[(i)\*]
+0:Array pattern subscripts
+>1 ?
+>2 2
+>3 3
+>1 13
+
+  # It'd be nice to do some of the following with (r), but we run into
+  # limitations of the ztst script parsing of backslashes in the output.
+  print -R $a[(i)\\\\?] $a[(i)\\\\\?]
+  print -R $a[(i)\\\\\\\\?] $a[(i)\\\\\\\\\?]
+  print -R ${a[(i)\\\\\\\\?]} ${a[(i)\\\\\\\\\?]}
+  print -R "$a[(i)\\\\\\\\?] $a[(i)\\\\\\\\\?]"
+  print -R $a[(i)\]] $a[(i)\\\\\]] $a[(i)\\\\\\\\\]] $a[(i)\\\\\\\\\\\\\]]
+  print -R $a[(i)${(q)a[5]}] $a[(i)${(q)a[8]}] $a[(i)${(q)a[11]}]
+  print -R $a[(i)${a[3]}] $a[(i)${a[6]}] $a[(i)${a[9]}] $a[(i)${a[12]}]
+0:Array pattern subscripts with multiple backslashes
+>4 6
+>7 9
+>7 9
+>7 9
+>2 5 8 11
+>5 8 11
+>1 3 4 6
+
+  print -R $A[1] $A[?] $A[\\\\3] $A[\\\]]
+  print -R $A[$a[11]]
+  print -R $A[${(q)a[5]}]
+0:Associative array lookup (direct subscripting)
+>] \2 \\] \?
+>\\\?
+>\\\?
+
+  # The (o) is necessary here for predictable output ordering
+  print -R $A[(I)\?] ${(o)A[(I)?]}
+  print -R $A[(i)\\\\\\\\3]
+  print -R $A[(I)\\\\\\\\\?] ${(o)A[(I)\\\\\\\\?]}
+0:Associative array lookup (pattern subscripting)
+>? 1 ?
+>\\3
+>\\? \\3 \\?
+
+  print -R $A[(R)\?] : ${(o)A[(R)?]}
+  print -R $A[(R)\\\\\?] ${(o)A[(R)\\\\?]} ${(o)A[(R)\\\\\?]}
+  print -R ${(o)A[(R)\\\\\\\\\]]}
+0:Associative array lookup (reverse subscripting)
+>: ]
+>\? \2 \? \?
+>\\]
+
+  x='*'
+  A[$x]=xstar
+  A[${(q)x}]=qxstar
+  print -R ${(k)A[(r)xstar]} $A[$x]
+  print -R ${(k)A[(r)qxstar]} $A[${(q)x}]
+  # A[*] is interpreted specially, assignment to it fails silently (oops)
+  A[*]=star
+  A[\*]=backstar
+  print -R ${(k)A[(r)star]} $A[$x]
+  print -R ${(k)A[(r)backstar]} $A[\*]
+0:Associative array assignment
+>* xstar
+>\* qxstar
+>xstar
+>\* backstar
+
+  o='['
+  c=']'
+  A[\]]=cbrack
+  A[\[]=obrack
+  A[\\\[]=backobrack
+  A[\\\]]=backcbrack
+  print -R $A[$o] $A[$c] $A[\[] $A[\]] $A[\\\[] $A[\\\]]
+  print -R $A[(i)\[] $A[(i)\]] $A[(i)\\\\\[] $A[(i)\\\\\]]
+0:Associative array keys with open and close brackets
+>obrack cbrack obrack cbrack backobrack backcbrack
+>[ ] \[ \]
+
+  print -R $A[$o] $A[$s[(r)\[]]
+  print -R $A[(r)$c] $A[(r)$s[(r)\]]]
+  print -R $A[$A[(i)\\\\\]]]
+0:Associative array lookup using a pattern subscript to get the key
+>obrack obrack
+>] ]
+>backcbrack
Index: Src/lex.c
===================================================================
diff -x CVS -ru ../common/Src/lex.c Src/lex.c
--- ../common/Src/lex.c	Tue Apr 17 19:54:53 2001
+++ Src/lex.c	Thu Apr 19 21:20:35 2001
@@ -1302,10 +1302,13 @@
 	    c = hgetc();
 	    if (c != '\n') {
 		if (c == '$' || c == '\\' || (c == '}' && !intick && bct) ||
-		    c == endchar || c == '`')
+		    c == endchar || c == '`' ||
+		    (math && (c == '[' || c == ']' ||
+			      c == '(' || c == ')' ||
+			      c == '{' || c == '}')))
 		    add(Bnull);
 		else {
-		    /* lexstop is implicitely handled here */
+		    /* lexstop is implicitly handled here */
 		    add('\\');
 		    goto cont;
 		}
Index: Src/params.c
===================================================================
diff -x CVS -ru ../common/Src/params.c Src/params.c
--- ../common/Src/params.c	Wed Apr 18 10:35:30 2001
+++ Src/params.c	Thu Apr 19 21:21:16 2001
@@ -915,26 +915,42 @@
     for (t = s, i = 0;
 	 (c = *t) && ((c != Outbrack &&
 		       (ishash || c != ',')) || i); t++) {
-	if (c == Inbrack)
+	/* Untokenize INULL() except before brackets, for parsestr() */
+	if (INULL(c)) {
+	    if (t[1] == '[' || t[1] == ']') {
+		/* This test handles nested subscripts in hash keys */
+		if (ishash && i)
+		    *t = ztokens[c - Pound];
+		needtok = 1;
+		++t;
+	    } else
+		*t = ztokens[c - Pound];
+	    continue;
+	}
+	/* Inbrack and Outbrack are probably never found here ... */
+	if (c == '[' || c == Inbrack)
 	    i++;
-	else if (c == Outbrack)
+	else if (c == ']' || c == Outbrack)
 	    i--;
-	if (INULL(c)) {
-	    if (!*++t)
-		break;
-	} else if (ispecial(c))
+	if (ispecial(c))
 	    needtok = 1;
     }
     if (!c)
 	return 0;
     s = dupstrpfx(s, t - s);
-    remnulargs(s);
     *str = tt = t;
+    /* If we're NOT reverse subscripting, strip the INULL()s so brackets *
+     * are not backslashed after parsestr().  Otherwise leave them alone *
+     * so that the brackets will be escaped when we patcompile() or when *
+     * subscript arithmetic is performed (for nested subscripts).        */
+    if (ishash && !rev)
+	remnulargs(s);
     if (needtok) {
 	if (parsestr(s))
 	    return 0;
 	singsub(&s);
-    }
+    } else if (rev)
+	remnulargs(s);	/* This is probably always a no-op, but ... */
     if (!rev) {
 	if (ishash) {
 	    HashTable ht = v->pm->gets.hfn(v->pm);
@@ -942,7 +958,6 @@
 		ht = newparamtable(17, v->pm->nam);
 		v->pm->sets.hfn(v->pm, ht);
 	    }
-	    remnulargs(s);
 	    untokenize(s);
 	    if (!(v->pm = (Param) ht->getnode(ht, s))) {
 		HashTable tht = paramtab;
@@ -1157,13 +1172,17 @@
     char *s = *pptr, *tbrack;
 
     *s++ = Inbrack;
-    s = parse_subscript(s); /* Error handled elsewhere */
+    s = parse_subscript(s);	/* Error handled after untokenizing */
+    /* Now we untokenize everthing except INULL() markers so we can check *
+     * for the '*' and '@' special subscripts.  The INULL()s are removed  *
+     * in getarg() after we know whether we're doing reverse indexing.    */
     for (tbrack = *pptr + 1; *tbrack && tbrack != s; tbrack++) {
 	if (INULL(*tbrack) && !*++tbrack)
 	    break;
 	if (itok(*tbrack))
 	    *tbrack = ztokens[*tbrack - Pound];
     }
+    /* If we reached the end of the string (s == NULL) we have an error */
     if (*tbrack)
 	*tbrack = Outbrack;
     else {

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   



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