|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that: (1) source distributions retain this entire copyright ! 7: * notice and comment, and (2) distributions including binaries display ! 8: * the following acknowledgement: ``This product includes software ! 9: * developed by the University of California, Berkeley and its contributors'' ! 10: * in the documentation or other materials provided with the distribution ! 11: * and in all advertising materials mentioning features or use of this ! 12: * software. Neither the name of the University nor the names of its ! 13: * contributors may be used to endorse or promote products derived ! 14: * from this software without specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: static char sccsid[] = "@(#)names.c 5.4 (Berkeley) 6/1/90"; ! 22: #endif /* not lint */ ! 23: ! 24: /* ! 25: * Name are the internal representation for identifiers. ! 26: * ! 27: * A hash table is used to map identifiers to names. ! 28: */ ! 29: ! 30: #include "defs.h" ! 31: #include "names.h" ! 32: ! 33: #ifndef public ! 34: typedef struct Name *Name; ! 35: ! 36: /* ! 37: * Inline (for speed) function to return the identifier (string) ! 38: * associated with a name. Because C cannot support both inlines ! 39: * and data hiding at the same time, the Name structure must be ! 40: * publicly visible. It is not used explicitly, however, outside of this file. ! 41: */ ! 42: ! 43: struct Name { ! 44: char *identifier; ! 45: Name chain; ! 46: }; ! 47: ! 48: #define ident(n) ((n == nil) ? "(noname)" : n->identifier) ! 49: #endif ! 50: ! 51: /* ! 52: * The hash table is a power of two, in order to make hashing faster. ! 53: * Using a non-prime is ok since we use chaining instead of re-hashing. ! 54: */ ! 55: ! 56: #define HASHTABLESIZE 8192 ! 57: ! 58: private Name nametable[HASHTABLESIZE]; ! 59: ! 60: /* ! 61: * Names are allocated in large chunks to avoid calls to malloc ! 62: * and to cluster names in memory so that tracing hash chains ! 63: * doesn't cause many a page fault. ! 64: */ ! 65: ! 66: #define CHUNKSIZE 1000 ! 67: ! 68: typedef struct Namepool { ! 69: struct Name name[CHUNKSIZE]; ! 70: struct Namepool *prevpool; ! 71: } *Namepool; ! 72: ! 73: private Namepool namepool = nil; ! 74: private Integer nleft = 0; ! 75: ! 76: /* ! 77: * Given an identifier, convert it to a name. ! 78: * If it's not in the hash table, then put it there. ! 79: * ! 80: * The second argument specifies whether the string should be copied ! 81: * into newly allocated space if not found. ! 82: * ! 83: * This routine is time critical when starting up the debugger ! 84: * on large programs. ! 85: */ ! 86: ! 87: public Name identname(s, isallocated) ! 88: String s; ! 89: Boolean isallocated; ! 90: { ! 91: register unsigned h; ! 92: register char *p, *q; ! 93: register Name n, *np; ! 94: Namepool newpool; ! 95: ! 96: h = 0; ! 97: for (p = s; *p != '\0'; p++) { ! 98: h = (h << 1) ^ (*p); ! 99: } ! 100: h &= (HASHTABLESIZE-1); ! 101: np = &nametable[h]; ! 102: n = *np; ! 103: while (n != nil) { ! 104: p = s; ! 105: q = n->identifier; ! 106: while (*p == *q) { ! 107: if (*p == '\0') { ! 108: return n; ! 109: } ! 110: ++p; ! 111: ++q; ! 112: } ! 113: n = n->chain; ! 114: } ! 115: ! 116: /* ! 117: * Now we know that name hasn't been found, ! 118: * so we allocate a name, store the identifier, and ! 119: * enter it in the hash table. ! 120: */ ! 121: if (nleft <= 0) { ! 122: newpool = new(Namepool); ! 123: newpool->prevpool = namepool; ! 124: namepool = newpool; ! 125: nleft = CHUNKSIZE; ! 126: } ! 127: --nleft; ! 128: n = &(namepool->name[nleft]); ! 129: if (isallocated) { ! 130: n->identifier = s; ! 131: } else { ! 132: /* this case doesn't happen very often */ ! 133: n->identifier = newarr(char, strlen(s) + 1); ! 134: p = s; ! 135: q = n->identifier; ! 136: while (*p != '\0') { ! 137: *q++ = *p++; ! 138: } ! 139: *q = '\0'; ! 140: } ! 141: n->chain = *np; ! 142: *np = n; ! 143: return n; ! 144: } ! 145: ! 146: /* ! 147: * Deallocate the name table. ! 148: */ ! 149: ! 150: public names_free() ! 151: { ! 152: Namepool n, m; ! 153: register integer i; ! 154: ! 155: n = namepool; ! 156: while (n != nil) { ! 157: m = n->prevpool; ! 158: dispose(n); ! 159: n = m; ! 160: } ! 161: for (i = 0; i < HASHTABLESIZE; i++) { ! 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.