Mon Mar 15 16:45:30 2021 UTC ()
make: fix documentation of Lst_MoveAll

In CLEANUP mode, was originally meant to track memory allocations but is
useful during debugging as well, initialize the list.  There is no
distinct constant representing an invalid pointer, otherwise that would
have been an even better choice.


(rillig)
diff -r1.104 -r1.105 src/usr.bin/make/lst.c

cvs diff -r1.104 -r1.105 src/usr.bin/make/lst.c (switch to unified diff)

--- src/usr.bin/make/lst.c 2021/02/01 19:39:31 1.104
+++ src/usr.bin/make/lst.c 2021/03/15 16:45:30 1.105
@@ -1,288 +1,292 @@ @@ -1,288 +1,292 @@
1/* $NetBSD: lst.c,v 1.104 2021/02/01 19:39:31 rillig Exp $ */ 1/* $NetBSD: lst.c,v 1.105 2021/03/15 16:45:30 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include "make.h" 35#include "make.h"
36 36
37MAKE_RCSID("$NetBSD: lst.c,v 1.104 2021/02/01 19:39:31 rillig Exp $"); 37MAKE_RCSID("$NetBSD: lst.c,v 1.105 2021/03/15 16:45:30 rillig Exp $");
38 38
39static ListNode * 39static ListNode *
40LstNodeNew(ListNode *prev, ListNode *next, void *datum) 40LstNodeNew(ListNode *prev, ListNode *next, void *datum)
41{ 41{
42 ListNode *ln = bmake_malloc(sizeof *ln); 42 ListNode *ln = bmake_malloc(sizeof *ln);
43 43
44 ln->prev = prev; 44 ln->prev = prev;
45 ln->next = next; 45 ln->next = next;
46 ln->datum = datum; 46 ln->datum = datum;
47 47
48 return ln; 48 return ln;
49} 49}
50 50
51/* Create and initialize a new, empty list. */ 51/* Create and initialize a new, empty list. */
52List * 52List *
53Lst_New(void) 53Lst_New(void)
54{ 54{
55 List *list = bmake_malloc(sizeof *list); 55 List *list = bmake_malloc(sizeof *list);
56 Lst_Init(list); 56 Lst_Init(list);
57 return list; 57 return list;
58} 58}
59 59
60void 60void
61Lst_Done(List *list) 61Lst_Done(List *list)
62{ 62{
63 ListNode *ln, *next; 63 ListNode *ln, *next;
64 64
65 for (ln = list->first; ln != NULL; ln = next) { 65 for (ln = list->first; ln != NULL; ln = next) {
66 next = ln->next; 66 next = ln->next;
67 free(ln); 67 free(ln);
68 } 68 }
69} 69}
70 70
71void 71void
72Lst_DoneCall(List *list, LstFreeProc freeProc) 72Lst_DoneCall(List *list, LstFreeProc freeProc)
73{ 73{
74 ListNode *ln, *next; 74 ListNode *ln, *next;
75 75
76 for (ln = list->first; ln != NULL; ln = next) { 76 for (ln = list->first; ln != NULL; ln = next) {
77 next = ln->next; 77 next = ln->next;
78 freeProc(ln->datum); 78 freeProc(ln->datum);
79 free(ln); 79 free(ln);
80 } 80 }
81} 81}
82 82
83/* Free a list and all its nodes. The node data are not freed though. */ 83/* Free a list and all its nodes. The node data are not freed though. */
84void 84void
85Lst_Free(List *list) 85Lst_Free(List *list)
86{ 86{
87 87
88 Lst_Done(list); 88 Lst_Done(list);
89 free(list); 89 free(list);
90} 90}
91 91
92/* Insert a new node with the datum before the given node. */ 92/* Insert a new node with the datum before the given node. */
93void 93void
94Lst_InsertBefore(List *list, ListNode *ln, void *datum) 94Lst_InsertBefore(List *list, ListNode *ln, void *datum)
95{ 95{
96 ListNode *newNode; 96 ListNode *newNode;
97 97
98 assert(datum != NULL); 98 assert(datum != NULL);
99 99
100 newNode = LstNodeNew(ln->prev, ln, datum); 100 newNode = LstNodeNew(ln->prev, ln, datum);
101 101
102 if (ln->prev != NULL) 102 if (ln->prev != NULL)
103 ln->prev->next = newNode; 103 ln->prev->next = newNode;
104 ln->prev = newNode; 104 ln->prev = newNode;
105 105
106 if (ln == list->first) 106 if (ln == list->first)
107 list->first = newNode; 107 list->first = newNode;
108} 108}
109 109
110/* Add a piece of data at the start of the given list. */ 110/* Add a piece of data at the start of the given list. */
111void 111void
112Lst_Prepend(List *list, void *datum) 112Lst_Prepend(List *list, void *datum)
113{ 113{
114 ListNode *ln; 114 ListNode *ln;
115 115
116 assert(datum != NULL); 116 assert(datum != NULL);
117 117
118 ln = LstNodeNew(NULL, list->first, datum); 118 ln = LstNodeNew(NULL, list->first, datum);
119 119
120 if (list->first == NULL) { 120 if (list->first == NULL) {
121 list->first = ln; 121 list->first = ln;
122 list->last = ln; 122 list->last = ln;
123 } else { 123 } else {
124 list->first->prev = ln; 124 list->first->prev = ln;
125 list->first = ln; 125 list->first = ln;
126 } 126 }
127} 127}
128 128
129/* Add a piece of data at the end of the given list. */ 129/* Add a piece of data at the end of the given list. */
130void 130void
131Lst_Append(List *list, void *datum) 131Lst_Append(List *list, void *datum)
132{ 132{
133 ListNode *ln; 133 ListNode *ln;
134 134
135 assert(datum != NULL); 135 assert(datum != NULL);
136 136
137 ln = LstNodeNew(list->last, NULL, datum); 137 ln = LstNodeNew(list->last, NULL, datum);
138 138
139 if (list->last == NULL) { 139 if (list->last == NULL) {
140 list->first = ln; 140 list->first = ln;
141 list->last = ln; 141 list->last = ln;
142 } else { 142 } else {
143 list->last->next = ln; 143 list->last->next = ln;
144 list->last = ln; 144 list->last = ln;
145 } 145 }
146} 146}
147 147
148/* 148/*
149 * Remove the given node from the given list. 149 * Remove the given node from the given list.
150 * The datum stored in the node must be freed by the caller, if necessary. 150 * The datum stored in the node must be freed by the caller, if necessary.
151 */ 151 */
152void 152void
153Lst_Remove(List *list, ListNode *ln) 153Lst_Remove(List *list, ListNode *ln)
154{ 154{
155 /* unlink it from its neighbors */ 155 /* unlink it from its neighbors */
156 if (ln->next != NULL) 156 if (ln->next != NULL)
157 ln->next->prev = ln->prev; 157 ln->next->prev = ln->prev;
158 if (ln->prev != NULL) 158 if (ln->prev != NULL)
159 ln->prev->next = ln->next; 159 ln->prev->next = ln->next;
160 160
161 /* unlink it from the list */ 161 /* unlink it from the list */
162 if (list->first == ln) 162 if (list->first == ln)
163 list->first = ln->next; 163 list->first = ln->next;
164 if (list->last == ln) 164 if (list->last == ln)
165 list->last = ln->prev; 165 list->last = ln->prev;
166} 166}
167 167
168/* Replace the datum in the given node with the new datum. */ 168/* Replace the datum in the given node with the new datum. */
169void 169void
170LstNode_Set(ListNode *ln, void *datum) 170LstNode_Set(ListNode *ln, void *datum)
171{ 171{
172 assert(datum != NULL); 172 assert(datum != NULL);
173 173
174 ln->datum = datum; 174 ln->datum = datum;
175} 175}
176 176
177/* 177/*
178 * Replace the datum in the given node with NULL. 178 * Replace the datum in the given node with NULL.
179 * Having NULL values in a list is unusual though. 179 * Having NULL values in a list is unusual though.
180 */ 180 */
181void 181void
182LstNode_SetNull(ListNode *ln) 182LstNode_SetNull(ListNode *ln)
183{ 183{
184 ln->datum = NULL; 184 ln->datum = NULL;
185} 185}
186 186
187/* 187/*
188 * Return the first node that contains the given datum, or NULL. 188 * Return the first node that contains the given datum, or NULL.
189 * 189 *
190 * Time complexity: O(length(list)) 190 * Time complexity: O(length(list))
191 */ 191 */
192ListNode * 192ListNode *
193Lst_FindDatum(List *list, const void *datum) 193Lst_FindDatum(List *list, const void *datum)
194{ 194{
195 ListNode *ln; 195 ListNode *ln;
196 196
197 assert(datum != NULL); 197 assert(datum != NULL);
198 198
199 for (ln = list->first; ln != NULL; ln = ln->next) 199 for (ln = list->first; ln != NULL; ln = ln->next)
200 if (ln->datum == datum) 200 if (ln->datum == datum)
201 return ln; 201 return ln;
202 202
203 return NULL; 203 return NULL;
204} 204}
205 205
206/* 206/*
207 * Move all nodes from src to the end of dst. 207 * Move all nodes from src to the end of dst.
208 * The source list becomes empty but is not freed. 208 * The source list becomes indeterminate.
209 */ 209 */
210void 210void
211Lst_MoveAll(List *dst, List *src) 211Lst_MoveAll(List *dst, List *src)
212{ 212{
213 if (src->first != NULL) { 213 if (src->first != NULL) {
214 src->first->prev = dst->last; 214 src->first->prev = dst->last;
215 if (dst->last != NULL) 215 if (dst->last != NULL)
216 dst->last->next = src->first; 216 dst->last->next = src->first;
217 else 217 else
218 dst->first = src->first; 218 dst->first = src->first;
219 219
220 dst->last = src->last; 220 dst->last = src->last;
221 } 221 }
 222#ifdef CLEANUP
 223 src->first = NULL;
 224 src->last = NULL;
 225#endif
222} 226}
223 227
224/* Copy the element data from src to the start of dst. */ 228/* Copy the element data from src to the start of dst. */
225void 229void
226Lst_PrependAll(List *dst, List *src) 230Lst_PrependAll(List *dst, List *src)
227{ 231{
228 ListNode *ln; 232 ListNode *ln;
229 233
230 for (ln = src->last; ln != NULL; ln = ln->prev) 234 for (ln = src->last; ln != NULL; ln = ln->prev)
231 Lst_Prepend(dst, ln->datum); 235 Lst_Prepend(dst, ln->datum);
232} 236}
233 237
234/* Copy the element data from src to the end of dst. */ 238/* Copy the element data from src to the end of dst. */
235void 239void
236Lst_AppendAll(List *dst, List *src) 240Lst_AppendAll(List *dst, List *src)
237{ 241{
238 ListNode *ln; 242 ListNode *ln;
239 243
240 for (ln = src->first; ln != NULL; ln = ln->next) 244 for (ln = src->first; ln != NULL; ln = ln->next)
241 Lst_Append(dst, ln->datum); 245 Lst_Append(dst, ln->datum);
242} 246}
243 247
244/* Remove and return the datum at the head of the given list. */ 248/* Remove and return the datum at the head of the given list. */
245void * 249void *
246Lst_Dequeue(List *list) 250Lst_Dequeue(List *list)
247{ 251{
248 void *datum = list->first->datum; 252 void *datum = list->first->datum;
249 Lst_Remove(list, list->first); 253 Lst_Remove(list, list->first);
250 assert(datum != NULL); /* since NULL would mean end of the list */ 254 assert(datum != NULL); /* since NULL would mean end of the list */
251 return datum; 255 return datum;
252} 256}
253 257
254void 258void
255Vector_Init(Vector *v, size_t itemSize) 259Vector_Init(Vector *v, size_t itemSize)
256{ 260{
257 v->len = 0; 261 v->len = 0;
258 v->cap = 10; 262 v->cap = 10;
259 v->itemSize = itemSize; 263 v->itemSize = itemSize;
260 v->items = bmake_malloc(v->cap * v->itemSize); 264 v->items = bmake_malloc(v->cap * v->itemSize);
261} 265}
262 266
263/* 267/*
264 * Add space for a new item to the vector and return a pointer to that space. 268 * Add space for a new item to the vector and return a pointer to that space.
265 * The returned data is valid until the next modifying operation. 269 * The returned data is valid until the next modifying operation.
266 */ 270 */
267void * 271void *
268Vector_Push(Vector *v) 272Vector_Push(Vector *v)
269{ 273{
270 if (v->len >= v->cap) { 274 if (v->len >= v->cap) {
271 v->cap *= 2; 275 v->cap *= 2;
272 v->items = bmake_realloc(v->items, v->cap * v->itemSize); 276 v->items = bmake_realloc(v->items, v->cap * v->itemSize);
273 } 277 }
274 v->len++; 278 v->len++;
275 return Vector_Get(v, v->len - 1); 279 return Vector_Get(v, v->len - 1);
276} 280}
277 281
278/* 282/*
279 * Remove the last item from the vector, return the pointer to it. 283 * Remove the last item from the vector, return the pointer to it.
280 * The returned data is valid until the next modifying operation. 284 * The returned data is valid until the next modifying operation.
281 */ 285 */
282void * 286void *
283Vector_Pop(Vector *v) 287Vector_Pop(Vector *v)
284{ 288{
285 assert(v->len > 0); 289 assert(v->len > 0);
286 v->len--; 290 v->len--;
287 return Vector_Get(v, v->len); 291 return Vector_Get(v, v->len);
288} 292}