xref: /titanic_44/usr/src/cmd/ssh/include/sys-tree.h (revision b9aa66a73c9016cf5c71fe80efe90ce9f2ca5c73)
17c478bd9Sstevel@tonic-gate /*	$OpenBSD: tree.h,v 1.6 2002/06/11 22:09:52 provos Exp $	*/
27c478bd9Sstevel@tonic-gate /*
37c478bd9Sstevel@tonic-gate  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
47c478bd9Sstevel@tonic-gate  * All rights reserved.
57c478bd9Sstevel@tonic-gate  *
67c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
77c478bd9Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
87c478bd9Sstevel@tonic-gate  * are met:
97c478bd9Sstevel@tonic-gate  * 1. Redistributions of source code must retain the above copyright
107c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
117c478bd9Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
127c478bd9Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
137c478bd9Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
147c478bd9Sstevel@tonic-gate  *
157c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
167c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
177c478bd9Sstevel@tonic-gate  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
187c478bd9Sstevel@tonic-gate  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
197c478bd9Sstevel@tonic-gate  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
207c478bd9Sstevel@tonic-gate  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
217c478bd9Sstevel@tonic-gate  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
227c478bd9Sstevel@tonic-gate  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
237c478bd9Sstevel@tonic-gate  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
247c478bd9Sstevel@tonic-gate  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #ifndef	_SYS_TREE_H
287c478bd9Sstevel@tonic-gate #define	_SYS_TREE_H
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #ifdef __cplusplus
317c478bd9Sstevel@tonic-gate extern "C" {
327c478bd9Sstevel@tonic-gate #endif
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate  * This file defines data structures for different types of trees:
367c478bd9Sstevel@tonic-gate  * splay trees and red-black trees.
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * A splay tree is a self-organizing data structure.  Every operation
397c478bd9Sstevel@tonic-gate  * on the tree causes a splay to happen.  The splay moves the requested
407c478bd9Sstevel@tonic-gate  * node to the root of the tree and partly rebalances it.
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * This has the benefit that request locality causes faster lookups as
437c478bd9Sstevel@tonic-gate  * the requested nodes move to the top of the tree.  On the other hand,
447c478bd9Sstevel@tonic-gate  * every lookup causes memory writes.
457c478bd9Sstevel@tonic-gate  *
467c478bd9Sstevel@tonic-gate  * The Balance Theorem bounds the total access time for m operations
477c478bd9Sstevel@tonic-gate  * and n inserts on an initially empty tree as O((m + n)lg n).  The
487c478bd9Sstevel@tonic-gate  * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
497c478bd9Sstevel@tonic-gate  *
507c478bd9Sstevel@tonic-gate  * A red-black tree is a binary search tree with the node color as an
517c478bd9Sstevel@tonic-gate  * extra attribute.  It fulfills a set of conditions:
527c478bd9Sstevel@tonic-gate  *	- every search path from the root to a leaf consists of the
537c478bd9Sstevel@tonic-gate  *	  same number of black nodes,
547c478bd9Sstevel@tonic-gate  *	- each red node (except for the root) has a black parent,
557c478bd9Sstevel@tonic-gate  *	- each leaf node is black.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * Every operation on a red-black tree is bounded as O(lg n).
587c478bd9Sstevel@tonic-gate  * The maximum height of a red-black tree is 2lg (n+1).
597c478bd9Sstevel@tonic-gate  */
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #define SPLAY_HEAD(name, type)						\
627c478bd9Sstevel@tonic-gate struct name {								\
637c478bd9Sstevel@tonic-gate 	struct type *sph_root; /* root of the tree */			\
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #define SPLAY_INITIALIZER(root)						\
677c478bd9Sstevel@tonic-gate 	{ NULL }
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define SPLAY_INIT(root) do {						\
707c478bd9Sstevel@tonic-gate 	(root)->sph_root = NULL;					\
717c478bd9Sstevel@tonic-gate } while (0)
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #define SPLAY_ENTRY(type)						\
747c478bd9Sstevel@tonic-gate struct {								\
757c478bd9Sstevel@tonic-gate 	struct type *spe_left; /* left element */			\
767c478bd9Sstevel@tonic-gate 	struct type *spe_right; /* right element */			\
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate #define SPLAY_LEFT(elm, field)		(elm)->field.spe_left
807c478bd9Sstevel@tonic-gate #define SPLAY_RIGHT(elm, field)		(elm)->field.spe_right
817c478bd9Sstevel@tonic-gate #define SPLAY_ROOT(head)		(head)->sph_root
827c478bd9Sstevel@tonic-gate #define SPLAY_EMPTY(head)		(SPLAY_ROOT(head) == NULL)
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
857c478bd9Sstevel@tonic-gate #define SPLAY_ROTATE_RIGHT(head, tmp, field) do {			\
867c478bd9Sstevel@tonic-gate 	SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field);	\
877c478bd9Sstevel@tonic-gate 	SPLAY_RIGHT(tmp, field) = (head)->sph_root;			\
887c478bd9Sstevel@tonic-gate 	(head)->sph_root = tmp;						\
897c478bd9Sstevel@tonic-gate } while (0)
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate #define SPLAY_ROTATE_LEFT(head, tmp, field) do {			\
927c478bd9Sstevel@tonic-gate 	SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field);	\
937c478bd9Sstevel@tonic-gate 	SPLAY_LEFT(tmp, field) = (head)->sph_root;			\
947c478bd9Sstevel@tonic-gate 	(head)->sph_root = tmp;						\
957c478bd9Sstevel@tonic-gate } while (0)
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #define SPLAY_LINKLEFT(head, tmp, field) do {				\
987c478bd9Sstevel@tonic-gate 	SPLAY_LEFT(tmp, field) = (head)->sph_root;			\
997c478bd9Sstevel@tonic-gate 	tmp = (head)->sph_root;						\
1007c478bd9Sstevel@tonic-gate 	(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);		\
1017c478bd9Sstevel@tonic-gate } while (0)
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #define SPLAY_LINKRIGHT(head, tmp, field) do {				\
1047c478bd9Sstevel@tonic-gate 	SPLAY_RIGHT(tmp, field) = (head)->sph_root;			\
1057c478bd9Sstevel@tonic-gate 	tmp = (head)->sph_root;						\
1067c478bd9Sstevel@tonic-gate 	(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);	\
1077c478bd9Sstevel@tonic-gate } while (0)
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #define SPLAY_ASSEMBLE(head, node, left, right, field) do {		\
1107c478bd9Sstevel@tonic-gate 	SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field);	\
1117c478bd9Sstevel@tonic-gate 	SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
1127c478bd9Sstevel@tonic-gate 	SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field);	\
1137c478bd9Sstevel@tonic-gate 	SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field);	\
1147c478bd9Sstevel@tonic-gate } while (0)
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /* Generates prototypes and inline functions */
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate #define SPLAY_PROTOTYPE(name, type, field, cmp)				\
1197c478bd9Sstevel@tonic-gate void name##_SPLAY(struct name *, struct type *);			\
1207c478bd9Sstevel@tonic-gate void name##_SPLAY_MINMAX(struct name *, int);				\
1217c478bd9Sstevel@tonic-gate struct type *name##_SPLAY_INSERT(struct name *, struct type *);		\
1227c478bd9Sstevel@tonic-gate struct type *name##_SPLAY_REMOVE(struct name *, struct type *);		\
1237c478bd9Sstevel@tonic-gate 									\
1247c478bd9Sstevel@tonic-gate /* Finds the node with the same key as elm */				\
1257c478bd9Sstevel@tonic-gate static __inline struct type *						\
1267c478bd9Sstevel@tonic-gate name##_SPLAY_FIND(struct name *head, struct type *elm)			\
1277c478bd9Sstevel@tonic-gate {									\
1287c478bd9Sstevel@tonic-gate 	if (SPLAY_EMPTY(head))						\
1297c478bd9Sstevel@tonic-gate 		return(NULL);						\
1307c478bd9Sstevel@tonic-gate 	name##_SPLAY(head, elm);					\
1317c478bd9Sstevel@tonic-gate 	if ((cmp)(elm, (head)->sph_root) == 0)				\
1327c478bd9Sstevel@tonic-gate 		return (head->sph_root);				\
1337c478bd9Sstevel@tonic-gate 	return (NULL);							\
1347c478bd9Sstevel@tonic-gate }									\
1357c478bd9Sstevel@tonic-gate 									\
1367c478bd9Sstevel@tonic-gate static __inline struct type *						\
1377c478bd9Sstevel@tonic-gate name##_SPLAY_NEXT(struct name *head, struct type *elm)			\
1387c478bd9Sstevel@tonic-gate {									\
1397c478bd9Sstevel@tonic-gate 	name##_SPLAY(head, elm);					\
1407c478bd9Sstevel@tonic-gate 	if (SPLAY_RIGHT(elm, field) != NULL) {				\
1417c478bd9Sstevel@tonic-gate 		elm = SPLAY_RIGHT(elm, field);				\
1427c478bd9Sstevel@tonic-gate 		while (SPLAY_LEFT(elm, field) != NULL) {		\
1437c478bd9Sstevel@tonic-gate 			elm = SPLAY_LEFT(elm, field);			\
1447c478bd9Sstevel@tonic-gate 		}							\
1457c478bd9Sstevel@tonic-gate 	} else								\
1467c478bd9Sstevel@tonic-gate 		elm = NULL;						\
1477c478bd9Sstevel@tonic-gate 	return (elm);							\
1487c478bd9Sstevel@tonic-gate }									\
1497c478bd9Sstevel@tonic-gate 									\
1507c478bd9Sstevel@tonic-gate static __inline struct type *						\
1517c478bd9Sstevel@tonic-gate name##_SPLAY_MIN_MAX(struct name *head, int val)			\
1527c478bd9Sstevel@tonic-gate {									\
1537c478bd9Sstevel@tonic-gate 	name##_SPLAY_MINMAX(head, val);					\
1547c478bd9Sstevel@tonic-gate         return (SPLAY_ROOT(head));					\
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate /* Main splay operation.
1587c478bd9Sstevel@tonic-gate  * Moves node close to the key of elm to top
1597c478bd9Sstevel@tonic-gate  */
1607c478bd9Sstevel@tonic-gate #define SPLAY_GENERATE(name, type, field, cmp)				\
1617c478bd9Sstevel@tonic-gate struct type *								\
1627c478bd9Sstevel@tonic-gate name##_SPLAY_INSERT(struct name *head, struct type *elm)		\
1637c478bd9Sstevel@tonic-gate {									\
1647c478bd9Sstevel@tonic-gate     if (SPLAY_EMPTY(head)) {						\
1657c478bd9Sstevel@tonic-gate 	    SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL;	\
1667c478bd9Sstevel@tonic-gate     } else {								\
1677c478bd9Sstevel@tonic-gate 	    int __comp;							\
1687c478bd9Sstevel@tonic-gate 	    name##_SPLAY(head, elm);					\
1697c478bd9Sstevel@tonic-gate 	    __comp = (cmp)(elm, (head)->sph_root);			\
1707c478bd9Sstevel@tonic-gate 	    if(__comp < 0) {						\
1717c478bd9Sstevel@tonic-gate 		    SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
1727c478bd9Sstevel@tonic-gate 		    SPLAY_RIGHT(elm, field) = (head)->sph_root;		\
1737c478bd9Sstevel@tonic-gate 		    SPLAY_LEFT((head)->sph_root, field) = NULL;		\
1747c478bd9Sstevel@tonic-gate 	    } else if (__comp > 0) {					\
1757c478bd9Sstevel@tonic-gate 		    SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
1767c478bd9Sstevel@tonic-gate 		    SPLAY_LEFT(elm, field) = (head)->sph_root;		\
1777c478bd9Sstevel@tonic-gate 		    SPLAY_RIGHT((head)->sph_root, field) = NULL;	\
1787c478bd9Sstevel@tonic-gate 	    } else							\
1797c478bd9Sstevel@tonic-gate 		    return ((head)->sph_root);				\
1807c478bd9Sstevel@tonic-gate     }									\
1817c478bd9Sstevel@tonic-gate     (head)->sph_root = (elm);						\
1827c478bd9Sstevel@tonic-gate     return (NULL);							\
1837c478bd9Sstevel@tonic-gate }									\
1847c478bd9Sstevel@tonic-gate 									\
1857c478bd9Sstevel@tonic-gate struct type *								\
1867c478bd9Sstevel@tonic-gate name##_SPLAY_REMOVE(struct name *head, struct type *elm)		\
1877c478bd9Sstevel@tonic-gate {									\
1887c478bd9Sstevel@tonic-gate 	struct type *__tmp;						\
1897c478bd9Sstevel@tonic-gate 	if (SPLAY_EMPTY(head))						\
1907c478bd9Sstevel@tonic-gate 		return (NULL);						\
1917c478bd9Sstevel@tonic-gate 	name##_SPLAY(head, elm);					\
1927c478bd9Sstevel@tonic-gate 	if ((cmp)(elm, (head)->sph_root) == 0) {			\
1937c478bd9Sstevel@tonic-gate 		if (SPLAY_LEFT((head)->sph_root, field) == NULL) {	\
1947c478bd9Sstevel@tonic-gate 			(head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
1957c478bd9Sstevel@tonic-gate 		} else {						\
1967c478bd9Sstevel@tonic-gate 			__tmp = SPLAY_RIGHT((head)->sph_root, field);	\
1977c478bd9Sstevel@tonic-gate 			(head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
1987c478bd9Sstevel@tonic-gate 			name##_SPLAY(head, elm);			\
1997c478bd9Sstevel@tonic-gate 			SPLAY_RIGHT((head)->sph_root, field) = __tmp;	\
2007c478bd9Sstevel@tonic-gate 		}							\
2017c478bd9Sstevel@tonic-gate 		return (elm);						\
2027c478bd9Sstevel@tonic-gate 	}								\
2037c478bd9Sstevel@tonic-gate 	return (NULL);							\
2047c478bd9Sstevel@tonic-gate }									\
2057c478bd9Sstevel@tonic-gate 									\
2067c478bd9Sstevel@tonic-gate void									\
2077c478bd9Sstevel@tonic-gate name##_SPLAY(struct name *head, struct type *elm)			\
2087c478bd9Sstevel@tonic-gate {									\
2097c478bd9Sstevel@tonic-gate 	struct type __node, *__left, *__right, *__tmp;			\
2107c478bd9Sstevel@tonic-gate 	int __comp;							\
2117c478bd9Sstevel@tonic-gate \
2127c478bd9Sstevel@tonic-gate 	SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
2137c478bd9Sstevel@tonic-gate 	__left = __right = &__node;					\
2147c478bd9Sstevel@tonic-gate \
2157c478bd9Sstevel@tonic-gate 	while ((__comp = (cmp)(elm, (head)->sph_root))) {		\
2167c478bd9Sstevel@tonic-gate 		if (__comp < 0) {					\
2177c478bd9Sstevel@tonic-gate 			__tmp = SPLAY_LEFT((head)->sph_root, field);	\
2187c478bd9Sstevel@tonic-gate 			if (__tmp == NULL)				\
2197c478bd9Sstevel@tonic-gate 				break;					\
2207c478bd9Sstevel@tonic-gate 			if ((cmp)(elm, __tmp) < 0){			\
2217c478bd9Sstevel@tonic-gate 				SPLAY_ROTATE_RIGHT(head, __tmp, field);	\
2227c478bd9Sstevel@tonic-gate 				if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
2237c478bd9Sstevel@tonic-gate 					break;				\
2247c478bd9Sstevel@tonic-gate 			}						\
2257c478bd9Sstevel@tonic-gate 			SPLAY_LINKLEFT(head, __right, field);		\
2267c478bd9Sstevel@tonic-gate 		} else if (__comp > 0) {				\
2277c478bd9Sstevel@tonic-gate 			__tmp = SPLAY_RIGHT((head)->sph_root, field);	\
2287c478bd9Sstevel@tonic-gate 			if (__tmp == NULL)				\
2297c478bd9Sstevel@tonic-gate 				break;					\
2307c478bd9Sstevel@tonic-gate 			if ((cmp)(elm, __tmp) > 0){			\
2317c478bd9Sstevel@tonic-gate 				SPLAY_ROTATE_LEFT(head, __tmp, field);	\
2327c478bd9Sstevel@tonic-gate 				if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
2337c478bd9Sstevel@tonic-gate 					break;				\
2347c478bd9Sstevel@tonic-gate 			}						\
2357c478bd9Sstevel@tonic-gate 			SPLAY_LINKRIGHT(head, __left, field);		\
2367c478bd9Sstevel@tonic-gate 		}							\
2377c478bd9Sstevel@tonic-gate 	}								\
2387c478bd9Sstevel@tonic-gate 	SPLAY_ASSEMBLE(head, &__node, __left, __right, field);		\
2397c478bd9Sstevel@tonic-gate }									\
2407c478bd9Sstevel@tonic-gate 									\
2417c478bd9Sstevel@tonic-gate /* Splay with either the minimum or the maximum element			\
2427c478bd9Sstevel@tonic-gate  * Used to find minimum or maximum element in tree.			\
2437c478bd9Sstevel@tonic-gate  */									\
2447c478bd9Sstevel@tonic-gate void name##_SPLAY_MINMAX(struct name *head, int __comp) \
2457c478bd9Sstevel@tonic-gate {									\
2467c478bd9Sstevel@tonic-gate 	struct type __node, *__left, *__right, *__tmp;			\
2477c478bd9Sstevel@tonic-gate \
2487c478bd9Sstevel@tonic-gate 	SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
2497c478bd9Sstevel@tonic-gate 	__left = __right = &__node;					\
2507c478bd9Sstevel@tonic-gate \
2517c478bd9Sstevel@tonic-gate 	while (1) {							\
2527c478bd9Sstevel@tonic-gate 		if (__comp < 0) {					\
2537c478bd9Sstevel@tonic-gate 			__tmp = SPLAY_LEFT((head)->sph_root, field);	\
2547c478bd9Sstevel@tonic-gate 			if (__tmp == NULL)				\
2557c478bd9Sstevel@tonic-gate 				break;					\
2567c478bd9Sstevel@tonic-gate 			if (__comp < 0){				\
2577c478bd9Sstevel@tonic-gate 				SPLAY_ROTATE_RIGHT(head, __tmp, field);	\
2587c478bd9Sstevel@tonic-gate 				if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
2597c478bd9Sstevel@tonic-gate 					break;				\
2607c478bd9Sstevel@tonic-gate 			}						\
2617c478bd9Sstevel@tonic-gate 			SPLAY_LINKLEFT(head, __right, field);		\
2627c478bd9Sstevel@tonic-gate 		} else if (__comp > 0) {				\
2637c478bd9Sstevel@tonic-gate 			__tmp = SPLAY_RIGHT((head)->sph_root, field);	\
2647c478bd9Sstevel@tonic-gate 			if (__tmp == NULL)				\
2657c478bd9Sstevel@tonic-gate 				break;					\
2667c478bd9Sstevel@tonic-gate 			if (__comp > 0) {				\
2677c478bd9Sstevel@tonic-gate 				SPLAY_ROTATE_LEFT(head, __tmp, field);	\
2687c478bd9Sstevel@tonic-gate 				if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
2697c478bd9Sstevel@tonic-gate 					break;				\
2707c478bd9Sstevel@tonic-gate 			}						\
2717c478bd9Sstevel@tonic-gate 			SPLAY_LINKRIGHT(head, __left, field);		\
2727c478bd9Sstevel@tonic-gate 		}							\
2737c478bd9Sstevel@tonic-gate 	}								\
2747c478bd9Sstevel@tonic-gate 	SPLAY_ASSEMBLE(head, &__node, __left, __right, field);		\
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate #define SPLAY_NEGINF	-1
2787c478bd9Sstevel@tonic-gate #define SPLAY_INF	1
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate #define SPLAY_INSERT(name, x, y)	name##_SPLAY_INSERT(x, y)
2817c478bd9Sstevel@tonic-gate #define SPLAY_REMOVE(name, x, y)	name##_SPLAY_REMOVE(x, y)
2827c478bd9Sstevel@tonic-gate #define SPLAY_FIND(name, x, y)		name##_SPLAY_FIND(x, y)
2837c478bd9Sstevel@tonic-gate #define SPLAY_NEXT(name, x, y)		name##_SPLAY_NEXT(x, y)
2847c478bd9Sstevel@tonic-gate #define SPLAY_MIN(name, x)		(SPLAY_EMPTY(x) ? NULL	\
2857c478bd9Sstevel@tonic-gate 					: name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
2867c478bd9Sstevel@tonic-gate #define SPLAY_MAX(name, x)		(SPLAY_EMPTY(x) ? NULL	\
2877c478bd9Sstevel@tonic-gate 					: name##_SPLAY_MIN_MAX(x, SPLAY_INF))
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate #define SPLAY_FOREACH(x, name, head)					\
2907c478bd9Sstevel@tonic-gate 	for ((x) = SPLAY_MIN(name, head);				\
2917c478bd9Sstevel@tonic-gate 	     (x) != NULL;						\
2927c478bd9Sstevel@tonic-gate 	     (x) = SPLAY_NEXT(name, head, x))
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate /* Macros that define a red-back tree */
2957c478bd9Sstevel@tonic-gate #define RB_HEAD(name, type)						\
2967c478bd9Sstevel@tonic-gate struct name {								\
2977c478bd9Sstevel@tonic-gate 	struct type *rbh_root; /* root of the tree */			\
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate #define RB_INITIALIZER(root)						\
3017c478bd9Sstevel@tonic-gate 	{ NULL }
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate #define RB_INIT(root) do {						\
3047c478bd9Sstevel@tonic-gate 	(root)->rbh_root = NULL;					\
3057c478bd9Sstevel@tonic-gate } while (0)
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate #define RB_BLACK	0
3087c478bd9Sstevel@tonic-gate #define RB_RED		1
3097c478bd9Sstevel@tonic-gate #define RB_ENTRY(type)							\
3107c478bd9Sstevel@tonic-gate struct {								\
3117c478bd9Sstevel@tonic-gate 	struct type *rbe_left;		/* left element */		\
3127c478bd9Sstevel@tonic-gate 	struct type *rbe_right;		/* right element */		\
3137c478bd9Sstevel@tonic-gate 	struct type *rbe_parent;	/* parent element */		\
3147c478bd9Sstevel@tonic-gate 	int rbe_color;			/* node color */		\
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate #define RB_LEFT(elm, field)		(elm)->field.rbe_left
3187c478bd9Sstevel@tonic-gate #define RB_RIGHT(elm, field)		(elm)->field.rbe_right
3197c478bd9Sstevel@tonic-gate #define RB_PARENT(elm, field)		(elm)->field.rbe_parent
3207c478bd9Sstevel@tonic-gate #define RB_COLOR(elm, field)		(elm)->field.rbe_color
3217c478bd9Sstevel@tonic-gate #define RB_ROOT(head)			(head)->rbh_root
3227c478bd9Sstevel@tonic-gate #define RB_EMPTY(head)			(RB_ROOT(head) == NULL)
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate #define RB_SET(elm, parent, field) do {					\
3257c478bd9Sstevel@tonic-gate 	RB_PARENT(elm, field) = parent;					\
3267c478bd9Sstevel@tonic-gate 	RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL;		\
3277c478bd9Sstevel@tonic-gate 	RB_COLOR(elm, field) = RB_RED;					\
3287c478bd9Sstevel@tonic-gate } while (0)
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate #define RB_SET_BLACKRED(black, red, field) do {				\
3317c478bd9Sstevel@tonic-gate 	RB_COLOR(black, field) = RB_BLACK;				\
3327c478bd9Sstevel@tonic-gate 	RB_COLOR(red, field) = RB_RED;					\
3337c478bd9Sstevel@tonic-gate } while (0)
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate #ifndef RB_AUGMENT
3367c478bd9Sstevel@tonic-gate #define RB_AUGMENT(x)
3377c478bd9Sstevel@tonic-gate #endif
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate #define RB_ROTATE_LEFT(head, elm, tmp, field) do {			\
3407c478bd9Sstevel@tonic-gate 	(tmp) = RB_RIGHT(elm, field);					\
3417c478bd9Sstevel@tonic-gate 	if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field))) {		\
3427c478bd9Sstevel@tonic-gate 		RB_PARENT(RB_LEFT(tmp, field), field) = (elm);		\
3437c478bd9Sstevel@tonic-gate 	}								\
3447c478bd9Sstevel@tonic-gate 	RB_AUGMENT(elm);						\
3457c478bd9Sstevel@tonic-gate 	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {		\
3467c478bd9Sstevel@tonic-gate 		if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))	\
3477c478bd9Sstevel@tonic-gate 			RB_LEFT(RB_PARENT(elm, field), field) = (tmp);	\
3487c478bd9Sstevel@tonic-gate 		else							\
3497c478bd9Sstevel@tonic-gate 			RB_RIGHT(RB_PARENT(elm, field), field) = (tmp);	\
3507c478bd9Sstevel@tonic-gate 		RB_AUGMENT(RB_PARENT(elm, field));			\
3517c478bd9Sstevel@tonic-gate 	} else								\
3527c478bd9Sstevel@tonic-gate 		(head)->rbh_root = (tmp);				\
3537c478bd9Sstevel@tonic-gate 	RB_LEFT(tmp, field) = (elm);					\
3547c478bd9Sstevel@tonic-gate 	RB_PARENT(elm, field) = (tmp);					\
3557c478bd9Sstevel@tonic-gate 	RB_AUGMENT(tmp);						\
3567c478bd9Sstevel@tonic-gate } while (0)
3577c478bd9Sstevel@tonic-gate 
3587c478bd9Sstevel@tonic-gate #define RB_ROTATE_RIGHT(head, elm, tmp, field) do {			\
3597c478bd9Sstevel@tonic-gate 	(tmp) = RB_LEFT(elm, field);					\
3607c478bd9Sstevel@tonic-gate 	if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field))) {		\
3617c478bd9Sstevel@tonic-gate 		RB_PARENT(RB_RIGHT(tmp, field), field) = (elm);		\
3627c478bd9Sstevel@tonic-gate 	}								\
3637c478bd9Sstevel@tonic-gate 	RB_AUGMENT(elm);						\
3647c478bd9Sstevel@tonic-gate 	if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field))) {		\
3657c478bd9Sstevel@tonic-gate 		if ((elm) == RB_LEFT(RB_PARENT(elm, field), field))	\
3667c478bd9Sstevel@tonic-gate 			RB_LEFT(RB_PARENT(elm, field), field) = (tmp);	\
3677c478bd9Sstevel@tonic-gate 		else							\
3687c478bd9Sstevel@tonic-gate 			RB_RIGHT(RB_PARENT(elm, field), field) = (tmp);	\
3697c478bd9Sstevel@tonic-gate 		RB_AUGMENT(RB_PARENT(elm, field));			\
3707c478bd9Sstevel@tonic-gate 	} else								\
3717c478bd9Sstevel@tonic-gate 		(head)->rbh_root = (tmp);				\
3727c478bd9Sstevel@tonic-gate 	RB_RIGHT(tmp, field) = (elm);					\
3737c478bd9Sstevel@tonic-gate 	RB_PARENT(elm, field) = (tmp);					\
3747c478bd9Sstevel@tonic-gate 	RB_AUGMENT(tmp);						\
3757c478bd9Sstevel@tonic-gate } while (0)
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate /* Generates prototypes and inline functions */
3787c478bd9Sstevel@tonic-gate #define RB_PROTOTYPE(name, type, field, cmp)				\
3797c478bd9Sstevel@tonic-gate void name##_RB_INSERT_COLOR(struct name *, struct type *);	\
3807c478bd9Sstevel@tonic-gate void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
3817c478bd9Sstevel@tonic-gate struct type *name##_RB_REMOVE(struct name *, struct type *);		\
3827c478bd9Sstevel@tonic-gate struct type *name##_RB_INSERT(struct name *, struct type *);		\
3837c478bd9Sstevel@tonic-gate struct type *name##_RB_FIND(struct name *, struct type *);		\
3847c478bd9Sstevel@tonic-gate struct type *name##_RB_NEXT(struct name *, struct type *);		\
385*b9aa66a7SJan Pechanec struct type *name##_RB_MINMAX(struct name *, int);
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /* Main rb operation.
3887c478bd9Sstevel@tonic-gate  * Moves node close to the key of elm to top
3897c478bd9Sstevel@tonic-gate  */
3907c478bd9Sstevel@tonic-gate #define RB_GENERATE(name, type, field, cmp)				\
3917c478bd9Sstevel@tonic-gate void									\
3927c478bd9Sstevel@tonic-gate name##_RB_INSERT_COLOR(struct name *head, struct type *elm)		\
3937c478bd9Sstevel@tonic-gate {									\
3947c478bd9Sstevel@tonic-gate 	struct type *parent, *gparent, *tmp;				\
3957c478bd9Sstevel@tonic-gate 	while ((parent = RB_PARENT(elm, field)) &&			\
3967c478bd9Sstevel@tonic-gate 	    RB_COLOR(parent, field) == RB_RED) {			\
3977c478bd9Sstevel@tonic-gate 		gparent = RB_PARENT(parent, field);			\
3987c478bd9Sstevel@tonic-gate 		if (parent == RB_LEFT(gparent, field)) {		\
3997c478bd9Sstevel@tonic-gate 			tmp = RB_RIGHT(gparent, field);			\
4007c478bd9Sstevel@tonic-gate 			if (tmp && RB_COLOR(tmp, field) == RB_RED) {	\
4017c478bd9Sstevel@tonic-gate 				RB_COLOR(tmp, field) = RB_BLACK;	\
4027c478bd9Sstevel@tonic-gate 				RB_SET_BLACKRED(parent, gparent, field);\
4037c478bd9Sstevel@tonic-gate 				elm = gparent;				\
4047c478bd9Sstevel@tonic-gate 				continue;				\
4057c478bd9Sstevel@tonic-gate 			}						\
4067c478bd9Sstevel@tonic-gate 			if (RB_RIGHT(parent, field) == elm) {		\
4077c478bd9Sstevel@tonic-gate 				RB_ROTATE_LEFT(head, parent, tmp, field);\
4087c478bd9Sstevel@tonic-gate 				tmp = parent;				\
4097c478bd9Sstevel@tonic-gate 				parent = elm;				\
4107c478bd9Sstevel@tonic-gate 				elm = tmp;				\
4117c478bd9Sstevel@tonic-gate 			}						\
4127c478bd9Sstevel@tonic-gate 			RB_SET_BLACKRED(parent, gparent, field);	\
4137c478bd9Sstevel@tonic-gate 			RB_ROTATE_RIGHT(head, gparent, tmp, field);	\
4147c478bd9Sstevel@tonic-gate 		} else {						\
4157c478bd9Sstevel@tonic-gate 			tmp = RB_LEFT(gparent, field);			\
4167c478bd9Sstevel@tonic-gate 			if (tmp && RB_COLOR(tmp, field) == RB_RED) {	\
4177c478bd9Sstevel@tonic-gate 				RB_COLOR(tmp, field) = RB_BLACK;	\
4187c478bd9Sstevel@tonic-gate 				RB_SET_BLACKRED(parent, gparent, field);\
4197c478bd9Sstevel@tonic-gate 				elm = gparent;				\
4207c478bd9Sstevel@tonic-gate 				continue;				\
4217c478bd9Sstevel@tonic-gate 			}						\
4227c478bd9Sstevel@tonic-gate 			if (RB_LEFT(parent, field) == elm) {		\
4237c478bd9Sstevel@tonic-gate 				RB_ROTATE_RIGHT(head, parent, tmp, field);\
4247c478bd9Sstevel@tonic-gate 				tmp = parent;				\
4257c478bd9Sstevel@tonic-gate 				parent = elm;				\
4267c478bd9Sstevel@tonic-gate 				elm = tmp;				\
4277c478bd9Sstevel@tonic-gate 			}						\
4287c478bd9Sstevel@tonic-gate 			RB_SET_BLACKRED(parent, gparent, field);	\
4297c478bd9Sstevel@tonic-gate 			RB_ROTATE_LEFT(head, gparent, tmp, field);	\
4307c478bd9Sstevel@tonic-gate 		}							\
4317c478bd9Sstevel@tonic-gate 	}								\
4327c478bd9Sstevel@tonic-gate 	RB_COLOR(head->rbh_root, field) = RB_BLACK;			\
4337c478bd9Sstevel@tonic-gate }									\
4347c478bd9Sstevel@tonic-gate 									\
4357c478bd9Sstevel@tonic-gate void									\
4367c478bd9Sstevel@tonic-gate name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
4377c478bd9Sstevel@tonic-gate {									\
4387c478bd9Sstevel@tonic-gate 	struct type *tmp;						\
4397c478bd9Sstevel@tonic-gate 	while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) &&	\
4407c478bd9Sstevel@tonic-gate 	    elm != RB_ROOT(head)) {					\
4417c478bd9Sstevel@tonic-gate 		if (RB_LEFT(parent, field) == elm) {			\
4427c478bd9Sstevel@tonic-gate 			tmp = RB_RIGHT(parent, field);			\
4437c478bd9Sstevel@tonic-gate 			if (RB_COLOR(tmp, field) == RB_RED) {		\
4447c478bd9Sstevel@tonic-gate 				RB_SET_BLACKRED(tmp, parent, field);	\
4457c478bd9Sstevel@tonic-gate 				RB_ROTATE_LEFT(head, parent, tmp, field);\
4467c478bd9Sstevel@tonic-gate 				tmp = RB_RIGHT(parent, field);		\
4477c478bd9Sstevel@tonic-gate 			}						\
4487c478bd9Sstevel@tonic-gate 			if ((RB_LEFT(tmp, field) == NULL ||		\
4497c478bd9Sstevel@tonic-gate 			    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
4507c478bd9Sstevel@tonic-gate 			    (RB_RIGHT(tmp, field) == NULL ||		\
4517c478bd9Sstevel@tonic-gate 			    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
4527c478bd9Sstevel@tonic-gate 				RB_COLOR(tmp, field) = RB_RED;		\
4537c478bd9Sstevel@tonic-gate 				elm = parent;				\
4547c478bd9Sstevel@tonic-gate 				parent = RB_PARENT(elm, field);		\
4557c478bd9Sstevel@tonic-gate 			} else {					\
4567c478bd9Sstevel@tonic-gate 				if (RB_RIGHT(tmp, field) == NULL ||	\
4577c478bd9Sstevel@tonic-gate 				    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
4587c478bd9Sstevel@tonic-gate 					struct type *oleft;		\
4597c478bd9Sstevel@tonic-gate 					if ((oleft = RB_LEFT(tmp, field)))\
4607c478bd9Sstevel@tonic-gate 						RB_COLOR(oleft, field) = RB_BLACK;\
4617c478bd9Sstevel@tonic-gate 					RB_COLOR(tmp, field) = RB_RED;	\
4627c478bd9Sstevel@tonic-gate 					RB_ROTATE_RIGHT(head, tmp, oleft, field);\
4637c478bd9Sstevel@tonic-gate 					tmp = RB_RIGHT(parent, field);	\
4647c478bd9Sstevel@tonic-gate 				}					\
4657c478bd9Sstevel@tonic-gate 				RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
4667c478bd9Sstevel@tonic-gate 				RB_COLOR(parent, field) = RB_BLACK;	\
4677c478bd9Sstevel@tonic-gate 				if (RB_RIGHT(tmp, field))		\
4687c478bd9Sstevel@tonic-gate 					RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
4697c478bd9Sstevel@tonic-gate 				RB_ROTATE_LEFT(head, parent, tmp, field);\
4707c478bd9Sstevel@tonic-gate 				elm = RB_ROOT(head);			\
4717c478bd9Sstevel@tonic-gate 				break;					\
4727c478bd9Sstevel@tonic-gate 			}						\
4737c478bd9Sstevel@tonic-gate 		} else {						\
4747c478bd9Sstevel@tonic-gate 			tmp = RB_LEFT(parent, field);			\
4757c478bd9Sstevel@tonic-gate 			if (RB_COLOR(tmp, field) == RB_RED) {		\
4767c478bd9Sstevel@tonic-gate 				RB_SET_BLACKRED(tmp, parent, field);	\
4777c478bd9Sstevel@tonic-gate 				RB_ROTATE_RIGHT(head, parent, tmp, field);\
4787c478bd9Sstevel@tonic-gate 				tmp = RB_LEFT(parent, field);		\
4797c478bd9Sstevel@tonic-gate 			}						\
4807c478bd9Sstevel@tonic-gate 			if ((RB_LEFT(tmp, field) == NULL ||		\
4817c478bd9Sstevel@tonic-gate 			    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
4827c478bd9Sstevel@tonic-gate 			    (RB_RIGHT(tmp, field) == NULL ||		\
4837c478bd9Sstevel@tonic-gate 			    RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
4847c478bd9Sstevel@tonic-gate 				RB_COLOR(tmp, field) = RB_RED;		\
4857c478bd9Sstevel@tonic-gate 				elm = parent;				\
4867c478bd9Sstevel@tonic-gate 				parent = RB_PARENT(elm, field);		\
4877c478bd9Sstevel@tonic-gate 			} else {					\
4887c478bd9Sstevel@tonic-gate 				if (RB_LEFT(tmp, field) == NULL ||	\
4897c478bd9Sstevel@tonic-gate 				    RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
4907c478bd9Sstevel@tonic-gate 					struct type *oright;		\
4917c478bd9Sstevel@tonic-gate 					if ((oright = RB_RIGHT(tmp, field)))\
4927c478bd9Sstevel@tonic-gate 						RB_COLOR(oright, field) = RB_BLACK;\
4937c478bd9Sstevel@tonic-gate 					RB_COLOR(tmp, field) = RB_RED;	\
4947c478bd9Sstevel@tonic-gate 					RB_ROTATE_LEFT(head, tmp, oright, field);\
4957c478bd9Sstevel@tonic-gate 					tmp = RB_LEFT(parent, field);	\
4967c478bd9Sstevel@tonic-gate 				}					\
4977c478bd9Sstevel@tonic-gate 				RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
4987c478bd9Sstevel@tonic-gate 				RB_COLOR(parent, field) = RB_BLACK;	\
4997c478bd9Sstevel@tonic-gate 				if (RB_LEFT(tmp, field))		\
5007c478bd9Sstevel@tonic-gate 					RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
5017c478bd9Sstevel@tonic-gate 				RB_ROTATE_RIGHT(head, parent, tmp, field);\
5027c478bd9Sstevel@tonic-gate 				elm = RB_ROOT(head);			\
5037c478bd9Sstevel@tonic-gate 				break;					\
5047c478bd9Sstevel@tonic-gate 			}						\
5057c478bd9Sstevel@tonic-gate 		}							\
5067c478bd9Sstevel@tonic-gate 	}								\
5077c478bd9Sstevel@tonic-gate 	if (elm)							\
5087c478bd9Sstevel@tonic-gate 		RB_COLOR(elm, field) = RB_BLACK;			\
5097c478bd9Sstevel@tonic-gate }									\
5107c478bd9Sstevel@tonic-gate 									\
5117c478bd9Sstevel@tonic-gate struct type *								\
5127c478bd9Sstevel@tonic-gate name##_RB_REMOVE(struct name *head, struct type *elm)			\
5137c478bd9Sstevel@tonic-gate {									\
5147c478bd9Sstevel@tonic-gate 	struct type *child, *parent, *old = elm;			\
5157c478bd9Sstevel@tonic-gate 	int color;							\
5167c478bd9Sstevel@tonic-gate 	if (RB_LEFT(elm, field) == NULL)				\
5177c478bd9Sstevel@tonic-gate 		child = RB_RIGHT(elm, field);				\
5187c478bd9Sstevel@tonic-gate 	else if (RB_RIGHT(elm, field) == NULL)				\
5197c478bd9Sstevel@tonic-gate 		child = RB_LEFT(elm, field);				\
5207c478bd9Sstevel@tonic-gate 	else {								\
5217c478bd9Sstevel@tonic-gate 		struct type *left;					\
5227c478bd9Sstevel@tonic-gate 		elm = RB_RIGHT(elm, field);				\
5237c478bd9Sstevel@tonic-gate 		while ((left = RB_LEFT(elm, field)))			\
5247c478bd9Sstevel@tonic-gate 			elm = left;					\
5257c478bd9Sstevel@tonic-gate 		child = RB_RIGHT(elm, field);				\
5267c478bd9Sstevel@tonic-gate 		parent = RB_PARENT(elm, field);				\
5277c478bd9Sstevel@tonic-gate 		color = RB_COLOR(elm, field);				\
5287c478bd9Sstevel@tonic-gate 		if (child)						\
5297c478bd9Sstevel@tonic-gate 			RB_PARENT(child, field) = parent;		\
5307c478bd9Sstevel@tonic-gate 		if (parent) {						\
5317c478bd9Sstevel@tonic-gate 			if (RB_LEFT(parent, field) == elm)		\
5327c478bd9Sstevel@tonic-gate 				RB_LEFT(parent, field) = child;		\
5337c478bd9Sstevel@tonic-gate 			else						\
5347c478bd9Sstevel@tonic-gate 				RB_RIGHT(parent, field) = child;	\
5357c478bd9Sstevel@tonic-gate 			RB_AUGMENT(parent);				\
5367c478bd9Sstevel@tonic-gate 		} else							\
5377c478bd9Sstevel@tonic-gate 			RB_ROOT(head) = child;				\
5387c478bd9Sstevel@tonic-gate 		if (RB_PARENT(elm, field) == old)			\
5397c478bd9Sstevel@tonic-gate 			parent = elm;					\
5407c478bd9Sstevel@tonic-gate 		(elm)->field = (old)->field;				\
5417c478bd9Sstevel@tonic-gate 		if (RB_PARENT(old, field)) {				\
5427c478bd9Sstevel@tonic-gate 			if (RB_LEFT(RB_PARENT(old, field), field) == old)\
5437c478bd9Sstevel@tonic-gate 				RB_LEFT(RB_PARENT(old, field), field) = elm;\
5447c478bd9Sstevel@tonic-gate 			else						\
5457c478bd9Sstevel@tonic-gate 				RB_RIGHT(RB_PARENT(old, field), field) = elm;\
5467c478bd9Sstevel@tonic-gate 			RB_AUGMENT(RB_PARENT(old, field));		\
5477c478bd9Sstevel@tonic-gate 		} else							\
5487c478bd9Sstevel@tonic-gate 			RB_ROOT(head) = elm;				\
5497c478bd9Sstevel@tonic-gate 		RB_PARENT(RB_LEFT(old, field), field) = elm;		\
5507c478bd9Sstevel@tonic-gate 		if (RB_RIGHT(old, field))				\
5517c478bd9Sstevel@tonic-gate 			RB_PARENT(RB_RIGHT(old, field), field) = elm;	\
5527c478bd9Sstevel@tonic-gate 		if (parent) {						\
5537c478bd9Sstevel@tonic-gate 			left = parent;					\
5547c478bd9Sstevel@tonic-gate 			do {						\
5557c478bd9Sstevel@tonic-gate 				RB_AUGMENT(left);			\
5567c478bd9Sstevel@tonic-gate 			} while ((left = RB_PARENT(left, field)));	\
5577c478bd9Sstevel@tonic-gate 		}							\
5587c478bd9Sstevel@tonic-gate 		goto color;						\
5597c478bd9Sstevel@tonic-gate 	}								\
5607c478bd9Sstevel@tonic-gate 	parent = RB_PARENT(elm, field);					\
5617c478bd9Sstevel@tonic-gate 	color = RB_COLOR(elm, field);					\
5627c478bd9Sstevel@tonic-gate 	if (child)							\
5637c478bd9Sstevel@tonic-gate 		RB_PARENT(child, field) = parent;			\
5647c478bd9Sstevel@tonic-gate 	if (parent) {							\
5657c478bd9Sstevel@tonic-gate 		if (RB_LEFT(parent, field) == elm)			\
5667c478bd9Sstevel@tonic-gate 			RB_LEFT(parent, field) = child;			\
5677c478bd9Sstevel@tonic-gate 		else							\
5687c478bd9Sstevel@tonic-gate 			RB_RIGHT(parent, field) = child;		\
5697c478bd9Sstevel@tonic-gate 		RB_AUGMENT(parent);					\
5707c478bd9Sstevel@tonic-gate 	} else								\
5717c478bd9Sstevel@tonic-gate 		RB_ROOT(head) = child;					\
5727c478bd9Sstevel@tonic-gate color:									\
5737c478bd9Sstevel@tonic-gate 	if (color == RB_BLACK)						\
5747c478bd9Sstevel@tonic-gate 		name##_RB_REMOVE_COLOR(head, parent, child);		\
5757c478bd9Sstevel@tonic-gate 	return (old);							\
5767c478bd9Sstevel@tonic-gate }									\
5777c478bd9Sstevel@tonic-gate 									\
5787c478bd9Sstevel@tonic-gate /* Inserts a node into the RB tree */					\
5797c478bd9Sstevel@tonic-gate struct type *								\
5807c478bd9Sstevel@tonic-gate name##_RB_INSERT(struct name *head, struct type *elm)			\
5817c478bd9Sstevel@tonic-gate {									\
5827c478bd9Sstevel@tonic-gate 	struct type *tmp;						\
5837c478bd9Sstevel@tonic-gate 	struct type *parent = NULL;					\
5847c478bd9Sstevel@tonic-gate 	int comp = 0;							\
5857c478bd9Sstevel@tonic-gate 	tmp = RB_ROOT(head);						\
5867c478bd9Sstevel@tonic-gate 	while (tmp) {							\
5877c478bd9Sstevel@tonic-gate 		parent = tmp;						\
5887c478bd9Sstevel@tonic-gate 		comp = (cmp)(elm, parent);				\
5897c478bd9Sstevel@tonic-gate 		if (comp < 0)						\
5907c478bd9Sstevel@tonic-gate 			tmp = RB_LEFT(tmp, field);			\
5917c478bd9Sstevel@tonic-gate 		else if (comp > 0)					\
5927c478bd9Sstevel@tonic-gate 			tmp = RB_RIGHT(tmp, field);			\
5937c478bd9Sstevel@tonic-gate 		else							\
5947c478bd9Sstevel@tonic-gate 			return (tmp);					\
5957c478bd9Sstevel@tonic-gate 	}								\
5967c478bd9Sstevel@tonic-gate 	RB_SET(elm, parent, field);					\
5977c478bd9Sstevel@tonic-gate 	if (parent != NULL) {						\
5987c478bd9Sstevel@tonic-gate 		if (comp < 0)						\
5997c478bd9Sstevel@tonic-gate 			RB_LEFT(parent, field) = elm;			\
6007c478bd9Sstevel@tonic-gate 		else							\
6017c478bd9Sstevel@tonic-gate 			RB_RIGHT(parent, field) = elm;			\
6027c478bd9Sstevel@tonic-gate 		RB_AUGMENT(parent);					\
6037c478bd9Sstevel@tonic-gate 	} else								\
6047c478bd9Sstevel@tonic-gate 		RB_ROOT(head) = elm;					\
6057c478bd9Sstevel@tonic-gate 	name##_RB_INSERT_COLOR(head, elm);				\
6067c478bd9Sstevel@tonic-gate 	return (NULL);							\
6077c478bd9Sstevel@tonic-gate }									\
6087c478bd9Sstevel@tonic-gate 									\
6097c478bd9Sstevel@tonic-gate /* Finds the node with the same key as elm */				\
6107c478bd9Sstevel@tonic-gate struct type *								\
6117c478bd9Sstevel@tonic-gate name##_RB_FIND(struct name *head, struct type *elm)			\
6127c478bd9Sstevel@tonic-gate {									\
6137c478bd9Sstevel@tonic-gate 	struct type *tmp = RB_ROOT(head);				\
6147c478bd9Sstevel@tonic-gate 	int comp;							\
6157c478bd9Sstevel@tonic-gate 	while (tmp) {							\
6167c478bd9Sstevel@tonic-gate 		comp = cmp(elm, tmp);					\
6177c478bd9Sstevel@tonic-gate 		if (comp < 0)						\
6187c478bd9Sstevel@tonic-gate 			tmp = RB_LEFT(tmp, field);			\
6197c478bd9Sstevel@tonic-gate 		else if (comp > 0)					\
6207c478bd9Sstevel@tonic-gate 			tmp = RB_RIGHT(tmp, field);			\
6217c478bd9Sstevel@tonic-gate 		else							\
6227c478bd9Sstevel@tonic-gate 			return (tmp);					\
6237c478bd9Sstevel@tonic-gate 	}								\
6247c478bd9Sstevel@tonic-gate 	return (NULL);							\
6257c478bd9Sstevel@tonic-gate }									\
6267c478bd9Sstevel@tonic-gate 									\
6277c478bd9Sstevel@tonic-gate struct type *								\
6287c478bd9Sstevel@tonic-gate name##_RB_NEXT(struct name *head, struct type *elm)			\
6297c478bd9Sstevel@tonic-gate {									\
6307c478bd9Sstevel@tonic-gate 	if (RB_RIGHT(elm, field)) {					\
6317c478bd9Sstevel@tonic-gate 		elm = RB_RIGHT(elm, field);				\
6327c478bd9Sstevel@tonic-gate 		while (RB_LEFT(elm, field))				\
6337c478bd9Sstevel@tonic-gate 			elm = RB_LEFT(elm, field);			\
6347c478bd9Sstevel@tonic-gate 	} else {							\
6357c478bd9Sstevel@tonic-gate 		if (RB_PARENT(elm, field) &&				\
6367c478bd9Sstevel@tonic-gate 		    (elm == RB_LEFT(RB_PARENT(elm, field), field)))	\
6377c478bd9Sstevel@tonic-gate 			elm = RB_PARENT(elm, field);			\
6387c478bd9Sstevel@tonic-gate 		else {							\
6397c478bd9Sstevel@tonic-gate 			while (RB_PARENT(elm, field) &&			\
6407c478bd9Sstevel@tonic-gate 			    (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
6417c478bd9Sstevel@tonic-gate 				elm = RB_PARENT(elm, field);		\
6427c478bd9Sstevel@tonic-gate 			elm = RB_PARENT(elm, field);			\
6437c478bd9Sstevel@tonic-gate 		}							\
6447c478bd9Sstevel@tonic-gate 	}								\
6457c478bd9Sstevel@tonic-gate 	return (elm);							\
6467c478bd9Sstevel@tonic-gate }									\
6477c478bd9Sstevel@tonic-gate 									\
6487c478bd9Sstevel@tonic-gate struct type *								\
6497c478bd9Sstevel@tonic-gate name##_RB_MINMAX(struct name *head, int val)				\
6507c478bd9Sstevel@tonic-gate {									\
6517c478bd9Sstevel@tonic-gate 	struct type *tmp = RB_ROOT(head);				\
6527c478bd9Sstevel@tonic-gate 	struct type *parent = NULL;					\
6537c478bd9Sstevel@tonic-gate 	while (tmp) {							\
6547c478bd9Sstevel@tonic-gate 		parent = tmp;						\
6557c478bd9Sstevel@tonic-gate 		if (val < 0)						\
6567c478bd9Sstevel@tonic-gate 			tmp = RB_LEFT(tmp, field);			\
6577c478bd9Sstevel@tonic-gate 		else							\
6587c478bd9Sstevel@tonic-gate 			tmp = RB_RIGHT(tmp, field);			\
6597c478bd9Sstevel@tonic-gate 	}								\
6607c478bd9Sstevel@tonic-gate 	return (parent);						\
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate #define RB_NEGINF	-1
6647c478bd9Sstevel@tonic-gate #define RB_INF	1
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate #define RB_INSERT(name, x, y)	name##_RB_INSERT(x, y)
6677c478bd9Sstevel@tonic-gate #define RB_REMOVE(name, x, y)	name##_RB_REMOVE(x, y)
6687c478bd9Sstevel@tonic-gate #define RB_FIND(name, x, y)	name##_RB_FIND(x, y)
6697c478bd9Sstevel@tonic-gate #define RB_NEXT(name, x, y)	name##_RB_NEXT(x, y)
6707c478bd9Sstevel@tonic-gate #define RB_MIN(name, x)		name##_RB_MINMAX(x, RB_NEGINF)
6717c478bd9Sstevel@tonic-gate #define RB_MAX(name, x)		name##_RB_MINMAX(x, RB_INF)
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate #define RB_FOREACH(x, name, head)					\
6747c478bd9Sstevel@tonic-gate 	for ((x) = RB_MIN(name, head);					\
6757c478bd9Sstevel@tonic-gate 	     (x) != NULL;						\
6767c478bd9Sstevel@tonic-gate 	     (x) = name##_RB_NEXT(head, x))
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate #ifdef __cplusplus
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate #endif
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate #endif /* _SYS_TREE_H */
683