From 78ebbfe2ce56d5504cbee0883c747fb427279653 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 5 Feb 2017 17:29:12 -0500 Subject: Make -quit happen immediately, not at the end of the current expression --- eval.c | 34 +++++++++++++++++++++++++++++++--- tests.sh | 12 +++++++++++- tests/test_0139.out | 1 + tests/test_0140.out | 0 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 tests/test_0139.out create mode 100644 tests/test_0140.out 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 -- cgit v1.2.3