12b15cb3dSCy Schubert /* 22b15cb3dSCy Schubert * ntp_lists.h - linked lists common code 32b15cb3dSCy Schubert * 42b15cb3dSCy Schubert * SLIST: singly-linked lists 52b15cb3dSCy Schubert * ========================== 62b15cb3dSCy Schubert * 72b15cb3dSCy Schubert * These macros implement a simple singly-linked list template. Both 82b15cb3dSCy Schubert * the listhead and per-entry next fields are declared as pointers to 92b15cb3dSCy Schubert * the list entry struct type. Initialization to NULL is typically 102b15cb3dSCy Schubert * implicit (for globals and statics) or handled by zeroing of the 112b15cb3dSCy Schubert * containing structure. 122b15cb3dSCy Schubert * 132b15cb3dSCy Schubert * The name of the next link field is passed as an argument to allow 142b15cb3dSCy Schubert * membership in several lists at once using multiple next link fields. 152b15cb3dSCy Schubert * 162b15cb3dSCy Schubert * When possible, placing the link field first in the entry structure 172b15cb3dSCy Schubert * allows slightly smaller code to be generated on some platforms. 182b15cb3dSCy Schubert * 192b15cb3dSCy Schubert * LINK_SLIST(listhead, pentry, nextlink) 202b15cb3dSCy Schubert * add entry at head 212b15cb3dSCy Schubert * 222b15cb3dSCy Schubert * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) 232b15cb3dSCy Schubert * add entry at tail. This is O(n), if this is a common 242b15cb3dSCy Schubert * operation the FIFO template may be more appropriate. 252b15cb3dSCy Schubert * 262b15cb3dSCy Schubert * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype) 272b15cb3dSCy Schubert * add entry in sorted order. beforecur is an expression comparing 282b15cb3dSCy Schubert * pentry with the current list entry. The current entry can be 292b15cb3dSCy Schubert * referenced within beforecur as L_S_S_CUR(), which is short for 302b15cb3dSCy Schubert * LINK_SORT_SLIST_CUR(). beforecur is nonzero if pentry sorts 312b15cb3dSCy Schubert * before L_S_S_CUR(). 322b15cb3dSCy Schubert * 332b15cb3dSCy Schubert * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink) 342b15cb3dSCy Schubert * unlink first entry and point punlinked to it, or set punlinked 352b15cb3dSCy Schubert * to NULL if the list is empty. 362b15cb3dSCy Schubert * 372b15cb3dSCy Schubert * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype) 382b15cb3dSCy Schubert * unlink entry pointed to by ptounlink. punlinked is set to NULL 392b15cb3dSCy Schubert * if the entry is not found on the list, otherwise it is set to 402b15cb3dSCy Schubert * ptounlink. 412b15cb3dSCy Schubert * 422b15cb3dSCy Schubert * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype) 432b15cb3dSCy Schubert * unlink entry where expression expr is nonzero. expr can refer 442b15cb3dSCy Schubert * to the entry being tested using UNLINK_EXPR_SLIST_CURRENT(), 452b15cb3dSCy Schubert * alias U_E_S_CUR(). See the implementation of UNLINK_SLIST() 462b15cb3dSCy Schubert * below for an example. U_E_S_CUR() is NULL iff the list is empty. 472b15cb3dSCy Schubert * punlinked is pointed to the removed entry or NULL if none 482b15cb3dSCy Schubert * satisfy expr. 492b15cb3dSCy Schubert * 502b15cb3dSCy Schubert * FIFO: singly-linked lists plus tail pointer 512b15cb3dSCy Schubert * =========================================== 522b15cb3dSCy Schubert * 532b15cb3dSCy Schubert * This is the same as FreeBSD's sys/queue.h STAILQ -- a singly-linked 542b15cb3dSCy Schubert * list implementation with tail-pointer maintenance, so that adding 552b15cb3dSCy Schubert * at the tail for first-in, first-out access is O(1). 562b15cb3dSCy Schubert * 572b15cb3dSCy Schubert * DECL_FIFO_ANCHOR(entrytype) 582b15cb3dSCy Schubert * provides the type specification portion of the declaration for 592b15cb3dSCy Schubert * a variable to refer to a FIFO queue (similar to listhead). The 602b15cb3dSCy Schubert * anchor contains the head and indirect tail pointers. Example: 612b15cb3dSCy Schubert * 622b15cb3dSCy Schubert * #include "ntp_lists.h" 632b15cb3dSCy Schubert * 642b15cb3dSCy Schubert * typedef struct myentry_tag myentry; 652b15cb3dSCy Schubert * struct myentry_tag { 662b15cb3dSCy Schubert * myentry *next_link; 672b15cb3dSCy Schubert * ... 682b15cb3dSCy Schubert * }; 692b15cb3dSCy Schubert * 702b15cb3dSCy Schubert * DECL_FIFO_ANCHOR(myentry) my_fifo; 712b15cb3dSCy Schubert * 722b15cb3dSCy Schubert * void somefunc(myentry *pentry) 732b15cb3dSCy Schubert * { 742b15cb3dSCy Schubert * LINK_FIFO(my_fifo, pentry, next_link); 752b15cb3dSCy Schubert * } 762b15cb3dSCy Schubert * 772b15cb3dSCy Schubert * If DECL_FIFO_ANCHOR is used with stack or heap storage, it 782b15cb3dSCy Schubert * should be initialized to NULL pointers using a = { NULL }; 792b15cb3dSCy Schubert * initializer or memset. 802b15cb3dSCy Schubert * 812b15cb3dSCy Schubert * HEAD_FIFO(anchor) 822b15cb3dSCy Schubert * TAIL_FIFO(anchor) 832b15cb3dSCy Schubert * Pointer to first/last entry, NULL if FIFO is empty. 842b15cb3dSCy Schubert * 852b15cb3dSCy Schubert * LINK_FIFO(anchor, pentry, nextlink) 862b15cb3dSCy Schubert * add entry at tail. 872b15cb3dSCy Schubert * 882b15cb3dSCy Schubert * UNLINK_FIFO(punlinked, anchor, nextlink) 892b15cb3dSCy Schubert * unlink head entry and point punlinked to it, or set punlinked 902b15cb3dSCy Schubert * to NULL if the list is empty. 912b15cb3dSCy Schubert * 922b15cb3dSCy Schubert * CONCAT_FIFO(q1, q2, nextlink) 932b15cb3dSCy Schubert * empty fifoq q2 moving its nodes to q1 following q1's existing 942b15cb3dSCy Schubert * nodes. 952b15cb3dSCy Schubert * 962b15cb3dSCy Schubert * DLIST: doubly-linked lists 972b15cb3dSCy Schubert * ========================== 982b15cb3dSCy Schubert * 992b15cb3dSCy Schubert * Elements on DLISTs always have non-NULL forward and back links, 1002b15cb3dSCy Schubert * because both link chains are circular. The beginning/end is marked 1012b15cb3dSCy Schubert * by the listhead, which is the same type as elements for simplicity. 1022b15cb3dSCy Schubert * An empty list's listhead has both links set to its own address. 1032b15cb3dSCy Schubert * 1042b15cb3dSCy Schubert * 1052b15cb3dSCy Schubert */ 1062b15cb3dSCy Schubert #ifndef NTP_LISTS_H 1072b15cb3dSCy Schubert #define NTP_LISTS_H 1082b15cb3dSCy Schubert 1092b15cb3dSCy Schubert #include "ntp_types.h" /* TRUE and FALSE */ 1102b15cb3dSCy Schubert #include "ntp_assert.h" 1112b15cb3dSCy Schubert 1122b15cb3dSCy Schubert #ifdef DEBUG 1132b15cb3dSCy Schubert # define NTP_DEBUG_LISTS_H 1142b15cb3dSCy Schubert #endif 1152b15cb3dSCy Schubert 1162b15cb3dSCy Schubert /* 1172b15cb3dSCy Schubert * If list debugging is not enabled, save a little time by not clearing 1182b15cb3dSCy Schubert * an entry's link pointer when it is unlinked, as the stale pointer 1192b15cb3dSCy Schubert * is harmless as long as it is ignored when the entry is not in a 1202b15cb3dSCy Schubert * list. 1212b15cb3dSCy Schubert */ 1222b15cb3dSCy Schubert #ifndef NTP_DEBUG_LISTS_H 1232b15cb3dSCy Schubert #define MAYBE_Z_LISTS(p) do { } while (FALSE) 1242b15cb3dSCy Schubert #else 1252b15cb3dSCy Schubert #define MAYBE_Z_LISTS(p) (p) = NULL 1262b15cb3dSCy Schubert #endif 1272b15cb3dSCy Schubert 1282b15cb3dSCy Schubert #define LINK_SLIST(listhead, pentry, nextlink) \ 1292b15cb3dSCy Schubert do { \ 1302b15cb3dSCy Schubert (pentry)->nextlink = (listhead); \ 1312b15cb3dSCy Schubert (listhead) = (pentry); \ 1322b15cb3dSCy Schubert } while (FALSE) 1332b15cb3dSCy Schubert 1342b15cb3dSCy Schubert #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) \ 1352b15cb3dSCy Schubert do { \ 1362b15cb3dSCy Schubert entrytype **pptail; \ 1372b15cb3dSCy Schubert \ 1382b15cb3dSCy Schubert pptail = &(listhead); \ 1392b15cb3dSCy Schubert while (*pptail != NULL) \ 1402b15cb3dSCy Schubert pptail = &((*pptail)->nextlink); \ 1412b15cb3dSCy Schubert \ 1422b15cb3dSCy Schubert (pentry)->nextlink = NULL; \ 1432b15cb3dSCy Schubert *pptail = (pentry); \ 1442b15cb3dSCy Schubert } while (FALSE) 1452b15cb3dSCy Schubert 1462b15cb3dSCy Schubert #define LINK_SORT_SLIST_CURRENT() (*ppentry) 1472b15cb3dSCy Schubert #define L_S_S_CUR() LINK_SORT_SLIST_CURRENT() 1482b15cb3dSCy Schubert 1492b15cb3dSCy Schubert #define LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, \ 1502b15cb3dSCy Schubert entrytype) \ 1512b15cb3dSCy Schubert do { \ 1522b15cb3dSCy Schubert entrytype **ppentry; \ 1532b15cb3dSCy Schubert \ 1542b15cb3dSCy Schubert ppentry = &(listhead); \ 1552b15cb3dSCy Schubert while (TRUE) { \ 1562b15cb3dSCy Schubert if (NULL == *ppentry || (beforecur)) { \ 1572b15cb3dSCy Schubert (pentry)->nextlink = *ppentry; \ 1582b15cb3dSCy Schubert *ppentry = (pentry); \ 1592b15cb3dSCy Schubert break; \ 1602b15cb3dSCy Schubert } \ 1612b15cb3dSCy Schubert ppentry = &((*ppentry)->nextlink); \ 1622b15cb3dSCy Schubert if (NULL == *ppentry) { \ 1632b15cb3dSCy Schubert (pentry)->nextlink = NULL; \ 1642b15cb3dSCy Schubert *ppentry = (pentry); \ 1652b15cb3dSCy Schubert break; \ 1662b15cb3dSCy Schubert } \ 1672b15cb3dSCy Schubert } \ 1682b15cb3dSCy Schubert } while (FALSE) 1692b15cb3dSCy Schubert 1702b15cb3dSCy Schubert #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink) \ 1712b15cb3dSCy Schubert do { \ 1722b15cb3dSCy Schubert (punlinked) = (listhead); \ 1732b15cb3dSCy Schubert if (NULL != (punlinked)) { \ 1742b15cb3dSCy Schubert (listhead) = (punlinked)->nextlink; \ 1752b15cb3dSCy Schubert MAYBE_Z_LISTS((punlinked)->nextlink); \ 1762b15cb3dSCy Schubert } \ 1772b15cb3dSCy Schubert } while (FALSE) 1782b15cb3dSCy Schubert 1792b15cb3dSCy Schubert #define UNLINK_EXPR_SLIST_CURRENT() (*ppentry) 1802b15cb3dSCy Schubert #define U_E_S_CUR() UNLINK_EXPR_SLIST_CURRENT() 1812b15cb3dSCy Schubert 1822b15cb3dSCy Schubert #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, \ 1832b15cb3dSCy Schubert entrytype) \ 184*f5f40dd6SCy Schubert if (NULL != (listhead)) { \ 1852b15cb3dSCy Schubert entrytype **ppentry; \ 1862b15cb3dSCy Schubert \ 1872b15cb3dSCy Schubert ppentry = &(listhead); \ 1882b15cb3dSCy Schubert \ 1892b15cb3dSCy Schubert while (!(expr)) \ 1902b15cb3dSCy Schubert if (*ppentry != NULL && \ 1912b15cb3dSCy Schubert (*ppentry)->nextlink != NULL) { \ 1922b15cb3dSCy Schubert ppentry = &((*ppentry)->nextlink); \ 1932b15cb3dSCy Schubert } else { \ 1942b15cb3dSCy Schubert ppentry = NULL; \ 1952b15cb3dSCy Schubert break; \ 1962b15cb3dSCy Schubert } \ 1972b15cb3dSCy Schubert \ 1982b15cb3dSCy Schubert if (ppentry != NULL) { \ 1992b15cb3dSCy Schubert (punlinked) = *ppentry; \ 2002b15cb3dSCy Schubert *ppentry = (punlinked)->nextlink; \ 2012b15cb3dSCy Schubert MAYBE_Z_LISTS((punlinked)->nextlink); \ 2022b15cb3dSCy Schubert } else { \ 2032b15cb3dSCy Schubert (punlinked) = NULL; \ 2042b15cb3dSCy Schubert } \ 205*f5f40dd6SCy Schubert } else do { \ 206*f5f40dd6SCy Schubert (punlinked) = NULL; \ 2072b15cb3dSCy Schubert } while (FALSE) 2082b15cb3dSCy Schubert 2092b15cb3dSCy Schubert #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, \ 2102b15cb3dSCy Schubert entrytype) \ 2112b15cb3dSCy Schubert UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) == \ 2122b15cb3dSCy Schubert U_E_S_CUR(), nextlink, entrytype) 2132b15cb3dSCy Schubert 2142b15cb3dSCy Schubert #define CHECK_SLIST(listhead, nextlink, entrytype) \ 2152b15cb3dSCy Schubert do { \ 2162b15cb3dSCy Schubert entrytype *pentry; \ 2172b15cb3dSCy Schubert \ 2182b15cb3dSCy Schubert for (pentry = (listhead); \ 2192b15cb3dSCy Schubert pentry != NULL; \ 2202b15cb3dSCy Schubert pentry = pentry->nextlink) { \ 2219034852cSGleb Smirnoff INSIST(pentry != pentry->nextlink); \ 2229034852cSGleb Smirnoff INSIST((listhead) != pentry->nextlink); \ 2232b15cb3dSCy Schubert } \ 2242b15cb3dSCy Schubert } while (FALSE) 2252b15cb3dSCy Schubert 2262b15cb3dSCy Schubert /* 2272b15cb3dSCy Schubert * FIFO 2282b15cb3dSCy Schubert */ 2292b15cb3dSCy Schubert 2302b15cb3dSCy Schubert #define DECL_FIFO_ANCHOR(entrytype) \ 2312b15cb3dSCy Schubert struct { \ 2322b15cb3dSCy Schubert entrytype * phead; /* NULL if list empty */ \ 2332b15cb3dSCy Schubert entrytype ** pptail; /* NULL if list empty */ \ 2342b15cb3dSCy Schubert } 2352b15cb3dSCy Schubert 2362b15cb3dSCy Schubert #define HEAD_FIFO(anchor) ((anchor).phead) 2372b15cb3dSCy Schubert #define TAIL_FIFO(anchor) ((NULL == (anchor).pptail) \ 2382b15cb3dSCy Schubert ? NULL \ 2392b15cb3dSCy Schubert : *((anchor).pptail)) 2402b15cb3dSCy Schubert 2412b15cb3dSCy Schubert /* 2422b15cb3dSCy Schubert * For DEBUG builds only, verify both or neither of the anchor pointers 2432b15cb3dSCy Schubert * are NULL with each operation. 2442b15cb3dSCy Schubert */ 2452b15cb3dSCy Schubert #if !defined(NTP_DEBUG_LISTS_H) 2462b15cb3dSCy Schubert #define CHECK_FIFO_CONSISTENCY(anchor) do { } while (FALSE) 2472b15cb3dSCy Schubert #else 2482b15cb3dSCy Schubert #define CHECK_FIFO_CONSISTENCY(anchor) \ 2492b15cb3dSCy Schubert check_gen_fifo_consistency(&(anchor)) 2502b15cb3dSCy Schubert void check_gen_fifo_consistency(void *fifo); 2512b15cb3dSCy Schubert #endif 2522b15cb3dSCy Schubert 2532b15cb3dSCy Schubert /* 2542b15cb3dSCy Schubert * generic FIFO element used to access any FIFO where each element 2552b15cb3dSCy Schubert * begins with the link pointer 2562b15cb3dSCy Schubert */ 2572b15cb3dSCy Schubert typedef struct gen_node_tag gen_node; 2582b15cb3dSCy Schubert struct gen_node_tag { 2592b15cb3dSCy Schubert gen_node * link; 2602b15cb3dSCy Schubert }; 2612b15cb3dSCy Schubert 2622b15cb3dSCy Schubert /* generic FIFO */ 2632b15cb3dSCy Schubert typedef DECL_FIFO_ANCHOR(gen_node) gen_fifo; 2642b15cb3dSCy Schubert 2652b15cb3dSCy Schubert 2662b15cb3dSCy Schubert #define LINK_FIFO(anchor, pentry, nextlink) \ 2672b15cb3dSCy Schubert do { \ 2682b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(anchor); \ 2692b15cb3dSCy Schubert \ 2702b15cb3dSCy Schubert (pentry)->nextlink = NULL; \ 2712b15cb3dSCy Schubert if (NULL != (anchor).pptail) { \ 2722b15cb3dSCy Schubert (*((anchor).pptail))->nextlink = (pentry); \ 2732b15cb3dSCy Schubert (anchor).pptail = \ 2742b15cb3dSCy Schubert &(*((anchor).pptail))->nextlink; \ 2752b15cb3dSCy Schubert } else { \ 2762b15cb3dSCy Schubert (anchor).phead = (pentry); \ 2772b15cb3dSCy Schubert (anchor).pptail = &(anchor).phead; \ 2782b15cb3dSCy Schubert } \ 2792b15cb3dSCy Schubert \ 2802b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(anchor); \ 2812b15cb3dSCy Schubert } while (FALSE) 2822b15cb3dSCy Schubert 2832b15cb3dSCy Schubert #define UNLINK_FIFO(punlinked, anchor, nextlink) \ 2842b15cb3dSCy Schubert do { \ 2852b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(anchor); \ 2862b15cb3dSCy Schubert \ 2872b15cb3dSCy Schubert (punlinked) = (anchor).phead; \ 2882b15cb3dSCy Schubert if (NULL != (punlinked)) { \ 2892b15cb3dSCy Schubert (anchor).phead = (punlinked)->nextlink; \ 2902b15cb3dSCy Schubert if (NULL == (anchor).phead) \ 2912b15cb3dSCy Schubert (anchor).pptail = NULL; \ 2922b15cb3dSCy Schubert else if ((anchor).pptail == \ 2932b15cb3dSCy Schubert &(punlinked)->nextlink) \ 2942b15cb3dSCy Schubert (anchor).pptail = &(anchor).phead; \ 2952b15cb3dSCy Schubert MAYBE_Z_LISTS((punlinked)->nextlink); \ 2962b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(anchor); \ 2972b15cb3dSCy Schubert } \ 2982b15cb3dSCy Schubert } while (FALSE) 2992b15cb3dSCy Schubert 3002b15cb3dSCy Schubert #define UNLINK_MID_FIFO(punlinked, anchor, tounlink, nextlink, \ 3012b15cb3dSCy Schubert entrytype) \ 3022b15cb3dSCy Schubert do { \ 3032b15cb3dSCy Schubert entrytype **ppentry; \ 3042b15cb3dSCy Schubert \ 3052b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(anchor); \ 3062b15cb3dSCy Schubert \ 3072b15cb3dSCy Schubert ppentry = &(anchor).phead; \ 3082b15cb3dSCy Schubert \ 3092b15cb3dSCy Schubert while ((tounlink) != *ppentry) \ 3102b15cb3dSCy Schubert if ((*ppentry)->nextlink != NULL) { \ 3112b15cb3dSCy Schubert ppentry = &((*ppentry)->nextlink); \ 3122b15cb3dSCy Schubert } else { \ 3132b15cb3dSCy Schubert ppentry = NULL; \ 3142b15cb3dSCy Schubert break; \ 3152b15cb3dSCy Schubert } \ 3162b15cb3dSCy Schubert \ 3172b15cb3dSCy Schubert if (ppentry != NULL) { \ 3182b15cb3dSCy Schubert (punlinked) = *ppentry; \ 3192b15cb3dSCy Schubert *ppentry = (punlinked)->nextlink; \ 3202b15cb3dSCy Schubert if (NULL == *ppentry) \ 3212b15cb3dSCy Schubert (anchor).pptail = NULL; \ 3222b15cb3dSCy Schubert else if ((anchor).pptail == \ 3232b15cb3dSCy Schubert &(punlinked)->nextlink) \ 3242b15cb3dSCy Schubert (anchor).pptail = &(anchor).phead; \ 3252b15cb3dSCy Schubert MAYBE_Z_LISTS((punlinked)->nextlink); \ 3262b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(anchor); \ 3272b15cb3dSCy Schubert } else { \ 3282b15cb3dSCy Schubert (punlinked) = NULL; \ 3292b15cb3dSCy Schubert } \ 3302b15cb3dSCy Schubert } while (FALSE) 3312b15cb3dSCy Schubert 3322b15cb3dSCy Schubert #define CONCAT_FIFO(f1, f2, nextlink) \ 3332b15cb3dSCy Schubert do { \ 3342b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(f1); \ 3352b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(f2); \ 3362b15cb3dSCy Schubert \ 3372b15cb3dSCy Schubert if ((f2).pptail != NULL) { \ 3382b15cb3dSCy Schubert if ((f1).pptail != NULL) { \ 3392b15cb3dSCy Schubert (*(f1).pptail)->nextlink = (f2).phead; \ 3402b15cb3dSCy Schubert if ((f2).pptail == &(f2).phead) \ 3412b15cb3dSCy Schubert (f1).pptail = \ 3422b15cb3dSCy Schubert &(*(f1).pptail)->nextlink; \ 3432b15cb3dSCy Schubert else \ 3442b15cb3dSCy Schubert (f1).pptail = (f2).pptail; \ 3452b15cb3dSCy Schubert CHECK_FIFO_CONSISTENCY(f1); \ 3462b15cb3dSCy Schubert } else { \ 3472b15cb3dSCy Schubert (f1) = (f2); \ 3482b15cb3dSCy Schubert } \ 3492b15cb3dSCy Schubert MAYBE_Z_LISTS((f2).phead); \ 3502b15cb3dSCy Schubert MAYBE_Z_LISTS((f2).pptail); \ 3512b15cb3dSCy Schubert } \ 3522b15cb3dSCy Schubert } while (FALSE) 3532b15cb3dSCy Schubert 3542b15cb3dSCy Schubert /* 3552b15cb3dSCy Schubert * DLIST 3562b15cb3dSCy Schubert */ 3572b15cb3dSCy Schubert #define DECL_DLIST_LINK(entrytype, link) \ 3582b15cb3dSCy Schubert struct { \ 3592b15cb3dSCy Schubert entrytype * b; \ 3602b15cb3dSCy Schubert entrytype * f; \ 3612b15cb3dSCy Schubert } link 3622b15cb3dSCy Schubert 3632b15cb3dSCy Schubert #define INIT_DLIST(listhead, link) \ 3642b15cb3dSCy Schubert do { \ 3652b15cb3dSCy Schubert (listhead).link.f = &(listhead); \ 3662b15cb3dSCy Schubert (listhead).link.b = &(listhead); \ 3672b15cb3dSCy Schubert } while (FALSE) 3682b15cb3dSCy Schubert 3692b15cb3dSCy Schubert #define HEAD_DLIST(listhead, link) \ 3702b15cb3dSCy Schubert ( \ 3712b15cb3dSCy Schubert (&(listhead) != (listhead).link.f) \ 3722b15cb3dSCy Schubert ? (listhead).link.f \ 3732b15cb3dSCy Schubert : NULL \ 3742b15cb3dSCy Schubert ) 3752b15cb3dSCy Schubert 3762b15cb3dSCy Schubert #define TAIL_DLIST(listhead, link) \ 3772b15cb3dSCy Schubert ( \ 3782b15cb3dSCy Schubert (&(listhead) != (listhead).link.b) \ 3792b15cb3dSCy Schubert ? (listhead).link.b \ 3802b15cb3dSCy Schubert : NULL \ 3812b15cb3dSCy Schubert ) 3822b15cb3dSCy Schubert 3832b15cb3dSCy Schubert #define NEXT_DLIST(listhead, entry, link) \ 3842b15cb3dSCy Schubert ( \ 3852b15cb3dSCy Schubert (&(listhead) != (entry)->link.f) \ 3862b15cb3dSCy Schubert ? (entry)->link.f \ 3872b15cb3dSCy Schubert : NULL \ 3882b15cb3dSCy Schubert ) 3892b15cb3dSCy Schubert 3902b15cb3dSCy Schubert #define PREV_DLIST(listhead, entry, link) \ 3912b15cb3dSCy Schubert ( \ 3922b15cb3dSCy Schubert (&(listhead) != (entry)->link.b) \ 3932b15cb3dSCy Schubert ? (entry)->link.b \ 3942b15cb3dSCy Schubert : NULL \ 3952b15cb3dSCy Schubert ) 3962b15cb3dSCy Schubert 3972b15cb3dSCy Schubert #define LINK_DLIST(listhead, pentry, link) \ 3982b15cb3dSCy Schubert do { \ 3992b15cb3dSCy Schubert (pentry)->link.f = (listhead).link.f; \ 4002b15cb3dSCy Schubert (pentry)->link.b = &(listhead); \ 4012b15cb3dSCy Schubert (listhead).link.f->link.b = (pentry); \ 4022b15cb3dSCy Schubert (listhead).link.f = (pentry); \ 4032b15cb3dSCy Schubert } while (FALSE) 4042b15cb3dSCy Schubert 4052b15cb3dSCy Schubert #define LINK_TAIL_DLIST(listhead, pentry, link) \ 4062b15cb3dSCy Schubert do { \ 4072b15cb3dSCy Schubert (pentry)->link.b = (listhead).link.b; \ 4082b15cb3dSCy Schubert (pentry)->link.f = &(listhead); \ 4092b15cb3dSCy Schubert (listhead).link.b->link.f = (pentry); \ 4102b15cb3dSCy Schubert (listhead).link.b = (pentry); \ 4112b15cb3dSCy Schubert } while (FALSE) 4122b15cb3dSCy Schubert 4132b15cb3dSCy Schubert #define UNLINK_DLIST(ptounlink, link) \ 4142b15cb3dSCy Schubert do { \ 4152b15cb3dSCy Schubert (ptounlink)->link.b->link.f = (ptounlink)->link.f; \ 4162b15cb3dSCy Schubert (ptounlink)->link.f->link.b = (ptounlink)->link.b; \ 4172b15cb3dSCy Schubert MAYBE_Z_LISTS((ptounlink)->link.b); \ 4182b15cb3dSCy Schubert MAYBE_Z_LISTS((ptounlink)->link.f); \ 4192b15cb3dSCy Schubert } while (FALSE) 4202b15cb3dSCy Schubert 4212b15cb3dSCy Schubert #define ITER_DLIST_BEGIN(listhead, iter, link, entrytype) \ 4222b15cb3dSCy Schubert { \ 4232b15cb3dSCy Schubert entrytype *i_dl_nextiter; \ 4242b15cb3dSCy Schubert \ 4252b15cb3dSCy Schubert for ((iter) = (listhead).link.f; \ 4262b15cb3dSCy Schubert (iter) != &(listhead) \ 4272b15cb3dSCy Schubert && ((i_dl_nextiter = (iter)->link.f), TRUE); \ 4282b15cb3dSCy Schubert (iter) = i_dl_nextiter) { 4292b15cb3dSCy Schubert #define ITER_DLIST_END() \ 4302b15cb3dSCy Schubert } \ 4312b15cb3dSCy Schubert } 4322b15cb3dSCy Schubert 4332b15cb3dSCy Schubert #define REV_ITER_DLIST_BEGIN(listhead, iter, link, entrytype) \ 4342b15cb3dSCy Schubert { \ 4352b15cb3dSCy Schubert entrytype *i_dl_nextiter; \ 4362b15cb3dSCy Schubert \ 4372b15cb3dSCy Schubert for ((iter) = (listhead).link.b; \ 4382b15cb3dSCy Schubert (iter) != &(listhead) \ 4392b15cb3dSCy Schubert && ((i_dl_nextiter = (iter)->link.b), TRUE); \ 4402b15cb3dSCy Schubert (iter) = i_dl_nextiter) { 4412b15cb3dSCy Schubert #define REV_ITER_DLIST_END() \ 4422b15cb3dSCy Schubert } \ 4432b15cb3dSCy Schubert } 4442b15cb3dSCy Schubert 4452b15cb3dSCy Schubert #endif /* NTP_LISTS_H */ 446