1 /* list.c
2 
3    Written by D.R.Maszle
4    28 October 1991
5 
6    Copyright (c) 1991-2017 Free Software Foundation, Inc.
7 
8    This file is part of GNU MCSim.
9 
10    GNU MCSim is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License
12    as published by the Free Software Foundation; either version 3
13    of the License, or (at your option) any later version.
14 
15    GNU MCSim is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with GNU MCSim; if not, see <http://www.gnu.org/licenses/>
22 
23    A LIST data type utility.
24 */
25 
26 #include <stdlib.h>
27 
28 #include "lexerr.h"
29 #include "list.h"
30 
31 
32 /* -----------------------------------------------------------------------------
33    InitList
34 
35    Initialized a list header structure and returns the pointer.  This
36    LIST may then be used in other exciting list functions.
37 */
38 
InitList(void)39 PLIST InitList (void)
40 {
41   /* Allocate header record */
42   PLIST plist = (PLIST) malloc (sizeof(LIST));
43 
44   if (plist) {                /* If allocation succeeds, */
45     plist->pleHead = NULL;    /* .. initialize all to 0  */
46     plist->pleTail = NULL;
47     plist->iSize = 0;
48   }
49   else
50     ReportError (NULL, RE_OUTOFMEM | RE_FATAL, "InitList", NULL);
51 
52   return (plist);
53 
54 } /* InitList */
55 
56 
57 /* -----------------------------------------------------------------------------
58    FreeList
59 
60    Frees the memory allocated to a LIST, incrementing through each
61    element sequentially. Allows user to free data with a provided
62    callback function, or to specify free'ing of data in this routine.
63 
64    If the pfvFreeData function is non-NULL, the function is called
65    with each data pointer in the list, and bAndData is ignored.
66 
67    If the callback is NULL and the boolean bAndData is set, free() is
68    called with each user data pointer before freeing the list element.
69 
70    NOTE: ppList is a pointer to a LIST structure which is itself a pointer.
71 */
72 
FreeList(PLIST * pplist,PFV_FREELISTCALLBACK pfvFreeData,BOOL bAndData)73 void FreeList (PLIST *pplist, PFV_FREELISTCALLBACK pfvFreeData, BOOL bAndData)
74 {
75   PLIST plist = *pplist; /* Get single pointer to work with */
76 
77   if (!plist)
78     return;
79 
80   while (plist->pleHead) {
81     if (pfvFreeData)
82       (*pfvFreeData)(plist->pleHead->pData); /* Call user free routine */
83 
84     else if (bAndData && plist->pleHead->pData)
85       free (plist->pleHead->pData); /* Free user data block */
86 
87     plist->pleTail = plist->pleHead; /* Save p to current elem */
88     plist->pleHead = plist->pleHead->pleNext; /* Next list item */
89     free (plist->pleTail); /* Free saved current elem */
90 
91   } /* while */
92 
93   free (plist); /* Free the list header */
94   *pplist = NULL; /* Reset the user's pointer */
95 
96 } /* FreeList */
97 
98 
99 /* -----------------------------------------------------------------------------
100    QueueListItem
101 
102    Adds a new list item to the tail of the list.
103 */
104 
QueueListItem(PLIST plist,PVOID pData)105 void QueueListItem (PLIST plist, PVOID pData)
106 {
107   PLISTELEM pNewElem;
108 
109   if (!plist)
110     return;
111 
112   if (!(pNewElem = (PLISTELEM) malloc (sizeof(LISTELEM))))
113     ReportError (NULL, RE_OUTOFMEM | RE_FATAL, "QueueListItem", NULL);
114 
115   pNewElem->pData = pData; /* Init new element */
116   pNewElem->pleNext = NULL;
117 
118   if (plist->pleTail)
119     plist->pleTail->pleNext = pNewElem; /* Link new element */
120   else
121     plist->pleHead = pNewElem; /* Link first element */
122 
123   plist->pleTail = pNewElem; /* Reset tail to new elem */
124   plist->iSize++; /* Increment size of list */
125 
126 } /* QueueListItem */
127 
128 
129 /* -----------------------------------------------------------------------------
130    ForAllList
131 
132    Takes a PLIST, a PFI_LISTCALLBACK function, and PVOID to user
133    information, and calls the callback function for each of the list
134    elems in sequence.
135 
136    The PFI_LISTCALLBACK takes the user's data point at each list
137    element and the pointer to user information as arguments.  It
138    returns an integer.  The sum of the integers of all calls to the
139    callback is returned from ForAllList().
140 */
141 
ForAllList(PLIST plist,PFI_FORLISTCALLBACK pfiCallback,PVOID pUserInfo)142 int ForAllList (PLIST plist, PFI_FORLISTCALLBACK pfiCallback, PVOID pUserInfo)
143 {
144   int iTotal = 0;
145   PLISTELEM ple;
146 
147   if (!plist || !pfiCallback)
148     return 0;
149 
150   ple = plist->pleHead;
151 
152   while (ple) {
153     iTotal += (*pfiCallback) (ple->pData, pUserInfo);
154     ple = ple->pleNext; /* Increment to next elem */
155   }
156 
157   return (iTotal);
158 
159 } /* ForAllList */
160 
161 /* -----------------------------------------------------------------------------
162    ForAllList3
163 
164    Like ForAllList, but takes three user arguments
165    Included temporarily to avoid rewriting a lot of code
166 */
167 
ForAllList3(PLIST plist,PFI_FORLISTCALLBACK3 pfiCallback,PVOID pUserInfo1,PVOID pUserInfo2,PVOID pUserInfo3)168 void ForAllList3(PLIST plist, PFI_FORLISTCALLBACK3 pfiCallback,
169                  PVOID pUserInfo1, PVOID pUserInfo2, PVOID pUserInfo3)
170 {
171   PLISTELEM ple;
172 
173   if (!plist || !pfiCallback)
174     return;
175 
176   ple = plist->pleHead;
177 
178   while (ple) {
179     (*pfiCallback) (ple->pData, pUserInfo1, pUserInfo2, pUserInfo3);
180     ple = ple->pleNext; /* Increment to next elem */
181   }
182 
183 } /* ForAllList3 */
184