19672Slinton /* Copyright (c) 1982 Regents of the University of California */ 29672Slinton 3*11103Slinton static char sccsid[] = "@(#)names.c 1.3 02/16/83"; 49672Slinton 59672Slinton /* 69672Slinton * Name are the internal representation for identifiers. 79672Slinton * 89672Slinton * A hash table is used to map identifiers to names. 99672Slinton */ 109672Slinton 119672Slinton #include "defs.h" 129672Slinton #include "names.h" 139672Slinton 149672Slinton #ifndef public 159672Slinton typedef struct Name *Name; 169672Slinton 179672Slinton /* 189672Slinton * Inline (for speed) function to return the identifier (string) 199672Slinton * associated with a name. Because C cannot support both inlines 209672Slinton * and data hiding at the same time, the Name structure must be 219672Slinton * publicly visible. It is not used explicitly, however, outside of this file. 229672Slinton */ 239672Slinton 249672Slinton struct Name { 259672Slinton char *identifier; 269672Slinton Name chain; 279672Slinton }; 289672Slinton 299672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier) 309672Slinton #endif 319672Slinton 329672Slinton #define HASHTABLESIZE 2997 339672Slinton 349672Slinton private Name nametable[HASHTABLESIZE]; 359672Slinton 369672Slinton /* 379672Slinton * Names are allocated in large chunks to avoid calls to malloc 389672Slinton * and to cluster names in memory so that tracing hash chains 399672Slinton * doesn't cause many a page fault. 409672Slinton */ 419672Slinton 42*11103Slinton #define CHUNKSIZE 200 439672Slinton 449672Slinton typedef struct Namepool { 459672Slinton struct Name name[CHUNKSIZE]; 469672Slinton struct Namepool *prevpool; 479672Slinton } *Namepool; 489672Slinton 499672Slinton private Namepool namepool = nil; 509672Slinton private Integer nleft = 0; 519672Slinton 529672Slinton /* 539672Slinton * Given an identifier, convert it to a name. 549672Slinton * If it's not in the hash table, then put it there. 559672Slinton * 569672Slinton * The second argument specifies whether the string should be copied 579672Slinton * into newly allocated space if not found. 589672Slinton * 599672Slinton * Pardon my use of goto's, but it seemed more efficient and less convoluted 609672Slinton * than adding a collection of boolean variables. This routine is time 619672Slinton * critical when starting up the debugger on large programs. 629672Slinton */ 639672Slinton 649672Slinton public Name identname(s, isallocated) 659672Slinton String s; 669672Slinton Boolean isallocated; 679672Slinton { 689672Slinton register unsigned h; 699672Slinton register Char *p, *q; 709672Slinton register Name n; 719672Slinton register Integer len; 729672Slinton Namepool newpool; 739672Slinton 749672Slinton h = 0; 759672Slinton for (p = s; *p != '\0'; p++) { 769672Slinton h = (h << 1) ^ (*p); 779672Slinton } 789672Slinton h = h mod HASHTABLESIZE; 799672Slinton len = p - s; 809672Slinton n = nametable[h]; 819672Slinton while (n != nil) { 829672Slinton p = s; 839672Slinton q = n->identifier; 849672Slinton for (;;) { 859672Slinton if (*p != *q) { 869672Slinton goto nomatch; 879672Slinton } else if (*p == '\0') { 889672Slinton goto match; 899672Slinton } 909672Slinton ++p; 919672Slinton ++q; 929672Slinton } 939672Slinton nomatch: 949672Slinton n = n->chain; 959672Slinton } 969672Slinton 979672Slinton /* 989672Slinton * Now we know that name hasn't been found (otherwise we'd have jumped 999672Slinton * down to match), so we allocate a name, store the identifier, and 1009672Slinton * enter it in the hash table. 1019672Slinton */ 1029672Slinton if (nleft <= 0) { 1039672Slinton newpool = new(Namepool); 104*11103Slinton bzero(newpool, sizeof(newpool)); 1059672Slinton newpool->prevpool = namepool; 1069672Slinton namepool = newpool; 1079672Slinton nleft = CHUNKSIZE; 1089672Slinton } 1099672Slinton --nleft; 1109672Slinton n = &(namepool->name[nleft]); 1119672Slinton if (isallocated) { 1129672Slinton n->identifier = s; 1139672Slinton } else { 1149672Slinton n->identifier = newarr(char, len + 1); 1159672Slinton p = s; 1169672Slinton q = n->identifier; 1179672Slinton while (*p != '\0') { 1189672Slinton *q++ = *p++; 1199672Slinton } 1209672Slinton *q = '\0'; 1219672Slinton } 1229672Slinton n->chain = nametable[h]; 1239672Slinton nametable[h] = n; 1249672Slinton 1259672Slinton /* 1269672Slinton * The two possibilities (name known versus unknown) rejoin. 1279672Slinton */ 1289672Slinton match: 1299672Slinton return n; 1309672Slinton } 1319672Slinton 1329672Slinton /* 1339672Slinton * Return the identifier associated with a name. 1349672Slinton * 1359672Slinton * Currently compiled inline. 1369672Slinton * 1379672Slinton * 1389672Slinton * public String ident(n) 1399672Slinton Name n; 1409672Slinton { 1419672Slinton return (n == nil) ? "(noname)" : n->identifier; 1429672Slinton } 1439672Slinton * 1449672Slinton */ 1459672Slinton 1469672Slinton /* 1479672Slinton * Deallocate the name table. 1489672Slinton */ 1499672Slinton 1509672Slinton public names_free() 1519672Slinton { 1529672Slinton register int i; 1539672Slinton register Name n, next; 1549672Slinton 1559672Slinton for (i = 0; i < HASHTABLESIZE; i++) { 1569672Slinton n = nametable[i]; 1579672Slinton while (n != nil) { 1589672Slinton next = n->chain; 1599672Slinton dispose(n); 1609672Slinton n = next; 1619672Slinton } 1629672Slinton nametable[i] = nil; 1639672Slinton } 1649672Slinton namepool = nil; 1659672Slinton nleft = 0; 1669672Slinton } 167