OSDN Git Service

*error.c: Use flag_fatal_error.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / error.c
index be3d991..aa23330 100644 (file)
@@ -1,23 +1,24 @@
 /* Handle errors.
-   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation,
+   Inc.
    Contributed by Andy Vaught & Niels Kristian Bech Jensen
 
-This file is part of GNU G95.
+This file is part of GCC.
 
-GNU G95 is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU G95 is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU G95; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+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
@@ -27,23 +28,14 @@ Boston, MA 02111-1307, USA.  */
 
 #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 int terminal_width, buffer_flag, errors, warnings;
 
-static char *error_ptr, *warning_ptr;
-
-static gfc_error_buf error_buffer, warning_buffer;
+static gfc_error_buf error_buffer, warning_buffer, *cur_error_buffer;
 
 
 /* Per-file error initialization.  */
@@ -51,8 +43,7 @@ static gfc_error_buf error_buffer, warning_buffer;
 void
 gfc_error_init_1 (void)
 {
-
-  terminal_width = gfc_terminal_width();
+  terminal_width = gfc_terminal_width ();
   errors = 0;
   warnings = 0;
   buffer_flag = 0;
@@ -64,7 +55,6 @@ gfc_error_init_1 (void)
 void
 gfc_buffer_error (int flag)
 {
-
   buffer_flag = flag;
 }
 
@@ -75,26 +65,41 @@ gfc_buffer_error (int flag)
 static void
 error_char (char c)
 {
-
   if (buffer_flag)
     {
-      if (use_warning_buffer)
+      if (cur_error_buffer->index >= cur_error_buffer->allocated)
        {
-         *warning_ptr++ = c;
-         if (warning_ptr - warning_buffer.message >= MAX_ERROR_MESSAGE)
-           gfc_internal_error ("error_char(): Warning buffer overflow");
-       }
-      else
-       {
-         *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;
+           }
+       }
     }
 }
 
@@ -104,21 +109,21 @@ error_char (char c)
 static void
 error_string (const char *p)
 {
-
   while (*p)
     error_char (*p++);
 }
 
 
-/* Show the file, where it was included and the source line give a
+/* Show the file, where it was included and the source line, give a
    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 * l)
+show_locus (int offset, locus * loc)
 {
+  gfc_linebuf *lb;
   gfc_file *f;
   char c, *p;
   int i, m;
@@ -126,20 +131,31 @@ show_locus (int offset, locus * l)
   /* TODO: Either limit the total length and number of included files
      displayed or add buffering of arbitrary number of characters in
      error messages.  */
-  f = l->file;
-  error_printf ("In file %s:%d\n", f->filename, l->lp->start_line + l->line);
 
-  f = f->included_by;
-  while (f != NULL)
+  lb = loc->lb;
+  f = lb->file;
+  error_printf ("In file %s:%d\n", f->filename,
+#ifdef USE_MAPPED_LOCATION
+               LOCATION_LINE (lb->location)
+#else
+               lb->linenum
+#endif
+               );
+
+  for (;;)
     {
-      error_printf ("    Included at %s:%d\n", f->filename,
-                   f->loc.lp->start_line + f->loc.line);
+      i = f->inclusion_line;
+
       f = f->included_by;
+      if (f == NULL) break;
+
+      error_printf ("    Included at %s:%d\n", f->filename, i);
     }
 
   /* Show the line itself, taking care not to print more than what can
      show up on the terminal.  Tabs are converted to spaces.  */
-  p = l->lp->line[l->line] + offset;
+
+  p = lb->line + offset;
   i = strlen (p);
   if (i > terminal_width)
     i = terminal_width - 1;
@@ -189,12 +205,12 @@ show_loci (locus * l1, locus * l2)
       return;
     }
 
-  c1 = l1->nextc - l1->lp->line[l1->line];
+  c1 = l1->nextc - l1->lb->line;
   c2 = 0;
   if (l2 == NULL)
     goto separate;
 
-  c2 = l2->nextc - l2->lp->line[l2->line];
+  c2 = l2->nextc - l2->lb->line;
 
   if (c1 < c2)
     m = c2 - c1;
@@ -202,7 +218,7 @@ show_loci (locus * l1, locus * l2)
     m = c1 - c2;
 
 
-  if (l1->lp != l2->lp || l1->line != l2->line || m > terminal_width - 10)
+  if (l1->lb != l2->lb || m > terminal_width - 10)
     goto separate;
 
   offset = 0;
@@ -298,7 +314,7 @@ separate:
 #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];
@@ -331,7 +347,7 @@ error_print (const char *type, const char *format0, va_list argp)
 
            case 'C':
              if (c == 'C')
-               loc = gfc_current_locus ();
+               loc = &gfc_current_locus;
 
              if (have_l1)
                {
@@ -433,12 +449,12 @@ error_print (const char *type, const char *format0, va_list argp)
 /* 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);
 }
 
@@ -446,7 +462,7 @@ error_printf (const char *format, ...)
 /* Issue a warning.  */
 
 void
-gfc_warning (const char *format, ...)
+gfc_warning (const char *nocmsgid, ...)
 {
   va_list argp;
 
@@ -454,13 +470,13 @@ gfc_warning (const char *format, ...)
     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');
@@ -470,10 +486,10 @@ gfc_warning (const char *format, ...)
 /* 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;
@@ -487,18 +503,9 @@ gfc_notify_std (int std, const char *format, ...)
   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)
     {
@@ -507,11 +514,11 @@ gfc_notify_std (int std, const char *format, ...)
       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');
@@ -522,7 +529,7 @@ gfc_notify_std (int std, const char *format, ...)
 /* 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;
@@ -534,8 +541,8 @@ gfc_warning_now (const char *format, ...)
   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');
@@ -548,7 +555,6 @@ gfc_warning_now (const char *format, ...)
 void
 gfc_clear_warning (void)
 {
-
   warning_buffer.flag = 0;
 }
 
@@ -559,11 +565,11 @@ gfc_clear_warning (void)
 void
 gfc_warning_check (void)
 {
-
   if (warning_buffer.flag)
     {
       warnings++;
-      fputs (warning_buffer.message, stderr);
+      if (warning_buffer.message != NULL)
+       fputs (warning_buffer.message, stderr);
       warning_buffer.flag = 0;
     }
 }
@@ -572,7 +578,7 @@ gfc_warning_check (void)
 /* Issue an error.  */
 
 void
-gfc_error (const char *format, ...)
+gfc_error (const char *nocmsgid, ...)
 {
   va_list argp;
 
@@ -580,13 +586,13 @@ gfc_error (const char *format, ...)
     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');
@@ -596,38 +602,42 @@ gfc_error (const char *format, ...)
 /* 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);
@@ -645,7 +655,7 @@ gfc_internal_error (const char *format, ...)
 
   va_start (argp, format);
 
-  show_loci (gfc_current_locus (), NULL);
+  show_loci (&gfc_current_locus, NULL);
   error_printf ("Internal Error at (1):");
 
   error_print ("", format, argp);
@@ -660,7 +670,6 @@ gfc_internal_error (const char *format, ...)
 void
 gfc_clear_error (void)
 {
-
   error_buffer.flag = 0;
 }
 
@@ -678,8 +687,12 @@ gfc_error_check (void)
   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;
@@ -691,10 +704,9 @@ gfc_error_check (void)
 void
 gfc_push_error (gfc_error_buf * err)
 {
-
   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;
 }
@@ -705,23 +717,37 @@ gfc_push_error (gfc_error_buf * err)
 void
 gfc_pop_error (gfc_error_buf * err)
 {
-
   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);
 }
@@ -737,12 +763,11 @@ gfc_status_char (char c)
 }
 
 
-/* Report the number of warnings and errors that occored to the caller.  */
+/* Report the number of warnings and errors that occurred to the caller.  */
 
 void
 gfc_get_errors (int *w, int *e)
 {
-
   if (w != NULL)
     *w = warnings;
   if (e != NULL)