1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
/*
* Doubly linked list primitives
* Copyright
* (C) 1992 Joseph H. Allen
*
* This file is part of JOE (Joe's Own Editor)
*/
#ifndef _JOE_QUEUE
#define _JOE_QUEUE 1
extern void *ITEM;
extern void *QUEUE;
extern void *LAST;
struct stditem {
LINK(STDITEM) link;
};
/* Initialize a doubly-linked list */
#define izque(type,member,item) do { \
QUEUE = (void *)(item); \
((type *)QUEUE)->member.prev = (type *)QUEUE; \
((type *)QUEUE)->member.next = (type *)QUEUE; \
} while(0)
/* Remove an item from a list */
#define deque(type,member,item) do { \
ITEM = (void *)(item); \
((type *)ITEM)->member.prev->member.next = ((type *)ITEM)->member.next; \
((type *)ITEM)->member.next->member.prev = ((type *)ITEM)->member.prev; \
} while(0)
/* Remove an item from a list and return it */
#define deque_f(type,member,item) \
( \
ITEM=(void *)(item), \
((type *)ITEM)->member.prev->member.next=((type *)ITEM)->member.next, \
((type *)ITEM)->member.next->member.prev=((type *)ITEM)->member.prev, \
(type *)ITEM \
)
/* Return true if doubly-linked list is empty */
#define qempty(type,member,item) \
( \
QUEUE=(void *)(item), \
(type *)QUEUE==((type *)QUEUE)->member.next \
)
/* Insert an item at front of list */
#define enquef(type,member,queue,item) do { \
ITEM = (void *)(item); \
QUEUE = (void *)(queue); \
((type *)ITEM)->member.next = ((type *)QUEUE)->member.next; \
((type *)ITEM)->member.prev = (type *)QUEUE; \
((type *)QUEUE)->member.next->member.prev = (type *)ITEM; \
((type *)QUEUE)->member.next = (type *)ITEM; \
} while(0)
/* Insert an item at back of list */
#define enqueb(type,member,queue,item) do { \
ITEM = (void *)(item); \
QUEUE = (void *)(queue); \
((type *)ITEM)->member.next = (type *)QUEUE; \
((type *)ITEM)->member.prev = ((type *)QUEUE)->member.prev; \
((type *)QUEUE)->member.prev->member.next = (type *)ITEM; \
((type *)QUEUE)->member.prev = (type *)ITEM; \
} while(0)
/* Insert an item at front of list and return it */
#define enqueb_f(type,member,queue,item) \
( \
ITEM=(void *)(item), \
QUEUE=(void *)(queue), \
((type *)ITEM)->member.next=(type *)QUEUE, \
((type *)ITEM)->member.prev=((type *)QUEUE)->member.prev, \
((type *)QUEUE)->member.prev->member.next=(type *)ITEM, \
((type *)QUEUE)->member.prev=(type *)ITEM, \
(type *)ITEM \
)
/* Promote an item to front of list */
#define promote(type,member,queue,item) \
enquef(type,member,(queue),deque_f(type,member,(item)))
/* Demote an item to back of list */
#define demote(type,member,queue,item) \
enqueb(type,member,(queue),deque_f(type,member,(item)))
/* Splice a chain into from of a list */
#define splicef(type,member,queue,chain) do { \
ITEM = (void *)(chain); \
LAST = (void *)((type *)ITEM)->member.prev; \
QUEUE = (void *)(queue); \
((type *)LAST)->member.next = ((type *)QUEUE)->member.next; \
((type *)ITEM)->member.prev = (type *)QUEUE; \
((type *)QUEUE)->member.next->member.prev = (type *)LAST; \
((type *)QUEUE)->member.next = (type *)ITEM; \
} while(0)
/* Splice a chain into back of a list */
#define spliceb(type,member,queue,chain) do { \
ITEM = (void *)(chain); \
LAST = (void *)((type *)ITEM)->member.prev; \
QUEUE = (void *)(queue); \
((type *)LAST)->member.next = (type *)QUEUE; \
((type *)ITEM)->member.prev = ((type *)QUEUE)->member.prev; \
((type *)QUEUE)->member.prev->member.next = (type *)ITEM; \
((type *)QUEUE)->member.prev = (type *)LAST; \
} while(0)
#define spliceb_f(type,member,queue,chain) \
( \
ITEM=(void *)(chain), \
LAST=(void *)((type *)ITEM)->member.prev, \
QUEUE=(void *)(queue), \
((type *)LAST)->member.next=(type *)QUEUE, \
((type *)ITEM)->member.prev=((type *)QUEUE)->member.prev, \
((type *)QUEUE)->member.prev->member.next=(type *)ITEM, \
((type *)QUEUE)->member.prev=(type *)LAST, \
(type *)ITEM \
)
/* Remove a range of items from a list and return it as a chain for later splicing */
#define snip(type,member,first,last) \
( \
ITEM=(void *)(first), \
LAST=(void *)(last), \
((type *)LAST)->member.next->member.prev=((type *)ITEM)->member.prev, \
((type *)ITEM)->member.prev->member.next=((type *)LAST)->member.next, \
((type *)ITEM)->member.prev=(type *)LAST, \
((type *)LAST)->member.next=(type *)ITEM, \
(type *)ITEM \
)
/* Allocate an item */
void *alitem PARAMS((void *list, int itemsize));
/* Free an item */
void frchn PARAMS((void *list, void *ch));
#endif
|