xref: /onnv-gate/usr/src/lib/libast/common/comp/tsearch.c (revision 4887:feebf9260c2e)
1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1985-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
18*4887Schin *                  David Korn <dgk@research.att.com>                   *
19*4887Schin *                   Phong Vo <kpv@research.att.com>                    *
20*4887Schin *                                                                      *
21*4887Schin ***********************************************************************/
22*4887Schin /*
23*4887Schin  * tsearch() for systems that have <search.h> but no tsearch()
24*4887Schin  * why would such a system provide the interface but not the
25*4887Schin  * implementation? that's what happens when one slimes their
26*4887Schin  * way through standards compliance
27*4887Schin  *
28*4887Schin  * NOTE: please excuse the crude feature test
29*4887Schin  */
30*4887Schin 
31*4887Schin #if !_UWIN
32*4887Schin 
33*4887Schin void _STUB_tsearch(){}
34*4887Schin 
35*4887Schin #else
36*4887Schin 
37*4887Schin #if _PACKAGE_ast
38*4887Schin #include	<ast.h>
39*4887Schin #endif
40*4887Schin 
41*4887Schin #define tdelete		______tdelete
42*4887Schin #define tfind		______tfind
43*4887Schin #define tsearch		______tsearch
44*4887Schin #define twalk		______twalk
45*4887Schin 
46*4887Schin #include	<search.h>
47*4887Schin 
48*4887Schin #undef	tdelete
49*4887Schin #undef	tfind
50*4887Schin #undef	tsearch
51*4887Schin #undef	twalk
52*4887Schin 
53*4887Schin #include	"dthdr.h"
54*4887Schin 
55*4887Schin /*	POSIX tsearch library based on libcdt
56*4887Schin **	Written by Kiem-Phong Vo (AT&T Research, 07/19/95)
57*4887Schin */
58*4887Schin 
59*4887Schin typedef struct _tree_s
60*4887Schin {	Dtlink_t	link;
61*4887Schin 	Void_t*		key;
62*4887Schin } Tree_t;
63*4887Schin 
64*4887Schin typedef struct _treedisc_s
65*4887Schin {	Dtdisc_t	disc;
66*4887Schin 	int(*		comparf)_ARG_((const Void_t*, const Void_t*));
67*4887Schin } Treedisc_t;
68*4887Schin 
69*4887Schin #if defined(__EXPORT__)
70*4887Schin #define extern	__EXPORT__
71*4887Schin #endif
72*4887Schin 
73*4887Schin /* compare function */
74*4887Schin #if __STD_C
75*4887Schin static int treecompare(Dt_t* dt, char* one, char* two, Dtdisc_t* disc)
76*4887Schin #else
77*4887Schin static int treecompare(dt, one, two, disc)
78*4887Schin Dt_t*		dt;
79*4887Schin char*		one;
80*4887Schin char*		two;
81*4887Schin Dtdisc_t*	disc;
82*4887Schin #endif
83*4887Schin {
84*4887Schin 	return (*((Treedisc_t*)disc)->comparf)((Void_t*)one,(Void_t*)two);
85*4887Schin }
86*4887Schin 
87*4887Schin static Treedisc_t	Treedisc =
88*4887Schin {	{ sizeof(Dtlink_t), -1,	/* object is key		*/
89*4887Schin 	  0,
90*4887Schin 	  NIL(Dtmake_f), NIL(Dtfree_f),
91*4887Schin 	  treecompare,
92*4887Schin 	  NIL(Dthash_f),
93*4887Schin 	  NIL(Dtmemory_f),
94*4887Schin 	  NIL(Dtevent_f)
95*4887Schin 	},
96*4887Schin 	0
97*4887Schin };
98*4887Schin 
99*4887Schin extern
100*4887Schin #if __STD_C
101*4887Schin Void_t* tsearch(const Void_t* key, Void_t** rootp,
102*4887Schin 		int(*comparf)(const Void_t*,const Void_t*) )
103*4887Schin #else
104*4887Schin Void_t* tsearch(key, rootp, comparf)
105*4887Schin Void_t*		key;
106*4887Schin Void_t**	rootp;
107*4887Schin int(*		comparf)();
108*4887Schin #endif
109*4887Schin {
110*4887Schin 	reg Dt_t*	dt;
111*4887Schin 	reg Tree_t*	o;
112*4887Schin 
113*4887Schin 	if(!rootp ||
114*4887Schin 	   (!(dt = *((Dt_t**)rootp)) && !(dt = dtopen((Dtdisc_t*)(&Treedisc),Dtorder))) )
115*4887Schin 		return NIL(Void_t*);
116*4887Schin 
117*4887Schin 	/* dangerous to set comparf on each call but that's tsearch */
118*4887Schin 	Treedisc.comparf = comparf;
119*4887Schin 
120*4887Schin 	if(!(o = (Tree_t*)dtmatch(dt,key)) )
121*4887Schin 	{	if(!(o = (Tree_t*)malloc(sizeof(Tree_t))) )
122*4887Schin 			return NIL(Void_t*);
123*4887Schin 		o->key = (Void_t*)key;
124*4887Schin 		dtinsert(dt,o);
125*4887Schin 	}
126*4887Schin 
127*4887Schin 	if(o)
128*4887Schin 		*rootp = (Void_t*)dt;
129*4887Schin 	else if(*rootp == NIL(Void_t*) )
130*4887Schin 		dtclose(dt);
131*4887Schin 
132*4887Schin 	return (Void_t*)(&o->key);
133*4887Schin }
134*4887Schin 
135*4887Schin extern
136*4887Schin #if __STD_C
137*4887Schin Void_t* tfind(const Void_t* key, Void_t*const* rootp,
138*4887Schin 		int(*comparf)(const Void_t*, const Void_t*) )
139*4887Schin #else
140*4887Schin Void_t* tfind(key, rootp, comparf)
141*4887Schin Void_t*		key;
142*4887Schin Void_t**	rootp;
143*4887Schin int(*		comparf)();
144*4887Schin #endif
145*4887Schin {
146*4887Schin 	reg Dt_t*	dt;
147*4887Schin 	reg Tree_t*	o;
148*4887Schin 
149*4887Schin 	if(!rootp || !(dt = *((Dt_t**)rootp)) )
150*4887Schin 		return NIL(Void_t*);
151*4887Schin 	Treedisc.comparf = comparf;
152*4887Schin 
153*4887Schin 	return (o = (Tree_t*)dtmatch(dt,key)) ? (Void_t*)(&o->key) : NIL(Void_t*);
154*4887Schin }
155*4887Schin 
156*4887Schin /* the original tdelete() specifies that it will return the parent pointer
157*4887Schin ** in the tree if there is one. Since we are using a splay tree, a deleted
158*4887Schin ** node is always rotated to the root first. So this implementation always
159*4887Schin ** returns the key of the new root.
160*4887Schin */
161*4887Schin extern
162*4887Schin #if __STD_C
163*4887Schin Void_t* tdelete(const Void_t* key, Void_t** rootp,
164*4887Schin 		int(*comparf)(const Void_t*, const Void_t*) )
165*4887Schin #else
166*4887Schin Void_t* tdelete(key, rootp, comparf)
167*4887Schin Void_t*		key;
168*4887Schin Void_t**	rootp;
169*4887Schin int(*		comparf)();
170*4887Schin #endif
171*4887Schin {
172*4887Schin 	reg Dt_t*	dt;
173*4887Schin 	reg Tree_t*	o;
174*4887Schin 	Tree_t		obj;
175*4887Schin 
176*4887Schin 	if(!rootp || !(dt = *((Dt_t**)rootp)) )
177*4887Schin 		return NIL(Void_t*);
178*4887Schin 
179*4887Schin 	Treedisc.comparf = comparf;
180*4887Schin 
181*4887Schin 	obj.key = (Void_t*)key;
182*4887Schin 	dtdelete(dt,&obj);
183*4887Schin 
184*4887Schin 	if(!(o = dtfinger(dt)) )
185*4887Schin 	{	dtclose(dt);
186*4887Schin 		*rootp = NIL(Void_t*);
187*4887Schin 	}
188*4887Schin 
189*4887Schin 	return o ? (Void_t*)(&o->key) : NIL(Void_t*);
190*4887Schin }
191*4887Schin 
192*4887Schin /* the below routine assumes a particular layout of Dtlink_t.
193*4887Schin ** If this ever gets changed, this routine should be redone.
194*4887Schin */
195*4887Schin #define lchild	link.hl._left
196*4887Schin #define rchild	link.right
197*4887Schin 
198*4887Schin #if __STD_C
199*4887Schin static void _twalk(Tree_t* obj, void(*action)(const Void_t*,VISIT,int), int level)
200*4887Schin #else
201*4887Schin static void _twalk(obj,action,level)
202*4887Schin Tree_t*	obj;
203*4887Schin void(*		action)();
204*4887Schin int		level;
205*4887Schin #endif
206*4887Schin {	if(!obj->lchild && !obj->rchild)
207*4887Schin 		(*action)((Void_t*)obj,leaf,level);
208*4887Schin 	else
209*4887Schin 	{	(*action)((Void_t*)obj,preorder,level);
210*4887Schin 		if(obj->lchild)
211*4887Schin 			_twalk((Tree_t*)obj->lchild,action,level+1);
212*4887Schin 		(*action)((Void_t*)obj,postorder,level);
213*4887Schin 		if(obj->rchild)
214*4887Schin 			_twalk((Tree_t*)obj->rchild,action,level+1);
215*4887Schin 		(*action)((Void_t*)obj,endorder,level);
216*4887Schin 	}
217*4887Schin }
218*4887Schin 
219*4887Schin /* the original twalk allows specifying arbitrary node to start traversal.
220*4887Schin ** Since our root is a dictionary structure, the search here will start
221*4887Schin ** at whichever node happens to be current root.
222*4887Schin */
223*4887Schin extern
224*4887Schin #if __STD_C
225*4887Schin void twalk(const Void_t* root, void(*action)(const Void_t*,VISIT,int) )
226*4887Schin #else
227*4887Schin void twalk(root, action)
228*4887Schin Void_t*	root;
229*4887Schin void(*	action)();
230*4887Schin #endif
231*4887Schin {
232*4887Schin 	reg Tree_t*	o;
233*4887Schin 
234*4887Schin 	if(root && (o = (Tree_t*)dtfinger((Dt_t*)root)) )
235*4887Schin 		_twalk(o,action,0);
236*4887Schin }
237*4887Schin 
238*4887Schin #endif
239