14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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 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 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 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 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 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 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 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