Wild Life: list.c Source File

Wild Life 2.29

- Main Page
- Data Structures
- Files

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Macros
list.c
Go to the documentation of this file.
1 /*
2 * Copyright 1991 Digital Equipment Corporation.
3 * All Rights Reserved.
4 */
5 /* $Id: list.c,v 1.2 1994/12/08 23:28:16 duchier Exp $ */
6
7 /*
8 ** list.c contains the functions to manage double link list
9 ** with 2 entries (first and last element)
10 ** Links belongs to each atom
11 */
12
13 #include "defs.h"
14
15
16
17 /*=============================================================================*/
18 /* Set functions */
19 /*=============================================================================*/
20
21 void List_SetLinkProc (header, getLinks)
22 RefListHeader header;
23 RefListGetLinksProc getLinks;
24 {
25 header->First = NULL;
26 header->Last = NULL;
27
28 #ifdef prlDEBUG
29 header->Lock = 0;
30 #endif
31
32 header->GetLinks = getLinks;
33 }
34
35 /*=============================================================================*/
36 /* List functions */
37 /*=============================================================================*/
38
39 void List_InsertAhead (header, atom)
40 RefListHeader header;
41 Ref atom;
42 {
43 RefListGetLinksProc getLinks = header->GetLinks;
44
45 /* Update links of atom to insert */
46
47 (*getLinks)(atom)->Next = header->First;
48 (*getLinks)(atom)->Prev = NULL;
49
50 /* Link to the head of list */
51
52 if (header->First != NULL)
53 (*getLinks)(header->First)->Prev = atom;
54
55 else /* The list is empty */
56 header->Last = atom;
57
58 header->First = atom;
59 }
60
61 /*==============================================================================*/
62
63 void List_Append (header, atom)
64 RefListHeader header;
65 Ref atom;
66 {
67 RefListGetLinksProc getLinks = header->GetLinks;
68
69 /* Link to the end of list */
70
71 if (header->Last != NULL)
72 (*getLinks)(header->Last)->Next = atom;
73
74 else /* The list is empty */
75 header->First = atom;
76
77 /* Update links of atom to insert */
78
79 (*getLinks)(atom)->Prev = header->Last;
80 (*getLinks)(atom)->Next = NULL;
81
82 /* Update last element of header */
83
84 header->Last = atom;
85 }
86
87 /*==============================================================================*/
88
89 void List_InsertBefore (header, atom, mark)
90 RefListHeader header;
91 Ref atom;
92 Ref mark;
93 {
94 RefListGetLinksProc getLinks = header->GetLinks;
95
96 if (mark != NULL)
97 {
98 (*getLinks)(atom)->Next = mark;
99
100 if (mark != header->First)
101 {
102 (*getLinks)(atom)->Prev = (*getLinks)(mark)->Prev;
103 (*getLinks)((*getLinks)(mark)->Prev)->Next = atom;
104 }
105 else /* Insert ahead the list */
106 {
107 (*getLinks)(atom)->Prev = NULL;
108 header->First = atom;
109 }
110
111 (*getLinks)(mark)->Prev = atom;
112 }
113 else /* Append to the list */
114 List_Append (header, atom);
115 }
116
117 /*==============================================================================*/
118
119 void List_InsertAfter (header, atom, mark)
120 RefListHeader header;
121 Ref atom;
122 Ref mark;
123 {
124 RefListGetLinksProc getLinks = header->GetLinks;
125
126 #ifdef prlDEBUG
127 if (header->Lock > 1)
128 OS_PrintMessage ("List_InsertAfter: Warning insert after on recursive List_Enum call !!\n");
129 #endif
130
131 if (mark != NULL)
132 {
133 (*getLinks)(atom)->Prev = mark;
134
135 if (mark != header->Last)
136 {
137 (*getLinks)(atom)->Next = (*getLinks)(mark)->Next;
138 (*getLinks)((*getLinks)(mark)->Next)->Prev = atom;
139 }
140 else /* Insert at the end of the list */
141 {
142 (*getLinks)(atom)->Next = NULL;
143 header->Last = atom;
144 }
145
146 (*getLinks)(mark)->Next = atom;
147 }
148 else /* Insert ahead the list */
149 List_InsertAhead (header, atom);
150 }
151
152 /*==============================================================================*/
153
154 void List_Swap (header, first, second)
155 RefListHeader header;
156 Ref first;
157 Ref second;
158 {
159 RefListGetLinksProc getLinks = header->GetLinks;
160
161 /* Don't swap if the input is wrong */
162
163 if ((*getLinks)(first)->Next != second)
164 {
165 #ifdef prlDEBUG
166 OS_PrintMessage ("List_Swap: WARNING wrong input data, swap not done..\n");
167 #endif
168 return;
169 }
170
171 /* Special Cases */
172
173 if (header->First == first)
174 header->First = second;
175 else
176 (*getLinks)((*getLinks)(first)->Prev)->Next = second;
177
178 if (header->Last == second)
179 header->Last = first;
180 else
181 (*getLinks)((*getLinks)(second)->Next)->Prev = first;
182
183 /* Swap the atoms */
184
185 (*getLinks)(second)->Prev = (*getLinks)(first)->Prev;
186 (*getLinks)(first)->Next = (*getLinks)(second)->Next;
187 (*getLinks)(first)->Prev = second;
188 (*getLinks)(second)->Next = first;
189 }
190
191 /*==============================================================================*/
192
193 static long List_SwapLinks (header, atom)
194 RefListHeader header;
195 Ref atom;
196 {
197 Ref save;
198
199 save = (*header->GetLinks)(atom)->Next;
200 (*header->GetLinks)(atom)->Next = (*header->GetLinks)(atom)->Prev;
201 (*header->GetLinks)(atom)->Prev = save;
202
203 return TRUE;
204 }
205
206 void List_Reverse (header)
207 RefListHeader header;
208 {
209 Ref cur, next;
210 RefListGetLinksProc getLinks = header->GetLinks;
211
212 /* This traverse cannot be done with function List_Enum() */
213
214 cur = header->First;
215
216 /* Swap the headers */
217 header->First = header->Last;
218 header->Last = cur;
219
220 while (cur != NULL)
221 {
222 next = (*getLinks)(cur)->Next;
223 (void)List_SwapLinks (header, cur);
224 cur = next;
225 }
226 }
227
228 /*==============================================================================*/
229
230 void List_Remove (header, atom)
231 RefListHeader header;
232 Ref atom;
233 {
234 /*-----------------------------------------------------------------------------
235
236 WARNING
237 - The container is 'updated' two times if the first and last atom
238 of list is the only one to remove.
239
240 -----------------------------------------------------------------------------*/
241
242 RefListGetLinksProc getLinks = header->GetLinks;
243
244 #ifdef prlDEBUG
245 if (header->Lock > 1)
246 OS_PrintMessage ("List_Remove: Warning remove on recursive List_Enum call !!\n");
247 #endif
248
249 /* Update the DownStream links */
250
251 if ((*getLinks)(atom)->Prev != NULL)
252 {
253 (*getLinks)((*getLinks)(atom)->Prev)->Next =
254 (*getLinks)(atom)->Next;
255 }
256 else /* Atom is the first of list */
257 header->First = (*getLinks)(atom)->Next;
258
259 /* Update the UpStream links */
260
261 if ((*getLinks)(atom)->Next != NULL)
262 {
263 (*getLinks)((*getLinks)(atom)->Next)->Prev =
264 (*getLinks)(atom)->Prev;
265 }
266 else /* Atom is the last of list */
267 header->Last = (*getLinks)(atom)->Prev;
268
269 /* Reset the atom links */
270
271 (*getLinks)(atom)->Prev = NULL;
272 (*getLinks)(atom)->Next = NULL;
273 }
274
275 /*==============================================================================*/
276
277 void List_Concat (header1, header2)
278 RefListHeader header1;
279 RefListHeader header2;
280 {
281 RefListGetLinksProc getLinks = header1->GetLinks;
282
283 if (header1->GetLinks == header2->GetLinks)
284 {
285 #ifdef prlDEBUG
286 OS_PrintMessage ("List_Concat: ERROR concat different lists\n");
287 #endif
288 return;
289 }
290
291 /* Concatenate only if the second list is not empty */
292
293 if (header2->First != NULL)
294 {
295 /* Obvious concatenate when the first list is empty */
296
297 if (header1->First == NULL)
298 header1->First = header2->First;
299
300 else /* Concatenate the two non empty lists */
301 {
302 (*getLinks)(header1->Last)->Next = header2->First;
303 (*getLinks)(header2->First)->Prev = header1->Last;
304 }
305 header1->Last = header2->Last;
306 }
307 }
308
309 /*==============================================================================*/
310
311 long List_EnumFrom (header, atom, proc, closure)
312 RefListHeader header;
313 Ref atom;
314 RefListEnumProc proc;
315 Ref closure;
316 {
317 Ref cur, next;
318 int notInterrupted = TRUE;
319
320 #ifdef prlDEBUG
321 header->Lock += 1;
322 #endif
323
324 cur = atom;
325 while (cur != NULL && notInterrupted)
326 {
327 next = List_Next (header, cur);
328 notInterrupted = (*proc)(cur, closure);
329 cur = next;
330 }
331
332 #ifdef prlDEBUG
333 header->Lock -=1;
334 #endif
335
336 return (notInterrupted);
337 }
338
339 /*==============================================================================*/
340
341 long List_Enum (header, proc, closure)
342 RefListHeader header;
343 RefListEnumProc proc;
344 Ref closure;
345 /*-----------------------------------------------------------------------------
346
347 (NO) SIDE EFFECTS
348 The current atom can be modified by the function RemoveAtom () during
349 the traversing of the list. This is the reason why the current pointer
350 is managed on the header.
351
352 -----------------------------------------------------------------------------*/
353 {
354 return (List_EnumFrom (header, header->First, proc, closure));
355 }
356
357 /*==============================================================================*/
358
359 long List_EnumBackFrom (header, atom, proc, closure)
360 RefListHeader header;
361 Ref atom;
362 RefListEnumProc proc;
363 Ref closure;
364 {
365 Ref cur, prev;
366 int notInterrupted = TRUE;
367
368 #ifdef prlDEBUG
369 header->Lock += 1;
370 #endif
371
372 cur = atom;
373 while (cur != NULL && notInterrupted)
374 {
375 prev = List_Prev (header, cur);
376 notInterrupted = (*proc)(cur, closure);
377 cur = prev;
378 }
379
380 #ifdef prlDEBUG
381 header->Lock -=1;
382 #endif
383
384 return (notInterrupted);
385 }
386
387 /*==============================================================================*/
388
389 long List_EnumBack (header, proc, closure)
390 RefListHeader header;
391 RefListEnumProc proc;
392 Ref closure;
393 {
394 return (List_EnumBackFrom (header, header->Last, proc, closure));
395 }
396
397 /*==============================================================================*/
398
399 /*ARGSUSED*/
400 static long List_CountAtom (p, nbR)
401 Ref p;
402 Ref nbR;
403 {
404 long *nb = (long *)nbR;
405
406 ++*nb;
407 return TRUE;
408 }
409
410 long List_Card (header)
411 RefListHeader header;
412 {
413 long n = 0;
414
415 (void)List_Enum (header,(RefListEnumProc) List_CountAtom, &n);
416 return n;
417 }
418
419 /*==============================================================================*/
420
421 long List_IsUnlink (links)
422 RefListLinks links;
423 {
424 return (links->Next == NULL && links->Prev == NULL);
425 }
426
427 /*==============================================================================*/
428
429 void List_Cut (header, atom, newHeader)
430 RefListHeader header;
431 Ref atom;
432 RefListHeader newHeader;
433 {
434 RefListGetLinksProc getLinks = header->GetLinks;
435
436 if (atom != List_Last (header))
437 {
438 newHeader->First = List_Next (header, atom);
439 newHeader->Last = header->Last;
440
441 header->Last = atom;
442
443 /* Update the links */
444 (*getLinks)(atom)->Next = NULL;
445 (*getLinks)(newHeader->First)->Prev = NULL;
446 }
447 }
448
449 /*==============================================================================*/
List_EnumBackFrom
long List_EnumBackFrom(RefListHeader header, Ref atom, RefListEnumProc proc, Ref closure)
Definition: list.c:359
List_Concat
void List_Concat(RefListHeader header1, RefListHeader header2)
Definition: list.c:277
List_Swap
void List_Swap(RefListHeader header, Ref first, Ref second)
Definition: list.c:154
List_IsUnlink
long List_IsUnlink(RefListLinks links)
Definition: list.c:421
List_InsertAfter
void List_InsertAfter(RefListHeader header, Ref atom, Ref mark)
Definition: list.c:119
defs.h
List_Prev
#define List_Prev(header, RefAtom)
Definition: def_macro.h:157
List_InsertBefore
void List_InsertBefore(RefListHeader header, Ref atom, Ref mark)
Definition: list.c:89
List_Cut
void List_Cut(RefListHeader header, Ref atom, RefListHeader newHeader)
Definition: list.c:429
wl_ListHeader::GetLinks
RefListGetLinksProc GetLinks
Definition: def_struct.h:288
List_SwapLinks
static long List_SwapLinks(RefListHeader header, Ref atom)
Definition: list.c:193
NULL
#define NULL
Definition: def_const.h:203
wl_ListLinks::Next
Ref Next
Definition: def_struct.h:295
wl_ListLinks
Definition: def_struct.h:293
List_Reverse
void List_Reverse(RefListHeader header)
Definition: list.c:206
RefListGetLinksProc
RefListLinks(* RefListGetLinksProc)()
Definition: def_struct.h:261
List_InsertAhead
void List_InsertAhead(RefListHeader header, Ref atom)
Definition: list.c:39
List_Next
#define List_Next(header, RefAtom)
Definition: def_macro.h:156
TRUE
#define TRUE
Definition: def_const.h:127
List_Card
long List_Card(RefListHeader header)
Definition: list.c:410
List_Last
#define List_Last(header)
Definition: def_macro.h:155
List_SetLinkProc
void List_SetLinkProc(RefListHeader header, RefListGetLinksProc getLinks)
Definition: list.c:21
wl_ListHeader
Definition: def_struct.h:280
List_EnumFrom
long List_EnumFrom(RefListHeader header, Ref atom, RefListEnumProc proc, Ref closure)
Definition: list.c:311
RefListEnumProc
int(* RefListEnumProc)()
Definition: def_struct.h:262
wl_ListHeader::Last
Ref Last
Definition: def_struct.h:282
List_Append
void List_Append(RefListHeader header, Ref atom)
Definition: list.c:63
List_CountAtom
static long List_CountAtom(Ref p, Ref nbR)
Definition: list.c:400
List_EnumBack
long List_EnumBack(RefListHeader header, RefListEnumProc proc, Ref closure)
Definition: list.c:389
List_Enum
long List_Enum(RefListHeader header, RefListEnumProc proc, Ref closure)
Definition: list.c:341
wl_ListHeader::First
Ref First
Definition: def_struct.h:282
Ref
void * Ref
Definition: def_struct.h:258
List_Remove
void List_Remove(RefListHeader header, Ref atom)
Definition: list.c:230