Introduce %depend and %pathsearch, and make incbin a macro
Introduce new preprocessor directives %depend and %pathsearch, and make incbin a standard macro using these filenames. This lets us remove the code that makes incbin search the path.
This commit is contained in:
parent
5ff39dc78d
commit
418ca70d4e
6 changed files with 141 additions and 112 deletions
52
assemble.c
52
assemble.c
|
@ -119,7 +119,6 @@
|
||||||
#include "nasmlib.h"
|
#include "nasmlib.h"
|
||||||
#include "assemble.h"
|
#include "assemble.h"
|
||||||
#include "insns.h"
|
#include "insns.h"
|
||||||
#include "preproc.h"
|
|
||||||
#include "tables.h"
|
#include "tables.h"
|
||||||
|
|
||||||
/* Initialized to zero by the C standard */
|
/* Initialized to zero by the C standard */
|
||||||
|
@ -369,8 +368,6 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
||||||
static char fname[FILENAME_MAX];
|
static char fname[FILENAME_MAX];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int32_t len;
|
int32_t len;
|
||||||
char *prefix = "", *combine;
|
|
||||||
char **pPrevPath = NULL;
|
|
||||||
|
|
||||||
len = FILENAME_MAX - 1;
|
len = FILENAME_MAX - 1;
|
||||||
if (len > instruction->eops->stringlen)
|
if (len > instruction->eops->stringlen)
|
||||||
|
@ -378,30 +375,14 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
||||||
strncpy(fname, instruction->eops->stringval, len);
|
strncpy(fname, instruction->eops->stringval, len);
|
||||||
fname[len] = '\0';
|
fname[len] = '\0';
|
||||||
|
|
||||||
while (1) { /* added by alexfru: 'incbin' uses include paths */
|
fp = fopen(fname, "rb");
|
||||||
combine = nasm_malloc(strlen(prefix) + len + 1);
|
if (!fp) {
|
||||||
strcpy(combine, prefix);
|
|
||||||
strcat(combine, fname);
|
|
||||||
|
|
||||||
if ((fp = fopen(combine, "rb")) != NULL) {
|
|
||||||
nasm_free(combine);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nasm_free(combine);
|
|
||||||
pPrevPath = pp_get_include_path_ptr(pPrevPath);
|
|
||||||
if (pPrevPath == NULL)
|
|
||||||
break;
|
|
||||||
prefix = *pPrevPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp == NULL)
|
|
||||||
error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
|
error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
|
||||||
fname);
|
fname);
|
||||||
else if (fseek(fp, 0L, SEEK_END) < 0)
|
} else if (fseek(fp, 0L, SEEK_END) < 0) {
|
||||||
error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
|
error(ERR_NONFATAL, "`incbin': unable to seek on file `%s'",
|
||||||
fname);
|
fname);
|
||||||
else {
|
} else {
|
||||||
static char buf[2048];
|
static char buf[2048];
|
||||||
int32_t t = instruction->times;
|
int32_t t = instruction->times;
|
||||||
int32_t base = 0;
|
int32_t base = 0;
|
||||||
|
@ -694,34 +675,15 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, uint32_t cp,
|
||||||
char fname[FILENAME_MAX];
|
char fname[FILENAME_MAX];
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int32_t len;
|
int32_t len;
|
||||||
char *prefix = "", *combine;
|
|
||||||
char **pPrevPath = NULL;
|
|
||||||
|
|
||||||
len = FILENAME_MAX - 1;
|
len = FILENAME_MAX - 1;
|
||||||
if (len > instruction->eops->stringlen)
|
if (len > instruction->eops->stringlen)
|
||||||
len = instruction->eops->stringlen;
|
len = instruction->eops->stringlen;
|
||||||
strncpy(fname, instruction->eops->stringval, len);
|
strncpy(fname, instruction->eops->stringval, len);
|
||||||
fname[len] = '\0';
|
fname[len] = '\0';
|
||||||
|
|
||||||
/* added by alexfru: 'incbin' uses include paths */
|
fp = fopen(fname, "rb");
|
||||||
while (1) {
|
if (!fp)
|
||||||
combine = nasm_malloc(strlen(prefix) + len + 1);
|
|
||||||
strcpy(combine, prefix);
|
|
||||||
strcat(combine, fname);
|
|
||||||
|
|
||||||
if ((fp = fopen(combine, "rb")) != NULL) {
|
|
||||||
nasm_free(combine);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nasm_free(combine);
|
|
||||||
pPrevPath = pp_get_include_path_ptr(pPrevPath);
|
|
||||||
if (pPrevPath == NULL)
|
|
||||||
break;
|
|
||||||
prefix = *pPrevPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fp == NULL)
|
|
||||||
error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
|
error(ERR_NONFATAL, "`incbin': unable to open file `%s'",
|
||||||
fname);
|
fname);
|
||||||
else if (fseek(fp, 0L, SEEK_END) < 0)
|
else if (fseek(fp, 0L, SEEK_END) < 0)
|
||||||
|
|
|
@ -930,6 +930,8 @@ int src_get(int32_t *xline, char **xname)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX: This is broken for strings which contain multiple quotes...
|
||||||
|
NASM doesn't have a sane syntax for dealing with those currently. */
|
||||||
void nasm_quote(char **str)
|
void nasm_quote(char **str)
|
||||||
{
|
{
|
||||||
int ln = strlen(*str);
|
int ln = strlen(*str);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
%assign
|
%assign
|
||||||
%clear
|
%clear
|
||||||
%define
|
%define
|
||||||
|
%depend
|
||||||
%elif*
|
%elif*
|
||||||
%else
|
%else
|
||||||
%endif
|
%endif
|
||||||
|
@ -34,6 +35,7 @@
|
||||||
%line
|
%line
|
||||||
%local
|
%local
|
||||||
%macro
|
%macro
|
||||||
|
%pathsearch
|
||||||
%pop
|
%pop
|
||||||
%push
|
%push
|
||||||
%rep
|
%rep
|
||||||
|
|
188
preproc.c
188
preproc.c
|
@ -1276,7 +1276,8 @@ static bool in_list(const StrList *list, const char *str)
|
||||||
* the include path one by one until it finds the file or reaches
|
* the include path one by one until it finds the file or reaches
|
||||||
* the end of the path.
|
* the end of the path.
|
||||||
*/
|
*/
|
||||||
static FILE *inc_fopen(const char *file)
|
static FILE *inc_fopen(const char *file, StrList **dhead, StrList **dtail,
|
||||||
|
bool missing_ok)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *prefix = "";
|
char *prefix = "";
|
||||||
|
@ -1290,29 +1291,33 @@ static FILE *inc_fopen(const char *file)
|
||||||
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);
|
||||||
fp = fopen(sl->str, "r");
|
fp = fopen(sl->str, "r");
|
||||||
if (fp && dephead && !in_list(*dephead, sl->str)) {
|
if (fp && dhead && !in_list(*dhead, sl->str)) {
|
||||||
sl->next = NULL;
|
sl->next = NULL;
|
||||||
*deptail = sl;
|
*dtail = sl;
|
||||||
deptail = &sl->next;
|
dtail = &sl->next;
|
||||||
} else {
|
} else {
|
||||||
nasm_free(sl);
|
nasm_free(sl);
|
||||||
}
|
}
|
||||||
if (fp)
|
if (fp)
|
||||||
return fp;
|
return fp;
|
||||||
if (!ip)
|
if (!ip) {
|
||||||
break;
|
if (!missing_ok)
|
||||||
prefix = ip->path;
|
break;
|
||||||
ip = ip->next;
|
prefix = NULL;
|
||||||
|
} else {
|
||||||
|
prefix = ip->path;
|
||||||
|
ip = ip->next;
|
||||||
|
}
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
prefix_len = strlen(prefix);
|
prefix_len = strlen(prefix);
|
||||||
} else {
|
} else {
|
||||||
/* -MG given and file not found */
|
/* -MG given and file not found */
|
||||||
if (dephead && !in_list(*dephead, file)) {
|
if (dhead && !in_list(*dhead, file)) {
|
||||||
sl = nasm_malloc(len+1+sizeof sl->next);
|
sl = nasm_malloc(len+1+sizeof sl->next);
|
||||||
sl->next = NULL;
|
sl->next = NULL;
|
||||||
strcpy(sl->str, file);
|
strcpy(sl->str, file);
|
||||||
*deptail = sl;
|
*dtail = sl;
|
||||||
deptail = &sl->next;
|
dtail = &sl->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1681,7 +1686,9 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expand macros in a string. Used in %error and %include directives.
|
* Expand macros in a string. Used in %error directives (and it should
|
||||||
|
* almost certainly be removed from there, too.)
|
||||||
|
*
|
||||||
* First tokenize the string, apply "expand_smacro" and then de-tokenize back.
|
* First tokenize the string, apply "expand_smacro" and then de-tokenize back.
|
||||||
* The returned variable should ALWAYS be freed after usage.
|
* The returned variable should ALWAYS be freed after usage.
|
||||||
*/
|
*/
|
||||||
|
@ -2060,9 +2067,37 @@ static int do_directive(Token * tline)
|
||||||
free_tlist(origline);
|
free_tlist(origline);
|
||||||
return DIRECTIVE_FOUND;
|
return DIRECTIVE_FOUND;
|
||||||
|
|
||||||
case PP_INCLUDE:
|
case PP_DEPEND:
|
||||||
tline = expand_smacros(tline->next);
|
tline = expand_smacro(tline->next);
|
||||||
skip_white_(tline);
|
skip_white_(tline);
|
||||||
|
if (!tline || (tline->type != TOK_STRING &&
|
||||||
|
tline->type != TOK_INTERNAL_STRING)) {
|
||||||
|
error(ERR_NONFATAL, "`%%depend' expects a file name");
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND; /* but we did _something_ */
|
||||||
|
}
|
||||||
|
if (tline->next)
|
||||||
|
error(ERR_WARNING,
|
||||||
|
"trailing garbage after `%%depend' ignored");
|
||||||
|
if (tline->type != TOK_INTERNAL_STRING) {
|
||||||
|
p = tline->text + 1; /* point past the quote to the name */
|
||||||
|
p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
|
||||||
|
} else
|
||||||
|
p = tline->text; /* internal_string is easier */
|
||||||
|
if (dephead && !in_list(*dephead, p)) {
|
||||||
|
StrList *sl = nasm_malloc(strlen(p)+1+sizeof sl->next);
|
||||||
|
sl->next = NULL;
|
||||||
|
strcpy(sl->str, p);
|
||||||
|
*deptail = sl;
|
||||||
|
deptail = &sl->next;
|
||||||
|
}
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND;
|
||||||
|
|
||||||
|
case PP_INCLUDE:
|
||||||
|
tline = expand_smacro(tline->next);
|
||||||
|
skip_white_(tline);
|
||||||
|
|
||||||
if (!tline || (tline->type != TOK_STRING &&
|
if (!tline || (tline->type != TOK_STRING &&
|
||||||
tline->type != TOK_INTERNAL_STRING)) {
|
tline->type != TOK_INTERNAL_STRING)) {
|
||||||
error(ERR_NONFATAL, "`%%include' expects a file name");
|
error(ERR_NONFATAL, "`%%include' expects a file name");
|
||||||
|
@ -2080,8 +2115,8 @@ static int do_directive(Token * tline)
|
||||||
inc = nasm_malloc(sizeof(Include));
|
inc = nasm_malloc(sizeof(Include));
|
||||||
inc->next = istk;
|
inc->next = istk;
|
||||||
inc->conds = NULL;
|
inc->conds = NULL;
|
||||||
inc->fp = inc_fopen(p);
|
inc->fp = inc_fopen(p, dephead, deptail, pass == 0);
|
||||||
if (!inc->fp && pass == 0) {
|
if (!inc->fp) {
|
||||||
/* -MG given but file not found */
|
/* -MG given but file not found */
|
||||||
nasm_free(inc);
|
nasm_free(inc);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2153,7 +2188,7 @@ static int do_directive(Token * tline)
|
||||||
if (tok_type_(tline, TOK_STRING)) {
|
if (tok_type_(tline, TOK_STRING)) {
|
||||||
p = tline->text + 1; /* point past the quote to the name */
|
p = tline->text + 1; /* point past the quote to the name */
|
||||||
p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
|
p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
|
||||||
expand_macros_in_string(&p);
|
expand_macros_in_string(&p);
|
||||||
error(ERR_NONFATAL, "%s", p);
|
error(ERR_NONFATAL, "%s", p);
|
||||||
nasm_free(p);
|
nasm_free(p);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2596,6 +2631,76 @@ static int do_directive(Token * tline)
|
||||||
free_tlist(origline);
|
free_tlist(origline);
|
||||||
return DIRECTIVE_FOUND;
|
return DIRECTIVE_FOUND;
|
||||||
|
|
||||||
|
case PP_PATHSEARCH:
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
StrList *xsl = NULL;
|
||||||
|
|
||||||
|
casesense = true;
|
||||||
|
|
||||||
|
tline = tline->next;
|
||||||
|
skip_white_(tline);
|
||||||
|
tline = expand_id(tline);
|
||||||
|
if (!tline || (tline->type != TOK_ID &&
|
||||||
|
(tline->type != TOK_PREPROC_ID ||
|
||||||
|
tline->text[1] != '$'))) {
|
||||||
|
error(ERR_NONFATAL,
|
||||||
|
"`%%pathsearch' expects a macro identifier as first parameter");
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND;
|
||||||
|
}
|
||||||
|
ctx = get_ctx(tline->text, false);
|
||||||
|
|
||||||
|
mname = tline->text;
|
||||||
|
last = tline;
|
||||||
|
tline = expand_smacro(tline->next);
|
||||||
|
last->next = NULL;
|
||||||
|
|
||||||
|
t = tline;
|
||||||
|
while (tok_type_(t, TOK_WHITESPACE))
|
||||||
|
t = t->next;
|
||||||
|
|
||||||
|
if (!t || (t->type != TOK_STRING &&
|
||||||
|
t->type != TOK_INTERNAL_STRING)) {
|
||||||
|
error(ERR_NONFATAL, "`%%pathsearch' expects a file name");
|
||||||
|
free_tlist(tline);
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND; /* but we did _something_ */
|
||||||
|
}
|
||||||
|
if (t->next)
|
||||||
|
error(ERR_WARNING,
|
||||||
|
"trailing garbage after `%%pathsearch' ignored");
|
||||||
|
if (t->type != TOK_INTERNAL_STRING) {
|
||||||
|
p = t->text + 1; /* point past the quote to the name */
|
||||||
|
p[strlen(p) - 1] = '\0'; /* remove the trailing quote */
|
||||||
|
} else
|
||||||
|
p = t->text; /* internal_string is easier */
|
||||||
|
|
||||||
|
fp = inc_fopen(p, &xsl, &xsl, true);
|
||||||
|
if (fp) {
|
||||||
|
p = xsl->str;
|
||||||
|
fclose(fp); /* Don't actually care about the file */
|
||||||
|
}
|
||||||
|
macro_start = nasm_malloc(sizeof(*macro_start));
|
||||||
|
macro_start->next = NULL;
|
||||||
|
macro_start->text = nasm_strdup(p);
|
||||||
|
nasm_quote(¯o_start->text);
|
||||||
|
macro_start->type = TOK_STRING;
|
||||||
|
macro_start->mac = NULL;
|
||||||
|
if (xsl)
|
||||||
|
nasm_free(xsl);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We now have a macro name, an implicit parameter count of
|
||||||
|
* zero, and a string token to use as an expansion. Create
|
||||||
|
* and store an SMacro.
|
||||||
|
*/
|
||||||
|
define_smacro(ctx, mname, casesense, 0, macro_start);
|
||||||
|
free_tlist(tline);
|
||||||
|
free_tlist(origline);
|
||||||
|
return DIRECTIVE_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
case PP_STRLEN:
|
case PP_STRLEN:
|
||||||
casesense = true;
|
casesense = true;
|
||||||
|
|
||||||
|
@ -4032,55 +4137,6 @@ void pp_include_path(char *path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* added by alexfru:
|
|
||||||
*
|
|
||||||
* This function is used to "export" the include paths, e.g.
|
|
||||||
* the paths specified in the '-I' command switch.
|
|
||||||
* The need for such exporting is due to the 'incbin' directive,
|
|
||||||
* which includes raw binary files (unlike '%include', which
|
|
||||||
* includes text source files). It would be real nice to be
|
|
||||||
* able to specify paths to search for incbin'ned files also.
|
|
||||||
* So, this is a simple workaround.
|
|
||||||
*
|
|
||||||
* The function use is simple:
|
|
||||||
*
|
|
||||||
* The 1st call (with NULL argument) returns a pointer to the 1st path
|
|
||||||
* (char** type) or NULL if none include paths available.
|
|
||||||
*
|
|
||||||
* All subsequent calls take as argument the value returned by this
|
|
||||||
* function last. The return value is either the next path
|
|
||||||
* (char** type) or NULL if the end of the paths list is reached.
|
|
||||||
*
|
|
||||||
* It is maybe not the best way to do things, but I didn't want
|
|
||||||
* to export too much, just one or two functions and no types or
|
|
||||||
* variables exported.
|
|
||||||
*
|
|
||||||
* Can't say I like the current situation with e.g. this path list either,
|
|
||||||
* it seems to be never deallocated after creation...
|
|
||||||
*/
|
|
||||||
char **pp_get_include_path_ptr(char **pPrevPath)
|
|
||||||
{
|
|
||||||
/* This macro returns offset of a member of a structure */
|
|
||||||
#define GetMemberOffset(StructType,MemberName)\
|
|
||||||
((size_t)&((StructType*)0)->MemberName)
|
|
||||||
IncPath *i;
|
|
||||||
|
|
||||||
if (pPrevPath == NULL) {
|
|
||||||
if (ipath != NULL)
|
|
||||||
return &ipath->path;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
i = (IncPath *) ((char *)pPrevPath - GetMemberOffset(IncPath, path));
|
|
||||||
i = i->next;
|
|
||||||
if (i != NULL)
|
|
||||||
return &i->path;
|
|
||||||
else
|
|
||||||
return NULL;
|
|
||||||
#undef GetMemberOffset
|
|
||||||
}
|
|
||||||
|
|
||||||
void pp_pre_include(char *fname)
|
void pp_pre_include(char *fname)
|
||||||
{
|
{
|
||||||
Token *inc, *space, *name;
|
Token *inc, *space, *name;
|
||||||
|
|
|
@ -15,7 +15,6 @@ extern const char * const pp_directives[];
|
||||||
|
|
||||||
enum preproc_token pp_token_hash(const char *token);
|
enum preproc_token pp_token_hash(const char *token);
|
||||||
void pp_include_path(char *);
|
void pp_include_path(char *);
|
||||||
char **pp_get_include_path_ptr(char **pPrevPath);
|
|
||||||
void pp_pre_include(char *);
|
void pp_pre_include(char *);
|
||||||
void pp_pre_define(char *);
|
void pp_pre_define(char *);
|
||||||
void pp_pre_undefine(char *);
|
void pp_pre_undefine(char *);
|
||||||
|
|
|
@ -141,3 +141,11 @@ __SECT__
|
||||||
%imacro default 1+.nolist
|
%imacro default 1+.nolist
|
||||||
[default %1]
|
[default %1]
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%imacro incbin 1-2+.nolist 0
|
||||||
|
%push _incbin
|
||||||
|
%pathsearch %$dep %1
|
||||||
|
%depend %$dep
|
||||||
|
incbin %$dep,%2
|
||||||
|
%pop
|
||||||
|
%endmacro
|
||||||
|
|
Loading…
Reference in a new issue