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

Re: Function code breaking out of if then ...fi



On the behaviour that when the shell encounters a "fatal" error in a
script it resumes at the next "top level" command:  here's a proposal.
This makes that behaviour optional, for compatibility, but turns it off
by default.  I don't think the old, undocumented, behaviour is intuitive
enough for us to go on leaving it as the default.  The shell essentially
skips a chunk of code and resumes later on at a point where there's not
the slightest reason to suppose it's appropriate to do so; you might be
relying on the structure that was previously executing to set things up
for the next chunk of code.

I'm not really even sure we need the option, but it seems possible that
people who happened on the behaviour have become reliant on it.

I've taken the opportunity to document the behaviour on fatal errors.
The list is exhausting rather than exhaustive.  I haven't bothered
listing errors associated with interactive shells where you'd be
returned to the command prompt.

That test at the end was a bit weird:  I don't think it was testing
POSIX_BUILTINS at all since errors with read-only variables are always
hard errors as a grep for the error message will immediately show.
It does provide a useful test for CONTINUE_ON_ERROR.

Index: Doc/Zsh/grammar.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/grammar.yo,v
retrieving revision 1.23
diff -p -u -r1.23 grammar.yo
--- Doc/Zsh/grammar.yo	1 Feb 2012 12:53:49 -0000	1.23
+++ Doc/Zsh/grammar.yo	9 Nov 2012 22:43:30 -0000
@@ -438,7 +438,7 @@ where var(term) is at least one newline 
 A short form of tt(select).
 )
 enditem()
-texinode(Reserved Words)(Comments)(Alternate Forms For Complex Commands)(Shell Grammar)
+texinode(Reserved Words)(Errors)(Alternate Forms For Complex Commands)(Shell Grammar)
 sect(Reserved Words)
 cindex(reserved words)
 findex(disable, use of)
@@ -451,7 +451,56 @@ select coproc nocorrect foreach end ! [[
 
 Additionally, `tt(})' is recognized in any position if neither the
 tt(IGNORE_BRACES) option nor the tt(IGNORE_CLOSE_BRACES) option is set.
-texinode(Comments)(Aliasing)(Reserved Words)(Shell Grammar)
+texinode(Errors)(Comments)(Reserved Words)(Shell Grammar)
+sect(Errors)
+cindex(errors, handling of)
+Certain errors are treated as fatal by the shell: in an interactive
+shell, they cause control to return to the command line, and in a
+non-interactive shell they cause the shell to be aborted.  In older
+versions of zsh, a non-interactive shell running a script would not
+abort completely, but would resume execution at the next command to be
+read from the script, skipping the remainder of any functions or
+shell constructs such as loops or conditions; this somewhat illogical
+behaviour can be recovered by setting the option tt(CONTINUE_ON_ERROR).
+
+Fatal errors found in non-interactive shells include:
+startlist()
+list(Failure to parse shell options passed when invoking the shell)
+list(Failure to change options with the tt(set) builtin)
+list(Parse errors of all sorts, including failures to parse
+mathematical expressions)
+list(Failures to set or modify variable behaviour with tt(typeset),
+tt(local), tt(declare), tt(export), tt(integer), tt(float))
+list(Execution of incorrectly positioned loop control structures
+(tt(continue), tt(break)))
+list(Attempts to use regular expression with no regular expression
+module available)
+list(Disallowed operations when the tt(RESTRICTED) options is set)
+list(Failure to create a pipe needed for a pipeline)
+list(Failure to create a multio)
+list(Failure to autoload a module needed for a declared shell feature)
+list(Errors creating command or process substitutions)
+list(Syntax errors in glob qualifiers)
+list(File generation errors where not caught by the option tt(BAD_PATTERN))
+list(All bad patterns used for matching within case statements)
+list(File generation failures where not caused by tt(NO_MATCH) or
+list(All file generation errors where the pattern was used to create a
+multio)
+list(Memory errors where detected by the shell)
+list(Invalid subscripts to shell variables)
+list(Attempts to assign read-only variables)
+list(Logical errors with variables such as assignment to the wrong type)
+list(Use of invalid variable names)
+list(Errors in variable substitution syntax)
+list(Failure to convert characters in tt($')...tt(') expressions)
+similar options)
+endlist()
+
+If the tt(POSIX_BUILTINS) option is set, more errors associated with
+shell builtin commands are treated as fatal, as specified by the POSIX
+standard.
+
+texinode(Comments)(Aliasing)(Errors)(Shell Grammar)
 sect(Comments)
 cindex(comments)
 pindex(INTERACTIVE_COMMENTS, use of)
Index: Doc/Zsh/options.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/options.yo,v
retrieving revision 1.107
diff -p -u -r1.107 options.yo
--- Doc/Zsh/options.yo	1 Mar 2012 03:34:15 -0000	1.107
+++ Doc/Zsh/options.yo	9 Nov 2012 22:43:31 -0000
@@ -1733,6 +1733,22 @@ Make the tt(echo) builtin compatible wit
 This disables backslashed escape sequences in echo strings unless the
 tt(-e) option is specified.
 )
+pindex(CONTINUE_ON_ERROR)
+pindex(NO_CONTINUE_ON_ERROR)
+pindex(CONTINUEONERROR)
+pindex(NOCONTINUEONERROR)
+cindex(error, option to continue script on)
+item(tt(CONTINUE_ON_ERROR))(
+If a fatal error is encountered (see 
+ifnzman(noderef(Errors))\
+ifzman(the section ERRORS in zmanref(zshmisc))), and the code is running
+in a script, the shell will resume execution at the next statement
+in the script at the top level, in other words outside all functions
+or shell constructs such as loops and conditions.  This mimics the
+behaviour of interactive shells, where the shell returns to the
+line editor to read a new command; it was the normal behaviour in versions
+of zsh before 5.0.1.
+)
 pindex(CSH_JUNKIE_HISTORY)
 pindex(NO_CSH_JUNKIE_HISTORY)
 pindex(CSHJUNKIEHISTORY)
Index: Src/hist.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/hist.c,v
retrieving revision 1.118
diff -p -u -r1.118 hist.c
--- Src/hist.c	21 Apr 2012 18:42:56 -0000	1.118
+++ Src/hist.c	9 Nov 2012 22:43:31 -0000
@@ -573,7 +573,7 @@ histsubchar(int c)
 		} else {
 		    herrflush();
 		    unqueue_signals();
-		    zerr("Ambiguous history reference");
+		    zerr("ambiguous history reference");
 		    return -1;
 		}
 
Index: Src/init.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/init.c,v
retrieving revision 1.127
diff -p -u -r1.127 init.c
--- Src/init.c	11 Oct 2012 20:14:03 -0000	1.127
+++ Src/init.c	9 Nov 2012 22:43:31 -0000
@@ -1608,15 +1608,20 @@ zsh_main(UNUSED(int argc), char **argv)
 	 * We only do this at top level, because if we are
 	 * executing stuff we may refer to them by job pointer.
 	 */
+	int errexit = 0;
 	maybeshrinkjobtab();
 
 	do {
 	    /* Reset return from top level which gets us back here */
 	    retflag = 0;
 	    loop(1,0);
+	    if (errflag && !interact && !isset(CONTINUEONERROR)) {
+		errexit = 1;
+		break;
+	    }
 	} while (tok != ENDINPUT && (tok != LEXERR || isset(SHINSTDIN)));
-	if (tok == LEXERR) {
-	    /* Make sure a parse error exits with non-zero status */
+	if (tok == LEXERR || errexit) {
+	    /* Make sure a fatal error exits with non-zero status */
 	    if (!lastval)
 		lastval = 1;
 	    stopmsg = 1;
Index: Src/options.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/options.c,v
retrieving revision 1.65
diff -p -u -r1.65 options.c
--- Src/options.c	11 Oct 2012 20:14:03 -0000	1.65
+++ Src/options.c	9 Nov 2012 22:43:31 -0000
@@ -113,6 +113,7 @@ static struct optname optns[] = {
 {{NULL, "combiningchars",     0},			 COMBININGCHARS},
 {{NULL, "completealiases",    0},			 COMPLETEALIASES},
 {{NULL, "completeinword",     0},			 COMPLETEINWORD},
+{{NULL, "continueonerror",    0},                        CONTINUEONERROR},
 {{NULL, "correct",	      0},			 CORRECT},
 {{NULL, "correctall",	      0},			 CORRECTALL},
 {{NULL, "cshjunkiehistory",   OPT_EMULATE|OPT_CSH},	 CSHJUNKIEHISTORY},
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.186
diff -p -u -r1.186 zsh.h
--- Src/zsh.h	11 Oct 2012 20:14:03 -0000	1.186
+++ Src/zsh.h	9 Nov 2012 22:43:31 -0000
@@ -1971,6 +1971,7 @@ enum {
     COMPLETEINWORD,
     CORRECT,
     CORRECTALL,
+    CONTINUEONERROR,
     CPRECEDENCES,
     CSHJUNKIEHISTORY,
     CSHJUNKIELOOPS,
Index: Test/A04redirect.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A04redirect.ztst,v
retrieving revision 1.24
diff -p -u -r1.24 A04redirect.ztst
--- Test/A04redirect.ztst	3 Oct 2012 18:11:15 -0000	1.24
+++ Test/A04redirect.ztst	9 Nov 2012 22:43:31 -0000
@@ -419,26 +419,26 @@
 >output
 ?zsh:.:2: no such file or directory: /nonexistent/nonexistent
 
-  $ZTST_testdir/../Src/zsh -f <<<'
+  $ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<'
   readonly foo
   foo=bar set output
   echo output'
-0:failed assignment on posix special, NO_POSIX_BUILTINS
+0:failed assignment on posix special, CONTINUE_ON_ERROR
 >output
 ?zsh: read-only variable: foo
 
-  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS <<<'
+  $ZTST_testdir/../Src/zsh -f <<<'
   readonly foo
   foo=bar set output
   echo output'
-1:failed assignment on posix special, POSIX_BUILTINS
+1:failed assignment on posix special, NO_CONTINUE_ON_ERROR
 ?zsh: read-only variable: foo
 
-  $ZTST_testdir/../Src/zsh -f -o POSIX_BUILTINS <<<'
+  $ZTST_testdir/../Src/zsh -f -o CONTINUE_ON_ERROR <<<'
   readonly foo
   foo=bar echo output
   echo output'
-0:failed assignment on non-posix-special, POSIX_BUILTINS
+0:failed assignment on non-posix-special, CONTINUE_ON_ERROR
 >output
 ?zsh: read-only variable: foo
 

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