summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Doc/Zsh/builtins.yo5
-rw-r--r--Src/builtin.c14
-rw-r--r--Test/.distfiles1
-rw-r--r--Test/B05eval.ztst34
4 files changed, 47 insertions, 7 deletions
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index d7e3526cb..bcd03be98 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -382,7 +382,10 @@ findex(eval)
 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.
diff --git a/Src/builtin.c b/Src/builtin.c
index 99daf866b..e1378d901 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4717,17 +4717,19 @@ bin_eval(UNUSED(char *nam), char **argv, UNUSED(Options ops), UNUSED(int func))
 
     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;
diff --git a/Test/.distfiles b/Test/.distfiles
index d79079696..6fd78491b 100644
--- a/Test/.distfiles
+++ b/Test/.distfiles
@@ -11,6 +11,7 @@ B01cd.ztst
 B02typeset.ztst
 B03print.ztst
 B04read.ztst
+B05eval.ztst
 C01arith.ztst
 C02cond.ztst
 C03traps.ztst
diff --git a/Test/B05eval.ztst b/Test/B05eval.ztst
new file mode 100644
index 000000000..6427d6f2c
--- /dev/null
+++ b/Test/B05eval.ztst
@@ -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