/* $NetBSD: lst.c,v 1.108 2024/04/27 17:33:46 rillig Exp $ */12/*3* Copyright (c) 1988, 1989, 1990, 19934* The Regents of the University of California. All rights reserved.5*6* This code is derived from software contributed to Berkeley by7* Adam de Boor.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17* 3. Neither the name of the University nor the names of its contributors18* may be used to endorse or promote products derived from this software19* without specific prior written permission.20*21* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND22* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE23* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE24* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE25* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL26* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS27* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)28* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT29* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY30* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF31* SUCH DAMAGE.32*/3334#include "make.h"3536MAKE_RCSID("$NetBSD: lst.c,v 1.108 2024/04/27 17:33:46 rillig Exp $");3738static ListNode *39LstNodeNew(ListNode *prev, ListNode *next, void *datum)40{41ListNode *ln = bmake_malloc(sizeof *ln);4243ln->prev = prev;44ln->next = next;45ln->datum = datum;4647return ln;48}4950void51Lst_Done(List *list)52{53ListNode *ln, *next;5455for (ln = list->first; ln != NULL; ln = next) {56next = ln->next;57free(ln);58}59}6061void62Lst_DoneFree(List *list)63{64ListNode *ln, *next;6566for (ln = list->first; ln != NULL; ln = next) {67next = ln->next;68free(ln->datum);69free(ln);70}71}7273/* Insert a new node with the datum before the given node. */74void75Lst_InsertBefore(List *list, ListNode *ln, void *datum)76{77ListNode *newNode;7879assert(datum != NULL);8081newNode = LstNodeNew(ln->prev, ln, datum);8283if (ln->prev != NULL)84ln->prev->next = newNode;85ln->prev = newNode;8687if (ln == list->first)88list->first = newNode;89}9091/* Add a piece of data at the start of the given list. */92void93Lst_Prepend(List *list, void *datum)94{95ListNode *ln;9697assert(datum != NULL);9899ln = LstNodeNew(NULL, list->first, datum);100101if (list->first == NULL) {102list->first = ln;103list->last = ln;104} else {105list->first->prev = ln;106list->first = ln;107}108}109110/* Add a piece of data at the end of the given list. */111void112Lst_Append(List *list, void *datum)113{114ListNode *ln;115116assert(datum != NULL);117118ln = LstNodeNew(list->last, NULL, datum);119120if (list->last == NULL) {121list->first = ln;122list->last = ln;123} else {124list->last->next = ln;125list->last = ln;126}127}128129/*130* Remove the given node from the given list.131* The datum stored in the node must be freed by the caller, if necessary.132*/133void134Lst_Remove(List *list, ListNode *ln)135{136/* unlink it from its neighbors */137if (ln->next != NULL)138ln->next->prev = ln->prev;139if (ln->prev != NULL)140ln->prev->next = ln->next;141142/* unlink it from the list */143if (list->first == ln)144list->first = ln->next;145if (list->last == ln)146list->last = ln->prev;147148free(ln);149}150151/* Replace the datum in the given node with the new datum. */152void153LstNode_Set(ListNode *ln, void *datum)154{155assert(datum != NULL);156157ln->datum = datum;158}159160/*161* Replace the datum in the given node with NULL.162* Having NULL values in a list is unusual though.163*/164void165LstNode_SetNull(ListNode *ln)166{167ln->datum = NULL;168}169170/*171* Return the first node that contains the given datum, or NULL.172*173* Time complexity: O(length(list))174*/175ListNode *176Lst_FindDatum(List *list, const void *datum)177{178ListNode *ln;179180assert(datum != NULL);181182for (ln = list->first; ln != NULL; ln = ln->next)183if (ln->datum == datum)184return ln;185186return NULL;187}188189/*190* Move all nodes from src to the end of dst.191* The source list becomes indeterminate.192*/193void194Lst_MoveAll(List *dst, List *src)195{196if (src->first != NULL) {197src->first->prev = dst->last;198if (dst->last != NULL)199dst->last->next = src->first;200else201dst->first = src->first;202203dst->last = src->last;204}205#ifdef CLEANUP206src->first = NULL;207src->last = NULL;208#endif209}210211/* Copy the element data from src to the start of dst. */212void213Lst_PrependAll(List *dst, List *src)214{215ListNode *ln;216217for (ln = src->last; ln != NULL; ln = ln->prev)218Lst_Prepend(dst, ln->datum);219}220221/* Copy the element data from src to the end of dst. */222void223Lst_AppendAll(List *dst, List *src)224{225ListNode *ln;226227for (ln = src->first; ln != NULL; ln = ln->next)228Lst_Append(dst, ln->datum);229}230231/* Remove and return the datum at the head of the given list. */232void *233Lst_Dequeue(List *list)234{235void *datum = list->first->datum;236Lst_Remove(list, list->first);237assert(datum != NULL); /* since NULL would mean end of the list */238return datum;239}240241void242Vector_Init(Vector *v, size_t itemSize)243{244v->len = 0;245v->cap = 10;246v->itemSize = itemSize;247v->items = bmake_malloc(v->cap * v->itemSize);248}249250/*251* Add space for a new item to the vector and return a pointer to that space.252* The returned data is valid until the next modifying operation.253*/254void *255Vector_Push(Vector *v)256{257if (v->len >= v->cap) {258v->cap *= 2;259v->items = bmake_realloc(v->items, v->cap * v->itemSize);260}261v->len++;262return Vector_Get(v, v->len - 1);263}264265/*266* Remove the last item from the vector, return the pointer to it.267* The returned data is valid until the next modifying operation.268*/269void *270Vector_Pop(Vector *v)271{272assert(v->len > 0);273v->len--;274return Vector_Get(v, v->len);275}276277278