home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 48
/
Amiga_Dream_48.iso
/
Atari
/
c
/
cpp.zoo
/
src
/
hash.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-03
|
4KB
|
188 lines
#include "global.h"
#include "ztype.h"
#define HASH_SIZE 1009
extern char *magic_words[];
extern int N_MWORDS;
/* a hash object */
typedef struct hash {
char *id;
Macro *data;
struct hash *next;
} Hash;
static Hash *H[HASH_SIZE];
/*
hash_id() -- compute a hash value for the identifier pointed to by |s|;
place a pointer to the first character after the identifier in |*end|.
Credit where it's due -- this hash function was originally suggested by Chris
Torek on comp.lang.c. As an explanation of the implementation, he
offered: "What *does* that 33 do? I have no idea."
*/
unsigned int hash_id(s, end)
register char *s;
char **end;
{
register unsigned int h = 0;
for (; is_ctok(*s); s++)
h = (h * 33 + *s) % HASH_SIZE;
if (end)
*end = s;
return h;
}
/*
hash_add() -- add to the hash table an entry for the identifier |s|, with
hash value |hv| and macro value |M|
*/
void hash_add(s, hv, M)
char *s;
unsigned int hv;
Macro *M;
{
Hash *h, *hh;
h = mallok(sizeof (Hash));
h->data = M;
h->next = NULL;
h->id = strdup(s);
h->next = H[hv];
H[hv] = h;
}
/*
hash_unlink() -- destroy the hash object pointed to by |h|; return a
pointer to the hash object following |h|. Used in hash_remove().
*/
static Hash *hash_unlink(h)
Hash *h;
{
Hash *hh = h->next;
free(h->id);
if (h->data->m_text)
free(h->data->m_text);
free(h->data);
free(h);
return hh;
}
/*
hash_remove() -- remove the hash object for identifier |s|, with hash
value |hv|
*/
void hash_remove(s, hv)
char *s;
unsigned int hv;
{
unsigned int i;
Hash *h;
if (!H[hv])
return;
if (streq(H[hv]->id, s)) {
H[hv] = hash_unlink(H[hv]);
return;
}
for (h = H[hv]; h->next; h = h->next)
if (streq(h->next->id, s)) {
h->next = hash_unlink(h->next);
return;
}
}
/*
magic_check() -- determine if the conditionally-active magic preprocessor
constant in hash object |h| is in fact active
*/
static int magic_check(h)
Hash *h;
{
if (streq(h->id, "__STDC__") && ansi)
return 1;
if (streq(h->id, "defined") && (get_mode() & IF_EXPR))
return 1;
return 0;
}
/*
lookup() -- look for the identifier |s| with hash value |hv| in the hash
table. Return its associated macro value, or NULL if the identifier is
not present
*/
Macro *lookup(s, hv)
char *s;
unsigned int hv;
{
Hash *h;
for (h = H[hv]; h; h = h->next)
if (streq(h->id, s)) {
if (!(h->data->flags & MAGIC2) || magic_check(h)) {
return h->data;
} else {
return NULL;
}
}
return NULL;
}
/*
hash_setup() -- initialize the hash table and add the predefined tokens
*/
void hash_setup()
{
int i;
Macro *M;
unsigned int hv;
for (i = 0; i < HASH_SIZE; i++)
H[i] = NULL;
for (i = 0; i < N_MWORDS; i++) {
M = mallok(sizeof (Macro));
M->nargs = 0;
M->m_text = M->argnames = NULL;
M->flags = MAGIC;
if (i < 2)
M->flags |= MAGIC2;
hash_add(magic_words[i], hash_id(magic_words[i], NULL), M);
}
}
/*
hash_clean_undef() -- remove all identifiers that were #undef'ined via -U
from the hash table
*/
void hash_clean_undef()
{
int i;
Hash *h;
for (i = 0; i < HASH_SIZE; i++) {
while (H[i] && H[i]->data->flags & UNDEF)
H[i] = hash_unlink(H[i]);
if (H[i]) {
for (h = H[i]; h->next; h = h->next)
if (h->next->data->flags & UNDEF)
h->next = hash_unlink(h->next);
}
}
}
/* hash_free() -- deallocate all hash objects */
void hash_free()
{
int i;
Hash *h;
for (i = 0; i < HASH_SIZE; i++)
for (h = H[i]; h; h = hash_unlink(h)) ;
}