From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6238 invoked by alias); 2 Oct 2016 18:01:12 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 39540 Received: (qmail 21078 invoked from network); 2 Oct 2016 18:01:12 -0000 X-Qmail-Scanner-Diagnostics: from know-smtprelay-omc-1.server.virginmedia.net by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(80.0.253.65):SA:0(-0.0/5.0):. Processed in 0.508598 secs); 02 Oct 2016 18:01:12 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.1 X-Envelope-From: p.w.stephenson@ntlworld.com X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: pass (ns1.primenet.com.au: SPF record at _smtprelay.virginmedia.com designates 80.0.253.65 as permitted sender) X-Originating-IP: [86.21.219.59] X-Spam: 0 X-Authority: v=2.1 cv=beuWK77B c=1 sm=1 tr=0 a=utowdAHh8RITBM/6U1BPxA==:117 a=utowdAHh8RITBM/6U1BPxA==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=kj9zAlcOel0A:10 a=P5Q6L1DsAAAA:8 a=Nlb0ESlPc8USRy0re6sA:9 a=J_mqw0XQ4s9pk6vy:21 a=GQelWxYQe-zYyTSk:21 a=CjuIK1q_8ugA:10 a=jxi25fIUQso1YTL4nQQM:22 Date: Sun, 2 Oct 2016 18:55:30 +0100 From: Peter Stephenson To: Zsh hackers list Subject: Re: 'set -e' with '!' POSIX issue Message-ID: <20161002185530.3fa8c013@ntlworld.com> In-Reply-To: <70cf25f2-f156-51c4-60b6-00def8769328@inlv.org> References: <70cf25f2-f156-51c4-60b6-00def8769328@inlv.org> X-Mailer: Claws Mail 3.11.1 (GTK+ 2.24.28; x86_64-redhat-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Sun, 2 Oct 2016 11:01:18 +0100 Martijn Dekker wrote: > 'set -e' ('set -o errexit') is not POSIX compliant on zsh because it > doesn't ignore a command beginning with "!". I don't really like the errexit logic as there are too many horrible cases, since the place we need to test is different from where the code is being executed (look at the particularly horrible oldnoeerrexit logic). This was not entirely trivial but we might get away with it. The tests are for ERR_RETURN because that's easier to write; most of the logic is shared with ERR_EXIT. pws diff --git a/Src/exec.c b/Src/exec.c index 349414c..a429428 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -1226,6 +1226,7 @@ execlist(Estate state, int dont_change_job, int exiting) } while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) { int donedebug; + int this_noerrexit = 0; ltype = WC_LIST_TYPE(code); csp = cmdsp; @@ -1309,9 +1310,12 @@ execlist(Estate state, int dont_change_job, int exiting) goto sublist_done; } while (wc_code(code) == WC_SUBLIST) { + int isend = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END); next = state->pc + WC_SUBLIST_SKIP(code); if (!oldnoerrexit) - noerrexit = (WC_SUBLIST_TYPE(code) != WC_SUBLIST_END); + noerrexit = !isend; + if ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) && isend) + this_noerrexit = 1; switch (WC_SUBLIST_TYPE(code)) { case WC_SUBLIST_END: /* End of sublist; just execute, ignoring status. */ @@ -1427,7 +1431,7 @@ sublist_done: /* Check whether we are suppressing traps/errexit * * (typically in init scripts) and if we haven't * * already performed them for this sublist. */ - if (!noerrexit && !donetrap) { + if (!noerrexit && !this_noerrexit && !donetrap) { if (sigtrapped[SIGZERR] && lastval) { dotrap(SIGZERR); donetrap = 1; diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst index 83c05aa..3a65b28 100644 --- a/Test/C03traps.ztst +++ b/Test/C03traps.ztst @@ -519,6 +519,43 @@ >Yes F:Must be tested with a top-level script rather than source or function + fn() { + emulate -L zsh + setopt errreturn + print before + false + print after + } + fn +1:ERRRETURN, basic case +>before + + fn() { + emulate -L zsh + setopt errreturn + print before + ! true + ! false + print after + } + fn +0:ERRETURN with "!" +>before +>after + + fn() { + emulate -L zsh + setopt errreturn + print before + ! true + ! false + false + print after + } + fn +1:ERRETURN with "!" and a following false +>before + %clean rm -f TRAPEXIT