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