zsh-workers
 help / color / mirror / code / Atom feed
* Re: path and += troubles
       [not found] <1051126170046.ZM773@candle.brasslantern.com>
@ 2005-11-26 18:40 ` Peter Stephenson
  2005-11-26 21:13   ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2005-11-26 18:40 UTC (permalink / raw)
  To: zsh-workers

> 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:

./=foo

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
(http://www.opengroup.org/onlinepubs/009695399/toc.htm):

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 @@
 pindex(EQUALS)
 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.
 )
 pindex(EXTENDED_GLOB)
 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 == '+')
                     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@ntlworld.com>
Web page still at http://www.pwstephenson.fsnet.co.uk/


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: path and += troubles
  2005-11-26 18:40 ` path and += troubles Peter Stephenson
@ 2005-11-26 21:13   ` Bart Schaefer
  2005-11-27 13:34     ` Peter Stephenson
  0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2005-11-26 21:13 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

On Nov 26,  6:40pm, Peter Stephenson wrote:
} Subject: Re: path and += troubles
}
} > On Nov 25,  9:32pm, Steven Klass wrote:
} > }
} > } 		$1+=($2)
} > 
} > 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.
} 
} It's a bug if you think the "=" should always indicate an assignment

No, that's not it.

} Otherwise, it looks like
} an expression with a set of globbing qualifiers at the end

Exactly ... the problem is this:

schaefer<508> echo $1+=($2)
zsh: no match
schaefer<509> $1+=($2)
schaefer<510> 

Where's my "no match" error in the second case?

} 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.

That's just fine, and I don't think it should be changed.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: path and += troubles
  2005-11-26 21:13   ` Bart Schaefer
@ 2005-11-27 13:34     ` Peter Stephenson
  2005-11-27 18:40       ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2005-11-27 13:34 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> Exactly ... the problem is this:
> 
> schaefer<508> echo $1+=($2)
> zsh: no match
> schaefer<509> $1+=($2)
> schaefer<510> 
> 
> Where's my "no match" error in the second case?

(I'll abandon the other patch since that's not what you're worried
about.)

I'm having a hard time coming up with a combination of options and
arguments that does this.

% zsh -f           
% echo $1+=($2)
zsh: no matches found: +=()
% $1+=($2)
zsh: no matches found: +=()
% fn1() { echo $1+=($2); }
% fn1
fn1: no matches found: +=()
% fn2() { $1+=($2); }     
% fn2
fn2: no matches found: +=()
% fn2 path /usr/bin
fn2: missing end of name

(the last is supposed to look like what Steven was trying to do.)

But didn't you say the problem was with NULLGLOB?  Surely you'd expect
the presence of something looking like glob qualifiers (as long as
they're valid, and a lot of strings are valid global qualifiers) to make
the command turn out to be a boojum?

% setopt nullglob
% foo(.)
% $1+=(.)
% $1+=($2)
%

What am I missing?

One oddity is that +=($2) *does* give a "not an indentifier" error,
which is almost redundant with the current way of parsing assignments.
I think that's because the lexical analyser finds that "=" is not at the
start, so searches for an assignment.  Then it finds an empty identifier
and skips over the "+".  This means that it successfully meets the
condition for an ENVSTRING (we got to the "=" without finding an invalid
character).  Later, the actual assignment rejects this with contumely.
This is a small inconsistency.

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


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: path and += troubles
  2005-11-27 13:34     ` Peter Stephenson
@ 2005-11-27 18:40       ` Bart Schaefer
  2005-11-27 20:39         ` Peter Stephenson
  0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2005-11-27 18:40 UTC (permalink / raw)
  To: zsh-workers

On Nov 27,  1:34pm, Peter Stephenson wrote:
} Subject: Re: path and += troubles
}
} > schaefer<508> echo $1+=($2)
} > zsh: no match
} > schaefer<509> $1+=($2)
} > schaefer<510> 
} > 
} > Where's my "no match" error in the second case?
} 
} I'm having a hard time coming up with a combination of options and
} arguments that does this.

Starting from "zsh -f":

zagzig% setopt cshnullglob
zagzig% echo $1+=($2)
zsh: no match
zagzig% $1+=($2)
zagzig% 

The problem of course is that cshnullglob is supposed to be like nomatch
if *nothing* matches -- it's only supposed to be like nullglob if at
least one of several patterns matches.

} But didn't you say the problem was with NULLGLOB?

I originally [in the -users thread] mentioned that the error message
vanishes with either nullglob or cshnullglob.  After I figured out that
it happens because the test string I was using was somehow a valid glob
qualifier -- that is, "(2)" is a valid qualifier, though I have no idea
what meaning it can possibly have -- then I said [on -workers] that it
was limited to cshnullglob.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: path and += troubles
  2005-11-27 18:40       ` Bart Schaefer
@ 2005-11-27 20:39         ` Peter Stephenson
  2005-11-28  1:15           ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2005-11-27 20:39 UTC (permalink / raw)
  To: zsh-workers

Bart Schaefer wrote:
> Starting from "zsh -f":
> 
> zagzig% setopt cshnullglob
> zagzig% echo $1+=($2)
> zsh: no match
> zagzig% $1+=($2)
> zagzig% 
> 
> The problem of course is that cshnullglob is supposed to be like nomatch
> if *nothing* matches -- it's only supposed to be like nullglob if at
> least one of several patterns matches.

The first argument is globbed separately in order to check whether its
arguments require special expansion, via a direct call to zglob() rather
than globlist() which is where cshnullglob is handled.  Even if the flag
had been set, if globlist() were later called for other arguments the
flag would be reset.

Does applying cshnullglob to the command word and its argument list
together make sense?  It would mean you were happy for any of the
expansions to give you the command to run.  I suppose that's just
conceivable.  This would need fixing up around execcmd() by separating
out the cshnullglob handling from globlist(), though we still need the
current form of handling in globlist() for other uses like array
assignments... not very pretty.

> I originally [in the -users thread] mentioned that the error message
> vanishes with either nullglob or cshnullglob.  After I figured out that
> it happens because the test string I was using was somehow a valid glob
> qualifier -- that is, "(2)" is a valid qualifier, though I have no idea
> what meaning it can possibly have -- then I said [on -workers] that it
> was limited to cshnullglob.

Looks like it means an octal mode: try *(644).  I have no idea where
this came from; it doesn't appear to be documented.

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


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: path and += troubles
  2005-11-27 20:39         ` Peter Stephenson
@ 2005-11-28  1:15           ` Bart Schaefer
  0 siblings, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2005-11-28  1:15 UTC (permalink / raw)
  To: zsh-workers

On Nov 27,  8:39pm, Peter Stephenson wrote:
}
} > zagzig% setopt cshnullglob
} > zagzig% $1+=($2)
} > zagzig% 
} 
} The first argument is globbed separately in order to check whether its
} arguments require special expansion, via a direct call to zglob() rather
} than globlist() which is where cshnullglob is handled.
[...]
} Does applying cshnullglob to the command word and its argument list
} together make sense?

No, I don't think it does.  A glob failure in command position should,
I think, always be a failure unless NO_NOMATCH is set.  It doesn't make
sense to me to produce an empty command name without failing.  Even with
NULL_GLOB, the empty command name should produce "command not found" or
some such error.

I've just tried tcsh and it produces "no match" on any glob failure in
command position, even if the rest of the arguments are successful globs.


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-11-28  1:16 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1051126170046.ZM773@candle.brasslantern.com>
2005-11-26 18:40 ` path and += troubles Peter Stephenson
2005-11-26 21:13   ` Bart Schaefer
2005-11-27 13:34     ` Peter Stephenson
2005-11-27 18:40       ` Bart Schaefer
2005-11-27 20:39         ` Peter Stephenson
2005-11-28  1:15           ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).