121614Sdist /*
238105Sbostic * Copyright (c) 1983 The Regents of the University of California.
338105Sbostic * All rights reserved.
438105Sbostic *
5*42683Sbostic * %sccs.include.redist.c%
621614Sdist */
79672Slinton
821614Sdist #ifndef lint
9*42683Sbostic static char sccsid[] = "@(#)names.c 5.4 (Berkeley) 06/01/90";
1038105Sbostic #endif /* not lint */
119672Slinton
129672Slinton /*
139672Slinton * Name are the internal representation for identifiers.
149672Slinton *
159672Slinton * A hash table is used to map identifiers to names.
169672Slinton */
179672Slinton
189672Slinton #include "defs.h"
199672Slinton #include "names.h"
209672Slinton
219672Slinton #ifndef public
229672Slinton typedef struct Name *Name;
239672Slinton
249672Slinton /*
259672Slinton * Inline (for speed) function to return the identifier (string)
269672Slinton * associated with a name. Because C cannot support both inlines
279672Slinton * and data hiding at the same time, the Name structure must be
289672Slinton * publicly visible. It is not used explicitly, however, outside of this file.
299672Slinton */
309672Slinton
319672Slinton struct Name {
329672Slinton char *identifier;
339672Slinton Name chain;
349672Slinton };
359672Slinton
369672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier)
379672Slinton #endif
389672Slinton
3933327Sdonn /*
4033327Sdonn * The hash table is a power of two, in order to make hashing faster.
4133327Sdonn * Using a non-prime is ok since we use chaining instead of re-hashing.
4233327Sdonn */
439672Slinton
4433327Sdonn #define HASHTABLESIZE 8192
4533327Sdonn
469672Slinton private Name nametable[HASHTABLESIZE];
479672Slinton
489672Slinton /*
499672Slinton * Names are allocated in large chunks to avoid calls to malloc
509672Slinton * and to cluster names in memory so that tracing hash chains
519672Slinton * doesn't cause many a page fault.
529672Slinton */
539672Slinton
5433327Sdonn #define CHUNKSIZE 1000
559672Slinton
569672Slinton typedef struct Namepool {
579672Slinton struct Name name[CHUNKSIZE];
589672Slinton struct Namepool *prevpool;
599672Slinton } *Namepool;
609672Slinton
619672Slinton private Namepool namepool = nil;
629672Slinton private Integer nleft = 0;
639672Slinton
649672Slinton /*
659672Slinton * Given an identifier, convert it to a name.
669672Slinton * If it's not in the hash table, then put it there.
679672Slinton *
689672Slinton * The second argument specifies whether the string should be copied
699672Slinton * into newly allocated space if not found.
709672Slinton *
7133327Sdonn * This routine is time critical when starting up the debugger
7233327Sdonn * on large programs.
739672Slinton */
749672Slinton
identname(s,isallocated)759672Slinton public Name identname(s, isallocated)
769672Slinton String s;
779672Slinton Boolean isallocated;
789672Slinton {
799672Slinton register unsigned h;
8033327Sdonn register char *p, *q;
8133327Sdonn register Name n, *np;
829672Slinton Namepool newpool;
839672Slinton
849672Slinton h = 0;
859672Slinton for (p = s; *p != '\0'; p++) {
869672Slinton h = (h << 1) ^ (*p);
879672Slinton }
8833327Sdonn h &= (HASHTABLESIZE-1);
8933327Sdonn np = &nametable[h];
9033327Sdonn n = *np;
919672Slinton while (n != nil) {
929672Slinton p = s;
939672Slinton q = n->identifier;
9433327Sdonn while (*p == *q) {
9533327Sdonn if (*p == '\0') {
9633327Sdonn return n;
979672Slinton }
989672Slinton ++p;
999672Slinton ++q;
1009672Slinton }
1019672Slinton n = n->chain;
1029672Slinton }
1039672Slinton
1049672Slinton /*
10533327Sdonn * Now we know that name hasn't been found,
10633327Sdonn * so we allocate a name, store the identifier, and
1079672Slinton * enter it in the hash table.
1089672Slinton */
1099672Slinton if (nleft <= 0) {
1109672Slinton newpool = new(Namepool);
1119672Slinton newpool->prevpool = namepool;
1129672Slinton namepool = newpool;
1139672Slinton nleft = CHUNKSIZE;
1149672Slinton }
1159672Slinton --nleft;
1169672Slinton n = &(namepool->name[nleft]);
1179672Slinton if (isallocated) {
1189672Slinton n->identifier = s;
1199672Slinton } else {
12033327Sdonn /* this case doesn't happen very often */
12133327Sdonn n->identifier = newarr(char, strlen(s) + 1);
1229672Slinton p = s;
1239672Slinton q = n->identifier;
1249672Slinton while (*p != '\0') {
1259672Slinton *q++ = *p++;
1269672Slinton }
1279672Slinton *q = '\0';
1289672Slinton }
12933327Sdonn n->chain = *np;
13033327Sdonn *np = n;
1319672Slinton return n;
1329672Slinton }
1339672Slinton
1349672Slinton /*
1359672Slinton * Deallocate the name table.
1369672Slinton */
1379672Slinton
names_free()1389672Slinton public names_free()
1399672Slinton {
14018225Slinton Namepool n, m;
14118225Slinton register integer i;
1429672Slinton
14318225Slinton n = namepool;
14418225Slinton while (n != nil) {
14518225Slinton m = n->prevpool;
14618225Slinton dispose(n);
14718225Slinton n = m;
14818225Slinton }
1499672Slinton for (i = 0; i < HASHTABLESIZE; i++) {
1509672Slinton nametable[i] = nil;
1519672Slinton }
1529672Slinton namepool = nil;
1539672Slinton nleft = 0;
1549672Slinton }
155