xref: /netbsd-src/usr.bin/m4/look.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
1 /*  File   : look.c
2     Author : Ozan Yigit
3     Updated: 4 May 1992
4     Purpose: Hash table for M4
5 */
6 
7 #include "mdef.h"
8 #include "extr.h"
9 
10 ndptr hashtab[HASHSIZE];
11 
12 
13 /*
14  * hash - get a hash value for string s
15  */
16 int
17 hash(name)
18 char *name;
19 {
20         register unsigned long h = 0;
21 
22         while (*name)
23                 h = (h << 5) + h + *name++;
24 
25         return h % HASHSIZE;
26 }
27 
28 /*
29  * lookup(name) - find name in the hash table
30  */
31 ndptr lookup(name)
32     char *name;
33     {
34 	register ndptr p;
35 
36 	for (p = hashtab[hash(name)]; p != nil; p = p->nxtptr)
37 	    if (strcmp(name, p->name) == 0)
38 		break;
39 	return p;
40     }
41 
42 /*
43  * addent(name) - hash and create an entry in the hash table.
44  * The new entry is added at the front of a hash bucket.
45  * BEWARE: the type and defn fields are UNDEFINED.
46  */
47 ndptr addent(name)
48     char *name;
49     {
50 	register ndptr p, *h;
51 
52 	p = (ndptr)malloc(sizeof *p);
53 	if (p == NULL) error("m4: no more memory.");
54 	h = &hashtab[hash(name)];
55 	p->name = strsave(name);
56 	p->defn = null;
57 	p->nxtptr = *h;
58 	*h = p;
59 	return p;
60     }
61 
62 
63 /*
64  * addkywd(name, type) - stores a keyword in the hash table.
65  */
66 void addkywd(name, type)
67     char *name;
68     int type;
69     {
70 	register ndptr p = addent(name);
71 	p->type = type | STATIC;
72     }
73 
74 
75 /*
76  * remhash(name, all)
77  * remove one entry (all==0) or all entries (all!=0) for a given name
78  * from the hash table.  All hash table entries must have been obtained
79  * from malloc(), so it is safe to free the records themselves.
80  * However, the ->name and ->defn fields might point to storage which
81  * was obtained from strsave() -- in which case they may be freed -- or
82  * to static storage -- in which case they must not be freed.  If the
83  * STATIC bit is set, the fields are not to be freed.
84  */
85 void remhash(name, all)
86     char *name;
87     int all;
88     {
89 	register ndptr p, *h;
90 	/*  h always points to the pointer to p  */
91 
92 	h = &hashtab[hash(name)];
93 	while ((p = *h) != nil) {
94 	    if (strcmp(p->name, name) == 0) {
95 		*h = p->nxtptr;			/* delink this record */
96 		if (!(p->type & STATIC)) {	/* free the name and defn */
97 		    free(p->name);		/* if they came from strsave */
98 		    if (p->defn != null) free(p->defn);
99 		}				/* otherwise leave them */
100 		free(p);			/* free the record itself */
101 		if (!all) return;		/* first occurrence has gone */
102 	    } else {
103 		h = &(p->nxtptr);
104 	    }
105 	}
106     }
107 
108