1*b0c40a00SSimon J. Gerraty /* $NetBSD: lst.c,v 1.105 2021/03/15 16:45:30 rillig Exp $ */ 22c3632d1SSimon J. Gerraty 32c3632d1SSimon J. Gerraty /* 42c3632d1SSimon J. Gerraty * Copyright (c) 1988, 1989, 1990, 1993 52c3632d1SSimon J. Gerraty * The Regents of the University of California. All rights reserved. 62c3632d1SSimon J. Gerraty * 72c3632d1SSimon J. Gerraty * This code is derived from software contributed to Berkeley by 82c3632d1SSimon J. Gerraty * Adam de Boor. 92c3632d1SSimon J. Gerraty * 102c3632d1SSimon J. Gerraty * Redistribution and use in source and binary forms, with or without 112c3632d1SSimon J. Gerraty * modification, are permitted provided that the following conditions 122c3632d1SSimon J. Gerraty * are met: 132c3632d1SSimon J. Gerraty * 1. Redistributions of source code must retain the above copyright 142c3632d1SSimon J. Gerraty * notice, this list of conditions and the following disclaimer. 152c3632d1SSimon J. Gerraty * 2. Redistributions in binary form must reproduce the above copyright 162c3632d1SSimon J. Gerraty * notice, this list of conditions and the following disclaimer in the 172c3632d1SSimon J. Gerraty * documentation and/or other materials provided with the distribution. 182c3632d1SSimon J. Gerraty * 3. Neither the name of the University nor the names of its contributors 192c3632d1SSimon J. Gerraty * may be used to endorse or promote products derived from this software 202c3632d1SSimon J. Gerraty * without specific prior written permission. 212c3632d1SSimon J. Gerraty * 222c3632d1SSimon J. Gerraty * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 232c3632d1SSimon J. Gerraty * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 242c3632d1SSimon J. Gerraty * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 252c3632d1SSimon J. Gerraty * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 262c3632d1SSimon J. Gerraty * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 272c3632d1SSimon J. Gerraty * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 282c3632d1SSimon J. Gerraty * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 292c3632d1SSimon J. Gerraty * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 302c3632d1SSimon J. Gerraty * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 312c3632d1SSimon J. Gerraty * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 322c3632d1SSimon J. Gerraty * SUCH DAMAGE. 332c3632d1SSimon J. Gerraty */ 342c3632d1SSimon J. Gerraty 35956e45f6SSimon J. Gerraty #include "make.h" 36956e45f6SSimon J. Gerraty 37*b0c40a00SSimon J. Gerraty MAKE_RCSID("$NetBSD: lst.c,v 1.105 2021/03/15 16:45:30 rillig Exp $"); 382c3632d1SSimon J. Gerraty 39956e45f6SSimon J. Gerraty static ListNode * 40956e45f6SSimon J. Gerraty LstNodeNew(ListNode *prev, ListNode *next, void *datum) 412c3632d1SSimon J. Gerraty { 42e2eeea75SSimon J. Gerraty ListNode *ln = bmake_malloc(sizeof *ln); 4306b9b3e0SSimon J. Gerraty 44e2eeea75SSimon J. Gerraty ln->prev = prev; 45e2eeea75SSimon J. Gerraty ln->next = next; 46e2eeea75SSimon J. Gerraty ln->datum = datum; 4706b9b3e0SSimon J. Gerraty 48e2eeea75SSimon J. Gerraty return ln; 492c3632d1SSimon J. Gerraty } 502c3632d1SSimon J. Gerraty 512c3632d1SSimon J. Gerraty /* Create and initialize a new, empty list. */ 52956e45f6SSimon J. Gerraty List * 53956e45f6SSimon J. Gerraty Lst_New(void) 542c3632d1SSimon J. Gerraty { 55956e45f6SSimon J. Gerraty List *list = bmake_malloc(sizeof *list); 5606b9b3e0SSimon J. Gerraty Lst_Init(list); 572c3632d1SSimon J. Gerraty return list; 582c3632d1SSimon J. Gerraty } 592c3632d1SSimon J. Gerraty 602c3632d1SSimon J. Gerraty void 6106b9b3e0SSimon J. Gerraty Lst_Done(List *list) 622c3632d1SSimon J. Gerraty { 63e2eeea75SSimon J. Gerraty ListNode *ln, *next; 642c3632d1SSimon J. Gerraty 65e2eeea75SSimon J. Gerraty for (ln = list->first; ln != NULL; ln = next) { 66e2eeea75SSimon J. Gerraty next = ln->next; 67e2eeea75SSimon J. Gerraty free(ln); 682c3632d1SSimon J. Gerraty } 692c3632d1SSimon J. Gerraty } 702c3632d1SSimon J. Gerraty 712c3632d1SSimon J. Gerraty void 7206b9b3e0SSimon J. Gerraty Lst_DoneCall(List *list, LstFreeProc freeProc) 732c3632d1SSimon J. Gerraty { 74e2eeea75SSimon J. Gerraty ListNode *ln, *next; 752c3632d1SSimon J. Gerraty 76e2eeea75SSimon J. Gerraty for (ln = list->first; ln != NULL; ln = next) { 77e2eeea75SSimon J. Gerraty next = ln->next; 78e2eeea75SSimon J. Gerraty freeProc(ln->datum); 79e2eeea75SSimon J. Gerraty free(ln); 802c3632d1SSimon J. Gerraty } 8106b9b3e0SSimon J. Gerraty } 822c3632d1SSimon J. Gerraty 8306b9b3e0SSimon J. Gerraty /* Free a list and all its nodes. The node data are not freed though. */ 8406b9b3e0SSimon J. Gerraty void 8506b9b3e0SSimon J. Gerraty Lst_Free(List *list) 8606b9b3e0SSimon J. Gerraty { 8706b9b3e0SSimon J. Gerraty 8806b9b3e0SSimon J. Gerraty Lst_Done(list); 8906b9b3e0SSimon J. Gerraty free(list); 9006b9b3e0SSimon J. Gerraty } 9106b9b3e0SSimon J. Gerraty 92956e45f6SSimon J. Gerraty /* Insert a new node with the datum before the given node. */ 932c3632d1SSimon J. Gerraty void 94e2eeea75SSimon J. Gerraty Lst_InsertBefore(List *list, ListNode *ln, void *datum) 952c3632d1SSimon J. Gerraty { 96956e45f6SSimon J. Gerraty ListNode *newNode; 972c3632d1SSimon J. Gerraty 982c3632d1SSimon J. Gerraty assert(datum != NULL); 992c3632d1SSimon J. Gerraty 100e2eeea75SSimon J. Gerraty newNode = LstNodeNew(ln->prev, ln, datum); 1012c3632d1SSimon J. Gerraty 102e2eeea75SSimon J. Gerraty if (ln->prev != NULL) 103e2eeea75SSimon J. Gerraty ln->prev->next = newNode; 104e2eeea75SSimon J. Gerraty ln->prev = newNode; 1052c3632d1SSimon J. Gerraty 106e2eeea75SSimon J. Gerraty if (ln == list->first) 1072c3632d1SSimon J. Gerraty list->first = newNode; 1082c3632d1SSimon J. Gerraty } 1092c3632d1SSimon J. Gerraty 1102c3632d1SSimon J. Gerraty /* Add a piece of data at the start of the given list. */ 1112c3632d1SSimon J. Gerraty void 112956e45f6SSimon J. Gerraty Lst_Prepend(List *list, void *datum) 1132c3632d1SSimon J. Gerraty { 114e2eeea75SSimon J. Gerraty ListNode *ln; 1152c3632d1SSimon J. Gerraty 1162c3632d1SSimon J. Gerraty assert(datum != NULL); 1172c3632d1SSimon J. Gerraty 118e2eeea75SSimon J. Gerraty ln = LstNodeNew(NULL, list->first, datum); 1192c3632d1SSimon J. Gerraty 1202c3632d1SSimon J. Gerraty if (list->first == NULL) { 121e2eeea75SSimon J. Gerraty list->first = ln; 122e2eeea75SSimon J. Gerraty list->last = ln; 1232c3632d1SSimon J. Gerraty } else { 124e2eeea75SSimon J. Gerraty list->first->prev = ln; 125e2eeea75SSimon J. Gerraty list->first = ln; 1262c3632d1SSimon J. Gerraty } 1272c3632d1SSimon J. Gerraty } 1282c3632d1SSimon J. Gerraty 1292c3632d1SSimon J. Gerraty /* Add a piece of data at the end of the given list. */ 1302c3632d1SSimon J. Gerraty void 131956e45f6SSimon J. Gerraty Lst_Append(List *list, void *datum) 1322c3632d1SSimon J. Gerraty { 133e2eeea75SSimon J. Gerraty ListNode *ln; 1342c3632d1SSimon J. Gerraty 1352c3632d1SSimon J. Gerraty assert(datum != NULL); 1362c3632d1SSimon J. Gerraty 137e2eeea75SSimon J. Gerraty ln = LstNodeNew(list->last, NULL, datum); 1382c3632d1SSimon J. Gerraty 1392c3632d1SSimon J. Gerraty if (list->last == NULL) { 140e2eeea75SSimon J. Gerraty list->first = ln; 141e2eeea75SSimon J. Gerraty list->last = ln; 1422c3632d1SSimon J. Gerraty } else { 143e2eeea75SSimon J. Gerraty list->last->next = ln; 144e2eeea75SSimon J. Gerraty list->last = ln; 1452c3632d1SSimon J. Gerraty } 1462c3632d1SSimon J. Gerraty } 1472c3632d1SSimon J. Gerraty 14806b9b3e0SSimon J. Gerraty /* 14906b9b3e0SSimon J. Gerraty * Remove the given node from the given list. 15006b9b3e0SSimon J. Gerraty * The datum stored in the node must be freed by the caller, if necessary. 15106b9b3e0SSimon J. Gerraty */ 1522c3632d1SSimon J. Gerraty void 153e2eeea75SSimon J. Gerraty Lst_Remove(List *list, ListNode *ln) 1542c3632d1SSimon J. Gerraty { 155956e45f6SSimon J. Gerraty /* unlink it from its neighbors */ 156e2eeea75SSimon J. Gerraty if (ln->next != NULL) 157e2eeea75SSimon J. Gerraty ln->next->prev = ln->prev; 158e2eeea75SSimon J. Gerraty if (ln->prev != NULL) 159e2eeea75SSimon J. Gerraty ln->prev->next = ln->next; 1602c3632d1SSimon J. Gerraty 161956e45f6SSimon J. Gerraty /* unlink it from the list */ 162e2eeea75SSimon J. Gerraty if (list->first == ln) 163e2eeea75SSimon J. Gerraty list->first = ln->next; 164e2eeea75SSimon J. Gerraty if (list->last == ln) 165e2eeea75SSimon J. Gerraty list->last = ln->prev; 1662c3632d1SSimon J. Gerraty } 1672c3632d1SSimon J. Gerraty 1682c3632d1SSimon J. Gerraty /* Replace the datum in the given node with the new datum. */ 1692c3632d1SSimon J. Gerraty void 170e2eeea75SSimon J. Gerraty LstNode_Set(ListNode *ln, void *datum) 1712c3632d1SSimon J. Gerraty { 1722c3632d1SSimon J. Gerraty assert(datum != NULL); 1732c3632d1SSimon J. Gerraty 174e2eeea75SSimon J. Gerraty ln->datum = datum; 1752c3632d1SSimon J. Gerraty } 1762c3632d1SSimon J. Gerraty 17706b9b3e0SSimon J. Gerraty /* 17806b9b3e0SSimon J. Gerraty * Replace the datum in the given node with NULL. 17906b9b3e0SSimon J. Gerraty * Having NULL values in a list is unusual though. 18006b9b3e0SSimon J. Gerraty */ 1812c3632d1SSimon J. Gerraty void 182e2eeea75SSimon J. Gerraty LstNode_SetNull(ListNode *ln) 1832c3632d1SSimon J. Gerraty { 184e2eeea75SSimon J. Gerraty ln->datum = NULL; 1852c3632d1SSimon J. Gerraty } 1862c3632d1SSimon J. Gerraty 18706b9b3e0SSimon J. Gerraty /* 18806b9b3e0SSimon J. Gerraty * Return the first node that contains the given datum, or NULL. 189e2eeea75SSimon J. Gerraty * 19006b9b3e0SSimon J. Gerraty * Time complexity: O(length(list)) 19106b9b3e0SSimon J. Gerraty */ 192956e45f6SSimon J. Gerraty ListNode * 193956e45f6SSimon J. Gerraty Lst_FindDatum(List *list, const void *datum) 1942c3632d1SSimon J. Gerraty { 195e2eeea75SSimon J. Gerraty ListNode *ln; 1962c3632d1SSimon J. Gerraty 1972c3632d1SSimon J. Gerraty assert(datum != NULL); 1982c3632d1SSimon J. Gerraty 199e2eeea75SSimon J. Gerraty for (ln = list->first; ln != NULL; ln = ln->next) 200e2eeea75SSimon J. Gerraty if (ln->datum == datum) 201e2eeea75SSimon J. Gerraty return ln; 2022c3632d1SSimon J. Gerraty 2032c3632d1SSimon J. Gerraty return NULL; 2042c3632d1SSimon J. Gerraty } 2052c3632d1SSimon J. Gerraty 20606b9b3e0SSimon J. Gerraty /* 20706b9b3e0SSimon J. Gerraty * Move all nodes from src to the end of dst. 208*b0c40a00SSimon J. Gerraty * The source list becomes indeterminate. 20906b9b3e0SSimon J. Gerraty */ 2102c3632d1SSimon J. Gerraty void 211e2eeea75SSimon J. Gerraty Lst_MoveAll(List *dst, List *src) 2122c3632d1SSimon J. Gerraty { 213e2eeea75SSimon J. Gerraty if (src->first != NULL) { 214e2eeea75SSimon J. Gerraty src->first->prev = dst->last; 215e2eeea75SSimon J. Gerraty if (dst->last != NULL) 216e2eeea75SSimon J. Gerraty dst->last->next = src->first; 217956e45f6SSimon J. Gerraty else 218e2eeea75SSimon J. Gerraty dst->first = src->first; 219956e45f6SSimon J. Gerraty 220e2eeea75SSimon J. Gerraty dst->last = src->last; 2212c3632d1SSimon J. Gerraty } 222*b0c40a00SSimon J. Gerraty #ifdef CLEANUP 223*b0c40a00SSimon J. Gerraty src->first = NULL; 224*b0c40a00SSimon J. Gerraty src->last = NULL; 225*b0c40a00SSimon J. Gerraty #endif 2262c3632d1SSimon J. Gerraty } 2272c3632d1SSimon J. Gerraty 2282c3632d1SSimon J. Gerraty /* Copy the element data from src to the start of dst. */ 2292c3632d1SSimon J. Gerraty void 230956e45f6SSimon J. Gerraty Lst_PrependAll(List *dst, List *src) 2312c3632d1SSimon J. Gerraty { 23206b9b3e0SSimon J. Gerraty ListNode *ln; 23306b9b3e0SSimon J. Gerraty 23406b9b3e0SSimon J. Gerraty for (ln = src->last; ln != NULL; ln = ln->prev) 23506b9b3e0SSimon J. Gerraty Lst_Prepend(dst, ln->datum); 2362c3632d1SSimon J. Gerraty } 2372c3632d1SSimon J. Gerraty 2382c3632d1SSimon J. Gerraty /* Copy the element data from src to the end of dst. */ 2392c3632d1SSimon J. Gerraty void 240956e45f6SSimon J. Gerraty Lst_AppendAll(List *dst, List *src) 2412c3632d1SSimon J. Gerraty { 24206b9b3e0SSimon J. Gerraty ListNode *ln; 2432c3632d1SSimon J. Gerraty 24406b9b3e0SSimon J. Gerraty for (ln = src->first; ln != NULL; ln = ln->next) 24506b9b3e0SSimon J. Gerraty Lst_Append(dst, ln->datum); 2462c3632d1SSimon J. Gerraty } 2472c3632d1SSimon J. Gerraty 2482c3632d1SSimon J. Gerraty /* Remove and return the datum at the head of the given list. */ 2492c3632d1SSimon J. Gerraty void * 250956e45f6SSimon J. Gerraty Lst_Dequeue(List *list) 2512c3632d1SSimon J. Gerraty { 252956e45f6SSimon J. Gerraty void *datum = list->first->datum; 2532c3632d1SSimon J. Gerraty Lst_Remove(list, list->first); 254956e45f6SSimon J. Gerraty assert(datum != NULL); /* since NULL would mean end of the list */ 2552c3632d1SSimon J. Gerraty return datum; 2562c3632d1SSimon J. Gerraty } 257956e45f6SSimon J. Gerraty 258956e45f6SSimon J. Gerraty void 259956e45f6SSimon J. Gerraty Vector_Init(Vector *v, size_t itemSize) 260956e45f6SSimon J. Gerraty { 261956e45f6SSimon J. Gerraty v->len = 0; 26206b9b3e0SSimon J. Gerraty v->cap = 10; 263956e45f6SSimon J. Gerraty v->itemSize = itemSize; 26406b9b3e0SSimon J. Gerraty v->items = bmake_malloc(v->cap * v->itemSize); 265956e45f6SSimon J. Gerraty } 266956e45f6SSimon J. Gerraty 26706b9b3e0SSimon J. Gerraty /* 26806b9b3e0SSimon J. Gerraty * Add space for a new item to the vector and return a pointer to that space. 26906b9b3e0SSimon J. Gerraty * The returned data is valid until the next modifying operation. 27006b9b3e0SSimon J. Gerraty */ 271956e45f6SSimon J. Gerraty void * 272956e45f6SSimon J. Gerraty Vector_Push(Vector *v) 273956e45f6SSimon J. Gerraty { 27406b9b3e0SSimon J. Gerraty if (v->len >= v->cap) { 27506b9b3e0SSimon J. Gerraty v->cap *= 2; 27606b9b3e0SSimon J. Gerraty v->items = bmake_realloc(v->items, v->cap * v->itemSize); 277956e45f6SSimon J. Gerraty } 278956e45f6SSimon J. Gerraty v->len++; 279956e45f6SSimon J. Gerraty return Vector_Get(v, v->len - 1); 280956e45f6SSimon J. Gerraty } 281956e45f6SSimon J. Gerraty 28206b9b3e0SSimon J. Gerraty /* 283dba7b0efSSimon J. Gerraty * Remove the last item from the vector, return the pointer to it. 28406b9b3e0SSimon J. Gerraty * The returned data is valid until the next modifying operation. 28506b9b3e0SSimon J. Gerraty */ 286956e45f6SSimon J. Gerraty void * 287956e45f6SSimon J. Gerraty Vector_Pop(Vector *v) 288956e45f6SSimon J. Gerraty { 289956e45f6SSimon J. Gerraty assert(v->len > 0); 290956e45f6SSimon J. Gerraty v->len--; 291956e45f6SSimon J. Gerraty return Vector_Get(v, v->len); 292956e45f6SSimon J. Gerraty } 293