/* * 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