xref: /csrg-svn/old/dbx/names.c (revision 38105)
121614Sdist /*
2*38105Sbostic  * Copyright (c) 1983 The Regents of the University of California.
3*38105Sbostic  * All rights reserved.
4*38105Sbostic  *
5*38105Sbostic  * Redistribution and use in source and binary forms are permitted
6*38105Sbostic  * provided that the above copyright notice and this paragraph are
7*38105Sbostic  * duplicated in all such forms and that any documentation,
8*38105Sbostic  * advertising materials, and other materials related to such
9*38105Sbostic  * distribution and use acknowledge that the software was developed
10*38105Sbostic  * by the University of California, Berkeley.  The name of the
11*38105Sbostic  * University may not be used to endorse or promote products derived
12*38105Sbostic  * from this software without specific prior written permission.
13*38105Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14*38105Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15*38105Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621614Sdist  */
179672Slinton 
1821614Sdist #ifndef lint
19*38105Sbostic static char sccsid[] = "@(#)names.c	5.3 (Berkeley) 05/23/89";
20*38105Sbostic #endif /* not lint */
219672Slinton 
229672Slinton /*
239672Slinton  * Name are the internal representation for identifiers.
249672Slinton  *
259672Slinton  * A hash table is used to map identifiers to names.
269672Slinton  */
279672Slinton 
289672Slinton #include "defs.h"
299672Slinton #include "names.h"
309672Slinton 
319672Slinton #ifndef public
329672Slinton typedef struct Name *Name;
339672Slinton 
349672Slinton /*
359672Slinton  * Inline (for speed) function to return the identifier (string)
369672Slinton  * associated with a name.  Because C cannot support both inlines
379672Slinton  * and data hiding at the same time, the Name structure must be
389672Slinton  * publicly visible.  It is not used explicitly, however, outside of this file.
399672Slinton  */
409672Slinton 
419672Slinton struct Name {
429672Slinton     char *identifier;
439672Slinton     Name chain;
449672Slinton };
459672Slinton 
469672Slinton #define ident(n) ((n == nil) ? "(noname)" : n->identifier)
479672Slinton #endif
489672Slinton 
4933327Sdonn /*
5033327Sdonn  * The hash table is a power of two, in order to make hashing faster.
5133327Sdonn  * Using a non-prime is ok since we use chaining instead of re-hashing.
5233327Sdonn  */
539672Slinton 
5433327Sdonn #define HASHTABLESIZE 8192
5533327Sdonn 
569672Slinton private Name nametable[HASHTABLESIZE];
579672Slinton 
589672Slinton /*
599672Slinton  * Names are allocated in large chunks to avoid calls to malloc
609672Slinton  * and to cluster names in memory so that tracing hash chains
619672Slinton  * doesn't cause many a page fault.
629672Slinton  */
639672Slinton 
6433327Sdonn #define CHUNKSIZE 1000
659672Slinton 
669672Slinton typedef struct Namepool {
679672Slinton     struct Name name[CHUNKSIZE];
689672Slinton     struct Namepool *prevpool;
699672Slinton } *Namepool;
709672Slinton 
719672Slinton private Namepool namepool = nil;
729672Slinton private Integer nleft = 0;
739672Slinton 
749672Slinton /*
759672Slinton  * Given an identifier, convert it to a name.
769672Slinton  * If it's not in the hash table, then put it there.
779672Slinton  *
789672Slinton  * The second argument specifies whether the string should be copied
799672Slinton  * into newly allocated space if not found.
809672Slinton  *
8133327Sdonn  * This routine is time critical when starting up the debugger
8233327Sdonn  * on large programs.
839672Slinton  */
849672Slinton 
859672Slinton public Name identname(s, isallocated)
869672Slinton String s;
879672Slinton Boolean isallocated;
889672Slinton {
899672Slinton     register unsigned h;
9033327Sdonn     register char *p, *q;
9133327Sdonn     register Name n, *np;
929672Slinton     Namepool newpool;
939672Slinton 
949672Slinton     h = 0;
959672Slinton     for (p = s; *p != '\0'; p++) {
969672Slinton 	h = (h << 1) ^ (*p);
979672Slinton     }
9833327Sdonn     h &= (HASHTABLESIZE-1);
9933327Sdonn     np = &nametable[h];
10033327Sdonn     n = *np;
1019672Slinton     while (n != nil) {
1029672Slinton 	p = s;
1039672Slinton 	q = n->identifier;
10433327Sdonn 	while (*p == *q) {
10533327Sdonn 	    if (*p == '\0') {
10633327Sdonn 		return n;
1079672Slinton 	    }
1089672Slinton 	    ++p;
1099672Slinton 	    ++q;
1109672Slinton 	}
1119672Slinton 	n = n->chain;
1129672Slinton     }
1139672Slinton 
1149672Slinton     /*
11533327Sdonn      * Now we know that name hasn't been found,
11633327Sdonn      * so we allocate a name, store the identifier, and
1179672Slinton      * enter it in the hash table.
1189672Slinton      */
1199672Slinton     if (nleft <= 0) {
1209672Slinton 	newpool = new(Namepool);
1219672Slinton 	newpool->prevpool = namepool;
1229672Slinton 	namepool = newpool;
1239672Slinton 	nleft = CHUNKSIZE;
1249672Slinton     }
1259672Slinton     --nleft;
1269672Slinton     n = &(namepool->name[nleft]);
1279672Slinton     if (isallocated) {
1289672Slinton 	n->identifier = s;
1299672Slinton     } else {
13033327Sdonn 	/* this case doesn't happen very often */
13133327Sdonn 	n->identifier = newarr(char, strlen(s) + 1);
1329672Slinton 	p = s;
1339672Slinton 	q = n->identifier;
1349672Slinton 	while (*p != '\0') {
1359672Slinton 	    *q++ = *p++;
1369672Slinton 	}
1379672Slinton 	*q = '\0';
1389672Slinton     }
13933327Sdonn     n->chain = *np;
14033327Sdonn     *np = n;
1419672Slinton     return n;
1429672Slinton }
1439672Slinton 
1449672Slinton /*
1459672Slinton  * Deallocate the name table.
1469672Slinton  */
1479672Slinton 
1489672Slinton public names_free()
1499672Slinton {
15018225Slinton     Namepool n, m;
15118225Slinton     register integer i;
1529672Slinton 
15318225Slinton     n = namepool;
15418225Slinton     while (n != nil) {
15518225Slinton 	m = n->prevpool;
15618225Slinton 	dispose(n);
15718225Slinton 	n = m;
15818225Slinton     }
1599672Slinton     for (i = 0; i < HASHTABLESIZE; i++) {
1609672Slinton 	nametable[i] = nil;
1619672Slinton     }
1629672Slinton     namepool = nil;
1639672Slinton     nleft = 0;
1649672Slinton }
165