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

Add a hash for pathname searches, instead of searching very pass

We have been doing a pathname search every time we encounter a file,
which means every file in every pass.  Instead, put the pathnames
found in a hash table.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin 2016-09-25 17:08:05 -07:00
parent 96921a5ad8
commit 169ac7c152
4 changed files with 117 additions and 51 deletions

View File

@ -348,8 +348,12 @@ int main(int argc, char **argv)
preproc = &nasmpp; preproc = &nasmpp;
operating_mode = OP_NORMAL; operating_mode = OP_NORMAL;
/* Define some macros dependent on the runtime, but not /*
on the command line. */ * Define some macros dependent on the runtime, but not
* on the command line. This only works because the only
* alternative preprocessor is preproc_nop...
*/
preproc->init();
define_macros_early(); define_macros_early();
parse_cmdline(argc, argv); parse_cmdline(argc, argv);

View File

@ -57,6 +57,11 @@
static FILE *nop_fp; static FILE *nop_fp;
static int32_t nop_lineinc; static int32_t nop_lineinc;
static void nop_init(void)
{
/* Nothing to do */
}
static void nop_reset(char *file, int pass, StrList **deplist) static void nop_reset(char *file, int pass, StrList **deplist)
{ {
src_set(0, file); src_set(0, file);
@ -174,6 +179,7 @@ static void nop_error_list_macros(int severity)
} }
const struct preproc_ops preproc_nop = { const struct preproc_ops preproc_nop = {
nop_init,
nop_reset, nop_reset,
nop_getline, nop_getline,
nop_cleanup, nop_cleanup,

View File

@ -285,6 +285,13 @@ struct IncPath {
char *path; char *path;
}; };
/*
* 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
* is used more than once.)
*/
struct hash_table FileHash;
/* /*
* Conditional assembly: we maintain a separate stack of these for * Conditional assembly: we maintain a separate stack of these for
* each level of file inclusion. (The only reason we keep the * each level of file inclusion. (The only reason we keep the
@ -1515,13 +1522,13 @@ enum incopen_mode {
INC_PROBE /* Only an existence probe */ INC_PROBE /* Only an existence probe */
}; };
static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail, /* This is conducts a full pathname search */
char **found_path, enum incopen_mode omode, static FILE *inc_fopen_search(const char *file, StrList **slpath,
enum file_flags fmode) enum incopen_mode omode, enum file_flags fmode)
{ {
FILE *fp; FILE *fp;
char *prefix = ""; char *prefix = "";
IncPath *ip = ipath; const IncPath *ip = ipath;
int len = strlen(file); int len = strlen(file);
size_t prefix_len = 0; size_t prefix_len = 0;
StrList *sl; StrList *sl;
@ -1534,6 +1541,7 @@ static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
sl = nasm_malloc(path_len + sizeof sl->next); sl = nasm_malloc(path_len + sizeof sl->next);
memcpy(sl->str, prefix, prefix_len); memcpy(sl->str, prefix, prefix_len);
memcpy(sl->str+prefix_len, file, len+1); memcpy(sl->str+prefix_len, file, len+1);
sl->next = NULL;
if (omode == INC_PROBE) { if (omode == INC_PROBE) {
fp = NULL; fp = NULL;
@ -1543,49 +1551,94 @@ static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
found = (fp != NULL); found = (fp != NULL);
} }
if (found) { if (found) {
if (found_path) *slpath = sl;
*found_path = nasm_strdup(sl->str);
if (dhead && !in_list(*dhead, sl->str)) {
sl->next = NULL;
**dtail = sl;
*dtail = &sl->next;
} else {
nasm_free(sl);
}
}
if (found)
return fp; return fp;
}
nasm_free(sl); nasm_free(sl);
if (!ip) { if (!ip)
if (omode == INC_NEEDED) return NULL;
break;
prefix = NULL;
} else {
prefix = ip->path; prefix = ip->path;
prefix_len = strlen(prefix);
ip = ip->next; ip = ip->next;
} }
if (prefix) { }
prefix_len = strlen(prefix);
/*
* Open a file, or test for the presence of one (depending on omode),
* considering the include path.
*/
static FILE *inc_fopen(const char *file,
StrList **dhead, StrList ***dtail,
char **found_path,
enum incopen_mode omode,
enum file_flags fmode)
{
StrList *sl;
struct hash_insert hi;
void **hp;
char *path;
FILE *fp = NULL;
hp = hash_find(&FileHash, file, &hi);
if (hp) {
path = *hp;
} else { } else {
/* -MG given and file not found */ /* Need to do the actual path search */
if (dhead && !in_list(*dhead, file)) { size_t file_len;
sl = nasm_malloc(len+1+sizeof sl->next);
sl = NULL;
fp = inc_fopen_search(file, &sl, omode, fmode);
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; sl->next = NULL;
strcpy(sl->str, file); file = sl->str;
path = NULL;
} else {
path = sl->str;
file = strchr(path, '\0') - file_len;
}
hash_add(&hi, file, path); /* Positive or negative result */
if (path || omode != INC_NEEDED) {
/*
* Add file to dependency path. The in_list() is needed
* in case the file was already added with %depend.
*/
if (dhead && !in_list(*dhead, sl->str)) {
**dtail = sl; **dtail = sl;
*dtail = &sl->next; *dtail = &sl->next;
} }
return NULL;
} }
} }
nasm_error(ERR_FATAL, "unable to open include file `%s'", file); if (!path) {
if (omode == INC_NEEDED)
nasm_fatal(0, "unable to open include file `%s'", file);
if (found_path)
*found_path = NULL;
return NULL; return NULL;
} }
if (!fp && omode != INC_PROBE)
fp = nasm_open_read(file, fmode);
if (found_path)
*found_path = nasm_strdup(path);
return fp;
}
/* /*
* Opens an include or input file. Public version, for use by modules * Opens an include or input file. Public version, for use by modules
* that get a file:lineno pair and need to look at the file again * that get a file:lineno pair and need to look at the file again
@ -1593,14 +1646,7 @@ static FILE *inc_fopen(const char *file, StrList **dhead, StrList ***dtail,
*/ */
FILE *pp_input_fopen(const char *filename, enum file_flags mode) FILE *pp_input_fopen(const char *filename, enum file_flags mode)
{ {
FILE *fp; return inc_fopen(filename, NULL, NULL, NULL, INC_OPTIONAL, mode);
StrList *xsl = NULL;
StrList **xst = &xsl;
fp = inc_fopen(filename, &xsl, &xst, NULL, INC_OPTIONAL, mode);
if (xsl)
nasm_free(xsl);
return fp;
} }
/* /*
@ -3249,8 +3295,7 @@ issue_error:
case PP_PATHSEARCH: case PP_PATHSEARCH:
{ {
StrList *xsl = NULL; char *found_path;
StrList **xst = &xsl;
casesense = true; casesense = true;
@ -3288,16 +3333,16 @@ issue_error:
if (t->type != TOK_INTERNAL_STRING) if (t->type != TOK_INTERNAL_STRING)
nasm_unquote(p, NULL); nasm_unquote(p, NULL);
inc_fopen(p, &xsl, &xst, NULL, INC_PROBE, NF_BINARY); inc_fopen(p, NULL, NULL, &found_path, INC_PROBE, NF_BINARY);
if (xsl) if (found_path)
p = xsl->str; p = found_path;
macro_start = nasm_malloc(sizeof(*macro_start)); macro_start = nasm_malloc(sizeof(*macro_start));
macro_start->next = NULL; macro_start->next = NULL;
macro_start->text = nasm_quote(p, strlen(p)); macro_start->text = nasm_quote(p, strlen(p));
macro_start->type = TOK_STRING; macro_start->type = TOK_STRING;
macro_start->a.mac = NULL; macro_start->a.mac = NULL;
if (xsl) if (found_path)
nasm_free(xsl); nasm_free(found_path);
/* /*
* We now have a macro name, an implicit parameter count of * We now have a macro name, an implicit parameter count of
@ -4930,6 +4975,11 @@ pp_reset(char *file, int apass, StrList **deplist)
define_smacro(NULL, "__PASS__", true, 0, t); define_smacro(NULL, "__PASS__", true, 0, t);
} }
static void pp_init(void)
{
hash_init(&FileHash, HASH_MEDIUM);
}
static char *pp_getline(void) static char *pp_getline(void)
{ {
char *line; char *line;
@ -5325,6 +5375,7 @@ static void pp_error_list_macros(int severity)
} }
const struct preproc_ops nasmpp = { const struct preproc_ops nasmpp = {
pp_init,
pp_reset, pp_reset,
pp_getline, pp_getline,
pp_cleanup, pp_cleanup,

View File

@ -344,6 +344,11 @@ typedef struct string_list {
* preprocessors ought to look like this: * preprocessors ought to look like this:
*/ */
struct preproc_ops { struct preproc_ops {
/*
* Called once at the very start of assembly.
*/
void (*init)(void);
/* /*
* Called at the start of a pass; given a file name, the number * Called at the start of a pass; given a file name, the number
* of the pass, an error reporting function, an evaluator * of the pass, an error reporting function, an evaluator