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:
parent
96921a5ad8
commit
169ac7c152
@ -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);
|
||||||
|
@ -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,
|
||||||
|
139
asm/preproc.c
139
asm/preproc.c
@ -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,
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user