1*21614Sdist /* 2*21614Sdist * Copyright (c) 1983 Regents of the University of California. 3*21614Sdist * All rights reserved. The Berkeley software License Agreement 4*21614Sdist * specifies the terms and conditions for redistribution. 5*21614Sdist */ 69672Slinton 7*21614Sdist #ifndef lint 8*21614Sdist static char sccsid[] = "@(#)names.c 5.1 (Berkeley) 05/31/85"; 9*21614Sdist #endif not lint 109672Slinton 1118225Slinton static char rcsid[] = "$Header: names.c,v 1.4 84/12/26 10:40:47 linton 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 409672Slinton #define HASHTABLESIZE 2997 419672Slinton 429672Slinton private Name nametable[HASHTABLESIZE]; 439672Slinton 449672Slinton /* 459672Slinton * Names are allocated in large chunks to avoid calls to malloc 469672Slinton * and to cluster names in memory so that tracing hash chains 479672Slinton * doesn't cause many a page fault. 489672Slinton */ 499672Slinton 5011103Slinton #define CHUNKSIZE 200 519672Slinton 529672Slinton typedef struct Namepool { 539672Slinton struct Name name[CHUNKSIZE]; 549672Slinton struct Namepool *prevpool; 559672Slinton } *Namepool; 569672Slinton 579672Slinton private Namepool namepool = nil; 589672Slinton private Integer nleft = 0; 599672Slinton 609672Slinton /* 619672Slinton * Given an identifier, convert it to a name. 629672Slinton * If it's not in the hash table, then put it there. 639672Slinton * 649672Slinton * The second argument specifies whether the string should be copied 659672Slinton * into newly allocated space if not found. 669672Slinton * 679672Slinton * Pardon my use of goto's, but it seemed more efficient and less convoluted 689672Slinton * than adding a collection of boolean variables. This routine is time 699672Slinton * critical when starting up the debugger on large programs. 709672Slinton */ 719672Slinton 729672Slinton public Name identname(s, isallocated) 739672Slinton String s; 749672Slinton Boolean isallocated; 759672Slinton { 769672Slinton register unsigned h; 779672Slinton register Char *p, *q; 789672Slinton register Name n; 799672Slinton register Integer len; 809672Slinton Namepool newpool; 819672Slinton 829672Slinton h = 0; 839672Slinton for (p = s; *p != '\0'; p++) { 849672Slinton h = (h << 1) ^ (*p); 859672Slinton } 869672Slinton h = h mod HASHTABLESIZE; 879672Slinton len = p - s; 889672Slinton n = nametable[h]; 899672Slinton while (n != nil) { 909672Slinton p = s; 919672Slinton q = n->identifier; 929672Slinton for (;;) { 939672Slinton if (*p != *q) { 949672Slinton goto nomatch; 959672Slinton } else if (*p == '\0') { 969672Slinton goto match; 979672Slinton } 989672Slinton ++p; 999672Slinton ++q; 1009672Slinton } 1019672Slinton nomatch: 1029672Slinton n = n->chain; 1039672Slinton } 1049672Slinton 1059672Slinton /* 1069672Slinton * Now we know that name hasn't been found (otherwise we'd have jumped 1079672Slinton * down to match), 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); 11211103Slinton bzero(newpool, sizeof(newpool)); 1139672Slinton newpool->prevpool = namepool; 1149672Slinton namepool = newpool; 1159672Slinton nleft = CHUNKSIZE; 1169672Slinton } 1179672Slinton --nleft; 1189672Slinton n = &(namepool->name[nleft]); 1199672Slinton if (isallocated) { 1209672Slinton n->identifier = s; 1219672Slinton } else { 1229672Slinton n->identifier = newarr(char, len + 1); 1239672Slinton p = s; 1249672Slinton q = n->identifier; 1259672Slinton while (*p != '\0') { 1269672Slinton *q++ = *p++; 1279672Slinton } 1289672Slinton *q = '\0'; 1299672Slinton } 1309672Slinton n->chain = nametable[h]; 1319672Slinton nametable[h] = n; 1329672Slinton 1339672Slinton /* 1349672Slinton * The two possibilities (name known versus unknown) rejoin. 1359672Slinton */ 1369672Slinton match: 1379672Slinton return n; 1389672Slinton } 1399672Slinton 1409672Slinton /* 1419672Slinton * Deallocate the name table. 1429672Slinton */ 1439672Slinton 1449672Slinton public names_free() 1459672Slinton { 14618225Slinton Namepool n, m; 14718225Slinton register integer i; 1489672Slinton 14918225Slinton n = namepool; 15018225Slinton while (n != nil) { 15118225Slinton m = n->prevpool; 15218225Slinton dispose(n); 15318225Slinton n = m; 15418225Slinton } 1559672Slinton for (i = 0; i < HASHTABLESIZE; i++) { 1569672Slinton nametable[i] = nil; 1579672Slinton } 1589672Slinton namepool = nil; 1599672Slinton nleft = 0; 1609672Slinton } 161