Blame src/lib/libast/comp/tsearch.c

Packit Service a8c26c
/***********************************************************************
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*               This software is part of the ast package               *
Packit Service a8c26c
*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
Packit Service a8c26c
*                      and is licensed under the                       *
Packit Service a8c26c
*                 Eclipse Public License, Version 1.0                  *
Packit Service a8c26c
*                    by AT&T Intellectual Property                     *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                A copy of the License is available at                 *
Packit Service a8c26c
*          http://www.eclipse.org/org/documents/epl-v10.html           *
Packit Service a8c26c
*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*              Information and Software Systems Research               *
Packit Service a8c26c
*                            AT&T Research                             *
Packit Service a8c26c
*                           Florham Park NJ                            *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
*                 Glenn Fowler <gsf@research.att.com>                  *
Packit Service a8c26c
*                  David Korn <dgk@research.att.com>                   *
Packit Service a8c26c
*                   Phong Vo <kpv@research.att.com>                    *
Packit Service a8c26c
*                                                                      *
Packit Service a8c26c
***********************************************************************/
Packit Service a8c26c
/*
Packit Service a8c26c
 * tsearch() for systems that have <search.h> but no tsearch()
Packit Service a8c26c
 * why would such a system provide the interface but not the
Packit Service a8c26c
 * implementation? that's what happens when one slimes their
Packit Service a8c26c
 * way through standards compliance
Packit Service a8c26c
 *
Packit Service a8c26c
 * NOTE: please excuse the crude feature test
Packit Service a8c26c
 */
Packit Service a8c26c
Packit Service a8c26c
#if !_UWIN
Packit Service a8c26c
Packit Service a8c26c
void _STUB_tsearch(){}
Packit Service a8c26c
Packit Service a8c26c
#else
Packit Service a8c26c
Packit Service a8c26c
#if _PACKAGE_ast
Packit Service a8c26c
#include	<ast.h>
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
#define tdelete		______tdelete
Packit Service a8c26c
#define tfind		______tfind
Packit Service a8c26c
#define tsearch		______tsearch
Packit Service a8c26c
#define twalk		______twalk
Packit Service a8c26c
Packit Service a8c26c
#include	<search.h>
Packit Service a8c26c
Packit Service a8c26c
#undef	tdelete
Packit Service a8c26c
#undef	tfind
Packit Service a8c26c
#undef	tsearch
Packit Service a8c26c
#undef	twalk
Packit Service a8c26c
Packit Service a8c26c
#include	"dthdr.h"
Packit Service a8c26c
Packit Service a8c26c
extern Void_t*		dtfinger(Dt_t*);
Packit Service a8c26c
Packit Service a8c26c
/*	POSIX tsearch library based on libcdt
Packit Service a8c26c
**	Written by Kiem-Phong Vo (AT&T Research, 07/19/95)
Packit Service a8c26c
*/
Packit Service a8c26c
Packit Service a8c26c
typedef struct _tree_s
Packit Service a8c26c
{	Dtlink_t	link;
Packit Service a8c26c
	Void_t*		key;
Packit Service a8c26c
} Tree_t;
Packit Service a8c26c
Packit Service a8c26c
typedef struct _treedisc_s
Packit Service a8c26c
{	Dtdisc_t	disc;
Packit Service a8c26c
	int(*		comparf)_ARG_((const Void_t*, const Void_t*));
Packit Service a8c26c
} Treedisc_t;
Packit Service a8c26c
Packit Service a8c26c
#if defined(__EXPORT__)
Packit Service a8c26c
#define extern	__EXPORT__
Packit Service a8c26c
#endif
Packit Service a8c26c
Packit Service a8c26c
/* compare function */
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static int treecompare(Dt_t* dt, char* one, char* two, Dtdisc_t* disc)
Packit Service a8c26c
#else
Packit Service a8c26c
static int treecompare(dt, one, two, disc)
Packit Service a8c26c
Dt_t*		dt;
Packit Service a8c26c
char*		one;
Packit Service a8c26c
char*		two;
Packit Service a8c26c
Dtdisc_t*	disc;
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	return (*((Treedisc_t*)disc)->comparf)((Void_t*)one,(Void_t*)two);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
static Treedisc_t	Treedisc =
Packit Service a8c26c
{	{ sizeof(Dtlink_t), -1,	/* object is key		*/
Packit Service a8c26c
	  0,
Packit Service a8c26c
	  NIL(Dtmake_f), NIL(Dtfree_f),
Packit Service a8c26c
	  treecompare,
Packit Service a8c26c
	  NIL(Dthash_f),
Packit Service a8c26c
	  NIL(Dtmemory_f),
Packit Service a8c26c
	  NIL(Dtevent_f)
Packit Service a8c26c
	},
Packit Service a8c26c
	0
Packit Service a8c26c
};
Packit Service a8c26c
Packit Service a8c26c
extern
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
Void_t* tsearch(const Void_t* key, Void_t** rootp,
Packit Service a8c26c
		int(*comparf)(const Void_t*,const Void_t*) )
Packit Service a8c26c
#else
Packit Service a8c26c
Void_t* tsearch(key, rootp, comparf)
Packit Service a8c26c
Void_t*		key;
Packit Service a8c26c
Void_t**	rootp;
Packit Service a8c26c
int(*		comparf)();
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Dt_t*	dt;
Packit Service a8c26c
	reg Tree_t*	o;
Packit Service a8c26c
Packit Service a8c26c
	if(!rootp ||
Packit Service a8c26c
	   (!(dt = *((Dt_t**)rootp)) && !(dt = dtopen((Dtdisc_t*)(&Treedisc),Dtoset))) )
Packit Service a8c26c
		return NIL(Void_t*);
Packit Service a8c26c
Packit Service a8c26c
	/* dangerous to set comparf on each call but that's tsearch */
Packit Service a8c26c
	Treedisc.comparf = comparf;
Packit Service a8c26c
Packit Service a8c26c
	if(!(o = (Tree_t*)dtmatch(dt,key)) )
Packit Service a8c26c
	{	if(!(o = (Tree_t*)malloc(sizeof(Tree_t))) )
Packit Service a8c26c
			return NIL(Void_t*);
Packit Service a8c26c
		o->key = (Void_t*)key;
Packit Service a8c26c
		dtinsert(dt,o);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	if(o)
Packit Service a8c26c
		*rootp = (Void_t*)dt;
Packit Service a8c26c
	else if(*rootp == NIL(Void_t*) )
Packit Service a8c26c
		dtclose(dt);
Packit Service a8c26c
Packit Service a8c26c
	return (Void_t*)(&o->key);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
extern
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
Void_t* tfind(const Void_t* key, Void_t*const* rootp,
Packit Service a8c26c
		int(*comparf)(const Void_t*, const Void_t*) )
Packit Service a8c26c
#else
Packit Service a8c26c
Void_t* tfind(key, rootp, comparf)
Packit Service a8c26c
Void_t*		key;
Packit Service a8c26c
Void_t**	rootp;
Packit Service a8c26c
int(*		comparf)();
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Dt_t*	dt;
Packit Service a8c26c
	reg Tree_t*	o;
Packit Service a8c26c
Packit Service a8c26c
	if(!rootp || !(dt = *((Dt_t**)rootp)) )
Packit Service a8c26c
		return NIL(Void_t*);
Packit Service a8c26c
	Treedisc.comparf = comparf;
Packit Service a8c26c
Packit Service a8c26c
	return (o = (Tree_t*)dtmatch(dt,key)) ? (Void_t*)(&o->key) : NIL(Void_t*);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* the original tdelete() specifies that it will return the parent pointer
Packit Service a8c26c
** in the tree if there is one. Since we are using a splay tree, a deleted
Packit Service a8c26c
** node is always rotated to the root first. So this implementation always
Packit Service a8c26c
** returns the key of the new root.
Packit Service a8c26c
*/
Packit Service a8c26c
extern
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
Void_t* tdelete(const Void_t* key, Void_t** rootp,
Packit Service a8c26c
		int(*comparf)(const Void_t*, const Void_t*) )
Packit Service a8c26c
#else
Packit Service a8c26c
Void_t* tdelete(key, rootp, comparf)
Packit Service a8c26c
Void_t*		key;
Packit Service a8c26c
Void_t**	rootp;
Packit Service a8c26c
int(*		comparf)();
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Dt_t*	dt;
Packit Service a8c26c
	reg Tree_t*	o;
Packit Service a8c26c
	Tree_t		obj;
Packit Service a8c26c
Packit Service a8c26c
	if(!rootp || !(dt = *((Dt_t**)rootp)) )
Packit Service a8c26c
		return NIL(Void_t*);
Packit Service a8c26c
Packit Service a8c26c
	Treedisc.comparf = comparf;
Packit Service a8c26c
Packit Service a8c26c
	obj.key = (Void_t*)key;
Packit Service a8c26c
	dtdelete(dt,&obj);
Packit Service a8c26c
Packit Service a8c26c
	if(!(o = dtfinger(dt)) )
Packit Service a8c26c
	{	dtclose(dt);
Packit Service a8c26c
		*rootp = NIL(Void_t*);
Packit Service a8c26c
	}
Packit Service a8c26c
Packit Service a8c26c
	return o ? (Void_t*)(&o->key) : NIL(Void_t*);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* the below routine assumes a particular layout of Dtlink_t.
Packit Service a8c26c
** If this ever gets changed, this routine should be redone.
Packit Service a8c26c
*/
Packit Service a8c26c
#define lchild	link.lh.__left
Packit Service a8c26c
#define rchild	link.rh.__rght
Packit Service a8c26c
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
static void _twalk(Tree_t* obj, void(*action)(const Void_t*,VISIT,int), int level)
Packit Service a8c26c
#else
Packit Service a8c26c
static void _twalk(obj,action,level)
Packit Service a8c26c
Tree_t*	obj;
Packit Service a8c26c
void(*		action)();
Packit Service a8c26c
int		level;
Packit Service a8c26c
#endif
Packit Service a8c26c
{	if(!obj->lchild && !obj->rchild)
Packit Service a8c26c
		(*action)((Void_t*)obj,leaf,level);
Packit Service a8c26c
	else
Packit Service a8c26c
	{	(*action)((Void_t*)obj,preorder,level);
Packit Service a8c26c
		if(obj->lchild)
Packit Service a8c26c
			_twalk((Tree_t*)obj->lchild,action,level+1);
Packit Service a8c26c
		(*action)((Void_t*)obj,postorder,level);
Packit Service a8c26c
		if(obj->rchild)
Packit Service a8c26c
			_twalk((Tree_t*)obj->rchild,action,level+1);
Packit Service a8c26c
		(*action)((Void_t*)obj,endorder,level);
Packit Service a8c26c
	}
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
/* the original twalk allows specifying arbitrary node to start traversal.
Packit Service a8c26c
** Since our root is a dictionary structure, the search here will start
Packit Service a8c26c
** at whichever node happens to be current root.
Packit Service a8c26c
*/
Packit Service a8c26c
extern
Packit Service a8c26c
#if __STD_C
Packit Service a8c26c
void twalk(const Void_t* root, void(*action)(const Void_t*,VISIT,int) )
Packit Service a8c26c
#else
Packit Service a8c26c
void twalk(root, action)
Packit Service a8c26c
Void_t*	root;
Packit Service a8c26c
void(*	action)();
Packit Service a8c26c
#endif
Packit Service a8c26c
{
Packit Service a8c26c
	reg Tree_t*	o;
Packit Service a8c26c
Packit Service a8c26c
	if(root && (o = (Tree_t*)dtfinger((Dt_t*)root)) )
Packit Service a8c26c
		_twalk(o,action,0);
Packit Service a8c26c
}
Packit Service a8c26c
Packit Service a8c26c
#endif