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