X-Git-Url: http://dxcluster.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=src%2Fchain.c;fp=src%2Fchain.c;h=4e36b3ed4e911d5839e4f80676e8d2c1dc8a2d8f;hb=8804833a62667fe6a33655351790b241256e5980;hp=0000000000000000000000000000000000000000;hpb=a6d0720c825ae5d7233025c96e0f04ac48d5b811;p=spider.git diff --git a/src/chain.c b/src/chain.c new file mode 100755 index 00000000..4e36b3ed --- /dev/null +++ b/src/chain.c @@ -0,0 +1,222 @@ +/* + * routines to operate on double linked circular chains + * + * chain_init() - initialise a chain + * chain_add() - add an item after the ref provided + * chain_delete() - delete the item + * chainins() - insert an item before the ref + * chainnext() - get the next item on chain returning NULL if eof + * chainprev() - get the previous item on chain returning NULL if eof + * chain_empty_test() - is the chain empty? + * chain_movebase() - move a chain of things onto (the end of) another base + * + * $Header$ + * + * $Log$ + * Revision 1.1 2000-03-26 00:03:30 djk + * first cut of client + * + * Revision 1.4 1998/01/02 19:39:58 djk + * made various changes to cope with glibc + * fixed problem with extended status in etsi_router + * + * Revision 1.3 1997/01/02 18:46:46 djk + * Added conv.c from ETSI router + * Changed qerror.c to use syslog rather than qerror.log + * removed all the map27 stuff into a separate directory + * added dump.c (a debugging tool for dumping frames of data) + * + * Revision 1.1 1996/08/08 11:33:44 djk + * Initial revision + * + * Revision 1.2 1995/04/21 16:02:51 djk + * remove rcs id + * + * Revision 1.1 1995/03/04 11:46:26 djk + * Initial revision + * + * Revision 1.2 1995/01/24 15:09:39 djk + * Changed Indent to Id in rcsid + * + * Revision 1.1 1995/01/24 15:06:28 djk + * Initial revision + * + * Revision 1.3 91/03/08 13:21:56 dlp + * changed the chain broken checks to dlpabort for dlperror + * + * Revision 1.2 90/09/15 22:37:39 dlp + * checked in with -k by dirk at 91.02.20.15.53.51. + * + * Revision 1.2 90/09/15 22:37:39 dlp + * *** empty log message *** + * + * Revision 1.1 90/09/15 22:18:23 dlp + * Initial revision + * + */ + +#include + +/* chain definitions */ +typedef struct _reft { + struct _reft *next, *prev; +} reft; + +static char erm[] = "chain broken in %s"; +#define check(p, ss) if (p == (struct _reft *) 0 || p->prev->next != p || p->next->prev != p) die(erm, ss); + +/* + * chain_init() + */ + +void chain_init(p) +struct _reft *p; +{ + p->next = p->prev = p; +} + +/* + * chain_insert() - insert an item before the ref provided + */ + +void chain_insert(p, q) +struct _reft *p, *q; +{ + check(p, "ins"); + q->prev = p->prev; + q->next = p; + p->prev->next = q; + p->prev = q; +} +/* + * chain_movebase() - insert an chain of items from one base to another + */ + +void chain_movebase(p, q) +struct _reft *p, *q; +{ + check(p, "movebase"); + q->prev->prev = p->prev; + q->next->next = p; + p->prev->next = q->next; + p->prev = q->prev; + q->next = q->prev = q; +} + +/* + * chain_add() - add an item after the ref + */ + +void chain_add(p, q) +struct _reft *p, *q; +{ + check(p, "add"); + p = p->next; + chain_insert(p, q); +} + +/* + * chain_delete() - delete an item in a chain + */ + +struct _reft *chain_delete(p) +struct _reft *p; +{ + check(p, "del"); + p->prev->next = p->next; + p->next->prev = p->prev; + return p->prev; +} + +/* + * chain_empty_test() - test to see if the chain is empty + */ + +int chain_empty_test(base) +struct _reft *base; +{ + check(base, "chain_empty_test") + return base->next == base; +} + +/* + * chainnext() - get next item in chain + */ + +struct _reft *chain_get_next(base, p) +struct _reft *base, *p; +{ + + check(base, "next base"); + + if (!p) + return (chain_empty_test(base)) ? 0 : base->next; + + check(p, "next last ref"); + if (p->next != base) + return p->next; + else + return (struct _reft *) 0; +} + +/* + * chainprev() - get previous item in chain + */ + +struct _reft *chain_get_prev(base, p) +struct _reft *base, *p; +{ + check(base, "prev base"); + if (!p) + return (chain_empty_test(base)) ? 0 : base->prev; + + check(p, "prev last ref"); + if (p->prev != base) + return p->prev; + else + return (struct _reft *) 0; +} + +/* + * rechain() - re-chain an item at this point (usually after the chain base) + */ + +void chain_rechain(base, p) +struct _reft *base, *p; +{ + check(base, "rechain base"); + check(p, "rechain last ref"); + chain_delete(p); + chain_add(base, p); +} + +/* + * emptychain() - remove all the elements in a chain, this frees all elements + * in a chain leaving just the base. + */ + +void chain_flush(base) +struct _reft *base; +{ + struct _reft *p; + + while (!chain_empty_test(base)) { + p = base->next; + chain_delete(p); + free(p); + } +} + +/* + * newchain() - create a new chain base in the heap + */ + +reft *chain_new() +{ + reft *p = malloc(sizeof(reft)); + if (!p) + die("out of room in chain_new"); + chain_init(p); + return p; +} +