summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2022-01-01 02:33:27 +0000
committerColin Watson <cjwatson@debian.org>2022-01-01 02:33:27 +0000
commit9740c56b311f863f295b84cf93aee84379d0740b (patch)
tree06c879f650250f30902e70508ffa021cbd122bf8 /lib
parent5c28907556920624e6a257b1aeaaa91501306ed8 (diff)
Simplify interface to container iterator macros
The Gnulib container iterator macros (GL_LIST_FOREACH_* and GL_MAP_FOREACH_*) have to run code both before and after a chunk of user-supplied code. This previously required a START/END macro pair used something like this: GL_LIST_FOREACH_START (names, name) { ... } GL_LIST_FOREACH_END (names); This doesn't look natural in C, and so it was easy to get it wrong. It's possible to do better, at the cost of some tricky macros. Fortunately, Simon Tatham has already done the hard work in https://www.chiark.greenend.org.uk/~sgtatham/mp/, and the necessary header file is MIT-licensed, so we can incorporate it. Now these iterator macros are used more like this, which is a much more natural C style: GL_LIST_FOREACH (names, name) { ... } * lib/mp.h: New file. * lib/Makefile.am (libman_la_SOURCES): Add mp.h. * lib/README: Add mp.h. Rephrase introductory text about licensing to account for an MIT-licensed file. * lib/glcontainers.h (GL_LIST_FOREACH_START, GL_LIST_FOREACH_END): Rewrite as ... (GL_LIST_FOREACH): ... this. Update all callers. (GL_MAP_FOREACH_START, GL_MAP_FOREACH_END): Rewrite as ... (GL_MAP_FOREACH): ... this. Update all callers. * NEWS, README.md, docs/HACKING: Document C99 compiler requirement.
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/README7
-rw-r--r--lib/glcontainers.h36
-rw-r--r--lib/mp.h483
-rw-r--r--lib/orderfiles.c8
5 files changed, 507 insertions, 28 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index e5bd626c..62bce086 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -43,6 +43,7 @@ libman_la_SOURCES = \
glcontainers.h \
linelength.c \
linelength.h \
+ mp.h \
orderfiles.c \
orderfiles.h \
pathsearch.c \
diff --git a/lib/README b/lib/README
index 884b4338..6d9f8ed9 100644
--- a/lib/README
+++ b/lib/README
@@ -1,6 +1,6 @@
-These library source files have various authors but are all covered by
-either the GNU General Public License or the GNU Lesser General Public
-License, and are freely distributable under their terms and conditions.
+These library source files have various authors and specific licenses,
+but may all be used as part of a complete work that is distributed under
+the terms of the GNU General Public License version 2 or later.
See the files ../docs/COPYING and ../docs/COPYING.LIB for relevant
information.
@@ -11,6 +11,7 @@ debug.c author - Colin Watson
encodings.* author - Colin Watson
glcontainers.* author - Colin Watson
linelength.* author - Martin Schulze, Jon Tombs, Colin Watson
+mp.h author - Simon Tatham
orderfiles.* author - Colin Watson
pathsearch.* author - Colin Watson
sandbox.* author - Colin Watson
diff --git a/lib/glcontainers.h b/lib/glcontainers.h
index a60bf2e3..56ae0993 100644
--- a/lib/glcontainers.h
+++ b/lib/glcontainers.h
@@ -30,6 +30,8 @@
#include "gl_map.h"
#include "gl_set.h"
+#include "mp.h"
+
/* These types are compatible with those required by Gnulib container
* initialisation.
*/
@@ -48,27 +50,19 @@ gl_set_t new_string_set (gl_set_implementation_t implementation);
/* Iterator macros. */
-#define GL_LIST_FOREACH_START(list, item) \
- do { \
- gl_list_iterator_t list##_iter = gl_list_iterator (list); \
- gl_list_node_t list##_node; \
- while (gl_list_iterator_next (&list##_iter, \
- (const void **) &item, \
- &list##_node))
-
-#define GL_LIST_FOREACH_END(list) \
- gl_list_iterator_free (&list##_iter); \
- } while (0)
-
-#define GL_MAP_FOREACH_START(map, key, value) \
- do { \
- gl_map_iterator_t map##_iter = gl_map_iterator (map); \
- while (gl_map_iterator_next (&map##_iter, \
- (const void **) &key, \
- (const void **) &value))
+#define GL_LIST_FOREACH(list, item) \
+ MPP_DECLARE (1, gl_list_iterator_t list##_iter = gl_list_iterator (list)) \
+ MPP_DECLARE (2, gl_list_node_t list##_node) \
+ MPP_WHILE (3, gl_list_iterator_next (&list##_iter, \
+ (const void **) &item, \
+ &list##_node)) \
+ MPP_FINALLY (4, gl_list_iterator_free (&list##_iter))
-#define GL_MAP_FOREACH_END(map) \
- gl_map_iterator_free (&map##_iter); \
- } while (0)
+#define GL_MAP_FOREACH(map, key, value) \
+ MPP_DECLARE (1, gl_map_iterator_t map##_iter = gl_map_iterator (map)) \
+ MPP_WHILE (2, gl_map_iterator_next (&map##_iter, \
+ (const void **) &key, \
+ (const void **) &value)) \
+ MPP_FINALLY (3, gl_map_iterator_free (&map##_iter))
#endif /* MAN_GLCONTAINERS_H */
diff --git a/lib/mp.h b/lib/mp.h
new file mode 100644
index 00000000..d3128cec
--- /dev/null
+++ b/lib/mp.h
@@ -0,0 +1,483 @@
+/*
+ * mp.h: header file providing macros for 'metaprogramming' custom
+ * loop constructions in standard C.
+ *
+ * Accompanies the article on the web at
+ * https://www.chiark.greenend.org.uk/~sgtatham/mp/
+ */
+
+/*
+ * mp.h is copyright 2012 Simon Tatham.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+/*
+ * Macros beginning with 'MPI_' are internal to this header file, and
+ * intended only to be used by other macros defined _in_ this header
+ * file. Do not refer to them externally.
+ */
+
+/* Standard trickery to allow us to macro-expand and then token-paste */
+#define MPI_TOKPASTEINNER(x,y) x ## y
+#define MPI_TOKPASTE(x,y) MPI_TOKPASTEINNER(x,y)
+
+/* Method of constructing line-unique labels */
+#define MPI_LABEL(id1,id2) \
+ MPI_TOKPASTE(MPI_LABEL_ ## id1 ## _ ## id2 ## _, __LINE__)
+
+/*
+ * Macros beginning with 'MPP_' and 'MPS_' are building blocks
+ * intended for metaprogrammers to make useful control constructions
+ * from.
+ *
+ * The prefixes distinguish their syntactic role. MPP_ macros are
+ * statement _prefixes_; you would typically build a custom control
+ * structure by defining a macro expanding to a sequence of them. MPS_
+ * macros are actual statements, which you might use in the various
+ * parameters of MPP_ macros that are expected to be statement-shaped.
+ */
+
+/*
+ * Safety considerations:
+ *
+ * - All of these macros are C89-safe, except for MPP_DECLARE if you
+ * pass an actual declaration and not just an assignment, since
+ * that one relies on the C99 (and C++) extension of being able to
+ * write a declaration in the initialisation clause of a for
+ * statement.
+ *
+ * - None of these macros uses switch, so case labels from a switch
+ * outside the whole lot may be written inside the suffixed
+ * statement/block.
+ *
+ * - All of these constructions use 'goto' with labels constructed
+ * programmatically, using __LINE__ to make them unique between
+ * multiple invocations of the same loop macro. So don't put two
+ * loop macros defined using these building blocks on the same
+ * source line.
+ *
+ * - All of these constructions can be prefixed to something that is
+ * syntactically a single C statement, and generate something that
+ * is also a single C statement. So they're if-else safe - you can
+ * use an unbraced one of these constructs followed by an unbraced
+ * statement within the then-clause of an outer if, and the else
+ * will still bind to what it looks as if it ought to.
+ *
+ * - Controlling what happens if the user writes a 'break' in the
+ * suffixed statement is unavoidably rather fiddly. The macros
+ * below fall into a few categories:
+ *
+ * + naturally transparent to 'break' (MPP_BEFORE, MPP_IF). Macros
+ * of this type will not affect the semantics of 'break' in the
+ * suffixed statement at all - it will terminate the next
+ * innermost loop or switch outside the construction.
+ *
+ * + artificially transparent to 'break', by means of deliberately
+ * catching and 'rethrowing' it. (MPP_BREAK_{THROW,CATCH};
+ * MPP_BREAK_HANDLER; MPP_FINALLY.) These macros will propagate
+ * a break outwards to the next containing loop, but in order to
+ * do so they require that there _be_ a next containing loop,
+ * since their expansion can't avoid including a break statement
+ * which they themselves do not wrap in a loop. So you should
+ * only use these when you know there is a containing loop (e.g.
+ * because MPP_WHILE or MPP_DO_WHILE precedes them in your
+ * construction).
+ *
+ * + loop constructions. (MPP_WHILE and MPP_DO_WHILE). These
+ * macros give 'break' the obvious semantics of terminating the
+ * loop they define.
+ *
+ * + break-unsafe macros, which have to include a C looping
+ * construction to do something not essentially loopy, and hence
+ * have the unfortunate side effect of causing 'break' to only
+ * terminate the suffixed statement itself. On the other hand,
+ * they can be used in contexts where there is no surrounding
+ * loop at all (which is why I don't just fix them to contain a
+ * built-in MPP_BREAK_{THROW,CATCH}).
+ *
+ * If you are using these macros to build a looping construct, then
+ * you will probably include an MPP_WHILE or MPP_DO_WHILE in your
+ * stack, and you'll want 'break' to terminate that. So you just
+ * need to be sure that break is correctly propagated from the
+ * suffixed statement back to that loop, which you can do by
+ * sticking to the break-transparent macros where possible and
+ * using MPP_BREAK_{THROW,CATCH} to bypass any break-unsafe macro
+ * such as MPP_DECLARE that you might need to use. Having done
+ * that, 'break' will do what the user expects.
+ *
+ * But if you're using the macros to wrap some context around a
+ * statement you still intend to be executed only once, there will
+ * be unavoidable side effects on 'break': you can't use the
+ * artificially break-unsafe macros because the user might use your
+ * construction in a context with no surrounding loop at all, so
+ * you must stick to the naturally break-transparent and the
+ * break-unsafe, and there aren't enough of the former to be really
+ * useful. So you must just live with 'break' acquiring unhelpful
+ * behaviour inside such a macro.
+ *
+ * - Almost none of these macros is transparent to 'continue'. The
+ * naturally break-transparent MPP_BEFORE is, but none of the rest
+ * can possibly be, because as soon as you include any loop
+ * construction in the stuff being prefixed to a statement, you
+ * introduce the invariant that 'continue' is equivalent to jumping
+ * to the end of the suffixed statement or block. This is not too
+ * bad if you're defining a custom loop construction (it was quite
+ * likely the behaviour you wanted for continue anyway), but if you
+ * were trying to use MPP_DECLARE and/or MPP_BEFORE_AND_AFTER to
+ * wrap a statement in some context but still only execute it once,
+ * you'd have to be aware of that limitation.
+ *
+ * - MPP_FINALLY and MPP_BREAK_HANDLER can only catch non-local exits
+ * from the block _by break_. They are not true C++ try/finally, so
+ * they can't catch other kinds of exit such as return, goto,
+ * longjmp or exit.
+ *
+ * - Finally, it almost goes without saying, but don't forget that
+ * snippets of code you use as parameters to these macros must
+ * avoid using commas not contained inside parentheses, or else the
+ * C preprocessor will consider the comma to end that macro
+ * parameter and start the next one. If there is any reason you
+ * really need an unbracketed comma, you can work around this by
+ * one of two methods:
+ * - define a macro that expands to a comma ('#define COMMA ,')
+ * and then use that macro in place of commas in your macro
+ * argument. It won't be expanded to an actual comma until after
+ * the argument-separation has finished.
+ * - if you're allowed to use C99, define a variadic macro that
+ * expands to its unmodified input argument list ('#define
+ * WRAP(...) __VA_ARGS__') and then enclose comma-using code in
+ * WRAP(). Again, this will protect the commas for just long
+ * enough.
+ */
+
+/*
+ * MPP_BEFORE: run the code given in the argument 'before' and then
+ * the suffixed statement.
+ *
+ * 'before' should have the syntactic form of one or more declarations
+ * and statements, except that a trailing semicolon may be omitted.
+ * Any declarations will be in scope only within 'before', not within
+ * the suffixed statement.
+ *
+ * This macro, unusually among the collection, is naturally
+ * transparent to 'break' and also transparent to 'continue'.
+ */
+#define MPP_BEFORE(labid,before) \
+ if (1) { \
+ before; \
+ goto MPI_LABEL(labid, body); \
+ } else \
+ MPI_LABEL(labid, body):
+
+/*
+ * MPP_AFTER: run the suffixed statement, and then the code given in
+ * the argument 'after'.
+ *
+ * 'after' should have the syntactic form of one or more declarations
+ * and statements, except that a trailing semicolon may be omitted.
+ * Any declaration in 'after' will be in scope only within 'after'.
+ *
+ * This macro is break-unsafe - it causes a 'break' to terminate the
+ * suffixed statement only. If you need different behaviour, you can
+ * use MPP_BREAK_CATCH and MPP_BREAK_THROW to pass a break past it -
+ * but beware that in that case the 'after' clause will not be
+ * executed, so MPP_FINALLY or MPP_BREAK_HANDLER may be useful too.
+ */
+#define MPP_AFTER(labid,after) \
+ if (1) \
+ goto MPI_LABEL(labid, body); \
+ else \
+ while (1) \
+ if (1) { \
+ after; \
+ break; \
+ } else \
+ MPI_LABEL(labid, body):
+
+/*
+ * MPP_DECLARE: run the 'declaration' argument before the suffixed
+ * statement. The argument may have the form of either a C expression
+ * (e.g. an assignment) or a declaration; if the latter, it will be in
+ * scope within the suffixed statement.
+ *
+ * This macro is break-unsafe - it causes a 'break' to terminate the
+ * suffixed statement only. If you need different behaviour, you can
+ * use MPP_BREAK_CATCH and MPP_BREAK_THROW to pass a break past it.
+ */
+#define MPP_DECLARE(labid, declaration) \
+ if (0) \
+ ; \
+ else \
+ for (declaration;;) \
+ if (1) { \
+ goto MPI_LABEL(labid, body); \
+ MPI_LABEL(labid, done): break; \
+ } else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, done); \
+ else \
+ MPI_LABEL(labid, body):
+/* (The 'if(0) ; else' at the start of the above is just in case we
+ * encounter an old-style compiler that considers variables declared
+ * in for statements to have scope extending beyond the for statement.
+ * Putting another layer outside the 'for' ensures that the variable's
+ * scope is constrained to _that_ layer even if not to the for itself,
+ * and it doesn't leak into the calling scope. */
+
+/*
+ * MPP_WHILE: run the suffixed statement within a 'while (condition)'
+ * loop.
+ *
+ * In fact, just writing 'while (condition)' works fine for this, but
+ * it's nice to make it look like the rest of these macros!
+ *
+ * This macro defines an actual loop, and 'break' in the suffixed
+ * statement terminates that loop as you would expect.
+ */
+#define MPP_WHILE(labid, condition) \
+ while (condition)
+
+/*
+ * MPP_DO_WHILE: run the suffixed statement within a loop with the
+ * semantics of 'do suffixed-statement while (condition)'.
+ *
+ * This macro defines an actual loop, and 'break' in the suffixed
+ * statement terminates that loop as you would expect.
+ */
+#define MPP_DO_WHILE(labid, condition) \
+ if (1) \
+ goto MPI_LABEL(labid, body); \
+ else \
+ while (condition) \
+ MPI_LABEL(labid, body):
+
+/*
+ * MPP_IF: run the suffixed statement only if 'condition' is true.
+ *
+ * This macro is naturally transparent to 'break' and also transparent
+ * to 'continue'.
+ */
+#define MPP_IF(labid, condition) \
+ if (!(condition)) \
+ ; \
+ else
+
+/*
+ * MPP_BREAK_THROW and MPP_BREAK_CATCH: propagate 'break' control flow
+ * transfers past other prefixes that mess about with them.
+ *
+ * Write an MPP_BREAK_CATCH, then other metaprogramming prefixes from
+ * this collection, and then an MPP_BREAK_THROW with the same label
+ * id. If the statement following the MPP_BREAK_THROW terminates by
+ * 'break', then the effect will be as if the MPP_BREAK_CATCH had
+ * terminated by 'break', regardless of how the in-between prefixes
+ * would have handled a 'break'.
+ *
+ * These macros are artificially transparent to 'break': they pass
+ * break through, but include a 'break' statement at the top level of
+ * MPP_BREAK_CATCH, so that must always be contained inside some loop
+ * or switch construction.
+ *
+ * We also provide MPS_BREAK_THROW, which is a statement-type macro
+ * that manufactures a break event and passes it to a specified
+ * MPP_BREAK_CATCH.
+ */
+#define MPP_BREAK_CATCH(labid) \
+ if (0) \
+ MPI_LABEL(labid, catch): break; \
+ else
+
+#define MPP_BREAK_THROW(labid) \
+ if (1) { \
+ goto MPI_LABEL(labid, body); \
+ MPI_LABEL(labid, finish):; \
+ } else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, catch); \
+ else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, finish); \
+ else \
+ MPI_LABEL(labid, body):
+
+#define MPS_BREAK_THROW(labid) goto MPI_LABEL(labid, catch)
+
+/*
+ * MPP_BREAK_HANDLER: handle a 'break' in the suffixed statement by
+ * executing the provided handler code and then terminating as if by
+ * break.
+ *
+ * 'handler' should have the syntactic form of one or more
+ * declarations and statements, except that a trailing semicolon may
+ * be omitted.
+ *
+ * This macro is artificially transparent to 'break': it passes break
+ * through, but includes a 'break' statement at the top level, so it
+ * must always be contained inside some loop or switch construction.
+ */
+#define MPP_BREAK_HANDLER(labid, handler) \
+ if (1) { \
+ goto MPI_LABEL(labid, body); \
+ MPI_LABEL(labid, break): \
+ {handler;} \
+ break; \
+ MPI_LABEL(labid, finish):; \
+ } else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, break); \
+ else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, finish); \
+ else \
+ MPI_LABEL(labid, body):
+
+/*
+ * MPP_FINALLY: execute the suffixed statement, and execute the
+ * provided 'finally' clause after it finishes. If it terminates by
+ * 'break', execute the same 'finally' clause but propagate the break
+ * to the containing statement.
+ *
+ * 'finally' should have the syntactic form of one or more
+ * declarations and statements, except that a trailing semicolon may
+ * be omitted.
+ *
+ * The 'finally' argument will be double-expanded. Of course it'll
+ * only be executed once in any given run, so that's not a concern for
+ * function side effects, but don't do anything fiddly like declaring
+ * a static variable to which you return a pointer and then expecting
+ * the pointer to be the same no matter which copy of 'finally' it
+ * came from.
+ *
+ * This macro is artificially transparent to 'break': it passes break
+ * through, but includes a 'break' statement at the top level, so it
+ * must always be contained inside some loop or switch construction.
+ */
+#define MPP_FINALLY(labid, finally) \
+ if (1) { \
+ goto MPI_LABEL(labid, body); \
+ MPI_LABEL(labid, break): \
+ {finally;} \
+ break; \
+ MPI_LABEL(labid, finish): \
+ {finally;} \
+ } else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, break); \
+ else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, finish); \
+ else \
+ MPI_LABEL(labid, body):
+
+/*
+ * MPP_BREAK_STOP: handle a 'break' in the suffixed statement by
+ * executing the provided handler code and then terminating as if
+ * normally.
+ *
+ * 'handler' should have the syntactic form of one or more
+ * declarations and statements, except that a trailing semicolon may
+ * be omitted.
+ */
+#define MPP_BREAK_STOP(labid, handler) \
+ if (1) { \
+ goto MPI_LABEL(labid, body); \
+ MPI_LABEL(labid, break): \
+ {handler;} \
+ MPI_LABEL(labid, finish):; \
+ } else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, break); \
+ else \
+ while (1) \
+ if (1) \
+ goto MPI_LABEL(labid, finish); \
+ else \
+ MPI_LABEL(labid, body):
+
+/*
+ * MPP_ELSE_ACCEPT, MPS_MAIN_INVOKE, MPS_ELSE_INVOKE: arrange to
+ * accept an optional 'else' clause after the suffixed statement, and
+ * provide two statement macros which jump to the main clause and the
+ * else clause. The main (non-else) clause will be be executed in the
+ * default case, and can be invoked again using MPS_MAIN_INVOKE;
+ * MPS_ELSE_INVOKE will invoke the else clause.
+ *
+ * Like MPP_BREAK_THROW and MPP_BREAK_CATCH, these macros should be
+ * used in groups with the same label id, so as to match them up to
+ * each other. MPS_ELSE_INVOKE and MPS_MAIN_INVOKE will go to the
+ * appropriate clauses corresponding to the MPP_ELSE_ACCEPT with the
+ * same id.
+ */
+#define MPP_ELSE_ACCEPT(labid) \
+ if (1) \
+ goto MPI_LABEL(labid, body); \
+ else \
+ MPI_LABEL(labid, else): \
+ if (0) \
+ MPI_LABEL(labid, body):
+
+#define MPS_MAIN_INVOKE(labid) \
+ goto MPI_LABEL(labid, body)
+
+#define MPS_ELSE_INVOKE(labid) \
+ goto MPI_LABEL(labid, else)
+
+/*
+ * MPP_ELSE_GENERAL: like MPP_ELSE_ACCEPT, but also lets you provide a
+ * snippet of code that will be run after the else clause terminates
+ * and one which will be run after the else clause breaks.
+ *
+ * You can use MPS_MAIN_INVOKE and MPS_ELSE_INVOKE with this as well
+ * as with MPP_ELSE_ACCEPT.
+ *
+ * Will mess up what happens after the main body, so you'll probably
+ * want to follow this macro with others such as MPP_AFTER and
+ * something to catch break in the main body too.
+ */
+#define MPP_ELSE_GENERAL(labid, after, breakhandler) \
+ if (1) \
+ goto MPI_LABEL(labid, body); \
+ else \
+ while (1) \
+ if (1) { \
+ {breakhandler;} \
+ break; \
+ } else \
+ while (1) \
+ if (1) { \
+ {after;} \
+ break; \
+ } else \
+ MPI_LABEL(labid, else): \
+ if (0) \
+ MPI_LABEL(labid, body):
diff --git a/lib/orderfiles.c b/lib/orderfiles.c
index bc12c88a..75a3ad70 100644
--- a/lib/orderfiles.c
+++ b/lib/orderfiles.c
@@ -104,7 +104,7 @@ void order_files (const char *dir, gl_list_t *basenamesp)
physical_offsets = gl_map_create_empty (GL_HASH_MAP, string_equals,
string_hash, NULL, plain_free);
sorted_basenames = new_string_list (GL_RBTREE_LIST, false);
- GL_LIST_FOREACH_START (basenames, name) {
+ GL_LIST_FOREACH (basenames, name) {
struct {
struct fiemap fiemap;
struct fiemap_extent extent;
@@ -134,7 +134,7 @@ void order_files (const char *dir, gl_list_t *basenamesp)
close (fd);
gl_sortedlist_add (sorted_basenames, compare_physical_offsets,
xstrdup (name));
- } GL_LIST_FOREACH_END (basenames);
+ }
gl_map_free (physical_offsets);
physical_offsets = NULL;
close (dir_fd);
@@ -160,13 +160,13 @@ void order_files (const char *dir, gl_list_t *basenamesp)
/* While we can't actually order the files, we can at least ask the
* kernel to preload them.
*/
- GL_LIST_FOREACH_START (basenames, name) {
+ GL_LIST_FOREACH (basenames, name) {
int fd = openat (dir_fd, name, O_RDONLY | O_NONBLOCK);
if (fd >= 0) {
posix_fadvise (fd, 0, 0, POSIX_FADV_WILLNEED);
close (fd);
}
- } GL_LIST_FOREACH_END (basenames);
+ }
close (dir_fd);
}