1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 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*
hashfree(register Hash_table_t * tab)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