/* * Copyright (c) 2005 Massachusetts Institute of Technology * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* $Id$ */ /* Not exported */ #ifndef _KHIMAIRA_KHLIST_H #define _KHIMAIRA_KHLIST_H /* Note that most of these are "unsafe" macros. Not for general use */ /* LIFO lists */ #define LDCL(type) \ type * next; \ type * prev #define LINIT(pe) \ do { \ (pe)->next = NULL; \ (pe)->prev = NULL; } while(0) #define LPUSH(pph,pe) \ do { \ (pe)->next = *pph; \ (pe)->prev = NULL; \ if(*(pph)) (*(pph))->prev = (pe); \ (*(pph)) = (pe); } while(0) #define LPOP(pph,ppe) \ do { \ *(ppe) = *(pph); \ if(*(pph)) *(pph) = (*(pph))->next; \ if(*(pph)) (*(pph))->prev = NULL; \ if(*(ppe)) (*(ppe))->next = NULL; \ } while(0) #define LDELETE(pph,pe) \ do { \ if((pe)->prev) (pe)->prev->next = (pe)->next; \ if((pe)->next) (pe)->next->prev = (pe)->prev; \ if(*(pph) == (pe)) *(pph) = (pe)->next; \ (pe)->next = (pe)->prev = NULL; \ } while(0) #define LEMPTY(pph) (*(pph) == NULL) #define LNEXT(pe) ((pe)?(pe)->next:NULL) #define LPREV(pe) ((pe)?(pe)->prev:NULL) /* Trees with LIFO child lists */ #define TDCL(type) \ LDCL(type); \ type * children; \ type * parent #define TINIT(pe) \ do { \ (pe)->children = NULL; \ (pe)->parent = NULL; } while(0) #define TADDCHILD(pt,pe) \ do { \ LPUSH(&((pt)->children),(pe)); \ (pe)->parent = (pt); } while(0) #define TFIRSTCHILD(pt) ((pt)?(pt)->children:NULL) #define TPOPCHILD(pt, ppe) \ do { \ LPOP(&((pt)->children), ppe); \ if(*(ppe)) (*(ppe))->parent = NULL; \ } while(0) #define TDELCHILD(pt, pe) \ do { \ LDELETE(&((pt)->children), (pe)); \ (pe)->parent = NULL; } while(0) #define TPARENT(pe) ((pe)?(pe)->parent:NULL) /* FIFO lists */ #define QDCL(type) \ type * head; \ type * tail #define QINIT(pq) \ do { \ (pq)->head = (pq)->tail = NULL; \ } while(0) #define QPUT(pq, pe) \ do { \ LPUSH(&(pq)->tail, (pe)); \ if(!(pq)->head) (pq)->head = (pe); \ } while(0) #define QPUSH(pq, pe) \ do { \ (pe)->next = NULL; \ (pe)->prev = (pq)->head; \ if((pq)->head) (pq)->head->next = (pe); \ if(!(pq)->tail) (pq)->tail = (pe); \ (pq)->head = (pe); \ } while (0) #define QGET(pq, ppe) \ do { \ *(ppe) = (pq)->head; \ if(*(ppe)) { \ (pq)->head = (*(ppe))->prev; \ if( (*(ppe))->prev ) (*(ppe))->prev->next = NULL; \ (*(ppe))->prev = NULL; \ if( (pq)->tail == *(ppe)) (pq)->tail = NULL; \ } \ } while(0) #define QDEL(pq, pe) \ do { \ if((pq)->head == (pe)) (pq)->head = LPREV(pe); \ LDELETE(&((pq)->tail), (pe)); \ } while(0) #define QGETT(pq,ppe) \ do { \ *(ppe) = (pq)->tail; \ if(*(ppe)) { \ (pq)->tail = (*(ppe))->next; \ if( (*(ppe))->next ) (*(ppe))->next->prev = NULL; \ (*(ppe))->next = NULL; \ if( (pq)->head == *(ppe)) (pq)->head = NULL; \ } \ } while(0) #define QTOP(pq) ((pq)->head) #define QBOTTOM(pq) ((pq)->tail) #define QNEXT(pe) ((pe)->prev) #define QPREV(pe) ((pe)->next) #define QINSERT(pt, pre, pe) \ do { \ if ((pre) == NULL || \ QNEXT(pre) == NULL) { QPUT(pt, pe); } \ else { \ (pe)->prev = (pre)->prev; \ (pe)->next = (pre); \ (pre)->prev->next = (pe); \ (pre)->prev = (pe); \ }} while(0) /* Trees with FIFO child lists */ #define TQDCL(type) \ LDCL(type); \ QDCL(type); \ type * parent #define TQINIT(pe) \ do { \ LINIT(pe); \ QINIT(pe); \ (pe)->parent = NULL; } while(0) #define TQPUTCHILD(pt,pe) \ do { \ QPUT((pt), (pe)); \ (pe)->parent = (pt); } while(0) #define TQINSERT(pt, pre, pe) \ do { \ QINSERT(pt, pre, pe); \ (pe)->parent = (pt); } while(0) #define TQGETCHILD(pt,ppe) \ do { \ QGET(pt, ppe); \ if (*(ppe)) { *(ppe)->parent = NULL; } \ } while(0) #define TQDELCHILD(pt, pe) \ do { \ QDEL(pt, pe); \ (pe)->parent = NULL; } while(0) #define TQFIRSTCHILD(pt) ((pt)?QTOP(pt):NULL) #define TQNEXTCHILD(pe) QNEXT(pe) #define TQPREVCHILD(pe) QPREV(pe) #define TQPARENT(pe) ((pe)?(pe)->parent:NULL) #endif