1*9e9fa66aSchristos /* $NetBSD: ntp_lists.h,v 1.8 2024/10/01 20:59:51 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4f003fb54Skardel * ntp_lists.h - linked lists common code 5f003fb54Skardel * 6f003fb54Skardel * SLIST: singly-linked lists 7f003fb54Skardel * ========================== 8abb0f93cSkardel * 9abb0f93cSkardel * These macros implement a simple singly-linked list template. Both 10abb0f93cSkardel * the listhead and per-entry next fields are declared as pointers to 11abb0f93cSkardel * the list entry struct type. Initialization to NULL is typically 12abb0f93cSkardel * implicit (for globals and statics) or handled by zeroing of the 13abb0f93cSkardel * containing structure. 14abb0f93cSkardel * 15abb0f93cSkardel * The name of the next link field is passed as an argument to allow 16abb0f93cSkardel * membership in several lists at once using multiple next link fields. 17abb0f93cSkardel * 18abb0f93cSkardel * When possible, placing the link field first in the entry structure 19abb0f93cSkardel * allows slightly smaller code to be generated on some platforms. 20abb0f93cSkardel * 21abb0f93cSkardel * LINK_SLIST(listhead, pentry, nextlink) 22abb0f93cSkardel * add entry at head 23abb0f93cSkardel * 24abb0f93cSkardel * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) 25f003fb54Skardel * add entry at tail. This is O(n), if this is a common 26f003fb54Skardel * operation the FIFO template may be more appropriate. 27f003fb54Skardel * 28f003fb54Skardel * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype) 29f003fb54Skardel * add entry in sorted order. beforecur is an expression comparing 30f003fb54Skardel * pentry with the current list entry. The current entry can be 31f003fb54Skardel * referenced within beforecur as L_S_S_CUR(), which is short for 32f003fb54Skardel * LINK_SORT_SLIST_CUR(). beforecur is nonzero if pentry sorts 33f003fb54Skardel * before L_S_S_CUR(). 34abb0f93cSkardel * 35abb0f93cSkardel * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink) 36abb0f93cSkardel * unlink first entry and point punlinked to it, or set punlinked 37abb0f93cSkardel * to NULL if the list is empty. 38abb0f93cSkardel * 39abb0f93cSkardel * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype) 40abb0f93cSkardel * unlink entry pointed to by ptounlink. punlinked is set to NULL 41abb0f93cSkardel * if the entry is not found on the list, otherwise it is set to 42abb0f93cSkardel * ptounlink. 43abb0f93cSkardel * 44abb0f93cSkardel * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype) 45abb0f93cSkardel * unlink entry where expression expr is nonzero. expr can refer 46f003fb54Skardel * to the entry being tested using UNLINK_EXPR_SLIST_CURRENT(), 47f003fb54Skardel * alias U_E_S_CUR(). See the implementation of UNLINK_SLIST() 48f003fb54Skardel * below for an example. U_E_S_CUR() is NULL iff the list is empty. 49abb0f93cSkardel * punlinked is pointed to the removed entry or NULL if none 50abb0f93cSkardel * satisfy expr. 51f003fb54Skardel * 52f003fb54Skardel * FIFO: singly-linked lists plus tail pointer 53f003fb54Skardel * =========================================== 54f003fb54Skardel * 55f003fb54Skardel * This is the same as FreeBSD's sys/queue.h STAILQ -- a singly-linked 56f003fb54Skardel * list implementation with tail-pointer maintenance, so that adding 57f003fb54Skardel * at the tail for first-in, first-out access is O(1). 58f003fb54Skardel * 59f003fb54Skardel * DECL_FIFO_ANCHOR(entrytype) 60f003fb54Skardel * provides the type specification portion of the declaration for 61f003fb54Skardel * a variable to refer to a FIFO queue (similar to listhead). The 62f003fb54Skardel * anchor contains the head and indirect tail pointers. Example: 63f003fb54Skardel * 64f003fb54Skardel * #include "ntp_lists.h" 65f003fb54Skardel * 66f003fb54Skardel * typedef struct myentry_tag myentry; 67f003fb54Skardel * struct myentry_tag { 68f003fb54Skardel * myentry *next_link; 69f003fb54Skardel * ... 70f003fb54Skardel * }; 71f003fb54Skardel * 72f003fb54Skardel * DECL_FIFO_ANCHOR(myentry) my_fifo; 73f003fb54Skardel * 74f003fb54Skardel * void somefunc(myentry *pentry) 75f003fb54Skardel * { 76f003fb54Skardel * LINK_FIFO(my_fifo, pentry, next_link); 77f003fb54Skardel * } 78f003fb54Skardel * 79f003fb54Skardel * If DECL_FIFO_ANCHOR is used with stack or heap storage, it 80f003fb54Skardel * should be initialized to NULL pointers using a = { NULL }; 81f003fb54Skardel * initializer or memset. 82f003fb54Skardel * 83f003fb54Skardel * HEAD_FIFO(anchor) 84f003fb54Skardel * TAIL_FIFO(anchor) 85f003fb54Skardel * Pointer to first/last entry, NULL if FIFO is empty. 86f003fb54Skardel * 87f003fb54Skardel * LINK_FIFO(anchor, pentry, nextlink) 88f003fb54Skardel * add entry at tail. 89f003fb54Skardel * 90f003fb54Skardel * UNLINK_FIFO(punlinked, anchor, nextlink) 91f003fb54Skardel * unlink head entry and point punlinked to it, or set punlinked 92f003fb54Skardel * to NULL if the list is empty. 93f003fb54Skardel * 94f003fb54Skardel * CONCAT_FIFO(q1, q2, nextlink) 95f003fb54Skardel * empty fifoq q2 moving its nodes to q1 following q1's existing 96f003fb54Skardel * nodes. 97f003fb54Skardel * 98f003fb54Skardel * DLIST: doubly-linked lists 99f003fb54Skardel * ========================== 100f003fb54Skardel * 101f003fb54Skardel * Elements on DLISTs always have non-NULL forward and back links, 102f003fb54Skardel * because both link chains are circular. The beginning/end is marked 103f003fb54Skardel * by the listhead, which is the same type as elements for simplicity. 104f003fb54Skardel * An empty list's listhead has both links set to its own address. 105f003fb54Skardel * 106f003fb54Skardel * 107abb0f93cSkardel */ 108abb0f93cSkardel #ifndef NTP_LISTS_H 109abb0f93cSkardel #define NTP_LISTS_H 110abb0f93cSkardel 111f003fb54Skardel #include "ntp_types.h" /* TRUE and FALSE */ 112f003fb54Skardel #include "ntp_assert.h" 113f003fb54Skardel 114f003fb54Skardel #ifdef DEBUG 115f003fb54Skardel # define NTP_DEBUG_LISTS_H 116abb0f93cSkardel #endif 117abb0f93cSkardel 118f003fb54Skardel /* 119f003fb54Skardel * If list debugging is not enabled, save a little time by not clearing 120f003fb54Skardel * an entry's link pointer when it is unlinked, as the stale pointer 121f003fb54Skardel * is harmless as long as it is ignored when the entry is not in a 122f003fb54Skardel * list. 123f003fb54Skardel */ 124f003fb54Skardel #ifndef NTP_DEBUG_LISTS_H 125f003fb54Skardel #define MAYBE_Z_LISTS(p) do { } while (FALSE) 126f003fb54Skardel #else 127f003fb54Skardel #define MAYBE_Z_LISTS(p) (p) = NULL 128f003fb54Skardel #endif 129abb0f93cSkardel 130abb0f93cSkardel #define LINK_SLIST(listhead, pentry, nextlink) \ 131abb0f93cSkardel do { \ 132abb0f93cSkardel (pentry)->nextlink = (listhead); \ 133abb0f93cSkardel (listhead) = (pentry); \ 134f003fb54Skardel } while (FALSE) 135abb0f93cSkardel 136abb0f93cSkardel #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype) \ 137abb0f93cSkardel do { \ 138abb0f93cSkardel entrytype **pptail; \ 139abb0f93cSkardel \ 140abb0f93cSkardel pptail = &(listhead); \ 141abb0f93cSkardel while (*pptail != NULL) \ 142abb0f93cSkardel pptail = &((*pptail)->nextlink); \ 143abb0f93cSkardel \ 144abb0f93cSkardel (pentry)->nextlink = NULL; \ 145abb0f93cSkardel *pptail = (pentry); \ 146f003fb54Skardel } while (FALSE) 147f003fb54Skardel 148f003fb54Skardel #define LINK_SORT_SLIST_CURRENT() (*ppentry) 149f003fb54Skardel #define L_S_S_CUR() LINK_SORT_SLIST_CURRENT() 150f003fb54Skardel 151f003fb54Skardel #define LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, \ 152f003fb54Skardel entrytype) \ 153f003fb54Skardel do { \ 154f003fb54Skardel entrytype **ppentry; \ 155f003fb54Skardel \ 156f003fb54Skardel ppentry = &(listhead); \ 157f003fb54Skardel while (TRUE) { \ 158*9e9fa66aSchristos if (beforecur) { \ 159f003fb54Skardel (pentry)->nextlink = *ppentry; \ 160f003fb54Skardel *ppentry = (pentry); \ 161f003fb54Skardel break; \ 162f003fb54Skardel } \ 163f003fb54Skardel ppentry = &((*ppentry)->nextlink); \ 164f003fb54Skardel if (NULL == *ppentry) { \ 165f003fb54Skardel (pentry)->nextlink = NULL; \ 166f003fb54Skardel *ppentry = (pentry); \ 167f003fb54Skardel break; \ 168f003fb54Skardel } \ 169f003fb54Skardel } \ 170f003fb54Skardel } while (FALSE) 171abb0f93cSkardel 172abb0f93cSkardel #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink) \ 173abb0f93cSkardel do { \ 174abb0f93cSkardel (punlinked) = (listhead); \ 175abb0f93cSkardel if (NULL != (punlinked)) { \ 176abb0f93cSkardel (listhead) = (punlinked)->nextlink; \ 177f003fb54Skardel MAYBE_Z_LISTS((punlinked)->nextlink); \ 178abb0f93cSkardel } \ 179f003fb54Skardel } while (FALSE) 180f003fb54Skardel 181f003fb54Skardel #define UNLINK_EXPR_SLIST_CURRENT() (*ppentry) 182f003fb54Skardel #define U_E_S_CUR() UNLINK_EXPR_SLIST_CURRENT() 183abb0f93cSkardel 184abb0f93cSkardel #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, \ 185abb0f93cSkardel entrytype) \ 186eabc0478Schristos if (NULL != (listhead)) { \ 187abb0f93cSkardel entrytype **ppentry; \ 188abb0f93cSkardel \ 189abb0f93cSkardel ppentry = &(listhead); \ 190abb0f93cSkardel \ 191abb0f93cSkardel while (!(expr)) \ 192f003fb54Skardel if (*ppentry != NULL && \ 193f003fb54Skardel (*ppentry)->nextlink != NULL) { \ 194abb0f93cSkardel ppentry = &((*ppentry)->nextlink); \ 195f003fb54Skardel } else { \ 196abb0f93cSkardel ppentry = NULL; \ 197abb0f93cSkardel break; \ 198abb0f93cSkardel } \ 199abb0f93cSkardel \ 200abb0f93cSkardel if (ppentry != NULL) { \ 201abb0f93cSkardel (punlinked) = *ppentry; \ 202abb0f93cSkardel *ppentry = (punlinked)->nextlink; \ 203f003fb54Skardel MAYBE_Z_LISTS((punlinked)->nextlink); \ 204f003fb54Skardel } else { \ 205abb0f93cSkardel (punlinked) = NULL; \ 206f003fb54Skardel } \ 207eabc0478Schristos } else do { \ 208eabc0478Schristos (punlinked) = NULL; \ 209f003fb54Skardel } while (FALSE) 210abb0f93cSkardel 211abb0f93cSkardel #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, \ 212abb0f93cSkardel entrytype) \ 213abb0f93cSkardel UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) == \ 214f003fb54Skardel U_E_S_CUR(), nextlink, entrytype) 215f003fb54Skardel 216f003fb54Skardel #define CHECK_SLIST(listhead, nextlink, entrytype) \ 217f003fb54Skardel do { \ 218f003fb54Skardel entrytype *pentry; \ 219f003fb54Skardel \ 220f003fb54Skardel for (pentry = (listhead); \ 221f003fb54Skardel pentry != NULL; \ 222f003fb54Skardel pentry = pentry->nextlink) { \ 223af12ab5eSchristos INSIST(pentry != pentry->nextlink); \ 224af12ab5eSchristos INSIST((listhead) != pentry->nextlink); \ 225f003fb54Skardel } \ 226f003fb54Skardel } while (FALSE) 227f003fb54Skardel 228f003fb54Skardel /* 229f003fb54Skardel * FIFO 230f003fb54Skardel */ 231f003fb54Skardel 232f003fb54Skardel #define DECL_FIFO_ANCHOR(entrytype) \ 233f003fb54Skardel struct { \ 234f003fb54Skardel entrytype * phead; /* NULL if list empty */ \ 235f003fb54Skardel entrytype ** pptail; /* NULL if list empty */ \ 236f003fb54Skardel } 237f003fb54Skardel 238f003fb54Skardel #define HEAD_FIFO(anchor) ((anchor).phead) 239f003fb54Skardel #define TAIL_FIFO(anchor) ((NULL == (anchor).pptail) \ 240f003fb54Skardel ? NULL \ 241f003fb54Skardel : *((anchor).pptail)) 242f003fb54Skardel 243f003fb54Skardel /* 244f003fb54Skardel * For DEBUG builds only, verify both or neither of the anchor pointers 245f003fb54Skardel * are NULL with each operation. 246f003fb54Skardel */ 247f003fb54Skardel #if !defined(NTP_DEBUG_LISTS_H) 248f003fb54Skardel #define CHECK_FIFO_CONSISTENCY(anchor) do { } while (FALSE) 249f003fb54Skardel #else 250f003fb54Skardel #define CHECK_FIFO_CONSISTENCY(anchor) \ 251f003fb54Skardel check_gen_fifo_consistency(&(anchor)) 252f003fb54Skardel void check_gen_fifo_consistency(void *fifo); 253f003fb54Skardel #endif 254f003fb54Skardel 255f003fb54Skardel /* 256f003fb54Skardel * generic FIFO element used to access any FIFO where each element 257f003fb54Skardel * begins with the link pointer 258f003fb54Skardel */ 259f003fb54Skardel typedef struct gen_node_tag gen_node; 260f003fb54Skardel struct gen_node_tag { 261f003fb54Skardel gen_node * link; 262f003fb54Skardel }; 263f003fb54Skardel 264f003fb54Skardel /* generic FIFO */ 265f003fb54Skardel typedef DECL_FIFO_ANCHOR(gen_node) gen_fifo; 266f003fb54Skardel 267f003fb54Skardel 268f003fb54Skardel #define LINK_FIFO(anchor, pentry, nextlink) \ 269f003fb54Skardel do { \ 270f003fb54Skardel CHECK_FIFO_CONSISTENCY(anchor); \ 271f003fb54Skardel \ 272f003fb54Skardel (pentry)->nextlink = NULL; \ 273f003fb54Skardel if (NULL != (anchor).pptail) { \ 274f003fb54Skardel (*((anchor).pptail))->nextlink = (pentry); \ 275f003fb54Skardel (anchor).pptail = \ 276f003fb54Skardel &(*((anchor).pptail))->nextlink; \ 277f003fb54Skardel } else { \ 278f003fb54Skardel (anchor).phead = (pentry); \ 279f003fb54Skardel (anchor).pptail = &(anchor).phead; \ 280f003fb54Skardel } \ 281f003fb54Skardel \ 282f003fb54Skardel CHECK_FIFO_CONSISTENCY(anchor); \ 283f003fb54Skardel } while (FALSE) 284f003fb54Skardel 285f003fb54Skardel #define UNLINK_FIFO(punlinked, anchor, nextlink) \ 286f003fb54Skardel do { \ 287f003fb54Skardel CHECK_FIFO_CONSISTENCY(anchor); \ 288f003fb54Skardel \ 289f003fb54Skardel (punlinked) = (anchor).phead; \ 290f003fb54Skardel if (NULL != (punlinked)) { \ 291f003fb54Skardel (anchor).phead = (punlinked)->nextlink; \ 292f003fb54Skardel if (NULL == (anchor).phead) \ 293f003fb54Skardel (anchor).pptail = NULL; \ 294f003fb54Skardel else if ((anchor).pptail == \ 295f003fb54Skardel &(punlinked)->nextlink) \ 296f003fb54Skardel (anchor).pptail = &(anchor).phead; \ 297f003fb54Skardel MAYBE_Z_LISTS((punlinked)->nextlink); \ 298f003fb54Skardel CHECK_FIFO_CONSISTENCY(anchor); \ 299f003fb54Skardel } \ 300f003fb54Skardel } while (FALSE) 301f003fb54Skardel 302f003fb54Skardel #define UNLINK_MID_FIFO(punlinked, anchor, tounlink, nextlink, \ 303f003fb54Skardel entrytype) \ 304f003fb54Skardel do { \ 305f003fb54Skardel entrytype **ppentry; \ 306f003fb54Skardel \ 307f003fb54Skardel CHECK_FIFO_CONSISTENCY(anchor); \ 308f003fb54Skardel \ 309f003fb54Skardel ppentry = &(anchor).phead; \ 310f003fb54Skardel \ 311f003fb54Skardel while ((tounlink) != *ppentry) \ 312f003fb54Skardel if ((*ppentry)->nextlink != NULL) { \ 313f003fb54Skardel ppentry = &((*ppentry)->nextlink); \ 314f003fb54Skardel } else { \ 315f003fb54Skardel ppentry = NULL; \ 316f003fb54Skardel break; \ 317f003fb54Skardel } \ 318f003fb54Skardel \ 319f003fb54Skardel if (ppentry != NULL) { \ 320f003fb54Skardel (punlinked) = *ppentry; \ 321f003fb54Skardel *ppentry = (punlinked)->nextlink; \ 322f003fb54Skardel if (NULL == *ppentry) \ 323f003fb54Skardel (anchor).pptail = NULL; \ 324f003fb54Skardel else if ((anchor).pptail == \ 325f003fb54Skardel &(punlinked)->nextlink) \ 326f003fb54Skardel (anchor).pptail = &(anchor).phead; \ 327f003fb54Skardel MAYBE_Z_LISTS((punlinked)->nextlink); \ 328f003fb54Skardel CHECK_FIFO_CONSISTENCY(anchor); \ 329f003fb54Skardel } else { \ 330f003fb54Skardel (punlinked) = NULL; \ 331f003fb54Skardel } \ 332f003fb54Skardel } while (FALSE) 333f003fb54Skardel 334f003fb54Skardel #define CONCAT_FIFO(f1, f2, nextlink) \ 335f003fb54Skardel do { \ 336f003fb54Skardel CHECK_FIFO_CONSISTENCY(f1); \ 337f003fb54Skardel CHECK_FIFO_CONSISTENCY(f2); \ 338f003fb54Skardel \ 339f003fb54Skardel if ((f2).pptail != NULL) { \ 340f003fb54Skardel if ((f1).pptail != NULL) { \ 341f003fb54Skardel (*(f1).pptail)->nextlink = (f2).phead; \ 342f003fb54Skardel if ((f2).pptail == &(f2).phead) \ 343f003fb54Skardel (f1).pptail = \ 344f003fb54Skardel &(*(f1).pptail)->nextlink; \ 345f003fb54Skardel else \ 346f003fb54Skardel (f1).pptail = (f2).pptail; \ 347f003fb54Skardel CHECK_FIFO_CONSISTENCY(f1); \ 348f003fb54Skardel } else { \ 349f003fb54Skardel (f1) = (f2); \ 350f003fb54Skardel } \ 351f003fb54Skardel MAYBE_Z_LISTS((f2).phead); \ 352f003fb54Skardel MAYBE_Z_LISTS((f2).pptail); \ 353f003fb54Skardel } \ 354f003fb54Skardel } while (FALSE) 355f003fb54Skardel 356f003fb54Skardel /* 357f003fb54Skardel * DLIST 358f003fb54Skardel */ 359f003fb54Skardel #define DECL_DLIST_LINK(entrytype, link) \ 360f003fb54Skardel struct { \ 361f003fb54Skardel entrytype * b; \ 362f003fb54Skardel entrytype * f; \ 363f003fb54Skardel } link 364f003fb54Skardel 365f003fb54Skardel #define INIT_DLIST(listhead, link) \ 366f003fb54Skardel do { \ 367f003fb54Skardel (listhead).link.f = &(listhead); \ 368f003fb54Skardel (listhead).link.b = &(listhead); \ 369f003fb54Skardel } while (FALSE) 370f003fb54Skardel 371f003fb54Skardel #define HEAD_DLIST(listhead, link) \ 372f003fb54Skardel ( \ 373f003fb54Skardel (&(listhead) != (listhead).link.f) \ 374f003fb54Skardel ? (listhead).link.f \ 375f003fb54Skardel : NULL \ 376f003fb54Skardel ) 377f003fb54Skardel 378f003fb54Skardel #define TAIL_DLIST(listhead, link) \ 379f003fb54Skardel ( \ 380f003fb54Skardel (&(listhead) != (listhead).link.b) \ 381f003fb54Skardel ? (listhead).link.b \ 382f003fb54Skardel : NULL \ 383f003fb54Skardel ) 384f003fb54Skardel 385f003fb54Skardel #define NEXT_DLIST(listhead, entry, link) \ 386f003fb54Skardel ( \ 387f003fb54Skardel (&(listhead) != (entry)->link.f) \ 388f003fb54Skardel ? (entry)->link.f \ 389f003fb54Skardel : NULL \ 390f003fb54Skardel ) 391f003fb54Skardel 392f003fb54Skardel #define PREV_DLIST(listhead, entry, link) \ 393f003fb54Skardel ( \ 394f003fb54Skardel (&(listhead) != (entry)->link.b) \ 395f003fb54Skardel ? (entry)->link.b \ 396f003fb54Skardel : NULL \ 397f003fb54Skardel ) 398f003fb54Skardel 399f003fb54Skardel #define LINK_DLIST(listhead, pentry, link) \ 400f003fb54Skardel do { \ 401f003fb54Skardel (pentry)->link.f = (listhead).link.f; \ 402f003fb54Skardel (pentry)->link.b = &(listhead); \ 403f003fb54Skardel (listhead).link.f->link.b = (pentry); \ 404f003fb54Skardel (listhead).link.f = (pentry); \ 405f003fb54Skardel } while (FALSE) 406f003fb54Skardel 407f003fb54Skardel #define LINK_TAIL_DLIST(listhead, pentry, link) \ 408f003fb54Skardel do { \ 409f003fb54Skardel (pentry)->link.b = (listhead).link.b; \ 410f003fb54Skardel (pentry)->link.f = &(listhead); \ 411f003fb54Skardel (listhead).link.b->link.f = (pentry); \ 412f003fb54Skardel (listhead).link.b = (pentry); \ 413f003fb54Skardel } while (FALSE) 414f003fb54Skardel 415f003fb54Skardel #define UNLINK_DLIST(ptounlink, link) \ 416f003fb54Skardel do { \ 417f003fb54Skardel (ptounlink)->link.b->link.f = (ptounlink)->link.f; \ 418f003fb54Skardel (ptounlink)->link.f->link.b = (ptounlink)->link.b; \ 419f003fb54Skardel MAYBE_Z_LISTS((ptounlink)->link.b); \ 420f003fb54Skardel MAYBE_Z_LISTS((ptounlink)->link.f); \ 421f003fb54Skardel } while (FALSE) 422f003fb54Skardel 423f003fb54Skardel #define ITER_DLIST_BEGIN(listhead, iter, link, entrytype) \ 424f003fb54Skardel { \ 425f003fb54Skardel entrytype *i_dl_nextiter; \ 426f003fb54Skardel \ 427f003fb54Skardel for ((iter) = (listhead).link.f; \ 428f003fb54Skardel (iter) != &(listhead) \ 429f003fb54Skardel && ((i_dl_nextiter = (iter)->link.f), TRUE); \ 430f003fb54Skardel (iter) = i_dl_nextiter) { 431f003fb54Skardel #define ITER_DLIST_END() \ 432f003fb54Skardel } \ 433f003fb54Skardel } 434f003fb54Skardel 435f003fb54Skardel #define REV_ITER_DLIST_BEGIN(listhead, iter, link, entrytype) \ 436f003fb54Skardel { \ 437f003fb54Skardel entrytype *i_dl_nextiter; \ 438f003fb54Skardel \ 439f003fb54Skardel for ((iter) = (listhead).link.b; \ 440f003fb54Skardel (iter) != &(listhead) \ 441f003fb54Skardel && ((i_dl_nextiter = (iter)->link.b), TRUE); \ 442f003fb54Skardel (iter) = i_dl_nextiter) { 443f003fb54Skardel #define REV_ITER_DLIST_END() \ 444f003fb54Skardel } \ 445f003fb54Skardel } 446abb0f93cSkardel 447abb0f93cSkardel #endif /* NTP_LISTS_H */ 448