summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin (Intel) <hpa@zytor.com>2019-01-11 13:13:03 -0800
committerH. Peter Anvin (Intel) <hpa@zytor.com>2019-01-11 13:13:03 -0800
commit1df7263ae937ac11abb2c6938b8891745af91ce6 (patch)
treee2f0e201f2dbfc7f036ff701e61027c02f1391f0
parent38ddb19977c109ae18d69699d177c7d34c9d0455 (diff)
downloadnasm-1df7263ae937ac11abb2c6938b8891745af91ce6.tar.gz
warnings: add [warning push] and [warning pop]
Add [warning push] and [warning pop] directives. Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
-rw-r--r--asm/directiv.c11
-rw-r--r--asm/error.c76
-rw-r--r--asm/nasm.c37
-rwxr-xr-xasm/warnings.pl4
-rw-r--r--doc/changes.src6
-rw-r--r--doc/nasmdoc.src4
-rw-r--r--include/error.h6
-rw-r--r--test/warnstack.asm10
8 files changed, 124 insertions, 30 deletions
diff --git a/asm/directiv.c b/asm/directiv.c
index 943e532f..cd13938d 100644
--- a/asm/directiv.c
+++ b/asm/directiv.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2019 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -421,7 +421,14 @@ bool process_directives(char *directive)
break;
}
- case D_WARNING: /* [WARNING {+|-|*}warn-name] */
+ case D_WARNING: /* [WARNING {push|pop|{+|-|*}warn-name}] */
+ value = nasm_skip_spaces(value);
+ if ((*value | 0x20) == 'p') {
+ if (!nasm_stricmp(value, "push"))
+ push_warnings();
+ else if (!nasm_stricmp(value, "pop"))
+ pop_warnings();
+ }
set_warning_status(value);
break;
diff --git a/asm/error.c b/asm/error.c
index ef3fd988..4e86a0d7 100644
--- a/asm/error.c
+++ b/asm/error.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 1996-2018 The NASM Authors - All Rights Reserved
+ * Copyright 1996-2019 The NASM Authors - All Rights Reserved
* See the file AUTHORS included with the NASM distribution for
* the specific copyright holders.
*
@@ -85,7 +85,7 @@ void nasm_warn(errflags severity, const char *fmt, ...)
{
nasm_do_error(ERR_WARNING|severity);
}
-
+
fatal_func nasm_panic_from_macro(const char *file, int line)
{
nasm_panic("internal error at %s:%d\n", file, line);
@@ -96,6 +96,72 @@ fatal_func nasm_assert_failed(const char *file, int line, const char *msg)
nasm_panic("assertion %s failed at %s:%d", msg, file, line);
}
+
+/*
+ * Warning stack management. Note that there is an implicit "push"
+ * after the command line has been parsed, but this particular push
+ * cannot be popped.
+ */
+struct warning_stack {
+ struct warning_stack *next;
+ uint8_t state[sizeof warning_state];
+};
+static struct warning_stack *warning_stack, *warning_state_init;
+
+/* Push the warning status onto the warning stack */
+void push_warnings(void)
+{
+ struct warning_stack *ws;
+
+ ws = nasm_malloc(sizeof *ws);
+ memcpy(ws->state, warning_state, sizeof warning_state);
+ ws->next = warning_stack;
+ warning_stack = ws;
+}
+
+/* Pop the warning status off the warning stack */
+void pop_warnings(void)
+{
+ struct warning_stack *ws = warning_stack;
+
+ memcpy(warning_state, ws->state, sizeof warning_state);
+ if (!ws->next) {
+ /*!
+ *!warn-stack-empty [on] warning stack empty
+ *! a [WARNING POP] directive was executed when
+ *! the warning stack is empty. This is treated
+ *! as a [WARNING *all] directive.
+ */
+ nasm_warn(WARN_WARN_STACK_EMPTY, "warning stack empty");
+ } else {
+ warning_stack = ws->next;
+ nasm_free(ws);
+ }
+}
+
+/* Call after the command line is parsed, but before the first pass */
+void init_warnings(void)
+{
+ push_warnings();
+ warning_state_init = warning_stack;
+}
+
+
+/* Call after each pass */
+void reset_warnings(void)
+{
+ struct warning_stack *ws = warning_stack;
+
+ /* Unwind the warning stack. We do NOT delete the last entry! */
+ while (ws->next) {
+ struct warning_stack *wst = ws;
+ ws = ws->next;
+ nasm_free(wst);
+ }
+ warning_stack = ws;
+ memcpy(warning_state, ws->state, sizeof warning_state);
+}
+
/*
* This is called when processing a -w or -W option, or a warning directive.
* Returns on if if the action was successful.
@@ -120,6 +186,7 @@ bool set_warning_status(const char *value)
int i;
value = nasm_skip_spaces(value);
+
switch (*value) {
case '-':
action = WID_OFF;
@@ -185,7 +252,8 @@ bool set_warning_status(const char *value)
break;
case WID_RESET:
warning_state[i] &= ~mask;
- warning_state[i] |= warning_state_init[i] & mask;
+ warning_state[i] |=
+ warning_state_init->state[i] & mask;
break;
}
}
@@ -199,6 +267,6 @@ bool set_warning_status(const char *value)
*/
nasm_warn(WARN_UNKNOWN_WARNING, "unknown warning name: %s", name);
}
-
+
return ok;
}
diff --git a/asm/nasm.c b/asm/nasm.c
index 6a0a8b00..283f45d3 100644
--- a/asm/nasm.c
+++ b/asm/nasm.c
@@ -511,7 +511,7 @@ int main(int argc, char **argv)
}
/* Save away the default state of warnings */
- memcpy(warning_state_init, warning_state, sizeof warning_state_init);
+ init_warnings();
/* Dependency filename if we are also doing other things */
if (!depend_file && (operating_mode & ~OP_DEPEND)) {
@@ -550,6 +550,7 @@ int main(int argc, char **argv)
while ((line = preproc->getline()))
nasm_free(line);
preproc->cleanup_pass();
+ reset_warnings();
} else if (operating_mode & OP_PREPROCESS) {
char *line;
const char *file_name = NULL;
@@ -568,9 +569,6 @@ int main(int argc, char **argv)
_pass_type = PASS_FIRST; /* We emulate this assembly pass */
preproc->reset(inname, PP_PREPROC, depend_list);
- /* Revert all warnings to the default state */
- memcpy(warning_state, warning_state_init, sizeof warning_state);
-
while ((line = preproc->getline())) {
/*
* We generate %line directives if needed for later programs
@@ -592,6 +590,7 @@ int main(int argc, char **argv)
nasm_free(line);
}
preproc->cleanup_pass();
+ reset_warnings();
if (ofile)
fclose(ofile);
if (ofile && terminate_after_phase && !keep_all)
@@ -1334,8 +1333,7 @@ static void parse_cmdline(int argc, char **argv, int pass)
* Initialize all the warnings to their default state, including
* warning index 0 used for "always on".
*/
- memcpy(warning_state, warning_default, sizeof warning_state);
- memcpy(warning_state_init, warning_default, sizeof warning_state_init);
+ memcpy(warning_state, warning_default, sizeof warning_state);
/*
* First, process the NASMENV environment variable.
@@ -1546,9 +1544,6 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
switch_segment(ofmt->section(NULL, &globalbits));
preproc->reset(fname, PP_NORMAL, pass_final() ? depend_list : NULL);
- /* Revert all warnings to the default state */
- memcpy(warning_state, warning_state_init, sizeof warning_state);
-
globallineno = 0;
while ((line = preproc->getline())) {
@@ -1575,10 +1570,6 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
preproc->cleanup_pass();
- /* Don't output further messages if we are dead anyway */
- if (terminate_after_phase)
- break;
-
if (global_offset_changed) {
switch (pass_type()) {
case PASS_OPT:
@@ -1596,11 +1587,13 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
if (stall_count > nasm_limit[LIMIT_STALLED] ||
pass_count() >= nasm_limit[LIMIT_PASSES]) {
/* No convergence, almost certainly dead */
- nasm_nonfatal("unable to find valid values for all labels "
- "after %"PRId64" passes; "
- "stalled for %"PRId64", giving up.",
- pass_count(), stall_count);
- nasm_note("Possible causes: recursive EQUs, macro abuse.");
+ nasm_nonfatalf(ERR_UNDEAD,
+ "unable to find valid values for all labels "
+ "after %"PRId64" passes; "
+ "stalled for %"PRId64", giving up.",
+ pass_count(), stall_count);
+ nasm_notef(ERR_UNDEAD,
+ "Possible causes: recursive EQUs, macro abuse.");
}
break;
@@ -1611,12 +1604,14 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
*! the second-to-last assembly pass. This is not
*! inherently fatal, but may be a source of bugs.
*/
- nasm_warn(WARN_PHASE, "phase error during stabilization "
+ nasm_warn(WARN_PHASE|ERR_UNDEAD,
+ "phase error during stabilization "
"pass, hoping for the best");
break;
case PASS_FINAL:
- nasm_nonfatal("phase error during code generation pass");
+ nasm_nonfatalf(ERR_UNDEAD,
+ "phase error during code generation pass");
break;
default:
@@ -1624,6 +1619,8 @@ static void assemble_file(const char *fname, struct strlist *depend_list)
break;
}
}
+
+ reset_warnings();
}
if (opt_verbose_info && pass_final()) {
diff --git a/asm/warnings.pl b/asm/warnings.pl
index cb336ada..0c2ed516 100755
--- a/asm/warnings.pl
+++ b/asm/warnings.pl
@@ -132,8 +132,6 @@ if ($what eq 'c') {
print $out "\n};\n\n";
printf $out "uint8_t warning_state[%d];\t/* Current state */\n",
$#warn_noall + 2;
- printf $out "uint8_t warning_state_init[%d];\t/* Command-line state, for reset */\n",
- $#warn_noall + 2;
} elsif ($what eq 'h') {
my $filename = basename($outfile);
my $guard = $filename;
@@ -174,8 +172,6 @@ if ($what eq 'c') {
$#warn_noall + 2;
printf $out "extern uint8_t warning_state[%d];\n",
$#warn_noall + 2;
- printf $out "extern uint8_t warning_state_init[%d];\n",
- $#warn_noall + 2;
print $out "\n#endif /* $guard */\n";
} elsif ($what eq 'doc') {
my %whatdef = ( 'on' => 'Enabled',
diff --git a/doc/changes.src b/doc/changes.src
index a4df0473..ad539676 100644
--- a/doc/changes.src
+++ b/doc/changes.src
@@ -7,6 +7,12 @@
The NASM 2 series supports x86-64, and is the production version of NASM
since 2007.
+\S{cl-2.15} Version 2.15
+
+\b The state of warnings can now be saved and restored via the
+\c{[WARNING PUSH]} and \c{[WARNING POP]} directives. See
+\k{asmdir-warning}.
+
\S{cl-2.14.03} Version 2.14.03
\b Suppress nuisance "\c{label changed during code generation}" messages
diff --git a/doc/nasmdoc.src b/doc/nasmdoc.src
index 5ce113a2..a8559d46 100644
--- a/doc/nasmdoc.src
+++ b/doc/nasmdoc.src
@@ -4776,6 +4776,10 @@ more details about warning classes.
the original value, either the default value or as specified on the
command line.
+\b \c{[warning push]} saves the current warning state on a stack.
+
+\b \c{[warning pop]} restores the current warning state from the stack.
+
The \c{[WARNING]} directive also accepts the \c{all}, \c{error} and
\c{error=}\e{warning-class} specifiers.
diff --git a/include/error.h b/include/error.h
index 03380764..9091fe81 100644
--- a/include/error.h
+++ b/include/error.h
@@ -122,6 +122,12 @@ static inline vefunc nasm_set_verror(vefunc ve)
/* Process a warning option or directive */
bool set_warning_status(const char *value);
+/* Warning stack management */
+void push_warnings(void);
+void pop_warnings(void);
+void init_warnings(void);
+void reset_warnings(void);
+
/* Should be included from within error.h only */
#include "warnings.h"
diff --git a/test/warnstack.asm b/test/warnstack.asm
new file mode 100644
index 00000000..6e762904
--- /dev/null
+++ b/test/warnstack.asm
@@ -0,0 +1,10 @@
+%warning "Good warning"
+ [warning push]
+ [warning -user]
+%warning "Bad warning"
+ [warning pop]
+%warning "Good warning"
+ [warning -user]
+%warning "Bad warning"
+ [warning pop] ; should warn but reset all
+%warning "Good warning"