1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 20 * * 21 ***********************************************************************/ 22 #pragma prototyped 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * hash table library 28 */ 29 30 #include "hashlib.h" 31 32 /* 33 * free (remove) a hash table 34 * can be called for partially constructed tables 35 * scope covered table pointer is returned 36 * root info freed when last reference freed 37 */ 38 39 Hash_table_t* 40 hashfree(register Hash_table_t* tab) 41 { 42 register Hash_bucket_t** sp; 43 register Hash_bucket_t* b; 44 register Hash_bucket_t* p; 45 Hash_bucket_t** sx; 46 Hash_root_t* rp; 47 Hash_table_t* tp; 48 Hash_free_f freevalue; 49 Hash_free_f freebucket; 50 Hash_region_f region; 51 void* handle; 52 53 if (!tab) return(0); 54 if (tab->table) 55 { 56 freebucket = 0; 57 freevalue = 0; 58 if (tab->root->local->free) 59 { 60 if (tab->root->flags & HASH_BUCKET) freebucket = tab->root->local->free; 61 else freevalue = tab->root->local->free; 62 } 63 if (region = tab->root->local->region) 64 handle = tab->root->local->handle; 65 sx = &tab->table[tab->size]; 66 sp = &tab->table[0]; 67 while (sp < sx) 68 { 69 b = *sp++; 70 while (b) 71 { 72 p = b; 73 b = b->next; 74 if (freebucket) (*freebucket)((char*)p); 75 else if (freevalue && p->value) (*freevalue)(p->value); 76 if (p->hash & HASH_FREENAME) 77 { 78 p->hash &= ~HASH_FREENAME; 79 if (region) (*region)(handle, p->name, 0, 0); 80 else free(p->name); 81 } 82 if (!(p->hash & HASH_KEEP)) 83 { 84 if (region) (*region)(handle, p, 0, 0); 85 else free(p); 86 } 87 else if (p->hash & HASH_HIDES) 88 { 89 p->hash &= ~HASH_HIDES; 90 p->name = ((Hash_bucket_t*)p->name)->name; 91 } 92 } 93 } 94 if ((tab->flags & (HASH_RESIZE|HASH_STATIC)) != HASH_STATIC) 95 { 96 if (region) (*region)(handle, tab->table, 0, 0); 97 else free(tab->table); 98 } 99 } 100 else region = 0; 101 if (tab->root) 102 { 103 if (!region) 104 { 105 /* 106 * remove from the table lists 107 */ 108 109 if ((tp = tab->root->references) != tab) 110 { 111 for (; tp; tp = tp->next) 112 if (tp->next == tab) 113 { 114 tp->next = tab->next; 115 break; 116 } 117 } 118 else if (!(tab->root->references = tp->next)) 119 { 120 if ((rp = hash_info.list) != tab->root) 121 { 122 for (; rp; rp = rp->next) 123 if (rp->next == tab->root) 124 { 125 rp->next = tab->root->next; 126 break; 127 } 128 } 129 else hash_info.list = rp->next; 130 } 131 } 132 if (!(tab->root->references)) 133 { 134 if (tab->root->local) 135 free(tab->root->local); 136 if (region) (*region)(handle, tab->root, 0, 0); 137 else free(tab->root); 138 } 139 } 140 if (tp = tab->scope) tp->frozen--; 141 if (region) (*region)(handle, tab, 0, 0); 142 else free(tab); 143 return(tp); 144 } 145