xref: /csrg-svn/old/dbx/names.c (revision 42683)
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