suitcase

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

utlist.h (81585B)


      1 /*
      2 Copyright (c) 2007-2022, Troy D. Hanson  https://troydhanson.github.io/uthash/
      3 All rights reserved.
      4 
      5 Redistribution and use in source and binary forms, with or without
      6 modification, are permitted provided that the following conditions are met:
      7 
      8     * Redistributions of source code must retain the above copyright
      9       notice, this list of conditions and the following disclaimer.
     10 
     11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     12 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     13 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     14 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     15 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     16 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     17 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     18 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     19 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     20 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     22 */
     23 
     24 #ifndef UTLIST_H
     25 #define UTLIST_H
     26 
     27 #define UTLIST_VERSION 2.3.0
     28 
     29 #include <assert.h>
     30 
     31 /*
     32  * This file contains macros to manipulate singly and doubly-linked lists.
     33  *
     34  * 1. LL_ macros:  singly-linked lists.
     35  * 2. DL_ macros:  doubly-linked lists.
     36  * 3. CDL_ macros: circular doubly-linked lists.
     37  *
     38  * To use singly-linked lists, your structure must have a "next" pointer.
     39  * To use doubly-linked lists, your structure must "prev" and "next" pointers.
     40  * Either way, the pointer to the head of the list must be initialized to NULL.
     41  *
     42  * ----------------.EXAMPLE -------------------------
     43  * struct item {
     44  *      int id;
     45  *      struct item *prev, *next;
     46  * }
     47  *
     48  * struct item *list = NULL:
     49  *
     50  * int main() {
     51  *      struct item *item;
     52  *      ... allocate and populate item ...
     53  *      DL_APPEND(list, item);
     54  * }
     55  * --------------------------------------------------
     56  *
     57  * For doubly-linked lists, the append and delete macros are O(1)
     58  * For singly-linked lists, append and delete are O(n) but prepend is O(1)
     59  * The sort macro is O(n log(n)) for all types of single/double/circular lists.
     60  */
     61 
     62 /* These macros use decltype or the earlier __typeof GNU extension.
     63    As decltype is only available in newer compilers (VS2010 or gcc 4.3+
     64    when compiling c++ source) this code uses whatever method is needed
     65    or, for VS2008 where neither is available, uses casting workarounds. */
     66 #if !defined(LDECLTYPE) && !defined(NO_DECLTYPE)
     67 #if defined(_MSC_VER)   /* MS compiler */
     68 #if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
     69 #define LDECLTYPE(x) decltype(x)
     70 #else                   /* VS2008 or older (or VS2010 in C mode) */
     71 #define NO_DECLTYPE
     72 #endif
     73 #elif defined(__MCST__)  /* Elbrus C Compiler */
     74 #define LDECLTYPE(x) __typeof(x)
     75 #elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__)
     76 #define NO_DECLTYPE
     77 #else                   /* GNU, Sun and other compilers */
     78 #define LDECLTYPE(x) __typeof(x)
     79 #endif
     80 #endif
     81 
     82 /* for VS2008 we use some workarounds to get around the lack of decltype,
     83  * namely, we always reassign our tmp variable to the list head if we need
     84  * to dereference its prev/next pointers, and save/restore the real head.*/
     85 #ifdef NO_DECLTYPE
     86 #define IF_NO_DECLTYPE(x) x
     87 #define LDECLTYPE(x) char*
     88 #define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
     89 #define UTLIST_NEXT(elt,list,next) ((char*)((list)->next))
     90 #define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
     91 /* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */
     92 #define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
     93 #define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
     94 #define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
     95 #else
     96 #define IF_NO_DECLTYPE(x)
     97 #define UTLIST_SV(elt,list)
     98 #define UTLIST_NEXT(elt,list,next) ((elt)->next)
     99 #define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
    100 /* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */
    101 #define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
    102 #define UTLIST_RS(list)
    103 #define UTLIST_CASTASGN(a,b) (a)=(b)
    104 #endif
    105 
    106 /******************************************************************************
    107  * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort    *
    108  * Unwieldy variable names used here to avoid shadowing passed-in variables.  *
    109  *****************************************************************************/
    110 #define LL_SORT(list, cmp)                                                                     \
    111     LL_SORT2(list, cmp, next)
    112 
    113 #define LL_SORT2(list, cmp, next)                                                              \
    114 do {                                                                                           \
    115   LDECLTYPE(list) _ls_p;                                                                       \
    116   LDECLTYPE(list) _ls_q;                                                                       \
    117   LDECLTYPE(list) _ls_e;                                                                       \
    118   LDECLTYPE(list) _ls_tail;                                                                    \
    119   IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;)                                                        \
    120   int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
    121   if (list) {                                                                                  \
    122     _ls_insize = 1;                                                                            \
    123     _ls_looping = 1;                                                                           \
    124     while (_ls_looping) {                                                                      \
    125       UTLIST_CASTASGN(_ls_p,list);                                                             \
    126       (list) = NULL;                                                                           \
    127       _ls_tail = NULL;                                                                         \
    128       _ls_nmerges = 0;                                                                         \
    129       while (_ls_p) {                                                                          \
    130         _ls_nmerges++;                                                                         \
    131         _ls_q = _ls_p;                                                                         \
    132         _ls_psize = 0;                                                                         \
    133         for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
    134           _ls_psize++;                                                                         \
    135           UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list);        \
    136           if (!_ls_q) break;                                                                   \
    137         }                                                                                      \
    138         _ls_qsize = _ls_insize;                                                                \
    139         while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
    140           if (_ls_psize == 0) {                                                                \
    141             _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
    142               UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
    143           } else if (_ls_qsize == 0 || !_ls_q) {                                               \
    144             _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
    145               UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
    146           } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
    147             _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
    148               UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
    149           } else {                                                                             \
    150             _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
    151               UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
    152           }                                                                                    \
    153           if (_ls_tail) {                                                                      \
    154             UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
    155           } else {                                                                             \
    156             UTLIST_CASTASGN(list,_ls_e);                                                       \
    157           }                                                                                    \
    158           _ls_tail = _ls_e;                                                                    \
    159         }                                                                                      \
    160         _ls_p = _ls_q;                                                                         \
    161       }                                                                                        \
    162       if (_ls_tail) {                                                                          \
    163         UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list);   \
    164       }                                                                                        \
    165       if (_ls_nmerges <= 1) {                                                                  \
    166         _ls_looping=0;                                                                         \
    167       }                                                                                        \
    168       _ls_insize *= 2;                                                                         \
    169     }                                                                                          \
    170   }                                                                                            \
    171 } while (0)
    172 
    173 
    174 #define DL_SORT(list, cmp)                                                                     \
    175     DL_SORT2(list, cmp, prev, next)
    176 
    177 #define DL_SORT2(list, cmp, prev, next)                                                        \
    178 do {                                                                                           \
    179   LDECLTYPE(list) _ls_p;                                                                       \
    180   LDECLTYPE(list) _ls_q;                                                                       \
    181   LDECLTYPE(list) _ls_e;                                                                       \
    182   LDECLTYPE(list) _ls_tail;                                                                    \
    183   IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;)                                                        \
    184   int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
    185   if (list) {                                                                                  \
    186     _ls_insize = 1;                                                                            \
    187     _ls_looping = 1;                                                                           \
    188     while (_ls_looping) {                                                                      \
    189       UTLIST_CASTASGN(_ls_p,list);                                                             \
    190       (list) = NULL;                                                                           \
    191       _ls_tail = NULL;                                                                         \
    192       _ls_nmerges = 0;                                                                         \
    193       while (_ls_p) {                                                                          \
    194         _ls_nmerges++;                                                                         \
    195         _ls_q = _ls_p;                                                                         \
    196         _ls_psize = 0;                                                                         \
    197         for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
    198           _ls_psize++;                                                                         \
    199           UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list);        \
    200           if (!_ls_q) break;                                                                   \
    201         }                                                                                      \
    202         _ls_qsize = _ls_insize;                                                                \
    203         while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) {                                \
    204           if (_ls_psize == 0) {                                                                \
    205             _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
    206               UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
    207           } else if ((_ls_qsize == 0) || (!_ls_q)) {                                           \
    208             _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
    209               UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
    210           } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
    211             _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
    212               UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
    213           } else {                                                                             \
    214             _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
    215               UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
    216           }                                                                                    \
    217           if (_ls_tail) {                                                                      \
    218             UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
    219           } else {                                                                             \
    220             UTLIST_CASTASGN(list,_ls_e);                                                       \
    221           }                                                                                    \
    222           UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list);   \
    223           _ls_tail = _ls_e;                                                                    \
    224         }                                                                                      \
    225         _ls_p = _ls_q;                                                                         \
    226       }                                                                                        \
    227       UTLIST_CASTASGN((list)->prev, _ls_tail);                                                 \
    228       UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list);     \
    229       if (_ls_nmerges <= 1) {                                                                  \
    230         _ls_looping=0;                                                                         \
    231       }                                                                                        \
    232       _ls_insize *= 2;                                                                         \
    233     }                                                                                          \
    234   }                                                                                            \
    235 } while (0)
    236 
    237 #define CDL_SORT(list, cmp)                                                                    \
    238     CDL_SORT2(list, cmp, prev, next)
    239 
    240 #define CDL_SORT2(list, cmp, prev, next)                                                       \
    241 do {                                                                                           \
    242   LDECLTYPE(list) _ls_p;                                                                       \
    243   LDECLTYPE(list) _ls_q;                                                                       \
    244   LDECLTYPE(list) _ls_e;                                                                       \
    245   LDECLTYPE(list) _ls_tail;                                                                    \
    246   LDECLTYPE(list) _ls_oldhead;                                                                 \
    247   LDECLTYPE(list) _tmp;                                                                        \
    248   int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
    249   if (list) {                                                                                  \
    250     _ls_insize = 1;                                                                            \
    251     _ls_looping = 1;                                                                           \
    252     while (_ls_looping) {                                                                      \
    253       UTLIST_CASTASGN(_ls_p,list);                                                             \
    254       UTLIST_CASTASGN(_ls_oldhead,list);                                                       \
    255       (list) = NULL;                                                                           \
    256       _ls_tail = NULL;                                                                         \
    257       _ls_nmerges = 0;                                                                         \
    258       while (_ls_p) {                                                                          \
    259         _ls_nmerges++;                                                                         \
    260         _ls_q = _ls_p;                                                                         \
    261         _ls_psize = 0;                                                                         \
    262         for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
    263           _ls_psize++;                                                                         \
    264           UTLIST_SV(_ls_q,list);                                                               \
    265           if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) {                                   \
    266             _ls_q = NULL;                                                                      \
    267           } else {                                                                             \
    268             _ls_q = UTLIST_NEXT(_ls_q,list,next);                                              \
    269           }                                                                                    \
    270           UTLIST_RS(list);                                                                     \
    271           if (!_ls_q) break;                                                                   \
    272         }                                                                                      \
    273         _ls_qsize = _ls_insize;                                                                \
    274         while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
    275           if (_ls_psize == 0) {                                                                \
    276             _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
    277               UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
    278             if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
    279           } else if (_ls_qsize == 0 || !_ls_q) {                                               \
    280             _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
    281               UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
    282             if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
    283           } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
    284             _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p =                                      \
    285               UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--;                      \
    286             if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
    287           } else {                                                                             \
    288             _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q =                                      \
    289               UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--;                      \
    290             if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
    291           }                                                                                    \
    292           if (_ls_tail) {                                                                      \
    293             UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \
    294           } else {                                                                             \
    295             UTLIST_CASTASGN(list,_ls_e);                                                       \
    296           }                                                                                    \
    297           UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list);   \
    298           _ls_tail = _ls_e;                                                                    \
    299         }                                                                                      \
    300         _ls_p = _ls_q;                                                                         \
    301       }                                                                                        \
    302       UTLIST_CASTASGN((list)->prev,_ls_tail);                                                  \
    303       UTLIST_CASTASGN(_tmp,list);                                                              \
    304       UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list);     \
    305       if (_ls_nmerges <= 1) {                                                                  \
    306         _ls_looping=0;                                                                         \
    307       }                                                                                        \
    308       _ls_insize *= 2;                                                                         \
    309     }                                                                                          \
    310   }                                                                                            \
    311 } while (0)
    312 
    313 /******************************************************************************
    314  * singly linked list macros (non-circular)                                   *
    315  *****************************************************************************/
    316 #define LL_PREPEND(head,add)                                                                   \
    317     LL_PREPEND2(head,add,next)
    318 
    319 #define LL_PREPEND2(head,add,next)                                                             \
    320 do {                                                                                           \
    321   (add)->next = (head);                                                                        \
    322   (head) = (add);                                                                              \
    323 } while (0)
    324 
    325 #define LL_CONCAT(head1,head2)                                                                 \
    326     LL_CONCAT2(head1,head2,next)
    327 
    328 #define LL_CONCAT2(head1,head2,next)                                                           \
    329 do {                                                                                           \
    330   LDECLTYPE(head1) _tmp;                                                                       \
    331   if (head1) {                                                                                 \
    332     _tmp = (head1);                                                                            \
    333     while (_tmp->next) { _tmp = _tmp->next; }                                                  \
    334     _tmp->next=(head2);                                                                        \
    335   } else {                                                                                     \
    336     (head1)=(head2);                                                                           \
    337   }                                                                                            \
    338 } while (0)
    339 
    340 #define LL_APPEND(head,add)                                                                    \
    341     LL_APPEND2(head,add,next)
    342 
    343 #define LL_APPEND2(head,add,next)                                                              \
    344 do {                                                                                           \
    345   LDECLTYPE(head) _tmp;                                                                        \
    346   (add)->next=NULL;                                                                            \
    347   if (head) {                                                                                  \
    348     _tmp = (head);                                                                             \
    349     while (_tmp->next) { _tmp = _tmp->next; }                                                  \
    350     _tmp->next=(add);                                                                          \
    351   } else {                                                                                     \
    352     (head)=(add);                                                                              \
    353   }                                                                                            \
    354 } while (0)
    355 
    356 #define LL_INSERT_INORDER(head,add,cmp)                                                        \
    357     LL_INSERT_INORDER2(head,add,cmp,next)
    358 
    359 #define LL_INSERT_INORDER2(head,add,cmp,next)                                                  \
    360 do {                                                                                           \
    361   LDECLTYPE(head) _tmp;                                                                        \
    362   if (head) {                                                                                  \
    363     LL_LOWER_BOUND2(head, _tmp, add, cmp, next);                                               \
    364     LL_APPEND_ELEM2(head, _tmp, add, next);                                                    \
    365   } else {                                                                                     \
    366     (head) = (add);                                                                            \
    367     (head)->next = NULL;                                                                       \
    368   }                                                                                            \
    369 } while (0)
    370 
    371 #define LL_LOWER_BOUND(head,elt,like,cmp)                                                      \
    372     LL_LOWER_BOUND2(head,elt,like,cmp,next)
    373 
    374 #define LL_LOWER_BOUND2(head,elt,like,cmp,next)                                                \
    375   do {                                                                                         \
    376     if ((head) == NULL || (cmp(head, like)) >= 0) {                                            \
    377       (elt) = NULL;                                                                            \
    378     } else {                                                                                   \
    379       for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) {                         \
    380         if (cmp((elt)->next, like) >= 0) {                                                     \
    381           break;                                                                               \
    382         }                                                                                      \
    383       }                                                                                        \
    384     }                                                                                          \
    385   } while (0)
    386 
    387 #define LL_DELETE(head,del)                                                                    \
    388     LL_DELETE2(head,del,next)
    389 
    390 #define LL_DELETE2(head,del,next)                                                              \
    391 do {                                                                                           \
    392   LDECLTYPE(head) _tmp;                                                                        \
    393   if ((head) == (del)) {                                                                       \
    394     (head)=(head)->next;                                                                       \
    395   } else {                                                                                     \
    396     _tmp = (head);                                                                             \
    397     while (_tmp->next && (_tmp->next != (del))) {                                              \
    398       _tmp = _tmp->next;                                                                       \
    399     }                                                                                          \
    400     if (_tmp->next) {                                                                          \
    401       _tmp->next = (del)->next;                                                                \
    402     }                                                                                          \
    403   }                                                                                            \
    404 } while (0)
    405 
    406 #define LL_COUNT(head,el,counter)                                                              \
    407     LL_COUNT2(head,el,counter,next)                                                            \
    408 
    409 #define LL_COUNT2(head,el,counter,next)                                                        \
    410 do {                                                                                           \
    411   (counter) = 0;                                                                               \
    412   LL_FOREACH2(head,el,next) { ++(counter); }                                                   \
    413 } while (0)
    414 
    415 #define LL_FOREACH(head,el)                                                                    \
    416     LL_FOREACH2(head,el,next)
    417 
    418 #define LL_FOREACH2(head,el,next)                                                              \
    419     for ((el) = (head); el; (el) = (el)->next)
    420 
    421 #define LL_FOREACH_SAFE(head,el,tmp)                                                           \
    422     LL_FOREACH_SAFE2(head,el,tmp,next)
    423 
    424 #define LL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
    425   for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
    426 
    427 #define LL_SEARCH_SCALAR(head,out,field,val)                                                   \
    428     LL_SEARCH_SCALAR2(head,out,field,val,next)
    429 
    430 #define LL_SEARCH_SCALAR2(head,out,field,val,next)                                             \
    431 do {                                                                                           \
    432     LL_FOREACH2(head,out,next) {                                                               \
    433       if ((out)->field == (val)) break;                                                        \
    434     }                                                                                          \
    435 } while (0)
    436 
    437 #define LL_SEARCH(head,out,elt,cmp)                                                            \
    438     LL_SEARCH2(head,out,elt,cmp,next)
    439 
    440 #define LL_SEARCH2(head,out,elt,cmp,next)                                                      \
    441 do {                                                                                           \
    442     LL_FOREACH2(head,out,next) {                                                               \
    443       if ((cmp(out,elt))==0) break;                                                            \
    444     }                                                                                          \
    445 } while (0)
    446 
    447 #define LL_REPLACE_ELEM2(head, el, add, next)                                                  \
    448 do {                                                                                           \
    449  LDECLTYPE(head) _tmp;                                                                         \
    450  assert((head) != NULL);                                                                       \
    451  assert((el) != NULL);                                                                         \
    452  assert((add) != NULL);                                                                        \
    453  (add)->next = (el)->next;                                                                     \
    454  if ((head) == (el)) {                                                                         \
    455   (head) = (add);                                                                              \
    456  } else {                                                                                      \
    457   _tmp = (head);                                                                               \
    458   while (_tmp->next && (_tmp->next != (el))) {                                                 \
    459    _tmp = _tmp->next;                                                                          \
    460   }                                                                                            \
    461   if (_tmp->next) {                                                                            \
    462     _tmp->next = (add);                                                                        \
    463   }                                                                                            \
    464  }                                                                                             \
    465 } while (0)
    466 
    467 #define LL_REPLACE_ELEM(head, el, add)                                                         \
    468     LL_REPLACE_ELEM2(head, el, add, next)
    469 
    470 #define LL_PREPEND_ELEM2(head, el, add, next)                                                  \
    471 do {                                                                                           \
    472  if (el) {                                                                                     \
    473   LDECLTYPE(head) _tmp;                                                                        \
    474   assert((head) != NULL);                                                                      \
    475   assert((add) != NULL);                                                                       \
    476   (add)->next = (el);                                                                          \
    477   if ((head) == (el)) {                                                                        \
    478    (head) = (add);                                                                             \
    479   } else {                                                                                     \
    480    _tmp = (head);                                                                              \
    481    while (_tmp->next && (_tmp->next != (el))) {                                                \
    482     _tmp = _tmp->next;                                                                         \
    483    }                                                                                           \
    484    if (_tmp->next) {                                                                           \
    485      _tmp->next = (add);                                                                       \
    486    }                                                                                           \
    487   }                                                                                            \
    488  } else {                                                                                      \
    489   LL_APPEND2(head, add, next);                                                                 \
    490  }                                                                                             \
    491 } while (0)                                                                                    \
    492 
    493 #define LL_PREPEND_ELEM(head, el, add)                                                         \
    494     LL_PREPEND_ELEM2(head, el, add, next)
    495 
    496 #define LL_APPEND_ELEM2(head, el, add, next)                                                   \
    497 do {                                                                                           \
    498  if (el) {                                                                                     \
    499   assert((head) != NULL);                                                                      \
    500   assert((add) != NULL);                                                                       \
    501   (add)->next = (el)->next;                                                                    \
    502   (el)->next = (add);                                                                          \
    503  } else {                                                                                      \
    504   LL_PREPEND2(head, add, next);                                                                \
    505  }                                                                                             \
    506 } while (0)                                                                                    \
    507 
    508 #define LL_APPEND_ELEM(head, el, add)                                                          \
    509     LL_APPEND_ELEM2(head, el, add, next)
    510 
    511 #ifdef NO_DECLTYPE
    512 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
    513 
    514 #undef LL_CONCAT2
    515 #define LL_CONCAT2(head1,head2,next)                                                           \
    516 do {                                                                                           \
    517   char *_tmp;                                                                                  \
    518   if (head1) {                                                                                 \
    519     _tmp = (char*)(head1);                                                                     \
    520     while ((head1)->next) { (head1) = (head1)->next; }                                         \
    521     (head1)->next = (head2);                                                                   \
    522     UTLIST_RS(head1);                                                                          \
    523   } else {                                                                                     \
    524     (head1)=(head2);                                                                           \
    525   }                                                                                            \
    526 } while (0)
    527 
    528 #undef LL_APPEND2
    529 #define LL_APPEND2(head,add,next)                                                              \
    530 do {                                                                                           \
    531   if (head) {                                                                                  \
    532     (add)->next = head;     /* use add->next as a temp variable */                             \
    533     while ((add)->next->next) { (add)->next = (add)->next->next; }                             \
    534     (add)->next->next=(add);                                                                   \
    535   } else {                                                                                     \
    536     (head)=(add);                                                                              \
    537   }                                                                                            \
    538   (add)->next=NULL;                                                                            \
    539 } while (0)
    540 
    541 #undef LL_INSERT_INORDER2
    542 #define LL_INSERT_INORDER2(head,add,cmp,next)                                                  \
    543 do {                                                                                           \
    544   if ((head) == NULL || (cmp(head, add)) >= 0) {                                               \
    545     (add)->next = (head);                                                                      \
    546     (head) = (add);                                                                            \
    547   } else {                                                                                     \
    548     char *_tmp = (char*)(head);                                                                \
    549     while ((head)->next != NULL && (cmp((head)->next, add)) < 0) {                             \
    550       (head) = (head)->next;                                                                   \
    551     }                                                                                          \
    552     (add)->next = (head)->next;                                                                \
    553     (head)->next = (add);                                                                      \
    554     UTLIST_RS(head);                                                                           \
    555   }                                                                                            \
    556 } while (0)
    557 
    558 #undef LL_DELETE2
    559 #define LL_DELETE2(head,del,next)                                                              \
    560 do {                                                                                           \
    561   if ((head) == (del)) {                                                                       \
    562     (head)=(head)->next;                                                                       \
    563   } else {                                                                                     \
    564     char *_tmp = (char*)(head);                                                                \
    565     while ((head)->next && ((head)->next != (del))) {                                          \
    566       (head) = (head)->next;                                                                   \
    567     }                                                                                          \
    568     if ((head)->next) {                                                                        \
    569       (head)->next = ((del)->next);                                                            \
    570     }                                                                                          \
    571     UTLIST_RS(head);                                                                           \
    572   }                                                                                            \
    573 } while (0)
    574 
    575 #undef LL_REPLACE_ELEM2
    576 #define LL_REPLACE_ELEM2(head, el, add, next)                                                  \
    577 do {                                                                                           \
    578   assert((head) != NULL);                                                                      \
    579   assert((el) != NULL);                                                                        \
    580   assert((add) != NULL);                                                                       \
    581   if ((head) == (el)) {                                                                        \
    582     (head) = (add);                                                                            \
    583   } else {                                                                                     \
    584     (add)->next = head;                                                                        \
    585     while ((add)->next->next && ((add)->next->next != (el))) {                                 \
    586       (add)->next = (add)->next->next;                                                         \
    587     }                                                                                          \
    588     if ((add)->next->next) {                                                                   \
    589       (add)->next->next = (add);                                                               \
    590     }                                                                                          \
    591   }                                                                                            \
    592   (add)->next = (el)->next;                                                                    \
    593 } while (0)
    594 
    595 #undef LL_PREPEND_ELEM2
    596 #define LL_PREPEND_ELEM2(head, el, add, next)                                                  \
    597 do {                                                                                           \
    598   if (el) {                                                                                    \
    599     assert((head) != NULL);                                                                    \
    600     assert((add) != NULL);                                                                     \
    601     if ((head) == (el)) {                                                                      \
    602       (head) = (add);                                                                          \
    603     } else {                                                                                   \
    604       (add)->next = (head);                                                                    \
    605       while ((add)->next->next && ((add)->next->next != (el))) {                               \
    606         (add)->next = (add)->next->next;                                                       \
    607       }                                                                                        \
    608       if ((add)->next->next) {                                                                 \
    609         (add)->next->next = (add);                                                             \
    610       }                                                                                        \
    611     }                                                                                          \
    612     (add)->next = (el);                                                                        \
    613   } else {                                                                                     \
    614     LL_APPEND2(head, add, next);                                                               \
    615   }                                                                                            \
    616 } while (0)                                                                                    \
    617 
    618 #endif /* NO_DECLTYPE */
    619 
    620 /******************************************************************************
    621  * doubly linked list macros (non-circular)                                   *
    622  *****************************************************************************/
    623 #define DL_PREPEND(head,add)                                                                   \
    624     DL_PREPEND2(head,add,prev,next)
    625 
    626 #define DL_PREPEND2(head,add,prev,next)                                                        \
    627 do {                                                                                           \
    628  (add)->next = (head);                                                                         \
    629  if (head) {                                                                                   \
    630    (add)->prev = (head)->prev;                                                                 \
    631    (head)->prev = (add);                                                                       \
    632  } else {                                                                                      \
    633    (add)->prev = (add);                                                                        \
    634  }                                                                                             \
    635  (head) = (add);                                                                               \
    636 } while (0)
    637 
    638 #define DL_APPEND(head,add)                                                                    \
    639     DL_APPEND2(head,add,prev,next)
    640 
    641 #define DL_APPEND2(head,add,prev,next)                                                         \
    642 do {                                                                                           \
    643   if (head) {                                                                                  \
    644       (add)->prev = (head)->prev;                                                              \
    645       (head)->prev->next = (add);                                                              \
    646       (head)->prev = (add);                                                                    \
    647       (add)->next = NULL;                                                                      \
    648   } else {                                                                                     \
    649       (head)=(add);                                                                            \
    650       (head)->prev = (head);                                                                   \
    651       (head)->next = NULL;                                                                     \
    652   }                                                                                            \
    653 } while (0)
    654 
    655 #define DL_INSERT_INORDER(head,add,cmp)                                                        \
    656     DL_INSERT_INORDER2(head,add,cmp,prev,next)
    657 
    658 #define DL_INSERT_INORDER2(head,add,cmp,prev,next)                                             \
    659 do {                                                                                           \
    660   LDECLTYPE(head) _tmp;                                                                        \
    661   if (head) {                                                                                  \
    662     DL_LOWER_BOUND2(head, _tmp, add, cmp, next);                                               \
    663     DL_APPEND_ELEM2(head, _tmp, add, prev, next);                                              \
    664   } else {                                                                                     \
    665     (head) = (add);                                                                            \
    666     (head)->prev = (head);                                                                     \
    667     (head)->next = NULL;                                                                       \
    668   }                                                                                            \
    669 } while (0)
    670 
    671 #define DL_LOWER_BOUND(head,elt,like,cmp)                                                      \
    672     DL_LOWER_BOUND2(head,elt,like,cmp,next)
    673 
    674 #define DL_LOWER_BOUND2(head,elt,like,cmp,next)                                                \
    675 do {                                                                                           \
    676   if ((head) == NULL || (cmp(head, like)) >= 0) {                                              \
    677     (elt) = NULL;                                                                              \
    678   } else {                                                                                     \
    679     for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) {                           \
    680       if ((cmp((elt)->next, like)) >= 0) {                                                     \
    681         break;                                                                                 \
    682       }                                                                                        \
    683     }                                                                                          \
    684   }                                                                                            \
    685 } while (0)
    686 
    687 #define DL_CONCAT(head1,head2)                                                                 \
    688     DL_CONCAT2(head1,head2,prev,next)
    689 
    690 #define DL_CONCAT2(head1,head2,prev,next)                                                      \
    691 do {                                                                                           \
    692   LDECLTYPE(head1) _tmp;                                                                       \
    693   if (head2) {                                                                                 \
    694     if (head1) {                                                                               \
    695         UTLIST_CASTASGN(_tmp, (head2)->prev);                                                  \
    696         (head2)->prev = (head1)->prev;                                                         \
    697         (head1)->prev->next = (head2);                                                         \
    698         UTLIST_CASTASGN((head1)->prev, _tmp);                                                  \
    699     } else {                                                                                   \
    700         (head1)=(head2);                                                                       \
    701     }                                                                                          \
    702   }                                                                                            \
    703 } while (0)
    704 
    705 #define DL_DELETE(head,del)                                                                    \
    706     DL_DELETE2(head,del,prev,next)
    707 
    708 #define DL_DELETE2(head,del,prev,next)                                                         \
    709 do {                                                                                           \
    710   assert((head) != NULL);                                                                      \
    711   assert((del)->prev != NULL);                                                                 \
    712   if ((del)->prev == (del)) {                                                                  \
    713       (head)=NULL;                                                                             \
    714   } else if ((del)==(head)) {                                                                  \
    715       (del)->next->prev = (del)->prev;                                                         \
    716       (head) = (del)->next;                                                                    \
    717   } else {                                                                                     \
    718       (del)->prev->next = (del)->next;                                                         \
    719       if ((del)->next) {                                                                       \
    720           (del)->next->prev = (del)->prev;                                                     \
    721       } else {                                                                                 \
    722           (head)->prev = (del)->prev;                                                          \
    723       }                                                                                        \
    724   }                                                                                            \
    725 } while (0)
    726 
    727 #define DL_COUNT(head,el,counter)                                                              \
    728     DL_COUNT2(head,el,counter,next)                                                            \
    729 
    730 #define DL_COUNT2(head,el,counter,next)                                                        \
    731 do {                                                                                           \
    732   (counter) = 0;                                                                               \
    733   DL_FOREACH2(head,el,next) { ++(counter); }                                                   \
    734 } while (0)
    735 
    736 #define DL_FOREACH(head,el)                                                                    \
    737     DL_FOREACH2(head,el,next)
    738 
    739 #define DL_FOREACH2(head,el,next)                                                              \
    740     for ((el) = (head); el; (el) = (el)->next)
    741 
    742 /* this version is safe for deleting the elements during iteration */
    743 #define DL_FOREACH_SAFE(head,el,tmp)                                                           \
    744     DL_FOREACH_SAFE2(head,el,tmp,next)
    745 
    746 #define DL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
    747   for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
    748 
    749 /* these are identical to their singly-linked list counterparts */
    750 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
    751 #define DL_SEARCH LL_SEARCH
    752 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
    753 #define DL_SEARCH2 LL_SEARCH2
    754 
    755 #define DL_REPLACE_ELEM2(head, el, add, prev, next)                                            \
    756 do {                                                                                           \
    757  assert((head) != NULL);                                                                       \
    758  assert((el) != NULL);                                                                         \
    759  assert((add) != NULL);                                                                        \
    760  if ((head) == (el)) {                                                                         \
    761   (head) = (add);                                                                              \
    762   (add)->next = (el)->next;                                                                    \
    763   if ((el)->next == NULL) {                                                                    \
    764    (add)->prev = (add);                                                                        \
    765   } else {                                                                                     \
    766    (add)->prev = (el)->prev;                                                                   \
    767    (add)->next->prev = (add);                                                                  \
    768   }                                                                                            \
    769  } else {                                                                                      \
    770   (add)->next = (el)->next;                                                                    \
    771   (add)->prev = (el)->prev;                                                                    \
    772   (add)->prev->next = (add);                                                                   \
    773   if ((el)->next == NULL) {                                                                    \
    774    (head)->prev = (add);                                                                       \
    775   } else {                                                                                     \
    776    (add)->next->prev = (add);                                                                  \
    777   }                                                                                            \
    778  }                                                                                             \
    779 } while (0)
    780 
    781 #define DL_REPLACE_ELEM(head, el, add)                                                         \
    782     DL_REPLACE_ELEM2(head, el, add, prev, next)
    783 
    784 #define DL_PREPEND_ELEM2(head, el, add, prev, next)                                            \
    785 do {                                                                                           \
    786  if (el) {                                                                                     \
    787   assert((head) != NULL);                                                                      \
    788   assert((add) != NULL);                                                                       \
    789   (add)->next = (el);                                                                          \
    790   (add)->prev = (el)->prev;                                                                    \
    791   (el)->prev = (add);                                                                          \
    792   if ((head) == (el)) {                                                                        \
    793    (head) = (add);                                                                             \
    794   } else {                                                                                     \
    795    (add)->prev->next = (add);                                                                  \
    796   }                                                                                            \
    797  } else {                                                                                      \
    798   DL_APPEND2(head, add, prev, next);                                                           \
    799  }                                                                                             \
    800 } while (0)                                                                                    \
    801 
    802 #define DL_PREPEND_ELEM(head, el, add)                                                         \
    803     DL_PREPEND_ELEM2(head, el, add, prev, next)
    804 
    805 #define DL_APPEND_ELEM2(head, el, add, prev, next)                                             \
    806 do {                                                                                           \
    807  if (el) {                                                                                     \
    808   assert((head) != NULL);                                                                      \
    809   assert((add) != NULL);                                                                       \
    810   (add)->next = (el)->next;                                                                    \
    811   (add)->prev = (el);                                                                          \
    812   (el)->next = (add);                                                                          \
    813   if ((add)->next) {                                                                           \
    814    (add)->next->prev = (add);                                                                  \
    815   } else {                                                                                     \
    816    (head)->prev = (add);                                                                       \
    817   }                                                                                            \
    818  } else {                                                                                      \
    819   DL_PREPEND2(head, add, prev, next);                                                          \
    820  }                                                                                             \
    821 } while (0)                                                                                    \
    822 
    823 #define DL_APPEND_ELEM(head, el, add)                                                          \
    824    DL_APPEND_ELEM2(head, el, add, prev, next)
    825 
    826 #ifdef NO_DECLTYPE
    827 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
    828 
    829 #undef DL_INSERT_INORDER2
    830 #define DL_INSERT_INORDER2(head,add,cmp,prev,next)                                             \
    831 do {                                                                                           \
    832   if ((head) == NULL) {                                                                        \
    833     (add)->prev = (add);                                                                       \
    834     (add)->next = NULL;                                                                        \
    835     (head) = (add);                                                                            \
    836   } else if ((cmp(head, add)) >= 0) {                                                          \
    837     (add)->prev = (head)->prev;                                                                \
    838     (add)->next = (head);                                                                      \
    839     (head)->prev = (add);                                                                      \
    840     (head) = (add);                                                                            \
    841   } else {                                                                                     \
    842     char *_tmp = (char*)(head);                                                                \
    843     while ((head)->next && (cmp((head)->next, add)) < 0) {                                     \
    844       (head) = (head)->next;                                                                   \
    845     }                                                                                          \
    846     (add)->prev = (head);                                                                      \
    847     (add)->next = (head)->next;                                                                \
    848     (head)->next = (add);                                                                      \
    849     UTLIST_RS(head);                                                                           \
    850     if ((add)->next) {                                                                         \
    851       (add)->next->prev = (add);                                                               \
    852     } else {                                                                                   \
    853       (head)->prev = (add);                                                                    \
    854     }                                                                                          \
    855   }                                                                                            \
    856 } while (0)
    857 #endif /* NO_DECLTYPE */
    858 
    859 /******************************************************************************
    860  * circular doubly linked list macros                                         *
    861  *****************************************************************************/
    862 #define CDL_APPEND(head,add)                                                                   \
    863     CDL_APPEND2(head,add,prev,next)
    864 
    865 #define CDL_APPEND2(head,add,prev,next)                                                        \
    866 do {                                                                                           \
    867  if (head) {                                                                                   \
    868    (add)->prev = (head)->prev;                                                                 \
    869    (add)->next = (head);                                                                       \
    870    (head)->prev = (add);                                                                       \
    871    (add)->prev->next = (add);                                                                  \
    872  } else {                                                                                      \
    873    (add)->prev = (add);                                                                        \
    874    (add)->next = (add);                                                                        \
    875    (head) = (add);                                                                             \
    876  }                                                                                             \
    877 } while (0)
    878 
    879 #define CDL_PREPEND(head,add)                                                                  \
    880     CDL_PREPEND2(head,add,prev,next)
    881 
    882 #define CDL_PREPEND2(head,add,prev,next)                                                       \
    883 do {                                                                                           \
    884  if (head) {                                                                                   \
    885    (add)->prev = (head)->prev;                                                                 \
    886    (add)->next = (head);                                                                       \
    887    (head)->prev = (add);                                                                       \
    888    (add)->prev->next = (add);                                                                  \
    889  } else {                                                                                      \
    890    (add)->prev = (add);                                                                        \
    891    (add)->next = (add);                                                                        \
    892  }                                                                                             \
    893  (head) = (add);                                                                               \
    894 } while (0)
    895 
    896 #define CDL_INSERT_INORDER(head,add,cmp)                                                       \
    897     CDL_INSERT_INORDER2(head,add,cmp,prev,next)
    898 
    899 #define CDL_INSERT_INORDER2(head,add,cmp,prev,next)                                            \
    900 do {                                                                                           \
    901   LDECLTYPE(head) _tmp;                                                                        \
    902   if (head) {                                                                                  \
    903     CDL_LOWER_BOUND2(head, _tmp, add, cmp, next);                                              \
    904     CDL_APPEND_ELEM2(head, _tmp, add, prev, next);                                             \
    905   } else {                                                                                     \
    906     (head) = (add);                                                                            \
    907     (head)->next = (head);                                                                     \
    908     (head)->prev = (head);                                                                     \
    909   }                                                                                            \
    910 } while (0)
    911 
    912 #define CDL_LOWER_BOUND(head,elt,like,cmp)                                                     \
    913     CDL_LOWER_BOUND2(head,elt,like,cmp,next)
    914 
    915 #define CDL_LOWER_BOUND2(head,elt,like,cmp,next)                                               \
    916 do {                                                                                           \
    917   if ((head) == NULL || (cmp(head, like)) >= 0) {                                              \
    918     (elt) = NULL;                                                                              \
    919   } else {                                                                                     \
    920     for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) {                         \
    921       if ((cmp((elt)->next, like)) >= 0) {                                                     \
    922         break;                                                                                 \
    923       }                                                                                        \
    924     }                                                                                          \
    925   }                                                                                            \
    926 } while (0)
    927 
    928 #define CDL_DELETE(head,del)                                                                   \
    929     CDL_DELETE2(head,del,prev,next)
    930 
    931 #define CDL_DELETE2(head,del,prev,next)                                                        \
    932 do {                                                                                           \
    933   if (((head)==(del)) && ((head)->next == (head))) {                                           \
    934       (head) = NULL;                                                                           \
    935   } else {                                                                                     \
    936      (del)->next->prev = (del)->prev;                                                          \
    937      (del)->prev->next = (del)->next;                                                          \
    938      if ((del) == (head)) (head)=(del)->next;                                                  \
    939   }                                                                                            \
    940 } while (0)
    941 
    942 #define CDL_COUNT(head,el,counter)                                                             \
    943     CDL_COUNT2(head,el,counter,next)                                                           \
    944 
    945 #define CDL_COUNT2(head, el, counter,next)                                                     \
    946 do {                                                                                           \
    947   (counter) = 0;                                                                               \
    948   CDL_FOREACH2(head,el,next) { ++(counter); }                                                  \
    949 } while (0)
    950 
    951 #define CDL_FOREACH(head,el)                                                                   \
    952     CDL_FOREACH2(head,el,next)
    953 
    954 #define CDL_FOREACH2(head,el,next)                                                             \
    955     for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next))
    956 
    957 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
    958     CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
    959 
    960 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)                                         \
    961   for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL;                                   \
    962        (el) && ((tmp2) = (el)->next, 1);                                                       \
    963        (el) = ((el) == (tmp1) ? NULL : (tmp2)))
    964 
    965 #define CDL_SEARCH_SCALAR(head,out,field,val)                                                  \
    966     CDL_SEARCH_SCALAR2(head,out,field,val,next)
    967 
    968 #define CDL_SEARCH_SCALAR2(head,out,field,val,next)                                            \
    969 do {                                                                                           \
    970     CDL_FOREACH2(head,out,next) {                                                              \
    971       if ((out)->field == (val)) break;                                                        \
    972     }                                                                                          \
    973 } while (0)
    974 
    975 #define CDL_SEARCH(head,out,elt,cmp)                                                           \
    976     CDL_SEARCH2(head,out,elt,cmp,next)
    977 
    978 #define CDL_SEARCH2(head,out,elt,cmp,next)                                                     \
    979 do {                                                                                           \
    980     CDL_FOREACH2(head,out,next) {                                                              \
    981       if ((cmp(out,elt))==0) break;                                                            \
    982     }                                                                                          \
    983 } while (0)
    984 
    985 #define CDL_REPLACE_ELEM2(head, el, add, prev, next)                                           \
    986 do {                                                                                           \
    987  assert((head) != NULL);                                                                       \
    988  assert((el) != NULL);                                                                         \
    989  assert((add) != NULL);                                                                        \
    990  if ((el)->next == (el)) {                                                                     \
    991   (add)->next = (add);                                                                         \
    992   (add)->prev = (add);                                                                         \
    993   (head) = (add);                                                                              \
    994  } else {                                                                                      \
    995   (add)->next = (el)->next;                                                                    \
    996   (add)->prev = (el)->prev;                                                                    \
    997   (add)->next->prev = (add);                                                                   \
    998   (add)->prev->next = (add);                                                                   \
    999   if ((head) == (el)) {                                                                        \
   1000    (head) = (add);                                                                             \
   1001   }                                                                                            \
   1002  }                                                                                             \
   1003 } while (0)
   1004 
   1005 #define CDL_REPLACE_ELEM(head, el, add)                                                        \
   1006     CDL_REPLACE_ELEM2(head, el, add, prev, next)
   1007 
   1008 #define CDL_PREPEND_ELEM2(head, el, add, prev, next)                                           \
   1009 do {                                                                                           \
   1010   if (el) {                                                                                    \
   1011     assert((head) != NULL);                                                                    \
   1012     assert((add) != NULL);                                                                     \
   1013     (add)->next = (el);                                                                        \
   1014     (add)->prev = (el)->prev;                                                                  \
   1015     (el)->prev = (add);                                                                        \
   1016     (add)->prev->next = (add);                                                                 \
   1017     if ((head) == (el)) {                                                                      \
   1018       (head) = (add);                                                                          \
   1019     }                                                                                          \
   1020   } else {                                                                                     \
   1021     CDL_APPEND2(head, add, prev, next);                                                        \
   1022   }                                                                                            \
   1023 } while (0)
   1024 
   1025 #define CDL_PREPEND_ELEM(head, el, add)                                                        \
   1026     CDL_PREPEND_ELEM2(head, el, add, prev, next)
   1027 
   1028 #define CDL_APPEND_ELEM2(head, el, add, prev, next)                                            \
   1029 do {                                                                                           \
   1030  if (el) {                                                                                     \
   1031   assert((head) != NULL);                                                                      \
   1032   assert((add) != NULL);                                                                       \
   1033   (add)->next = (el)->next;                                                                    \
   1034   (add)->prev = (el);                                                                          \
   1035   (el)->next = (add);                                                                          \
   1036   (add)->next->prev = (add);                                                                   \
   1037  } else {                                                                                      \
   1038   CDL_PREPEND2(head, add, prev, next);                                                         \
   1039  }                                                                                             \
   1040 } while (0)
   1041 
   1042 #define CDL_APPEND_ELEM(head, el, add)                                                         \
   1043     CDL_APPEND_ELEM2(head, el, add, prev, next)
   1044 
   1045 #ifdef NO_DECLTYPE
   1046 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
   1047 
   1048 #undef CDL_INSERT_INORDER2
   1049 #define CDL_INSERT_INORDER2(head,add,cmp,prev,next)                                            \
   1050 do {                                                                                           \
   1051   if ((head) == NULL) {                                                                        \
   1052     (add)->prev = (add);                                                                       \
   1053     (add)->next = (add);                                                                       \
   1054     (head) = (add);                                                                            \
   1055   } else if ((cmp(head, add)) >= 0) {                                                          \
   1056     (add)->prev = (head)->prev;                                                                \
   1057     (add)->next = (head);                                                                      \
   1058     (add)->prev->next = (add);                                                                 \
   1059     (head)->prev = (add);                                                                      \
   1060     (head) = (add);                                                                            \
   1061   } else {                                                                                     \
   1062     char *_tmp = (char*)(head);                                                                \
   1063     while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) {                      \
   1064       (head) = (head)->next;                                                                   \
   1065     }                                                                                          \
   1066     (add)->prev = (head);                                                                      \
   1067     (add)->next = (head)->next;                                                                \
   1068     (add)->next->prev = (add);                                                                 \
   1069     (head)->next = (add);                                                                      \
   1070     UTLIST_RS(head);                                                                           \
   1071   }                                                                                            \
   1072 } while (0)
   1073 #endif /* NO_DECLTYPE */
   1074 
   1075 #endif /* UTLIST_H */