1*9672Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9672Slinton 3*9672Slinton static char sccsid[] = "@(#)@(#)names.c 1.1 12/15/82"; 4*9672Slinton 5*9672Slinton /* 6*9672Slinton * Name are the internal representation for identifiers. 7*9672Slinton * 8*9672Slinton * A hash table is used to map identifiers to names. 9*9672Slinton */ 10*9672Slinton 11*9672Slinton #include "defs.h" 12*9672Slinton #include "names.h" 13*9672Slinton 14*9672Slinton #ifndef public 15*9672Slinton typedef struct Name *Name; 16*9672Slinton 17*9672Slinton /* 18*9672Slinton * Inline (for speed) function to return the identifier (string) 19*9672Slinton * associated with a name. Because C cannot support both inlines 20*9672Slinton * and data hiding at the same time, the Name structure must be 21*9672Slinton * publicly visible. It is not used explicitly, however, outside of this file. 22*9672Slinton */ 23*9672Slinton 24*9672Slinton struct Name { 25*9672Slinton char *identifier; 26*9672Slinton Name chain; 27*9672Slinton }; 28*9672Slinton 29*9672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier) 30*9672Slinton #endif 31*9672Slinton 32*9672Slinton #define HASHTABLESIZE 2997 33*9672Slinton 34*9672Slinton private Name nametable[HASHTABLESIZE]; 35*9672Slinton 36*9672Slinton /* 37*9672Slinton * Names are allocated in large chunks to avoid calls to malloc 38*9672Slinton * and to cluster names in memory so that tracing hash chains 39*9672Slinton * doesn't cause many a page fault. 40*9672Slinton */ 41*9672Slinton 42*9672Slinton #define CHUNKSIZE 1000 43*9672Slinton 44*9672Slinton typedef struct Namepool { 45*9672Slinton struct Name name[CHUNKSIZE]; 46*9672Slinton struct Namepool *prevpool; 47*9672Slinton } *Namepool; 48*9672Slinton 49*9672Slinton private Namepool namepool = nil; 50*9672Slinton private Integer nleft = 0; 51*9672Slinton private struct Namepool zeropool; 52*9672Slinton 53*9672Slinton /* 54*9672Slinton * Given an identifier, convert it to a name. 55*9672Slinton * If it's not in the hash table, then put it there. 56*9672Slinton * 57*9672Slinton * The second argument specifies whether the string should be copied 58*9672Slinton * into newly allocated space if not found. 59*9672Slinton * 60*9672Slinton * Pardon my use of goto's, but it seemed more efficient and less convoluted 61*9672Slinton * than adding a collection of boolean variables. This routine is time 62*9672Slinton * critical when starting up the debugger on large programs. 63*9672Slinton */ 64*9672Slinton 65*9672Slinton public Name identname(s, isallocated) 66*9672Slinton String s; 67*9672Slinton Boolean isallocated; 68*9672Slinton { 69*9672Slinton register unsigned h; 70*9672Slinton register Char *p, *q; 71*9672Slinton register Name n; 72*9672Slinton register Integer len; 73*9672Slinton Namepool newpool; 74*9672Slinton 75*9672Slinton h = 0; 76*9672Slinton for (p = s; *p != '\0'; p++) { 77*9672Slinton h = (h << 1) ^ (*p); 78*9672Slinton } 79*9672Slinton h = h mod HASHTABLESIZE; 80*9672Slinton len = p - s; 81*9672Slinton n = nametable[h]; 82*9672Slinton while (n != nil) { 83*9672Slinton p = s; 84*9672Slinton q = n->identifier; 85*9672Slinton for (;;) { 86*9672Slinton if (*p != *q) { 87*9672Slinton goto nomatch; 88*9672Slinton } else if (*p == '\0') { 89*9672Slinton goto match; 90*9672Slinton } 91*9672Slinton ++p; 92*9672Slinton ++q; 93*9672Slinton } 94*9672Slinton nomatch: 95*9672Slinton n = n->chain; 96*9672Slinton } 97*9672Slinton 98*9672Slinton /* 99*9672Slinton * Now we know that name hasn't been found (otherwise we'd have jumped 100*9672Slinton * down to match), so we allocate a name, store the identifier, and 101*9672Slinton * enter it in the hash table. 102*9672Slinton */ 103*9672Slinton if (nleft <= 0) { 104*9672Slinton newpool = new(Namepool); 105*9672Slinton *newpool = zeropool; 106*9672Slinton newpool->prevpool = namepool; 107*9672Slinton namepool = newpool; 108*9672Slinton nleft = CHUNKSIZE; 109*9672Slinton } 110*9672Slinton --nleft; 111*9672Slinton n = &(namepool->name[nleft]); 112*9672Slinton if (isallocated) { 113*9672Slinton n->identifier = s; 114*9672Slinton } else { 115*9672Slinton n->identifier = newarr(char, len + 1); 116*9672Slinton p = s; 117*9672Slinton q = n->identifier; 118*9672Slinton while (*p != '\0') { 119*9672Slinton *q++ = *p++; 120*9672Slinton } 121*9672Slinton *q = '\0'; 122*9672Slinton } 123*9672Slinton n->chain = nametable[h]; 124*9672Slinton nametable[h] = n; 125*9672Slinton 126*9672Slinton /* 127*9672Slinton * The two possibilities (name known versus unknown) rejoin. 128*9672Slinton */ 129*9672Slinton match: 130*9672Slinton return n; 131*9672Slinton } 132*9672Slinton 133*9672Slinton /* 134*9672Slinton * Return the identifier associated with a name. 135*9672Slinton * 136*9672Slinton * Currently compiled inline. 137*9672Slinton * 138*9672Slinton * 139*9672Slinton * public String ident(n) 140*9672Slinton Name n; 141*9672Slinton { 142*9672Slinton return (n == nil) ? "(noname)" : n->identifier; 143*9672Slinton } 144*9672Slinton * 145*9672Slinton */ 146*9672Slinton 147*9672Slinton /* 148*9672Slinton * Deallocate the name table. 149*9672Slinton */ 150*9672Slinton 151*9672Slinton public names_free() 152*9672Slinton { 153*9672Slinton register int i; 154*9672Slinton register Name n, next; 155*9672Slinton 156*9672Slinton for (i = 0; i < HASHTABLESIZE; i++) { 157*9672Slinton n = nametable[i]; 158*9672Slinton while (n != nil) { 159*9672Slinton next = n->chain; 160*9672Slinton dispose(n); 161*9672Slinton n = next; 162*9672Slinton } 163*9672Slinton nametable[i] = nil; 164*9672Slinton } 165*9672Slinton namepool = nil; 166*9672Slinton nleft = 0; 167*9672Slinton } 168