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