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