summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-12-20 20:18:35 -0500
committerTavian Barnes <tavianator@tavianator.com>2023-12-20 20:37:44 -0500
commit70092ae5c8f83a99fbc98dc8e2ca2eaab676a5a8 (patch)
tree3c1ff27c143258cdaa4218972b2960ef4653212a
parent9c6e4ce18304c395338c7c5b2bac9eb89583a568 (diff)
downloadbfs-70092ae5c8f83a99fbc98dc8e2ca2eaab676a5a8.tar.xz
expr: Arena-allocate expressions
-rw-r--r--src/ctx.c11
-rw-r--r--src/ctx.h6
-rw-r--r--src/expr.c22
-rw-r--r--src/expr.h19
-rw-r--r--src/opt.c113
-rw-r--r--src/parse.c340
6 files changed, 210 insertions, 301 deletions
diff --git a/src/ctx.c b/src/ctx.c
index f5dc465..a3c5140 100644
--- a/src/ctx.c
+++ b/src/ctx.c
@@ -22,6 +22,9 @@ struct bfs_ctx *bfs_ctx_new(void) {
return NULL;
}
+ SLIST_INIT(&ctx->expr_list);
+ ARENA_INIT(&ctx->expr_arena, struct bfs_expr);
+
ctx->maxdepth = INT_MAX;
ctx->flags = BFTW_RECOVER;
ctx->strategy = BFTW_BFS;
@@ -202,9 +205,6 @@ int bfs_ctx_free(struct bfs_ctx *ctx) {
CFILE *cout = ctx->cout;
CFILE *cerr = ctx->cerr;
- bfs_expr_free(ctx->exclude);
- bfs_expr_free(ctx->expr);
-
bfs_mtab_free(ctx->mtab);
bfs_groups_free(ctx->groups);
@@ -241,6 +241,11 @@ int bfs_ctx_free(struct bfs_ctx *ctx) {
free_colors(ctx->colors);
+ for_slist (struct bfs_expr, expr, &ctx->expr_list) {
+ bfs_expr_clear(expr);
+ }
+ arena_destroy(&ctx->expr_arena);
+
for (size_t i = 0; i < ctx->npaths; ++i) {
free((char *)ctx->paths[i]);
}
diff --git a/src/ctx.h b/src/ctx.h
index 75891da..aa91f2c 100644
--- a/src/ctx.h
+++ b/src/ctx.h
@@ -8,9 +8,11 @@
#ifndef BFS_CTX_H
#define BFS_CTX_H
+#include "alloc.h"
#include "bftw.h"
#include "config.h"
#include "diag.h"
+#include "expr.h"
#include "trie.h"
#include <stddef.h>
#include <sys/resource.h>
@@ -34,6 +36,10 @@ struct bfs_ctx {
struct bfs_expr *expr;
/** An expression for files to filter out. */
struct bfs_expr *exclude;
+ /** A list of allocated expressions. */
+ struct bfs_exprs expr_list;
+ /** bfs_expr arena. */
+ struct arena expr_arena;
/** -mindepth option. */
int mindepth;
diff --git a/src/expr.c b/src/expr.c
index 380038c..2002fc7 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -3,24 +3,27 @@
#include "expr.h"
#include "alloc.h"
+#include "ctx.h"
#include "eval.h"
#include "exec.h"
#include "printf.h"
#include "xregex.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
-struct bfs_expr *bfs_expr_new(bfs_eval_fn *eval_fn, size_t argc, char **argv) {
- struct bfs_expr *expr = ZALLOC(struct bfs_expr);
+struct bfs_expr *bfs_expr_new(struct bfs_ctx *ctx, bfs_eval_fn *eval_fn, size_t argc, char **argv) {
+ struct bfs_expr *expr = arena_alloc(&ctx->expr_arena);
if (!expr) {
- perror("zalloc()");
return NULL;
}
+ memset(expr, 0, sizeof(*expr));
expr->eval_fn = eval_fn;
expr->argc = argc;
expr->argv = argv;
expr->probability = 0.5;
+ SLIST_PREPEND(&ctx->expr_list, expr);
return expr;
}
@@ -36,21 +39,12 @@ bool bfs_expr_never_returns(const struct bfs_expr *expr) {
return expr->always_true && expr->always_false;
}
-void bfs_expr_free(struct bfs_expr *expr) {
- if (!expr) {
- return;
- }
-
- if (bfs_expr_is_parent(expr)) {
- bfs_expr_free(expr->rhs);
- bfs_expr_free(expr->lhs);
- } else if (expr->eval_fn == eval_exec) {
+void bfs_expr_clear(struct bfs_expr *expr) {
+ if (expr->eval_fn == eval_exec) {
bfs_exec_free(expr->exec);
} else if (expr->eval_fn == eval_fprintf) {
bfs_printf_free(expr->printf);
} else if (expr->eval_fn == eval_regex) {
bfs_regfree(expr->regex);
}
-
- free(expr);
}
diff --git a/src/expr.h b/src/expr.h
index 95118b9..290f1f8 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -75,9 +75,20 @@ enum bfs_size_unit {
};
/**
+ * A linked list of expressions.
+ */
+struct bfs_exprs {
+ struct bfs_expr *head;
+ struct bfs_expr **tail;
+};
+
+/**
* A command line expression.
*/
struct bfs_expr {
+ /** The next allocated expression. */
+ struct bfs_expr *next;
+
/** The function that evaluates this expression. */
bfs_eval_fn *eval_fn;
@@ -199,10 +210,12 @@ struct bfs_expr {
};
};
+struct bfs_ctx;
+
/**
* Create a new expression.
*/
-struct bfs_expr *bfs_expr_new(bfs_eval_fn *eval, size_t argc, char **argv);
+struct bfs_expr *bfs_expr_new(struct bfs_ctx *ctx, bfs_eval_fn *eval, size_t argc, char **argv);
/**
* @return Whether the expression has child expressions.
@@ -220,8 +233,8 @@ bool bfs_expr_never_returns(const struct bfs_expr *expr);
bool bfs_expr_cmp(const struct bfs_expr *expr, long long n);
/**
- * Free an expression tree.
+ * Free any resources owned by an expression.
*/
-void bfs_expr_free(struct bfs_expr *expr);
+void bfs_expr_clear(struct bfs_expr *expr);
#endif // BFS_EXPR_H
diff --git a/src/opt.c b/src/opt.c
index a989670..1dc985a 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -284,7 +284,7 @@ static void df_join(struct df_domain *dest, const struct df_domain *src) {
*/
struct bfs_opt {
/** The context we're optimizing. */
- const struct bfs_ctx *ctx;
+ struct bfs_ctx *ctx;
/** Data flow state before this expression is evaluated. */
struct df_domain before;
@@ -330,31 +330,22 @@ static void opt_warning(const struct bfs_opt *opt, const struct bfs_expr *expr,
}
/** Create a constant expression. */
-static struct bfs_expr *opt_const(bool value) {
+static struct bfs_expr *opt_const(const struct bfs_opt *opt, bool value) {
static bfs_eval_fn *fns[] = {eval_false, eval_true};
static char *fake_args[] = {"-false", "-true"};
- return bfs_expr_new(fns[value], 1, &fake_args[value]);
-}
-
-/** Extract a child expression, freeing the outer expression. */
-static struct bfs_expr *extract_child_expr(struct bfs_expr *expr, struct bfs_expr **child) {
- struct bfs_expr *ret = *child;
- *child = NULL;
- bfs_expr_free(expr);
- return ret;
+ return bfs_expr_new(opt->ctx, fns[value], 1, &fake_args[value]);
}
/**
* Negate an expression.
*/
-static struct bfs_expr *negate_expr(struct bfs_expr *rhs, char **argv) {
+static struct bfs_expr *negate_expr(const struct bfs_opt *opt, struct bfs_expr *rhs, char **argv) {
if (rhs->eval_fn == eval_not) {
- return extract_child_expr(rhs, &rhs->rhs);
+ return rhs->rhs;
}
- struct bfs_expr *expr = bfs_expr_new(eval_not, 1, argv);
+ struct bfs_expr *expr = bfs_expr_new(opt->ctx, eval_not, 1, argv);
if (!expr) {
- bfs_expr_free(rhs);
return NULL;
}
@@ -373,7 +364,7 @@ static struct bfs_expr *optimize_or_expr(const struct bfs_opt *opt, struct bfs_e
static struct bfs_expr *de_morgan(const struct bfs_opt *opt, struct bfs_expr *expr, char **argv) {
bool debug = opt_debug(opt, 1, "De Morgan's laws: %pe ", expr);
- struct bfs_expr *parent = negate_expr(expr, argv);
+ struct bfs_expr *parent = negate_expr(opt, expr, argv);
if (!parent) {
return NULL;
}
@@ -393,10 +384,9 @@ static struct bfs_expr *de_morgan(const struct bfs_opt *opt, struct bfs_expr *ex
expr->argv = &fake_and_arg;
}
- expr->lhs = negate_expr(expr->lhs, argv);
- expr->rhs = negate_expr(expr->rhs, argv);
+ expr->lhs = negate_expr(opt, expr->lhs, argv);
+ expr->rhs = negate_expr(opt, expr->rhs, argv);
if (!expr->lhs || !expr->rhs) {
- bfs_expr_free(parent);
return NULL;
}
@@ -411,7 +401,6 @@ static struct bfs_expr *de_morgan(const struct bfs_opt *opt, struct bfs_expr *ex
expr->rhs = optimize_not_expr(opt, expr->rhs);
}
if (!expr->lhs || !expr->rhs) {
- bfs_expr_free(parent);
return NULL;
}
@@ -426,7 +415,6 @@ static struct bfs_expr *de_morgan(const struct bfs_opt *opt, struct bfs_expr *ex
parent = expr;
}
if (!expr) {
- bfs_expr_free(parent);
return NULL;
}
@@ -450,16 +438,15 @@ static struct bfs_expr *optimize_not_expr(const struct bfs_opt *opt, struct bfs_
int optlevel = opt->ctx->optlevel;
if (optlevel >= 1) {
if (rhs->eval_fn == eval_true || rhs->eval_fn == eval_false) {
- struct bfs_expr *ret = opt_const(rhs->eval_fn == eval_false);
+ struct bfs_expr *ret = opt_const(opt, rhs->eval_fn == eval_false);
opt_debug(opt, 1, "constant propagation: %pe <==> %pe\n", expr, ret);
- bfs_expr_free(expr);
return ret;
} else if (rhs->eval_fn == eval_not) {
opt_debug(opt, 1, "double negation: %pe <==> %pe\n", expr, rhs->rhs);
- return extract_child_expr(expr, &rhs->rhs);
+ return rhs->rhs;
} else if (bfs_expr_never_returns(rhs)) {
opt_debug(opt, 1, "reachability: %pe <==> %pe\n", expr, rhs);
- return extract_child_expr(expr, &expr->rhs);
+ return expr->rhs;
} else if ((rhs->eval_fn == eval_and || rhs->eval_fn == eval_or)
&& (rhs->lhs->eval_fn == eval_not || rhs->rhs->eval_fn == eval_not)) {
return de_morgan(opt, expr, expr->argv);
@@ -480,17 +467,13 @@ static struct bfs_expr *optimize_not_expr_recursive(struct bfs_opt *opt, struct
struct bfs_opt rhs_state = *opt;
expr->rhs = optimize_expr_recursive(&rhs_state, expr->rhs);
if (!expr->rhs) {
- goto fail;
+ return NULL;
}
opt->after_true = rhs_state.after_false;
opt->after_false = rhs_state.after_true;
return optimize_not_expr(opt, expr);
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/** Optimize a conjunction. */
@@ -505,18 +488,18 @@ static struct bfs_expr *optimize_and_expr(const struct bfs_opt *opt, struct bfs_
if (optlevel >= 1) {
if (lhs->eval_fn == eval_true) {
opt_debug(opt, 1, "conjunction elimination: %pe <==> %pe\n", expr, rhs);
- return extract_child_expr(expr, &expr->rhs);
+ return expr->rhs;
} else if (rhs->eval_fn == eval_true) {
opt_debug(opt, 1, "conjunction elimination: %pe <==> %pe\n", expr, lhs);
- return extract_child_expr(expr, &expr->lhs);
+ return expr->lhs;
} else if (lhs->always_false) {
opt_debug(opt, 1, "short-circuit: %pe <==> %pe\n", expr, lhs);
opt_warning(opt, expr->rhs, "This expression is unreachable.\n\n");
- return extract_child_expr(expr, &expr->lhs);
+ return expr->lhs;
} else if (lhs->always_true && rhs->eval_fn == eval_false) {
bool debug = opt_debug(opt, 1, "strength reduction: %pe <==> ", expr);
- struct bfs_expr *ret = extract_child_expr(expr, &expr->lhs);
- ret = negate_expr(ret, &fake_not_arg);
+ struct bfs_expr *ret = expr->lhs;
+ ret = negate_expr(opt, ret, &fake_not_arg);
if (debug && ret) {
cfprintf(ctx->cerr, "%pe\n", ret);
}
@@ -524,7 +507,7 @@ static struct bfs_expr *optimize_and_expr(const struct bfs_opt *opt, struct bfs_
} else if (optlevel >= 2 && lhs->pure && rhs->eval_fn == eval_false) {
opt_debug(opt, 2, "purity: %pe <==> %pe\n", expr, rhs);
opt_warning(opt, expr->lhs, "The result of this expression is ignored.\n\n");
- return extract_child_expr(expr, &expr->rhs);
+ return expr->rhs;
} else if (lhs->eval_fn == eval_not && rhs->eval_fn == eval_not) {
return de_morgan(opt, expr, expr->lhs->argv);
}
@@ -544,14 +527,14 @@ static struct bfs_expr *optimize_and_expr_recursive(struct bfs_opt *opt, struct
struct bfs_opt lhs_state = *opt;
expr->lhs = optimize_expr_recursive(&lhs_state, expr->lhs);
if (!expr->lhs) {
- goto fail;
+ return NULL;
}
struct bfs_opt rhs_state = *opt;
rhs_state.before = lhs_state.after_true;
expr->rhs = optimize_expr_recursive(&rhs_state, expr->rhs);
if (!expr->rhs) {
- goto fail;
+ return NULL;
}
opt->after_true = rhs_state.after_true;
@@ -559,10 +542,6 @@ static struct bfs_expr *optimize_and_expr_recursive(struct bfs_opt *opt, struct
df_join(&opt->after_false, &rhs_state.after_false);
return optimize_and_expr(opt, expr);
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/** Optimize a disjunction. */
@@ -578,17 +557,17 @@ static struct bfs_expr *optimize_or_expr(const struct bfs_opt *opt, struct bfs_e
if (lhs->always_true) {
opt_debug(opt, 1, "short-circuit: %pe <==> %pe\n", expr, lhs);
opt_warning(opt, expr->rhs, "This expression is unreachable.\n\n");
- return extract_child_expr(expr, &expr->lhs);
+ return expr->lhs;
} else if (lhs->eval_fn == eval_false) {
opt_debug(opt, 1, "disjunctive syllogism: %pe <==> %pe\n", expr, rhs);
- return extract_child_expr(expr, &expr->rhs);
+ return expr->rhs;
} else if (rhs->eval_fn == eval_false) {
opt_debug(opt, 1, "disjunctive syllogism: %pe <==> %pe\n", expr, lhs);
- return extract_child_expr(expr, &expr->lhs);
+ return expr->lhs;
} else if (lhs->always_false && rhs->eval_fn == eval_true) {
bool debug = opt_debug(opt, 1, "strength reduction: %pe <==> ", expr);
- struct bfs_expr *ret = extract_child_expr(expr, &expr->lhs);
- ret = negate_expr(ret, &fake_not_arg);
+ struct bfs_expr *ret = expr->lhs;
+ ret = negate_expr(opt, ret, &fake_not_arg);
if (debug && ret) {
cfprintf(ctx->cerr, "%pe\n", ret);
}
@@ -596,7 +575,7 @@ static struct bfs_expr *optimize_or_expr(const struct bfs_opt *opt, struct bfs_e
} else if (optlevel >= 2 && lhs->pure && rhs->eval_fn == eval_true) {
opt_debug(opt, 2, "purity: %pe <==> %pe\n", expr, rhs);
opt_warning(opt, expr->lhs, "The result of this expression is ignored.\n\n");
- return extract_child_expr(expr, &expr->rhs);
+ return expr->rhs;
} else if (lhs->eval_fn == eval_not && rhs->eval_fn == eval_not) {
return de_morgan(opt, expr, expr->lhs->argv);
}
@@ -616,14 +595,14 @@ static struct bfs_expr *optimize_or_expr_recursive(struct bfs_opt *opt, struct b
struct bfs_opt lhs_state = *opt;
expr->lhs = optimize_expr_recursive(&lhs_state, expr->lhs);
if (!expr->lhs) {
- goto fail;
+ return NULL;
}
struct bfs_opt rhs_state = *opt;
rhs_state.before = lhs_state.after_false;
expr->rhs = optimize_expr_recursive(&rhs_state, expr->rhs);
if (!expr->rhs) {
- goto fail;
+ return NULL;
}
opt->after_false = rhs_state.after_false;
@@ -631,10 +610,6 @@ static struct bfs_expr *optimize_or_expr_recursive(struct bfs_opt *opt, struct b
df_join(&opt->after_true, &rhs_state.after_true);
return optimize_or_expr(opt, expr);
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/** Optimize an expression in an ignored-result context. */
@@ -646,23 +621,22 @@ static struct bfs_expr *ignore_result(const struct bfs_opt *opt, struct bfs_expr
if (expr->eval_fn == eval_not) {
opt_debug(opt, 1, "ignored result: %pe --> %pe\n", expr, expr->rhs);
opt_warning(opt, expr, "The result of this expression is ignored.\n\n");
- expr = extract_child_expr(expr, &expr->rhs);
+ expr = expr->rhs;
} else if (optlevel >= 2
&& (expr->eval_fn == eval_and || expr->eval_fn == eval_or || expr->eval_fn == eval_comma)
&& expr->rhs->pure) {
opt_debug(opt, 2, "ignored result: %pe --> %pe\n", expr, expr->lhs);
opt_warning(opt, expr->rhs, "The result of this expression is ignored.\n\n");
- expr = extract_child_expr(expr, &expr->lhs);
+ expr = expr->lhs;
} else {
break;
}
}
if (optlevel >= 2 && expr->pure && expr->eval_fn != eval_false) {
- struct bfs_expr *ret = opt_const(false);
+ struct bfs_expr *ret = opt_const(opt, false);
opt_debug(opt, 2, "ignored result: %pe --> %pe\n", expr, ret);
opt_warning(opt, expr, "The result of this expression is ignored.\n\n");
- bfs_expr_free(expr);
return ret;
}
}
@@ -684,15 +658,15 @@ static struct bfs_expr *optimize_comma_expr(const struct bfs_opt *opt, struct bf
if (bfs_expr_never_returns(lhs)) {
opt_debug(opt, 1, "reachability: %pe <==> %pe\n", expr, lhs);
opt_warning(opt, expr->rhs, "This expression is unreachable.\n\n");
- return extract_child_expr(expr, &expr->lhs);
+ return expr->lhs;
} else if ((lhs->always_true && rhs->eval_fn == eval_true)
|| (lhs->always_false && rhs->eval_fn == eval_false)) {
opt_debug(opt, 1, "redundancy elimination: %pe <==> %pe\n", expr, lhs);
- return extract_child_expr(expr, &expr->lhs);
+ return expr->lhs;
} else if (optlevel >= 2 && lhs->pure) {
opt_debug(opt, 2, "purity: %pe <==> %pe\n", expr, rhs);
opt_warning(opt, expr->lhs, "The result of this expression is ignored.\n\n");
- return extract_child_expr(expr, &expr->rhs);
+ return expr->rhs;
}
}
@@ -710,7 +684,7 @@ static struct bfs_expr *optimize_comma_expr_recursive(struct bfs_opt *opt, struc
struct bfs_opt lhs_state = *opt;
expr->lhs = optimize_expr_recursive(&lhs_state, expr->lhs);
if (!expr->lhs) {
- goto fail;
+ return NULL;
}
struct bfs_opt rhs_state = *opt;
@@ -719,14 +693,10 @@ static struct bfs_expr *optimize_comma_expr_recursive(struct bfs_opt *opt, struc
expr->rhs = optimize_expr_recursive(&rhs_state, expr->rhs);
if (!expr->rhs) {
- goto fail;
+ return NULL;
}
return optimize_comma_expr(opt, expr);
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/** Optimize an icmp-style ([+-]N) expression. */
@@ -1213,10 +1183,9 @@ static struct bfs_expr *optimize_expr_recursive(struct bfs_opt *opt, struct bfs_
opt->after_false = opt->before;
if (optlevel >= 2 && df_is_bottom(&opt->before)) {
- struct bfs_expr *ret = opt_const(false);
+ struct bfs_expr *ret = opt_const(opt, false);
opt_debug(opt, 2, "reachability: %pe --> %pe\n", expr, ret);
opt_warning(opt, expr, "This expression is unreachable.\n\n");
- bfs_expr_free(expr);
return ret;
}
@@ -1257,10 +1226,9 @@ static struct bfs_expr *optimize_expr_recursive(struct bfs_opt *opt, struct bfs_
if (df_is_bottom(&opt->after_true)) {
if (expr->pure) {
- struct bfs_expr *ret = opt_const(false);
+ struct bfs_expr *ret = opt_const(opt, false);
opt_warning(opt, expr, "This expression is always false.\n\n");
opt_debug(opt, 2, "data flow: %pe --> %pe\n", expr, ret);
- bfs_expr_free(expr);
return ret;
} else {
expr->always_false = true;
@@ -1268,10 +1236,9 @@ static struct bfs_expr *optimize_expr_recursive(struct bfs_opt *opt, struct bfs_
}
} else if (df_is_bottom(&opt->after_false)) {
if (expr->pure) {
- struct bfs_expr *ret = opt_const(true);
+ struct bfs_expr *ret = opt_const(opt, true);
opt_debug(opt, 2, "data flow: %pe --> %pe\n", expr, ret);
opt_warning(opt, expr, "This expression is always true.\n\n");
- bfs_expr_free(expr);
return ret;
} else {
expr->always_true = true;
diff --git a/src/parse.c b/src/parse.c
index 18a1064..17fe8ad 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -55,50 +55,6 @@ static char *fake_print_arg = "-print";
static char *fake_true_arg = "-true";
/**
- * Create a new unary expression.
- */
-static struct bfs_expr *new_unary_expr(bfs_eval_fn *eval_fn, struct bfs_expr *rhs, char **argv) {
- struct bfs_expr *expr = bfs_expr_new(eval_fn, 1, argv);
- if (!expr) {
- bfs_expr_free(rhs);
- return NULL;
- }
-
- expr->lhs = NULL;
- expr->rhs = rhs;
- bfs_assert(bfs_expr_is_parent(expr));
-
- expr->persistent_fds = rhs->persistent_fds;
- expr->ephemeral_fds = rhs->ephemeral_fds;
- return expr;
-}
-
-/**
- * Create a new binary expression.
- */
-static struct bfs_expr *new_binary_expr(bfs_eval_fn *eval_fn, struct bfs_expr *lhs, struct bfs_expr *rhs, char **argv) {
- struct bfs_expr *expr = bfs_expr_new(eval_fn, 1, argv);
- if (!expr) {
- bfs_expr_free(rhs);
- bfs_expr_free(lhs);
- return NULL;
- }
-
- expr->lhs = lhs;
- expr->rhs = rhs;
- bfs_assert(bfs_expr_is_parent(expr));
-
- expr->persistent_fds = lhs->persistent_fds + rhs->persistent_fds;
- if (lhs->ephemeral_fds > rhs->ephemeral_fds) {
- expr->ephemeral_fds = lhs->ephemeral_fds;
- } else {
- expr->ephemeral_fds = rhs->ephemeral_fds;
- }
-
- return expr;
-}
-
-/**
* Color use flags.
*/
enum use_color {
@@ -344,6 +300,58 @@ static bool parse_expr_warning(const struct bfs_parser *parser, const struct bfs
}
/**
+ * Allocate a new expression.
+ */
+static struct bfs_expr *parse_new_expr(const struct bfs_parser *parser, bfs_eval_fn *eval_fn, size_t argc, char **argv) {
+ struct bfs_expr *expr = bfs_expr_new(parser->ctx, eval_fn, argc, argv);
+ if (!expr) {
+ parse_perror(parser, "bfs_expr_new()");
+ }
+ return expr;
+}
+
+/**
+ * Create a new unary expression.
+ */
+static struct bfs_expr *new_unary_expr(const struct bfs_parser *parser, bfs_eval_fn *eval_fn, struct bfs_expr *rhs, char **argv) {
+ struct bfs_expr *expr = parse_new_expr(parser, eval_fn, 1, argv);
+ if (!expr) {
+ return NULL;
+ }
+
+ expr->lhs = NULL;
+ expr->rhs = rhs;
+ bfs_assert(bfs_expr_is_parent(expr));
+
+ expr->persistent_fds = rhs->persistent_fds;
+ expr->ephemeral_fds = rhs->ephemeral_fds;
+ return expr;
+}
+
+/**
+ * Create a new binary expression.
+ */
+static struct bfs_expr *new_binary_expr(const struct bfs_parser *parser, bfs_eval_fn *eval_fn, struct bfs_expr *lhs, struct bfs_expr *rhs, char **argv) {
+ struct bfs_expr *expr = parse_new_expr(parser, eval_fn, 1, argv);
+ if (!expr) {
+ return NULL;
+ }
+
+ expr->lhs = lhs;
+ expr->rhs = rhs;
+ bfs_assert(bfs_expr_is_parent(expr));
+
+ expr->persistent_fds = lhs->persistent_fds + rhs->persistent_fds;
+ if (lhs->ephemeral_fds > rhs->ephemeral_fds) {
+ expr->ephemeral_fds = lhs->ephemeral_fds;
+ } else {
+ expr->ephemeral_fds = rhs->ephemeral_fds;
+ }
+
+ return expr;
+}
+
+/**
* Fill in a "-print"-type expression.
*/
static void init_print_expr(struct bfs_parser *parser, struct bfs_expr *expr) {
@@ -645,7 +653,7 @@ static bool looks_like_icmp(const char *str) {
*/
static struct bfs_expr *parse_flag(struct bfs_parser *parser, size_t argc) {
char **argv = parser_advance(parser, T_FLAG, argc);
- return bfs_expr_new(eval_true, argc, argv);
+ return parse_new_expr(parser, eval_true, argc, argv);
}
/**
@@ -674,7 +682,7 @@ static struct bfs_expr *parse_unary_flag(struct bfs_parser *parser) {
*/
static struct bfs_expr *parse_option(struct bfs_parser *parser, size_t argc) {
char **argv = parser_advance(parser, T_OPTION, argc);
- return bfs_expr_new(eval_true, argc, argv);
+ return parse_new_expr(parser, eval_true, argc, argv);
}
/**
@@ -703,7 +711,7 @@ static struct bfs_expr *parse_unary_option(struct bfs_parser *parser) {
*/
static struct bfs_expr *parse_test(struct bfs_parser *parser, bfs_eval_fn *eval_fn, size_t argc) {
char **argv = parser_advance(parser, T_TEST, argc);
- return bfs_expr_new(eval_fn, argc, argv);
+ return parse_new_expr(parser, eval_fn, argc, argv);
}
/**
@@ -742,7 +750,7 @@ static struct bfs_expr *parse_action(struct bfs_parser *parser, bfs_eval_fn *eva
parser->implicit_print = false;
}
- return bfs_expr_new(eval_fn, argc, argv);
+ return parse_new_expr(parser, eval_fn, argc, argv);
}
/**
@@ -771,7 +779,7 @@ static struct bfs_expr *parse_unary_action(struct bfs_parser *parser, bfs_eval_f
*/
static int parse_exclude(struct bfs_parser *parser, struct bfs_expr *expr) {
struct bfs_ctx *ctx = parser->ctx;
- ctx->exclude = new_binary_expr(eval_or, ctx->exclude, expr, &fake_or_arg);
+ ctx->exclude = new_binary_expr(parser, eval_or, ctx->exclude, expr, &fake_or_arg);
if (ctx->exclude) {
return 0;
} else {
@@ -789,7 +797,6 @@ static struct bfs_expr *parse_test_icmp(struct bfs_parser *parser, bfs_eval_fn *
}
if (!parse_icmp(parser, expr, 0)) {
- bfs_expr_free(expr);
return NULL;
}
@@ -848,7 +855,6 @@ static struct bfs_expr *parse_debug(struct bfs_parser *parser, int arg1, int arg
if (parse_debug_flag(flag, len, "help")) {
debug_help(ctx->cout);
parser->just_info = true;
- bfs_expr_free(expr);
return NULL;
} else if (parse_debug_flag(flag, len, "all")) {
ctx->debug = DEBUG_ALL;
@@ -896,7 +902,6 @@ static struct bfs_expr *parse_optlevel(struct bfs_parser *parser, int arg1, int
if (strcmp(expr->argv[0], "-Ofast") == 0) {
*optlevel = 4;
} else if (!parse_int(parser, expr->argv, expr->argv[0] + 2, optlevel, IF_INT | IF_UNSIGNED)) {
- bfs_expr_free(expr);
return NULL;
}
@@ -963,16 +968,12 @@ static struct bfs_expr *parse_newer(struct bfs_parser *parser, int field, int ar
struct bfs_stat sb;
if (stat_arg(parser, &expr->argv[1], &sb) != 0) {
- goto fail;
+ return NULL;
}
expr->reftime = sb.mtime;
expr->stat_field = field;
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1004,7 +1005,7 @@ static struct bfs_expr *parse_time(struct bfs_parser *parser, int field, int arg
const char *tail = parse_icmp(parser, expr, IF_PARTIAL_OK);
if (!tail) {
- goto fail;
+ return NULL;
}
if (!*tail) {
@@ -1033,7 +1034,7 @@ static struct bfs_expr *parse_time(struct bfs_parser *parser, int field, int arg
break;
default:
parse_expr_error(parser, expr, "Unknown time unit ${bld}%c${rs}.\n", *tail);
- goto fail;
+ return NULL;
}
expr->num += time;
@@ -1044,20 +1045,16 @@ static struct bfs_expr *parse_time(struct bfs_parser *parser, int field, int arg
tail = parse_int(parser, &expr->argv[1], tail, &time, IF_PARTIAL_OK | IF_LONG_LONG | IF_UNSIGNED);
if (!tail) {
- goto fail;
+ return NULL;
}
if (!*tail) {
parse_expr_error(parser, expr, "Missing time unit.\n");
- goto fail;
+ return NULL;
}
}
expr->time_unit = BFS_SECONDS;
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1087,7 +1084,6 @@ static struct bfs_expr *parse_color(struct bfs_parser *parser, int color, int ar
if (color) {
if (!colors) {
parse_expr_error(parser, expr, "Error parsing $$LS_COLORS: %s.\n", xstrerror(ctx->colors_error));
- bfs_expr_free(expr);
return NULL;
}
@@ -1182,7 +1178,6 @@ static struct bfs_expr *parse_depth_limit(struct bfs_parser *parser, int is_min,
int *depth = is_min ? &ctx->mindepth : &ctx->maxdepth;
char **arg = &expr->argv[1];
if (!parse_int(parser, arg, *arg, depth, IF_INT | IF_UNSIGNED)) {
- bfs_expr_free(expr);
return NULL;
}
@@ -1235,7 +1230,7 @@ static struct bfs_expr *parse_exec(struct bfs_parser *parser, int flags, int arg
} else {
parse_perror(parser, "strndup()");
}
- goto fail;
+ return NULL;
}
path = strchr(path, ':');
@@ -1257,10 +1252,6 @@ static struct bfs_expr *parse_exec(struct bfs_parser *parser, int flags, int arg
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1292,7 +1283,6 @@ static struct bfs_expr *parse_f(struct bfs_parser *parser, int arg1, int arg2) {
}
if (parse_root(parser, expr->argv[1]) != 0) {
- bfs_expr_free(expr);
return NULL;
}
@@ -1318,7 +1308,7 @@ static struct bfs_expr *parse_files0_from(struct bfs_parser *parser, int arg1, i
}
if (!file) {
parse_expr_error(parser, expr, "%m.\n");
- goto fail;
+ return NULL;
}
while (true) {
@@ -1348,10 +1338,9 @@ static struct bfs_expr *parse_files0_from(struct bfs_parser *parser, int arg1, i
return expr;
fail:
- if (file && file != stdin) {
+ if (file != stdin) {
fclose(file);
}
- bfs_expr_free(expr);
return NULL;
}
@@ -1385,7 +1374,6 @@ static struct bfs_expr *parse_flags(struct bfs_parser *parser, int arg1, int arg
} else {
parse_expr_error(parser, expr, "Invalid flags.\n");
}
- bfs_expr_free(expr);
return NULL;
}
@@ -1398,18 +1386,14 @@ static struct bfs_expr *parse_flags(struct bfs_parser *parser, int arg1, int arg
static struct bfs_expr *parse_fls(struct bfs_parser *parser, int arg1, int arg2) {
struct bfs_expr *expr = parse_unary_action(parser, eval_fls);
if (!expr) {
- goto fail;
+ return NULL;
}
if (expr_open(parser, expr, expr->argv[1]) != 0) {
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1417,16 +1401,15 @@ fail:
*/
static struct bfs_expr *parse_fprint(struct bfs_parser *parser, int arg1, int arg2) {
struct bfs_expr *expr = parse_unary_action(parser, eval_fprint);
- if (expr) {
- if (expr_open(parser, expr, expr->argv[1]) != 0) {
- goto fail;
- }
+ if (!expr) {
+ return NULL;
}
- return expr;
-fail:
- bfs_expr_free(expr);
- return NULL;
+ if (expr_open(parser, expr, expr->argv[1]) != 0) {
+ return NULL;
+ }
+
+ return expr;
}
/**
@@ -1434,16 +1417,15 @@ fail:
*/
static struct bfs_expr *parse_fprint0(struct bfs_parser *parser, int arg1, int arg2) {
struct bfs_expr *expr = parse_unary_action(parser, eval_fprint0);
- if (expr) {
- if (expr_open(parser, expr, expr->argv[1]) != 0) {
- goto fail;
- }
+ if (!expr) {
+ return NULL;
}
- return expr;
-fail:
- bfs_expr_free(expr);
- return NULL;
+ if (expr_open(parser, expr, expr->argv[1]) != 0) {
+ return NULL;
+ }
+
+ return expr;
}
/**
@@ -1470,18 +1452,14 @@ static struct bfs_expr *parse_fprintf(struct bfs_parser *parser, int arg1, int a
}
if (expr_open(parser, expr, file) != 0) {
- goto fail;
+ return NULL;
}
if (bfs_printf_parse(parser->ctx, expr, format) != 0) {
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1495,7 +1473,6 @@ static struct bfs_expr *parse_fstype(struct bfs_parser *parser, int arg1, int ar
if (!bfs_ctx_mtab(parser->ctx)) {
parse_expr_error(parser, expr, "Couldn't parse the mount table: %m.\n");
- bfs_expr_free(expr);
return NULL;
}
@@ -1517,21 +1494,17 @@ static struct bfs_expr *parse_group(struct bfs_parser *parser, int arg1, int arg
expr->int_cmp = BFS_INT_EQUAL;
} else if (looks_like_icmp(expr->argv[1])) {
if (!parse_icmp(parser, expr, 0)) {
- goto fail;
+ return NULL;
}
} else if (errno) {
parse_expr_error(parser, expr, "%m.\n");
- goto fail;
+ return NULL;
} else {
parse_expr_error(parser, expr, "No such group.\n");
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1564,21 +1537,17 @@ static struct bfs_expr *parse_user(struct bfs_parser *parser, int arg1, int arg2
expr->int_cmp = BFS_INT_EQUAL;
} else if (looks_like_icmp(expr->argv[1])) {
if (!parse_icmp(parser, expr, 0)) {
- goto fail;
+ return NULL;
}
} else if (errno) {
parse_expr_error(parser, expr, "%m.\n");
- goto fail;
+ return NULL;
} else {
parse_expr_error(parser, expr, "No such user.\n");
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1614,13 +1583,11 @@ static struct bfs_expr *parse_jobs(struct bfs_parser *parser, int arg1, int arg2
unsigned int n;
if (!parse_int(parser, expr->argv, expr->argv[0] + 2, &n, IF_INT | IF_UNSIGNED)) {
- bfs_expr_free(expr);
return NULL;
}
if (n == 0) {
parse_expr_error(parser, expr, "${bld}0${rs} is not enough threads.\n");
- bfs_expr_free(expr);
return NULL;
}
@@ -1680,7 +1647,6 @@ static struct bfs_expr *parse_fnmatch(const struct bfs_parser *parser, struct bf
expr->fnm_flags = FNM_CASEFOLD;
#else
parse_expr_error(parser, expr, "Missing platform support.\n");
- bfs_expr_free(expr);
return NULL;
#endif
} else {
@@ -1811,7 +1777,7 @@ static struct bfs_expr *parse_newerxy(struct bfs_parser *parser, int arg1, int a
struct bfs_expr *expr = parse_unary_test(parser, eval_newer);
if (!expr) {
- goto fail;
+ return NULL;
}
expr->stat_field = parse_newerxy_field(arg[6]);
@@ -1819,12 +1785,12 @@ static struct bfs_expr *parse_newerxy(struct bfs_parser *parser, int arg1, int a
parse_expr_error(parser, expr,
"For ${blu}-newer${bld}XY${rs}, ${bld}X${rs} should be ${bld}a${rs}, ${bld}c${rs}, ${bld}m${rs}, or ${bld}B${rs}, not ${err}%c${rs}.\n",
arg[6]);
- goto fail;
+ return NULL;
}
if (arg[7] == 't') {
if (parse_reftime(parser, expr) != 0) {
- goto fail;
+ return NULL;
}
} else {
enum bfs_stat_field field = parse_newerxy_field(arg[7]);
@@ -1832,28 +1798,24 @@ static struct bfs_expr *parse_newerxy(struct bfs_parser *parser, int arg1, int a
parse_expr_error(parser, expr,
"For ${blu}-newer${bld}XY${rs}, ${bld}Y${rs} should be ${bld}a${rs}, ${bld}c${rs}, ${bld}m${rs}, ${bld}B${rs}, or ${bld}t${rs}, not ${err}%c${rs}.\n",
arg[7]);
- goto fail;
+ return NULL;
}
struct bfs_stat sb;
if (stat_arg(parser, &expr->argv[1], &sb) != 0) {
- goto fail;
+ return NULL;
}
const struct timespec *reftime = bfs_stat_time(&sb, field);
if (!reftime) {
parse_expr_error(parser, expr, "Couldn't get file %s.\n", bfs_stat_field_name(field));
- goto fail;
+ return NULL;
}
expr->reftime = *reftime;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -1872,7 +1834,7 @@ static struct bfs_expr *parse_nogroup(struct bfs_parser *parser, int arg1, int a
* Parse -nohidden.
*/
static struct bfs_expr *parse_nohidden(struct bfs_parser *parser, int arg1, int arg2) {
- struct bfs_expr *hidden = bfs_expr_new(eval_hidden, 1, &fake_hidden_arg);
+ struct bfs_expr *hidden = parse_new_expr(parser, eval_hidden, 1, &fake_hidden_arg);
if (!hidden) {
return NULL;
}
@@ -2158,14 +2120,10 @@ static struct bfs_expr *parse_perm(struct bfs_parser *parser, int field, int arg
}
if (parse_mode(parser, mode, expr) != 0) {
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -2202,7 +2160,6 @@ static struct bfs_expr *parse_printf(struct bfs_parser *parser, int arg1, int ar
init_print_expr(parser, expr);
if (bfs_printf_parse(parser->ctx, expr, expr->argv[1]) != 0) {
- bfs_expr_free(expr);
return NULL;
}
@@ -2241,31 +2198,26 @@ static struct bfs_expr *parse_quit(struct bfs_parser *parser, int arg1, int arg2
static struct bfs_expr *parse_regex(struct bfs_parser *parser, int flags, int arg2) {
struct bfs_expr *expr = parse_unary_test(parser, eval_regex);
if (!expr) {
- goto fail;
+ return NULL;
}
if (bfs_regcomp(&expr->regex, expr->argv[1], parser->regex_type, flags) != 0) {
- if (!expr->regex) {
+ if (expr->regex) {
+ char *str = bfs_regerror(expr->regex);
+ if (str) {
+ parse_expr_error(parser, expr, "%s.\n", str);
+ free(str);
+ } else {
+ parse_perror(parser, "bfs_regerror()");
+ }
+ } else {
parse_perror(parser, "bfs_regcomp()");
- goto fail;
}
- char *str = bfs_regerror(expr->regex);
- if (!str) {
- parse_perror(parser, "bfs_regerror()");
- goto fail;
- }
-
- parse_expr_error(parser, expr, "%s.\n", str);
- free(str);
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -2324,8 +2276,6 @@ list_types:
cfprintf(cfile, " ${bld}grep${rs}: Like ${grn}grep${rs}\n");
#endif
cfprintf(cfile, " ${bld}sed${rs}: Like ${grn}sed${rs} (same as ${bld}posix-basic${rs})\n");
-
- bfs_expr_free(expr);
return NULL;
}
@@ -2348,7 +2298,6 @@ static struct bfs_expr *parse_samefile(struct bfs_parser *parser, int arg1, int
struct bfs_stat sb;
if (stat_arg(parser, &expr->argv[1], &sb) != 0) {
- bfs_expr_free(expr);
return NULL;
}
@@ -2396,8 +2345,6 @@ list_strategies:
cfprintf(cfile, " ${bld}dfs${rs}: depth-first search\n");
cfprintf(cfile, " ${bld}ids${rs}: iterative deepening search\n");
cfprintf(cfile, " ${bld}eds${rs}: exponential deepening search\n");
-
- bfs_expr_free(expr);
return NULL;
}
@@ -2411,15 +2358,11 @@ static struct bfs_expr *parse_since(struct bfs_parser *parser, int field, int ar
}
if (parse_reftime(parser, expr) != 0) {
- goto fail;
+ return NULL;
}
expr->stat_field = field;
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -2433,7 +2376,7 @@ static struct bfs_expr *parse_size(struct bfs_parser *parser, int arg1, int arg2
const char *unit = parse_icmp(parser, expr, IF_PARTIAL_OK);
if (!unit) {
- goto fail;
+ return NULL;
}
if (strlen(unit) > 1) {
@@ -2468,16 +2411,12 @@ static struct bfs_expr *parse_size(struct bfs_parser *parser, int arg1, int arg2
break;
default:
- goto bad_unit;
+ bad_unit:
+ parse_expr_error(parser, expr, "Expected a size unit (one of ${bld}cwbkMGTP${rs}); found ${err}%pq${rs}.\n", unit);
+ return NULL;
}
return expr;
-
-bad_unit:
- parse_expr_error(parser, expr, "Expected a size unit (one of ${bld}cwbkMGTP${rs}); found ${err}%pq${rs}.\n", unit);
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -2543,11 +2482,11 @@ static struct bfs_expr *parse_type(struct bfs_parser *parser, int x, int arg2) {
case '\0':
parse_expr_error(parser, expr, "Expected a type flag.\n");
- goto fail;
+ return NULL;
default:
parse_expr_error(parser, expr, "Unknown type flag ${err}%c${rs}; expected one of [${bld}bcdpflsD${rs}].\n", *c);
- goto fail;
+ return NULL;
}
++c;
@@ -2558,15 +2497,11 @@ static struct bfs_expr *parse_type(struct bfs_parser *parser, int x, int arg2) {
continue;
} else {
parse_expr_error(parser, expr, "Types must be comma-separated.\n");
- goto fail;
+ return NULL;
}
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
/**
@@ -3244,14 +3179,12 @@ static struct bfs_expr *parse_factor(struct bfs_parser *parser) {
}
if (skip_paths(parser) != 0) {
- bfs_expr_free(expr);
return NULL;
}
arg = parser->argv[0];
if (!arg || strcmp(arg, ")") != 0) {
parse_argv_error(parser, parser->last_arg, 1, "Expected a ${red})${rs}.\n");
- bfs_expr_free(expr);
return NULL;
}
@@ -3277,7 +3210,7 @@ static struct bfs_expr *parse_factor(struct bfs_parser *parser) {
return NULL;
}
- return bfs_expr_new(eval_true, parser->argv - argv, argv);
+ return parse_new_expr(parser, eval_true, parser->argv - argv, argv);
} else if (strcmp(arg, "!") == 0 || strcmp(arg, "-not") == 0) {
char **argv = parser_advance(parser, T_OPERATOR, 1);
@@ -3286,7 +3219,7 @@ static struct bfs_expr *parse_factor(struct bfs_parser *parser) {
return NULL;
}
- return new_unary_expr(eval_not, factor, argv);
+ return new_unary_expr(parser, eval_not, factor, argv);
} else {
return parse_primary(parser);
}
@@ -3303,7 +3236,6 @@ static struct bfs_expr *parse_term(struct bfs_parser *parser) {
while (term) {
if (skip_paths(parser) != 0) {
- bfs_expr_free(term);
return NULL;
}
@@ -3326,11 +3258,10 @@ static struct bfs_expr *parse_term(struct bfs_parser *parser) {
struct bfs_expr *lhs = term;
struct bfs_expr *rhs = parse_factor(parser);
if (!rhs) {
- bfs_expr_free(lhs);
return NULL;
}
- term = new_binary_expr(eval_and, lhs, rhs, argv);
+ term = new_binary_expr(parser, eval_and, lhs, rhs, argv);
}
return term;
@@ -3346,7 +3277,6 @@ static struct bfs_expr *parse_clause(struct bfs_parser *parser) {
while (clause) {
if (skip_paths(parser) != 0) {
- bfs_expr_free(clause);
return NULL;
}
@@ -3364,11 +3294,10 @@ static struct bfs_expr *parse_clause(struct bfs_parser *parser) {
struct bfs_expr *lhs = clause;
struct bfs_expr *rhs = parse_term(parser);
if (!rhs) {
- bfs_expr_free(lhs);
return NULL;
}
- clause = new_binary_expr(eval_or, lhs, rhs, argv);
+ clause = new_binary_expr(parser, eval_or, lhs, rhs, argv);
}
return clause;
@@ -3383,7 +3312,6 @@ static struct bfs_expr *parse_expr(struct bfs_parser *parser) {
while (expr) {
if (skip_paths(parser) != 0) {
- bfs_expr_free(expr);
return NULL;
}
@@ -3401,11 +3329,10 @@ static struct bfs_expr *parse_expr(struct bfs_parser *parser) {
struct bfs_expr *lhs = expr;
struct bfs_expr *rhs = parse_clause(parser);
if (!rhs) {
- bfs_expr_free(lhs);
return NULL;
}
- expr = new_binary_expr(eval_comma, lhs, rhs, argv);
+ expr = new_binary_expr(parser, eval_comma, lhs, rhs, argv);
}
return expr;
@@ -3423,7 +3350,7 @@ static struct bfs_expr *parse_whole_expr(struct bfs_parser *parser) {
if (parser->argv[0]) {
expr = parse_expr(parser);
} else {
- expr = bfs_expr_new(eval_true, 1, &fake_true_arg);
+ expr = parse_new_expr(parser, eval_true, 1, &fake_true_arg);
}
if (!expr) {
return NULL;
@@ -3431,19 +3358,19 @@ static struct bfs_expr *parse_whole_expr(struct bfs_parser *parser) {
if (parser->argv[0]) {
parse_error(parser, "Unexpected argument.\n");
- goto fail;
+ return NULL;
}
if (parser->implicit_print) {
- struct bfs_expr *print = bfs_expr_new(eval_fprint, 1, &fake_print_arg);
+ struct bfs_expr *print = parse_new_expr(parser, eval_fprint, 1, &fake_print_arg);
if (!print) {
- goto fail;
+ return NULL;
}
init_print_expr(parser, print);
- expr = new_binary_expr(eval_and, expr, print, &fake_and_arg);
+ expr = new_binary_expr(parser, eval_and, expr, print, &fake_and_arg);
if (!expr) {
- goto fail;
+ return NULL;
}
}
@@ -3461,7 +3388,7 @@ static struct bfs_expr *parse_whole_expr(struct bfs_parser *parser) {
if (parser->interactive) {
bfs_warning(parser->ctx, "Do you want to continue? ");
if (ynprompt() == 0) {
- goto fail;
+ return NULL;
}
}
@@ -3472,14 +3399,10 @@ static struct bfs_expr *parse_whole_expr(struct bfs_parser *parser) {
parse_conflict_error(parser, parser->ok_expr->argv, parser->ok_expr->argc, parser->files0_stdin_arg, 2,
"${blu}%s${rs} conflicts with ${blu}%s${rs} ${bld}%s${rs}.\n",
parser->ok_expr->argv[0], parser->files0_stdin_arg[0], parser->files0_stdin_arg[1]);
- goto fail;
+ return NULL;
}
return expr;
-
-fail:
- bfs_expr_free(expr);
- return NULL;
}
static const char *bftw_strategy_name(enum bftw_strategy strategy) {
@@ -3637,7 +3560,7 @@ static void dump_costs(const struct bfs_ctx *ctx) {
struct bfs_ctx *bfs_parse_cmdline(int argc, char *argv[]) {
struct bfs_ctx *ctx = bfs_ctx_new();
if (!ctx) {
- perror("bfs_new_ctx()");
+ perror("bfs_ctx_new()");
goto fail;
}
@@ -3715,7 +3638,7 @@ struct bfs_ctx *bfs_parse_cmdline(int argc, char *argv[]) {
.now = ctx->now,
};
- ctx->exclude = bfs_expr_new(eval_false, 1, &fake_false_arg);
+ ctx->exclude = parse_new_expr(&parser, eval_false, 1, &fake_false_arg);
if (!ctx->exclude) {
goto fail;
}
@@ -3734,6 +3657,7 @@ struct bfs_ctx *bfs_parse_cmdline(int argc, char *argv[]) {
}
if (bfs_optimize(ctx) != 0) {
+ bfs_perror(ctx, "bfs_optimize()");
goto fail;
}