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 #pragma prototyped 23*4887Schin /* 24*4887Schin * Glenn Fowler 25*4887Schin * AT&T Research 26*4887Schin * 27*4887Schin * hash table library 28*4887Schin */ 29*4887Schin 30*4887Schin #include "hashlib.h" 31*4887Schin 32*4887Schin /* 33*4887Schin * free (remove) a hash table 34*4887Schin * can be called for partially constructed tables 35*4887Schin * scope covered table pointer is returned 36*4887Schin * root info freed when last reference freed 37*4887Schin */ 38*4887Schin 39*4887Schin Hash_table_t* 40*4887Schin hashfree(register Hash_table_t* tab) 41*4887Schin { 42*4887Schin register Hash_bucket_t** sp; 43*4887Schin register Hash_bucket_t* b; 44*4887Schin register Hash_bucket_t* p; 45*4887Schin Hash_bucket_t** sx; 46*4887Schin Hash_root_t* rp; 47*4887Schin Hash_table_t* tp; 48*4887Schin Hash_free_f freevalue; 49*4887Schin Hash_free_f freebucket; 50*4887Schin Hash_region_f region; 51*4887Schin void* handle; 52*4887Schin 53*4887Schin if (!tab) return(0); 54*4887Schin if (tab->table) 55*4887Schin { 56*4887Schin freebucket = 0; 57*4887Schin freevalue = 0; 58*4887Schin if (tab->root->local->free) 59*4887Schin { 60*4887Schin if (tab->root->flags & HASH_BUCKET) freebucket = tab->root->local->free; 61*4887Schin else freevalue = tab->root->local->free; 62*4887Schin } 63*4887Schin if (region = tab->root->local->region) 64*4887Schin handle = tab->root->local->handle; 65*4887Schin sx = &tab->table[tab->size]; 66*4887Schin sp = &tab->table[0]; 67*4887Schin while (sp < sx) 68*4887Schin { 69*4887Schin b = *sp++; 70*4887Schin while (b) 71*4887Schin { 72*4887Schin p = b; 73*4887Schin b = b->next; 74*4887Schin if (freebucket) (*freebucket)((char*)p); 75*4887Schin else if (freevalue && p->value) (*freevalue)(p->value); 76*4887Schin if (p->hash & HASH_FREENAME) 77*4887Schin { 78*4887Schin p->hash &= ~HASH_FREENAME; 79*4887Schin if (region) (*region)(handle, p->name, 0, 0); 80*4887Schin else free(p->name); 81*4887Schin } 82*4887Schin if (!(p->hash & HASH_KEEP)) 83*4887Schin { 84*4887Schin if (region) (*region)(handle, p, 0, 0); 85*4887Schin else free(p); 86*4887Schin } 87*4887Schin else if (p->hash & HASH_HIDES) 88*4887Schin { 89*4887Schin p->hash &= ~HASH_HIDES; 90*4887Schin p->name = ((Hash_bucket_t*)p->name)->name; 91*4887Schin } 92*4887Schin } 93*4887Schin } 94*4887Schin if ((tab->flags & (HASH_RESIZE|HASH_STATIC)) != HASH_STATIC) 95*4887Schin { 96*4887Schin if (region) (*region)(handle, tab->table, 0, 0); 97*4887Schin else free(tab->table); 98*4887Schin } 99*4887Schin } 100*4887Schin else region = 0; 101*4887Schin if (tab->root) 102*4887Schin { 103*4887Schin if (!region) 104*4887Schin { 105*4887Schin /* 106*4887Schin * remove from the table lists 107*4887Schin */ 108*4887Schin 109*4887Schin if ((tp = tab->root->references) != tab) 110*4887Schin { 111*4887Schin for (; tp; tp = tp->next) 112*4887Schin if (tp->next == tab) 113*4887Schin { 114*4887Schin tp->next = tab->next; 115*4887Schin break; 116*4887Schin } 117*4887Schin } 118*4887Schin else if (!(tab->root->references = tp->next)) 119*4887Schin { 120*4887Schin if ((rp = hash_info.list) != tab->root) 121*4887Schin { 122*4887Schin for (; rp; rp = rp->next) 123*4887Schin if (rp->next == tab->root) 124*4887Schin { 125*4887Schin rp->next = tab->root->next; 126*4887Schin break; 127*4887Schin } 128*4887Schin } 129*4887Schin else hash_info.list = rp->next; 130*4887Schin } 131*4887Schin } 132*4887Schin if (!(tab->root->references)) 133*4887Schin { 134*4887Schin if (tab->root->local) 135*4887Schin free(tab->root->local); 136*4887Schin if (region) (*region)(handle, tab->root, 0, 0); 137*4887Schin else free(tab->root); 138*4887Schin } 139*4887Schin } 140*4887Schin if (tp = tab->scope) tp->frozen--; 141*4887Schin if (region) (*region)(handle, tab, 0, 0); 142*4887Schin else free(tab); 143*4887Schin return(tp); 144*4887Schin } 145