121614Sdist /* 221614Sdist * Copyright (c) 1983 Regents of the University of California. 321614Sdist * All rights reserved. The Berkeley software License Agreement 421614Sdist * specifies the terms and conditions for redistribution. 521614Sdist */ 69672Slinton 721614Sdist #ifndef lint 8*33327Sdonn static char sccsid[] = "@(#)names.c 5.2 (Berkeley) 01/12/88"; 921614Sdist #endif not lint 109672Slinton 11*33327Sdonn static char rcsid[] = "$Header: names.c,v 1.2 87/03/26 20:16:59 donn Exp $"; 1218225Slinton 139672Slinton /* 149672Slinton * Name are the internal representation for identifiers. 159672Slinton * 169672Slinton * A hash table is used to map identifiers to names. 179672Slinton */ 189672Slinton 199672Slinton #include "defs.h" 209672Slinton #include "names.h" 219672Slinton 229672Slinton #ifndef public 239672Slinton typedef struct Name *Name; 249672Slinton 259672Slinton /* 269672Slinton * Inline (for speed) function to return the identifier (string) 279672Slinton * associated with a name. Because C cannot support both inlines 289672Slinton * and data hiding at the same time, the Name structure must be 299672Slinton * publicly visible. It is not used explicitly, however, outside of this file. 309672Slinton */ 319672Slinton 329672Slinton struct Name { 339672Slinton char *identifier; 349672Slinton Name chain; 359672Slinton }; 369672Slinton 379672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier) 389672Slinton #endif 399672Slinton 40*33327Sdonn /* 41*33327Sdonn * The hash table is a power of two, in order to make hashing faster. 42*33327Sdonn * Using a non-prime is ok since we use chaining instead of re-hashing. 43*33327Sdonn */ 449672Slinton 45*33327Sdonn #define HASHTABLESIZE 8192 46*33327Sdonn 479672Slinton private Name nametable[HASHTABLESIZE]; 489672Slinton 499672Slinton /* 509672Slinton * Names are allocated in large chunks to avoid calls to malloc 519672Slinton * and to cluster names in memory so that tracing hash chains 529672Slinton * doesn't cause many a page fault. 539672Slinton */ 549672Slinton 55*33327Sdonn #define CHUNKSIZE 1000 569672Slinton 579672Slinton typedef struct Namepool { 589672Slinton struct Name name[CHUNKSIZE]; 599672Slinton struct Namepool *prevpool; 609672Slinton } *Namepool; 619672Slinton 629672Slinton private Namepool namepool = nil; 639672Slinton private Integer nleft = 0; 649672Slinton 659672Slinton /* 669672Slinton * Given an identifier, convert it to a name. 679672Slinton * If it's not in the hash table, then put it there. 689672Slinton * 699672Slinton * The second argument specifies whether the string should be copied 709672Slinton * into newly allocated space if not found. 719672Slinton * 72*33327Sdonn * This routine is time critical when starting up the debugger 73*33327Sdonn * on large programs. 749672Slinton */ 759672Slinton 769672Slinton public Name identname(s, isallocated) 779672Slinton String s; 789672Slinton Boolean isallocated; 799672Slinton { 809672Slinton register unsigned h; 81*33327Sdonn register char *p, *q; 82*33327Sdonn register Name n, *np; 839672Slinton Namepool newpool; 849672Slinton 859672Slinton h = 0; 869672Slinton for (p = s; *p != '\0'; p++) { 879672Slinton h = (h << 1) ^ (*p); 889672Slinton } 89*33327Sdonn h &= (HASHTABLESIZE-1); 90*33327Sdonn np = &nametable[h]; 91*33327Sdonn n = *np; 929672Slinton while (n != nil) { 939672Slinton p = s; 949672Slinton q = n->identifier; 95*33327Sdonn while (*p == *q) { 96*33327Sdonn if (*p == '\0') { 97*33327Sdonn return n; 989672Slinton } 999672Slinton ++p; 1009672Slinton ++q; 1019672Slinton } 1029672Slinton n = n->chain; 1039672Slinton } 1049672Slinton 1059672Slinton /* 106*33327Sdonn * Now we know that name hasn't been found, 107*33327Sdonn * so we allocate a name, store the identifier, and 1089672Slinton * enter it in the hash table. 1099672Slinton */ 1109672Slinton if (nleft <= 0) { 1119672Slinton newpool = new(Namepool); 1129672Slinton newpool->prevpool = namepool; 1139672Slinton namepool = newpool; 1149672Slinton nleft = CHUNKSIZE; 1159672Slinton } 1169672Slinton --nleft; 1179672Slinton n = &(namepool->name[nleft]); 1189672Slinton if (isallocated) { 1199672Slinton n->identifier = s; 1209672Slinton } else { 121*33327Sdonn /* this case doesn't happen very often */ 122*33327Sdonn n->identifier = newarr(char, strlen(s) + 1); 1239672Slinton p = s; 1249672Slinton q = n->identifier; 1259672Slinton while (*p != '\0') { 1269672Slinton *q++ = *p++; 1279672Slinton } 1289672Slinton *q = '\0'; 1299672Slinton } 130*33327Sdonn n->chain = *np; 131*33327Sdonn *np = n; 1329672Slinton return n; 1339672Slinton } 1349672Slinton 1359672Slinton /* 1369672Slinton * Deallocate the name table. 1379672Slinton */ 1389672Slinton 1399672Slinton public names_free() 1409672Slinton { 14118225Slinton Namepool n, m; 14218225Slinton register integer i; 1439672Slinton 14418225Slinton n = namepool; 14518225Slinton while (n != nil) { 14618225Slinton m = n->prevpool; 14718225Slinton dispose(n); 14818225Slinton n = m; 14918225Slinton } 1509672Slinton for (i = 0; i < HASHTABLESIZE; i++) { 1519672Slinton nametable[i] = nil; 1529672Slinton } 1539672Slinton namepool = nil; 1549672Slinton nleft = 0; 1559672Slinton } 156