summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2016-05-09 13:59:44 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2016-05-09 13:59:44 -0700
commit4def1a8db462548f60b3b5b44c2ee585c21af9e0 (patch)
tree4d179aa1f1de2a607927cfd0aff0617450c0365c
parentb4f734fb844dbc4cc29304e952b33aa9fc96e398 (diff)
downloadnasm-4def1a8db462548f60b3b5b44c2ee585c21af9e0.tar.gz
Show the expanded macro stack when displaying diagnostics
It can be hard to find errors inside potentially nested macros. Show the mmacro expansion stack when printing diagnostics. Note that a list file doesn't help for errors that are detected before the code-generation pass. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--nasm.c13
-rw-r--r--nasm.h7
-rw-r--r--nasmlib.c6
-rw-r--r--nasmlib.h2
-rw-r--r--preproc-nop.c12
-rw-r--r--preproc.c37
-rw-r--r--test/macroerr.asm11
-rw-r--r--test/macroerr.inc3
8 files changed, 78 insertions, 13 deletions
diff --git a/nasm.c b/nasm.c
index f46cf4fa..3bf98af7 100644
--- a/nasm.c
+++ b/nasm.c
@@ -128,7 +128,7 @@ static struct RAA *offsets;
static struct SAA *forwrefs; /* keep track of forward references */
static const struct forwrefinfo *forwref;
-static struct preproc_ops *preproc;
+static const struct preproc_ops *preproc;
#define OP_NORMAL (1u << 0)
#define OP_PREPROCESS (1u << 1)
@@ -1876,12 +1876,11 @@ static void nasm_verror_gnu(int severity, const char *fmt, va_list ap)
return;
if (!(severity & ERR_NOFILE))
- src_get(&lineno, &currentfile);
+ src_get(&lineno, &currentfile);
if (!skip_this_pass(severity)) {
if (currentfile) {
fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
- nasm_free(currentfile);
} else {
fputs("nasm: ", error_file);
}
@@ -2002,7 +2001,7 @@ static void nasm_verror_common(int severity, const char *fmt, va_list args)
}
vsnprintf(msg, sizeof msg - 64, fmt, args);
- if (severity & ERR_WARN_MASK) {
+ if ((severity & (ERR_WARN_MASK|ERR_PP_LISTMACRO)) == ERR_WARN_MASK) {
char *p = strchr(msg, '\0');
snprintf(p, 64, " [-w+%s]", warnings[WARN_IDX(severity)].name);
}
@@ -2010,6 +2009,10 @@ static void nasm_verror_common(int severity, const char *fmt, va_list args)
if (!skip_this_pass(severity))
fprintf(error_file, "%s%s\n", pfx, msg);
+ /* Are we recursing from error_list_macros? */
+ if (severity & ERR_PP_LISTMACRO)
+ return;
+
/*
* Don't suppress this with skip_this_pass(), or we don't get
* pass1 or preprocessor warnings in the list file
@@ -2020,6 +2023,8 @@ static void nasm_verror_common(int severity, const char *fmt, va_list args)
if (severity & ERR_USAGE)
want_usage = true;
+ preproc->error_list_macros(severity);
+
switch (severity & ERR_MASK) {
case ERR_DEBUG:
/* no further action, by definition */
diff --git a/nasm.h b/nasm.h
index aa2409bf..663cc21e 100644
--- a/nasm.h
+++ b/nasm.h
@@ -342,10 +342,13 @@ struct preproc_ops {
/* Include path from command line */
void (*include_path)(char *path);
+
+ /* Unwind the macro stack when printing an error message */
+ void (*error_list_macros)(int severity);
};
-extern struct preproc_ops nasmpp;
-extern struct preproc_ops preproc_nop;
+extern const struct preproc_ops nasmpp;
+extern const struct preproc_ops preproc_nop;
/*
* Some lexical properties of the NASM source language, included
diff --git a/nasmlib.c b/nasmlib.c
index a1a3191f..2bea64b3 100644
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -570,6 +570,12 @@ int32_t src_set_linnum(int32_t newline)
return oldline;
}
+/* This returns a pointer, not a copy, to the current fname */
+const char *src_get_fname(void)
+{
+ return file_name;
+}
+
int32_t src_get_linnum(void)
{
return line_number;
diff --git a/nasmlib.h b/nasmlib.h
index d307f777..08b2dc30 100644
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -107,6 +107,7 @@ static inline vefunc nasm_set_verror(vefunc ve)
#define ERR_NO_SEVERITY 0x00000100 /* suppress printing severity */
#define ERR_PP_PRECOND 0x00000200 /* for preprocessor use */
+#define ERR_PP_LISTMACRO 0x00000400 /* from preproc->error_list_macros() */
/*
* These codes define specific types of suppressible warning.
@@ -392,6 +393,7 @@ int bsi(const char *string, const char **array, int size);
int bsii(const char *string, const char **array, int size);
char *src_set_fname(char *newname);
+const char *src_get_fname(void);
int32_t src_set_linnum(int32_t newline);
int32_t src_get_linnum(void);
/*
diff --git a/preproc-nop.c b/preproc-nop.c
index 8024cac2..f8513a8a 100644
--- a/preproc-nop.c
+++ b/preproc-nop.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2012 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2016 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -170,7 +170,12 @@ static void nop_include_path(char *path)
(void)path;
}
-struct preproc_ops preproc_nop = {
+static void nop_error_list_macros(int severity)
+{
+ (void)severity;
+}
+
+const struct preproc_ops preproc_nop = {
nop_reset,
nop_getline,
nop_cleanup,
@@ -178,5 +183,6 @@ struct preproc_ops preproc_nop = {
nop_pre_define,
nop_pre_undefine,
nop_pre_include,
- nop_include_path
+ nop_include_path,
+ nop_error_list_macros,
};
diff --git a/preproc.c b/preproc.c
index 9576fe90..fa2dcaf3 100644
--- a/preproc.c
+++ b/preproc.c
@@ -155,6 +155,9 @@ struct MMacro {
uint64_t unique;
int lineno; /* Current line number on expansion */
uint64_t condcnt; /* number of if blocks... */
+
+ char *fname; /* File where defined */
+ int32_t xline; /* First line in macro */
};
@@ -625,6 +628,7 @@ static void free_mmacro(MMacro * m)
free_tlist(m->dlist);
nasm_free(m->defaults);
free_llist(m->expansion);
+ nasm_free(m->fname);
nasm_free(m);
}
@@ -2738,7 +2742,7 @@ issue_error:
pp_directives[i]);
return DIRECTIVE_FOUND;
}
- defining = nasm_malloc(sizeof(MMacro));
+ defining = nasm_zalloc(sizeof(MMacro));
defining->max_depth =
(i == PP_RMACRO) || (i == PP_IRMACRO) ? DEADMAN_LIMIT : 0;
defining->casesense = (i == PP_MACRO) || (i == PP_RMACRO);
@@ -2748,6 +2752,8 @@ issue_error:
return DIRECTIVE_FOUND;
}
+ src_get(&defining->xline, &defining->fname);
+
mmac = (MMacro *) hash_findix(&mmacros, defining->name);
while (mmac) {
if (!strcmp(mmac->name, defining->name) &&
@@ -5011,7 +5017,7 @@ static char *pp_getline(void)
/* only set line and file name if there's a next node */
if (i->next) {
src_set_linnum(i->lineno);
- nasm_free(src_set_fname(nasm_strdup(i->fname)));
+ src_set_fname(nasm_strdup(i->fname));
}
istk = i->next;
lfmt->downlevel(LIST_INCLUDE);
@@ -5237,7 +5243,29 @@ static void make_tok_num(Token * tok, int64_t val)
tok->type = TOK_NUMBER;
}
-struct preproc_ops nasmpp = {
+static void pp_error_list_macros(int severity)
+{
+ MMacro *m;
+ int32_t saved_line;
+ const char *saved_fname = NULL;
+
+ severity |= ERR_PP_LISTMACRO | ERR_NO_SEVERITY;
+ saved_line = src_get_linnum();
+ saved_fname = src_get_fname();
+
+ list_for_each(m, istk->mstk) {
+ if (m->name && !m->nolist) {
+ src_set_linnum(m->xline + m->lineno);
+ src_set_fname(m->fname);
+ nasm_error(severity, "from macro `%s' defined here", m->name);
+ }
+ }
+
+ src_set_fname((char *)saved_fname);
+ src_set_linnum(saved_line);
+}
+
+const struct preproc_ops nasmpp = {
pp_reset,
pp_getline,
pp_cleanup,
@@ -5245,5 +5273,6 @@ struct preproc_ops nasmpp = {
pp_pre_define,
pp_pre_undefine,
pp_pre_include,
- pp_include_path
+ pp_include_path,
+ pp_error_list_macros,
};
diff --git a/test/macroerr.asm b/test/macroerr.asm
new file mode 100644
index 00000000..5f1c93e2
--- /dev/null
+++ b/test/macroerr.asm
@@ -0,0 +1,11 @@
+%include "macroerr.inc"
+
+%macro bluttan 1
+ mov eax,%1
+%endmacro
+
+ bluttan ptr
+ blej ptr
+ dd ptr, ptr
+
+ptr:
diff --git a/test/macroerr.inc b/test/macroerr.inc
new file mode 100644
index 00000000..f40f7e60
--- /dev/null
+++ b/test/macroerr.inc
@@ -0,0 +1,3 @@
+%macro blej 1
+ mov eax,%1
+%endmacro