121614Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621614Sdist */ 179672Slinton 1821614Sdist #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)names.c 5.3 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 219672Slinton 229672Slinton /* 239672Slinton * Name are the internal representation for identifiers. 249672Slinton * 259672Slinton * A hash table is used to map identifiers to names. 269672Slinton */ 279672Slinton 289672Slinton #include "defs.h" 299672Slinton #include "names.h" 309672Slinton 319672Slinton #ifndef public 329672Slinton typedef struct Name *Name; 339672Slinton 349672Slinton /* 359672Slinton * Inline (for speed) function to return the identifier (string) 369672Slinton * associated with a name. Because C cannot support both inlines 379672Slinton * and data hiding at the same time, the Name structure must be 389672Slinton * publicly visible. It is not used explicitly, however, outside of this file. 399672Slinton */ 409672Slinton 419672Slinton struct Name { 429672Slinton char *identifier; 439672Slinton Name chain; 449672Slinton }; 459672Slinton 469672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier) 479672Slinton #endif 489672Slinton 4933327Sdonn /* 5033327Sdonn * The hash table is a power of two, in order to make hashing faster. 5133327Sdonn * Using a non-prime is ok since we use chaining instead of re-hashing. 5233327Sdonn */ 539672Slinton 5433327Sdonn #define HASHTABLESIZE 8192 5533327Sdonn 569672Slinton private Name nametable[HASHTABLESIZE]; 579672Slinton 589672Slinton /* 599672Slinton * Names are allocated in large chunks to avoid calls to malloc 609672Slinton * and to cluster names in memory so that tracing hash chains 619672Slinton * doesn't cause many a page fault. 629672Slinton */ 639672Slinton 6433327Sdonn #define CHUNKSIZE 1000 659672Slinton 669672Slinton typedef struct Namepool { 679672Slinton struct Name name[CHUNKSIZE]; 689672Slinton struct Namepool *prevpool; 699672Slinton } *Namepool; 709672Slinton 719672Slinton private Namepool namepool = nil; 729672Slinton private Integer nleft = 0; 739672Slinton 749672Slinton /* 759672Slinton * Given an identifier, convert it to a name. 769672Slinton * If it's not in the hash table, then put it there. 779672Slinton * 789672Slinton * The second argument specifies whether the string should be copied 799672Slinton * into newly allocated space if not found. 809672Slinton * 8133327Sdonn * This routine is time critical when starting up the debugger 8233327Sdonn * on large programs. 839672Slinton */ 849672Slinton 859672Slinton public Name identname(s, isallocated) 869672Slinton String s; 879672Slinton Boolean isallocated; 889672Slinton { 899672Slinton register unsigned h; 9033327Sdonn register char *p, *q; 9133327Sdonn register Name n, *np; 929672Slinton Namepool newpool; 939672Slinton 949672Slinton h = 0; 959672Slinton for (p = s; *p != '\0'; p++) { 969672Slinton h = (h << 1) ^ (*p); 979672Slinton } 9833327Sdonn h &= (HASHTABLESIZE-1); 9933327Sdonn np = &nametable[h]; 10033327Sdonn n = *np; 1019672Slinton while (n != nil) { 1029672Slinton p = s; 1039672Slinton q = n->identifier; 10433327Sdonn while (*p == *q) { 10533327Sdonn if (*p == '\0') { 10633327Sdonn return n; 1079672Slinton } 1089672Slinton ++p; 1099672Slinton ++q; 1109672Slinton } 1119672Slinton n = n->chain; 1129672Slinton } 1139672Slinton 1149672Slinton /* 11533327Sdonn * Now we know that name hasn't been found, 11633327Sdonn * so we allocate a name, store the identifier, and 1179672Slinton * enter it in the hash table. 1189672Slinton */ 1199672Slinton if (nleft <= 0) { 1209672Slinton newpool = new(Namepool); 1219672Slinton newpool->prevpool = namepool; 1229672Slinton namepool = newpool; 1239672Slinton nleft = CHUNKSIZE; 1249672Slinton } 1259672Slinton --nleft; 1269672Slinton n = &(namepool->name[nleft]); 1279672Slinton if (isallocated) { 1289672Slinton n->identifier = s; 1299672Slinton } else { 13033327Sdonn /* this case doesn't happen very often */ 13133327Sdonn n->identifier = newarr(char, strlen(s) + 1); 1329672Slinton p = s; 1339672Slinton q = n->identifier; 1349672Slinton while (*p != '\0') { 1359672Slinton *q++ = *p++; 1369672Slinton } 1379672Slinton *q = '\0'; 1389672Slinton } 13933327Sdonn n->chain = *np; 14033327Sdonn *np = n; 1419672Slinton return n; 1429672Slinton } 1439672Slinton 1449672Slinton /* 1459672Slinton * Deallocate the name table. 1469672Slinton */ 1479672Slinton 1489672Slinton public names_free() 1499672Slinton { 15018225Slinton Namepool n, m; 15118225Slinton register integer i; 1529672Slinton 15318225Slinton n = namepool; 15418225Slinton while (n != nil) { 15518225Slinton m = n->prevpool; 15618225Slinton dispose(n); 15718225Slinton n = m; 15818225Slinton } 1599672Slinton for (i = 0; i < HASHTABLESIZE; i++) { 1609672Slinton nametable[i] = nil; 1619672Slinton } 1629672Slinton namepool = nil; 1639672Slinton nleft = 0; 1649672Slinton } 165