|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)names.c 5.2 (Berkeley) 1/12/88"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: names.c,v 1.2 87/03/26 20:16:59 donn Exp $"; ! 12: ! 13: /* ! 14: * Name are the internal representation for identifiers. ! 15: * ! 16: * A hash table is used to map identifiers to names. ! 17: */ ! 18: ! 19: #include "defs.h" ! 20: #include "names.h" ! 21: ! 22: #ifndef public ! 23: typedef struct Name *Name; ! 24: ! 25: /* ! 26: * Inline (for speed) function to return the identifier (string) ! 27: * associated with a name. Because C cannot support both inlines ! 28: * and data hiding at the same time, the Name structure must be ! 29: * publicly visible. It is not used explicitly, however, outside of this file. ! 30: */ ! 31: ! 32: struct Name { ! 33: char *identifier; ! 34: Name chain; ! 35: }; ! 36: ! 37: #define ident(n) ((n == nil) ? "(noname)" : n->identifier) ! 38: #endif ! 39: ! 40: /* ! 41: * The hash table is a power of two, in order to make hashing faster. ! 42: * Using a non-prime is ok since we use chaining instead of re-hashing. ! 43: */ ! 44: ! 45: #define HASHTABLESIZE 8192 ! 46: ! 47: private Name nametable[HASHTABLESIZE]; ! 48: ! 49: /* ! 50: * Names are allocated in large chunks to avoid calls to malloc ! 51: * and to cluster names in memory so that tracing hash chains ! 52: * doesn't cause many a page fault. ! 53: */ ! 54: ! 55: #define CHUNKSIZE 1000 ! 56: ! 57: typedef struct Namepool { ! 58: struct Name name[CHUNKSIZE]; ! 59: struct Namepool *prevpool; ! 60: } *Namepool; ! 61: ! 62: private Namepool namepool = nil; ! 63: private Integer nleft = 0; ! 64: ! 65: /* ! 66: * Given an identifier, convert it to a name. ! 67: * If it's not in the hash table, then put it there. ! 68: * ! 69: * The second argument specifies whether the string should be copied ! 70: * into newly allocated space if not found. ! 71: * ! 72: * This routine is time critical when starting up the debugger ! 73: * on large programs. ! 74: */ ! 75: ! 76: public Name identname(s, isallocated) ! 77: String s; ! 78: Boolean isallocated; ! 79: { ! 80: register unsigned h; ! 81: register char *p, *q; ! 82: register Name n, *np; ! 83: Namepool newpool; ! 84: ! 85: h = 0; ! 86: for (p = s; *p != '\0'; p++) { ! 87: h = (h << 1) ^ (*p); ! 88: } ! 89: h &= (HASHTABLESIZE-1); ! 90: np = &nametable[h]; ! 91: n = *np; ! 92: while (n != nil) { ! 93: p = s; ! 94: q = n->identifier; ! 95: while (*p == *q) { ! 96: if (*p == '\0') { ! 97: return n; ! 98: } ! 99: ++p; ! 100: ++q; ! 101: } ! 102: n = n->chain; ! 103: } ! 104: ! 105: /* ! 106: * Now we know that name hasn't been found, ! 107: * so we allocate a name, store the identifier, and ! 108: * enter it in the hash table. ! 109: */ ! 110: if (nleft <= 0) { ! 111: newpool = new(Namepool); ! 112: newpool->prevpool = namepool; ! 113: namepool = newpool; ! 114: nleft = CHUNKSIZE; ! 115: } ! 116: --nleft; ! 117: n = &(namepool->name[nleft]); ! 118: if (isallocated) { ! 119: n->identifier = s; ! 120: } else { ! 121: /* this case doesn't happen very often */ ! 122: n->identifier = newarr(char, strlen(s) + 1); ! 123: p = s; ! 124: q = n->identifier; ! 125: while (*p != '\0') { ! 126: *q++ = *p++; ! 127: } ! 128: *q = '\0'; ! 129: } ! 130: n->chain = *np; ! 131: *np = n; ! 132: return n; ! 133: } ! 134: ! 135: /* ! 136: * Deallocate the name table. ! 137: */ ! 138: ! 139: public names_free() ! 140: { ! 141: Namepool n, m; ! 142: register integer i; ! 143: ! 144: n = namepool; ! 145: while (n != nil) { ! 146: m = n->prevpool; ! 147: dispose(n); ! 148: n = m; ! 149: } ! 150: for (i = 0; i < HASHTABLESIZE; i++) { ! 151: nametable[i] = nil; ! 152: } ! 153: namepool = nil; ! 154: nleft = 0; ! 155: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.