From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1479 invoked from network); 19 May 1999 10:10:19 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 19 May 1999 10:10:19 -0000 Received: (qmail 26898 invoked by alias); 19 May 1999 10:10:09 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 6314 Received: (qmail 26891 invoked from network); 19 May 1999 10:10:08 -0000 Message-Id: <9905190944.AA29055@ibmth.df.unipi.it> To: Clint Adams , zsh-workers@sunsite.auc.dk (Zsh hackers list) Subject: PATCH: pws-18: ERR_EXIT behavior inconsistent with other shells In-Reply-To: "Clint Adams"'s message of "Mon, 17 May 1999 00:08:02 DFT." <19990517000802.A27319@dman.com> Date: Wed, 19 May 1999 11:44:05 +0200 From: Peter Stephenson Last thing on my to-do list before pws-19: Clint Adams wrote: > ARGV0=sh zsh -fexc 'testerrexit() { return 1; }; false || echo simplecommand; > testerrexit || echo function'; echo $? > > does this > > + false > + echo simplecommand > simplecommand > + testerrexit > + return 1 > 1 > > Other shells seems to do this > > ARGV0=sh ksh -fexc 'testerrexit() { return 1; }; false || echo simplecommand; > te > sterrexit || echo function'; echo $? > > + false > + echo simplecommand > simplecommand > + testerrexit > + echo function > function > 0 It took me a couple of minutes to work out the logic: any shell stuff which is followed at any level of execution by a || or && should suppress errexit until the final set of commands in the chain at the level at which the || or && appears. I originally thought that being in a function was turning off errexit, but that's not it, and it should apply to { ... } structures as well as functions (I checked this). I can't imagine this was anything other than an oversight in the zsh code, since I don't suppose anybody ever thought about it before. The following should make it consistent. It also keeps it consistent with % ksh -fec 'false || { false; print two; false; }; print three' where you don't get the message `two' because in this case the shell exits at the first `false' on the right. The rule seems to be `never exit on a non-zero status left of a || or &&, always exit on the extreme right', because you also get % ksh -fec 'false && true; print yes' yes where zsh was already consistent with ksh. --- Src/exec.c.ee Tue May 18 11:25:25 1999 +++ Src/exec.c Wed May 19 11:22:10 1999 @@ -697,6 +697,13 @@ static int donetrap; int ret, cj; int old_pline_level, old_list_pipe; + /* + * ERREXIT only forces the shell to exit if the last command in a && + * or || fails. This is the case even if an earlier command is a + * shell function or other current shell structure, so we have to set + * noerrexit here if the sublist is not of type END. + */ + int oldnoerrexit = noerrexit; cj = thisjob; old_pline_level = pline_level; @@ -716,6 +723,8 @@ /* Loop through code followed by &&, ||, or end of sublist. */ while (slist) { + if (!oldnoerrexit) + noerrexit = (slist->type != END); switch (slist->type) { case END: /* End of sublist; just execute, ignoring status. */ @@ -758,6 +767,8 @@ slist = slist->right; } sublist_done: + + noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG]) dotrap(SIGDEBUG); -- Peter Stephenson Tel: +39 050 844536 WWW: http://www.ifh.de/~pws/ Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy