Remove Stephen Casner as the PDP11 maintainer.
[binutils-gdb.git] / gas / messages.c
blob0db075d779c9af54e1fa0a60e4c638420d25594e
1 /* messages.c - error reporter -
2 Copyright (C) 1987-2023 Free Software Foundation, Inc.
3 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
20 #include "as.h"
21 #include <limits.h>
22 #include <signal.h>
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
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;
36 /* Despite the rest of the comments in this file, (FIXME-SOON),
37 here is the current scheme for error messages etc:
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.
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.
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.
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.
72 as_abort () is used for logic failure (assert or abort, signal).
75 static void
76 identify (const char *file)
78 static int identified;
80 if (identified)
81 return;
82 identified++;
84 if (!file)
86 unsigned int x;
87 file = as_where (&x);
90 if (file)
91 fprintf (stderr, "%s: ", file);
92 fprintf (stderr, _("Assembler messages:\n"));
95 /* The number of warnings issued. */
96 static int warning_count;
98 int
99 had_warnings (void)
101 return warning_count;
104 /* Nonzero if we've hit a 'bad error', and should not write an obj file,
105 and exit with a nonzero error code. */
107 static int error_count;
110 had_errors (void)
112 return error_count;
115 /* Print the current location to stderr. */
117 static void
118 as_show_where (void)
120 const char *file;
121 unsigned int line;
123 file = as_where_top (&line);
124 identify (file);
125 if (file)
127 if (line != 0)
128 fprintf (stderr, "%s:%u: ", file, line);
129 else
130 fprintf (stderr, "%s: ", file);
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. */
137 void
138 as_info_where (const char *file, unsigned int line, unsigned int indent,
139 const char *format, ...)
141 va_list args;
142 char buffer[2000];
144 gas_assert (file != NULL && line > 0 && indent <= INT_MAX);
146 va_start (args, format);
147 vsnprintf (buffer, sizeof (buffer), format, args);
148 va_end (args);
149 fprintf (stderr, "%s:%u: %*s%s%s\n",
150 file, line, (int)indent, "", _("Info: "), buffer);
153 /* Send to stderr a string as a warning, and locate warning
154 in input file(s).
155 Please only use this for when we have some recovery action.
156 Please explain in string (which may have '\n's) what recovery was
157 done. */
159 void
160 as_tsktsk (const char *format, ...)
162 va_list args;
164 as_show_where ();
165 va_start (args, format);
166 vfprintf (stderr, format, args);
167 va_end (args);
168 (void) putc ('\n', stderr);
169 as_report_context ();
172 /* The common portion of as_warn and as_warn_where. */
174 static void
175 as_warn_internal (const char *file, unsigned int line, char *buffer)
177 bool context = false;
179 ++warning_count;
181 if (file == NULL)
183 file = as_where_top (&line);
184 context = true;
187 identify (file);
188 if (file)
190 if (line != 0)
191 fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Warning: "), buffer);
192 else
193 fprintf (stderr, "%s: %s%s\n", file, _("Warning: "), buffer);
195 else
196 fprintf (stderr, "%s%s\n", _("Warning: "), buffer);
198 if (context)
199 as_report_context ();
201 #ifndef NO_LISTING
202 listing_warning (buffer);
203 #endif
206 /* Send to stderr a string as a warning, and locate warning
207 in input file(s).
208 Please only use this for when we have some recovery action.
209 Please explain in string (which may have '\n's) what recovery was
210 done. */
212 void
213 as_warn (const char *format, ...)
215 va_list args;
216 char buffer[2000];
218 if (!flag_no_warnings)
220 va_start (args, format);
221 vsnprintf (buffer, sizeof (buffer), format, args);
222 va_end (args);
223 as_warn_internal ((char *) NULL, 0, buffer);
227 /* Like as_warn but the file name and line number are passed in.
228 Unfortunately, we have to repeat the function in order to handle
229 the varargs correctly and portably. */
231 void
232 as_warn_where (const char *file, unsigned int line, const char *format, ...)
234 va_list args;
235 char buffer[2000];
237 if (!flag_no_warnings)
239 va_start (args, format);
240 vsnprintf (buffer, sizeof (buffer), format, args);
241 va_end (args);
242 as_warn_internal (file, line, buffer);
246 /* The common portion of as_bad and as_bad_where. */
248 static void
249 as_bad_internal (const char *file, unsigned int line, char *buffer)
251 bool context = false;
253 ++error_count;
255 if (file == NULL)
257 file = as_where_top (&line);
258 context = true;
261 identify (file);
262 if (file)
264 if (line != 0)
265 fprintf (stderr, "%s:%u: %s%s\n", file, line, _("Error: "), buffer);
266 else
267 fprintf (stderr, "%s: %s%s\n", file, _("Error: "), buffer);
269 else
270 fprintf (stderr, "%s%s\n", _("Error: "), buffer);
272 if (context)
273 as_report_context ();
275 #ifndef NO_LISTING
276 listing_error (buffer);
277 #endif
280 /* Send to stderr a string as a warning, and locate warning in input
281 file(s). Please use when there is no recovery, but we want to
282 continue processing but not produce an object file.
283 Please explain in string (which may have '\n's) what recovery was
284 done. */
286 void
287 as_bad (const char *format, ...)
289 va_list args;
290 char buffer[2000];
292 va_start (args, format);
293 vsnprintf (buffer, sizeof (buffer), format, args);
294 va_end (args);
296 as_bad_internal ((char *) NULL, 0, buffer);
299 /* Like as_bad but the file name and line number are passed in.
300 Unfortunately, we have to repeat the function in order to handle
301 the varargs correctly and portably. */
303 void
304 as_bad_where (const char *file, unsigned int line, const char *format, ...)
306 va_list args;
307 char buffer[2000];
309 va_start (args, format);
310 vsnprintf (buffer, sizeof (buffer), format, args);
311 va_end (args);
313 as_bad_internal (file, line, buffer);
316 /* Send to stderr a string as a fatal message, and print location of
317 error in input file(s).
318 Please only use this for when we DON'T have some recovery action.
319 It xexit()s with a warning status. */
321 void
322 as_fatal (const char *format, ...)
324 va_list args;
326 as_show_where ();
327 va_start (args, format);
328 fprintf (stderr, _("Fatal error: "));
329 vfprintf (stderr, format, args);
330 (void) putc ('\n', stderr);
331 va_end (args);
332 as_report_context ();
333 /* Delete the output file, if it exists. This will prevent make from
334 thinking that a file was created and hence does not need rebuilding. */
335 if (out_file_name != NULL)
336 unlink_if_ordinary (out_file_name);
337 xexit (EXIT_FAILURE);
340 /* Indicate internal constency error.
341 Arguments: Filename, line number, optional function name.
342 FILENAME may be NULL, which we use for crash-via-signal. */
344 void
345 as_abort (const char *file, int line, const char *fn)
347 as_show_where ();
349 if (!file)
350 fprintf (stderr, _("Internal error (%s).\n"), fn ? fn : "unknown");
351 else if (fn)
352 fprintf (stderr, _("Internal error in %s at %s:%d.\n"), fn, file, line);
353 else
354 fprintf (stderr, _("Internal error at %s:%d.\n"), file, line);
355 as_report_context ();
357 fprintf (stderr, _("Please report this bug.\n"));
359 xexit (EXIT_FAILURE);
362 /* Handler for fatal signals, such as SIGSEGV. */
364 static void
365 signal_crash (int signo)
367 /* Reset, to prevent unbounded recursion. */
368 signal (signo, SIG_DFL);
370 as_abort (NULL, 0, strsignal (signo));
373 /* Register signal handlers, for less abrubt crashes. */
375 void
376 signal_init (void)
378 #ifdef SIGSEGV
379 signal (SIGSEGV, signal_crash);
380 #endif
381 #ifdef SIGILL
382 signal (SIGILL, signal_crash);
383 #endif
384 #ifdef SIGBUS
385 signal (SIGBUS, signal_crash);
386 #endif
387 #ifdef SIGABRT
388 signal (SIGABRT, signal_crash);
389 #endif
390 #if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
391 signal (SIGIOT, signal_crash);
392 #endif
393 #ifdef SIGFPE
394 signal (SIGFPE, signal_crash);
395 #endif
398 /* Support routines. */
400 #define HEX_MAX_THRESHOLD 1024
401 #define HEX_MIN_THRESHOLD -(HEX_MAX_THRESHOLD)
403 static void
404 as_internal_value_out_of_range (const char *prefix,
405 offsetT val,
406 offsetT min,
407 offsetT max,
408 const char *file,
409 unsigned line,
410 bool bad)
412 const char * err;
414 if (prefix == NULL)
415 prefix = "";
417 if (val >= min && val <= max)
419 addressT right = max & -max;
421 if (max <= 1)
422 abort ();
424 /* xgettext:c-format */
425 err = _("%s out of domain (%" PRId64
426 " is not a multiple of %" PRId64 ")");
428 if (bad)
429 as_bad_where (file, line, err, prefix, (int64_t) val, (int64_t) right);
430 else
431 as_warn_where (file, line, err, prefix, (int64_t) val, (int64_t) right);
433 else if ( val < HEX_MAX_THRESHOLD
434 && min < HEX_MAX_THRESHOLD
435 && max < HEX_MAX_THRESHOLD
436 && val > HEX_MIN_THRESHOLD
437 && min > HEX_MIN_THRESHOLD
438 && max > HEX_MIN_THRESHOLD)
440 /* xgettext:c-format. */
441 err = _("%s out of range (%" PRId64
442 " is not between %" PRId64 " and %" PRId64 ")");
444 if (bad)
445 as_bad_where (file, line, err, prefix,
446 (int64_t) val, (int64_t) min, (int64_t) max);
447 else
448 as_warn_where (file, line, err, prefix,
449 (int64_t) val, (int64_t) min, (int64_t) max);
451 else
453 /* xgettext:c-format. */
454 err = _("%s out of range (0x%" PRIx64
455 " is not between 0x%" PRIx64 " and 0x%" PRIx64 ")");
457 if (bad)
458 as_bad_where (file, line, err, prefix,
459 (int64_t) val, (int64_t) min, (int64_t) max);
460 else
461 as_warn_where (file, line, err, prefix,
462 (int64_t) val, (int64_t) min, (int64_t) max);
466 void
467 as_warn_value_out_of_range (const char *prefix,
468 offsetT value,
469 offsetT min,
470 offsetT max,
471 const char *file,
472 unsigned line)
474 as_internal_value_out_of_range (prefix, value, min, max, file, line, false);
477 void
478 as_bad_value_out_of_range (const char *prefix,
479 offsetT value,
480 offsetT min,
481 offsetT max,
482 const char *file,
483 unsigned line)
485 as_internal_value_out_of_range (prefix, value, min, max, file, line, true);