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