ack/modules/src/idf/idf_pkg.body

160 lines
3.5 KiB
Plaintext
Raw Normal View History

1987-01-05 17:20:13 +00:00
/* SYMBOL TABLE HANDLING */
#include <alloc.h>
/* Each character of the identifier is xored with an 8-bit mask which
depends on the position of the character; the sum of these results
is the hash value. The random masks are obtained from a
congruence generator.
*/
#define HASHSIZE 256 /* size of hashtable, must be a power of 2 */
#ifndef IDF_HSIZE
#define IDF_HSIZE 64 /* # of significant characters for hashing.
This is NOT the number of significant
characters!
*/
#endif
#define HASH_X 0253 /* Knuth's X */
#define HASH_A 77 /* Knuth's a */
#define HASH_C 153 /* Knuth's c */
#define HASHMASK (HASHSIZE-1) /* since it is a power of 2 */
#define STARTHASH() (0)
#define ENHASH(hs,ch,hm) (hs + (ch ^ hm))
#define STOPHASH(hs) (hs & HASHMASK)
static char hmask[IDF_HSIZE];
static struct idf *id_hashtable[HASHSIZE];
/* All identifiers can in principle be reached through
id_hashtable; id_hashtable[hc] is the start of a chain of
idf's whose tags all hash to hc.
Any identifier is entered into this
list, regardless of the nature of its declaration
(variable, selector, structure tag, etc.).
*/
static struct idf *
new_idf(tg, size, cpy)
register char *tg;
register int size;
{
static int nidf;
static struct idf *pidf;
#define NIDS 50
#define IBUFSIZ 2048
static unsigned int icnt;
static char *ip;
register char *p;
if (! nidf--) {
nidf += NIDS;
pidf = (struct idf *) Malloc(NIDS * sizeof (struct idf));
clear((char *) pidf, NIDS * sizeof(struct idf));
}
if (cpy) {
if (size > icnt) {
icnt = size > IBUFSIZ ? size : IBUFSIZ;
p = Malloc(icnt);
}
else p = ip;
icnt -= size;
pidf->id_text = p;
while (size--) {
*p++ = *tg++;
}
ip = p;
}
else pidf->id_text = tg;
return pidf++;
}
1987-08-06 14:20:11 +00:00
#ifdef IDF_DEBUG
1987-01-05 17:20:13 +00:00
hash_stat()
{
register int i;
print("Hash table tally:\n");
for (i = 0; i < HASHSIZE; i++) {
register struct idf *notch = id_hashtable[i];
register int cnt = 0;
while (notch) {
cnt++;
1987-08-06 14:20:11 +00:00
notch = notch->id_next;
1987-01-05 17:20:13 +00:00
}
print("%d %d\n", i, cnt);
}
print("End hash table tally\n");
}
1987-08-06 14:20:11 +00:00
#endif IDF_DEBUG
1987-01-05 17:20:13 +00:00
struct idf *
str2idf(tg, cpy)
char tg[];
{
/* str2idf() returns an entry in the symbol table for the
identifier tg. If necessary, an entry is created.
*/
register char *cp = tg;
register char *phm = &hmask[0];
struct idf **hook;
register struct idf *notch;
register int hash;
int size;
hash = STARTHASH();
while (*cp && phm < &hmask[IDF_HSIZE]) {
hash = ENHASH(hash, *cp++, *phm++);
}
hash = STOPHASH(hash);
while (*cp++) /* nothing. Find end of string */ ;
size = cp - tg;
/* The tag tg with length size and known hash value hash is
looked up in the identifier table; if not found, it is
entered if cpy >= 0. A pointer to it is returned.
Notice that the chains of idf's are sorted alphabetically.
*/
hook = &id_hashtable[hash];
while ((notch = *hook)) {
register char *s1 = tg;
int cmp;
cp = notch->id_text;
while (!(cmp = (*s1 - *cp++))) {
if (*s1++ == '\0') {
break;
}
}
if (cmp == 0) return notch;
if (cmp < 0) break;
1987-08-06 14:20:11 +00:00
hook = &notch->id_next;
1987-01-05 17:20:13 +00:00
}
/* a new struct idf must be inserted at the hook */
if (cpy < 0) return 0;
notch = new_idf(tg, size, cpy);
1987-08-06 14:20:11 +00:00
notch->id_next = *hook;
1987-01-05 17:20:13 +00:00
*hook = notch; /* hooked in */
return notch;
}
init_idf() {
/* A simple congruence random number generator, as
described in Knuth, vol 2.
*/
int rnd = HASH_X;
register char *phm;
for (phm = &hmask[0]; phm < &hmask[IDF_HSIZE];) {
*phm++ = rnd;
rnd = (HASH_A * rnd + HASH_C) & HASHMASK;
}
}