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