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