1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
23 * tsearch() for systems that have <search.h> but no tsearch()
24 * why would such a system provide the interface but not the
25 * implementation? that's what happens when one slimes their
26 * way through standards compliance
28 * NOTE: please excuse the crude feature test
33 void _STUB_tsearch(){}
41 #define tdelete ______tdelete
42 #define tfind ______tfind
43 #define tsearch ______tsearch
44 #define twalk ______twalk
55 /* POSIX tsearch library based on libcdt
56 ** Written by Kiem-Phong Vo (AT&T Research, 07/19/95)
59 typedef struct _tree_s
64 typedef struct _treedisc_s
66 int(* comparf
)_ARG_((const Void_t
*, const Void_t
*));
69 #if defined(__EXPORT__)
70 #define extern __EXPORT__
73 /* compare function */
75 static int treecompare(Dt_t
* dt
, char* one
, char* two
, Dtdisc_t
* disc
)
77 static int treecompare(dt
, one
, two
, disc
)
84 return (*((Treedisc_t
*)disc
)->comparf
)((Void_t
*)one
,(Void_t
*)two
);
87 static Treedisc_t Treedisc
=
88 { { sizeof(Dtlink_t
), -1, /* object is key */
90 NIL(Dtmake_f
), NIL(Dtfree_f
),
101 Void_t
* tsearch(const Void_t
* key
, Void_t
** rootp
,
102 int(*comparf
)(const Void_t
*,const Void_t
*) )
104 Void_t
* tsearch(key
, rootp
, comparf
)
114 (!(dt
= *((Dt_t
**)rootp
)) && !(dt
= dtopen((Dtdisc_t
*)(&Treedisc
),Dtorder
))) )
117 /* dangerous to set comparf on each call but that's tsearch */
118 Treedisc
.comparf
= comparf
;
120 if(!(o
= (Tree_t
*)dtmatch(dt
,key
)) )
121 { if(!(o
= (Tree_t
*)malloc(sizeof(Tree_t
))) )
123 o
->key
= (Void_t
*)key
;
128 *rootp
= (Void_t
*)dt
;
129 else if(*rootp
== NIL(Void_t
*) )
132 return (Void_t
*)(&o
->key
);
137 Void_t
* tfind(const Void_t
* key
, Void_t
*const* rootp
,
138 int(*comparf
)(const Void_t
*, const Void_t
*) )
140 Void_t
* tfind(key
, rootp
, comparf
)
149 if(!rootp
|| !(dt
= *((Dt_t
**)rootp
)) )
151 Treedisc
.comparf
= comparf
;
153 return (o
= (Tree_t
*)dtmatch(dt
,key
)) ? (Void_t
*)(&o
->key
) : NIL(Void_t
*);
156 /* the original tdelete() specifies that it will return the parent pointer
157 ** in the tree if there is one. Since we are using a splay tree, a deleted
158 ** node is always rotated to the root first. So this implementation always
159 ** returns the key of the new root.
163 Void_t
* tdelete(const Void_t
* key
, Void_t
** rootp
,
164 int(*comparf
)(const Void_t
*, const Void_t
*) )
166 Void_t
* tdelete(key
, rootp
, comparf
)
176 if(!rootp
|| !(dt
= *((Dt_t
**)rootp
)) )
179 Treedisc
.comparf
= comparf
;
181 obj
.key
= (Void_t
*)key
;
184 if(!(o
= dtfinger(dt
)) )
186 *rootp
= NIL(Void_t
*);
189 return o
? (Void_t
*)(&o
->key
) : NIL(Void_t
*);
192 /* the below routine assumes a particular layout of Dtlink_t.
193 ** If this ever gets changed, this routine should be redone.
195 #define lchild link.hl._left
196 #define rchild link.right
199 static void _twalk(Tree_t
* obj
, void(*action
)(const Void_t
*,VISIT
,int), int level
)
201 static void _twalk(obj
,action
,level
)
206 { if(!obj
->lchild
&& !obj
->rchild
)
207 (*action
)((Void_t
*)obj
,leaf
,level
);
209 { (*action
)((Void_t
*)obj
,preorder
,level
);
211 _twalk((Tree_t
*)obj
->lchild
,action
,level
+1);
212 (*action
)((Void_t
*)obj
,postorder
,level
);
214 _twalk((Tree_t
*)obj
->rchild
,action
,level
+1);
215 (*action
)((Void_t
*)obj
,endorder
,level
);
219 /* the original twalk allows specifying arbitrary node to start traversal.
220 ** Since our root is a dictionary structure, the search here will start
221 ** at whichever node happens to be current root.
225 void twalk(const Void_t
* root
, void(*action
)(const Void_t
*,VISIT
,int) )
227 void twalk(root
, action
)
234 if(root
&& (o
= (Tree_t
*)dtfinger((Dt_t
*)root
)) )