1 /* Licensed under LGPLv3+ - see LICENSE file for details */
9 #if HAVE_COMPOUND_LITERALS
10 #if HAVE_FOR_LOOP_DECLARATION
12 * foreach_int - iterate over a fixed series of integers
13 * @i: the int-compatible iteration variable
14 * ...: one or more integer-compatible values
16 * This is a convenient wrapper function for setting a variable to one or
17 * more explicit values in turn. continue and break work as expected.
21 * foreach_int(i, 0, -1, 100, 0, -99) {
22 * printf("i is %i\n", i);
25 #define foreach_int(i, ...) \
26 for (unsigned _foreach_i = (((i) = ((int[]) { __VA_ARGS__ })[0]), 0); \
27 _foreach_i < sizeof((int[]) { __VA_ARGS__ })/sizeof(int); \
28 (i) = ((int[]) { __VA_ARGS__, 0 })[++_foreach_i])
31 * foreach_ptr - iterate over a non-NULL series of pointers
32 * @i: the pointer iteration variable
33 * ...: one or more compatible pointer values
35 * This is a convenient wrapper function for setting a variable to one
36 * or more explicit values in turn. None of the values can be NULL;
37 * that is the termination condition (ie. @i will be NULL on
38 * completion). continue and break work as expected.
42 * foreach_ptr(p, "Hello", "world") {
43 * printf("p is %s\n", p);
46 #define foreach_ptr(i, ...) \
47 for (unsigned _foreach_i \
48 = (((i) = (void *)((FOREACH_TYPEOF(i)[]){ __VA_ARGS__ })[0]), 0); \
50 (i) = (void *)((FOREACH_TYPEOF(i)[]) \
51 { __VA_ARGS__, NULL})[++_foreach_i], \
52 _foreach_no_nullval(_foreach_i, i, \
53 ((const void *[]){ __VA_ARGS__})))
54 #else /* !HAVE_FOR_LOOP_DECLARATION */
55 /* GCC in C89 mode still has compound literals, but no for-declarations */
56 #define foreach_int(i, ...) \
57 for ((i) = ((int[]){ __VA_ARGS__ })[0], _foreach_iter_init(&(i)); \
58 _foreach_iter(&(i)) < sizeof((int[]) { __VA_ARGS__ }) \
60 (i) = (int[]) { __VA_ARGS__, 0 }[_foreach_iter_inc(&(i))])
62 #define foreach_ptr(i, ...) \
63 for ((i) = (void *)((FOREACH_TYPEOF(i)[]){ __VA_ARGS__ })[0], \
64 _foreach_iter_init(&(i)); \
66 (i) = (void *)((FOREACH_TYPEOF(i)[]){ __VA_ARGS__, NULL }) \
67 [_foreach_iter_inc(&(i))], \
68 _foreach_no_nullval(_foreach_iter(&(i)), i, \
69 ((const void *[]){ __VA_ARGS__})))
71 void _foreach_iter_init(const void *i);
72 unsigned int _foreach_iter(const void *i);
73 unsigned int _foreach_iter_inc(const void *i);
75 #endif /* !HAVE_FOR_LOOP_DECLARATION */
77 /* Make sure they don't put NULL values into array! */
78 #define _foreach_no_nullval(i, p, arr) \
79 assert((i) >= sizeof(arr)/sizeof(arr[0]) || (p))
82 #define FOREACH_TYPEOF(i) __typeof__(i)
84 #define FOREACH_TYPEOF(i) const void *
87 #else /* !HAVE_COMPOUND_LITERALS */
89 /* No compound literals, but it's still (just) possible. */
90 #define foreach_int(i, ...) \
91 for (i = _foreach_intval_init(&(i), __VA_ARGS__, _foreach_term); \
92 !_foreach_intval_done(&i); \
93 i = _foreach_intval_next(&(i), __VA_ARGS__, _foreach_term))
95 #define foreach_ptr(i, ...) \
96 for (i = _foreach_ptrval_init(&(i), __VA_ARGS__, NULL); \
98 i = _foreach_ptrval_next(&(i), __VA_ARGS__, NULL))
100 extern int _foreach_term;
101 int _foreach_intval_init(const void *i, int val, ...);
102 bool _foreach_intval_done(const void *i);
103 int _foreach_intval_next(const void *i, int val, ...);
104 void *_foreach_ptrval_init(const void *i, const void *val, ...);
105 void *_foreach_ptrval_next(const void *i, const void *val, ...);
106 #endif /* !HAVE_COMPOUND_LITERALS */
108 #endif /* CCAN_FOREACH_H */