xref: /csrg-svn/old/dbx/names.c (revision 18225)
19672Slinton /* Copyright (c) 1982 Regents of the University of California */
29672Slinton 
3*18225Slinton static	char sccsid[] = "@(#)names.c	1.5 (Berkeley) 03/01/85";
49672Slinton 
5*18225Slinton static char rcsid[] = "$Header: names.c,v 1.4 84/12/26 10:40:47 linton Exp $";
6*18225Slinton 
79672Slinton /*
89672Slinton  * Name are the internal representation for identifiers.
99672Slinton  *
109672Slinton  * A hash table is used to map identifiers to names.
119672Slinton  */
129672Slinton 
139672Slinton #include "defs.h"
149672Slinton #include "names.h"
159672Slinton 
169672Slinton #ifndef public
179672Slinton typedef struct Name *Name;
189672Slinton 
199672Slinton /*
209672Slinton  * Inline (for speed) function to return the identifier (string)
219672Slinton  * associated with a name.  Because C cannot support both inlines
229672Slinton  * and data hiding at the same time, the Name structure must be
239672Slinton  * publicly visible.  It is not used explicitly, however, outside of this file.
249672Slinton  */
259672Slinton 
269672Slinton struct Name {
279672Slinton     char *identifier;
289672Slinton     Name chain;
299672Slinton };
309672Slinton 
319672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier)
329672Slinton #endif
339672Slinton 
349672Slinton #define HASHTABLESIZE 2997
359672Slinton 
369672Slinton private Name nametable[HASHTABLESIZE];
379672Slinton 
389672Slinton /*
399672Slinton  * Names are allocated in large chunks to avoid calls to malloc
409672Slinton  * and to cluster names in memory so that tracing hash chains
419672Slinton  * doesn't cause many a page fault.
429672Slinton  */
439672Slinton 
4411103Slinton #define CHUNKSIZE 200
459672Slinton 
469672Slinton typedef struct Namepool {
479672Slinton     struct Name name[CHUNKSIZE];
489672Slinton     struct Namepool *prevpool;
499672Slinton } *Namepool;
509672Slinton 
519672Slinton private Namepool namepool = nil;
529672Slinton private Integer nleft = 0;
539672Slinton 
549672Slinton /*
559672Slinton  * Given an identifier, convert it to a name.
569672Slinton  * If it's not in the hash table, then put it there.
579672Slinton  *
589672Slinton  * The second argument specifies whether the string should be copied
599672Slinton  * into newly allocated space if not found.
609672Slinton  *
619672Slinton  * Pardon my use of goto's, but it seemed more efficient and less convoluted
629672Slinton  * than adding a collection of boolean variables.  This routine is time
639672Slinton  * critical when starting up the debugger on large programs.
649672Slinton  */
659672Slinton 
669672Slinton public Name identname(s, isallocated)
679672Slinton String s;
689672Slinton Boolean isallocated;
699672Slinton {
709672Slinton     register unsigned h;
719672Slinton     register Char *p, *q;
729672Slinton     register Name n;
739672Slinton     register Integer len;
749672Slinton     Namepool newpool;
759672Slinton 
769672Slinton     h = 0;
779672Slinton     for (p = s; *p != '\0'; p++) {
789672Slinton 	h = (h << 1) ^ (*p);
799672Slinton     }
809672Slinton     h = h mod HASHTABLESIZE;
819672Slinton     len = p - s;
829672Slinton     n = nametable[h];
839672Slinton     while (n != nil) {
849672Slinton 	p = s;
859672Slinton 	q = n->identifier;
869672Slinton 	for (;;) {
879672Slinton 	    if (*p != *q) {
889672Slinton 		goto nomatch;
899672Slinton 	    } else if (*p == '\0') {
909672Slinton 		goto match;
919672Slinton 	    }
929672Slinton 	    ++p;
939672Slinton 	    ++q;
949672Slinton 	}
959672Slinton     nomatch:
969672Slinton 	n = n->chain;
979672Slinton     }
989672Slinton 
999672Slinton     /*
1009672Slinton      * Now we know that name hasn't been found (otherwise we'd have jumped
1019672Slinton      * down to match), so we allocate a name, store the identifier, and
1029672Slinton      * enter it in the hash table.
1039672Slinton      */
1049672Slinton     if (nleft <= 0) {
1059672Slinton 	newpool = new(Namepool);
10611103Slinton 	bzero(newpool, sizeof(newpool));
1079672Slinton 	newpool->prevpool = namepool;
1089672Slinton 	namepool = newpool;
1099672Slinton 	nleft = CHUNKSIZE;
1109672Slinton     }
1119672Slinton     --nleft;
1129672Slinton     n = &(namepool->name[nleft]);
1139672Slinton     if (isallocated) {
1149672Slinton 	n->identifier = s;
1159672Slinton     } else {
1169672Slinton 	n->identifier = newarr(char, len + 1);
1179672Slinton 	p = s;
1189672Slinton 	q = n->identifier;
1199672Slinton 	while (*p != '\0') {
1209672Slinton 	    *q++ = *p++;
1219672Slinton 	}
1229672Slinton 	*q = '\0';
1239672Slinton     }
1249672Slinton     n->chain = nametable[h];
1259672Slinton     nametable[h] = n;
1269672Slinton 
1279672Slinton     /*
1289672Slinton      * The two possibilities (name known versus unknown) rejoin.
1299672Slinton      */
1309672Slinton match:
1319672Slinton     return n;
1329672Slinton }
1339672Slinton 
1349672Slinton /*
1359672Slinton  * Deallocate the name table.
1369672Slinton  */
1379672Slinton 
1389672Slinton public names_free()
1399672Slinton {
140*18225Slinton     Namepool n, m;
141*18225Slinton     register integer i;
1429672Slinton 
143*18225Slinton     n = namepool;
144*18225Slinton     while (n != nil) {
145*18225Slinton 	m = n->prevpool;
146*18225Slinton 	dispose(n);
147*18225Slinton 	n = m;
148*18225Slinton     }
1499672Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
1509672Slinton 	nametable[i] = nil;
1519672Slinton     }
1529672Slinton     namepool = nil;
1539672Slinton     nleft = 0;
1549672Slinton }
155