From 9e2365ed14a1f771b25897e48ec755dd06c3673a Mon Sep 17 00:00:00 2001 From: Jack Conger Date: Mon, 25 May 2026 06:12:23 -0700 Subject: [PATCH] Do not exit from `es -e' due to assignments When assignments were made to return values, this caused any shell running with the `-e' flag to exit whenever an assignment was performed. This makes the `-e' flag effectively unusable. --- doc/es.1 | 8 ++++---- eval.c | 5 ++++- test/tests/option.es | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/doc/es.1 b/doc/es.1 index b8c5674b..e87d5e1c 100644 --- a/doc/es.1 +++ b/doc/es.1 @@ -2388,8 +2388,8 @@ shell scripts if the kernel does not. .TP .Cr "%exit-on-false \fIcmd\fP" Runs the command, and exits if any command -(except those executing as the tests of conditional statements) -returns a non-zero status. +(except assignments, or those executing as the tests of conditional +statements) returns a non-zero status. (This function is used in the definition of .Cr %dispatch when the shell is invoked with the @@ -2901,8 +2901,8 @@ starts with a dash .Rc ( - ). .TP .Cr \-e -Exit if any command (except those executing as the tests of -conditional statements) returns a non-zero status. +Exit if any command (except assignments, or those executing as the +tests of conditional statements) returns a non-zero status. .TP .Cr \-v Echo all input to standard error. diff --git a/eval.c b/eval.c index 015e4ffb..cbb44dc9 100644 --- a/eval.c +++ b/eval.c @@ -3,6 +3,7 @@ #include "es.h" unsigned long evaldepth = 0, maxevaldepth = MAXmaxevaldepth; +static Boolean did_assign = FALSE; static Noreturn failexec(char *file, List *args) { List *fn; @@ -76,6 +77,7 @@ static List *assign(Tree *varform, Tree *valueform0, Binding *binding0) { } RefEnd4(values, vars, binding, valueform); + did_assign = TRUE; RefReturn(result); } @@ -378,6 +380,7 @@ extern List *eval(List *list0, Binding *binding0, int flags) { return ltrue; } assert(list->term != NULL); + did_assign = FALSE; if ((cp = getclosure(list->term)) != NULL) { switch (cp->tree->kind) { @@ -478,7 +481,7 @@ extern List *eval(List *list0, Binding *binding0, int flags) { done: --evaldepth; - if ((flags & eval_exitonfalse) && !istrue(list)) + if ((flags & eval_exitonfalse) && !istrue(list) && !did_assign) esexit(exitstatus(list)); RefEnd2(funcname, binding); RefReturn(list); diff --git a/test/tests/option.es b/test/tests/option.es index 600b172d..5e58522b 100644 --- a/test/tests/option.es +++ b/test/tests/option.es @@ -20,9 +20,9 @@ test 'es -e' { '{true; {true; {false; true}}}' false # assignments - 'x = false' false - 'fn x {false}' false - '{true; {true; {x = false}; true}}' false + 'x = false' true + 'fn x {false}' true + '{true; {true; {x = false}; true}}' true 'let (x = false) true' true 'local (x = false) true' true )) {