mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-04-12 18:40:23 +08:00
Use hash tables even for context-sensitive macros
Normally, contexts aren't used with a large number of macros, but in case someone does, do use hash tables for those as well. This simplifies the code somewhat, since *all* handling of macros is now done via hash tables. Future note: consider if it wouldn't be better to allow struct hash_table to be allocated by the caller, instead of being allocated by the hash table routine.
This commit is contained in:
parent
bd420c7095
commit
072771e4a5
@ -11,7 +11,6 @@
|
||||
#include "nasm.h"
|
||||
#include "hashtbl.h"
|
||||
|
||||
#define HASH_INITIAL_SIZE 64
|
||||
#define HASH_MAX_LOAD 2 /* Higher = more memory-efficient, slower */
|
||||
|
||||
static struct hash_tbl_node *alloc_table(size_t newsize)
|
||||
@ -22,14 +21,14 @@ static struct hash_tbl_node *alloc_table(size_t newsize)
|
||||
return newtbl;
|
||||
}
|
||||
|
||||
struct hash_table *hash_init(void)
|
||||
struct hash_table *hash_init(size_t size)
|
||||
{
|
||||
struct hash_table *head = nasm_malloc(sizeof(struct hash_table));
|
||||
|
||||
head->table = alloc_table(HASH_INITIAL_SIZE);
|
||||
head->table = alloc_table(size);
|
||||
head->load = 0;
|
||||
head->size = HASH_INITIAL_SIZE;
|
||||
head->max_load = HASH_INITIAL_SIZE*(HASH_MAX_LOAD-1)/HASH_MAX_LOAD;
|
||||
head->size = size;
|
||||
head->max_load = size*(HASH_MAX_LOAD-1)/HASH_MAX_LOAD;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
@ -34,7 +34,12 @@ uint64_t crc64(uint64_t crc, const char *string);
|
||||
uint64_t crc64i(uint64_t crc, const char *string);
|
||||
#define CRC64_INIT UINT64_C(0xffffffffffffffff)
|
||||
|
||||
struct hash_table *hash_init(void);
|
||||
/* Some reasonable initial sizes... */
|
||||
#define HASH_SMALL 4
|
||||
#define HASH_MEDIUM 16
|
||||
#define HASH_LARGE 256
|
||||
|
||||
struct hash_table *hash_init(size_t size);
|
||||
void **hash_find(struct hash_table *head, const char *string,
|
||||
struct hash_insert *insert);
|
||||
void **hash_findi(struct hash_table *head, const char *string,
|
||||
|
2
labels.c
2
labels.c
@ -371,7 +371,7 @@ void declare_as_global(char *label, char *special, efunc error)
|
||||
|
||||
int init_labels(void)
|
||||
{
|
||||
ltab = hash_init();
|
||||
ltab = hash_init(HASH_LARGE);
|
||||
|
||||
ldata = lfree = (union label *)nasm_malloc(LBLK_SIZE);
|
||||
init_block(lfree);
|
||||
|
140
preproc.c
140
preproc.c
@ -128,7 +128,7 @@ struct MMacro {
|
||||
*/
|
||||
struct Context {
|
||||
Context *next;
|
||||
SMacro *localmac;
|
||||
struct hash_table *localmac;
|
||||
char *name;
|
||||
uint32_t number;
|
||||
};
|
||||
@ -523,15 +523,13 @@ static void free_mmacro(MMacro * m)
|
||||
/*
|
||||
* Free all currently defined macros, and free the hash tables
|
||||
*/
|
||||
static void free_macros(void)
|
||||
static void free_smacro_table(struct hash_table *smt)
|
||||
{
|
||||
struct hash_tbl_node *it;
|
||||
const char *key;
|
||||
SMacro *s;
|
||||
MMacro *m;
|
||||
const char *key;
|
||||
struct hash_tbl_node *it = NULL;
|
||||
|
||||
it = NULL;
|
||||
while ((s = hash_iterate(smacros, &it, &key)) != NULL) {
|
||||
while ((s = hash_iterate(smt, &it, &key)) != NULL) {
|
||||
nasm_free((void *)key);
|
||||
while (s) {
|
||||
SMacro *ns = s->next;
|
||||
@ -541,10 +539,17 @@ static void free_macros(void)
|
||||
s = ns;
|
||||
}
|
||||
}
|
||||
hash_free(smacros);
|
||||
hash_free(smt);
|
||||
}
|
||||
|
||||
static void free_mmacro_table(struct hash_table *mmt)
|
||||
{
|
||||
MMacro *m;
|
||||
const char *key;
|
||||
struct hash_tbl_node *it = NULL;
|
||||
|
||||
it = NULL;
|
||||
while ((m = hash_iterate(mmacros, &it, &key)) != NULL) {
|
||||
while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
|
||||
nasm_free((void *)key);
|
||||
while (m) {
|
||||
MMacro *nm = m->next;
|
||||
@ -552,7 +557,13 @@ static void free_macros(void)
|
||||
m = nm;
|
||||
}
|
||||
}
|
||||
hash_free(mmacros);
|
||||
hash_free(mmt);
|
||||
}
|
||||
|
||||
static void free_macros(void)
|
||||
{
|
||||
free_smacro_table(smacros);
|
||||
free_mmacro_table(mmacros);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -560,8 +571,8 @@ static void free_macros(void)
|
||||
*/
|
||||
static void init_macros(void)
|
||||
{
|
||||
smacros = hash_init();
|
||||
mmacros = hash_init();
|
||||
smacros = hash_init(HASH_LARGE);
|
||||
mmacros = hash_init(HASH_LARGE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -570,21 +581,46 @@ static void init_macros(void)
|
||||
static void ctx_pop(void)
|
||||
{
|
||||
Context *c = cstk;
|
||||
SMacro *smac, *s;
|
||||
|
||||
cstk = cstk->next;
|
||||
smac = c->localmac;
|
||||
while (smac) {
|
||||
s = smac;
|
||||
smac = smac->next;
|
||||
nasm_free(s->name);
|
||||
free_tlist(s->expansion);
|
||||
nasm_free(s);
|
||||
}
|
||||
free_smacro_table(c->localmac);
|
||||
nasm_free(c->name);
|
||||
nasm_free(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a key in the hash index; adding it if necessary
|
||||
* (in which case we initialize the data pointer to NULL.)
|
||||
*/
|
||||
static void **
|
||||
hash_findi_add(struct hash_table *hash, const char *str)
|
||||
{
|
||||
struct hash_insert hi;
|
||||
void **r;
|
||||
char *strx;
|
||||
|
||||
r = hash_findi(hash, str, &hi);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
strx = nasm_strdup(str); /* Use a more efficient allocator here? */
|
||||
return hash_add(&hi, strx, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like hash_findi, but returns the data element rather than a pointer
|
||||
* to it. Used only when not adding a new element, hence no third
|
||||
* argument.
|
||||
*/
|
||||
static void *
|
||||
hash_findix(struct hash_table *hash, const char *str)
|
||||
{
|
||||
void **p;
|
||||
|
||||
p = hash_findi(hash, str, NULL);
|
||||
return p ? *p : NULL;
|
||||
}
|
||||
|
||||
#define BUF_DELTA 512
|
||||
/*
|
||||
* Read a line from the top file in istk, handling multiple CR/LFs
|
||||
@ -1197,7 +1233,7 @@ static Context *get_ctx(char *name, bool all_contexts)
|
||||
|
||||
do {
|
||||
/* Search for this smacro in found context */
|
||||
m = ctx->localmac;
|
||||
m = hash_findix(ctx->localmac, name);
|
||||
while (m) {
|
||||
if (!mstrcmp(m->name, name, m->casesense))
|
||||
return ctx;
|
||||
@ -1263,39 +1299,6 @@ static FILE *inc_fopen(char *file)
|
||||
return NULL; /* never reached - placate compilers */
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a key in the hash index; adding it if necessary
|
||||
* (in which case we initialize the data pointer to NULL.)
|
||||
*/
|
||||
static void **
|
||||
hash_findi_add(struct hash_table *hash, const char *str)
|
||||
{
|
||||
struct hash_insert hi;
|
||||
void **r;
|
||||
char *strx;
|
||||
|
||||
r = hash_findi(hash, str, &hi);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
strx = nasm_strdup(str); /* Use a more efficient allocator here? */
|
||||
return hash_add(&hi, strx, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like hash_findi, but returns the data element rather than a pointer
|
||||
* to it. Used only when not adding a new element, hence no third
|
||||
* argument.
|
||||
*/
|
||||
static void *
|
||||
hash_findix(struct hash_table *hash, const char *str)
|
||||
{
|
||||
void **p;
|
||||
|
||||
p = hash_findi(hash, str, NULL);
|
||||
return p ? *p : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if we should warn on defining a single-line macro of
|
||||
* name `name', with `nparam' parameters. If nparam is 0 or -1, will
|
||||
@ -1324,13 +1327,13 @@ smacro_defined(Context * ctx, char *name, int nparam, SMacro ** defn,
|
||||
SMacro *m;
|
||||
|
||||
if (ctx) {
|
||||
m = ctx->localmac;
|
||||
m = (SMacro *) hash_findix(ctx->localmac, name);
|
||||
} else if (name[0] == '%' && name[1] == '$') {
|
||||
if (cstk)
|
||||
ctx = get_ctx(name, false);
|
||||
if (!ctx)
|
||||
return false; /* got to return _something_ */
|
||||
m = ctx->localmac;
|
||||
m = (SMacro *) hash_findix(ctx->localmac, name);
|
||||
} else {
|
||||
m = (SMacro *) hash_findix(smacros, name);
|
||||
}
|
||||
@ -1692,11 +1695,8 @@ static bool define_smacro(Context *ctx, char *mname, bool casesense,
|
||||
free_tlist(smac->expansion);
|
||||
}
|
||||
} else {
|
||||
if (!ctx)
|
||||
smhead = (SMacro **) hash_findi_add(smacros, mname);
|
||||
else
|
||||
smhead = &ctx->localmac;
|
||||
|
||||
smhead = (SMacro **) hash_findi_add(ctx ? ctx->localmac : smacros,
|
||||
mname);
|
||||
smac = nasm_malloc(sizeof(SMacro));
|
||||
smac->next = *smhead;
|
||||
*smhead = smac;
|
||||
@ -1716,10 +1716,7 @@ static void undef_smacro(Context *ctx, const char *mname)
|
||||
{
|
||||
SMacro **smhead, *s, **sp;
|
||||
|
||||
if (!ctx)
|
||||
smhead = (SMacro **) hash_findi(smacros, mname, NULL);
|
||||
else
|
||||
smhead = &ctx->localmac;
|
||||
smhead = (SMacro **)hash_findi(ctx ? ctx->localmac : smacros, mname, NULL);
|
||||
|
||||
if (smhead) {
|
||||
/*
|
||||
@ -2085,7 +2082,7 @@ static int do_directive(Token * tline)
|
||||
error(ERR_WARNING, "trailing garbage after `%%push' ignored");
|
||||
ctx = nasm_malloc(sizeof(Context));
|
||||
ctx->next = cstk;
|
||||
ctx->localmac = NULL;
|
||||
ctx->localmac = hash_init(HASH_SMALL);
|
||||
ctx->name = nasm_strdup(tline->text);
|
||||
ctx->number = unique++;
|
||||
cstk = ctx;
|
||||
@ -3052,11 +3049,10 @@ again:
|
||||
ctx = get_ctx(mname, true);
|
||||
else
|
||||
ctx = NULL;
|
||||
if (!ctx) {
|
||||
head = (SMacro *) hash_findix(smacros, mname);
|
||||
} else {
|
||||
head = ctx->localmac;
|
||||
}
|
||||
|
||||
head = (SMacro *) hash_findix(ctx ? ctx->localmac : smacros,
|
||||
mname);
|
||||
|
||||
/*
|
||||
* We've hit an identifier. As in is_mmacro below, we first
|
||||
* check whether the identifier is a single-line macro at
|
||||
|
Loading…
x
Reference in New Issue
Block a user