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