133965Sjdp/* messages.c - error reporter -
2218822Sdim   Copyright 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001,
3218822Sdim   2003, 2004, 2005, 2006, 2007
433965Sjdp   Free Software Foundation, Inc.
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
19218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2133965Sjdp
2233965Sjdp#include "as.h"
2333965Sjdp
24130561Sobrienstatic void identify (char *);
25130561Sobrienstatic void as_show_where (void);
26130561Sobrienstatic void as_warn_internal (char *, unsigned int, char *);
27130561Sobrienstatic void as_bad_internal (char *, unsigned int, char *);
2833965Sjdp
2977298Sobrien/* Despite the rest of the comments in this file, (FIXME-SOON),
30130561Sobrien   here is the current scheme for error messages etc:
3133965Sjdp
32130561Sobrien   as_fatal() is used when gas is quite confused and
33130561Sobrien   continuing the assembly is pointless.  In this case we
34130561Sobrien   exit immediately with error status.
35130561Sobrien
36130561Sobrien   as_bad() is used to mark errors that result in what we
37130561Sobrien   presume to be a useless object file.  Say, we ignored
38130561Sobrien   something that might have been vital.  If we see any of
39130561Sobrien   these, assembly will continue to the end of the source,
40130561Sobrien   no object file will be produced, and we will terminate
41130561Sobrien   with error status.  The new option, -Z, tells us to
42130561Sobrien   produce an object file anyway but we still exit with
43130561Sobrien   error status.  The assumption here is that you don't want
44130561Sobrien   this object file but we could be wrong.
45130561Sobrien
46130561Sobrien   as_warn() is used when we have an error from which we
47130561Sobrien   have a plausible error recovery.  eg, masking the top
48130561Sobrien   bits of a constant that is longer than will fit in the
49130561Sobrien   destination.  In this case we will continue to assemble
50130561Sobrien   the source, although we may have made a bad assumption,
51130561Sobrien   and we will produce an object file and return normal exit
52130561Sobrien   status (ie, no error).  The new option -X tells us to
53130561Sobrien   treat all as_warn() errors as as_bad() errors.  That is,
54130561Sobrien   no object file will be produced and we will exit with
55130561Sobrien   error status.  The idea here is that we don't kill an
56130561Sobrien   entire make because of an error that we knew how to
57130561Sobrien   correct.  On the other hand, sometimes you might want to
58130561Sobrien   stop the make at these points.
59130561Sobrien
60130561Sobrien   as_tsktsk() is used when we see a minor error for which
61130561Sobrien   our error recovery action is almost certainly correct.
62130561Sobrien   In this case, we print a message and then assembly
63130561Sobrien   continues as though no error occurred.  */
64130561Sobrien
6533965Sjdpstatic void
66130561Sobrienidentify (char *file)
6733965Sjdp{
6833965Sjdp  static int identified;
69130561Sobrien
7033965Sjdp  if (identified)
7133965Sjdp    return;
7233965Sjdp  identified++;
7333965Sjdp
7433965Sjdp  if (!file)
7533965Sjdp    {
7633965Sjdp      unsigned int x;
7733965Sjdp      as_where (&file, &x);
7833965Sjdp    }
7933965Sjdp
8033965Sjdp  if (file)
8133965Sjdp    fprintf (stderr, "%s: ", file);
8260484Sobrien  fprintf (stderr, _("Assembler messages:\n"));
8333965Sjdp}
8433965Sjdp
8577298Sobrien/* The number of warnings issued.  */
8677298Sobrienstatic int warning_count;
8733965Sjdp
8877298Sobrienint
89130561Sobrienhad_warnings (void)
9033965Sjdp{
91130561Sobrien  return warning_count;
9233965Sjdp}
9333965Sjdp
9433965Sjdp/* Nonzero if we've hit a 'bad error', and should not write an obj file,
9577298Sobrien   and exit with a nonzero error code.  */
9633965Sjdp
9733965Sjdpstatic int error_count;
9833965Sjdp
9977298Sobrienint
100130561Sobrienhad_errors (void)
10133965Sjdp{
102130561Sobrien  return error_count;
10333965Sjdp}
10433965Sjdp
10533965Sjdp/* Print the current location to stderr.  */
10633965Sjdp
10733965Sjdpstatic void
108130561Sobrienas_show_where (void)
10933965Sjdp{
11033965Sjdp  char *file;
11133965Sjdp  unsigned int line;
11233965Sjdp
11333965Sjdp  as_where (&file, &line);
11433965Sjdp  identify (file);
11533965Sjdp  if (file)
11633965Sjdp    fprintf (stderr, "%s:%u: ", file, line);
11733965Sjdp}
11833965Sjdp
11977298Sobrien/* Send to stderr a string as a warning, and locate warning
12077298Sobrien   in input file(s).
12177298Sobrien   Please only use this for when we have some recovery action.
12277298Sobrien   Please explain in string (which may have '\n's) what recovery was
12377298Sobrien   done.  */
12433965Sjdp
12533965Sjdp#ifdef USE_STDARG
12677298Sobrienvoid
12777298Sobrienas_tsktsk (const char *format, ...)
12833965Sjdp{
12933965Sjdp  va_list args;
13033965Sjdp
13133965Sjdp  as_show_where ();
13233965Sjdp  va_start (args, format);
13333965Sjdp  vfprintf (stderr, format, args);
13433965Sjdp  va_end (args);
13533965Sjdp  (void) putc ('\n', stderr);
13677298Sobrien}
13733965Sjdp#else
13877298Sobrienvoid
13933965Sjdpas_tsktsk (format, va_alist)
14033965Sjdp     const char *format;
14133965Sjdp     va_dcl
14233965Sjdp{
14333965Sjdp  va_list args;
14433965Sjdp
14533965Sjdp  as_show_where ();
14633965Sjdp  va_start (args);
14733965Sjdp  vfprintf (stderr, format, args);
14833965Sjdp  va_end (args);
14933965Sjdp  (void) putc ('\n', stderr);
15077298Sobrien}
15133965Sjdp#endif /* not NO_STDARG */
15233965Sjdp
15333965Sjdp/* The common portion of as_warn and as_warn_where.  */
15433965Sjdp
15533965Sjdpstatic void
156130561Sobrienas_warn_internal (char *file, unsigned int line, char *buffer)
15733965Sjdp{
15833965Sjdp  ++warning_count;
15933965Sjdp
16033965Sjdp  if (file == NULL)
16133965Sjdp    as_where (&file, &line);
16233965Sjdp
16333965Sjdp  identify (file);
16433965Sjdp  if (file)
16533965Sjdp    fprintf (stderr, "%s:%u: ", file, line);
16660484Sobrien  fprintf (stderr, _("Warning: "));
16733965Sjdp  fputs (buffer, stderr);
16833965Sjdp  (void) putc ('\n', stderr);
16933965Sjdp#ifndef NO_LISTING
17033965Sjdp  listing_warning (buffer);
17133965Sjdp#endif
17233965Sjdp}
17333965Sjdp
17477298Sobrien/* Send to stderr a string as a warning, and locate warning
17577298Sobrien   in input file(s).
17677298Sobrien   Please only use this for when we have some recovery action.
17777298Sobrien   Please explain in string (which may have '\n's) what recovery was
17877298Sobrien   done.  */
17933965Sjdp
18033965Sjdp#ifdef USE_STDARG
18177298Sobrienvoid
18277298Sobrienas_warn (const char *format, ...)
18333965Sjdp{
18433965Sjdp  va_list args;
18538889Sjdp  char buffer[2000];
18633965Sjdp
18733965Sjdp  if (!flag_no_warnings)
18833965Sjdp    {
18933965Sjdp      va_start (args, format);
190218822Sdim      vsnprintf (buffer, sizeof (buffer), format, args);
19133965Sjdp      va_end (args);
19233965Sjdp      as_warn_internal ((char *) NULL, 0, buffer);
19333965Sjdp    }
19477298Sobrien}
19533965Sjdp#else
19677298Sobrienvoid
19733965Sjdpas_warn (format, va_alist)
19833965Sjdp     const char *format;
19933965Sjdp     va_dcl
20033965Sjdp{
20133965Sjdp  va_list args;
20238889Sjdp  char buffer[2000];
20333965Sjdp
20433965Sjdp  if (!flag_no_warnings)
20533965Sjdp    {
20633965Sjdp      va_start (args);
207218822Sdim      vsnprintf (buffer, sizeof (buffer), format, args);
20833965Sjdp      va_end (args);
20933965Sjdp      as_warn_internal ((char *) NULL, 0, buffer);
21033965Sjdp    }
21177298Sobrien}
21233965Sjdp#endif /* not NO_STDARG */
21333965Sjdp
21477298Sobrien/* Like as_bad but the file name and line number are passed in.
21577298Sobrien   Unfortunately, we have to repeat the function in order to handle
21677298Sobrien   the varargs correctly and portably.  */
21733965Sjdp
21833965Sjdp#ifdef USE_STDARG
21977298Sobrienvoid
22077298Sobrienas_warn_where (char *file, unsigned int line, const char *format, ...)
22133965Sjdp{
22233965Sjdp  va_list args;
22338889Sjdp  char buffer[2000];
22433965Sjdp
22533965Sjdp  if (!flag_no_warnings)
22633965Sjdp    {
22733965Sjdp      va_start (args, format);
228218822Sdim      vsnprintf (buffer, sizeof (buffer), format, args);
22933965Sjdp      va_end (args);
23033965Sjdp      as_warn_internal (file, line, buffer);
23133965Sjdp    }
23277298Sobrien}
23333965Sjdp#else
23477298Sobrienvoid
23533965Sjdpas_warn_where (file, line, format, va_alist)
23633965Sjdp     char *file;
23733965Sjdp     unsigned int line;
23833965Sjdp     const char *format;
23933965Sjdp     va_dcl
24033965Sjdp{
24133965Sjdp  va_list args;
24238889Sjdp  char buffer[2000];
24333965Sjdp
24433965Sjdp  if (!flag_no_warnings)
24533965Sjdp    {
24633965Sjdp      va_start (args);
247218822Sdim      vsnprintf (buffer, sizeof (buffer), format, args);
24833965Sjdp      va_end (args);
24933965Sjdp      as_warn_internal (file, line, buffer);
25033965Sjdp    }
25177298Sobrien}
25233965Sjdp#endif /* not NO_STDARG */
25333965Sjdp
25433965Sjdp/* The common portion of as_bad and as_bad_where.  */
25533965Sjdp
25633965Sjdpstatic void
257130561Sobrienas_bad_internal (char *file, unsigned int line, char *buffer)
25833965Sjdp{
25933965Sjdp  ++error_count;
26033965Sjdp
26133965Sjdp  if (file == NULL)
26233965Sjdp    as_where (&file, &line);
26333965Sjdp
26433965Sjdp  identify (file);
26533965Sjdp  if (file)
26633965Sjdp    fprintf (stderr, "%s:%u: ", file, line);
26760484Sobrien  fprintf (stderr, _("Error: "));
26833965Sjdp  fputs (buffer, stderr);
26933965Sjdp  (void) putc ('\n', stderr);
27033965Sjdp#ifndef NO_LISTING
27133965Sjdp  listing_error (buffer);
27233965Sjdp#endif
27333965Sjdp}
27433965Sjdp
27577298Sobrien/* Send to stderr a string as a warning, and locate warning in input
27677298Sobrien   file(s).  Please us when there is no recovery, but we want to
27777298Sobrien   continue processing but not produce an object file.
27877298Sobrien   Please explain in string (which may have '\n's) what recovery was
27977298Sobrien   done.  */
28033965Sjdp
28133965Sjdp#ifdef USE_STDARG
28277298Sobrienvoid
28377298Sobrienas_bad (const char *format, ...)
28433965Sjdp{
28533965Sjdp  va_list args;
28638889Sjdp  char buffer[2000];
28733965Sjdp
28833965Sjdp  va_start (args, format);
289218822Sdim  vsnprintf (buffer, sizeof (buffer), format, args);
29033965Sjdp  va_end (args);
29133965Sjdp
29233965Sjdp  as_bad_internal ((char *) NULL, 0, buffer);
29333965Sjdp}
29433965Sjdp
29533965Sjdp#else
29677298Sobrienvoid
29733965Sjdpas_bad (format, va_alist)
29833965Sjdp     const char *format;
29933965Sjdp     va_dcl
30033965Sjdp{
30133965Sjdp  va_list args;
30238889Sjdp  char buffer[2000];
30333965Sjdp
30433965Sjdp  va_start (args);
305218822Sdim  vsnprintf (buffer, sizeof (buffer), format, args);
30633965Sjdp  va_end (args);
30733965Sjdp
30833965Sjdp  as_bad_internal ((char *) NULL, 0, buffer);
30933965Sjdp}
31033965Sjdp#endif /* not NO_STDARG */
31133965Sjdp
31277298Sobrien/* Like as_bad but the file name and line number are passed in.
31377298Sobrien   Unfortunately, we have to repeat the function in order to handle
31477298Sobrien   the varargs correctly and portably.  */
31533965Sjdp
31633965Sjdp#ifdef USE_STDARG
31777298Sobrienvoid
31877298Sobrienas_bad_where (char *file, unsigned int line, const char *format, ...)
31933965Sjdp{
32033965Sjdp  va_list args;
32138889Sjdp  char buffer[2000];
32233965Sjdp
32333965Sjdp  va_start (args, format);
324218822Sdim  vsnprintf (buffer, sizeof (buffer), format, args);
32533965Sjdp  va_end (args);
32633965Sjdp
32733965Sjdp  as_bad_internal (file, line, buffer);
32833965Sjdp}
32933965Sjdp
33033965Sjdp#else
33177298Sobrienvoid
33233965Sjdpas_bad_where (file, line, format, va_alist)
33333965Sjdp     char *file;
33433965Sjdp     unsigned int line;
33533965Sjdp     const char *format;
33633965Sjdp     va_dcl
33733965Sjdp{
33833965Sjdp  va_list args;
33938889Sjdp  char buffer[2000];
34033965Sjdp
34133965Sjdp  va_start (args);
342218822Sdim  vsnprintf (buffer, sizeof (buffer), format, args);
34333965Sjdp  va_end (args);
34433965Sjdp
34533965Sjdp  as_bad_internal (file, line, buffer);
34633965Sjdp}
34733965Sjdp#endif /* not NO_STDARG */
34833965Sjdp
34977298Sobrien/* Send to stderr a string as a fatal message, and print location of
35077298Sobrien   error in input file(s).
35177298Sobrien   Please only use this for when we DON'T have some recovery action.
35277298Sobrien   It xexit()s with a warning status.  */
35333965Sjdp
35433965Sjdp#ifdef USE_STDARG
35577298Sobrienvoid
35677298Sobrienas_fatal (const char *format, ...)
35733965Sjdp{
35833965Sjdp  va_list args;
35933965Sjdp
36033965Sjdp  as_show_where ();
36133965Sjdp  va_start (args, format);
36260484Sobrien  fprintf (stderr, _("Fatal error: "));
36333965Sjdp  vfprintf (stderr, format, args);
36433965Sjdp  (void) putc ('\n', stderr);
36533965Sjdp  va_end (args);
36677298Sobrien  /* Delete the output file, if it exists.  This will prevent make from
36777298Sobrien     thinking that a file was created and hence does not need rebuilding.  */
36877298Sobrien  if (out_file_name != NULL)
369218822Sdim    unlink_if_ordinary (out_file_name);
37033965Sjdp  xexit (EXIT_FAILURE);
37177298Sobrien}
37233965Sjdp#else
37377298Sobrienvoid
37433965Sjdpas_fatal (format, va_alist)
37533965Sjdp     char *format;
37633965Sjdp     va_dcl
37733965Sjdp{
37833965Sjdp  va_list args;
37933965Sjdp
38033965Sjdp  as_show_where ();
38133965Sjdp  va_start (args);
38260484Sobrien  fprintf (stderr, _("Fatal error: "));
38333965Sjdp  vfprintf (stderr, format, args);
38433965Sjdp  (void) putc ('\n', stderr);
38533965Sjdp  va_end (args);
38633965Sjdp  xexit (EXIT_FAILURE);
38777298Sobrien}
38833965Sjdp#endif /* not NO_STDARG */
38933965Sjdp
39077298Sobrien/* Indicate assertion failure.
39177298Sobrien   Arguments: Filename, line number, optional function name.  */
39233965Sjdp
39333965Sjdpvoid
394130561Sobrienas_assert (const char *file, int line, const char *fn)
39533965Sjdp{
39633965Sjdp  as_show_where ();
39760484Sobrien  fprintf (stderr, _("Internal error!\n"));
39833965Sjdp  if (fn)
39960484Sobrien    fprintf (stderr, _("Assertion failure in %s at %s line %d.\n"),
40060484Sobrien	     fn, file, line);
40160484Sobrien  else
40260484Sobrien    fprintf (stderr, _("Assertion failure at %s line %d.\n"), file, line);
40360484Sobrien  fprintf (stderr, _("Please report this bug.\n"));
40433965Sjdp  xexit (EXIT_FAILURE);
40533965Sjdp}
40633965Sjdp
40733965Sjdp/* as_abort: Print a friendly message saying how totally hosed we are,
40833965Sjdp   and exit without producing a core file.  */
40977298Sobrien
41033965Sjdpvoid
411130561Sobrienas_abort (const char *file, int line, const char *fn)
41233965Sjdp{
41333965Sjdp  as_show_where ();
41433965Sjdp  if (fn)
41560484Sobrien    fprintf (stderr, _("Internal error, aborting at %s line %d in %s\n"),
41660484Sobrien	     file, line, fn);
41760484Sobrien  else
41860484Sobrien    fprintf (stderr, _("Internal error, aborting at %s line %d\n"),
41960484Sobrien	     file, line);
42060484Sobrien  fprintf (stderr, _("Please report this bug.\n"));
42133965Sjdp  xexit (EXIT_FAILURE);
42233965Sjdp}
42333965Sjdp
42433965Sjdp/* Support routines.  */
42533965Sjdp
42633965Sjdpvoid
427218822Sdimsprint_value (char *buf, valueT val)
42833965Sjdp{
42933965Sjdp  if (sizeof (val) <= sizeof (long))
43033965Sjdp    {
431218822Sdim      sprintf (buf, "%ld", (long) val);
43233965Sjdp      return;
43333965Sjdp    }
43433965Sjdp  if (sizeof (val) <= sizeof (bfd_vma))
43533965Sjdp    {
436218822Sdim      sprintf_vma (buf, val);
43733965Sjdp      return;
43833965Sjdp    }
43933965Sjdp  abort ();
44033965Sjdp}
44133965Sjdp
442218822Sdim#define HEX_MAX_THRESHOLD	1024
443218822Sdim#define HEX_MIN_THRESHOLD	-(HEX_MAX_THRESHOLD)
444218822Sdim
445218822Sdimstatic void
446218822Sdimas_internal_value_out_of_range (char *    prefix,
447218822Sdim				offsetT   val,
448218822Sdim				offsetT   min,
449218822Sdim				offsetT   max,
450218822Sdim				char *    file,
451218822Sdim				unsigned  line,
452218822Sdim				int       bad)
45333965Sjdp{
454218822Sdim  const char * err;
455218822Sdim
456218822Sdim  if (prefix == NULL)
457218822Sdim    prefix = "";
458218822Sdim
459218822Sdim  if (val >= min && val <= max)
46033965Sjdp    {
461218822Sdim      addressT right = max & -max;
462218822Sdim
463218822Sdim      if (max <= 1)
464218822Sdim	abort ();
465218822Sdim
466218822Sdim      /* xgettext:c-format  */
467218822Sdim      err = _("%s out of domain (%d is not a multiple of %d)");
468218822Sdim      if (bad)
469218822Sdim	as_bad_where (file, line, err,
470218822Sdim		      prefix, (int) val, (int) right);
471218822Sdim      else
472218822Sdim	as_warn_where (file, line, err,
473218822Sdim		       prefix, (int) val, (int) right);
47433965Sjdp      return;
47533965Sjdp    }
476218822Sdim
477218822Sdim  if (   val < HEX_MAX_THRESHOLD
478218822Sdim      && min < HEX_MAX_THRESHOLD
479218822Sdim      && max < HEX_MAX_THRESHOLD
480218822Sdim      && val > HEX_MIN_THRESHOLD
481218822Sdim      && min > HEX_MIN_THRESHOLD
482218822Sdim      && max > HEX_MIN_THRESHOLD)
48333965Sjdp    {
484218822Sdim      /* xgettext:c-format  */
485218822Sdim      err = _("%s out of range (%d is not between %d and %d)");
486218822Sdim
487218822Sdim      if (bad)
488218822Sdim	as_bad_where (file, line, err,
489218822Sdim		      prefix, (int) val, (int) min, (int) max);
490218822Sdim      else
491218822Sdim	as_warn_where (file, line, err,
492218822Sdim		       prefix, (int) val, (int) min, (int) max);
49333965Sjdp    }
494218822Sdim  else
495218822Sdim    {
496218822Sdim      char val_buf [sizeof (val) * 3 + 2];
497218822Sdim      char min_buf [sizeof (val) * 3 + 2];
498218822Sdim      char max_buf [sizeof (val) * 3 + 2];
499218822Sdim
500218822Sdim      if (sizeof (val) > sizeof (bfd_vma))
501218822Sdim	abort ();
502218822Sdim
503218822Sdim      sprintf_vma (val_buf, val);
504218822Sdim      sprintf_vma (min_buf, min);
505218822Sdim      sprintf_vma (max_buf, max);
506218822Sdim
507218822Sdim      /* xgettext:c-format.  */
508218822Sdim      err = _("%s out of range (0x%s is not between 0x%s and 0x%s)");
509218822Sdim
510218822Sdim      if (bad)
511218822Sdim	as_bad_where (file, line, err, prefix, val_buf, min_buf, max_buf);
512218822Sdim      else
513218822Sdim	as_warn_where (file, line, err, prefix, val_buf, min_buf, max_buf);
514218822Sdim    }
51533965Sjdp}
516218822Sdim
517218822Sdimvoid
518218822Sdimas_warn_value_out_of_range (char *   prefix,
519218822Sdim			   offsetT  value,
520218822Sdim			   offsetT  min,
521218822Sdim			   offsetT  max,
522218822Sdim			   char *   file,
523218822Sdim			   unsigned line)
524218822Sdim{
525218822Sdim  as_internal_value_out_of_range (prefix, value, min, max, file, line, 0);
526218822Sdim}
527218822Sdim
528218822Sdimvoid
529218822Sdimas_bad_value_out_of_range (char *   prefix,
530218822Sdim			   offsetT  value,
531218822Sdim			   offsetT  min,
532218822Sdim			   offsetT  max,
533218822Sdim			   char *   file,
534218822Sdim			   unsigned line)
535218822Sdim{
536218822Sdim  as_internal_value_out_of_range (prefix, value, min, max, file, line, 1);
537218822Sdim}
538