version 1.12, 2003/06/30 21:42:50 |
version 1.13, 2003/06/30 22:10:21 |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <stddef.h> |
#include <stddef.h> |
#include <string.h> |
#include <string.h> |
|
#include <ohash.h> |
#include "mdef.h" |
#include "mdef.h" |
#include "stdd.h" |
#include "stdd.h" |
#include "extern.h" |
#include "extern.h" |
|
|
struct ndblock { /* hastable structure */ |
struct ndblock { /* hashtable structure */ |
char *name; /* entry name.. */ |
struct macro_definition *d; |
struct macro_definition d; |
char name[1]; /* entry name.. */ |
unsigned int hv; /* hash function value.. */ |
|
ndptr nxtptr; /* link to next entry.. */ |
|
}; |
}; |
|
|
static void freent(ndptr); |
extern void *hash_alloc(size_t, void *); |
static void remhash(const char *, int); |
extern void hash_free(void *, size_t, void *); |
static unsigned hash(const char *); |
extern void *element_alloc(size_t, void *); |
static ndptr addent(const char *); |
static void setup_definition(struct macro_definition *, const char *, |
|
const char *); |
|
|
static unsigned int |
static struct ohash_info macro_info = { |
hash(const char *name) |
offsetof(struct ndblock, name), |
|
NULL, hash_alloc, hash_free, element_alloc }; |
|
|
|
static struct ohash macros; |
|
|
|
void |
|
init_macros() |
{ |
{ |
unsigned int h = 0; |
ohash_init(¯os, 7, ¯o_info); |
while (*name) |
|
h = (h << 5) + h + *name++; |
|
return (h); |
|
} |
} |
|
|
/* |
/* |
|
|
ndptr |
ndptr |
lookup(const char *name) |
lookup(const char *name) |
{ |
{ |
ndptr p; |
return ohash_find(¯os, ohash_qlookup(¯os, name)); |
unsigned int h; |
|
|
|
h = hash(name); |
|
for (p = hashtab[h % HASHSIZE]; p != NULL; p = p->nxtptr) |
|
if (h == p->hv && STREQ(name, p->name)) |
|
break; |
|
return (p); |
|
} |
} |
|
|
/* |
|
* hash and create an entry in the hash table. |
|
* The new entry is added in front of a hash bucket. |
|
*/ |
|
static ndptr |
|
addent(const char *name) |
|
{ |
|
unsigned int h; |
|
ndptr p; |
|
|
|
h = hash(name); |
|
p = (ndptr) xalloc(sizeof(struct ndblock)); |
|
p->nxtptr = hashtab[h % HASHSIZE]; |
|
hashtab[h % HASHSIZE] = p; |
|
p->name = xstrdup(name); |
|
p->hv = h; |
|
return p; |
|
} |
|
|
|
static void |
|
freent(ndptr p) |
|
{ |
|
free((char *) p->name); |
|
if (p->d.defn != null) |
|
free((char *) p->d.defn); |
|
free((char *) p); |
|
} |
|
|
|
/* |
|
* remove an entry from the hashtable |
|
*/ |
|
static void |
|
remhash(const char *name, int all) |
|
{ |
|
unsigned int h; |
|
ndptr xp, tp, mp; |
|
|
|
h = hash(name); |
|
mp = hashtab[h % HASHSIZE]; |
|
tp = NULL; |
|
while (mp != NULL) { |
|
if (mp->hv == h && STREQ(mp->name, name)) { |
|
mp = mp->nxtptr; |
|
if (tp == NULL) { |
|
freent(hashtab[h % HASHSIZE]); |
|
hashtab[h % HASHSIZE] = mp; |
|
} |
|
else { |
|
xp = tp->nxtptr; |
|
tp->nxtptr = mp; |
|
freent(xp); |
|
} |
|
if (!all) |
|
break; |
|
} |
|
else { |
|
tp = mp; |
|
mp = mp->nxtptr; |
|
} |
|
} |
|
} |
|
|
|
struct macro_definition * |
struct macro_definition * |
lookup_macro_definition(const char *name) |
lookup_macro_definition(const char *name) |
{ |
{ |
|
|
|
|
p = lookup(name); |
p = lookup(name); |
if (p) |
if (p) |
return &(p->d); |
return p->d; |
else |
else |
return NULL; |
return NULL; |
} |
} |
|
|
static void |
static void |
setup_definition(struct macro_definition *d, const char *defn) |
setup_definition(struct macro_definition *d, const char *defn, const char *name) |
{ |
{ |
int n; |
int n; |
|
|
if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0) { |
if (strncmp(defn, BUILTIN_MARKER, sizeof(BUILTIN_MARKER)-1) == 0 && |
n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1); |
(n = builtin_type(defn+sizeof(BUILTIN_MARKER)-1)) != -1) { |
if (n != -1) { |
d->type = n & TYPEMASK; |
d->type = n & TYPEMASK; |
if ((n & NOARGS) == 0) |
if ((n & NOARGS) == 0) |
d->type |= NEEDARGS; |
d->type |= NEEDARGS; |
d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1); |
d->defn = xstrdup(defn+sizeof(BUILTIN_MARKER)-1); |
} else { |
return; |
if (!*defn) |
} |
d->defn = null; |
|
else |
|
d->defn = xstrdup(defn); |
|
d->type = MACRTYPE; |
} |
} |
if (!*defn) |
if (STREQ(name, defn)) |
d->defn = null; |
d->type |= RECDEF; |
else |
|
d->defn = xstrdup(defn); |
|
d->type = MACRTYPE; |
|
} |
} |
|
|
|
static ndptr |
|
create_entry(const char *name) |
|
{ |
|
const char *end = NULL; |
|
unsigned int i; |
|
ndptr n; |
|
|
|
i = ohash_qlookupi(¯os, name, &end); |
|
n = ohash_find(¯os, i); |
|
if (n == NULL) { |
|
n = ohash_create_entry(¯o_info, name, &end); |
|
ohash_insert(¯os, i, n); |
|
n->d = NULL; |
|
} |
|
return n; |
|
} |
|
|
void |
void |
macro_define(const char *name, const char *defn) |
macro_define(const char *name, const char *defn) |
{ |
{ |
ndptr p; |
ndptr n = create_entry(name); |
|
if (n->d != NULL) { |
if ((p = lookup(name)) == NULL) |
if (n->d->defn != null) |
p = addent(name); |
free(n->d->defn); |
else if (p->d.defn != null) |
} else { |
free((char *) p->d.defn); |
n->d = xalloc(sizeof(struct macro_definition)); |
setup_definition(&(p->d), defn); |
n->d->next = NULL; |
if (STREQ(name, defn)) |
} |
p->d.type |= RECDEF; |
setup_definition(n->d, defn, name); |
} |
} |
|
|
void |
void |
macro_pushdef(const char *name, const char *defn) |
macro_pushdef(const char *name, const char *defn) |
{ |
{ |
ndptr p; |
ndptr n; |
|
struct macro_definition *d; |
p = addent(name); |
|
setup_definition(&(p->d), defn); |
n = create_entry(name); |
if (STREQ(name, defn)) |
d = xalloc(sizeof(struct macro_definition)); |
p->d.type |= RECDEF; |
d->next = n->d; |
|
n->d = d; |
|
setup_definition(n->d, defn, name); |
} |
} |
|
|
void |
void |
macro_undefine(const char *name) |
macro_undefine(const char *name) |
{ |
{ |
remhash(name, ALL); |
ndptr n = lookup(name); |
|
if (n != NULL) { |
|
struct macro_definition *r, *r2; |
|
|
|
for (r = n->d; r != NULL; r = r2) { |
|
r2 = r->next; |
|
if (r->defn != null) |
|
free(r->defn); |
|
free(r); |
|
} |
|
n->d = NULL; |
|
} |
} |
} |
|
|
void |
void |
macro_popdef(const char *name) |
macro_popdef(const char *name) |
{ |
{ |
remhash(name, TOP); |
ndptr n = lookup(name); |
|
|
|
if (n != NULL) { |
|
struct macro_definition *r = n->d; |
|
if (r != NULL) { |
|
n->d = r->next; |
|
if (r->defn != null) |
|
free(r->defn); |
|
free(r); |
|
} |
|
} |
} |
} |
|
|
void |
void |
macro_for_all(void (*f)(const char *, struct macro_definition *)) |
macro_for_all(void (*f)(const char *, struct macro_definition *)) |
{ |
{ |
int n; |
ndptr n; |
ndptr p; |
unsigned int i; |
|
|
for (n = 0; n < HASHSIZE; n++) |
for (n = ohash_first(¯os, &i); n != NULL; |
for (p = hashtab[n]; p != NULL; p = p->nxtptr) |
n = ohash_next(¯os, &i)) |
f(p->name, &(p->d)); |
f(n->name, n->d); |
} |
} |
|
|
void |
void |
setup_builtin(const char *name, unsigned int type) |
setup_builtin(const char *name, unsigned int type) |
{ |
{ |
unsigned int h; |
ndptr n; |
ndptr p; |
|
|
|
h = hash(name); |
n = create_entry(name); |
p = (ndptr) xalloc(sizeof(struct ndblock)); |
n->d = xalloc(sizeof(struct macro_definition)); |
p->nxtptr = hashtab[h % HASHSIZE]; |
n->d->defn = xstrdup(name); |
hashtab[h % HASHSIZE] = p; |
n->d->type = type; |
p->name = xstrdup(name); |
n->d->next = NULL; |
p->d.defn = xstrdup(name); |
|
p->hv = h; |
|
p->d.type = type; |
|
} |
} |
|
|
const char * |
const char * |
|
|
struct macro_definition * |
struct macro_definition * |
macro_getdef(ndptr p) |
macro_getdef(ndptr p) |
{ |
{ |
return &(p->d); |
return p->d; |
} |
} |