xref: /freebsd/contrib/bmake/lst.c (revision b0c40a00a67f611868fc0f10bde6b28eb75931be)
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