1 /* messages.c - error reporter -
2    Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
3    2003, 2004
4    Free Software Foundation, Inc.
5    This file is part of GAS, the GNU Assembler.
6 
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11 
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to the Free
19    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20    02110-1301, USA.  */
21 
22 #include "as.h"
23 
24 #include <stdio.h>
25 #ifdef HAVE_ERRNO_H
26 #include <errno.h>
27 #endif
28 
29 #ifdef USE_STDARG
30 #include <stdarg.h>
31 #endif
32 
33 #ifdef USE_VARARGS
34 #include <varargs.h>
35 #endif
36 
37 #if !defined (USE_STDARG) && !defined (USE_VARARGS)
38 /* Roll our own.  */
39 #define va_alist REST
40 #define va_dcl
41 typedef int * va_list;
42 #define va_start(ARGS)	ARGS = &REST
43 #define va_end(ARGS)
44 #endif
45 
46 static void identify (char *);
47 static void as_show_where (void);
48 static void as_warn_internal (char *, unsigned int, char *);
49 static void as_bad_internal (char *, unsigned int, char *);
50 
51 /* Despite the rest of the comments in this file, (FIXME-SOON),
52    here is the current scheme for error messages etc:
53 
54    as_fatal() is used when gas is quite confused and
55    continuing the assembly is pointless.  In this case we
56    exit immediately with error status.
57 
58    as_bad() is used to mark errors that result in what we
59    presume to be a useless object file.  Say, we ignored
60    something that might have been vital.  If we see any of
61    these, assembly will continue to the end of the source,
62    no object file will be produced, and we will terminate
63    with error status.  The new option, -Z, tells us to
64    produce an object file anyway but we still exit with
65    error status.  The assumption here is that you don't want
66    this object file but we could be wrong.
67 
68    as_warn() is used when we have an error from which we
69    have a plausible error recovery.  eg, masking the top
70    bits of a constant that is longer than will fit in the
71    destination.  In this case we will continue to assemble
72    the source, although we may have made a bad assumption,
73    and we will produce an object file and return normal exit
74    status (ie, no error).  The new option -X tells us to
75    treat all as_warn() errors as as_bad() errors.  That is,
76    no object file will be produced and we will exit with
77    error status.  The idea here is that we don't kill an
78    entire make because of an error that we knew how to
79    correct.  On the other hand, sometimes you might want to
80    stop the make at these points.
81 
82    as_tsktsk() is used when we see a minor error for which
83    our error recovery action is almost certainly correct.
84    In this case, we print a message and then assembly
85    continues as though no error occurred.  */
86 
87 static void
identify(char * file)88 identify (char *file)
89 {
90   static int identified;
91 
92   if (identified)
93     return;
94   identified++;
95 
96   if (!file)
97     {
98       unsigned int x;
99       as_where (&file, &x);
100     }
101 
102   if (file)
103     fprintf (stderr, "%s: ", file);
104   fprintf (stderr, _("Assembler messages:\n"));
105 }
106 
107 /* The number of warnings issued.  */
108 static int warning_count;
109 
110 int
had_warnings(void)111 had_warnings (void)
112 {
113   return warning_count;
114 }
115 
116 /* Nonzero if we've hit a 'bad error', and should not write an obj file,
117    and exit with a nonzero error code.  */
118 
119 static int error_count;
120 
121 int
had_errors(void)122 had_errors (void)
123 {
124   return error_count;
125 }
126 
127 /* Print the current location to stderr.  */
128 
129 static void
as_show_where(void)130 as_show_where (void)
131 {
132   char *file;
133   unsigned int line;
134 
135   as_where (&file, &line);
136   identify (file);
137   if (file)
138     fprintf (stderr, "%s:%u: ", file, line);
139 }
140 
141 /* Like perror(3), but with more info.  */
142 
143 void
as_perror(const char * gripe,const char * filename)144 as_perror (const char *gripe,		/* Unpunctuated error theme.  */
145 	   const char *filename)
146 {
147   const char *errtxt;
148   int saved_errno = errno;
149 
150   as_show_where ();
151   fprintf (stderr, gripe, filename);
152   errno = saved_errno;
153 #ifdef BFD_ASSEMBLER
154   errtxt = bfd_errmsg (bfd_get_error ());
155 #else
156   errtxt = xstrerror (errno);
157 #endif
158   fprintf (stderr, ": %s\n", errtxt);
159   errno = 0;
160 #ifdef BFD_ASSEMBLER
161   bfd_set_error (bfd_error_no_error);
162 #endif
163 }
164 
165 /* Send to stderr a string as a warning, and locate warning
166    in input file(s).
167    Please only use this for when we have some recovery action.
168    Please explain in string (which may have '\n's) what recovery was
169    done.  */
170 
171 #ifdef USE_STDARG
172 void
as_tsktsk(const char * format,...)173 as_tsktsk (const char *format, ...)
174 {
175   va_list args;
176 
177   as_show_where ();
178   va_start (args, format);
179   vfprintf (stderr, format, args);
180   va_end (args);
181   (void) putc ('\n', stderr);
182 }
183 #else
184 void
as_tsktsk(format,va_alist)185 as_tsktsk (format, va_alist)
186      const char *format;
187      va_dcl
188 {
189   va_list args;
190 
191   as_show_where ();
192   va_start (args);
193   vfprintf (stderr, format, args);
194   va_end (args);
195   (void) putc ('\n', stderr);
196 }
197 #endif /* not NO_STDARG */
198 
199 /* The common portion of as_warn and as_warn_where.  */
200 
201 static void
as_warn_internal(char * file,unsigned int line,char * buffer)202 as_warn_internal (char *file, unsigned int line, char *buffer)
203 {
204   ++warning_count;
205 
206   if (file == NULL)
207     as_where (&file, &line);
208 
209   identify (file);
210   if (file)
211     fprintf (stderr, "%s:%u: ", file, line);
212   fprintf (stderr, _("Warning: "));
213   fputs (buffer, stderr);
214   (void) putc ('\n', stderr);
215 #ifndef NO_LISTING
216   listing_warning (buffer);
217 #endif
218 }
219 
220 /* Send to stderr a string as a warning, and locate warning
221    in input file(s).
222    Please only use this for when we have some recovery action.
223    Please explain in string (which may have '\n's) what recovery was
224    done.  */
225 
226 #ifdef USE_STDARG
227 void
as_warn(const char * format,...)228 as_warn (const char *format, ...)
229 {
230   va_list args;
231   char buffer[2000];
232 
233   if (!flag_no_warnings)
234     {
235       va_start (args, format);
236       vsprintf (buffer, format, args);
237       va_end (args);
238       as_warn_internal ((char *) NULL, 0, buffer);
239     }
240 }
241 #else
242 void
as_warn(format,va_alist)243 as_warn (format, va_alist)
244      const char *format;
245      va_dcl
246 {
247   va_list args;
248   char buffer[2000];
249 
250   if (!flag_no_warnings)
251     {
252       va_start (args);
253       vsprintf (buffer, format, args);
254       va_end (args);
255       as_warn_internal ((char *) NULL, 0, buffer);
256     }
257 }
258 #endif /* not NO_STDARG */
259 
260 /* Like as_bad but the file name and line number are passed in.
261    Unfortunately, we have to repeat the function in order to handle
262    the varargs correctly and portably.  */
263 
264 #ifdef USE_STDARG
265 void
as_warn_where(char * file,unsigned int line,const char * format,...)266 as_warn_where (char *file, unsigned int line, const char *format, ...)
267 {
268   va_list args;
269   char buffer[2000];
270 
271   if (!flag_no_warnings)
272     {
273       va_start (args, format);
274       vsprintf (buffer, format, args);
275       va_end (args);
276       as_warn_internal (file, line, buffer);
277     }
278 }
279 #else
280 void
as_warn_where(file,line,format,va_alist)281 as_warn_where (file, line, format, va_alist)
282      char *file;
283      unsigned int line;
284      const char *format;
285      va_dcl
286 {
287   va_list args;
288   char buffer[2000];
289 
290   if (!flag_no_warnings)
291     {
292       va_start (args);
293       vsprintf (buffer, format, args);
294       va_end (args);
295       as_warn_internal (file, line, buffer);
296     }
297 }
298 #endif /* not NO_STDARG */
299 
300 /* The common portion of as_bad and as_bad_where.  */
301 
302 static void
as_bad_internal(char * file,unsigned int line,char * buffer)303 as_bad_internal (char *file, unsigned int line, char *buffer)
304 {
305   ++error_count;
306 
307   if (file == NULL)
308     as_where (&file, &line);
309 
310   identify (file);
311   if (file)
312     fprintf (stderr, "%s:%u: ", file, line);
313   fprintf (stderr, _("Error: "));
314   fputs (buffer, stderr);
315   (void) putc ('\n', stderr);
316 #ifndef NO_LISTING
317   listing_error (buffer);
318 #endif
319 }
320 
321 /* Send to stderr a string as a warning, and locate warning in input
322    file(s).  Please us when there is no recovery, but we want to
323    continue processing but not produce an object file.
324    Please explain in string (which may have '\n's) what recovery was
325    done.  */
326 
327 #ifdef USE_STDARG
328 void
as_bad(const char * format,...)329 as_bad (const char *format, ...)
330 {
331   va_list args;
332   char buffer[2000];
333 
334   va_start (args, format);
335   vsprintf (buffer, format, args);
336   va_end (args);
337 
338   as_bad_internal ((char *) NULL, 0, buffer);
339 }
340 
341 #else
342 void
as_bad(format,va_alist)343 as_bad (format, va_alist)
344      const char *format;
345      va_dcl
346 {
347   va_list args;
348   char buffer[2000];
349 
350   va_start (args);
351   vsprintf (buffer, format, args);
352   va_end (args);
353 
354   as_bad_internal ((char *) NULL, 0, buffer);
355 }
356 #endif /* not NO_STDARG */
357 
358 /* Like as_bad but the file name and line number are passed in.
359    Unfortunately, we have to repeat the function in order to handle
360    the varargs correctly and portably.  */
361 
362 #ifdef USE_STDARG
363 void
as_bad_where(char * file,unsigned int line,const char * format,...)364 as_bad_where (char *file, unsigned int line, const char *format, ...)
365 {
366   va_list args;
367   char buffer[2000];
368 
369   va_start (args, format);
370   vsprintf (buffer, format, args);
371   va_end (args);
372 
373   as_bad_internal (file, line, buffer);
374 }
375 
376 #else
377 void
as_bad_where(file,line,format,va_alist)378 as_bad_where (file, line, format, va_alist)
379      char *file;
380      unsigned int line;
381      const char *format;
382      va_dcl
383 {
384   va_list args;
385   char buffer[2000];
386 
387   va_start (args);
388   vsprintf (buffer, format, args);
389   va_end (args);
390 
391   as_bad_internal (file, line, buffer);
392 }
393 #endif /* not NO_STDARG */
394 
395 /* Send to stderr a string as a fatal message, and print location of
396    error in input file(s).
397    Please only use this for when we DON'T have some recovery action.
398    It xexit()s with a warning status.  */
399 
400 #ifdef USE_STDARG
401 void
as_fatal(const char * format,...)402 as_fatal (const char *format, ...)
403 {
404   va_list args;
405 
406   as_show_where ();
407   va_start (args, format);
408   fprintf (stderr, _("Fatal error: "));
409   vfprintf (stderr, format, args);
410   (void) putc ('\n', stderr);
411   va_end (args);
412   /* Delete the output file, if it exists.  This will prevent make from
413      thinking that a file was created and hence does not need rebuilding.  */
414   if (out_file_name != NULL)
415     unlink_if_ordinary (out_file_name);
416   xexit (EXIT_FAILURE);
417 }
418 #else
419 void
as_fatal(format,va_alist)420 as_fatal (format, va_alist)
421      char *format;
422      va_dcl
423 {
424   va_list args;
425 
426   as_show_where ();
427   va_start (args);
428   fprintf (stderr, _("Fatal error: "));
429   vfprintf (stderr, format, args);
430   (void) putc ('\n', stderr);
431   va_end (args);
432   xexit (EXIT_FAILURE);
433 }
434 #endif /* not NO_STDARG */
435 
436 /* Indicate assertion failure.
437    Arguments: Filename, line number, optional function name.  */
438 
439 void
as_assert(const char * file,int line,const char * fn)440 as_assert (const char *file, int line, const char *fn)
441 {
442   as_show_where ();
443   fprintf (stderr, _("Internal error!\n"));
444   if (fn)
445     fprintf (stderr, _("Assertion failure in %s at %s line %d.\n"),
446 	     fn, file, line);
447   else
448     fprintf (stderr, _("Assertion failure at %s line %d.\n"), file, line);
449   fprintf (stderr, _("Please report this bug.\n"));
450   xexit (EXIT_FAILURE);
451 }
452 
453 /* as_abort: Print a friendly message saying how totally hosed we are,
454    and exit without producing a core file.  */
455 
456 void
as_abort(const char * file,int line,const char * fn)457 as_abort (const char *file, int line, const char *fn)
458 {
459   as_show_where ();
460   if (fn)
461     fprintf (stderr, _("Internal error, aborting at %s line %d in %s\n"),
462 	     file, line, fn);
463   else
464     fprintf (stderr, _("Internal error, aborting at %s line %d\n"),
465 	     file, line);
466   fprintf (stderr, _("Please report this bug.\n"));
467   xexit (EXIT_FAILURE);
468 }
469 
470 /* Support routines.  */
471 
472 void
sprint_value(char * buf,valueT val)473 sprint_value (char *buf, valueT val)
474 {
475   if (sizeof (val) <= sizeof (long))
476     {
477       sprintf (buf, "%ld", (long) val);
478       return;
479     }
480 #ifdef BFD_ASSEMBLER
481   if (sizeof (val) <= sizeof (bfd_vma))
482     {
483       sprintf_vma (buf, val);
484       return;
485     }
486 #endif
487   abort ();
488 }
489 
490 #define HEX_MAX_THRESHOLD	1024
491 #define HEX_MIN_THRESHOLD	-(HEX_MAX_THRESHOLD)
492 
493 static void
as_internal_value_out_of_range(char * prefix,offsetT val,offsetT min,offsetT max,char * file,unsigned line,int bad)494 as_internal_value_out_of_range (char *    prefix,
495 				offsetT   val,
496 				offsetT   min,
497 				offsetT   max,
498 				char *    file,
499 				unsigned  line,
500 				int       bad)
501 {
502   const char * err;
503 
504   if (prefix == NULL)
505     prefix = "";
506 
507 #ifdef BFD_ASSEMBLER
508   if (   val < HEX_MAX_THRESHOLD
509       && min < HEX_MAX_THRESHOLD
510       && max < HEX_MAX_THRESHOLD
511       && val > HEX_MIN_THRESHOLD
512       && min > HEX_MIN_THRESHOLD
513       && max > HEX_MIN_THRESHOLD)
514 #endif
515     {
516       /* xgettext:c-format  */
517       err = _("%s out of range (%d is not between %d and %d)");
518 
519       if (bad)
520 	as_bad_where (file, line, err,
521 		      prefix, (int) val, (int) min, (int) max);
522       else
523 	as_warn_where (file, line, err,
524 		       prefix, (int) val, (int) min, (int) max);
525     }
526 #ifdef BFD_ASSEMBLER
527   else
528     {
529       char val_buf [sizeof (val) * 3 + 2];
530       char min_buf [sizeof (val) * 3 + 2];
531       char max_buf [sizeof (val) * 3 + 2];
532 
533       if (sizeof (val) > sizeof (bfd_vma))
534 	abort ();
535 
536       sprintf_vma (val_buf, val);
537       sprintf_vma (min_buf, min);
538       sprintf_vma (max_buf, max);
539 
540       /* xgettext:c-format.  */
541       err = _("%s out of range (0x%s is not between 0x%s and 0x%s)");
542 
543       if (bad)
544 	as_bad_where (file, line, err, prefix, val_buf, min_buf, max_buf);
545       else
546 	as_warn_where (file, line, err, prefix, val_buf, min_buf, max_buf);
547     }
548 #endif
549 }
550 
551 void
as_warn_value_out_of_range(char * prefix,offsetT value,offsetT min,offsetT max,char * file,unsigned line)552 as_warn_value_out_of_range (char *   prefix,
553 			   offsetT  value,
554 			   offsetT  min,
555 			   offsetT  max,
556 			   char *   file,
557 			   unsigned line)
558 {
559   as_internal_value_out_of_range (prefix, value, min, max, file, line, 0);
560 }
561 
562 void
as_bad_value_out_of_range(char * prefix,offsetT value,offsetT min,offsetT max,char * file,unsigned line)563 as_bad_value_out_of_range (char *   prefix,
564 			   offsetT  value,
565 			   offsetT  min,
566 			   offsetT  max,
567 			   char *   file,
568 			   unsigned line)
569 {
570   as_internal_value_out_of_range (prefix, value, min, max, file, line, 1);
571 }
572