xref: /csrg-svn/old/dbx/names.c (revision 21614)
1*21614Sdist /*
2*21614Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21614Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21614Sdist  * specifies the terms and conditions for redistribution.
5*21614Sdist  */
69672Slinton 
7*21614Sdist #ifndef lint
8*21614Sdist static char sccsid[] = "@(#)names.c	5.1 (Berkeley) 05/31/85";
9*21614Sdist #endif not lint
109672Slinton 
1118225Slinton static char rcsid[] = "$Header: names.c,v 1.4 84/12/26 10:40:47 linton 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 
409672Slinton #define HASHTABLESIZE 2997
419672Slinton 
429672Slinton private Name nametable[HASHTABLESIZE];
439672Slinton 
449672Slinton /*
459672Slinton  * Names are allocated in large chunks to avoid calls to malloc
469672Slinton  * and to cluster names in memory so that tracing hash chains
479672Slinton  * doesn't cause many a page fault.
489672Slinton  */
499672Slinton 
5011103Slinton #define CHUNKSIZE 200
519672Slinton 
529672Slinton typedef struct Namepool {
539672Slinton     struct Name name[CHUNKSIZE];
549672Slinton     struct Namepool *prevpool;
559672Slinton } *Namepool;
569672Slinton 
579672Slinton private Namepool namepool = nil;
589672Slinton private Integer nleft = 0;
599672Slinton 
609672Slinton /*
619672Slinton  * Given an identifier, convert it to a name.
629672Slinton  * If it's not in the hash table, then put it there.
639672Slinton  *
649672Slinton  * The second argument specifies whether the string should be copied
659672Slinton  * into newly allocated space if not found.
669672Slinton  *
679672Slinton  * Pardon my use of goto's, but it seemed more efficient and less convoluted
689672Slinton  * than adding a collection of boolean variables.  This routine is time
699672Slinton  * critical when starting up the debugger on large programs.
709672Slinton  */
719672Slinton 
729672Slinton public Name identname(s, isallocated)
739672Slinton String s;
749672Slinton Boolean isallocated;
759672Slinton {
769672Slinton     register unsigned h;
779672Slinton     register Char *p, *q;
789672Slinton     register Name n;
799672Slinton     register Integer len;
809672Slinton     Namepool newpool;
819672Slinton 
829672Slinton     h = 0;
839672Slinton     for (p = s; *p != '\0'; p++) {
849672Slinton 	h = (h << 1) ^ (*p);
859672Slinton     }
869672Slinton     h = h mod HASHTABLESIZE;
879672Slinton     len = p - s;
889672Slinton     n = nametable[h];
899672Slinton     while (n != nil) {
909672Slinton 	p = s;
919672Slinton 	q = n->identifier;
929672Slinton 	for (;;) {
939672Slinton 	    if (*p != *q) {
949672Slinton 		goto nomatch;
959672Slinton 	    } else if (*p == '\0') {
969672Slinton 		goto match;
979672Slinton 	    }
989672Slinton 	    ++p;
999672Slinton 	    ++q;
1009672Slinton 	}
1019672Slinton     nomatch:
1029672Slinton 	n = n->chain;
1039672Slinton     }
1049672Slinton 
1059672Slinton     /*
1069672Slinton      * Now we know that name hasn't been found (otherwise we'd have jumped
1079672Slinton      * down to match), 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);
11211103Slinton 	bzero(newpool, sizeof(newpool));
1139672Slinton 	newpool->prevpool = namepool;
1149672Slinton 	namepool = newpool;
1159672Slinton 	nleft = CHUNKSIZE;
1169672Slinton     }
1179672Slinton     --nleft;
1189672Slinton     n = &(namepool->name[nleft]);
1199672Slinton     if (isallocated) {
1209672Slinton 	n->identifier = s;
1219672Slinton     } else {
1229672Slinton 	n->identifier = newarr(char, len + 1);
1239672Slinton 	p = s;
1249672Slinton 	q = n->identifier;
1259672Slinton 	while (*p != '\0') {
1269672Slinton 	    *q++ = *p++;
1279672Slinton 	}
1289672Slinton 	*q = '\0';
1299672Slinton     }
1309672Slinton     n->chain = nametable[h];
1319672Slinton     nametable[h] = n;
1329672Slinton 
1339672Slinton     /*
1349672Slinton      * The two possibilities (name known versus unknown) rejoin.
1359672Slinton      */
1369672Slinton match:
1379672Slinton     return n;
1389672Slinton }
1399672Slinton 
1409672Slinton /*
1419672Slinton  * Deallocate the name table.
1429672Slinton  */
1439672Slinton 
1449672Slinton public names_free()
1459672Slinton {
14618225Slinton     Namepool n, m;
14718225Slinton     register integer i;
1489672Slinton 
14918225Slinton     n = namepool;
15018225Slinton     while (n != nil) {
15118225Slinton 	m = n->prevpool;
15218225Slinton 	dispose(n);
15318225Slinton 	n = m;
15418225Slinton     }
1559672Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
1569672Slinton 	nametable[i] = nil;
1579672Slinton     }
1589672Slinton     namepool = nil;
1599672Slinton     nleft = 0;
1609672Slinton }
161