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