#ifndef LIST_H_ #define LIST_H_ /*=* Linked list macros *=*/ #define LIST_ENTRY(type) struct { type *_next, **_prev; } #define LIST_HEAD(headname, type) headname { type *_head; } #define LIST_INIT(head) ((head)->_head=NULL) #define LIST_ENTRY_INIT(elm, name) do { (elm)->name._next=NULL; (elm)->name._prev=NULL; } while(0) #define LIST_TOP(head) ((head)._head) #define LIST_NEXT(elm, name) ((elm)->name._next) #define LIST_PREVPTR(elm, name) ((elm)->name._prev) #define LIST_INSERT_ATPTR(prevptr, elm, name) do { \ (elm)->name._prev=(prevptr); \ if(((elm)->name._next=*(prevptr))!=NULL) \ (elm)->name._next->name._prev=&(elm)->name._next; \ *(prevptr)=(elm); \ } while(0) #define LIST_INSERT_AFTER(where, elm, name) do { \ (elm)->name._prev=&(where)->name._next; \ if(((elm)->name._next=(where)->name._next)!=NULL) \ (where)->name._next->name._prev=&(elm)->name._next; \ *(elm)->name._prev=(elm); \ } while(0) #define LIST_INSERT_HEAD_(head, elm, name) do { \ (elm)->name._prev=&(head)->_head; \ if(((elm)->name._next=(head)->_head)!=NULL) \ (head)->_head->name._prev=&(elm)->name._next; \ (head)->_head=(elm); \ } while(0) #define LIST_REMOVE_(elm, name) do { \ if((elm)->name._next!=NULL) \ (elm)->name._next->name._prev=(elm)->name._prev; \ if((elm)->name._prev) \ *(elm)->name._prev=(elm)->name._next; \ } while(0) #ifndef NTRACE /* enable tracing of some LIST_xxx macros */ # define LIST_INSERT_HEAD_trace(head, elm, name) do { \ DEBUG("LIST_INSERT_HEAD:Inserting %p\n", (void*)elm); \ LIST_INSERT_HEAD_(head, elm, name); \ } while(0) # define LIST_REMOVE_trace(elm, name) do { \ DEBUG("LIST_REMOVE:Removing %p\n", (void*)elm); \ LIST_REMOVE_(elm, name); \ } while(0) # define LIST_INSERT_HEAD LIST_INSERT_HEAD_trace # define LIST_REMOVE LIST_REMOVE_trace #else /* use non-tracing version */ #define LIST_INSERT_HEAD LIST_INSERT_HEAD_ #define LIST_REMOVE LIST_REMOVE_ #endif /******* TODO TODO TODO : write unit test for LIST_xxx macros *******/ #endif