about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/expn.yo7
-rw-r--r--Doc/Zsh/options.yo7
-rw-r--r--Src/subst.c3
-rw-r--r--Test/D04parameter.ztst9
5 files changed, 28 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 681975a05..995717e46 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2015-05-31  Peter Stephenson  <p.w.stephenson@ntlworld.com>
+
+	* 35343: Doc/Zsh/expn.yo, Doc/Zsh/options.yo, Src/subst.c,
+	Test/D04parameter.ztst: $#foo for any valid identifier
+	is only the length of foo if POSIX_IDENTIFIERS is not set.
+
 2015-05-30  Barton E. Schaefer  <schaefer@zsh.org>
 
 	* users/20238: Doc/Zsh/builtins.yo, Src/builtin.c: add "fc -L" to
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index afd6b1ff9..7d4e6fccb 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -777,6 +777,13 @@ This has the side-effect that joining is skipped even in quoted
 forms, which may affect other sub-expressions in var(spec).
 Note that `tt(^)', `tt(=)', and `tt(~)', below, must appear
 to the left of `tt(#)' when these forms are combined.
+
+If the option tt(POSIX_IDENTIFIERS) is not set, and var(spec) is a
+simple name, then the braces are optional; this is true even
+for special parameters so e.g. tt($#-) and tt($#*) take the length
+of the string tt($-) and the array tt($*) respectively.  If
+tt(POSIX_IDENTIFIERS) is set, then braces are required for
+the tt(#) to be treated in this fashion.
 )
 item(tt(${^)var(spec)tt(}))(
 pindex(RC_EXPAND_PARAM, toggle)
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 4c0ae122f..4dd68c9cb 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -2054,6 +2054,13 @@ When this option is set, only the ASCII characters tt(a) to tt(z), tt(A) to
 tt(Z), tt(0) to tt(9) and tt(_) may be used in identifiers (names
 of shell parameters and modules).
 
+In addition, setting this option limits the effect of parameter
+substitution with no braces, so that the expression tt($#) is treated as
+the parameter tt($#) even if followed by a valid parameter name.
+When it is unset, zsh allows expresions of the form tt($#)var(name)
+to refer to the length of tt($)var(name), even for special variables,
+for example in expressions such as tt($#-) and tt($#*).
+
 When the option is unset and multibyte character support is enabled (i.e. it
 is compiled in and the option tt(MULTIBYTE) is set), then additionally any
 alphanumeric characters in the local character set may be used in
diff --git a/Src/subst.c b/Src/subst.c
index 168f7f156..81d34d28a 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(POSIXIDENTIFIERS)) &&
 		   (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 c41e05ed3..d06a73afd 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