From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 982 invoked from network); 20 Apr 2001 07:32:47 -0000 Received: from sunsite.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 20 Apr 2001 07:32:47 -0000 Received: (qmail 21533 invoked by alias); 20 Apr 2001 07:32:41 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 14051 Received: (qmail 21520 invoked from network); 20 Apr 2001 07:32:41 -0000 From: "Bart Schaefer" Message-Id: <1010420052020.ZM24206@candle.brasslantern.com> Date: Fri, 20 Apr 2001 05:20:20 +0000 In-Reply-To: <1010419093411.ZM8881@candle.brasslantern.com> Comments: In reply to "Bart Schaefer" "Re: PATCH: Assorted parameter stuff" (Apr 19, 9:34am) References: <200104190705.JAA10878@beta.informatik.hu-berlin.de> <1010419093411.ZM8881@candle.brasslantern.com> X-Mailer: Z-Mail (5.0.0 30July97) To: zsh-workers@sunsite.dk Subject: Re: PATCH: Assorted parameter stuff MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii 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 --'. } } 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