1 /*
2 Copyright (c) 2007-2016, Troy D. Hanson   http://troydhanson.github.com/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.0.1
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++ code), this code uses whatever method is needed
65    or, for VS2008 where neither is available, uses casting workarounds. */
66 #ifdef _MSC_VER            /* MS compiler */
67 #if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
68 #define LDECLTYPE(x) decltype(x)
69 #else                     /* VS2008 or older (or VS2010 in C mode) */
70 #define NO_DECLTYPE
71 #endif
72 #elif defined(__ICCARM__)
73 #define NO_DECLTYPE
74 #else                      /* GNU, Sun and other compilers */
75 #define LDECLTYPE(x) __typeof(x)
76 #endif
77 
78 /* for VS2008 we use some workarounds to get around the lack of decltype,
79  * namely, we always reassign our tmp variable to the list head if we need
80  * to dereference its prev/next pointers, and save/restore the real head.*/
81 #ifdef NO_DECLTYPE
82 #define IF_NO_DECLTYPE(x) x
83 #define LDECLTYPE(x) char*
84 #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
85 #define _NEXT(elt,list,next) ((char*)((list)->next))
86 #define _NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
87 /* #define _PREV(elt,list,prev) ((char*)((list)->prev)) */
88 #define _PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
89 #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
90 #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
91 #else
92 #define IF_NO_DECLTYPE(x)
93 #define _SV(elt,list)
94 #define _NEXT(elt,list,next) ((elt)->next)
95 #define _NEXTASGN(elt,list,to,next) ((elt)->next)=(to)
96 /* #define _PREV(elt,list,prev) ((elt)->prev) */
97 #define _PREVASGN(elt,list,to,prev) ((elt)->prev)=(to)
98 #define _RS(list)
99 #define _CASTASGN(a,b) (a)=(b)
100 #endif
101 
102 /******************************************************************************
103  * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort    *
104  * Unwieldy variable names used here to avoid shadowing passed-in variables.  *
105  *****************************************************************************/
106 #define LL_SORT(list, cmp)                                                                     \
107     LL_SORT2(list, cmp, next)
108 
109 #define LL_SORT2(list, cmp, next)                                                              \
110 do {                                                                                           \
111   LDECLTYPE(list) _ls_p;                                                                       \
112   LDECLTYPE(list) _ls_q;                                                                       \
113   LDECLTYPE(list) _ls_e;                                                                       \
114   LDECLTYPE(list) _ls_tail;                                                                    \
115   IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;)                                                        \
116   int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
117   if (list) {                                                                                  \
118     _ls_insize = 1;                                                                            \
119     _ls_looping = 1;                                                                           \
120     while (_ls_looping) {                                                                      \
121       _CASTASGN(_ls_p,list);                                                                   \
122       (list) = NULL;                                                                           \
123       _ls_tail = NULL;                                                                         \
124       _ls_nmerges = 0;                                                                         \
125       while (_ls_p) {                                                                          \
126         _ls_nmerges++;                                                                         \
127         _ls_q = _ls_p;                                                                         \
128         _ls_psize = 0;                                                                         \
129         for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
130           _ls_psize++;                                                                         \
131           _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
132           if (!_ls_q) break;                                                                   \
133         }                                                                                      \
134         _ls_qsize = _ls_insize;                                                                \
135         while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
136           if (_ls_psize == 0) {                                                                \
137             _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
138               _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
139           } else if (_ls_qsize == 0 || !_ls_q) {                                               \
140             _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
141               _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
142           } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
143             _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
144               _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
145           } else {                                                                             \
146             _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
147               _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
148           }                                                                                    \
149           if (_ls_tail) {                                                                      \
150             _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
151           } else {                                                                             \
152             _CASTASGN(list,_ls_e);                                                             \
153           }                                                                                    \
154           _ls_tail = _ls_e;                                                                    \
155         }                                                                                      \
156         _ls_p = _ls_q;                                                                         \
157       }                                                                                        \
158       if (_ls_tail) {                                                                          \
159         _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                     \
160       }                                                                                        \
161       if (_ls_nmerges <= 1) {                                                                  \
162         _ls_looping=0;                                                                         \
163       }                                                                                        \
164       _ls_insize *= 2;                                                                         \
165     }                                                                                          \
166   }                                                                                            \
167 } while (0)
168 
169 
170 #define DL_SORT(list, cmp)                                                                     \
171     DL_SORT2(list, cmp, prev, next)
172 
173 #define DL_SORT2(list, cmp, prev, next)                                                        \
174 do {                                                                                           \
175   LDECLTYPE(list) _ls_p;                                                                       \
176   LDECLTYPE(list) _ls_q;                                                                       \
177   LDECLTYPE(list) _ls_e;                                                                       \
178   LDECLTYPE(list) _ls_tail;                                                                    \
179   IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;)                                                        \
180   int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
181   if (list) {                                                                                  \
182     _ls_insize = 1;                                                                            \
183     _ls_looping = 1;                                                                           \
184     while (_ls_looping) {                                                                      \
185       _CASTASGN(_ls_p,list);                                                                   \
186       (list) = NULL;                                                                           \
187       _ls_tail = NULL;                                                                         \
188       _ls_nmerges = 0;                                                                         \
189       while (_ls_p) {                                                                          \
190         _ls_nmerges++;                                                                         \
191         _ls_q = _ls_p;                                                                         \
192         _ls_psize = 0;                                                                         \
193         for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
194           _ls_psize++;                                                                         \
195           _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list,next); _RS(list);                          \
196           if (!_ls_q) break;                                                                   \
197         }                                                                                      \
198         _ls_qsize = _ls_insize;                                                                \
199         while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) {                                \
200           if (_ls_psize == 0) {                                                                \
201             _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
202               _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
203           } else if ((_ls_qsize == 0) || (!_ls_q)) {                                           \
204             _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
205               _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
206           } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
207             _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
208               _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
209           } else {                                                                             \
210             _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
211               _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
212           }                                                                                    \
213           if (_ls_tail) {                                                                      \
214             _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
215           } else {                                                                             \
216             _CASTASGN(list,_ls_e);                                                             \
217           }                                                                                    \
218           _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
219           _ls_tail = _ls_e;                                                                    \
220         }                                                                                      \
221         _ls_p = _ls_q;                                                                         \
222       }                                                                                        \
223       _CASTASGN((list)->prev, _ls_tail);                                                       \
224       _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL,next); _RS(list);                       \
225       if (_ls_nmerges <= 1) {                                                                  \
226         _ls_looping=0;                                                                         \
227       }                                                                                        \
228       _ls_insize *= 2;                                                                         \
229     }                                                                                          \
230   }                                                                                            \
231 } while (0)
232 
233 #define CDL_SORT(list, cmp)                                                                    \
234     CDL_SORT2(list, cmp, prev, next)
235 
236 #define CDL_SORT2(list, cmp, prev, next)                                                       \
237 do {                                                                                           \
238   LDECLTYPE(list) _ls_p;                                                                       \
239   LDECLTYPE(list) _ls_q;                                                                       \
240   LDECLTYPE(list) _ls_e;                                                                       \
241   LDECLTYPE(list) _ls_tail;                                                                    \
242   LDECLTYPE(list) _ls_oldhead;                                                                 \
243   LDECLTYPE(list) _tmp;                                                                        \
244   int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping;                       \
245   if (list) {                                                                                  \
246     _ls_insize = 1;                                                                            \
247     _ls_looping = 1;                                                                           \
248     while (_ls_looping) {                                                                      \
249       _CASTASGN(_ls_p,list);                                                                   \
250       _CASTASGN(_ls_oldhead,list);                                                             \
251       (list) = NULL;                                                                           \
252       _ls_tail = NULL;                                                                         \
253       _ls_nmerges = 0;                                                                         \
254       while (_ls_p) {                                                                          \
255         _ls_nmerges++;                                                                         \
256         _ls_q = _ls_p;                                                                         \
257         _ls_psize = 0;                                                                         \
258         for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) {                                         \
259           _ls_psize++;                                                                         \
260           _SV(_ls_q,list);                                                                     \
261           if (_NEXT(_ls_q,list,next) == _ls_oldhead) {                                         \
262             _ls_q = NULL;                                                                      \
263           } else {                                                                             \
264             _ls_q = _NEXT(_ls_q,list,next);                                                    \
265           }                                                                                    \
266           _RS(list);                                                                           \
267           if (!_ls_q) break;                                                                   \
268         }                                                                                      \
269         _ls_qsize = _ls_insize;                                                                \
270         while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) {                                    \
271           if (_ls_psize == 0) {                                                                \
272             _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
273               _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
274             if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
275           } else if (_ls_qsize == 0 || !_ls_q) {                                               \
276             _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
277               _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
278             if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
279           } else if (cmp(_ls_p,_ls_q) <= 0) {                                                  \
280             _ls_e = _ls_p; _SV(_ls_p,list); _ls_p =                                            \
281               _NEXT(_ls_p,list,next); _RS(list); _ls_psize--;                                  \
282             if (_ls_p == _ls_oldhead) { _ls_p = NULL; }                                        \
283           } else {                                                                             \
284             _ls_e = _ls_q; _SV(_ls_q,list); _ls_q =                                            \
285               _NEXT(_ls_q,list,next); _RS(list); _ls_qsize--;                                  \
286             if (_ls_q == _ls_oldhead) { _ls_q = NULL; }                                        \
287           }                                                                                    \
288           if (_ls_tail) {                                                                      \
289             _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e,next); _RS(list);                \
290           } else {                                                                             \
291             _CASTASGN(list,_ls_e);                                                             \
292           }                                                                                    \
293           _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail,prev); _RS(list);                     \
294           _ls_tail = _ls_e;                                                                    \
295         }                                                                                      \
296         _ls_p = _ls_q;                                                                         \
297       }                                                                                        \
298       _CASTASGN((list)->prev,_ls_tail);                                                        \
299       _CASTASGN(_tmp,list);                                                                    \
300       _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp,next); _RS(list);                       \
301       if (_ls_nmerges <= 1) {                                                                  \
302         _ls_looping=0;                                                                         \
303       }                                                                                        \
304       _ls_insize *= 2;                                                                         \
305     }                                                                                          \
306   }                                                                                            \
307 } while (0)
308 
309 /******************************************************************************
310  * singly linked list macros (non-circular)                                   *
311  *****************************************************************************/
312 #define LL_PREPEND(head,add)                                                                   \
313     LL_PREPEND2(head,add,next)
314 
315 #define LL_PREPEND2(head,add,next)                                                             \
316 do {                                                                                           \
317   (add)->next = (head);                                                                        \
318   (head) = (add);                                                                              \
319 } while (0)
320 
321 #define LL_CONCAT(head1,head2)                                                                 \
322     LL_CONCAT2(head1,head2,next)
323 
324 #define LL_CONCAT2(head1,head2,next)                                                           \
325 do {                                                                                           \
326   LDECLTYPE(head1) _tmp;                                                                       \
327   if (head1) {                                                                                 \
328     _tmp = (head1);                                                                            \
329     while (_tmp->next) { _tmp = _tmp->next; }                                                  \
330     _tmp->next=(head2);                                                                        \
331   } else {                                                                                     \
332     (head1)=(head2);                                                                           \
333   }                                                                                            \
334 } while (0)
335 
336 #define LL_APPEND(head,add)                                                                    \
337     LL_APPEND2(head,add,next)
338 
339 #define LL_APPEND2(head,add,next)                                                              \
340 do {                                                                                           \
341   LDECLTYPE(head) _tmp;                                                                        \
342   (add)->next=NULL;                                                                            \
343   if (head) {                                                                                  \
344     _tmp = (head);                                                                             \
345     while (_tmp->next) { _tmp = _tmp->next; }                                                  \
346     _tmp->next=(add);                                                                          \
347   } else {                                                                                     \
348     (head)=(add);                                                                              \
349   }                                                                                            \
350 } while (0)
351 
352 #define LL_DELETE(head,del)                                                                    \
353     LL_DELETE2(head,del,next)
354 
355 #define LL_DELETE2(head,del,next)                                                              \
356 do {                                                                                           \
357   LDECLTYPE(head) _tmp;                                                                        \
358   if ((head) == (del)) {                                                                       \
359     (head)=(head)->next;                                                                       \
360   } else {                                                                                     \
361     _tmp = (head);                                                                             \
362     while (_tmp->next && (_tmp->next != (del))) {                                              \
363       _tmp = _tmp->next;                                                                       \
364     }                                                                                          \
365     if (_tmp->next) {                                                                          \
366       _tmp->next = (del)->next;                                                                \
367     }                                                                                          \
368   }                                                                                            \
369 } while (0)
370 
371 #define LL_COUNT(head,el,counter)                                                              \
372     LL_COUNT2(head,el,counter,next)                                                            \
373 
374 #define LL_COUNT2(head,el,counter,next)                                                        \
375 do {                                                                                           \
376   (counter) = 0;                                                                               \
377   LL_FOREACH2(head,el,next) { ++(counter); }                                                   \
378 } while (0)
379 
380 #define LL_FOREACH(head,el)                                                                    \
381     LL_FOREACH2(head,el,next)
382 
383 #define LL_FOREACH2(head,el,next)                                                              \
384     for ((el) = (head); el; (el) = (el)->next)
385 
386 #define LL_FOREACH_SAFE(head,el,tmp)                                                           \
387     LL_FOREACH_SAFE2(head,el,tmp,next)
388 
389 #define LL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
390   for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
391 
392 #define LL_SEARCH_SCALAR(head,out,field,val)                                                   \
393     LL_SEARCH_SCALAR2(head,out,field,val,next)
394 
395 #define LL_SEARCH_SCALAR2(head,out,field,val,next)                                             \
396 do {                                                                                           \
397     LL_FOREACH2(head,out,next) {                                                               \
398       if ((out)->field == (val)) break;                                                        \
399     }                                                                                          \
400 } while (0)
401 
402 #define LL_SEARCH(head,out,elt,cmp)                                                            \
403     LL_SEARCH2(head,out,elt,cmp,next)
404 
405 #define LL_SEARCH2(head,out,elt,cmp,next)                                                      \
406 do {                                                                                           \
407     LL_FOREACH2(head,out,next) {                                                               \
408       if ((cmp(out,elt))==0) break;                                                            \
409     }                                                                                          \
410 } while (0)
411 
412 #define LL_REPLACE_ELEM2(head, el, add, next)                                                  \
413 do {                                                                                           \
414  LDECLTYPE(head) _tmp;                                                                         \
415  assert((head) != NULL);                                                                       \
416  assert((el) != NULL);                                                                         \
417  assert((add) != NULL);                                                                        \
418  (add)->next = (el)->next;                                                                     \
419  if ((head) == (el)) {                                                                         \
420   (head) = (add);                                                                              \
421  } else {                                                                                      \
422   _tmp = (head);                                                                               \
423   while (_tmp->next && (_tmp->next != (el))) {                                                 \
424    _tmp = _tmp->next;                                                                          \
425   }                                                                                            \
426   if (_tmp->next) {                                                                            \
427     _tmp->next = (add);                                                                        \
428   }                                                                                            \
429  }                                                                                             \
430 } while (0)
431 
432 #define LL_REPLACE_ELEM(head, el, add)                                                         \
433     LL_REPLACE_ELEM2(head, el, add, next)
434 
435 #define LL_PREPEND_ELEM2(head, el, add, next)                                                  \
436 do {                                                                                           \
437  if (el) {                                                                                     \
438   LDECLTYPE(head) _tmp;                                                                        \
439   assert((head) != NULL);                                                                      \
440   assert((add) != NULL);                                                                       \
441   (add)->next = (el);                                                                          \
442   if ((head) == (el)) {                                                                        \
443    (head) = (add);                                                                             \
444   } else {                                                                                     \
445    _tmp = (head);                                                                              \
446    while (_tmp->next && (_tmp->next != (el))) {                                                \
447     _tmp = _tmp->next;                                                                         \
448    }                                                                                           \
449    if (_tmp->next) {                                                                           \
450      _tmp->next = (add);                                                                       \
451    }                                                                                           \
452   }                                                                                            \
453  } else {                                                                                      \
454   LL_APPEND2(head, add, next);                                                                 \
455  }                                                                                             \
456 } while (0)                                                                                    \
457 
458 #define LL_PREPEND_ELEM(head, el, add)                                                         \
459     LL_PREPEND_ELEM2(head, el, add, next)
460 
461 #define LL_APPEND_ELEM2(head, el, add, next)                                                   \
462 do {                                                                                           \
463  if (el) {                                                                                     \
464   assert((head) != NULL);                                                                      \
465   assert((add) != NULL);                                                                       \
466   (add)->next = (el)->next;                                                                    \
467   (el)->next = (add);                                                                          \
468  } else {                                                                                      \
469   LL_PREPEND2(head, add, next);                                                                \
470  }                                                                                             \
471 } while (0)                                                                                    \
472 
473 #define LL_APPEND_ELEM(head, el, add)                                                          \
474     LL_APPEND_ELEM2(head, el, add, next)
475 
476 #ifdef NO_DECLTYPE
477 /* Here are VS2008 / NO_DECLTYPE replacements for a few functions */
478 
479 #undef LL_CONCAT2
480 #define LL_CONCAT2(head1,head2,next)                                                           \
481 do {                                                                                           \
482   char *_tmp;                                                                                  \
483   if (head1) {                                                                                 \
484     _tmp = (char*)(head1);                                                                     \
485     while ((head1)->next) { (head1) = (head1)->next; }                                         \
486     (head1)->next = (head2);                                                                   \
487     _RS(head1);                                                                                \
488   } else {                                                                                     \
489     (head1)=(head2);                                                                           \
490   }                                                                                            \
491 } while (0)
492 
493 #undef LL_APPEND2
494 #define LL_APPEND2(head,add,next)                                                              \
495 do {                                                                                           \
496   if (head) {                                                                                  \
497     (add)->next = head;     /* use add->next as a temp variable */                             \
498     while ((add)->next->next) { (add)->next = (add)->next->next; }                             \
499     (add)->next->next=(add);                                                                   \
500   } else {                                                                                     \
501     (head)=(add);                                                                              \
502   }                                                                                            \
503   (add)->next=NULL;                                                                            \
504 } while (0)
505 
506 #undef LL_DELETE2
507 #define LL_DELETE2(head,del,next)                                                              \
508 do {                                                                                           \
509   if ((head) == (del)) {                                                                       \
510     (head)=(head)->next;                                                                       \
511   } else {                                                                                     \
512     char *_tmp = (char*)(head);                                                                \
513     while ((head)->next && ((head)->next != (del))) {                                          \
514       (head) = (head)->next;                                                                   \
515     }                                                                                          \
516     if ((head)->next) {                                                                        \
517       (head)->next = ((del)->next);                                                            \
518     }                                                                                          \
519     _RS(head);                                                                                 \
520   }                                                                                            \
521 } while (0)
522 
523 #undef LL_REPLACE_ELEM2
524 #define LL_REPLACE_ELEM2(head, el, add, next)                                                  \
525 do {                                                                                           \
526   assert((head) != NULL);                                                                      \
527   assert((el) != NULL);                                                                        \
528   assert((add) != NULL);                                                                       \
529   if ((head) == (el)) {                                                                        \
530     (head) = (add);                                                                            \
531   } else {                                                                                     \
532     (add)->next = head;                                                                        \
533     while ((add)->next->next && ((add)->next->next != (el))) {                                 \
534       (add)->next = (add)->next->next;                                                         \
535     }                                                                                          \
536     if ((add)->next->next) {                                                                   \
537       (add)->next->next = (add);                                                               \
538     }                                                                                          \
539   }                                                                                            \
540   (add)->next = (el)->next;                                                                    \
541 } while (0)
542 
543 #undef LL_PREPEND_ELEM2
544 #define LL_PREPEND_ELEM2(head, el, add, next)                                                  \
545 do {                                                                                           \
546   if (el) {                                                                                    \
547     assert((head) != NULL);                                                                    \
548     assert((add) != NULL);                                                                     \
549     if ((head) == (el)) {                                                                      \
550       (head) = (add);                                                                          \
551     } else {                                                                                   \
552       (add)->next = (head);                                                                    \
553       while ((add)->next->next && ((add)->next->next != (el))) {                               \
554         (add)->next = (add)->next->next;                                                       \
555       }                                                                                        \
556       if ((add)->next->next) {                                                                 \
557         (add)->next->next = (add);                                                             \
558       }                                                                                        \
559     }                                                                                          \
560     (add)->next = (el);                                                                        \
561   } else {                                                                                     \
562     LL_APPEND2(head, add, next);                                                               \
563   }                                                                                            \
564 } while (0)                                                                                    \
565 
566 #endif /* NO_DECLTYPE */
567 
568 /******************************************************************************
569  * doubly linked list macros (non-circular)                                   *
570  *****************************************************************************/
571 #define DL_PREPEND(head,add)                                                                   \
572     DL_PREPEND2(head,add,prev,next)
573 
574 #define DL_PREPEND2(head,add,prev,next)                                                        \
575 do {                                                                                           \
576  (add)->next = (head);                                                                         \
577  if (head) {                                                                                   \
578    (add)->prev = (head)->prev;                                                                 \
579    (head)->prev = (add);                                                                       \
580  } else {                                                                                      \
581    (add)->prev = (add);                                                                        \
582  }                                                                                             \
583  (head) = (add);                                                                               \
584 } while (0)
585 
586 #define DL_APPEND(head,add)                                                                    \
587     DL_APPEND2(head,add,prev,next)
588 
589 #define DL_APPEND2(head,add,prev,next)                                                         \
590 do {                                                                                           \
591   if (head) {                                                                                  \
592       (add)->prev = (head)->prev;                                                              \
593       (head)->prev->next = (add);                                                              \
594       (head)->prev = (add);                                                                    \
595       (add)->next = NULL;                                                                      \
596   } else {                                                                                     \
597       (head)=(add);                                                                            \
598       (head)->prev = (head);                                                                   \
599       (head)->next = NULL;                                                                     \
600   }                                                                                            \
601 } while (0)
602 
603 #define DL_CONCAT(head1,head2)                                                                 \
604     DL_CONCAT2(head1,head2,prev,next)
605 
606 #define DL_CONCAT2(head1,head2,prev,next)                                                      \
607 do {                                                                                           \
608   LDECLTYPE(head1) _tmp;                                                                       \
609   if (head2) {                                                                                 \
610     if (head1) {                                                                               \
611         _CASTASGN(_tmp, (head2)->prev);                                                        \
612         (head2)->prev = (head1)->prev;                                                         \
613         (head1)->prev->next = (head2);                                                         \
614         _CASTASGN((head1)->prev, _tmp);                                                        \
615     } else {                                                                                   \
616         (head1)=(head2);                                                                       \
617     }                                                                                          \
618   }                                                                                            \
619 } while (0)
620 
621 #define DL_DELETE(head,del)                                                                    \
622     DL_DELETE2(head,del,prev,next)
623 
624 #define DL_DELETE2(head,del,prev,next)                                                         \
625 do {                                                                                           \
626   assert((del)->prev != NULL);                                                                 \
627   if ((del)->prev == (del)) {                                                                  \
628       (head)=NULL;                                                                             \
629   } else if ((del)==(head)) {                                                                  \
630       (del)->next->prev = (del)->prev;                                                         \
631       (head) = (del)->next;                                                                    \
632   } else {                                                                                     \
633       (del)->prev->next = (del)->next;                                                         \
634       if ((del)->next) {                                                                       \
635           (del)->next->prev = (del)->prev;                                                     \
636       } else {                                                                                 \
637           (head)->prev = (del)->prev;                                                          \
638       }                                                                                        \
639   }                                                                                            \
640 } while (0)
641 
642 #define DL_COUNT(head,el,counter)                                                              \
643     DL_COUNT2(head,el,counter,next)                                                            \
644 
645 #define DL_COUNT2(head,el,counter,next)                                                        \
646 do {                                                                                           \
647   (counter) = 0;                                                                               \
648   DL_FOREACH2(head,el,next) { ++(counter); }                                                   \
649 } while (0)
650 
651 #define DL_FOREACH(head,el)                                                                    \
652     DL_FOREACH2(head,el,next)
653 
654 #define DL_FOREACH2(head,el,next)                                                              \
655     for ((el) = (head); el; (el) = (el)->next)
656 
657 /* this version is safe for deleting the elements during iteration */
658 #define DL_FOREACH_SAFE(head,el,tmp)                                                           \
659     DL_FOREACH_SAFE2(head,el,tmp,next)
660 
661 #define DL_FOREACH_SAFE2(head,el,tmp,next)                                                     \
662   for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp))
663 
664 /* these are identical to their singly-linked list counterparts */
665 #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
666 #define DL_SEARCH LL_SEARCH
667 #define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2
668 #define DL_SEARCH2 LL_SEARCH2
669 
670 #define DL_REPLACE_ELEM2(head, el, add, prev, next)                                            \
671 do {                                                                                           \
672  assert((head) != NULL);                                                                       \
673  assert((el) != NULL);                                                                         \
674  assert((add) != NULL);                                                                        \
675  if ((head) == (el)) {                                                                         \
676   (head) = (add);                                                                              \
677   (add)->next = (el)->next;                                                                    \
678   if ((el)->next == NULL) {                                                                    \
679    (add)->prev = (add);                                                                        \
680   } else {                                                                                     \
681    (add)->prev = (el)->prev;                                                                   \
682    (add)->next->prev = (add);                                                                  \
683   }                                                                                            \
684  } else {                                                                                      \
685   (add)->next = (el)->next;                                                                    \
686   (add)->prev = (el)->prev;                                                                    \
687   (add)->prev->next = (add);                                                                   \
688   if ((el)->next == NULL) {                                                                    \
689    (head)->prev = (add);                                                                       \
690   } else {                                                                                     \
691    (add)->next->prev = (add);                                                                  \
692   }                                                                                            \
693  }                                                                                             \
694 } while (0)
695 
696 #define DL_REPLACE_ELEM(head, el, add)                                                         \
697     DL_REPLACE_ELEM2(head, el, add, prev, next)
698 
699 #define DL_PREPEND_ELEM2(head, el, add, prev, next)                                            \
700 do {                                                                                           \
701  if (el) {                                                                                     \
702   assert((head) != NULL);                                                                      \
703   assert((add) != NULL);                                                                       \
704   (add)->next = (el);                                                                          \
705   (add)->prev = (el)->prev;                                                                    \
706   (el)->prev = (add);                                                                          \
707   if ((head) == (el)) {                                                                        \
708    (head) = (add);                                                                             \
709   } else {                                                                                     \
710    (add)->prev->next = (add);                                                                  \
711   }                                                                                            \
712  } else {                                                                                      \
713   DL_APPEND2(head, add, prev, next);                                                           \
714  }                                                                                             \
715 } while (0)                                                                                    \
716 
717 #define DL_PREPEND_ELEM(head, el, add)                                                         \
718     DL_PREPEND_ELEM2(head, el, add, prev, next)
719 
720 #define DL_APPEND_ELEM2(head, el, add, prev, next)                                             \
721 do {                                                                                           \
722  if (el) {                                                                                     \
723   assert((head) != NULL);                                                                      \
724   assert((add) != NULL);                                                                       \
725   (add)->next = (el)->next;                                                                    \
726   (add)->prev = (el);                                                                          \
727   (el)->next = (add);                                                                          \
728   if ((add)->next) {                                                                           \
729    (add)->next->prev = (add);                                                                  \
730   } else {                                                                                     \
731    (head)->prev = (add);                                                                       \
732   }                                                                                            \
733  } else {                                                                                      \
734   DL_PREPEND2(head, add, prev, next);                                                          \
735  }                                                                                             \
736 } while (0)                                                                                    \
737 
738 #define DL_APPEND_ELEM(head, el, add)                                                          \
739    DL_APPEND_ELEM2(head, el, add, prev, next)
740 
741 /******************************************************************************
742  * circular doubly linked list macros                                         *
743  *****************************************************************************/
744 #define CDL_APPEND(head,add)                                                                   \
745     CDL_APPEND2(head,add,prev,next)
746 
747 #define CDL_APPEND2(head,add,prev,next)                                                        \
748 do {                                                                                           \
749  if (head) {                                                                                   \
750    (add)->prev = (head)->prev;                                                                 \
751    (add)->next = (head);                                                                       \
752    (head)->prev = (add);                                                                       \
753    (add)->prev->next = (add);                                                                  \
754  } else {                                                                                      \
755    (add)->prev = (add);                                                                        \
756    (add)->next = (add);                                                                        \
757    (head) = (add);                                                                             \
758  }                                                                                             \
759 } while (0)
760 
761 #define CDL_PREPEND(head,add)                                                                  \
762     CDL_PREPEND2(head,add,prev,next)
763 
764 #define CDL_PREPEND2(head,add,prev,next)                                                       \
765 do {                                                                                           \
766  if (head) {                                                                                   \
767    (add)->prev = (head)->prev;                                                                 \
768    (add)->next = (head);                                                                       \
769    (head)->prev = (add);                                                                       \
770    (add)->prev->next = (add);                                                                  \
771  } else {                                                                                      \
772    (add)->prev = (add);                                                                        \
773    (add)->next = (add);                                                                        \
774  }                                                                                             \
775  (head) = (add);                                                                               \
776 } while (0)
777 
778 #define CDL_DELETE(head,del)                                                                   \
779     CDL_DELETE2(head,del,prev,next)
780 
781 #define CDL_DELETE2(head,del,prev,next)                                                        \
782 do {                                                                                           \
783   if (((head)==(del)) && ((head)->next == (head))) {                                           \
784       (head) = NULL;                                                                           \
785   } else {                                                                                     \
786      (del)->next->prev = (del)->prev;                                                          \
787      (del)->prev->next = (del)->next;                                                          \
788      if ((del) == (head)) (head)=(del)->next;                                                  \
789   }                                                                                            \
790 } while (0)
791 
792 #define CDL_COUNT(head,el,counter)                                                             \
793     CDL_COUNT2(head,el,counter,next)                                                           \
794 
795 #define CDL_COUNT2(head, el, counter,next)                                                     \
796 do {                                                                                           \
797   (counter) = 0;                                                                               \
798   CDL_FOREACH2(head,el,next) { ++(counter); }                                                  \
799 } while (0)
800 
801 #define CDL_FOREACH(head,el)                                                                   \
802     CDL_FOREACH2(head,el,next)
803 
804 #define CDL_FOREACH2(head,el,next)                                                             \
805     for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next))
806 
807 #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2)                                                    \
808     CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)
809 
810 #define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next)                                         \
811   for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL;                                   \
812        (el) && ((tmp2) = (el)->next, 1);                                                       \
813        (el) = ((el) == (tmp1) ? NULL : (tmp2)))
814 
815 #define CDL_SEARCH_SCALAR(head,out,field,val)                                                  \
816     CDL_SEARCH_SCALAR2(head,out,field,val,next)
817 
818 #define CDL_SEARCH_SCALAR2(head,out,field,val,next)                                            \
819 do {                                                                                           \
820     CDL_FOREACH2(head,out,next) {                                                              \
821       if ((out)->field == (val)) break;                                                        \
822     }                                                                                          \
823 } while (0)
824 
825 #define CDL_SEARCH(head,out,elt,cmp)                                                           \
826     CDL_SEARCH2(head,out,elt,cmp,next)
827 
828 #define CDL_SEARCH2(head,out,elt,cmp,next)                                                     \
829 do {                                                                                           \
830     CDL_FOREACH2(head,out,next) {                                                              \
831       if ((cmp(out,elt))==0) break;                                                            \
832     }                                                                                          \
833 } while (0)
834 
835 #define CDL_REPLACE_ELEM2(head, el, add, prev, next)                                           \
836 do {                                                                                           \
837  assert((head) != NULL);                                                                       \
838  assert((el) != NULL);                                                                         \
839  assert((add) != NULL);                                                                        \
840  if ((el)->next == (el)) {                                                                     \
841   (add)->next = (add);                                                                         \
842   (add)->prev = (add);                                                                         \
843   (head) = (add);                                                                              \
844  } else {                                                                                      \
845   (add)->next = (el)->next;                                                                    \
846   (add)->prev = (el)->prev;                                                                    \
847   (add)->next->prev = (add);                                                                   \
848   (add)->prev->next = (add);                                                                   \
849   if ((head) == (el)) {                                                                        \
850    (head) = (add);                                                                             \
851   }                                                                                            \
852  }                                                                                             \
853 } while (0)
854 
855 #define CDL_REPLACE_ELEM(head, el, add)                                                        \
856     CDL_REPLACE_ELEM2(head, el, add, prev, next)
857 
858 #define CDL_PREPEND_ELEM2(head, el, add, prev, next)                                           \
859 do {                                                                                           \
860   if (el) {                                                                                    \
861     assert((head) != NULL);                                                                    \
862     assert((add) != NULL);                                                                     \
863     (add)->next = (el);                                                                        \
864     (add)->prev = (el)->prev;                                                                  \
865     (el)->prev = (add);                                                                        \
866     (add)->prev->next = (add);                                                                 \
867     if ((head) == (el)) {                                                                      \
868       (head) = (add);                                                                          \
869     }                                                                                          \
870   } else {                                                                                     \
871     CDL_APPEND2(head, add, prev, next);                                                        \
872   }                                                                                            \
873 } while (0)
874 
875 #define CDL_PREPEND_ELEM(head, el, add)                                                        \
876     CDL_PREPEND_ELEM2(head, el, add, prev, next)
877 
878 #define CDL_APPEND_ELEM2(head, el, add, prev, next)                                            \
879 do {                                                                                           \
880  if (el) {                                                                                     \
881   assert((head) != NULL);                                                                      \
882   assert((add) != NULL);                                                                       \
883   (add)->next = (el)->next;                                                                    \
884   (add)->prev = (el);                                                                          \
885   (el)->next = (add);                                                                          \
886   (add)->next->prev = (add);                                                                   \
887  } else {                                                                                      \
888   CDL_PREPEND2(head, add, prev, next);                                                         \
889  }                                                                                             \
890 } while (0)
891 
892 #define CDL_APPEND_ELEM(head, el, add)                                                         \
893     CDL_APPEND_ELEM2(head, el, add, prev, next)
894 
895 #endif /* UTLIST_H */
896