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

Re: Arith parsing bug with minus after $#



On Sat, 30 May 2015 20:24:12 +0100
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx> wrote:
> On Fri, 29 May 2015 14:24:45 -0700
> Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> > On May 29, 2015 1:54 PM, "ZyX" <kp-pav@xxxxxxxxx> wrote:
> > >
> > > But later it explicitly says that not enclosed in single braces may only
> > be names or single-character variables. I.e. $#- is ${#}-, $10 is ${1}0, …
> > 
> > Yes, but $#name to return the length of the value of $name is already a zsh
> > extension, so unless we're in some emulation mode, treating $#- as the
> > length of $- is perfectly reasonable.
> 
> Perhaps more interesting is $#*, since "*" is a much more commmon
> special parameter that's also an operator, and isn't quite so horrifically
> overloaded in parameter substitution.
> 
> % emulate sh -c 'fn() { echo $(( $#*3 )); }'
> % fn one
> 13
> 
> That looks like it needs some emulation, though it can wait since nobody's
> tripped over it.

It's easy, though, so no time like the present...  and this ought to be
consistent across all parameters, so make "-" behave the same.

What I'm not sure about is how to decide.  SH_WORD_SPLIT isn't the
same thing, though there's an obvious mnemonic for why it might have
this effect. We have the option of basing it on emulation alone, but
that always strikes me as something of a counsel of despair.  I'll add
documentation when this gets decided.

diff --git a/Src/subst.c b/Src/subst.c
index 168f7f1..67bd088 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2156,6 +2156,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
 		    nojoin = !(ifs && *ifs);
 	    }
 	} else if ((c == '#' || c == Pound) &&
+		   (inbrace || !isset(SHWORDSPLIT)) &&
 		   (itype_end(s+1, IIDENT, 0) != s + 1
 		    || (cc = s[1]) == '*' || cc == Star || cc == '@'
 		    || cc == '?' || cc == Quest
@@ -2170,7 +2171,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
 		     */
 		    || ((cc == '#' || cc == Pound) &&
 			s[2] == Outbrace)
-		    || (inbrace && (cc == '-' || (cc == ':' && s[2] == '-')))
+		    || cc == '-' || (cc == ':' && s[2] == '-')
 		    || (isstring(cc) && (s[2] == Inbrace || s[2] == Inpar)))) {
 	    getlen = 1 + whichlen, s++;
 	    /*
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index c41e05e..d06a73a 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -1704,7 +1704,10 @@
   [[ $funnychars = ${~${(b)funnychars}} ]]
 0:${(b)...} quoting protects from GLOB_SUBST
 
-  set --
-  print $#-1
-0:Avoid confusion after overloaded characters in braceless substitution
+  set -- foo
+  echo $(( $#*3 ))
+  emulate sh -c 'nolenwithoutbrace() { echo $#-1; }'
+  nolenwithoutbrace
+0:Avoid confusion after overloaded characters in braceless substitution in sh
+>13
 >0-1



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