summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--eval.c34
-rwxr-xr-xtests.sh12
-rw-r--r--tests/test_0139.out1
-rw-r--r--tests/test_0140.out0
4 files changed, 43 insertions, 4 deletions
diff --git a/eval.c b/eval.c
index f24c7c4..7ca9aa8 100644
--- a/eval.c
+++ b/eval.c
@@ -38,6 +38,8 @@ struct eval_state {
enum bftw_action action;
/** The eval_cmdline() return value. */
int *ret;
+ /** Whether to quit immediately. */
+ bool *quit;
/** A stat() buffer, if necessary. */
struct stat statbuf;
};
@@ -777,6 +779,7 @@ bool eval_prune(const struct expr *expr, struct eval_state *state) {
*/
bool eval_quit(const struct expr *expr, struct eval_state *state) {
state->action = BFTW_STOP;
+ *state->quit = true;
return true;
}
@@ -1005,14 +1008,30 @@ bool eval_not(const struct expr *expr, struct eval_state *state) {
* Evaluate a conjunction.
*/
bool eval_and(const struct expr *expr, struct eval_state *state) {
- return eval_expr(expr->lhs, state) && eval_expr(expr->rhs, state);
+ if (!eval_expr(expr->lhs, state)) {
+ return false;
+ }
+
+ if (*state->quit) {
+ return false;
+ }
+
+ return eval_expr(expr->rhs, state);
}
/**
* Evaluate a disjunction.
*/
bool eval_or(const struct expr *expr, struct eval_state *state) {
- return eval_expr(expr->lhs, state) || eval_expr(expr->rhs, state);
+ if (eval_expr(expr->lhs, state)) {
+ return true;
+ }
+
+ if (*state->quit) {
+ return false;
+ }
+
+ return eval_expr(expr->rhs, state);
}
/**
@@ -1020,6 +1039,11 @@ bool eval_or(const struct expr *expr, struct eval_state *state) {
*/
bool eval_comma(const struct expr *expr, struct eval_state *state) {
eval_expr(expr->lhs, state);
+
+ if (*state->quit) {
+ return false;
+ }
+
return eval_expr(expr->rhs, state);
}
@@ -1058,6 +1082,8 @@ struct callback_args {
const struct cmdline *cmdline;
/** Eventual return value from eval_cmdline(). */
int ret;
+ /** Whether to quit immediately. */
+ bool quit;
};
/**
@@ -1073,6 +1099,7 @@ static enum bftw_action cmdline_callback(struct BFTW *ftwbuf, void *ptr) {
.cmdline = cmdline,
.action = BFTW_CONTINUE,
.ret = &args->ret,
+ .quit = &args->quit,
};
if (ftwbuf->typeflag == BFTW_ERROR) {
@@ -1178,9 +1205,10 @@ int eval_cmdline(const struct cmdline *cmdline) {
struct callback_args args = {
.cmdline = cmdline,
.ret = 0,
+ .quit = false,
};
- for (struct root *root = cmdline->roots; root; root = root->next) {
+ for (struct root *root = cmdline->roots; root && !args.quit; root = root->next) {
if (bftw(root->path, cmdline_callback, nopenfd, cmdline->flags, &args) != 0) {
args.ret = -1;
perror("bftw()");
diff --git a/tests.sh b/tests.sh
index 001fea4..d83f824 100755
--- a/tests.sh
+++ b/tests.sh
@@ -841,9 +841,19 @@ function test_0138() {
bfs_diff basic/g -depth -name g
}
+function test_0139() {
+ [ "$BSD" -o "$GNU" ] || return 0
+ bfs_diff basic basic -print -quit
+}
+
+function test_0140() {
+ [ "$BSD" -o "$GNU" ] || return 0
+ bfs_diff basic basic -quit -print
+}
+
result=0
-for i in {1..138}; do
+for i in {1..140}; do
test="test_$(printf '%04d' $i)"
if [ -t 1 ]; then
diff --git a/tests/test_0139.out b/tests/test_0139.out
new file mode 100644
index 0000000..15a13db
--- /dev/null
+++ b/tests/test_0139.out
@@ -0,0 +1 @@
+basic
diff --git a/tests/test_0140.out b/tests/test_0140.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/test_0140.out