1 /*
2  * lists and queues implementations
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 2 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; see the file COPYING; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #ifndef _FRR_QUEUE_H
20 #define _FRR_QUEUE_H
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #if defined(__OpenBSD__) && !defined(STAILQ_HEAD)
27 #include "openbsd-queue.h"
28 
29 /* Try to map FreeBSD implementation to OpenBSD one. */
30 #define STAILQ_HEAD(name, type)				SIMPLEQ_HEAD(name, type)
31 #define STAILQ_HEAD_INITIALIZER(head)			SIMPLEQ_HEAD_INITIALIZER(head)
32 #define STAILQ_ENTRY(entry)				SIMPLEQ_ENTRY(entry)
33 
34 #define STAILQ_CONCAT(head1, head2)			SIMPLEQ_CONCAT(head1, head2)
35 #define STAILQ_EMPTY(head)				SIMPLEQ_EMPTY(head)
36 #define STAILQ_FIRST(head)				SIMPLEQ_FIRST(head)
37 #define STAILQ_FOREACH(var, head, field)		SIMPLEQ_FOREACH(var, head, field)
38 #define STAILQ_FOREACH_SAFE(var, head, field, tvar)	SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)
39 #define STAILQ_INIT(head)				SIMPLEQ_INIT(head)
40 #define STAILQ_INSERT_AFTER(head, tqelm, elm, field)	SIMPLEQ_INSERT_AFTER(head, tqelm, elm, field)
41 #define STAILQ_INSERT_HEAD(head, elm, field)		SIMPLEQ_INSERT_HEAD(head, elm, field)
42 #define STAILQ_INSERT_TAIL(head, elm, field)		SIMPLEQ_INSERT_TAIL(head, elm, field)
43 #define STAILQ_LAST(head, type, field)                                         \
44 	(SIMPLEQ_EMPTY((head))                                                 \
45 		 ? NULL                                                        \
46 		 : ((struct type *)(void *)((char *)((head)->sqh_last)         \
47 					    - offsetof(struct type, field))))
48 #define STAILQ_NEXT(elm, field)				SIMPLEQ_NEXT(elm, field)
49 #define STAILQ_REMOVE(head, elm, type, field)                                  \
50 	do {                                                                   \
51 		if (SIMPLEQ_FIRST((head)) == (elm)) {                          \
52 			SIMPLEQ_REMOVE_HEAD((head), field);                    \
53 		} else {                                                       \
54 			struct type *curelm = SIMPLEQ_FIRST((head));           \
55 			while (SIMPLEQ_NEXT(curelm, field) != (elm))           \
56 				curelm = SIMPLEQ_NEXT(curelm, field);          \
57 			SIMPLEQ_REMOVE_AFTER(head, curelm, field);             \
58 		}                                                              \
59 	} while (0)
60 #define STAILQ_REMOVE_AFTER(head, elm, field)		SIMPLEQ_REMOVE_AFTER(head, elm, field)
61 #define STAILQ_REMOVE_HEAD(head, field)			SIMPLEQ_REMOVE_HEAD(head, field)
62 #define STAILQ_SWAP(head1, head2, type)                                        \
63 	do {                                                                   \
64 		struct type *swap_first = STAILQ_FIRST(head1);                 \
65 		struct type **swap_last = (head1)->sqh_last;                   \
66 		STAILQ_FIRST(head1) = STAILQ_FIRST(head2);                     \
67 		(head1)->sqh_last = (head2)->sqh_last;                         \
68 		STAILQ_FIRST(head2) = swap_first;                              \
69 		(head2)->sqh_last = swap_last;                                 \
70 		if (STAILQ_EMPTY(head1))                                       \
71 			(head1)->sqh_last = &STAILQ_FIRST(head1);              \
72 		if (STAILQ_EMPTY(head2))                                       \
73 			(head2)->sqh_last = &STAILQ_FIRST(head2);              \
74 	} while (0)
75 #else
76 #include "freebsd-queue.h"
77 #endif /* defined(__OpenBSD__) && !defined(STAILQ_HEAD) */
78 
79 #ifndef TAILQ_POP_FIRST
80 #define TAILQ_POP_FIRST(head, field)                                           \
81 	({  typeof((head)->tqh_first) _elm = TAILQ_FIRST(head);                \
82 	    if (_elm) {                                                        \
83 		if ((TAILQ_NEXT((_elm), field)) != NULL)                       \
84 			TAILQ_NEXT((_elm), field)->field.tqe_prev =            \
85 				&TAILQ_FIRST(head);                            \
86 		else                                                           \
87 			(head)->tqh_last = &TAILQ_FIRST(head);                 \
88 		TAILQ_FIRST(head) = TAILQ_NEXT((_elm), field);                 \
89 	}; _elm; })
90 #endif
91 
92 #ifdef __cplusplus
93 }
94 #endif
95 
96 #endif /* _FRR_QUEUE_H */
97