xref: /onnv-gate/usr/src/lib/libast/common/comp/tsearch.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin /*
234887Schin  * tsearch() for systems that have <search.h> but no tsearch()
244887Schin  * why would such a system provide the interface but not the
254887Schin  * implementation? that's what happens when one slimes their
264887Schin  * way through standards compliance
274887Schin  *
284887Schin  * NOTE: please excuse the crude feature test
294887Schin  */
304887Schin 
314887Schin #if !_UWIN
324887Schin 
_STUB_tsearch()334887Schin void _STUB_tsearch(){}
344887Schin 
354887Schin #else
364887Schin 
374887Schin #if _PACKAGE_ast
384887Schin #include	<ast.h>
394887Schin #endif
404887Schin 
414887Schin #define tdelete		______tdelete
424887Schin #define tfind		______tfind
434887Schin #define tsearch		______tsearch
444887Schin #define twalk		______twalk
454887Schin 
464887Schin #include	<search.h>
474887Schin 
484887Schin #undef	tdelete
494887Schin #undef	tfind
504887Schin #undef	tsearch
514887Schin #undef	twalk
524887Schin 
534887Schin #include	"dthdr.h"
544887Schin 
554887Schin /*	POSIX tsearch library based on libcdt
564887Schin **	Written by Kiem-Phong Vo (AT&T Research, 07/19/95)
574887Schin */
584887Schin 
594887Schin typedef struct _tree_s
604887Schin {	Dtlink_t	link;
614887Schin 	Void_t*		key;
624887Schin } Tree_t;
634887Schin 
644887Schin typedef struct _treedisc_s
654887Schin {	Dtdisc_t	disc;
664887Schin 	int(*		comparf)_ARG_((const Void_t*, const Void_t*));
674887Schin } Treedisc_t;
684887Schin 
694887Schin #if defined(__EXPORT__)
704887Schin #define extern	__EXPORT__
714887Schin #endif
724887Schin 
734887Schin /* compare function */
744887Schin #if __STD_C
treecompare(Dt_t * dt,char * one,char * two,Dtdisc_t * disc)754887Schin static int treecompare(Dt_t* dt, char* one, char* two, Dtdisc_t* disc)
764887Schin #else
774887Schin static int treecompare(dt, one, two, disc)
784887Schin Dt_t*		dt;
794887Schin char*		one;
804887Schin char*		two;
814887Schin Dtdisc_t*	disc;
824887Schin #endif
834887Schin {
844887Schin 	return (*((Treedisc_t*)disc)->comparf)((Void_t*)one,(Void_t*)two);
854887Schin }
864887Schin 
874887Schin static Treedisc_t	Treedisc =
884887Schin {	{ sizeof(Dtlink_t), -1,	/* object is key		*/
894887Schin 	  0,
904887Schin 	  NIL(Dtmake_f), NIL(Dtfree_f),
914887Schin 	  treecompare,
924887Schin 	  NIL(Dthash_f),
934887Schin 	  NIL(Dtmemory_f),
944887Schin 	  NIL(Dtevent_f)
954887Schin 	},
964887Schin 	0
974887Schin };
984887Schin 
994887Schin extern
1004887Schin #if __STD_C
tsearch(const Void_t * key,Void_t ** rootp,int (* comparf)(const Void_t *,const Void_t *))1014887Schin Void_t* tsearch(const Void_t* key, Void_t** rootp,
1024887Schin 		int(*comparf)(const Void_t*,const Void_t*) )
1034887Schin #else
1044887Schin Void_t* tsearch(key, rootp, comparf)
1054887Schin Void_t*		key;
1064887Schin Void_t**	rootp;
1074887Schin int(*		comparf)();
1084887Schin #endif
1094887Schin {
1104887Schin 	reg Dt_t*	dt;
1114887Schin 	reg Tree_t*	o;
1124887Schin 
1134887Schin 	if(!rootp ||
1144887Schin 	   (!(dt = *((Dt_t**)rootp)) && !(dt = dtopen((Dtdisc_t*)(&Treedisc),Dtorder))) )
1154887Schin 		return NIL(Void_t*);
1164887Schin 
1174887Schin 	/* dangerous to set comparf on each call but that's tsearch */
1184887Schin 	Treedisc.comparf = comparf;
1194887Schin 
1204887Schin 	if(!(o = (Tree_t*)dtmatch(dt,key)) )
1214887Schin 	{	if(!(o = (Tree_t*)malloc(sizeof(Tree_t))) )
1224887Schin 			return NIL(Void_t*);
1234887Schin 		o->key = (Void_t*)key;
1244887Schin 		dtinsert(dt,o);
1254887Schin 	}
1264887Schin 
1274887Schin 	if(o)
1284887Schin 		*rootp = (Void_t*)dt;
1294887Schin 	else if(*rootp == NIL(Void_t*) )
1304887Schin 		dtclose(dt);
1314887Schin 
1324887Schin 	return (Void_t*)(&o->key);
1334887Schin }
1344887Schin 
1354887Schin extern
1364887Schin #if __STD_C
tfind(const Void_t * key,Void_t * const * rootp,int (* comparf)(const Void_t *,const Void_t *))1374887Schin Void_t* tfind(const Void_t* key, Void_t*const* rootp,
1384887Schin 		int(*comparf)(const Void_t*, const Void_t*) )
1394887Schin #else
1404887Schin Void_t* tfind(key, rootp, comparf)
1414887Schin Void_t*		key;
1424887Schin Void_t**	rootp;
1434887Schin int(*		comparf)();
1444887Schin #endif
1454887Schin {
1464887Schin 	reg Dt_t*	dt;
1474887Schin 	reg Tree_t*	o;
1484887Schin 
1494887Schin 	if(!rootp || !(dt = *((Dt_t**)rootp)) )
1504887Schin 		return NIL(Void_t*);
1514887Schin 	Treedisc.comparf = comparf;
1524887Schin 
1534887Schin 	return (o = (Tree_t*)dtmatch(dt,key)) ? (Void_t*)(&o->key) : NIL(Void_t*);
1544887Schin }
1554887Schin 
1564887Schin /* the original tdelete() specifies that it will return the parent pointer
1574887Schin ** in the tree if there is one. Since we are using a splay tree, a deleted
1584887Schin ** node is always rotated to the root first. So this implementation always
1594887Schin ** returns the key of the new root.
1604887Schin */
1614887Schin extern
1624887Schin #if __STD_C
tdelete(const Void_t * key,Void_t ** rootp,int (* comparf)(const Void_t *,const Void_t *))1634887Schin Void_t* tdelete(const Void_t* key, Void_t** rootp,
1644887Schin 		int(*comparf)(const Void_t*, const Void_t*) )
1654887Schin #else
1664887Schin Void_t* tdelete(key, rootp, comparf)
1674887Schin Void_t*		key;
1684887Schin Void_t**	rootp;
1694887Schin int(*		comparf)();
1704887Schin #endif
1714887Schin {
1724887Schin 	reg Dt_t*	dt;
1734887Schin 	reg Tree_t*	o;
1744887Schin 	Tree_t		obj;
1754887Schin 
1764887Schin 	if(!rootp || !(dt = *((Dt_t**)rootp)) )
1774887Schin 		return NIL(Void_t*);
1784887Schin 
1794887Schin 	Treedisc.comparf = comparf;
1804887Schin 
1814887Schin 	obj.key = (Void_t*)key;
1824887Schin 	dtdelete(dt,&obj);
1834887Schin 
1844887Schin 	if(!(o = dtfinger(dt)) )
1854887Schin 	{	dtclose(dt);
1864887Schin 		*rootp = NIL(Void_t*);
1874887Schin 	}
1884887Schin 
1894887Schin 	return o ? (Void_t*)(&o->key) : NIL(Void_t*);
1904887Schin }
1914887Schin 
1924887Schin /* the below routine assumes a particular layout of Dtlink_t.
1934887Schin ** If this ever gets changed, this routine should be redone.
1944887Schin */
1954887Schin #define lchild	link.hl._left
1964887Schin #define rchild	link.right
1974887Schin 
1984887Schin #if __STD_C
_twalk(Tree_t * obj,void (* action)(const Void_t *,VISIT,int),int level)1994887Schin static void _twalk(Tree_t* obj, void(*action)(const Void_t*,VISIT,int), int level)
2004887Schin #else
2014887Schin static void _twalk(obj,action,level)
2024887Schin Tree_t*	obj;
2034887Schin void(*		action)();
2044887Schin int		level;
2054887Schin #endif
2064887Schin {	if(!obj->lchild && !obj->rchild)
2074887Schin 		(*action)((Void_t*)obj,leaf,level);
2084887Schin 	else
2094887Schin 	{	(*action)((Void_t*)obj,preorder,level);
2104887Schin 		if(obj->lchild)
2114887Schin 			_twalk((Tree_t*)obj->lchild,action,level+1);
2124887Schin 		(*action)((Void_t*)obj,postorder,level);
2134887Schin 		if(obj->rchild)
2144887Schin 			_twalk((Tree_t*)obj->rchild,action,level+1);
2154887Schin 		(*action)((Void_t*)obj,endorder,level);
2164887Schin 	}
2174887Schin }
2184887Schin 
2194887Schin /* the original twalk allows specifying arbitrary node to start traversal.
2204887Schin ** Since our root is a dictionary structure, the search here will start
2214887Schin ** at whichever node happens to be current root.
2224887Schin */
2234887Schin extern
2244887Schin #if __STD_C
twalk(const Void_t * root,void (* action)(const Void_t *,VISIT,int))2254887Schin void twalk(const Void_t* root, void(*action)(const Void_t*,VISIT,int) )
2264887Schin #else
2274887Schin void twalk(root, action)
2284887Schin Void_t*	root;
2294887Schin void(*	action)();
2304887Schin #endif
2314887Schin {
2324887Schin 	reg Tree_t*	o;
2334887Schin 
2344887Schin 	if(root && (o = (Tree_t*)dtfinger((Dt_t*)root)) )
2354887Schin 		_twalk(o,action,0);
2364887Schin }
2374887Schin 
2384887Schin #endif
239