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

Re: eval and resetting $? (Was Re: trap DEBUG + set -o DEBUG_BEFORE_CMD not setting $? nonzero in current CVS)



On Mon, 4 Aug 2008 21:33:16 -0400
"Rocky Bernstein" <rocky.bernstein@xxxxxxxxx> wrote:
> However when I use it I run into something else that looks like either
> a bug or at least something whose behavior should be documented. In
> the following program it feels like $? gets changed/reset? before eval
> is run:
> 
> #!/usr/local/bin/zsh -f
> cmd='print $?'
> fdsafsdsfa # Invalid command
> eval $cmd  # print $? works and so does
>                   # ./file-containing: print $?
> 
> print $? works because $? is expanded before print is run. And
> sourcing a file which contains the string I want to eval also works,
> so this gives me a workaround for this problem.
> 
> But somehow I think that a string writing that to a file and sourcing
> it should be equivalent to eval'ing the string.

I think you're right, and it would confuse me, too.  Although this is
explicit behaviour of the eval builtin, it's not tested in the test
suite, and as well as not being documented it's not standard shell
behaviour, so it's probably a bug.  I think nobody's happened
to look at the current status in the first command of an eval
before---if they had, it's hard to see them thinking "great! the status
has been reset! all's well with the world!"

It might be here to ensure that an eval with empty code sets the status
to zero; in many (all?) shells, eval of an empty string or anything
syntactically equivalent resets the status.  We don't want to change
that.  Luckily, the test for that is easy, and unambiguous---if you
follow through execution as far as execlist() you'll see that any time
the test I've added to eval is false, there's shell code to execute.

Index: Doc/Zsh/builtins.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/builtins.yo,v
retrieving revision 1.108
diff -u -r1.108 builtins.yo
--- Doc/Zsh/builtins.yo	10 Jun 2008 08:50:36 -0000	1.108
+++ Doc/Zsh/builtins.yo	6 Aug 2008 19:28:23 -0000
@@ -382,7 +382,10 @@
 cindex(evaluating arguments as commands)
 item(tt(eval) [ var(arg) ... ])(
 Read the arguments as input to the shell and execute the resulting
-command in the current shell process.
+command(s) in the current shell process.  The return status is the
+same as if the commands had been executed directly by the shell;
+if there are no var(args) or they contain no commands (i.e. are
+an empty string or whitespace) the return status is zero.
 )
 item(tt(exec) [ tt(-cl) ] [ tt(-a) var(argv0) ] var(simple command))(
 Replace the current shell with an external command rather than forking.
Index: Src/builtin.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/builtin.c,v
retrieving revision 1.200
diff -u -r1.200 builtin.c
--- Src/builtin.c	31 Jul 2008 08:44:20 -0000	1.200
+++ Src/builtin.c	6 Aug 2008 19:28:24 -0000
@@ -4717,17 +4717,19 @@
 
     prog = parse_string(zjoin(argv, ' ', 1));
     if (prog) {
-	lastval = 0;
-
-	execode(prog, 1, 0);
+	if (wc_code(*prog->prog) != WC_LIST) {
+	    /* No code to execute */
+	    lastval = 0;
+	} else {
+	    execode(prog, 1, 0);
 
-	if (errflag)
-	    lastval = errflag;
+	    if (errflag)
+		lastval = errflag;
+	}
     } else {
 	lastval = 1;
     }
 
-
     errflag = 0;
     scriptname = oscriptname;
     ineval = oineval;
Index: Test/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/.distfiles,v
retrieving revision 1.20
diff -u -r1.20 .distfiles
--- Test/.distfiles	18 Dec 2007 21:16:30 -0000	1.20
+++ Test/.distfiles	6 Aug 2008 19:28:24 -0000
@@ -11,6 +11,7 @@
 B02typeset.ztst
 B03print.ztst
 B04read.ztst
+B05eval.ztst
 C01arith.ztst
 C02cond.ztst
 C03traps.ztst
Index: Test/B05eval.ztst
===================================================================
RCS file: Test/B05eval.ztst
diff -N Test/B05eval.ztst
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Test/B05eval.ztst	6 Aug 2008 19:28:24 -0000
@@ -0,0 +1,34 @@
+# Tests for the eval builtin.
+# This is quite short; eval is widely tested throughout the test suite
+# and its basic behaviour is fairly straightforward.
+
+%prep
+
+  cmd='print $?'
+
+%test
+
+  false
+  eval $cmd
+0:eval retains value of $?
+>1
+
+  # no point getting worked up over what the error message is...
+  ./command_not_found 2>/dev/null
+  eval $cmd
+0:eval after command not found
+>127
+
+  # trick the test system
+  sp=
+  false
+  eval "
+  $sp
+  $sp
+  $sp
+  "
+0:eval with empty command resets the status
+
+  false
+  eval
+0:eval with empty command resets the status

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