xref: /netbsd/external/bsd/ntp/dist/include/ntp_lists.h (revision 6550d01e)
1 /*	$NetBSD: ntp_lists.h,v 1.1.1.1 2009/12/13 16:54:51 kardel Exp $	*/
2 
3 /*
4  * ntp_lists.h - singly-linked lists common code
5  *
6  * These macros implement a simple singly-linked list template.  Both
7  * the listhead and per-entry next fields are declared as pointers to
8  * the list entry struct type.  Initialization to NULL is typically
9  * implicit (for globals and statics) or handled by zeroing of the
10  * containing structure.
11  *
12  * The name of the next link field is passed as an argument to allow
13  * membership in several lists at once using multiple next link fields.
14  *
15  * When possible, placing the link field first in the entry structure
16  * allows slightly smaller code to be generated on some platforms.
17  *
18  * LINK_SLIST(listhead, pentry, nextlink)
19  *	add entry at head
20  *
21  * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)
22  *	add entry at tail
23  *
24  * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)
25  *	unlink first entry and point punlinked to it, or set punlinked
26  *	to NULL if the list is empty.
27  *
28  * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype)
29  *	unlink entry pointed to by ptounlink.  punlinked is set to NULL
30  *	if the entry is not found on the list, otherwise it is set to
31  *	ptounlink.
32  *
33  * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype)
34  *	unlink entry where expression expr is nonzero.  expr can refer
35  *	to the entry being tested using UNLINK_EXPR_SLIST_CURRENT().
36  *	See the	implementation of UNLINK_SLIST() below for an example.
37  *	punlinked is pointed to the removed entry or NULL if none
38  *	satisfy expr.
39  */
40 #ifndef NTP_LISTS_H
41 #define NTP_LISTS_H
42 
43 #ifdef HAVE_CONFIG_H
44 # include <config.h>
45 #endif
46 
47 #include <isc/list.h>
48 
49 
50 #define LINK_SLIST(listhead, pentry, nextlink)			\
51 do {								\
52 	(pentry)->nextlink = (listhead);			\
53 	(listhead) = (pentry);					\
54 } while (0)
55 
56 #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)	\
57 do {								\
58 	entrytype **pptail;					\
59 								\
60 	pptail = &(listhead);					\
61 	while (*pptail != NULL)					\
62 		pptail = &((*pptail)->nextlink);		\
63 								\
64 	(pentry)->nextlink = NULL;				\
65 	*pptail = (pentry);					\
66 } while (0)
67 
68 #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)	\
69 do {								\
70 	(punlinked) = (listhead);				\
71 	if (NULL != (punlinked)) {				\
72 		(listhead) = (punlinked)->nextlink;		\
73 		(punlinked)->nextlink = NULL;			\
74 	}							\
75 } while (0)
76 
77 #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink,	\
78 			  entrytype)				\
79 do {								\
80 	entrytype **ppentry;					\
81 								\
82 	ppentry = &(listhead);					\
83 								\
84 	while (!(expr))						\
85 		if ((*ppentry)->nextlink != NULL)		\
86 			ppentry = &((*ppentry)->nextlink);	\
87 		else {						\
88 			ppentry = NULL;				\
89 			break;					\
90 		}						\
91 								\
92 	if (ppentry != NULL) {					\
93 		(punlinked) = *ppentry;				\
94 		*ppentry = (punlinked)->nextlink;		\
95 		(punlinked)->nextlink = NULL;			\
96 	} else							\
97 		(punlinked) = NULL;				\
98 } while (0)
99 #define UNLINK_EXPR_SLIST_CURRENT()	(*ppentry)
100 
101 #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink,	\
102 		     entrytype)					\
103 	UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) ==	\
104 	    UNLINK_EXPR_SLIST_CURRENT(), nextlink, entrytype)
105 
106 #endif	/* NTP_LISTS_H */
107