14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1985-2010 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 78462SApril.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 #pragma prototyped 234887Schin /* 244887Schin * Glenn Fowler 254887Schin * AT&T Research 264887Schin * 274887Schin * hash table library 284887Schin */ 294887Schin 304887Schin #include "hashlib.h" 314887Schin 324887Schin /* 334887Schin * hash table sequential scan 344887Schin * 354887Schin * Hash_position_t* pos; 364887Schin * Hash_bucket_t* b; 374887Schin * pos = hashscan(tab, flags); 384887Schin * while (b = hashnext(&pos)) ...; 394887Schin * hashdone(pos); 404887Schin */ 414887Schin 424887Schin /* 434887Schin * return pos for scan on table 444887Schin */ 454887Schin 464887Schin Hash_position_t* hashscan(register Hash_table_t * tab,register int flags)474887Schinhashscan(register Hash_table_t* tab, register int flags) 484887Schin { 494887Schin register Hash_position_t* pos; 504887Schin 514887Schin static Hash_bucket_t empty; 524887Schin 534887Schin if (!(pos = newof(0, Hash_position_t, 1, 0))) return(0); 544887Schin pos->tab = tab->root->last.table = tab; 554887Schin pos->bucket = ∅ 564887Schin pos->slot = tab->table - 1; 574887Schin pos->limit = tab->table + tab->size; 584887Schin if (tab->scope && !(flags & HASH_NOSCOPE)) 594887Schin { 604887Schin pos->flags = HASH_SCOPE; 614887Schin do 624887Schin { 634887Schin register Hash_bucket_t* b; 644887Schin 654887Schin if (tab->frozen) 664887Schin { 674887Schin register Hash_bucket_t** sp = tab->table; 684887Schin register Hash_bucket_t** sx = tab->table + tab->size; 694887Schin 704887Schin while (sp < sx) 714887Schin for (b = *sp++; b; b = b->next) 724887Schin b->hash &= ~HASH_HIDDEN; 734887Schin } 744887Schin } while (tab = tab->scope); 754887Schin tab = pos->tab; 764887Schin } 774887Schin else pos->flags = 0; 784887Schin tab->frozen++; 794887Schin return(pos); 804887Schin } 814887Schin 824887Schin /* 834887Schin * return next scan element 844887Schin */ 854887Schin 864887Schin Hash_bucket_t* hashnext(register Hash_position_t * pos)874887Schinhashnext(register Hash_position_t* pos) 884887Schin { 894887Schin register Hash_bucket_t* b; 904887Schin 914887Schin if (!pos) return(pos->tab->root->last.bucket = 0); 924887Schin b = pos->bucket; 934887Schin for (;;) 944887Schin { 954887Schin if (!(b = b->next)) 964887Schin { 974887Schin do 984887Schin { 994887Schin if (++pos->slot >= pos->limit) 1004887Schin { 1014887Schin pos->tab->frozen--; 1024887Schin if (!pos->flags || !pos->tab->scope) return(0); 1034887Schin pos->tab = pos->tab->scope; 1044887Schin pos->tab->root->last.table = pos->tab; 1054887Schin pos->limit = (pos->slot = pos->tab->table) + pos->tab->size; 1064887Schin pos->tab->frozen++; 1074887Schin } 1084887Schin } while (!(b = *pos->slot)); 1094887Schin } 1104887Schin if (!(b->hash & HASH_DELETED) && (!(pos->tab->flags & HASH_VALUE) || b->value) && (!pos->flags || !(b->hash & (HASH_HIDDEN|HASH_HIDES)))) break; 1114887Schin if (b->hash & HASH_HIDES) 1124887Schin { 1134887Schin register Hash_bucket_t* h = (Hash_bucket_t*)b->name; 1144887Schin 1154887Schin if (!(h->hash & HASH_HIDDEN)) 1164887Schin { 1174887Schin h->hash |= HASH_HIDDEN; 1184887Schin if (!(b->hash & HASH_DELETED)) break; 1194887Schin } 1204887Schin } 1214887Schin else b->hash &= ~HASH_HIDDEN; 1224887Schin } 1234887Schin return(pos->tab->root->last.bucket = pos->bucket = b); 1244887Schin } 1254887Schin 1264887Schin /* 1274887Schin * terminate scan 1284887Schin */ 1294887Schin 1304887Schin void hashdone(register Hash_position_t * pos)1314887Schinhashdone(register Hash_position_t* pos) 1324887Schin { 1334887Schin if (pos) 1344887Schin { 1354887Schin if (pos->tab->frozen) 1364887Schin pos->tab->frozen--; 1374887Schin free(pos); 1384887Schin } 1394887Schin } 140