Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: bug: $? after empty command
- X-seq: zsh-workers 27106
- From: Peter Stephenson <pws@xxxxxxx>
- To: zsh-workers@xxxxxxxxxx
- Subject: Re: bug: $? after empty command
- Date: Thu, 9 Jul 2009 15:41:24 +0100
- In-reply-to: <loom.20090709T130223-845@xxxxxxxxxxxxxx>
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
- Organization: CSR
- References: <loom.20090709T130223-845@xxxxxxxxxxxxxx>
On Thu, 9 Jul 2009 13:12:20 +0000 (UTC)
Eric Blake <ebb9@xxxxxxx> wrote:
> POSIX requires that the execution of an empty command change $? to 0, as shown
> here with bash:
>
> $ zsh -c 'foo=; false; $foo; echo $?'
> 1
I'm not aware that that's deliberate shell behaviour, and indeed I
wouldn't have expected it. It *is* deliberate behaviour that the status is
not reset simply by hitting return at the interactive prompt, but that's
actually a different issue, not affected by the following.
The fix for this is quite subtle because of the case
zsh -c 'false; $(exit 3); echo $?'
which should print 3, but I think I've finally found a way that handles
both.
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.165
diff -u -r1.165 exec.c
--- Src/exec.c 15 Mar 2009 01:04:50 -0000 1.165
+++ Src/exec.c 9 Jul 2009 14:38:41 -0000
@@ -151,6 +151,15 @@
/**/
int cmdoutval;
+/*
+ * This is set by an exiting $(...) substitution to indicate we need
+ * to retain the status. We initialize it to zero if we think we need
+ * to reset the status for a command.
+ */
+
+/**/
+int use_cmdoutval;
+
/* The context in which a shell function is called, see SFC_* in zsh.h. */
/**/
@@ -2262,6 +2271,14 @@
*/
if (!args && varspc)
lastval = errflag ? errflag : cmdoutval;
+ /*
+ * If there are arguments, we should reset the status for the
+ * command before execution---unless we are using the result of a
+ * command substitution, which will be indicated by setting
+ * use_cmdoutval to 1. We haven't kicked those off yet, so
+ * there's no race.
+ */
+ use_cmdoutval = !args;
for (i = 0; i < 10; i++) {
save[i] = -2;
@@ -2478,7 +2495,12 @@
lastval = 0;
return;
} else {
- cmdoutval = lastval;
+ /*
+ * No arguments. Reset the status if there were
+ * arguments before and no command substitution
+ * has provided a status.
+ */
+ cmdoutval = use_cmdoutval ? lastval : 0;
if (varspc)
addvars(state, varspc, 0);
if (errflag)
@@ -4674,6 +4696,7 @@
es->badcshglob = badcshglob;
es->cmdoutpid = cmdoutpid;
es->cmdoutval = cmdoutval;
+ es->use_cmdoutval = use_cmdoutval;
es->trap_return = trap_return;
es->trap_state = trap_state;
es->trapisfunc = trapisfunc;
@@ -4704,6 +4727,7 @@
badcshglob = exstack->badcshglob;
cmdoutpid = exstack->cmdoutpid;
cmdoutval = exstack->cmdoutval;
+ use_cmdoutval = exstack->use_cmdoutval;
trap_return = exstack->trap_return;
trap_state = exstack->trap_state;
trapisfunc = exstack->trapisfunc;
Index: Src/signals.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/signals.c,v
retrieving revision 1.54
diff -u -r1.54 signals.c
--- Src/signals.c 11 Feb 2009 20:42:16 -0000 1.54
+++ Src/signals.c 9 Jul 2009 14:38:41 -0000
@@ -494,6 +494,7 @@
*procsubval = (0200 | WTERMSIG(status));
else
*procsubval = WEXITSTATUS(status);
+ use_cmdoutval = 1;
get_usage();
cont = 1;
break;
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.158
diff -u -r1.158 zsh.h
--- Src/zsh.h 2 Jul 2009 13:48:36 -0000 1.158
+++ Src/zsh.h 9 Jul 2009 14:38:41 -0000
@@ -930,6 +930,7 @@
int badcshglob;
pid_t cmdoutpid;
int cmdoutval;
+ int use_cmdoutval;
int trap_return;
int trap_state;
int trapisfunc;
Index: Test/A01grammar.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/A01grammar.ztst,v
retrieving revision 1.22
diff -u -r1.22 A01grammar.ztst
--- Test/A01grammar.ztst 6 Jul 2009 20:44:29 -0000 1.22
+++ Test/A01grammar.ztst 9 Jul 2009 14:38:41 -0000
@@ -23,6 +23,10 @@
true | false
1:Exit status of pipeline with builtins (false)
+ false
+ $nonexistent_variable
+0:Executing command that evaluates to empty resets status
+
fn() { local foo; read foo; print $foo; }
coproc fn
print -p coproc test output
--
Peter Stephenson <pws@xxxxxxx> Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK Tel: +44 (0)1223 692070
Messages sorted by:
Reverse Date,
Date,
Thread,
Author