1 /* Licensed under LGPLv3+ - see LICENSE file for details */
2 #include <ccan/foreach/foreach.h>
3 #if !HAVE_COMPOUND_LITERALS || !HAVE_FOR_LOOP_DECLARATION
4 #include <ccan/list/list.h>
9 /* This list is normally very short. */
10 static LIST_HEAD(iters);
13 struct list_node list;
19 /* Is pointer still downstack from some other onstack var? */
20 static bool on_stack(const void *ptr, const void *onstack)
22 #if HAVE_STACK_GROWS_UPWARDS
29 static void free_old_iters(const void *index)
31 struct iter_info *i, *next;
33 list_for_each_safe(&iters, i, next, list) {
34 /* If we're re-using an index, free the old one.
35 * Otherwise, discard if it's passed off stack. */
37 || (i->onstack && !on_stack(i->index, &i))) {
44 static struct iter_info *find_iter(const void *index)
48 list_for_each(&iters, i, list) {
49 if (i->index == index)
55 static struct iter_info *new_iter(const void *index)
57 struct iter_info *info = malloc(sizeof *info);
59 info->i = info->num = 0;
60 info->onstack = on_stack(index, &info);
61 list_add(&iters, &info->list);
65 #if HAVE_COMPOUND_LITERALS
66 void _foreach_iter_init(const void *i)
72 unsigned int _foreach_iter(const void *i)
74 struct iter_info *info = find_iter(i);
78 unsigned int _foreach_iter_inc(const void *i)
80 struct iter_info *info = find_iter(i);
83 #else /* Don't have compound literals... */
84 int _foreach_term = 0x42430199;
86 /* We count values at beginning, and every time around the loop. We change
87 * the terminator each time, so we don't get fooled in case it really appears
89 static unsigned int count_vals(struct iter_info *info, va_list *ap)
94 for (i = 0; i < info->num || val != _foreach_term; i++) {
95 val = va_arg(*ap, int);
101 int _foreach_intval_init(const void *i, int val, ...)
104 struct iter_info *info;
110 info->num = count_vals(info, &ap);
116 bool _foreach_intval_done(const void *i)
118 struct iter_info *info = find_iter(i);
119 return info->i == info->num;
122 int _foreach_intval_next(const void *i, int val, ...)
124 struct iter_info *info = find_iter(i);
129 info->num = count_vals(info, &ap);
133 assert(info->i <= info->num);
134 if (info->i == info->num)
138 for (num = 0; num < info->i; num++)
139 val = va_arg(ap, int);
145 void *_foreach_ptrval_init(const void *i, const void *val, ...)
153 void *_foreach_ptrval_next(const void *i, const void *val, ...)
155 struct iter_info *info = find_iter(i);
161 for (num = 0; num < info->i; num++)
162 val = va_arg(ap, void *);
166 #endif /* !HAVE_COMPOUND_LITERALS */
167 #endif /* !HAVE_COMPOUND_LITERALS || !HAVE_FOR_LOOP_DECLARATION */