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