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 * hash table sequential scan 34*4887Schin * 35*4887Schin * Hash_position_t* pos; 36*4887Schin * Hash_bucket_t* b; 37*4887Schin * pos = hashscan(tab, flags); 38*4887Schin * while (b = hashnext(&pos)) ...; 39*4887Schin * hashdone(pos); 40*4887Schin */ 41*4887Schin 42*4887Schin /* 43*4887Schin * return pos for scan on table 44*4887Schin */ 45*4887Schin 46*4887Schin Hash_position_t* 47*4887Schin hashscan(register Hash_table_t* tab, register int flags) 48*4887Schin { 49*4887Schin register Hash_position_t* pos; 50*4887Schin 51*4887Schin static Hash_bucket_t empty; 52*4887Schin 53*4887Schin if (!(pos = newof(0, Hash_position_t, 1, 0))) return(0); 54*4887Schin pos->tab = tab->root->last.table = tab; 55*4887Schin pos->bucket = ∅ 56*4887Schin pos->slot = tab->table - 1; 57*4887Schin pos->limit = tab->table + tab->size; 58*4887Schin if (tab->scope && !(flags & HASH_NOSCOPE)) 59*4887Schin { 60*4887Schin pos->flags = HASH_SCOPE; 61*4887Schin do 62*4887Schin { 63*4887Schin register Hash_bucket_t* b; 64*4887Schin 65*4887Schin if (tab->frozen) 66*4887Schin { 67*4887Schin register Hash_bucket_t** sp = tab->table; 68*4887Schin register Hash_bucket_t** sx = tab->table + tab->size; 69*4887Schin 70*4887Schin while (sp < sx) 71*4887Schin for (b = *sp++; b; b = b->next) 72*4887Schin b->hash &= ~HASH_HIDDEN; 73*4887Schin } 74*4887Schin } while (tab = tab->scope); 75*4887Schin tab = pos->tab; 76*4887Schin } 77*4887Schin else pos->flags = 0; 78*4887Schin tab->frozen++; 79*4887Schin return(pos); 80*4887Schin } 81*4887Schin 82*4887Schin /* 83*4887Schin * return next scan element 84*4887Schin */ 85*4887Schin 86*4887Schin Hash_bucket_t* 87*4887Schin hashnext(register Hash_position_t* pos) 88*4887Schin { 89*4887Schin register Hash_bucket_t* b; 90*4887Schin 91*4887Schin if (!pos) return(pos->tab->root->last.bucket = 0); 92*4887Schin b = pos->bucket; 93*4887Schin for (;;) 94*4887Schin { 95*4887Schin if (!(b = b->next)) 96*4887Schin { 97*4887Schin do 98*4887Schin { 99*4887Schin if (++pos->slot >= pos->limit) 100*4887Schin { 101*4887Schin pos->tab->frozen--; 102*4887Schin if (!pos->flags || !pos->tab->scope) return(0); 103*4887Schin pos->tab = pos->tab->scope; 104*4887Schin pos->tab->root->last.table = pos->tab; 105*4887Schin pos->limit = (pos->slot = pos->tab->table) + pos->tab->size; 106*4887Schin pos->tab->frozen++; 107*4887Schin } 108*4887Schin } while (!(b = *pos->slot)); 109*4887Schin } 110*4887Schin if (!(b->hash & HASH_DELETED) && (!(pos->tab->flags & HASH_VALUE) || b->value) && (!pos->flags || !(b->hash & (HASH_HIDDEN|HASH_HIDES)))) break; 111*4887Schin if (b->hash & HASH_HIDES) 112*4887Schin { 113*4887Schin register Hash_bucket_t* h = (Hash_bucket_t*)b->name; 114*4887Schin 115*4887Schin if (!(h->hash & HASH_HIDDEN)) 116*4887Schin { 117*4887Schin h->hash |= HASH_HIDDEN; 118*4887Schin if (!(b->hash & HASH_DELETED)) break; 119*4887Schin } 120*4887Schin } 121*4887Schin else b->hash &= ~HASH_HIDDEN; 122*4887Schin } 123*4887Schin return(pos->tab->root->last.bucket = pos->bucket = b); 124*4887Schin } 125*4887Schin 126*4887Schin /* 127*4887Schin * terminate scan 128*4887Schin */ 129*4887Schin 130*4887Schin void 131*4887Schin hashdone(register Hash_position_t* pos) 132*4887Schin { 133*4887Schin if (pos) 134*4887Schin { 135*4887Schin if (pos->tab->frozen) 136*4887Schin pos->tab->frozen--; 137*4887Schin free(pos); 138*4887Schin } 139*4887Schin } 140