xref: /csrg-svn/old/dbx/names.c (revision 9672)
1*9672Slinton /* Copyright (c) 1982 Regents of the University of California */
2*9672Slinton 
3*9672Slinton static char sccsid[] = "@(#)@(#)names.c 1.1 12/15/82";
4*9672Slinton 
5*9672Slinton /*
6*9672Slinton  * Name are the internal representation for identifiers.
7*9672Slinton  *
8*9672Slinton  * A hash table is used to map identifiers to names.
9*9672Slinton  */
10*9672Slinton 
11*9672Slinton #include "defs.h"
12*9672Slinton #include "names.h"
13*9672Slinton 
14*9672Slinton #ifndef public
15*9672Slinton typedef struct Name *Name;
16*9672Slinton 
17*9672Slinton /*
18*9672Slinton  * Inline (for speed) function to return the identifier (string)
19*9672Slinton  * associated with a name.  Because C cannot support both inlines
20*9672Slinton  * and data hiding at the same time, the Name structure must be
21*9672Slinton  * publicly visible.  It is not used explicitly, however, outside of this file.
22*9672Slinton  */
23*9672Slinton 
24*9672Slinton struct Name {
25*9672Slinton     char *identifier;
26*9672Slinton     Name chain;
27*9672Slinton };
28*9672Slinton 
29*9672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier)
30*9672Slinton #endif
31*9672Slinton 
32*9672Slinton #define HASHTABLESIZE 2997
33*9672Slinton 
34*9672Slinton private Name nametable[HASHTABLESIZE];
35*9672Slinton 
36*9672Slinton /*
37*9672Slinton  * Names are allocated in large chunks to avoid calls to malloc
38*9672Slinton  * and to cluster names in memory so that tracing hash chains
39*9672Slinton  * doesn't cause many a page fault.
40*9672Slinton  */
41*9672Slinton 
42*9672Slinton #define CHUNKSIZE 1000
43*9672Slinton 
44*9672Slinton typedef struct Namepool {
45*9672Slinton     struct Name name[CHUNKSIZE];
46*9672Slinton     struct Namepool *prevpool;
47*9672Slinton } *Namepool;
48*9672Slinton 
49*9672Slinton private Namepool namepool = nil;
50*9672Slinton private Integer nleft = 0;
51*9672Slinton private struct Namepool zeropool;
52*9672Slinton 
53*9672Slinton /*
54*9672Slinton  * Given an identifier, convert it to a name.
55*9672Slinton  * If it's not in the hash table, then put it there.
56*9672Slinton  *
57*9672Slinton  * The second argument specifies whether the string should be copied
58*9672Slinton  * into newly allocated space if not found.
59*9672Slinton  *
60*9672Slinton  * Pardon my use of goto's, but it seemed more efficient and less convoluted
61*9672Slinton  * than adding a collection of boolean variables.  This routine is time
62*9672Slinton  * critical when starting up the debugger on large programs.
63*9672Slinton  */
64*9672Slinton 
65*9672Slinton public Name identname(s, isallocated)
66*9672Slinton String s;
67*9672Slinton Boolean isallocated;
68*9672Slinton {
69*9672Slinton     register unsigned h;
70*9672Slinton     register Char *p, *q;
71*9672Slinton     register Name n;
72*9672Slinton     register Integer len;
73*9672Slinton     Namepool newpool;
74*9672Slinton 
75*9672Slinton     h = 0;
76*9672Slinton     for (p = s; *p != '\0'; p++) {
77*9672Slinton 	h = (h << 1) ^ (*p);
78*9672Slinton     }
79*9672Slinton     h = h mod HASHTABLESIZE;
80*9672Slinton     len = p - s;
81*9672Slinton     n = nametable[h];
82*9672Slinton     while (n != nil) {
83*9672Slinton 	p = s;
84*9672Slinton 	q = n->identifier;
85*9672Slinton 	for (;;) {
86*9672Slinton 	    if (*p != *q) {
87*9672Slinton 		goto nomatch;
88*9672Slinton 	    } else if (*p == '\0') {
89*9672Slinton 		goto match;
90*9672Slinton 	    }
91*9672Slinton 	    ++p;
92*9672Slinton 	    ++q;
93*9672Slinton 	}
94*9672Slinton     nomatch:
95*9672Slinton 	n = n->chain;
96*9672Slinton     }
97*9672Slinton 
98*9672Slinton     /*
99*9672Slinton      * Now we know that name hasn't been found (otherwise we'd have jumped
100*9672Slinton      * down to match), so we allocate a name, store the identifier, and
101*9672Slinton      * enter it in the hash table.
102*9672Slinton      */
103*9672Slinton     if (nleft <= 0) {
104*9672Slinton 	newpool = new(Namepool);
105*9672Slinton 	*newpool = zeropool;
106*9672Slinton 	newpool->prevpool = namepool;
107*9672Slinton 	namepool = newpool;
108*9672Slinton 	nleft = CHUNKSIZE;
109*9672Slinton     }
110*9672Slinton     --nleft;
111*9672Slinton     n = &(namepool->name[nleft]);
112*9672Slinton     if (isallocated) {
113*9672Slinton 	n->identifier = s;
114*9672Slinton     } else {
115*9672Slinton 	n->identifier = newarr(char, len + 1);
116*9672Slinton 	p = s;
117*9672Slinton 	q = n->identifier;
118*9672Slinton 	while (*p != '\0') {
119*9672Slinton 	    *q++ = *p++;
120*9672Slinton 	}
121*9672Slinton 	*q = '\0';
122*9672Slinton     }
123*9672Slinton     n->chain = nametable[h];
124*9672Slinton     nametable[h] = n;
125*9672Slinton 
126*9672Slinton     /*
127*9672Slinton      * The two possibilities (name known versus unknown) rejoin.
128*9672Slinton      */
129*9672Slinton match:
130*9672Slinton     return n;
131*9672Slinton }
132*9672Slinton 
133*9672Slinton /*
134*9672Slinton  * Return the identifier associated with a name.
135*9672Slinton  *
136*9672Slinton  * Currently compiled inline.
137*9672Slinton  *
138*9672Slinton  *
139*9672Slinton  * public String ident(n)
140*9672Slinton Name n;
141*9672Slinton {
142*9672Slinton     return (n == nil) ? "(noname)" : n->identifier;
143*9672Slinton }
144*9672Slinton  *
145*9672Slinton  */
146*9672Slinton 
147*9672Slinton /*
148*9672Slinton  * Deallocate the name table.
149*9672Slinton  */
150*9672Slinton 
151*9672Slinton public names_free()
152*9672Slinton {
153*9672Slinton     register int i;
154*9672Slinton     register Name n, next;
155*9672Slinton 
156*9672Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
157*9672Slinton 	n = nametable[i];
158*9672Slinton 	while (n != nil) {
159*9672Slinton 	    next = n->chain;
160*9672Slinton 	    dispose(n);
161*9672Slinton 	    n = next;
162*9672Slinton 	}
163*9672Slinton 	nametable[i] = nil;
164*9672Slinton     }
165*9672Slinton     namepool = nil;
166*9672Slinton     nleft = 0;
167*9672Slinton }
168