8 #if HAVE_COMPOUND_LITERALS
9 #if HAVE_FOR_LOOP_DECLARATION
11 * foreach_int - iterate over a fixed series of integers
12 * @i: the int-compatible iteration variable
13 * @val: one or more integer-compatible values
15 * This is a convenient wrapper function for setting a variable to one or
16 * more explicit values in turn. continue and break work as expected.
20 * foreach_int(i, 0, -1, 100, 0, -99) {
21 * printf("i is %i\n", i);
24 #define foreach_int(i, val, ...) \
25 for (unsigned _foreach_i = ((i) = val, 0); \
26 _foreach_i < sizeof((int[]) { val, __VA_ARGS__ })/sizeof(val); \
27 (i) = (int[]) { val, __VA_ARGS__, 0 }[++_foreach_i])
30 * foreach_ptr - iterate over a non-NULL series of pointers
31 * @i: the pointer iteration variable
32 * @val: one or more compatible pointer values
34 * This is a convenient wrapper function for setting a variable to one
35 * or more explicit values in turn. None of the values can be NULL;
36 * that is the termination condition (ie. @i will be NULL on
37 * completion). continue and break work as expected.
41 * foreach_ptr(p, "Hello", "world") {
42 * printf("p is %s\n", p);
45 #define foreach_ptr(i, val, ...) \
46 for (unsigned _foreach_i = (unsigned long)((i) = (val), 0); \
48 (i) = ((FOREACH_TYPEOF(val)[]){(val), __VA_ARGS__, NULL}) \
50 _foreach_no_nullval(_foreach_i, i, \
51 ((void *[]){ val, __VA_ARGS__})))
52 #else /* !HAVE_FOR_LOOP_DECLARATION */
53 /* GCC in C89 mode still has compound literals, but no for-declarations */
54 #define foreach_int(i, val, ...) \
55 for ((i) = (val), _foreach_iter_init(&(i)); \
56 _foreach_iter(&(i)) < sizeof((int[]) { (val), __VA_ARGS__ }) \
58 (i) = (int[]) { (val), __VA_ARGS__, 0 }[_foreach_iter_inc(&(i))])
60 #define foreach_ptr(i, val, ...) \
61 for ((i) = (val), _foreach_iter_init(&(i)); \
63 (i) = ((FOREACH_TYPEOF(val)[]){ (val), __VA_ARGS__, 0 }) \
64 [_foreach_iter_inc(&(i))], \
65 _foreach_no_nullval(_foreach_iter(&(i)), i, \
66 ((void *[]){ val, __VA_ARGS__})))
68 void _foreach_iter_init(const void *i);
69 unsigned int _foreach_iter(const void *i);
70 unsigned int _foreach_iter_inc(const void *i);
72 #endif /* !HAVE_FOR_LOOP_DECLARATION */
74 /* Make sure they don't put NULL values into array! */
75 #define _foreach_no_nullval(i, p, arr) \
76 assert((i) >= sizeof(arr)/sizeof(arr[0]) || (p))
79 #define FOREACH_TYPEOF(val) __typeof__(&*(val))
81 #define FOREACH_TYPEOF(val) void *
84 #else /* !HAVE_COMPOUND_LITERALS */
86 /* No compound literals, but it's still (just) possible. */
87 #define foreach_int(i, val, ...) \
88 for (i = _foreach_intval_init(&(i), val, __VA_ARGS__, \
90 !_foreach_intval_done(&i); \
91 i = _foreach_intval_next(&(i), val, __VA_ARGS__, \
94 #define foreach_ptr(i, val, ...) \
95 for (i = _foreach_ptrval_init(&(i), val, __VA_ARGS__, NULL); \
97 i = _foreach_ptrval_next(&(i), val, __VA_ARGS__, NULL))
99 extern int _foreach_term;
100 int _foreach_intval_init(const void *i, int val, ...);
101 bool _foreach_intval_done(const void *i);
102 int _foreach_intval_next(const void *i, int val, ...);
103 void *_foreach_ptrval_init(const void *i, const void *val, ...);
104 void *_foreach_ptrval_next(const void *i, const void *val, ...);
105 #endif /* !HAVE_COMPOUND_LITERALS */
107 #endif /* CCAN_FOREACH_H */