/* Handle errors.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation,
- Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
+ Foundation, Inc.
Contributed by Andy Vaught & Niels Kristian Bech Jensen
This file is part of GCC.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* Handle the inevitable errors. A major catch here is that things
flagged as errors in one match subroutine can conceivably be legal
#include "config.h"
#include "system.h"
-
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
#include "flags.h"
#include "gfortran.h"
int gfc_suppress_error = 0;
-static int terminal_width, buffer_flag, errors,
- use_warning_buffer, warnings;
-
-static char *error_ptr, *warning_ptr;
+static int terminal_width, buffer_flag, errors, warnings;
-static gfc_error_buf error_buffer, warning_buffer;
+static gfc_error_buf error_buffer, warning_buffer, *cur_error_buffer;
/* Per-file error initialization. */
{
if (buffer_flag)
{
- if (use_warning_buffer)
- {
- *warning_ptr++ = c;
- if (warning_ptr - warning_buffer.message >= MAX_ERROR_MESSAGE)
- gfc_internal_error ("error_char(): Warning buffer overflow");
- }
- else
+ if (cur_error_buffer->index >= cur_error_buffer->allocated)
{
- *error_ptr++ = c;
- if (error_ptr - error_buffer.message >= MAX_ERROR_MESSAGE)
- gfc_internal_error ("error_char(): Error buffer overflow");
+ cur_error_buffer->allocated =
+ cur_error_buffer->allocated
+ ? cur_error_buffer->allocated * 2 : 1000;
+ cur_error_buffer->message
+ = xrealloc (cur_error_buffer->message,
+ cur_error_buffer->allocated);
}
+ cur_error_buffer->message[cur_error_buffer->index++] = c;
}
else
{
if (c != 0)
- fputc (c, stderr);
+ {
+ /* We build up complete lines before handing things
+ over to the library in order to speed up error printing. */
+ static char *line;
+ static size_t allocated = 0, index = 0;
+
+ if (index + 1 >= allocated)
+ {
+ allocated = allocated ? allocated * 2 : 1000;
+ line = xrealloc (line, allocated);
+ }
+ line[index++] = c;
+ if (c == '\n')
+ {
+ line[index] = '\0';
+ fputs (line, stderr);
+ index = 0;
+ }
+ }
}
}
locus. Calls error_printf() recursively, but the recursion is at
most one level deep. */
-static void error_printf (const char *, ...) ATTRIBUTE_PRINTF_1;
+static void error_printf (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
static void
show_locus (int offset, locus * loc)
lb = loc->lb;
f = lb->file;
- error_printf ("In file %s:%d\n", f->filename, lb->linenum);
+ error_printf ("In file %s:%d\n", f->filename,
+#ifdef USE_MAPPED_LOCATION
+ LOCATION_LINE (lb->location)
+#else
+ lb->linenum
+#endif
+ );
for (;;)
{
#define IBUF_LEN 30
#define MAX_ARGS 10
-static void
+static void ATTRIBUTE_GCC_GFC(2,0)
error_print (const char *type, const char *format0, va_list argp)
{
char c, *p, int_buf[IBUF_LEN], c_arg[MAX_ARGS], *cp_arg[MAX_ARGS];
/* Wrapper for error_print(). */
static void
-error_printf (const char *format, ...)
+error_printf (const char *nocmsgid, ...)
{
va_list argp;
- va_start (argp, format);
- error_print ("", format, argp);
+ va_start (argp, nocmsgid);
+ error_print ("", _(nocmsgid), argp);
va_end (argp);
}
/* Issue a warning. */
void
-gfc_warning (const char *format, ...)
+gfc_warning (const char *nocmsgid, ...)
{
va_list argp;
return;
warning_buffer.flag = 1;
- warning_ptr = warning_buffer.message;
- use_warning_buffer = 1;
+ warning_buffer.index = 0;
+ cur_error_buffer = &warning_buffer;
- va_start (argp, format);
+ va_start (argp, nocmsgid);
if (buffer_flag == 0)
warnings++;
- error_print ("Warning:", format, argp);
+ error_print (_("Warning:"), _(nocmsgid), argp);
va_end (argp);
error_char ('\0');
}
+/* Whether, for a feature included in a given standard set (GFC_STD_*),
+ we should issue an error or a warning, or be quiet. */
+
+notification
+gfc_notification_std (int std)
+{
+ bool warning;
+
+ warning = ((gfc_option.warn_std & std) != 0) && !inhibit_warnings;
+ if ((gfc_option.allow_std & std) != 0 && !warning)
+ return SILENT;
+
+ return warning ? WARNING : ERROR;
+}
+
+
/* Possibly issue a warning/error about use of a nonstandard (or deleted)
feature. An error/warning will be issued if the currently selected
standard does not contain the requested bits. Return FAILURE if
- and error is generated. */
+ an error is generated. */
try
-gfc_notify_std (int std, const char *format, ...)
+gfc_notify_std (int std, const char *nocmsgid, ...)
{
va_list argp;
bool warning;
if (gfc_suppress_error)
return warning ? SUCCESS : FAILURE;
- if (warning)
- {
- warning_buffer.flag = 1;
- warning_ptr = warning_buffer.message;
- use_warning_buffer = 1;
- }
- else
- {
- error_buffer.flag = 1;
- error_ptr = error_buffer.message;
- use_warning_buffer = 0;
- }
+ cur_error_buffer = warning ? &warning_buffer : &error_buffer;
+ cur_error_buffer->flag = 1;
+ cur_error_buffer->index = 0;
if (buffer_flag == 0)
{
else
errors++;
}
- va_start (argp, format);
+ va_start (argp, nocmsgid);
if (warning)
- error_print ("Warning:", format, argp);
+ error_print (_("Warning:"), _(nocmsgid), argp);
else
- error_print ("Error:", format, argp);
+ error_print (_("Error:"), _(nocmsgid), argp);
va_end (argp);
error_char ('\0');
/* Immediate warning (i.e. do not buffer the warning). */
void
-gfc_warning_now (const char *format, ...)
+gfc_warning_now (const char *nocmsgid, ...)
{
va_list argp;
int i;
buffer_flag = 0;
warnings++;
- va_start (argp, format);
- error_print ("Warning:", format, argp);
+ va_start (argp, nocmsgid);
+ error_print (_("Warning:"), _(nocmsgid), argp);
va_end (argp);
error_char ('\0');
if (warning_buffer.flag)
{
warnings++;
- fputs (warning_buffer.message, stderr);
+ if (warning_buffer.message != NULL)
+ fputs (warning_buffer.message, stderr);
warning_buffer.flag = 0;
}
}
/* Issue an error. */
void
-gfc_error (const char *format, ...)
+gfc_error (const char *nocmsgid, ...)
{
va_list argp;
return;
error_buffer.flag = 1;
- error_ptr = error_buffer.message;
- use_warning_buffer = 0;
+ error_buffer.index = 0;
+ cur_error_buffer = &error_buffer;
- va_start (argp, format);
+ va_start (argp, nocmsgid);
if (buffer_flag == 0)
errors++;
- error_print ("Error:", format, argp);
+ error_print (_("Error:"), _(nocmsgid), argp);
va_end (argp);
error_char ('\0');
/* Immediate error. */
void
-gfc_error_now (const char *format, ...)
+gfc_error_now (const char *nocmsgid, ...)
{
va_list argp;
int i;
error_buffer.flag = 1;
- error_ptr = error_buffer.message;
+ error_buffer.index = 0;
+ cur_error_buffer = &error_buffer;
i = buffer_flag;
buffer_flag = 0;
errors++;
- va_start (argp, format);
- error_print ("Error:", format, argp);
+ va_start (argp, nocmsgid);
+ error_print (_("Error:"), _(nocmsgid), argp);
va_end (argp);
error_char ('\0');
buffer_flag = i;
+
+ if (flag_fatal_errors)
+ exit (1);
}
/* Fatal error, never returns. */
void
-gfc_fatal_error (const char *format, ...)
+gfc_fatal_error (const char *nocmsgid, ...)
{
va_list argp;
buffer_flag = 0;
- va_start (argp, format);
- error_print ("Fatal Error:", format, argp);
+ va_start (argp, nocmsgid);
+ error_print (_("Fatal Error:"), _(nocmsgid), argp);
va_end (argp);
exit (3);
error_print ("", format, argp);
va_end (argp);
- exit (4);
+ exit (ICE_EXIT_CODE);
}
if (error_buffer.flag)
{
errors++;
- fputs (error_buffer.message, stderr);
+ if (error_buffer.message != NULL)
+ fputs (error_buffer.message, stderr);
error_buffer.flag = 0;
+
+ if (flag_fatal_errors)
+ exit (1);
}
return rc;
{
err->flag = error_buffer.flag;
if (error_buffer.flag)
- strcpy (err->message, error_buffer.message);
+ err->message = xstrdup (error_buffer.message);
error_buffer.flag = 0;
}
{
error_buffer.flag = err->flag;
if (error_buffer.flag)
- strcpy (error_buffer.message, err->message);
+ {
+ size_t len = strlen (err->message) + 1;
+ gcc_assert (len <= error_buffer.allocated);
+ memcpy (error_buffer.message, err->message, len);
+ gfc_free (err->message);
+ }
+}
+
+
+/* Free a pushed error state, but keep the current error state. */
+
+void
+gfc_free_error (gfc_error_buf * err)
+{
+ if (err->flag)
+ gfc_free (err->message);
}
/* Debug wrapper for printf. */
void
-gfc_status (const char *format, ...)
+gfc_status (const char *cmsgid, ...)
{
va_list argp;
- va_start (argp, format);
+ va_start (argp, cmsgid);
- vprintf (format, argp);
+ vprintf (_(cmsgid), argp);
va_end (argp);
}
}
-/* Report the number of warnings and errors that occured to the caller. */
+/* Report the number of warnings and errors that occurred to the caller. */
void
gfc_get_errors (int *w, int *e)