Remove path name from test case
[binutils-gdb.git] / gas / messages.c
1 /* messages.c - error reporter -
2 Copyright (C) 1987-2023 Free Software Foundation, Inc.
3 This file is part of GAS, the GNU Assembler.
4
5 GAS is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 GAS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GAS; see the file COPYING. If not, write to the Free
17 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
18 02110-1301, USA. */
19
20 #include "as.h"
21 #include <limits.h>
22 #include <signal.h>
23
24 /* If the system doesn't provide strsignal, we get it defined in
25 libiberty but no declaration is supplied. Because, reasons. */
26 #if !defined (HAVE_STRSIGNAL) && !defined (strsignal)
27 extern const char *strsignal (int);
28 #endif
29
30 static void identify (const char *);
31 static void as_show_where (void);
32 static void as_warn_internal (const char *, unsigned int, char *);
33 static void as_bad_internal (const char *, unsigned int, char *);
34 static void signal_crash (int) ATTRIBUTE_NORETURN;
35
36 /* Despite the rest of the comments in this file, (FIXME-SOON),
37 here is the current scheme for error messages etc:
38
39 as_fatal() is used when gas is quite confused and
40 continuing the assembly is pointless. In this case we
41 exit immediately with error status.
42
43 as_bad() is used to mark errors that result in what we
44 presume to be a useless object file. Say, we ignored
45 something that might have been vital. If we see any of
46 these, assembly will continue to the end of the source,
47 no object file will be produced, and we will terminate
48 with error status. The new option, -Z, tells us to
49 produce an object file anyway but we still exit with
50 error status. The assumption here is that you don't want
51 this object file but we could be wrong.
52
53 as_warn() is used when we have an error from which we
54 have a plausible error recovery. eg, masking the top
55 bits of a constant that is longer than will fit in the
56 destination. In this case we will continue to assemble
57 the source, although we may have made a bad assumption,
58 and we will produce an object file and return normal exit
59 status (ie, no error). The new option -X tells us to
60 treat all as_warn() errors as as_bad() errors. That is,
61 no object file will be produced and we will exit with
62 error status. The idea here is that we don't kill an
63 entire make because of an error that we knew how to
64 correct. On the other hand, sometimes you might want to
65 stop the make at these points.
66
67 as_tsktsk() is used when we see a minor error for which
68 our error recovery action is almost certainly correct.
69 In this case, we print a message and then assembly
70 continues as though no error occurred.
71
72 as_abort () is used for logic failure (assert or abort, signal).
73 */
74
75 static void
76 identify (const char *file)
77 {
78 static int identified;
79
80 if (identified)
81 return;
82 identified++;
83
84 if (!file)
85 {
86 unsigned int x;
87 file = as_where (&x);
88 }
89
90 if (file)
91 fprintf (stderr, "%s: ", file);
92 fprintf (stderr, _("Assembler messages:\n"));
93 }
94
95 /* The number of warnings issued. */
96 static int warning_count;
97
98 int
99 had_warnings (void)
100 {
101 return warning_count;
102 }
103
104 /* Nonzero if we've hit a 'bad error', and should not write an obj file,
105 and exit with a nonzero error code. */
106
107 static int error_count;
108
109 int
110 had_errors (void)
111 {
112 return error_count;
113 }
114
115 /* Print the current location to stderr. */
116
117 static void
118 as_show_where (void)
119 {
120 const char *file;
121 unsigned int line;
122
123 file = as_where_top (&line);
124 identify (file);
125 if (file)
126 {
127 if (line != 0)
128 fprintf (stderr, "%s:%u: ", file, line);
129 else
130 fprintf (stderr, "%s: ", file);
131 }
132 }
133
134 /* Send to stderr a string as information, with location data passed in.
135 Note that for now this is not intended for general use. */
136
137 void
138 as_info_where (const char *file, unsigned int line, unsigned int indent,
139 const char *format, ...)
140 {
141 va_list args;
142 char buffer[2000];
143
144 va_start (args, format);
145 vsnprintf (buffer, sizeof (buffer), format, args);
146 va_end (args);
147 fprintf (stderr, "%s:%u: %*s%s%s\n",
148 file, line, (int)indent, "", _("Info: "), buffer);
149 }
150
151 /* Send to stderr a string as a warning, and locate warning
152 in input file(s).
153 Please only use this for when we have some recovery action.
154 Please explain in string (which may have '\n's) what recovery was
155 done. */
156
157 void
158 as_tsktsk (const char *format, ...)
159 {
160 va_list args;
161
162 as_show_where ();
163 va_start (args, format);
164 vfprintf (stderr, format, args);
165 va_end (args);
166 (void) putc ('\n', stderr);
167 as_report_context ();
168 }
169
170 /* The common portion of as_warn and as_warn_where. */
171
172 static void
173 as_warn_internal (const char *file, unsigned int line, char *buffer)
174 {
175 bool context = false;
176
177 ++warning_count;
178
179 if (file == NULL)
180 {
181 file = as_where_top (&line);
182 context = true;
183 }
184
185 identify (file);
186 if (file)
187 {
188 if (line != 0)
189 fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Warning: "), buffer);
190 else
191 fprintf (stderr, "%s: %s%s\n", file, _("Warning: "), buffer);
192 }
193 else
194 fprintf (stderr, "%s%s\n", _("Warning: "), buffer);
195
196 if (context)
197 as_report_context ();
198
199 #ifndef NO_LISTING
200 listing_warning (buffer);
201 #endif
202 }
203
204 /* Send to stderr a string as a warning, and locate warning
205 in input file(s).
206 Please only use this for when we have some recovery action.
207 Please explain in string (which may have '\n's) what recovery was
208 done. */
209
210 void
211 as_warn (const char *format, ...)
212 {
213 va_list args;
214 char buffer[2000];
215
216 if (!flag_no_warnings)
217 {
218 va_start (args, format);
219 vsnprintf (buffer, sizeof (buffer), format, args);
220 va_end (args);
221 as_warn_internal ((char *) NULL, 0, buffer);
222 }
223 }
224
225 /* Like as_warn but the file name and line number are passed in.
226 Unfortunately, we have to repeat the function in order to handle
227 the varargs correctly and portably. */
228
229 void
230 as_warn_where (const char *file, unsigned int line, const char *format, ...)
231 {
232 va_list args;
233 char buffer[2000];
234
235 if (!flag_no_warnings)
236 {
237 va_start (args, format);
238 vsnprintf (buffer, sizeof (buffer), format, args);
239 va_end (args);
240 as_warn_internal (file, line, buffer);
241 }
242 }
243
244 /* The common portion of as_bad and as_bad_where. */
245
246 static void
247 as_bad_internal (const char *file, unsigned int line, char *buffer)
248 {
249 bool context = false;
250
251 ++error_count;
252
253 if (file == NULL)
254 {
255 file = as_where_top (&line);
256 context = true;
257 }
258
259 identify (file);
260 if (file)
261 {
262 if (line != 0)
263 fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Error: "), buffer);
264 else
265 fprintf (stderr, "%s: %s%s\n", file, _("Error: "), buffer);
266 }
267 else
268 fprintf (stderr, "%s%s\n", _("Error: "), buffer);
269
270 if (context)
271 as_report_context ();
272
273 #ifndef NO_LISTING
274 listing_error (buffer);
275 #endif
276 }
277
278 /* Send to stderr a string as a warning, and locate warning in input
279 file(s). Please use when there is no recovery, but we want to
280 continue processing but not produce an object file.
281 Please explain in string (which may have '\n's) what recovery was
282 done. */
283
284 void
285 as_bad (const char *format, ...)
286 {
287 va_list args;
288 char buffer[2000];
289
290 va_start (args, format);
291 vsnprintf (buffer, sizeof (buffer), format, args);
292 va_end (args);
293
294 as_bad_internal ((char *) NULL, 0, buffer);
295 }
296
297 /* Like as_bad but the file name and line number are passed in.
298 Unfortunately, we have to repeat the function in order to handle
299 the varargs correctly and portably. */
300
301 void
302 as_bad_where (const char *file, unsigned int line, const char *format, ...)
303 {
304 va_list args;
305 char buffer[2000];
306
307 va_start (args, format);
308 vsnprintf (buffer, sizeof (buffer), format, args);
309 va_end (args);
310
311 as_bad_internal (file, line, buffer);
312 }
313
314 /* Send to stderr a string as a fatal message, and print location of
315 error in input file(s).
316 Please only use this for when we DON'T have some recovery action.
317 It xexit()s with a warning status. */
318
319 void
320 as_fatal (const char *format, ...)
321 {
322 va_list args;
323
324 as_show_where ();
325 va_start (args, format);
326 fprintf (stderr, _("Fatal error: "));
327 vfprintf (stderr, format, args);
328 (void) putc ('\n', stderr);
329 va_end (args);
330 as_report_context ();
331 /* Delete the output file, if it exists. This will prevent make from
332 thinking that a file was created and hence does not need rebuilding. */
333 if (out_file_name != NULL)
334 unlink_if_ordinary (out_file_name);
335 xexit (EXIT_FAILURE);
336 }
337
338 /* Indicate internal constency error.
339 Arguments: Filename, line number, optional function name.
340 FILENAME may be NULL, which we use for crash-via-signal. */
341
342 void
343 as_abort (const char *file, int line, const char *fn)
344 {
345 as_show_where ();
346
347 if (!file)
348 fprintf (stderr, _("Internal error (%s).\n"), fn ? fn : "unknown");
349 else if (fn)
350 fprintf (stderr, _("Internal error in %s at %s:%d.\n"), fn, file, line);
351 else
352 fprintf (stderr, _("Internal error at %s:%d.\n"), file, line);
353 as_report_context ();
354
355 fprintf (stderr, _("Please report this bug.\n"));
356
357 xexit (EXIT_FAILURE);
358 }
359
360 /* Handler for fatal signals, such as SIGSEGV. */
361
362 static void
363 signal_crash (int signo)
364 {
365 /* Reset, to prevent unbounded recursion. */
366 signal (signo, SIG_DFL);
367
368 as_abort (NULL, 0, strsignal (signo));
369 }
370
371 /* Register signal handlers, for less abrubt crashes. */
372
373 void
374 signal_init (void)
375 {
376 #ifdef SIGSEGV
377 signal (SIGSEGV, signal_crash);
378 #endif
379 #ifdef SIGILL
380 signal (SIGILL, signal_crash);
381 #endif
382 #ifdef SIGBUS
383 signal (SIGBUS, signal_crash);
384 #endif
385 #ifdef SIGABRT
386 signal (SIGABRT, signal_crash);
387 #endif
388 #if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
389 signal (SIGIOT, signal_crash);
390 #endif
391 #ifdef SIGFPE
392 signal (SIGFPE, signal_crash);
393 #endif
394 }
395
396 /* Support routines. */
397
398 #define HEX_MAX_THRESHOLD 1024
399 #define HEX_MIN_THRESHOLD -(HEX_MAX_THRESHOLD)
400
401 static void
402 as_internal_value_out_of_range (const char *prefix,
403 offsetT val,
404 offsetT min,
405 offsetT max,
406 const char *file,
407 unsigned line,
408 bool bad)
409 {
410 const char * err;
411
412 if (prefix == NULL)
413 prefix = "";
414
415 if (val >= min && val <= max)
416 {
417 addressT right = max & -max;
418
419 if (max <= 1)
420 abort ();
421
422 /* xgettext:c-format */
423 err = _("%s out of domain (%" PRId64
424 " is not a multiple of %" PRId64 ")");
425
426 if (bad)
427 as_bad_where (file, line, err, prefix, (int64_t) val, (int64_t) right);
428 else
429 as_warn_where (file, line, err, prefix, (int64_t) val, (int64_t) right);
430 }
431 else if ( val < HEX_MAX_THRESHOLD
432 && min < HEX_MAX_THRESHOLD
433 && max < HEX_MAX_THRESHOLD
434 && val > HEX_MIN_THRESHOLD
435 && min > HEX_MIN_THRESHOLD
436 && max > HEX_MIN_THRESHOLD)
437 {
438 /* xgettext:c-format. */
439 err = _("%s out of range (%" PRId64
440 " is not between %" PRId64 " and %" PRId64 ")");
441
442 if (bad)
443 as_bad_where (file, line, err, prefix,
444 (int64_t) val, (int64_t) min, (int64_t) max);
445 else
446 as_warn_where (file, line, err, prefix,
447 (int64_t) val, (int64_t) min, (int64_t) max);
448 }
449 else
450 {
451 /* xgettext:c-format. */
452 err = _("%s out of range (0x%" PRIx64
453 " is not between 0x%" PRIx64 " and 0x%" PRIx64 ")");
454
455 if (bad)
456 as_bad_where (file, line, err, prefix,
457 (int64_t) val, (int64_t) min, (int64_t) max);
458 else
459 as_warn_where (file, line, err, prefix,
460 (int64_t) val, (int64_t) min, (int64_t) max);
461 }
462 }
463
464 void
465 as_warn_value_out_of_range (const char *prefix,
466 offsetT value,
467 offsetT min,
468 offsetT max,
469 const char *file,
470 unsigned line)
471 {
472 as_internal_value_out_of_range (prefix, value, min, max, file, line, false);
473 }
474
475 void
476 as_bad_value_out_of_range (const char *prefix,
477 offsetT value,
478 offsetT min,
479 offsetT max,
480 const char *file,
481 unsigned line)
482 {
483 as_internal_value_out_of_range (prefix, value, min, max, file, line, true);
484 }