lst.c revision 1.67
11.67Srillig/* $NetBSD: lst.c,v 1.67 2020/09/24 07:11:29 rillig Exp $ */ 21.1Srillig 31.1Srillig/* 41.1Srillig * Copyright (c) 1988, 1989, 1990, 1993 51.1Srillig * The Regents of the University of California. All rights reserved. 61.1Srillig * 71.1Srillig * This code is derived from software contributed to Berkeley by 81.1Srillig * Adam de Boor. 91.1Srillig * 101.1Srillig * Redistribution and use in source and binary forms, with or without 111.1Srillig * modification, are permitted provided that the following conditions 121.1Srillig * are met: 131.1Srillig * 1. Redistributions of source code must retain the above copyright 141.1Srillig * notice, this list of conditions and the following disclaimer. 151.1Srillig * 2. Redistributions in binary form must reproduce the above copyright 161.1Srillig * notice, this list of conditions and the following disclaimer in the 171.1Srillig * documentation and/or other materials provided with the distribution. 181.1Srillig * 3. Neither the name of the University nor the names of its contributors 191.1Srillig * may be used to endorse or promote products derived from this software 201.1Srillig * without specific prior written permission. 211.1Srillig * 221.1Srillig * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231.1Srillig * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241.1Srillig * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251.1Srillig * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261.1Srillig * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271.1Srillig * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281.1Srillig * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291.1Srillig * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301.1Srillig * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311.1Srillig * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321.1Srillig * SUCH DAMAGE. 331.1Srillig */ 341.1Srillig 351.30Sskrll#include <stdint.h> 361.8Srillig 371.19Srillig#include "make.h" 381.1Srillig 391.67SrilligMAKE_RCSID("$NetBSD: lst.c,v 1.67 2020/09/24 07:11:29 rillig Exp $"); 401.1Srillig 411.13Srilligstruct ListNode { 421.15Srillig struct ListNode *prev; /* previous element in list */ 431.15Srillig struct ListNode *next; /* next in list */ 441.7Srillig uint8_t useCount; /* Count of functions using the node. 451.4Srillig * node may not be deleted until count 461.4Srillig * goes to 0 */ 471.7Srillig Boolean deleted; /* List node should be removed when done */ 481.39Srillig union { 491.39Srillig void *datum; /* datum associated with this element */ 501.39Srillig const GNode *gnode; /* alias, just for debugging */ 511.39Srillig const char *str; /* alias, just for debugging */ 521.39Srillig }; 531.13Srillig}; 541.1Srillig 551.1Srilligtypedef enum { 561.1Srillig Head, Middle, Tail, Unknown 571.1Srillig} Where; 581.1Srillig 591.13Srilligstruct List { 601.65Srillig ListNode *first; /* first node in list */ 611.65Srillig ListNode *last; /* last node in list */ 621.20Srillig 631.20Srillig /* fields for sequential access */ 641.21Srillig Boolean isOpen; /* true if list has been Lst_Open'ed */ 651.15Srillig Where lastAccess; /* Where in the list the last access was */ 661.65Srillig ListNode *curr; /* current node, if open. NULL if 671.4Srillig * *just* opened */ 681.65Srillig ListNode *prev; /* Previous node, if open. Used by Lst_Remove */ 691.13Srillig}; 701.1Srillig 711.22Srillig/* Allocate and initialize a list node. 721.22Srillig * 731.22Srillig * The fields 'prev' and 'next' must be initialized by the caller. 741.22Srillig */ 751.65Srilligstatic ListNode * 761.12SrilligLstNodeNew(void *datum) 771.12Srillig{ 781.65Srillig ListNode *node = bmake_malloc(sizeof *node); 791.16Srillig node->useCount = 0; 801.16Srillig node->deleted = FALSE; 811.16Srillig node->datum = datum; 821.16Srillig return node; 831.12Srillig} 841.12Srillig 851.2Srilligstatic Boolean 861.65SrilligLstIsEmpty(List *list) 871.2Srillig{ 881.16Srillig return list->first == NULL; 891.2Srillig} 901.1Srillig 911.5Srillig/* Create and initialize a new, empty list. */ 921.65SrilligList * 931.5SrilligLst_Init(void) 941.1Srillig{ 951.65Srillig List *list = bmake_malloc(sizeof *list); 961.1Srillig 971.16Srillig list->first = NULL; 981.16Srillig list->last = NULL; 991.16Srillig list->isOpen = FALSE; 1001.16Srillig list->lastAccess = Unknown; 1011.1Srillig 1021.16Srillig return list; 1031.1Srillig} 1041.1Srillig 1051.14Srillig/* Duplicate an entire list, usually by copying the datum pointers. 1061.14Srillig * If copyProc is given, that function is used to create the new datum from the 1071.35Srillig * old datum, usually by creating a copy of it. */ 1081.65SrilligList * 1091.65SrilligLst_Copy(List *list, LstCopyProc copyProc) 1101.1Srillig{ 1111.65Srillig List *newList; 1121.65Srillig ListNode *node; 1131.1Srillig 1141.52Srillig assert(list != NULL); 1151.1Srillig 1161.16Srillig newList = Lst_Init(); 1171.1Srillig 1181.35Srillig for (node = list->first; node != NULL; node = node->next) { 1191.35Srillig void *datum = copyProc != NULL ? copyProc(node->datum) : node->datum; 1201.50Srillig Lst_Append(newList, datum); 1211.1Srillig } 1221.1Srillig 1231.16Srillig return newList; 1241.1Srillig} 1251.1Srillig 1261.42Srillig/* Free a list and all its nodes. The list data itself are not freed though. */ 1271.42Srilligvoid 1281.65SrilligLst_Free(List *list) 1291.42Srillig{ 1301.65Srillig ListNode *node; 1311.65Srillig ListNode *next; 1321.42Srillig 1331.52Srillig assert(list != NULL); 1341.42Srillig 1351.42Srillig for (node = list->first; node != NULL; node = next) { 1361.42Srillig next = node->next; 1371.42Srillig free(node); 1381.42Srillig } 1391.42Srillig 1401.42Srillig free(list); 1411.42Srillig} 1421.42Srillig 1431.59Srillig/* Destroy a list and free all its resources. The freeProc is called with the 1441.59Srillig * datum from each node in turn before the node is freed. */ 1451.1Srilligvoid 1461.65SrilligLst_Destroy(List *list, LstFreeProc freeProc) 1471.1Srillig{ 1481.65Srillig ListNode *node; 1491.65Srillig ListNode *next; 1501.1Srillig 1511.52Srillig assert(list != NULL); 1521.42Srillig assert(freeProc != NULL); 1531.1Srillig 1541.42Srillig for (node = list->first; node != NULL; node = next) { 1551.42Srillig next = node->next; 1561.42Srillig freeProc(node->datum); 1571.42Srillig free(node); 1581.1Srillig } 1591.1Srillig 1601.1Srillig free(list); 1611.1Srillig} 1621.1Srillig 1631.1Srillig/* 1641.1Srillig * Functions to modify a list 1651.1Srillig */ 1661.1Srillig 1671.14Srillig/* Insert a new node with the given piece of data before the given node in the 1681.14Srillig * given list. */ 1691.26Srilligvoid 1701.65SrilligLst_InsertBefore(List *list, ListNode *node, void *datum) 1711.26Srillig{ 1721.65Srillig ListNode *newNode; 1731.26Srillig 1741.52Srillig assert(list != NULL); 1751.26Srillig assert(!LstIsEmpty(list)); 1761.52Srillig assert(node != NULL); 1771.26Srillig assert(datum != NULL); 1781.26Srillig 1791.26Srillig newNode = LstNodeNew(datum); 1801.26Srillig newNode->prev = node->prev; 1811.26Srillig newNode->next = node; 1821.26Srillig 1831.26Srillig if (node->prev != NULL) { 1841.26Srillig node->prev->next = newNode; 1851.26Srillig } 1861.26Srillig node->prev = newNode; 1871.26Srillig 1881.26Srillig if (node == list->first) { 1891.26Srillig list->first = newNode; 1901.26Srillig } 1911.26Srillig} 1921.26Srillig 1931.22Srillig/* Add a piece of data at the start of the given list. */ 1941.22Srilligvoid 1951.65SrilligLst_Prepend(List *list, void *datum) 1961.22Srillig{ 1971.65Srillig ListNode *node; 1981.22Srillig 1991.52Srillig assert(list != NULL); 2001.22Srillig assert(datum != NULL); 2011.22Srillig 2021.22Srillig node = LstNodeNew(datum); 2031.22Srillig node->prev = NULL; 2041.22Srillig node->next = list->first; 2051.22Srillig 2061.22Srillig if (list->first == NULL) { 2071.22Srillig list->first = node; 2081.22Srillig list->last = node; 2091.22Srillig } else { 2101.22Srillig list->first->prev = node; 2111.22Srillig list->first = node; 2121.22Srillig } 2131.22Srillig} 2141.22Srillig 2151.21Srillig/* Add a piece of data at the end of the given list. */ 2161.21Srilligvoid 2171.65SrilligLst_Append(List *list, void *datum) 2181.21Srillig{ 2191.65Srillig ListNode *node; 2201.21Srillig 2211.52Srillig assert(list != NULL); 2221.21Srillig assert(datum != NULL); 2231.21Srillig 2241.21Srillig node = LstNodeNew(datum); 2251.21Srillig node->prev = list->last; 2261.21Srillig node->next = NULL; 2271.21Srillig 2281.21Srillig if (list->last == NULL) { 2291.21Srillig list->first = node; 2301.21Srillig list->last = node; 2311.21Srillig } else { 2321.21Srillig list->last->next = node; 2331.21Srillig list->last = node; 2341.21Srillig } 2351.21Srillig} 2361.21Srillig 2371.8Srillig/* Remove the given node from the given list. 2381.8Srillig * The datum stored in the node must be freed by the caller, if necessary. */ 2391.8Srilligvoid 2401.65SrilligLst_Remove(List *list, ListNode *node) 2411.1Srillig{ 2421.52Srillig assert(list != NULL); 2431.52Srillig assert(node != NULL); 2441.1Srillig 2451.1Srillig /* 2461.1Srillig * unlink it from the list 2471.1Srillig */ 2481.16Srillig if (node->next != NULL) { 2491.16Srillig node->next->prev = node->prev; 2501.1Srillig } 2511.16Srillig if (node->prev != NULL) { 2521.16Srillig node->prev->next = node->next; 2531.1Srillig } 2541.1Srillig 2551.1Srillig /* 2561.15Srillig * if either the first or last of the list point to this node, 2571.1Srillig * adjust them accordingly 2581.1Srillig */ 2591.16Srillig if (list->first == node) { 2601.16Srillig list->first = node->next; 2611.1Srillig } 2621.16Srillig if (list->last == node) { 2631.16Srillig list->last = node->prev; 2641.1Srillig } 2651.1Srillig 2661.1Srillig /* 2671.1Srillig * Sequential access stuff. If the node we're removing is the current 2681.1Srillig * node in the list, reset the current node to the previous one. If the 2691.15Srillig * previous one was non-existent (prev == NULL), we set the 2701.1Srillig * end to be Unknown, since it is. 2711.1Srillig */ 2721.16Srillig if (list->isOpen && list->curr == node) { 2731.15Srillig list->curr = list->prev; 2741.15Srillig if (list->curr == NULL) { 2751.15Srillig list->lastAccess = Unknown; 2761.1Srillig } 2771.1Srillig } 2781.1Srillig 2791.1Srillig /* 2801.1Srillig * note that the datum is unmolested. The caller must free it as 2811.1Srillig * necessary and as expected. 2821.1Srillig */ 2831.16Srillig if (node->useCount == 0) { 2841.16Srillig free(node); 2851.1Srillig } else { 2861.16Srillig node->deleted = TRUE; 2871.1Srillig } 2881.1Srillig} 2891.1Srillig 2901.8Srillig/* Replace the datum in the given node with the new datum. */ 2911.8Srilligvoid 2921.65SrilligLstNode_Set(ListNode *node, void *datum) 2931.1Srillig{ 2941.52Srillig assert(node != NULL); 2951.37Srillig assert(datum != NULL); 2961.37Srillig 2971.16Srillig node->datum = datum; 2981.1Srillig} 2991.1Srillig 3001.37Srillig/* Replace the datum in the given node to NULL. */ 3011.37Srilligvoid 3021.65SrilligLstNode_SetNull(ListNode *node) 3031.37Srillig{ 3041.52Srillig assert(node != NULL); 3051.37Srillig 3061.37Srillig node->datum = NULL; 3071.37Srillig} 3081.37Srillig 3091.1Srillig 3101.1Srillig/* 3111.1Srillig * Node-specific functions 3121.1Srillig */ 3131.1Srillig 3141.42Srillig/* Return the first node from the given list, or NULL if the list is empty. */ 3151.65SrilligListNode * 3161.65SrilligLst_First(List *list) 3171.42Srillig{ 3181.52Srillig assert(list != NULL); 3191.42Srillig 3201.42Srillig return list->first; 3211.42Srillig} 3221.42Srillig 3231.42Srillig/* Return the last node from the given list, or NULL if the list is empty. */ 3241.65SrilligListNode * 3251.65SrilligLst_Last(List *list) 3261.42Srillig{ 3271.52Srillig assert(list != NULL); 3281.42Srillig 3291.42Srillig return list->last; 3301.42Srillig} 3311.42Srillig 3321.6Srillig/* Return the successor to the given node on its list, or NULL. */ 3331.65SrilligListNode * 3341.65SrilligLstNode_Next(ListNode *node) 3351.42Srillig{ 3361.52Srillig assert(node != NULL); 3371.42Srillig 3381.42Srillig return node->next; 3391.42Srillig} 3401.42Srillig 3411.6Srillig/* Return the predecessor to the given node on its list, or NULL. */ 3421.65SrilligListNode * 3431.65SrilligLstNode_Prev(ListNode *node) 3441.1Srillig{ 3451.52Srillig assert(node != NULL); 3461.33Srillig return node->prev; 3471.1Srillig} 3481.1Srillig 3491.28Srillig/* Return the datum stored in the given node. */ 3501.1Srilligvoid * 3511.65SrilligLstNode_Datum(ListNode *node) 3521.1Srillig{ 3531.52Srillig assert(node != NULL); 3541.28Srillig return node->datum; 3551.1Srillig} 3561.1Srillig 3571.1Srillig 3581.1Srillig/* 3591.1Srillig * Functions for entire lists 3601.1Srillig */ 3611.1Srillig 3621.42Srillig/* Return TRUE if the given list is empty. */ 3631.42SrilligBoolean 3641.65SrilligLst_IsEmpty(List *list) 3651.42Srillig{ 3661.52Srillig assert(list != NULL); 3671.42Srillig 3681.42Srillig return LstIsEmpty(list); 3691.42Srillig} 3701.42Srillig 3711.53Srillig/* Return the first node from the list for which the match function returns 3721.53Srillig * TRUE, or NULL if none of the nodes matched. */ 3731.65SrilligListNode * 3741.65SrilligLst_Find(List *list, LstFindProc match, const void *matchArgs) 3751.53Srillig{ 3761.55Srillig return Lst_FindFrom(list, Lst_First(list), match, matchArgs); 3771.53Srillig} 3781.53Srillig 3791.53Srillig/* Return the first node from the list, starting at the given node, for which 3801.53Srillig * the match function returns TRUE, or NULL if none of the nodes matches. 3811.53Srillig * 3821.53Srillig * The start node may be NULL, in which case nothing is found. This allows 3831.56Srillig * for passing Lst_First or LstNode_Next as the start node. */ 3841.65SrilligListNode * 3851.65SrilligLst_FindFrom(List *list, ListNode *node, LstFindProc match, const void *matchArgs) 3861.53Srillig{ 3871.65Srillig ListNode *tln; 3881.53Srillig 3891.53Srillig assert(list != NULL); 3901.53Srillig assert(match != NULL); 3911.53Srillig 3921.53Srillig for (tln = node; tln != NULL; tln = tln->next) { 3931.53Srillig if (match(tln->datum, matchArgs)) 3941.53Srillig return tln; 3951.53Srillig } 3961.53Srillig 3971.53Srillig return NULL; 3981.53Srillig} 3991.53Srillig 4001.14Srillig/* Return the first node that contains the given datum, or NULL. */ 4011.65SrilligListNode * 4021.65SrilligLst_FindDatum(List *list, const void *datum) 4031.1Srillig{ 4041.65Srillig ListNode *node; 4051.1Srillig 4061.52Srillig assert(list != NULL); 4071.29Srillig assert(datum != NULL); 4081.1Srillig 4091.29Srillig for (node = list->first; node != NULL; node = node->next) { 4101.16Srillig if (node->datum == datum) { 4111.16Srillig return node; 4121.1Srillig } 4131.29Srillig } 4141.1Srillig 4151.1Srillig return NULL; 4161.1Srillig} 4171.1Srillig 4181.67Srilligstatic int Lst_ForEachFrom(List *, ListNode *, LstActionUntilProc, void *); 4191.66Srillig 4201.14Srillig/* Apply the given function to each element of the given list. The function 4211.14Srillig * should return 0 if traversal should continue and non-zero if it should 4221.14Srillig * abort. */ 4231.1Srilligint 4241.67SrilligLst_ForEachUntil(List *list, LstActionUntilProc proc, void *procData) 4251.42Srillig{ 4261.42Srillig if (LstIsEmpty(list)) 4271.42Srillig return 0; /* XXX: Document what this value means. */ 4281.50Srillig return Lst_ForEachFrom(list, Lst_First(list), proc, procData); 4291.42Srillig} 4301.42Srillig 4311.14Srillig/* Apply the given function to each element of the given list, starting from 4321.14Srillig * the given node. The function should return 0 if traversal should continue, 4331.14Srillig * and non-zero if it should abort. */ 4341.1Srilligint 4351.65SrilligLst_ForEachFrom(List *list, ListNode *node, 4361.67Srillig LstActionUntilProc proc, void *procData) 4371.1Srillig{ 4381.65Srillig ListNode *tln = node; 4391.65Srillig ListNode *next; 4401.4Srillig Boolean done; 4411.4Srillig int result; 4421.1Srillig 4431.52Srillig assert(list != NULL); 4441.52Srillig assert(node != NULL); 4451.42Srillig assert(proc != NULL); 4461.1Srillig 4471.1Srillig do { 4481.1Srillig /* 4491.1Srillig * Take care of having the current element deleted out from under 4501.1Srillig * us. 4511.1Srillig */ 4521.1Srillig 4531.15Srillig next = tln->next; 4541.1Srillig 4551.1Srillig /* 4561.1Srillig * We're done with the traversal if 4571.38Srillig * - the next node to examine doesn't exist and 4581.1Srillig * - nothing's been added after the current node (check this 4591.1Srillig * after proc() has been called). 4601.1Srillig */ 4611.38Srillig done = next == NULL; 4621.1Srillig 4631.17Srillig tln->useCount++; 4641.16Srillig result = (*proc)(tln->datum, procData); 4651.17Srillig tln->useCount--; 4661.1Srillig 4671.1Srillig /* 4681.1Srillig * Now check whether a node has been added. 4691.1Srillig * Note: this doesn't work if this node was deleted before 4701.1Srillig * the new node was added. 4711.1Srillig */ 4721.15Srillig if (next != tln->next) { 4731.15Srillig next = tln->next; 4741.4Srillig done = 0; 4751.1Srillig } 4761.1Srillig 4771.7Srillig if (tln->deleted) { 4781.1Srillig free((char *)tln); 4791.1Srillig } 4801.1Srillig tln = next; 4811.1Srillig } while (!result && !LstIsEmpty(list) && !done); 4821.1Srillig 4831.1Srillig return result; 4841.1Srillig} 4851.1Srillig 4861.34Srillig/* Move all nodes from list2 to the end of list1. 4871.34Srillig * List2 is destroyed and freed. */ 4881.34Srilligvoid 4891.65SrilligLst_MoveAll(List *list1, List *list2) 4901.1Srillig{ 4911.52Srillig assert(list1 != NULL); 4921.52Srillig assert(list2 != NULL); 4931.1Srillig 4941.34Srillig if (list2->first != NULL) { 4951.34Srillig list2->first->prev = list1->last; 4961.34Srillig if (list1->last != NULL) { 4971.34Srillig list1->last->next = list2->first; 4981.34Srillig } else { 4991.34Srillig list1->first = list2->first; 5001.1Srillig } 5011.34Srillig list1->last = list2->last; 5021.1Srillig } 5031.34Srillig free(list2); 5041.1Srillig} 5051.1Srillig 5061.22Srillig/* Copy the element data from src to the start of dst. */ 5071.22Srilligvoid 5081.65SrilligLst_PrependAll(List *dst, List *src) 5091.22Srillig{ 5101.65Srillig ListNode *node; 5111.22Srillig for (node = src->last; node != NULL; node = node->prev) 5121.50Srillig Lst_Prepend(dst, node->datum); 5131.22Srillig} 5141.22Srillig 5151.22Srillig/* Copy the element data from src to the end of dst. */ 5161.22Srilligvoid 5171.65SrilligLst_AppendAll(List *dst, List *src) 5181.22Srillig{ 5191.65Srillig ListNode *node; 5201.22Srillig for (node = src->first; node != NULL; node = node->next) 5211.50Srillig Lst_Append(dst, node->datum); 5221.22Srillig} 5231.1Srillig 5241.1Srillig/* 5251.1Srillig * these functions are for dealing with a list as a table, of sorts. 5261.1Srillig * An idea of the "current element" is kept and used by all the functions 5271.1Srillig * between Lst_Open() and Lst_Close(). 5281.1Srillig * 5291.1Srillig * The sequential functions access the list in a slightly different way. 5301.1Srillig * CurPtr points to their idea of the current node in the list and they 5311.1Srillig * access the list based on it. 5321.1Srillig */ 5331.1Srillig 5341.14Srillig/* Open a list for sequential access. A list can still be searched, etc., 5351.14Srillig * without confusing these functions. */ 5361.10Srilligvoid 5371.65SrilligLst_Open(List *list) 5381.10Srillig{ 5391.52Srillig assert(list != NULL); 5401.60Srillig assert(!list->isOpen); 5411.10Srillig 5421.16Srillig list->isOpen = TRUE; 5431.16Srillig list->lastAccess = LstIsEmpty(list) ? Head : Unknown; 5441.16Srillig list->curr = NULL; 5451.10Srillig} 5461.10Srillig 5471.10Srillig/* Return the next node for the given list, or NULL if the end has been 5481.10Srillig * reached. */ 5491.65SrilligListNode * 5501.65SrilligLst_Next(List *list) 5511.1Srillig{ 5521.65Srillig ListNode *node; 5531.1Srillig 5541.52Srillig assert(list != NULL); 5551.9Srillig assert(list->isOpen); 5561.1Srillig 5571.15Srillig list->prev = list->curr; 5581.1Srillig 5591.15Srillig if (list->curr == NULL) { 5601.15Srillig if (list->lastAccess == Unknown) { 5611.1Srillig /* 5621.15Srillig * If we're just starting out, lastAccess will be Unknown. 5631.1Srillig * Then we want to start this thing off in the right 5641.15Srillig * direction -- at the start with lastAccess being Middle. 5651.1Srillig */ 5661.16Srillig list->curr = node = list->first; 5671.15Srillig list->lastAccess = Middle; 5681.1Srillig } else { 5691.16Srillig node = NULL; 5701.15Srillig list->lastAccess = Tail; 5711.1Srillig } 5721.1Srillig } else { 5731.16Srillig node = list->curr->next; 5741.16Srillig list->curr = node; 5751.1Srillig 5761.16Srillig if (node == list->first || node == NULL) { 5771.1Srillig /* 5781.1Srillig * If back at the front, then we've hit the end... 5791.1Srillig */ 5801.15Srillig list->lastAccess = Tail; 5811.1Srillig } else { 5821.1Srillig /* 5831.1Srillig * Reset to Middle if gone past first. 5841.1Srillig */ 5851.15Srillig list->lastAccess = Middle; 5861.1Srillig } 5871.1Srillig } 5881.1Srillig 5891.16Srillig return node; 5901.1Srillig} 5911.1Srillig 5921.10Srillig/* Close a list which was opened for sequential access. */ 5931.1Srilligvoid 5941.65SrilligLst_Close(List *list) 5951.1Srillig{ 5961.52Srillig assert(list != NULL); 5971.16Srillig assert(list->isOpen); 5981.1Srillig 5991.10Srillig list->isOpen = FALSE; 6001.15Srillig list->lastAccess = Unknown; 6011.1Srillig} 6021.1Srillig 6031.1Srillig 6041.1Srillig/* 6051.1Srillig * for using the list as a queue 6061.1Srillig */ 6071.1Srillig 6081.14Srillig/* Add the datum to the tail of the given list. */ 6091.25Srilligvoid 6101.65SrilligLst_Enqueue(List *list, void *datum) 6111.1Srillig{ 6121.50Srillig Lst_Append(list, datum); 6131.1Srillig} 6141.1Srillig 6151.25Srillig/* Remove and return the datum at the head of the given list. */ 6161.1Srilligvoid * 6171.65SrilligLst_Dequeue(List *list) 6181.1Srillig{ 6191.16Srillig void *datum; 6201.1Srillig 6211.52Srillig assert(list != NULL); 6221.25Srillig assert(!LstIsEmpty(list)); 6231.1Srillig 6241.25Srillig datum = list->first->datum; 6251.50Srillig Lst_Remove(list, list->first); 6261.25Srillig assert(datum != NULL); 6271.16Srillig return datum; 6281.1Srillig} 6291.61Srillig 6301.61Srilligvoid 6311.61SrilligStack_Init(Stack *stack) 6321.61Srillig{ 6331.61Srillig stack->len = 0; 6341.61Srillig stack->cap = 10; 6351.61Srillig stack->items = bmake_malloc(stack->cap * sizeof stack->items[0]); 6361.61Srillig} 6371.61Srillig 6381.61SrilligBoolean Stack_IsEmpty(Stack *stack) 6391.61Srillig{ 6401.61Srillig return stack->len == 0; 6411.61Srillig} 6421.61Srillig 6431.61Srilligvoid Stack_Push(Stack *stack, void *datum) 6441.61Srillig{ 6451.61Srillig if (stack->len >= stack->cap) { 6461.62Srillig stack->cap *= 2; 6471.61Srillig stack->items = bmake_realloc(stack->items, 6481.61Srillig stack->cap * sizeof stack->items[0]); 6491.61Srillig } 6501.61Srillig stack->items[stack->len] = datum; 6511.61Srillig stack->len++; 6521.61Srillig} 6531.61Srillig 6541.61Srilligvoid *Stack_Pop(Stack *stack) 6551.61Srillig{ 6561.64Srillig void *datum; 6571.64Srillig 6581.61Srillig assert(stack->len > 0); 6591.61Srillig stack->len--; 6601.64Srillig datum = stack->items[stack->len]; 6611.64Srillig#ifdef CLEANUP 6621.64Srillig stack->items[stack->len] = NULL; 6631.64Srillig#endif 6641.64Srillig return datum; 6651.61Srillig} 6661.61Srillig 6671.61Srilligvoid Stack_Done(Stack *stack) 6681.61Srillig{ 6691.61Srillig free(stack->items); 6701.61Srillig} 671