Wild Life  2.29
 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 /*==============================================================================*/
long List_EnumBackFrom(RefListHeader header, Ref atom, RefListEnumProc proc, Ref closure)
Definition: list.c:359
void List_Concat(RefListHeader header1, RefListHeader header2)
Definition: list.c:277
void List_Swap(RefListHeader header, Ref first, Ref second)
Definition: list.c:154
long List_IsUnlink(RefListLinks links)
Definition: list.c:421
void List_InsertAfter(RefListHeader header, Ref atom, Ref mark)
Definition: list.c:119
#define List_Prev(header, RefAtom)
Definition: def_macro.h:157
void List_InsertBefore(RefListHeader header, Ref atom, Ref mark)
Definition: list.c:89
void List_Cut(RefListHeader header, Ref atom, RefListHeader newHeader)
Definition: list.c:429
RefListGetLinksProc GetLinks
Definition: def_struct.h:288
static long List_SwapLinks(RefListHeader header, Ref atom)
Definition: list.c:193
#define NULL
Definition: def_const.h:203
void List_Reverse(RefListHeader header)
Definition: list.c:206
RefListLinks(* RefListGetLinksProc)()
Definition: def_struct.h:261
void List_InsertAhead(RefListHeader header, Ref atom)
Definition: list.c:39
#define List_Next(header, RefAtom)
Definition: def_macro.h:156
#define TRUE
Definition: def_const.h:127
long List_Card(RefListHeader header)
Definition: list.c:410
#define List_Last(header)
Definition: def_macro.h:155
void List_SetLinkProc(RefListHeader header, RefListGetLinksProc getLinks)
Definition: list.c:21
long List_EnumFrom(RefListHeader header, Ref atom, RefListEnumProc proc, Ref closure)
Definition: list.c:311
int(* RefListEnumProc)()
Definition: def_struct.h:262
void List_Append(RefListHeader header, Ref atom)
Definition: list.c:63
static long List_CountAtom(Ref p, Ref nbR)
Definition: list.c:400
long List_EnumBack(RefListHeader header, RefListEnumProc proc, Ref closure)
Definition: list.c:389
long List_Enum(RefListHeader header, RefListEnumProc proc, Ref closure)
Definition: list.c:341
void * Ref
Definition: def_struct.h:258
void List_Remove(RefListHeader header, Ref atom)
Definition: list.c:230