1 | /* ----------------------------------------------------------------------- * |
2 | * |
3 | * Copyright 1996-2018 The NASM Authors - All Rights Reserved |
4 | * See the file AUTHORS included with the NASM distribution for |
5 | * the specific copyright holders. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following |
9 | * conditions are met: |
10 | * |
11 | * * Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * * Redistributions in binary form must reproduce the above |
14 | * copyright notice, this list of conditions and the following |
15 | * disclaimer in the documentation and/or other materials provided |
16 | * with the distribution. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND |
19 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, |
20 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
21 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
23 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
25 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
29 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | * |
32 | * ----------------------------------------------------------------------- */ |
33 | |
34 | /* |
35 | * error.c - error message handling routines for the assembler |
36 | */ |
37 | |
38 | #include "compiler.h" |
39 | |
40 | #include <stdlib.h> |
41 | |
42 | #include "nasmlib.h" |
43 | #include "error.h" |
44 | |
45 | /* |
46 | * Description of the suppressible warnings for the command line and |
47 | * the [warning] directive. |
48 | */ |
49 | #define on (WARN_ST_ENABLED) |
50 | #define off 0 |
51 | #define err (WARN_ST_ENABLED|WARN_ST_ERROR) |
52 | |
53 | const struct warning warnings[WARN_ALL+1] = { |
54 | {NULL, NULL, on}, /* must be on - used for unconditional enable */ |
55 | {"macro-params" , "macro calls with wrong parameter count" , on}, |
56 | {"macro-selfref" , "cyclic macro references" , off}, |
57 | {"macro-defaults" , "macros with more default than optional parameters" , on}, |
58 | {"orphan-labels" , "labels alone on lines without trailing `:'" , on}, |
59 | {"number-overflow" , "numeric constant does not fit" , on}, |
60 | {"gnu-elf-extensions" , "using 8- or 16-bit relocation in ELF32, a GNU extension" , off}, |
61 | {"float-overflow" , "floating point overflow" , on}, |
62 | {"float-denorm" , "floating point denormal" , off}, |
63 | {"float-underflow" , "floating point underflow" , off}, |
64 | {"float-toolong" , "too many digits in floating-point number" , on}, |
65 | {"user" , "%warning directives" , on}, |
66 | {"lock" , "lock prefix on unlockable instructions" , on}, |
67 | {"hle" , "invalid hle prefixes" , on}, |
68 | {"bnd" , "invalid bnd prefixes" , on}, |
69 | {"zext-reloc" , "relocation zero-extended to match output format" , on}, |
70 | {"ptr" , "non-NASM keyword used in other assemblers" , on}, |
71 | {"bad-pragma" , "empty or malformed %pragma" , off}, |
72 | {"unknown-pragma" , "unknown %pragma facility or directive" , off}, |
73 | {"not-my-pragma" , "%pragma not applicable to this compilation" , off}, |
74 | {"unknown-warning" , "unknown warning in -W/-w or warning directive" , off}, |
75 | {"negative-rep" , "regative %rep count" , on}, |
76 | {"phase" , "phase error during stabilization" , off}, |
77 | {"label-redef" , "label redefined to an identical value" , off}, |
78 | {"label-redef-late" , "label (re)defined during code generation" , err}, |
79 | |
80 | /* THESE ENTRIES SHOULD COME LAST */ |
81 | {"other" , "any warning not specifially mentioned above" , on}, |
82 | {"all" , "all possible warnings" , off} |
83 | }; |
84 | |
85 | uint8_t warning_state[WARN_ALL];/* Current state */ |
86 | uint8_t warning_state_init[WARN_ALL]; /* Command-line state, for reset */ |
87 | |
88 | vefunc nasm_verror; /* Global error handling function */ |
89 | |
90 | void nasm_error(int severity, const char *fmt, ...) |
91 | { |
92 | va_list ap; |
93 | |
94 | va_start(ap, fmt); |
95 | nasm_verror(severity, fmt, ap); |
96 | va_end(ap); |
97 | } |
98 | |
99 | fatal_func nasm_fatal(int flags, const char *fmt, ...) |
100 | { |
101 | va_list ap; |
102 | |
103 | va_start(ap, fmt); |
104 | nasm_verror(flags | ERR_FATAL, fmt, ap); |
105 | abort(); /* We should never get here */ |
106 | } |
107 | |
108 | fatal_func nasm_panic(int flags, const char *fmt, ...) |
109 | { |
110 | va_list ap; |
111 | |
112 | va_start(ap, fmt); |
113 | nasm_verror(flags | ERR_PANIC, fmt, ap); |
114 | abort(); /* We should never get here */ |
115 | } |
116 | |
117 | fatal_func nasm_panic_from_macro(const char *file, int line) |
118 | { |
119 | nasm_panic(ERR_NOFILE, "Internal error at %s:%d\n" , file, line); |
120 | } |
121 | |
122 | fatal_func nasm_assert_failed(const char *file, int line, const char *msg) |
123 | { |
124 | nasm_panic(0, "assertion %s failed at %s:%d" , msg, file, line); |
125 | } |
126 | |
127 | /* |
128 | * This is called when processing a -w or -W option, or a warning directive. |
129 | * Returns on if if the action was successful. |
130 | */ |
131 | bool set_warning_status(const char *value) |
132 | { |
133 | enum warn_action { WID_OFF, WID_ON, WID_RESET }; |
134 | enum warn_action action; |
135 | uint8_t mask; |
136 | int i; |
137 | bool ok = false; |
138 | |
139 | value = nasm_skip_spaces(value); |
140 | switch (*value) { |
141 | case '-': |
142 | action = WID_OFF; |
143 | value++; |
144 | break; |
145 | case '+': |
146 | action = WID_ON; |
147 | value++; |
148 | break; |
149 | case '*': |
150 | action = WID_RESET; |
151 | value++; |
152 | break; |
153 | case 'N': |
154 | case 'n': |
155 | if (!nasm_strnicmp(value, "no-" , 3)) { |
156 | action = WID_OFF; |
157 | value += 3; |
158 | break; |
159 | } else if (!nasm_stricmp(value, "none" )) { |
160 | action = WID_OFF; |
161 | value = NULL; |
162 | break; |
163 | } |
164 | /* else fall through */ |
165 | default: |
166 | action = WID_ON; |
167 | break; |
168 | } |
169 | |
170 | mask = WARN_ST_ENABLED; |
171 | |
172 | if (value && !nasm_strnicmp(value, "error" , 5)) { |
173 | switch (value[5]) { |
174 | case '=': |
175 | mask = WARN_ST_ERROR; |
176 | value += 6; |
177 | break; |
178 | case '\0': |
179 | mask = WARN_ST_ERROR; |
180 | value = NULL; |
181 | break; |
182 | default: |
183 | /* Just an accidental prefix? */ |
184 | break; |
185 | } |
186 | } |
187 | |
188 | if (value && !nasm_stricmp(value, "all" )) |
189 | value = NULL; |
190 | |
191 | /* This is inefficient, but it shouldn't matter... */ |
192 | for (i = 1; i < WARN_ALL; i++) { |
193 | if (!value || !nasm_stricmp(value, warnings[i].name)) { |
194 | ok = true; /* At least one action taken */ |
195 | switch (action) { |
196 | case WID_OFF: |
197 | warning_state[i] &= ~mask; |
198 | break; |
199 | case WID_ON: |
200 | warning_state[i] |= mask; |
201 | break; |
202 | case WID_RESET: |
203 | warning_state[i] &= ~mask; |
204 | warning_state[i] |= warning_state_init[i] & mask; |
205 | break; |
206 | } |
207 | } |
208 | } |
209 | |
210 | return ok; |
211 | } |
212 | |