NetBSD/usr.bin/m4/look.c

108 lines
2.3 KiB
C

/* File : look.c
Author : Ozan Yigit
Updated: 4 May 1992
Purpose: Hash table for M4
*/
#include "mdef.h"
#include "extr.h"
ndptr hashtab[HASHSIZE];
/*
* hash - get a hash value for string s
*/
int
hash(name)
char *name;
{
register unsigned long h = 0;
while (*name)
h = (h << 5) + h + *name++;
return h % HASHSIZE;
}
/*
* lookup(name) - find name in the hash table
*/
ndptr lookup(name)
char *name;
{
register ndptr p;
for (p = hashtab[hash(name)]; p != nil; p = p->nxtptr)
if (strcmp(name, p->name) == 0)
break;
return p;
}
/*
* addent(name) - hash and create an entry in the hash table.
* The new entry is added at the front of a hash bucket.
* BEWARE: the type and defn fields are UNDEFINED.
*/
ndptr addent(name)
char *name;
{
register ndptr p, *h;
p = (ndptr)malloc(sizeof *p);
if (p == NULL) error("m4: no more memory.");
h = &hashtab[hash(name)];
p->name = strsave(name);
p->defn = null;
p->nxtptr = *h;
*h = p;
return p;
}
/*
* addkywd(name, type) - stores a keyword in the hash table.
*/
void addkywd(name, type)
char *name;
int type;
{
register ndptr p = addent(name);
p->type = type | STATIC;
}
/*
* remhash(name, all)
* remove one entry (all==0) or all entries (all!=0) for a given name
* from the hash table. All hash table entries must have been obtained
* from malloc(), so it is safe to free the records themselves.
* However, the ->name and ->defn fields might point to storage which
* was obtained from strsave() -- in which case they may be freed -- or
* to static storage -- in which case they must not be freed. If the
* STATIC bit is set, the fields are not to be freed.
*/
void remhash(name, all)
char *name;
int all;
{
register ndptr p, *h;
/* h always points to the pointer to p */
h = &hashtab[hash(name)];
while ((p = *h) != nil) {
if (strcmp(p->name, name) == 0) {
*h = p->nxtptr; /* delink this record */
if (!(p->type & STATIC)) { /* free the name and defn */
free(p->name); /* if they came from strsave */
if (p->defn != null) free(p->defn);
} /* otherwise leave them */
free(p); /* free the record itself */
if (!all) return; /* first occurrence has gone */
} else {
h = &(p->nxtptr);
}
}
}