aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--asm/nasm.c107
-rw-r--r--asm/preproc.c255
-rw-r--r--asm/srcfile.c10
-rw-r--r--asm/srcfile.h16
-rw-r--r--travis/test/weirdpaste.i.t7
5 files changed, 235 insertions, 160 deletions
diff --git a/asm/nasm.c b/asm/nasm.c
index 51a74dfc..a9793a20 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -55,6 +55,7 @@
#include "outform.h"
#include "listing.h"
#include "iflag.h"
+#include "quote.h"
#include "ver.h"
/*
@@ -292,15 +293,6 @@ static void increment_offset(int64_t delta)
set_curr_offs(location.offset);
}
-static void nasm_fputs(const char *line, FILE * outfile)
-{
- if (outfile) {
- fputs(line, outfile);
- putc('\n', outfile);
- } else
- puts(line);
-}
-
/*
* Define system-defined macros that are not part of
* macros/standard.mac.
@@ -449,6 +441,41 @@ static int64_t make_posix_time(const struct tm *tm)
return t;
}
+/*
+ * Quote a filename string if and only if it is necessary.
+ * It is considered necessary if any one of these is true:
+ * 1. The filename contains control characters;
+ * 2. The filename starts or ends with a space or quote mark;
+ * 3. The filename is empty.
+ *
+ * The filename is returned in a newly allocated buffer.
+ */
+static char *nasm_quote_filename(const char *fn)
+{
+ const char *p = fn;
+
+ if (!p || !*p)
+ return nasm_strdup("\"\"");
+
+ if (*p <= ' ' || nasm_isquote(*p)) {
+ goto quote;
+ } else {
+ while (*p) {
+ if (*p < ' ')
+ goto quote;
+ p++;
+ }
+ if (p[-1] <= ' ' || nasm_isquote(p[-1]))
+ goto quote;
+ }
+
+ /* Quoting not necessary */
+ return nasm_strdup(fn);
+
+quote:
+ return nasm_quote(fn, NULL);
+}
+
static void timestamp(void)
{
struct compile_time * const oct = &official_compile_time;
@@ -595,15 +622,20 @@ int main(int argc, char **argv)
} else if (operating_mode & OP_PREPROCESS) {
char *line;
const char *file_name = NULL;
- int32_t prior_linnum = 0;
- int lineinc = 0;
+ char *quoted_file_name = nasm_quote_filename(file_name);
+ int32_t linnum = 0;
+ int32_t lineinc = 0;
+ FILE *out;
if (outname) {
ofile = nasm_open_write(outname, NF_TEXT);
if (!ofile)
nasm_fatal("unable to open output file `%s'", outname);
- } else
+ out = ofile;
+ } else {
ofile = NULL;
+ out = stdout;
+ }
location.known = false;
@@ -614,22 +646,47 @@ int main(int argc, char **argv)
/*
* We generate %line directives if needed for later programs
*/
- int32_t linnum = prior_linnum += lineinc;
- int altline = src_get(&linnum, &file_name);
- if (altline) {
- if (altline == 1 && lineinc == 1)
- nasm_fputs("", ofile);
- else {
- lineinc = (altline != -1 || lineinc != 1);
- fprintf(ofile ? ofile : stdout,
- "%%line %"PRId32"+%d %s\n", linnum, lineinc,
- file_name);
+ struct src_location where = src_where();
+ if (file_name != where.filename) {
+ file_name = where.filename;
+ linnum = -1; /* Force a new %line statement */
+ lineinc = file_name ? 1 : 0;
+ nasm_free(quoted_file_name);
+ quoted_file_name = nasm_quote_filename(file_name);
+ } else if (lineinc) {
+ if (linnum + lineinc == where.lineno) {
+ /* Add one blank line to account for increment */
+ fputc('\n', out);
+ linnum += lineinc;
+ } else if (linnum - lineinc == where.lineno) {
+ /*
+ * Standing still, probably a macro. Set increment
+ * to zero.
+ */
+ lineinc = 0;
}
- prior_linnum = linnum;
+ } else {
+ /* lineinc == 0 */
+ if (linnum + 1 == where.lineno)
+ lineinc = 1;
}
- nasm_fputs(line, ofile);
- nasm_free(line);
+
+ /* Skip blank lines if we will need a %line anyway */
+ if (linnum == -1 && !line[0])
+ continue;
+
+ if (linnum != where.lineno) {
+ fprintf(out, "%%line %"PRId32"%+"PRId32" %s\n",
+ where.lineno, lineinc, quoted_file_name);
+ }
+ linnum = where.lineno + lineinc;
+
+ fputs(line, out);
+ fputc('\n', out);
}
+
+ nasm_free(quoted_file_name);
+
preproc->cleanup_pass();
reset_warnings();
if (ofile)
diff --git a/asm/preproc.c b/asm/preproc.c
index fd06ba89..69c87087 100644
--- a/asm/preproc.c
+++ b/asm/preproc.c
@@ -279,15 +279,12 @@ struct MMacro {
struct mstk dstk; /* Macro definitions stack */
Token **params; /* actual parameters */
Token *iline; /* invocation line */
+ struct src_location where; /* location of definition */
unsigned int nparam, rotate;
char *iname; /* name invoked as */
int *paramlen;
uint64_t unique;
- int lineno; /* Current line number on expansion */
uint64_t condcnt; /* number of if blocks... */
-
- const char *fname; /* File where defined */
- int32_t xline; /* First line in macro */
};
@@ -365,24 +362,18 @@ static size_t tok_strlen(const char *str)
*/
static Token *set_text(struct Token *t, const char *text, size_t len)
{
+ char *textp;
+
if (t->len > INLINE_TEXT)
nasm_free(t->text.p.ptr);
nasm_zero(t->text);
t->len = len = tok_check_len(len);
- if (len > INLINE_TEXT) {
- char *textp;
-
- t->text.p.ptr = textp = nasm_malloc(len+1);
- memcpy(textp, text, len);
- textp[len] = '\0';
- } else {
- /* Null-terminated due to nasm_zero() above */
- t->len = len;
- memcpy(t->text.a, text, len);
- }
-
+ textp = (len > INLINE_TEXT)
+ ? (t->text.p.ptr = nasm_malloc(len+1)) : t->text.a;
+ memcpy(textp, text, len);
+ textp[len] = '\0';
return t;
}
@@ -390,8 +381,10 @@ static Token *set_text(struct Token *t, const char *text, size_t len)
* Set the text field to the existing pre-allocated string, either
* taking over or freeing the allocation in the process.
*/
-static Token *set_text_free(struct Token *t, char *text, size_t len)
+static Token *set_text_free(struct Token *t, char *text, unsigned int len)
{
+ char *textp;
+
if (t->len > INLINE_TEXT)
nasm_free(t->text.p.ptr);
@@ -399,13 +392,12 @@ static Token *set_text_free(struct Token *t, char *text, size_t len)
t->len = len = tok_check_len(len);
if (len > INLINE_TEXT) {
- t->text.p.ptr = text;
- text[len] = '\0';
+ textp = t->text.p.ptr = text;
} else {
- /* Null-terminated due to nasm_zero() above */
- memcpy(t->text.a, text, len);
+ textp = memcpy(t->text.a, text, len);
nasm_free(text);
}
+ textp[len] = '\0';
return t;
}
@@ -448,6 +440,7 @@ struct Line {
Line *next;
MMacro *finishes;
Token *first;
+ struct src_location where; /* Where defined */
};
/*
@@ -459,9 +452,9 @@ struct Include {
FILE *fp;
Cond *conds;
Line *expansion;
- const char *fname;
struct mstk mstk;
- int lineno, lineinc;
+ struct src_location where; /* Filename and current line number */
+ int32_t lineinc; /* Increment given by %line */
bool nolist;
};
@@ -1306,7 +1299,6 @@ static char *line_from_file(FILE *f)
unsigned int nr_cont = 0;
bool cont = false;
char *buffer, *p;
- int32_t lineno;
size = delta;
p = buffer = nasm_malloc(size);
@@ -1366,9 +1358,8 @@ static char *line_from_file(FILE *f)
*p++ = c;
} while (c);
- lineno = src_get_linnum() + istk->lineinc +
- (nr_cont * istk->lineinc);
- src_set_linnum(lineno);
+ istk->where.lineno += (nr_cont + 1) * istk->lineinc;
+ src_set_linnum(istk->where.lineno);
return buffer;
}
@@ -1390,7 +1381,7 @@ static char *read_line(void)
return NULL;
if (!istk->nolist)
- lfmt->line(LIST_READ, src_get_linnum(), line);
+ lfmt->line(LIST_READ, istk->where.lineno, line);
return line;
}
@@ -3411,6 +3402,56 @@ static int do_directive(Token *tline, Token **output)
}
/*
+ * %line directives are always processed immediately and
+ * unconditionally, as they are intended to reflect position
+ * in externally preprocessed sources.
+ */
+ if (op == PP_LINE) {
+ /*
+ * Syntax is `%line nnn[+mmm] [filename]'
+ */
+ if (pp_noline || istk->mstk.mstk)
+ goto done;
+
+ tline = tline->next;
+ tline = skip_white(tline);
+ if (!tok_type(tline, TOK_NUMBER)) {
+ nasm_nonfatal("`%s' expects line number", dname);
+ goto done;
+ }
+ k = readnum(tok_text(tline), &err);
+ m = 1;
+ tline = tline->next;
+ if (tok_is(tline, '+') || tok_is(tline, '-')) {
+ bool minus = tok_is(tline, '-');
+ tline = tline->next;
+ if (!tok_type(tline, TOK_NUMBER)) {
+ nasm_nonfatal("`%s' expects line increment", dname);
+ goto done;
+ }
+ m = readnum(tok_text(tline), &err);
+ if (minus)
+ m = -m;
+ tline = tline->next;
+ }
+ tline = skip_white(tline);
+ if (tline) {
+ if (tline->type == TOK_STRING) {
+ src_set_fname(unquote_token(tline));
+ } else {
+ char *fname = detoken(tline, false);
+ src_set_fname(fname);
+ nasm_free(fname);
+ }
+ }
+ src_set_linnum(k);
+
+ istk->where = src_where();
+ istk->lineinc = m;
+ goto done;
+ }
+
+ /*
* If we're in a non-emitting branch of a condition construct,
* or walking to the end of an already terminated %rep block,
* we should ignore all directives except for condition
@@ -3425,7 +3466,7 @@ static int do_directive(Token *tline, Token **output)
/*
* If we're defining a macro or reading a %rep block, we should
* ignore all directives except for %macro/%imacro (which nest),
- * %endm/%endmacro, and (only if we're in a %rep block) %endrep.
+ * %endm/%endmacro, %line and (only if we're in a %rep block) %endrep.
* If we're in a %rep block, another %rep nests, so should be let through.
*/
if (defining && op != PP_MACRO && op != PP_RMACRO &&
@@ -3755,8 +3796,8 @@ static int do_directive(Token *tline, Token **output)
/* -MG given but file not found */
nasm_free(inc);
} else {
- inc->fname = src_set_fname(found_path ? found_path : p);
- inc->lineno = src_set_linnum(0);
+ src_set(0, found_path ? found_path : p);
+ inc->where = src_where();
inc->lineinc = 1;
inc->nolist = istk->nolist;
istk = inc;
@@ -3784,8 +3825,7 @@ static int do_directive(Token *tline, Token **output)
stdmacpos = pkg->macros;
nasm_new(inc);
inc->next = istk;
- inc->fname = src_set_fname(NULL);
- inc->lineno = src_set_linnum(0);
+ src_set(0, NULL);
inc->nolist = !list_option('b') || istk->nolist;
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
@@ -3980,7 +4020,7 @@ issue_error:
}
defining = def;
- src_get(&defining->xline, &defining->fname);
+ defining->where = istk->where;
mmac = (MMacro *) hash_findix(&mmacros, defining->name);
while (mmac) {
@@ -4162,7 +4202,7 @@ issue_error:
defining->mstk = istk->mstk;
defining->dstk.mstk = tmp_defining;
defining->dstk.mmac = tmp_defining ? tmp_defining->dstk.mmac : NULL;
- src_get(&defining->xline, &defining->fname);
+ defining->where = istk->where;
break;
}
@@ -4187,6 +4227,7 @@ issue_error:
l->next = istk->expansion;
l->finishes = defining;
l->first = NULL;
+ l->where = src_where();
istk->expansion = l;
istk->mstk.mstk = defining;
@@ -4571,38 +4612,7 @@ issue_error:
break;
case PP_LINE:
- /*
- * Syntax is `%line nnn[+mmm] [filename]'
- */
- if (unlikely(pp_noline))
- goto done;
-
- tline = tline->next;
- tline = skip_white(tline);
- if (!tok_type(tline, TOK_NUMBER)) {
- nasm_nonfatal("`%s' expects line number", dname);
- goto done;
- }
- k = readnum(tok_text(tline), &err);
- m = 1;
- tline = tline->next;
- if (tok_is(tline, '+')) {
- tline = tline->next;
- if (!tok_type(tline, TOK_NUMBER)) {
- nasm_nonfatal("`%s' expects line increment", dname);
- goto done;
- }
- m = readnum(tok_text(tline), &err);
- tline = tline->next;
- }
- tline = skip_white(tline);
- src_set_linnum(k);
- istk->lineinc = m;
- if (tline) {
- char *fname = detoken(tline, false);
- src_set_fname(fname);
- nasm_free(fname);
- }
+ nasm_panic("`%s' directive not preprocessed early", dname);
break;
}
@@ -6250,6 +6260,7 @@ static int expand_mmacro(Token * tline)
nasm_new(ll);
ll->next = istk->expansion;
ll->finishes = m;
+ ll->where = istk->where;
istk->expansion = ll;
/*
@@ -6269,7 +6280,6 @@ static int expand_mmacro(Token * tline)
m->rotate = 0;
m->paramlen = paramlen;
m->unique = unique++;
- m->lineno = 0;
m->condcnt = 0;
m->mstk = istk->mstk;
@@ -6280,6 +6290,7 @@ static int expand_mmacro(Token * tline)
ll->next = istk->expansion;
istk->expansion = ll;
ll->first = dup_tlist(l->first, NULL);
+ ll->where = l->where;
}
/*
@@ -6304,6 +6315,7 @@ static int expand_mmacro(Token * tline)
ll->next = istk->expansion;
istk->expansion = ll;
ll->first = startline;
+ ll->where = istk->where;
if (!dont_prepend) {
while (label->next)
label = label->next;
@@ -6446,10 +6458,13 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
/* First set up the top level input file */
nasm_new(istk);
istk->fp = nasm_open_read(file, NF_TEXT);
+ if (!istk->fp) {
+ nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'%s%s",
+ file, errno ? " " : "", errno ? strerror(errno) : "");
+ }
src_set(0, file);
+ istk->where = src_where();
istk->lineinc = 1;
- if (!istk->fp)
- nasm_fatalf(ERR_NOFILE, "unable to open input file `%s'", file);
strlist_add(deplist, file);
@@ -6459,7 +6474,8 @@ pp_reset(const char *file, enum preproc_mode mode, struct strlist *dep_list)
*/
nasm_new(inc);
inc->next = istk;
- inc->fname = src_set_fname(NULL);
+ src_set(0, NULL);
+ inc->where = src_where();
inc->nolist = !list_option('b');
istk = inc;
lfmt->uplevel(LIST_INCLUDE, 0);
@@ -6550,20 +6566,12 @@ static Token *pp_tokline(void)
*/
fm->in_progress--;
list_for_each(l, fm->expansion) {
- Token *t, *tt, **tail;
Line *ll;
- istk->mstk.mstk->lineno = 0;
nasm_new(ll);
- ll->next = istk->expansion;
- tail = &ll->first;
-
- list_for_each(t, l->first) {
- if (t->len) {
- tt = *tail = dup_Token(NULL, t);
- tail = &tt->next;
- }
- }
+ ll->next = istk->expansion;
+ ll->first = dup_tlist(l->first, NULL);
+ ll->where = l->where;
istk->expansion = ll;
}
break;
@@ -6632,6 +6640,7 @@ static Token *pp_tokline(void)
free_mmacro(m);
#endif
}
+ istk->where = l->where;
istk->expansion = l->next;
nasm_free(l);
lfmt->downlevel(LIST_MACRO);
@@ -6643,27 +6652,17 @@ static Token *pp_tokline(void)
if (istk->expansion) { /* from a macro expansion */
Line *l = istk->expansion;
- int32_t lineno;
- if (istk->mstk.mstk) {
- istk->mstk.mstk->lineno++;
- if (istk->mstk.mstk->fname)
- lineno = istk->mstk.mstk->lineno +
- istk->mstk.mstk->xline;
- else
- lineno = 0; /* Defined at init time or builtin */
- } else {
- lineno = src_get_linnum();
- }
-
- tline = l->first;
istk->expansion = l->next;
+ istk->where = l->where;
+ tline = l->first;
nasm_free(l);
- line = detoken(tline, false);
- if (!istk->nolist)
- lfmt->line(LIST_MACRO, lineno, line);
- nasm_free(line);
+ if (!istk->nolist) {
+ line = detoken(tline, false);
+ lfmt->line(LIST_MACRO, istk->where.lineno, line);
+ nasm_free(line);
+ }
} else if ((line = read_line())) {
line = prepreproc(line);
tline = tokenize(line);
@@ -6673,17 +6672,23 @@ static Token *pp_tokline(void)
* The current file has ended; work down the istk
*/
Include *i = istk;
+ Include *is;
+
if (i->fp)
fclose(i->fp);
if (i->conds) {
- /* nasm_error can't be conditionally suppressed */
+ /* nasm_fatal can't be conditionally suppressed */
nasm_fatal("expected `%%endif' before end of file");
}
- /* only set line and file name if there's a next node */
- if (i->next)
- src_set(i->lineno, i->fname);
+
+ list_for_each(is, i->next) {
+ if (is->fp) {
+ lfmt->downlevel(LIST_INCLUDE);
+ src_update(is->where);
+ break;
+ }
+ }
istk = i->next;
- lfmt->downlevel(LIST_INCLUDE);
nasm_free(i);
return &tok_pop;
}
@@ -6718,11 +6723,13 @@ static Token *pp_tokline(void)
* shove the tokenized line on to the macro definition.
*/
MMacro *mmac = defining->dstk.mmac;
+ Line *l;
- Line *l = nasm_malloc(sizeof(Line));
+ nasm_new(l);
l->next = defining->expansion;
l->first = tline;
l->finishes = NULL;
+ l->where = istk->where;
defining->expansion = l;
/*
@@ -6966,16 +6973,30 @@ static Token *make_tok_char(Token *next, char op)
return t;
}
-static void pp_list_one_macro(MMacro *m, errflags severity)
+/*
+ * Descend the istk looking for macro definitions; we have to
+ * recurse because we want to show the messages in top-down order.
+ */
+static void pp_list_macro_istk(Include *inc, errflags severity)
{
- if (!m)
- return;
-
- /* We need to print the mstk.mmac list in reverse order */
- pp_list_one_macro(m->mstk.mmac, severity);
+ MMacro *m;
+ Include *inext;
+
+ /* Find the next higher level true macro invocation if any */
+ inext = inc->next;
+ if (inext && inext->mstk.mmac) {
+ while (inext) {
+ if (inext->mstk.mstk->name) {
+ pp_list_macro_istk(inext, severity);
+ break;
+ }
+ inext = inext->next;
+ }
+ }
- if (m->name && !m->nolist) {
- src_set(m->xline + m->lineno, m->fname);
+ m = inc->mstk.mstk;
+ if (m && m->name && !m->nolist) {
+ src_update(inc->where);
nasm_error(severity, "... from macro `%s' defined", m->name);
}
}
@@ -6984,12 +7005,12 @@ static void pp_error_list_macros(errflags severity)
{
struct src_location saved;
+ if (!istk)
+ return;
+
severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY | ERR_HERE;
saved = src_where();
-
- if (istk)
- pp_list_one_macro(istk->mstk.mmac, severity);
-
+ pp_list_macro_istk(istk, severity);
src_update(saved);
}
diff --git a/asm/srcfile.c b/asm/srcfile.c
index 0f35c5af..a27fffac 100644
--- a/asm/srcfile.c
+++ b/asm/srcfile.c
@@ -85,13 +85,3 @@ void src_set(int32_t line, const char *fname)
src_set_fname(fname);
src_set_linnum(line);
}
-
-struct src_location src_update(struct src_location whence)
-{
- struct src_location oldhere = _src_here;
-
- src_set_fname(whence.filename);
- src_set_linnum(whence.lineno);
-
- return oldhere;
-}
diff --git a/asm/srcfile.h b/asm/srcfile.h
index 3af6595e..759ceabf 100644
--- a/asm/srcfile.h
+++ b/asm/srcfile.h
@@ -62,6 +62,7 @@ static inline int32_t src_get_linnum(void)
{
return _src_here.lineno;
}
+
/* Can be used when there is no need for the old information */
void src_set(int32_t line, const char *filename);
@@ -91,12 +92,23 @@ static inline int32_t src_get(int32_t *xline, const char **xname)
}
/*
- * Returns and sets/returns the current information as a structure.
+ * Returns the current information as a structure.
*/
static inline struct src_location src_where(void)
{
return _src_here;
}
-struct src_location src_update(struct src_location);
+
+/*
+ * Sets the current information. The filename member of the structure
+ * *must* have been previously returned by src_get(), src_where(), or
+ * src_get_fname() and therefore be present in the hash.
+ */
+static inline struct src_location src_update(struct src_location whence)
+{
+ struct src_location old = _src_here;
+ _src_here = whence;
+ return old;
+}
#endif /* ASM_SRCFILE_H */
diff --git a/travis/test/weirdpaste.i.t b/travis/test/weirdpaste.i.t
index ac7ddf08..1725bdf5 100644
--- a/travis/test/weirdpaste.i.t
+++ b/travis/test/weirdpaste.i.t
@@ -1,9 +1,4 @@
-%line 3+1 ./travis/test/weirdpaste.asm
-
-
-
-%line 10+1 ./travis/test/weirdpaste.asm
-
+%line 11+1 ./travis/test/weirdpaste.asm
dw 25
%line 18+1 ./travis/test/weirdpaste.asm