1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
/* Licensed under LGPLv3+ - see LICENSE file for details */
#include <ccan/foreach/foreach.h>
#if !HAVE_COMPOUND_LITERALS || !HAVE_FOR_LOOP_DECLARATION
#include <ccan/list/list.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdarg.h>
/* This list is normally very short. */
static LIST_HEAD(iters);
struct iter_info {
struct list_node list;
const void *index;
unsigned int i, num;
bool onstack;
};
/* Is pointer still downstack from some other onstack var? */
static bool on_stack(const void *ptr, const void *onstack)
{
#if HAVE_STACK_GROWS_UPWARDS
return ptr < onstack;
#else
return ptr > onstack;
#endif
}
static void free_old_iters(const void *index)
{
struct iter_info *i, *next;
list_for_each_safe(&iters, i, next, list) {
/* If we're re-using an index, free the old one.
* Otherwise, discard if it's passed off stack. */
if (i->index == index
|| (i->onstack && !on_stack(i->index, &i))) {
list_del(&i->list);
free(i);
}
}
}
static struct iter_info *find_iter(const void *index)
{
struct iter_info *i;
list_for_each(&iters, i, list) {
if (i->index == index)
return i;
}
abort();
}
static struct iter_info *new_iter(const void *index)
{
struct iter_info *info = malloc(sizeof *info);
info->index = index;
info->i = info->num = 0;
info->onstack = on_stack(index, &info);
list_add(&iters, &info->list);
return info;
};
#if HAVE_COMPOUND_LITERALS
void _foreach_iter_init(const void *i)
{
free_old_iters(i);
new_iter(i);
}
unsigned int _foreach_iter(const void *i)
{
struct iter_info *info = find_iter(i);
return info->i;
}
unsigned int _foreach_iter_inc(const void *i)
{
struct iter_info *info = find_iter(i);
return ++info->i;
}
#else /* Don't have compound literals... */
int _foreach_term = 0x42430199;
/* We count values at beginning, and every time around the loop. We change
* the terminator each time, so we don't get fooled in case it really appears
* in the list. */
static unsigned int count_vals(struct iter_info *info, va_list *ap)
{
unsigned int i;
int val = 0;
for (i = 0; i < info->num || val != _foreach_term; i++) {
val = va_arg(*ap, int);
}
_foreach_term++;
return i;
}
int _foreach_intval_init(const void *i, int val, ...)
{
va_list ap;
struct iter_info *info;
free_old_iters(i);
info = new_iter(i);
va_start(ap, val);
info->num = count_vals(info, &ap);
va_end(ap);
return val;
}
bool _foreach_intval_done(const void *i)
{
struct iter_info *info = find_iter(i);
return info->i == info->num;
}
int _foreach_intval_next(const void *i, int val, ...)
{
struct iter_info *info = find_iter(i);
va_list ap;
unsigned int num;
va_start(ap, val);
info->num = count_vals(info, &ap);
va_end(ap);
info->i++;
assert(info->i <= info->num);
if (info->i == info->num)
return 0;
va_start(ap, val);
for (num = 0; num < info->i; num++)
val = va_arg(ap, int);
va_end(ap);
return val;
}
void *_foreach_ptrval_init(const void *i, const void *val, ...)
{
free_old_iters(i);
new_iter(i);
return (void *)val;
}
void *_foreach_ptrval_next(const void *i, const void *val, ...)
{
struct iter_info *info = find_iter(i);
va_list ap;
unsigned int num;
info->i++;
va_start(ap, val);
for (num = 0; num < info->i; num++)
val = va_arg(ap, void *);
va_end(ap);
return (void *)val;
}
#endif /* !HAVE_COMPOUND_LITERALS */
#endif /* !HAVE_COMPOUND_LITERALS || !HAVE_FOR_LOOP_DECLARATION */
|