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