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

Re: path and += troubles

> On Nov 25,  9:32pm, Steven Klass wrote:
> }
> } 		# Append the path to the end..
> } 		$1+=($2)
> As you've discovered, this won't work.  $1 is not an identifier (it's an
> identifier dereference) so $1+= is not an assignment.  Of course, you
> need to have a recent-enough version of zsh to support += assignments.
> For some reason "setopt nullglob" (even cshnullglob) prevents the error
> message that would otherwise be produced for this line, turning it into
> a silent no-op.  I think that's probably an obscure bug.

(Redirected to zsh-workers.)

It's a bug if you think the "=" should always indicate an assignment and
therefore cause an error if there isn't one.  Otherwise, it looks like
an expression with a set of globbing qualifiers at the end, and it
depends on $2 whether this is a valid set of globbing qualifiers that
fail to match a file or an error.  (For example, if $2 is foo you get
"invalid mode specification".)

At the moment lexical analysis is fairly restrictive about what it will
consider an assignment; if it doesn't like it, it will decide it's just
an ordinary string, so the word will be parsed as a command.

I have a trivial fix for this, but I'm wary about applying it since it
means the following also looks like a duff assignment:


and to most users (as well as, taking a convenient local sample of
shells, to bash and ash) it probably looks like it's going to run the
file =foo in the current directory.

The Single Unix Specification, aka IEEE Std 1003.1, 2004 Edition,
however, apparently allows us to go both ways

2.10.2 Shell grammar rules


7  [Assignment preceding command name]

  a. [When the first word]
     If the TOKEN does not contain the character '=', rule 1 is
     applied. Otherwise, 7b shall be applied.

  b. [Not the first word]
     If the TOKEN contains the equal sign character:
       - If it begins with '=', the token WORD shall be returned.
       - If all the characters preceding '=' form a valid name (see the
         Base Definitions volume of IEEE Std 1003.1-2001, Section 3.230,
         Name), the token ASSIGNMENT_WORD shall be returned. (Quoted
         characters cannot participate in forming a valid name.)
       - Otherwise, it is unspecified whether it is ASSIGNMENT_WORD or WORD
         that is returned.

  Assignment to the NAME shall occur as specified in Simple Commands.

Here, ASSIGNMENT_WORD and WORD correspond to the zsh tokens ENVSTRING
and STRING.  My change would take account of the first point of 7b.: we
certainly want =ls not to be parsed as an assignment.

We could use the kludge that if NO_EQUALS is set (which is the default
for any emulation other than native zsh) we parse duff assignments as an
ordinary string (as at present), and if EQUALS is set (which is the
default for native zsh) we parse them as assignments, meaning we later
report an error.  The logic for this is interpreting the EQUALS option
to mean "= signs are more special and need quoting when you want to use
them as part of a normal string".  The patch for that is as follows.
I won't apply this immediately.

Index: Doc/Zsh/options.yo
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/options.yo,v
retrieving revision 1.42
diff -u -r1.42 options.yo
--- Doc/Zsh/options.yo	4 Oct 2005 17:28:19 -0000	1.42
+++ Doc/Zsh/options.yo	26 Nov 2005 18:33:08 -0000
@@ -333,8 +333,12 @@
 cindex(filename expansion, =)
 item(tt(EQUALS) <Z>)(
-Perform tt(=) filename expansion.
-(See noderef(Filename Expansion).)
+Perform tt(=) filename expansion.  (See noderef(Filename Expansion).)
+When this option is in effect, words at the start of the command line
+which resemble assignments but do not have a valid indentifier before
+the tt(=) are parsed as assignments.  This means lines like tt($1=foo)
+and tt(./=mycmd) are treated as errors.
 cindex(globbing, extended)
Index: Src/lex.c
RCS file: /cvsroot/zsh/zsh/Src/lex.c,v
retrieving revision 1.31
diff -u -r1.31 lex.c
--- Src/lex.c	11 Oct 2005 16:48:06 -0000	1.31
+++ Src/lex.c	26 Nov 2005 18:33:09 -0000
@@ -1143,7 +1143,15 @@
 		if (*t == '+')
-		if (t == bptr) {
+		/*
+		 * 2005/11/26: Changed by pws from "if (t == bptr)" so
+		 * that when EQUALS is in effect we recognise this as an
+		 * assignment just as long as the "=" isn't at the start
+		 * of the line.  This means invalid assignments (such as
+		 * $1=...) trigger an error rather than being treated as
+		 * commands.
+		 */
+		if (isset(EQUALS) ? (bptr > tokstr) : (t == bptr)) {
 		    e = hgetc();
 		    if (e == '(' && incmdpos) {
 			*bptr = '\0';

Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page still at http://www.pwstephenson.fsnet.co.uk/

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