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

Re: sh compatibility issue



On Sun, 20 Feb 2011 00:05:40 +0100
Jilles Tjoelker <jilles@xxxxxxxx> wrote:
> > !(...) without space
> 
> I think the POSIX spec requires this to work, but that may not be
> intentional. '(' is an operator and therefore it does not need a space
> between it and other characters (except to disambiguate between two
> adjacent operators and one two-character operator). It may not be
> intentional because it conflicts with ksh extended pattern matching.
> 
> More generally, this rule also means that things like
>   while(true)do(pwd)done
> do not need any spaces. Although this example is contrived, I can
> imagine there are real scripts that zsh fails to parse because of this;
> the other shells I tried execute it correctly.

I think we can manage that when SH_GLOB is on (it'll screw up zsh
patterns royally otherwise), but it's quite a big change and we don't
have many tests for sh emulation, so someone ought to see what this
patch does before it goes much further.  All I've tested is what's in
the test patch.

This replaces the previous patch, but note that means you still need the
spaces in native zsh mode --- can't see a real problem there, in fact
it's probably safer as well as more consistent.

I had to exclude it with KSH_GLOB on because of the way we handle
KSH_GLOB expressions.  That's not the correct thing to do --- we should
handle KSH_GLOB expressions in the lexical analysis --- but KSH_GLOB
isn't on for normal sh emulation so I don't think it's a major problem.

> The situation for '!{' is different. '{' is a reserved word and
> therefore it is not recognized. Instead, this describes a utility (or
> alias) that probably does not exist. I do not recommend making special
> allowances for it.

You're right that '{' is different from '('.  I haven't done anything
special with it here.

> On a related note, here is another quite insidious sh compatibility
> issue:
>   sh -c 'exec </nonexistent/a; echo wrong'
> This should not print "wrong" because exec is a special builtin and
> redirection errors on special builtins are fatal. Most shells get this
> right nowadays (bash only in POSIX mode) but zsh gets it wrong. Even
>   set -o posixbuiltins
> does not help.

I think it does need to be fatal, but not because it's a special builtin
--- it looks like that's only a "may" rather than a "shall" --- but
because there is a rule for exec:

  If a redirection error occurs (see Consequences of Shell Errors ), the
  shell shall exit with a value in the range 1-125

which is certainly unambiguous on the subject.  This will need looking at.

Index: Doc/Zsh/options.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/options.yo,v
retrieving revision 1.99
diff -p -u -r1.99 options.yo
--- Doc/Zsh/options.yo	16 Dec 2010 13:55:35 -0000	1.99
+++ Doc/Zsh/options.yo	20 Feb 2011 19:04:30 -0000
@@ -683,8 +683,12 @@ item(tt(SH_GLOB) <K> <S>)(
 Disables the special meaning of `tt(LPAR())', `tt(|)', `tt(RPAR())'
 and 'tt(<)' for globbing the result of parameter and command substitutions,
 and in some other places where
-the shell accepts patterns.  This option is set by default if zsh is
-invoked as tt(sh) or tt(ksh).
+the shell accepts patterns.  If tt(SH_GLOB) is set but tt(KSH_GLOB) is
+not, the shell allows the interpretation of
+subshell expressions enclosed in parentheses in some cases where there
+is no space before the opening parenthesis, e.g. tt(!LPAR()true+RPAR())
+is interpreted as if there were a space after the tt(!).  This option is
+set by default if zsh is invoked as tt(sh) or tt(ksh).
 )
 pindex(UNSET)
 pindex(NO_UNSET)
Index: Src/lex.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/lex.c,v
retrieving revision 1.63
diff -p -u -r1.63 lex.c
--- Src/lex.c	19 Dec 2010 17:42:10 -0000	1.63
+++ Src/lex.c	20 Feb 2011 19:04:30 -0000
@@ -877,7 +877,7 @@ gettok(void)
 		dbparens = 1;
 		return DINPAR;
 	    }
-	    if (incmdpos) {
+	    if (incmdpos || (isset(SHGLOB) && !isset(KSHGLOB))) {
 		len = 0;
 		bptr = tokstr = (char *) hcalloc(bsiz = 32);
 		switch (cmd_or_math(CS_MATH)) {
@@ -1141,6 +1141,8 @@ gettokstr(int c, int sub)
 		    break;
 		if (incasepat && !len)
 		    return INPAR;
+		if (!isset(KSHGLOB) && len)
+		    goto brk;
 	    }
 	    if (!in_brace_param) {
 		if (!sub) {
Index: Test/A01grammar.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A01grammar.ztst,v
retrieving revision 1.27
diff -p -u -r1.27 A01grammar.ztst
--- Test/A01grammar.ztst	18 Mar 2010 16:30:58 -0000	1.27
+++ Test/A01grammar.ztst	20 Feb 2011 19:04:30 -0000
@@ -577,3 +577,15 @@
 0:$0 is traditionally if bizarrely set to the first argument with -c
 >myargzero
 >myargone
+
+  (setopt shglob
+  eval '
+  if ! (echo success1); then echo failure1; fi
+  if !(echo success2); then echo failure2; fi
+  print -l one two | while(read foo)do(print read it)done
+  ')
+0:Parentheses in shglob
+>success1
+>success2
+>read it
+>read it


-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



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