From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6985 invoked from network); 11 Jul 2009 16:40:17 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.5 Received: from new-brage.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.254.104) by ns1.primenet.com.au with SMTP; 11 Jul 2009 16:40:17 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 20155 invoked from network); 11 Jul 2009 16:40:04 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 11 Jul 2009 16:40:04 -0000 Received: (qmail 14720 invoked by alias); 11 Jul 2009 16:39:52 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 27129 Received: (qmail 14695 invoked from network); 11 Jul 2009 16:39:51 -0000 Received: from bifrost.dotsrc.org (130.225.254.106) by sunsite.dk with SMTP; 11 Jul 2009 16:39:51 -0000 Received: from mtaout01-winn.ispmail.ntl.com (mtaout01-winn.ispmail.ntl.com [81.103.221.47]) by bifrost.dotsrc.org (Postfix) with ESMTP id C16DC80307FA for ; Sat, 11 Jul 2009 18:39:47 +0200 (CEST) Received: from aamtaout02-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout01-winn.ispmail.ntl.com (InterMail vM.7.08.04.00 201-2186-134-20080326) with ESMTP id <20090711163947.EEAP6742.mtaout01-winn.ispmail.ntl.com@aamtaout02-winn.ispmail.ntl.com> for ; Sat, 11 Jul 2009 17:39:47 +0100 Received: from pws-pc ([81.107.42.185]) by aamtaout02-winn.ispmail.ntl.com (InterMail vG.2.02.00.01 201-2161-120-102-20060912) with ESMTP id <20090711163947.UQSB21638.aamtaout02-winn.ispmail.ntl.com@pws-pc> for ; Sat, 11 Jul 2009 17:39:47 +0100 Date: Sat, 11 Jul 2009 17:39:41 +0100 From: Peter Stephenson To: zsh-workers@sunsite.dk Subject: Re: bug: $? after empty command Message-ID: <20090711173941.18680254@pws-pc> In-Reply-To: <20090710230554.5760d429@pws-pc> References: <20090709154124.2cd2a227@news01> <20090710100228.783de399@news01> <20090710230554.5760d429@pws-pc> X-Mailer: Claws Mail 3.7.1 (GTK+ 2.16.2; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Cloudmark-Analysis: v=1.0 c=1 a=NLZqzBF-AAAA:8 a=4UtWO5riAAAA:8 a=9vXuR5GGAAAA:8 a=GPU_r4BuHECKGGKpALgA:9 a=jnMES6NAAaouOUxDqP8A:7 a=bXBtUBeTGqSN-yTqt91lWmlYaTsA:4 a=Mo27u2NpdeAA:10 a=_dQi-Dcv4p4A:10 a=Shd8Sdw-9eQA:10 a=eDFNAWYWrCwA:10 X-Virus-Scanned: ClamAV 0.94.2/9555/Sat Jul 11 10:31:19 2009 on bifrost X-Virus-Status: Clean On Fri, 10 Jul 2009 23:05:54 +0100 Peter Stephenson wrote: > On Fri, 10 Jul 2009 10:02:28 +0100 > Peter Stephenson wrote: > > On Thu, 9 Jul 2009 21:41:51 +0000 (UTC) > > Eric Blake wrote: > >> Eric Blake byu.net> writes: > >>> $ zsh -c 'false; . /dev/null; echo $?' > >>> 1 > >>> $ zsh -c 'false; ``; echo $?' > >>> 1 > >> $ zsh -c 'false; sleep& echo $?' > >> 1 > > > > "fn() { }" is valid, and I suspect "fn" > > logically ought to reset the status, too > > These four were all fairly easy; in each case there is a local context > where the command in question is being executed in which the status can > be reset. There may be a a more generic place, such as execlist(), for > these to go, but I like the transparency of resetting them locally; > execlist()/execode() are used in just too many places. Change of plan: I woke up in the night and realised that doing it this way breaks the case fn() { print $?; } false fn which is a bit strange but perfectly valid and should print "1". > However, that's a bit craven. This takes the brave option, but actually it's easy except for the case of "." which needs a bit more information from down below. For both executing a list and sourcing a file line by line we only reset the status if there is no code to execute. The case of starting a background function isn't affected, in that case the foreground code is always empty. Index: Src/exec.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/exec.c,v retrieving revision 1.167 diff -u -r1.167 exec.c --- Src/exec.c 10 Jul 2009 22:10:26 -0000 1.167 +++ Src/exec.c 11 Jul 2009 16:32:42 -0000 @@ -1056,6 +1056,10 @@ /* Loop over all sets of comands separated by newline, * * semi-colon or ampersand (`sublists'). */ code = *state->pc++; + if (wc_code(code) != WC_LIST) { + /* Empty list; this returns status zero. */ + lastval = 0; + } while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) { int donedebug; @@ -3513,7 +3517,6 @@ return retval; } /* pid == 0 */ - lastval = 0; /* status of empty list is zero */ child_unblock(); zclose(pipes[0]); redup(pipes[1], 1); @@ -4261,7 +4264,6 @@ if (trap_state == TRAP_STATE_PRIMED) trap_return--; oldlastval = lastval; - lastval = 0; /* status of empty function is zero */ oldnumpipestats = numpipestats; if (noreturnval) { /* Index: Src/init.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/init.c,v retrieving revision 1.104 diff -u -r1.104 init.c --- Src/init.c 10 Jul 2009 22:10:26 -0000 1.104 +++ Src/init.c 11 Jul 2009 16:32:42 -0000 @@ -99,11 +99,11 @@ /* keep executing lists until EOF found */ /**/ -int +enum loop_return loop(int toplevel, int justonce) { Eprog prog; - int err; + int err, non_empty = 0; pushheap(); if (!toplevel) @@ -151,6 +151,7 @@ if (hend(prog)) { int toksav = tok; + non_empty = 1; if (toplevel && (getshfunc("preexec") || paramtab->getnode(paramtab, "preexec" HOOK_SUFFIX))) { @@ -207,7 +208,11 @@ lexrestore(); popheap(); - return err; + if (err) + return LOOP_ERROR; + if (!non_empty) + return LOOP_EMPTY; + return LOOP_OK; } static char *cmd; @@ -1131,7 +1136,6 @@ fstack.tp = FS_SOURCE; funcstack = &fstack; - lastval = 0; /* status of empty file is zero */ if (prog) { pushheap(); errflag = 0; @@ -1141,8 +1145,21 @@ ret = SOURCE_ERROR; } else { /* loop through the file to be sourced */ - if (loop(0, 0)) + switch (loop(0, 0)) + { + case LOOP_OK: + /* nothing to do but compilers like a complete enum */ + break; + + case LOOP_EMPTY: + /* Empty code resets status */ + lastval = 0; + break; + + case LOOP_ERROR: ret = SOURCE_ERROR; + break; + } } funcstack = funcstack->prev; sourcelevel--; Index: Src/zsh.h =================================================================== RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v retrieving revision 1.159 diff -u -r1.159 zsh.h --- Src/zsh.h 10 Jul 2009 11:08:48 -0000 1.159 +++ Src/zsh.h 11 Jul 2009 16:32:43 -0000 @@ -1726,6 +1726,17 @@ #define PRINT_WHENCE_FUNCDEF (1<<9) #define PRINT_WHENCE_WORD (1<<10) +/* Return values from loop() */ + +enum loop_return { + /* Loop executed OK */ + LOOP_OK, + /* Loop executed no code */ + LOOP_EMPTY, + /* Loop encountered an error */ + LOOP_ERROR +}; + /* Return values from source() */ enum source_return { Index: Test/A01grammar.ztst =================================================================== RCS file: /cvsroot/zsh/zsh/Test/A01grammar.ztst,v retrieving revision 1.24 diff -u -r1.24 A01grammar.ztst --- Test/A01grammar.ztst 10 Jul 2009 22:10:27 -0000 1.24 +++ Test/A01grammar.ztst 11 Jul 2009 16:32:43 -0000 @@ -553,3 +553,9 @@ 0:Last status of successfully executed "." file is retained >1 >0 + + echo 'echo $?' >dot_status + false + . ./dot_status +0:"." file sees status from previous command +>1 Index: Test/C04funcdef.ztst =================================================================== RCS file: /cvsroot/zsh/zsh/Test/C04funcdef.ztst,v retrieving revision 1.6 diff -u -r1.6 C04funcdef.ztst --- Test/C04funcdef.ztst 10 Jul 2009 22:10:27 -0000 1.6 +++ Test/C04funcdef.ztst 11 Jul 2009 16:32:43 -0000 @@ -15,6 +15,13 @@ fnz 0:Empty function body resets status + fn3() { return 3; } + fnstat() { print $?; } + fn3 + fnstat +0:Status is not reset on non-empty function body +>3 + function f$$ () { print regress expansion of function names } Index: Test/D08cmdsubst.ztst =================================================================== RCS file: /cvsroot/zsh/zsh/Test/D08cmdsubst.ztst,v retrieving revision 1.3 diff -u -r1.3 D08cmdsubst.ztst --- Test/D08cmdsubst.ztst 10 Jul 2009 22:10:27 -0000 1.3 +++ Test/D08cmdsubst.ztst 11 Jul 2009 16:32:43 -0000 @@ -93,3 +93,8 @@ false `` 0:Empty command substitution resets status + + false + echo `echo $?` +0:Non-empty command substitution inherits status +>1 -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/