2 * routines to operate on double linked circular chains
4 * chain_init() - initialise a chain
5 * chain_add() - add an item after the ref provided
6 * chain_delete() - delete the item
7 * chainins() - insert an item before the ref
8 * chainnext() - get the next item on chain returning NULL if eof
9 * chainprev() - get the previous item on chain returning NULL if eof
10 * chain_empty_test() - is the chain empty?
11 * chain_movebase() - move a chain of things onto (the end of) another base
16 * Revision 1.2 2000-03-26 14:22:59 djk
17 * removed some irrelevant log info
19 * Revision 1.1 2000/03/26 00:03:30 djk
22 * Revision 1.4 1998/01/02 19:39:58 djk
23 * made various changes to cope with glibc
24 * fixed problem with extended status in etsi_router
26 * Revision 1.3 1997/01/02 18:46:46 djk
27 * Added conv.c from ETSI router
28 * Changed qerror.c to use syslog rather than qerror.log
29 * removed all the map27 stuff into a separate directory
30 * added dump.c (a debugging tool for dumping frames of data)
32 * Revision 1.1 1996/08/08 11:33:44 djk
35 * Revision 1.2 1995/04/21 16:02:51 djk
38 * Revision 1.1 1995/03/04 11:46:26 djk
41 * Revision 1.2 1995/01/24 15:09:39 djk
42 * Changed Indent to Id in rcsid
44 * Revision 1.1 1995/01/24 15:06:28 djk
47 * Revision 1.3 91/03/08 13:21:56 dlp
48 * changed the chain broken checks to dlpabort for dlperror
50 * Revision 1.2 90/09/15 22:37:39 dlp
51 * checked in with -k by dirk at 91.02.20.15.53.51.
53 * Revision 1.2 90/09/15 22:37:39 dlp
54 * *** empty log message ***
56 * Revision 1.1 90/09/15 22:18:23 dlp
63 /* chain definitions */
64 typedef struct _reft {
65 struct _reft *next, *prev;
68 static char erm[] = "chain broken in %s";
69 #define check(p, ss) if (p == (struct _reft *) 0 || p->prev->next != p || p->next->prev != p) die(erm, ss);
78 p->next = p->prev = p;
82 * chain_insert() - insert an item before the ref provided
85 void chain_insert(p, q)
95 * chain_movebase() - insert an chain of items from one base to another
98 void chain_movebase(p, q)
101 check(p, "movebase");
102 q->prev->prev = p->prev;
104 p->prev->next = q->next;
106 q->next = q->prev = q;
110 * chain_add() - add an item after the ref
122 * chain_delete() - delete an item in a chain
125 struct _reft *chain_delete(p)
129 p->prev->next = p->next;
130 p->next->prev = p->prev;
135 * chain_empty_test() - test to see if the chain is empty
138 int chain_empty_test(base)
141 check(base, "chain_empty_test")
142 return base->next == base;
146 * chainnext() - get next item in chain
149 struct _reft *chain_get_next(base, p)
150 struct _reft *base, *p;
153 check(base, "next base");
156 return (chain_empty_test(base)) ? 0 : base->next;
158 check(p, "next last ref");
162 return (struct _reft *) 0;
166 * chainprev() - get previous item in chain
169 struct _reft *chain_get_prev(base, p)
170 struct _reft *base, *p;
172 check(base, "prev base");
174 return (chain_empty_test(base)) ? 0 : base->prev;
176 check(p, "prev last ref");
180 return (struct _reft *) 0;
184 * rechain() - re-chain an item at this point (usually after the chain base)
187 void chain_rechain(base, p)
188 struct _reft *base, *p;
190 check(base, "rechain base");
191 check(p, "rechain last ref");
197 * emptychain() - remove all the elements in a chain, this frees all elements
198 * in a chain leaving just the base.
201 void chain_flush(base)
206 while (!chain_empty_test(base)) {
214 * newchain() - create a new chain base in the heap
219 reft *p = malloc(sizeof(reft));
221 die("out of room in chain_new");