summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bftw.c11
-rw-r--r--src/expr.c3
-rw-r--r--src/list.h27
-rw-r--r--src/opt.c47
4 files changed, 49 insertions, 39 deletions
diff --git a/src/bftw.c b/src/bftw.c
index 64991b0..0186e3f 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -1162,12 +1162,13 @@ static int bftw_file_open(struct bftw_state *state, struct bftw_file *file, cons
struct bftw_list parents;
SLIST_INIT(&parents);
- struct bftw_file *cur;
- for (cur = file; cur != base; cur = cur->parent) {
+ // Reverse the chain of parents
+ for (struct bftw_file *cur = file; cur != base; cur = cur->parent) {
SLIST_PREPEND(&parents, cur);
}
- while ((cur = SLIST_POP(&parents))) {
+ // Open each component relative to its parent
+ drain_slist (struct bftw_file, cur, &parents) {
if (!cur->parent || cur->parent->fd >= 0) {
bftw_file_openat(state, cur, cur->parent, cur->name);
}
@@ -1870,8 +1871,8 @@ static int bftw_gc(struct bftw_state *state, enum bftw_gc_flags flags) {
}
state->direrror = 0;
- while ((file = SLIST_POP(&state->to_close, ready))) {
- bftw_unwrapdir(state, file);
+ drain_slist (struct bftw_file, dead, &state->to_close, ready) {
+ bftw_unwrapdir(state, dead);
}
enum bftw_gc_flags visit = BFTW_VISIT_FILE;
diff --git a/src/expr.c b/src/expr.c
index 110e9b7..ca37ffc 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -68,8 +68,7 @@ void bfs_expr_append(struct bfs_expr *expr, struct bfs_expr *child) {
}
void bfs_expr_extend(struct bfs_expr *expr, struct bfs_exprs *children) {
- while (!SLIST_EMPTY(children)) {
- struct bfs_expr *child = SLIST_POP(children);
+ drain_slist (struct bfs_expr, child, children) {
bfs_expr_append(expr, child);
}
}
diff --git a/src/list.h b/src/list.h
index b30a96e..50c06a0 100644
--- a/src/list.h
+++ b/src/list.h
@@ -429,6 +429,33 @@ static inline void *slist_remove_impl(void *ret, void *cursor, void *next, size_
item = _next)
/**
+ * Loop over a singly-linked list, popping each item.
+ *
+ * @param type
+ * The list item type.
+ * @param item
+ * The induction variable name.
+ * @param list
+ * The list to drain.
+ * @param node (optional)
+ * If specified, use head->node.next rather than head->next.
+ */
+#define drain_slist(type, item, ...) \
+ drain_slist_(type, item, __VA_ARGS__, )
+
+#define drain_slist_(type, item, list, ...) \
+ drain_slist__(type, item, (list), LIST_NEXT_(__VA_ARGS__))
+
+#define drain_slist__(type, item, list, next) \
+ for (type *item = list->head; item && \
+ (SLIST_CHECK_(list), \
+ list->head = item->next, \
+ list->tail = list->head ? list->tail : &list->head, \
+ item->next = NULL, \
+ true); \
+ item = list->head)
+
+/**
* Initialize a doubly-linked list.
*
* @param list
diff --git a/src/opt.c b/src/opt.c
index 9d4323d..aa41a6a 100644
--- a/src/opt.c
+++ b/src/opt.c
@@ -737,9 +737,7 @@ static struct bfs_expr *visit_and(struct bfs_opt *opt, struct bfs_expr *expr, co
df_init_bottom(&opt->after_false);
struct bfs_opt nested = *opt;
- while (!SLIST_EMPTY(&children)) {
- struct bfs_expr *child = SLIST_POP(&children);
-
+ drain_slist (struct bfs_expr, child, &children) {
if (SLIST_EMPTY(&children)) {
nested.ignore_result = opt->ignore_result;
} else {
@@ -771,9 +769,7 @@ static struct bfs_expr *visit_or(struct bfs_opt *opt, struct bfs_expr *expr, con
df_init_bottom(&opt->after_true);
struct bfs_opt nested = *opt;
- while (!SLIST_EMPTY(&children)) {
- struct bfs_expr *child = SLIST_POP(&children);
-
+ drain_slist (struct bfs_expr, child, &children) {
if (SLIST_EMPTY(&children)) {
nested.ignore_result = opt->ignore_result;
} else {
@@ -803,9 +799,7 @@ static struct bfs_expr *visit_comma(struct bfs_opt *opt, struct bfs_expr *expr,
struct bfs_opt nested = *opt;
- while (!SLIST_EMPTY(&children)) {
- struct bfs_expr *child = SLIST_POP(&children);
-
+ drain_slist (struct bfs_expr, child, &children) {
if (SLIST_EMPTY(&children)) {
nested.ignore_result = opt->ignore_result;
} else {
@@ -1384,8 +1378,7 @@ static struct bfs_expr *sink_not_andor(struct bfs_opt *opt, struct bfs_expr *exp
struct bfs_exprs children;
foster_children(expr, &children);
- struct bfs_expr *child;
- while ((child = SLIST_POP(&children))) {
+ drain_slist (struct bfs_expr, child, &children) {
opt_enter(opt, "%pe\n", child);
child = negate_expr(opt, child, argv);
@@ -1412,8 +1405,7 @@ static struct bfs_expr *sink_not_comma(struct bfs_opt *opt, struct bfs_expr *exp
struct bfs_exprs children;
foster_children(expr, &children);
- struct bfs_expr *child;
- while ((child = SLIST_POP(&children))) {
+ drain_slist (struct bfs_expr, child, &children) {
if (SLIST_EMPTY(&children)) {
opt_enter(opt, "%pe\n", child);
opt_debug(opt, "sink\n");
@@ -1463,8 +1455,7 @@ static struct bfs_expr *canonicalize_assoc(struct bfs_opt *opt, struct bfs_expr
struct bfs_exprs flat;
SLIST_INIT(&flat);
- struct bfs_expr *child;
- while ((child = SLIST_POP(&children))) {
+ drain_slist (struct bfs_expr, child, &children) {
if (child->eval_fn == expr->eval_fn) {
struct bfs_expr *head = SLIST_HEAD(&child->children);
struct bfs_expr *tail = SLIST_TAIL(&child->children);
@@ -1572,8 +1563,7 @@ static struct bfs_expr *reorder_andor(struct bfs_opt *opt, struct bfs_expr *expr
struct bfs_exprs pure;
SLIST_INIT(&pure);
- struct bfs_expr *child;
- while ((child = SLIST_POP(&children))) {
+ drain_slist (struct bfs_expr, child, &children) {
if (child->pure) {
SLIST_APPEND(&pure, child);
} else {
@@ -1975,8 +1965,7 @@ static struct bfs_expr *lift_andor_not(struct bfs_opt *opt, struct bfs_expr *exp
struct bfs_exprs children;
foster_children(expr, &children);
- struct bfs_expr *child;
- while ((child = SLIST_POP(&children))) {
+ drain_slist (struct bfs_expr, child, &children) {
opt_enter(opt, "%pe\n", child);
child = negate_expr(opt, child, &fake_not_arg);
@@ -2022,9 +2011,7 @@ static struct bfs_expr *simplify_and(struct bfs_opt *opt, struct bfs_expr *expr,
struct bfs_exprs children;
foster_children(expr, &children);
- while (!SLIST_EMPTY(&children)) {
- struct bfs_expr *child = SLIST_POP(&children);
-
+ drain_slist (struct bfs_expr, child, &children) {
if (child == ignorable) {
ignore = true;
}
@@ -2045,8 +2032,8 @@ static struct bfs_expr *simplify_and(struct bfs_opt *opt, struct bfs_expr *expr,
bfs_expr_append(expr, child);
if (child->always_false) {
- while ((child = SLIST_POP(&children))) {
- opt_delete(opt, "%pe [short-circuit]\n", child);
+ drain_slist (struct bfs_expr, dead, &children) {
+ opt_delete(opt, "%pe [short-circuit]\n", dead);
}
}
}
@@ -2071,9 +2058,7 @@ static struct bfs_expr *simplify_or(struct bfs_opt *opt, struct bfs_expr *expr,
struct bfs_exprs children;
foster_children(expr, &children);
- while (!SLIST_EMPTY(&children)) {
- struct bfs_expr *child = SLIST_POP(&children);
-
+ drain_slist (struct bfs_expr, child, &children) {
if (child == ignorable) {
ignore = true;
}
@@ -2094,8 +2079,8 @@ static struct bfs_expr *simplify_or(struct bfs_opt *opt, struct bfs_expr *expr,
bfs_expr_append(expr, child);
if (child->always_true) {
- while ((child = SLIST_POP(&children))) {
- opt_delete(opt, "%pe [short-circuit]\n", child);
+ drain_slist (struct bfs_expr, dead, &children) {
+ opt_delete(opt, "%pe [short-circuit]\n", dead);
}
}
}
@@ -2117,9 +2102,7 @@ static struct bfs_expr *simplify_comma(struct bfs_opt *opt, struct bfs_expr *exp
struct bfs_exprs children;
foster_children(expr, &children);
- while (!SLIST_EMPTY(&children)) {
- struct bfs_expr *child = SLIST_POP(&children);
-
+ drain_slist (struct bfs_expr, child, &children) {
if (opt->level >= 2 && child->pure && !SLIST_EMPTY(&children)) {
if (!opt_ignore(opt, child, true)) {
return NULL;