0
0
mirror of https://github.com/netwide-assembler/nasm.git synced 2025-07-24 10:25:42 -04:00

strlist: use a hash table

Use a hash table to enforce uniqueness in a string list. It is still
an ordered list, however, and can be walked in insertion order.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2018-10-25 12:33:58 -07:00
parent c7922f95af
commit f7106d06e4
7 changed files with 108 additions and 162 deletions

View File

@ -75,7 +75,7 @@ struct forwrefinfo { /* info held on forward refs. */
}; };
static void parse_cmdline(int, char **, int); static void parse_cmdline(int, char **, int);
static void assemble_file(const char *, StrList **); static void assemble_file(const char *, StrList *);
static bool is_suppressed_warning(int severity); static bool is_suppressed_warning(int severity);
static bool skip_this_pass(int severity); static bool skip_this_pass(int severity);
static void nasm_verror_gnu(int severity, const char *fmt, va_list args); static void nasm_verror_gnu(int severity, const char *fmt, va_list args);
@ -309,9 +309,12 @@ static void emit_dependencies(StrList *list)
{ {
FILE *deps; FILE *deps;
int linepos, len; int linepos, len;
StrList *l, *nl;
bool wmake = (quote_for_make == quote_for_wmake); bool wmake = (quote_for_make == quote_for_wmake);
const char *wrapstr, *nulltarget; const char *wrapstr, *nulltarget;
struct strlist_entry *l;
if (!list)
return;
wrapstr = wmake ? " &\n " : " \\\n "; wrapstr = wmake ? " &\n " : " \\\n ";
nulltarget = wmake ? "\t%null\n" : ""; nulltarget = wmake ? "\t%null\n" : "";
@ -328,7 +331,7 @@ static void emit_dependencies(StrList *list)
} }
linepos = fprintf(deps, "%s :", depend_target); linepos = fprintf(deps, "%s :", depend_target);
list_for_each(l, list) { list_for_each(l, list->head) {
char *file = quote_for_make(l->str); char *file = quote_for_make(l->str);
len = strlen(file); len = strlen(file);
if (linepos + len > 62 && linepos > 1) { if (linepos + len > 62 && linepos > 1) {
@ -341,15 +344,16 @@ static void emit_dependencies(StrList *list)
} }
fprintf(deps, "\n\n"); fprintf(deps, "\n\n");
list_for_each_safe(l, nl, list) { list_for_each(l, list->head) {
if (depend_emit_phony) { if (depend_emit_phony) {
char *file = quote_for_make(l->str); char *file = quote_for_make(l->str);
fprintf(deps, "%s :\n%s\n", file, nulltarget); fprintf(deps, "%s :\n%s\n", file, nulltarget);
nasm_free(file); nasm_free(file);
} }
nasm_free(l);
} }
strlist_free(list);
if (deps != stdout) if (deps != stdout)
fclose(deps); fclose(deps);
} }
@ -409,8 +413,6 @@ static void timestamp(void)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
StrList **depend_ptr;
timestamp(); timestamp();
iflag_set_default_cpu(&cpu); iflag_set_default_cpu(&cpu);
@ -494,7 +496,8 @@ int main(int argc, char **argv)
/* define some macros dependent of command-line */ /* define some macros dependent of command-line */
define_macros_late(); define_macros_late();
depend_ptr = (depend_file || (operating_mode & OP_DEPEND)) ? &depend_list : NULL; if (depend_file || (operating_mode & OP_DEPEND))
depend_list = strlist_allocate();
if (!depend_target) if (!depend_target)
depend_target = quote_for_make(outname); depend_target = quote_for_make(outname);
@ -505,7 +508,7 @@ int main(int argc, char **argv)
if (depend_missing_ok) if (depend_missing_ok)
preproc->include_path(NULL); /* "assume generated" */ preproc->include_path(NULL); /* "assume generated" */
preproc->reset(inname, 0, depend_ptr); preproc->reset(inname, 0, depend_list);
ofile = NULL; ofile = NULL;
while ((line = preproc->getline())) while ((line = preproc->getline()))
nasm_free(line); nasm_free(line);
@ -528,7 +531,7 @@ int main(int argc, char **argv)
location.known = false; location.known = false;
/* pass = 1; */ /* pass = 1; */
preproc->reset(inname, 3, depend_ptr); preproc->reset(inname, 3, depend_list);
/* Revert all warnings to the default state */ /* Revert all warnings to the default state */
memcpy(warning_state, warning_state_init, sizeof warning_state); memcpy(warning_state, warning_state_init, sizeof warning_state);
@ -570,7 +573,7 @@ int main(int argc, char **argv)
ofmt->init(); ofmt->init();
dfmt->init(); dfmt->init();
assemble_file(inname, depend_ptr); assemble_file(inname, depend_list);
if (!terminate_after_phase) { if (!terminate_after_phase) {
ofmt->cleanup(); ofmt->cleanup();
@ -1379,7 +1382,7 @@ static void parse_cmdline(int argc, char **argv, int pass)
} }
} }
static void assemble_file(const char *fname, StrList **depend_ptr) static void assemble_file(const char *fname, StrList *depend_list)
{ {
char *line; char *line;
insn output_ins; insn output_ins;
@ -1431,7 +1434,7 @@ static void assemble_file(const char *fname, StrList **depend_ptr)
location.known = true; location.known = true;
ofmt->reset(); ofmt->reset();
switch_segment(ofmt->section(NULL, pass2, &globalbits)); switch_segment(ofmt->section(NULL, pass2, &globalbits));
preproc->reset(fname, pass1, pass1 == 2 ? depend_ptr : NULL); preproc->reset(fname, pass1, pass1 == 2 ? depend_list : NULL);
/* Revert all warnings to the default state */ /* Revert all warnings to the default state */
memcpy(warning_state, warning_state_init, sizeof warning_state); memcpy(warning_state, warning_state_init, sizeof warning_state);

View File

@ -63,7 +63,7 @@ static void nop_init(void)
/* Nothing to do */ /* Nothing to do */
} }
static void nop_reset(const char *file, int pass, StrList **deplist) static void nop_reset(const char *file, int pass, StrList *deplist)
{ {
src_set(0, file); src_set(0, file);
nop_lineinc = 1; nop_lineinc = 1;
@ -73,7 +73,7 @@ static void nop_reset(const char *file, int pass, StrList **deplist)
nasm_fatal_fl(ERR_NOFILE, "unable to open input file `%s'", file); nasm_fatal_fl(ERR_NOFILE, "unable to open input file `%s'", file);
(void)pass; /* placate compilers */ (void)pass; /* placate compilers */
nasm_add_string_to_strlist(deplist, file); strlist_add_string(deplist, file);
} }
static char *nop_getline(void) static char *nop_getline(void)
@ -170,7 +170,7 @@ static void nop_pre_command(const char *what, char *string)
(void)string; (void)string;
} }
static void nop_include_path(char *path) static void nop_include_path(const char *path)
{ {
(void)path; (void)path;
} }

View File

@ -91,7 +91,6 @@ typedef struct Blocks Blocks;
typedef struct Line Line; typedef struct Line Line;
typedef struct Include Include; typedef struct Include Include;
typedef struct Cond Cond; typedef struct Cond Cond;
typedef struct IncPath IncPath;
/* /*
* Note on the storage of both SMacro and MMacros: the hash table * Note on the storage of both SMacro and MMacros: the hash table
@ -276,16 +275,6 @@ struct Include {
MMacro *mstk; /* stack of active macros/reps */ MMacro *mstk; /* stack of active macros/reps */
}; };
/*
* Include search path. This is simply a list of strings which get
* prepended, in turn, to the name of an include file, in an
* attempt to find the file if it's not in the current directory.
*/
struct IncPath {
IncPath *next;
char *path;
};
/* /*
* File real name hash, so we don't have to re-search the include * File real name hash, so we don't have to re-search the include
* path for every pass (and potentially more than that if a file * path for every pass (and potentially more than that if a file
@ -397,10 +386,10 @@ static int LocalOffset = 0;
static Context *cstk; static Context *cstk;
static Include *istk; static Include *istk;
static IncPath *ipath = NULL; static StrList *ipath;
static int pass; /* HACK: pass 0 = generate dependencies only */ static int pass; /* HACK: pass 0 = generate dependencies only */
static StrList **dephead; static StrList *deplist;
static uint64_t unique; /* unique identifier numbers */ static uint64_t unique; /* unique identifier numbers */
@ -1509,43 +1498,37 @@ enum incopen_mode {
}; };
/* This is conducts a full pathname search */ /* This is conducts a full pathname search */
static FILE *inc_fopen_search(const char *file, StrList **slpath, static FILE *inc_fopen_search(const char *file, char **slpath,
enum incopen_mode omode, enum file_flags fmode) enum incopen_mode omode, enum file_flags fmode)
{ {
FILE *fp; FILE *fp;
char *prefix = ""; const char *prefix = "";
const IncPath *ip = ipath; const struct strlist_entry *ip = ipath->head;
int len;
StrList *sl;
char *sp; char *sp;
bool found; bool found;
while (1) { while (1) {
sp = nasm_catfile(prefix, file); sp = nasm_catfile(prefix, file);
len = strlen(sp) + 1;
sl = nasm_malloc(len + sizeof sl->next);
memcpy(sl->str, sp, len);
sl->next = NULL;
nasm_free(sp);
if (omode == INC_PROBE) { if (omode == INC_PROBE) {
fp = NULL; fp = NULL;
found = nasm_file_exists(sl->str); found = nasm_file_exists(sp);
} else { } else {
fp = nasm_open_read(sl->str, fmode); fp = nasm_open_read(sp, fmode);
found = (fp != NULL); found = (fp != NULL);
} }
if (found) { if (found) {
*slpath = sl; *slpath = sp;
return fp; return fp;
} }
nasm_free(sl); nasm_free(sp);
if (!ip) if (!ip) {
*slpath = NULL;
return NULL; return NULL;
}
prefix = ip->path; prefix = ip->str;
ip = ip->next; ip = ip->next;
} }
} }
@ -1555,12 +1538,11 @@ static FILE *inc_fopen_search(const char *file, StrList **slpath,
* considering the include path. * considering the include path.
*/ */
static FILE *inc_fopen(const char *file, static FILE *inc_fopen(const char *file,
StrList **dhead, StrList *dhead,
const char **found_path, const char **found_path,
enum incopen_mode omode, enum incopen_mode omode,
enum file_flags fmode) enum file_flags fmode)
{ {
StrList *sl;
struct hash_insert hi; struct hash_insert hi;
void **hp; void **hp;
char *path; char *path;
@ -1570,52 +1552,30 @@ static FILE *inc_fopen(const char *file,
if (hp) { if (hp) {
path = *hp; path = *hp;
if (path || omode != INC_NEEDED) { if (path || omode != INC_NEEDED) {
nasm_add_string_to_strlist(dhead, path ? path : file); strlist_add_string(dhead, path ? path : file);
} }
} else { } else {
/* Need to do the actual path search */ /* Need to do the actual path search */
size_t file_len; fp = inc_fopen_search(file, &path, omode, fmode);
sl = NULL; /* Positive or negative result */
fp = inc_fopen_search(file, &sl, omode, fmode); hash_add(&hi, nasm_strdup(file), path);
file_len = strlen(file);
if (!sl) {
/* Store negative result for this file */
sl = nasm_malloc(file_len + 1 + sizeof sl->next);
memcpy(sl->str, file, file_len+1);
sl->next = NULL;
file = sl->str;
path = NULL;
} else {
path = sl->str;
file = strchr(path, '\0') - file_len;
}
hash_add(&hi, file, path); /* Positive or negative result */
/* /*
* Add file to dependency path. The in_list() is needed * Add file to dependency path.
* in case the file was already added with %depend.
*/ */
if (path || omode != INC_NEEDED) if (path || omode != INC_NEEDED)
nasm_add_to_strlist(dhead, sl); strlist_add_string(dhead, file);
} }
if (!path) { if (!path) {
if (omode == INC_NEEDED) if (omode == INC_NEEDED)
nasm_fatal("unable to open include file `%s'", file); nasm_fatal("unable to open include file `%s'", file);
} else {
if (found_path) if (!fp && omode != INC_PROBE)
*found_path = NULL; fp = nasm_open_read(path, fmode);
return NULL;
} }
if (!fp && omode != INC_PROBE)
fp = nasm_open_read(path, fmode);
if (found_path) if (found_path)
*found_path = path; *found_path = path;
@ -2598,7 +2558,7 @@ static int do_directive(Token *tline, char **output)
p = t->text; p = t->text;
if (t->type != TOK_INTERNAL_STRING) if (t->type != TOK_INTERNAL_STRING)
nasm_unquote_cstr(p, i); nasm_unquote_cstr(p, i);
nasm_add_string_to_strlist(dephead, p); strlist_add_string(deplist, p);
free_tlist(origline); free_tlist(origline);
return DIRECTIVE_FOUND; return DIRECTIVE_FOUND;
@ -2622,7 +2582,7 @@ static int do_directive(Token *tline, char **output)
inc->next = istk; inc->next = istk;
inc->conds = NULL; inc->conds = NULL;
found_path = NULL; found_path = NULL;
inc->fp = inc_fopen(p, dephead, &found_path, inc->fp = inc_fopen(p, deplist, &found_path,
pass == 0 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT); pass == 0 ? INC_OPTIONAL : INC_NEEDED, NF_TEXT);
if (!inc->fp) { if (!inc->fp) {
/* -MG given but file not found */ /* -MG given but file not found */
@ -4972,7 +4932,7 @@ static void pp_verror(int severity, const char *fmt, va_list arg)
} }
static void static void
pp_reset(const char *file, int apass, StrList **deplist) pp_reset(const char *file, int apass, StrList *dep_list)
{ {
Token *t; Token *t;
@ -4993,6 +4953,7 @@ pp_reset(const char *file, int apass, StrList **deplist)
nested_rep_count = 0; nested_rep_count = 0;
init_macros(); init_macros();
unique = 0; unique = 0;
deplist = dep_list;
if (tasm_compatible_mode) if (tasm_compatible_mode)
pp_add_stdmac(nasm_stdmac_tasm); pp_add_stdmac(nasm_stdmac_tasm);
@ -5015,9 +4976,8 @@ pp_reset(const char *file, int apass, StrList **deplist)
*/ */
pass = apass > 2 ? 2 : apass; pass = apass > 2 ? 2 : apass;
dephead = deplist; strlist_add_string(deplist, file);
nasm_add_string_to_strlist(dephead, file);
/* /*
* Define the __PASS__ macro. This is defined here unlike * Define the __PASS__ macro. This is defined here unlike
* all the other builtins, because it is special -- it varies between * all the other builtins, because it is special -- it varies between
@ -5033,6 +4993,7 @@ pp_reset(const char *file, int apass, StrList **deplist)
static void pp_init(void) static void pp_init(void)
{ {
hash_init(&FileHash, HASH_MEDIUM); hash_init(&FileHash, HASH_MEDIUM);
ipath = strlist_allocate();
} }
static char *pp_getline(void) static char *pp_getline(void)
@ -5296,36 +5257,20 @@ static void pp_cleanup(int pass)
ctx_pop(); ctx_pop();
src_set_fname(NULL); src_set_fname(NULL);
if (pass == 0) { if (pass == 0) {
IncPath *i;
free_llist(predef); free_llist(predef);
predef = NULL; predef = NULL;
delete_Blocks(); delete_Blocks();
freeTokens = NULL; freeTokens = NULL;
while ((i = ipath)) { strlist_free(ipath);
ipath = i->next;
if (i->path)
nasm_free(i->path);
nasm_free(i);
}
} }
} }
static void pp_include_path(char *path) static void pp_include_path(const char *path)
{ {
IncPath *i; if (!path)
path = "";
i = nasm_malloc(sizeof(IncPath)); strlist_add_string(ipath, path);
i->path = path ? nasm_strdup(path) : NULL;
i->next = NULL;
if (ipath) {
IncPath *j = ipath;
while (j->next)
j = j->next;
j->next = i;
} else {
ipath = i;
}
} }
static void pp_pre_include(char *fname) static void pp_pre_include(char *fname)

View File

@ -336,7 +336,7 @@ struct preproc_ops {
* of the pass, an error reporting function, an evaluator * of the pass, an error reporting function, an evaluator
* function, and a listing generator to talk to. * function, and a listing generator to talk to.
*/ */
void (*reset)(const char *file, int pass, StrList **deplist); void (*reset)(const char *file, int pass, StrList *deplist);
/* /*
* Called to fetch a line of preprocessed source. The line * Called to fetch a line of preprocessed source. The line
@ -362,7 +362,7 @@ struct preproc_ops {
void (*pre_command)(const char *what, char *str); void (*pre_command)(const char *what, char *str);
/* Include path from command line */ /* Include path from command line */
void (*include_path)(char *path); void (*include_path)(const char *path);
/* Unwind the macro stack when printing an error message */ /* Unwind the macro stack when printing an error message */
void (*error_list_macros)(int severity); void (*error_list_macros)(int severity);

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- * /* ----------------------------------------------------------------------- *
* *
* Copyright 1996-2016 The NASM Authors - All Rights Reserved * Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@ -39,17 +39,22 @@
#define NASM_STRLIST_H #define NASM_STRLIST_H
#include "compiler.h" #include "compiler.h"
#include <string.h>
#include "nasmlib.h" #include "nasmlib.h"
#include "hashtbl.h"
struct strlist_entry {
struct strlist_entry *next;
size_t len;
char str[1];
};
typedef struct string_list { typedef struct string_list {
struct string_list *next; struct hash_table hash;
char str[1]; struct strlist_entry *head, **tailp;
} StrList; } StrList;
bool nasm_add_to_strlist(StrList **head, StrList *entry); StrList safe_alloc *strlist_allocate(void);
bool nasm_add_string_to_strlist(StrList **head, const char *str); bool strlist_add_string(StrList *list, const char *str);
void strlist_free(StrList *list);
#endif /* NASM_STRLIST_H */ #endif /* NASM_STRLIST_H */

View File

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- * /* ----------------------------------------------------------------------- *
* *
* Copyright 1996-2016 The NASM Authors - All Rights Reserved * Copyright 1996-2018 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for * See the file AUTHORS included with the NASM distribution for
* the specific copyright holders. * the specific copyright holders.
* *
@ -32,69 +32,62 @@
* ----------------------------------------------------------------------- */ * ----------------------------------------------------------------------- */
/* /*
* strlist.c - simple linked list of strings * strlist.c - list of unique, ordered strings
*/ */
#include "compiler.h"
#include <string.h>
#include "strlist.h" #include "strlist.h"
static inline StrList *nasm_str_to_strlist(const char *str)
{
size_t l = strlen(str) + 1;
StrList *sl = nasm_malloc(l + sizeof sl->next);
memcpy(sl->str, str, l);
sl->next = NULL;
return sl;
}
/* /*
* Append a string list entry to a string list if and only if it isn't * Create a string list
* already there. Return true if it was added.
*/ */
bool nasm_add_to_strlist(StrList **head, StrList *entry) StrList *strlist_allocate(void)
{ {
StrList *list; StrList *list;
if (!head) nasm_new(list);
return false; hash_init(&list->hash, HASH_MEDIUM);
list->tailp = &list->head;
list = *head; return list;
while (list) {
if (!strcmp(list->str, entry->str))
return false;
head = &list->next;
list = list->next;
}
*head = entry;
entry->next = NULL;
return true;
} }
/* /*
* Append a string to a string list if and only if it isn't * Append a string to a string list if and only if it isn't
* already there. Return true if it was added. * already there. Return true if it was added.
*/ */
bool nasm_add_string_to_strlist(StrList **head, const char *str) bool strlist_add_string(StrList *list, const char *str)
{ {
StrList *list; struct hash_insert hi;
struct strlist_entry *sl;
size_t l;
if (!head) if (!list)
return false; return false;
list = *head; if (hash_find(&list->hash, str, &hi))
while (list) { return false; /* Already present */
if (!strcmp(list->str, str))
return false;
head = &list->next;
list = list->next;
}
*head = nasm_str_to_strlist(str); l = strlen(str);
sl = nasm_malloc(sizeof(struct strlist_entry) + l);
sl->len = l;
memcpy(sl->str, str, l+1);
sl->next = NULL;
*list->tailp = sl;
list->tailp = &sl->next;
hash_add(&hi, sl->str, (void *)sl);
return true; return true;
} }
/*
* Free a string list
*/
void strlist_free(StrList *list)
{
if (!list)
return;
hash_free_all(&list->hash, false);
nasm_free(list);
}

View File

@ -1965,7 +1965,7 @@ static void obj_write_file(void)
struct ExpDef *export; struct ExpDef *export;
int lname_idx; int lname_idx;
ObjRecord *orp; ObjRecord *orp;
const StrList *depfile; const struct strlist_entry *depfile;
const bool debuginfo = (dfmt == &borland_debug_form); const bool debuginfo = (dfmt == &borland_debug_form);
/* /*
@ -1988,7 +1988,7 @@ static void obj_write_file(void)
* Output file dependency information * Output file dependency information
*/ */
if (!obj_nodepend) { if (!obj_nodepend) {
list_for_each(depfile, depend_list) { list_for_each(depfile, depend_list->head) {
uint32_t ts; uint32_t ts;
ts = obj_file_timestamp(depfile->str); ts = obj_file_timestamp(depfile->str);