From 60b51a3bda3f3fc220a2fa56de5f86c4bac35f2e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Tue, 24 Jan 2023 17:08:58 -0500 Subject: opt: Move always_{true,false} out of the parser --- src/opt.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/parse.c | 56 ++++++-------------------------------------------------- 2 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/opt.c b/src/opt.c index 934a4b4..c80d584 100644 --- a/src/opt.c +++ b/src/opt.c @@ -45,6 +45,7 @@ #include "ctx.h" #include "diag.h" #include "eval.h" +#include "exec.h" #include "expr.h" #include "pwcache.h" #include @@ -799,6 +800,15 @@ static struct bfs_expr *optimize_empty(struct opt_state *state, struct bfs_expr return expr; } +/** Optimize -{exec,ok}{,dir}. */ +static struct bfs_expr *optimize_exec(struct opt_state *state, struct bfs_expr *expr) { + if (expr->exec->flags & BFS_EXEC_MULTI) { + expr->always_true = true; + } + + return expr; +} + /** Optimize -gid. */ static struct bfs_expr *optimize_gid(struct opt_state *state, struct bfs_expr *expr) { struct range *range = &state->facts_when_true.ranges[GID_RANGE]; @@ -891,6 +901,34 @@ static bfs_eval_fn *const opt_pure[] = { eval_xattrname, }; +/** + * Table of always-true expressions. + */ +static bfs_eval_fn *const opt_always_true[] = { + eval_fls, + eval_fprint, + eval_fprint0, + eval_fprintf, + eval_fprintx, + eval_prune, + eval_true, + + // Non-returning + eval_exit, + eval_quit, +}; + +/** + * Table of always-false expressions. + */ +static bfs_eval_fn *const opt_always_false[] = { + eval_false, + + // Non-returning + eval_exit, + eval_quit, +}; + /** * Table of simple predicates. */ @@ -940,6 +978,7 @@ static const struct { // Primaries {eval_access, optimize_access}, {eval_empty, optimize_empty}, + {eval_exec, optimize_exec}, {eval_gid, optimize_gid}, {eval_samefile, optimize_samefile}, {eval_type, optimize_type}, @@ -964,6 +1003,20 @@ static struct bfs_expr *optimize_expr_lookup(struct opt_state *state, struct bfs } } + for (size_t i = 0; i < BFS_COUNTOF(opt_always_true); ++i) { + if (opt_always_true[i] == expr->eval_fn) { + expr->always_true = true; + break; + } + } + + for (size_t i = 0; i < BFS_COUNTOF(opt_always_false); ++i) { + if (opt_always_false[i] == expr->eval_fn) { + expr->always_false = true; + break; + } + } + for (size_t i = 0; i < BFS_COUNTOF(opt_preds); ++i) { if (opt_preds[i].eval_fn == expr->eval_fn) { infer_pred_facts(state, opt_preds[i].pred); @@ -1026,9 +1079,11 @@ static struct bfs_expr *optimize_expr_recursive(struct opt_state *state, struct } if (expr->always_true) { + expr->probability = 1.0; set_facts_impossible(&state->facts_when_false); } if (expr->always_false) { + expr->probability = 0.0; set_facts_impossible(&state->facts_when_true); } diff --git a/src/parse.c b/src/parse.c index 0b4224c..5766237 100644 --- a/src/parse.c +++ b/src/parse.c @@ -86,26 +86,15 @@ struct bfs_expr *bfs_expr_new(bfs_eval_fn *eval_fn, size_t argc, char **argv) { expr->persistent_fds = 0; expr->ephemeral_fds = 0; expr->pure = false; + expr->always_true = false; + expr->always_false = false; expr->cost = FAST_COST; + expr->probability = 0.5; expr->evaluations = 0; expr->successes = 0; expr->elapsed.tv_sec = 0; expr->elapsed.tv_nsec = 0; - if (eval_fn == eval_true) { - expr->always_true = true; - expr->always_false = false; - expr->probability = 1.0; - } else if (eval_fn == eval_false) { - expr->always_true = false; - expr->always_false = true; - expr->probability = 0.0; - } else { - expr->always_true = false; - expr->always_false = false; - expr->probability = 0.5; - } - // Prevent bfs_expr_free() from freeing uninitialized pointers on error paths if (bfs_expr_is_parent(expr)) { expr->lhs = NULL; @@ -196,21 +185,6 @@ static struct bfs_expr *new_binary_expr(bfs_eval_fn *eval_fn, struct bfs_expr *l return expr; } -/** - * Set an expression to always return true. - */ -static void expr_set_always_true(struct bfs_expr *expr) { - expr->always_true = true; - expr->probability = 1.0; -} - -/** - * Set an expression to never return. - */ -static void expr_set_never_returns(struct bfs_expr *expr) { - expr->always_true = expr->always_false = true; -} - /** * Color use flags. */ @@ -462,7 +436,6 @@ static bool parse_expr_warning(const struct parser_state *state, const struct bf * Fill in a "-print"-type expression. */ static void init_print_expr(struct parser_state *state, struct bfs_expr *expr) { - expr_set_always_true(expr); expr->cost = PRINT_COST; expr->cfile = state->ctx->cout; expr->path = NULL; @@ -1359,9 +1332,7 @@ static struct bfs_expr *parse_exec(struct parser_state *state, int flags, int ar expr->exec = execbuf; - if (execbuf->flags & BFS_EXEC_MULTI) { - expr_set_always_true(expr); - } else { + if (!(execbuf->flags & BFS_EXEC_MULTI)) { expr->cost = 1000000.0; } @@ -1395,7 +1366,6 @@ static struct bfs_expr *parse_exit(struct parser_state *state, int arg1, int arg struct bfs_expr *expr = parse_action(state, eval_exit, argc); if (expr) { - expr_set_never_returns(expr); expr->num = status; } return expr; @@ -1525,7 +1495,6 @@ static struct bfs_expr *parse_fls(struct parser_state *state, int arg1, int arg2 goto fail; } - expr_set_always_true(expr); expr->cost = PRINT_COST; return expr; @@ -1540,7 +1509,6 @@ fail: static struct bfs_expr *parse_fprint(struct parser_state *state, int arg1, int arg2) { struct bfs_expr *expr = parse_unary_action(state, eval_fprint); if (expr) { - expr_set_always_true(expr); expr->cost = PRINT_COST; if (expr_open(state, expr, expr->argv[1]) != 0) { goto fail; @@ -1559,7 +1527,6 @@ fail: static struct bfs_expr *parse_fprint0(struct parser_state *state, int arg1, int arg2) { struct bfs_expr *expr = parse_unary_action(state, eval_fprint0); if (expr) { - expr_set_always_true(expr); expr->cost = PRINT_COST; if (expr_open(state, expr, expr->argv[1]) != 0) { goto fail; @@ -1595,8 +1562,6 @@ static struct bfs_expr *parse_fprintf(struct parser_state *state, int arg1, int return NULL; } - expr_set_always_true(expr); - expr->cost = PRINT_COST; if (expr_open(state, expr, file) != 0) { @@ -2373,23 +2338,14 @@ static struct bfs_expr *parse_printx(struct parser_state *state, int arg1, int a */ static struct bfs_expr *parse_prune(struct parser_state *state, int arg1, int arg2) { state->prune_arg = state->argv; - - struct bfs_expr *expr = parse_nullary_action(state, eval_prune); - if (expr) { - expr_set_always_true(expr); - } - return expr; + return parse_nullary_action(state, eval_prune); } /** * Parse -quit. */ static struct bfs_expr *parse_quit(struct parser_state *state, int arg1, int arg2) { - struct bfs_expr *expr = parse_nullary_action(state, eval_quit); - if (expr) { - expr_set_never_returns(expr); - } - return expr; + return parse_nullary_action(state, eval_quit); } /** -- cgit v1.2.3