]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/fortran/scanner.c
Update FSF address.
[gcc.git] / gcc / fortran / scanner.c
index 8b8f0b0295e1138fdbf40108ad63d5558a3277a1..5aaecdb2ed99e9e1e9ec6bc8b45239ea4dd8a54e 100644 (file)
@@ -1,5 +1,6 @@
 /* Character scanner.
-   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
 
 This file is part of GCC.
@@ -16,8 +17,8 @@ for more details.
 
 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.  */
 
 /* Set of subroutines to (ultimately) return the next character to the
    various matching subroutines.  This file's job is to read files and
@@ -42,11 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    new characters and do a lot of jumping backwards.  */
 
 #include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-
+#include "system.h"
 #include "gfortran.h"
 
 /* Structure for holding module and include file search path.  */
@@ -360,7 +357,7 @@ skip_free_comments (void)
 
 /* Skip comment lines in fixed source mode.  We have the same rules as
    in skip_free_comment(), except that we can have a 'c', 'C' or '*'
-   in column 1. and a '!' cannot be in* column 6.  */
+   in column 1, and a '!' cannot be in column 6.  */
 
 static void
 skip_fixed_comments (void)
@@ -461,6 +458,9 @@ restart:
            }
          while (c != '\n');
 
+         /* Avoid truncation warnings for comment ending lines.  */
+         gfc_current_locus.lb->truncated = 0;
+
          goto done;
        }
 
@@ -468,7 +468,7 @@ restart:
        goto done;
 
       /* If the next nonblank character is a ! or \n, we've got a
-         continuation line. */
+         continuation line.  */
       old_loc = gfc_current_locus;
 
       c = next_char ();
@@ -528,6 +528,9 @@ restart:
              c = next_char ();
            }
          while (c != '\n');
+
+         /* Avoid truncation warnings for comment ending lines.  */
+         gfc_current_locus.lb->truncated = 0;
        }
 
       if (c != '\n')
@@ -634,21 +637,17 @@ gfc_error_recovery (void)
          if (c == delim)
            break;
          if (c == '\n')
-           goto done;
+           return;
          if (c == '\\')
            {
              c = next_char ();
              if (c == '\n')
-               goto done;
+               return;
            }
        }
       if (gfc_at_eof ())
        break;
     }
-
-done:
-  if (c == '\n')
-    gfc_advance_line ();
 }
 
 
@@ -671,26 +670,51 @@ gfc_gobble_whitespace (void)
 }
 
 
-/* Load a single line into the buffer.  We truncate lines that are too
-   long.  In fixed mode, we expand a tab that occurs within the
-   statement label region to expand to spaces that leave the next
-   character in the source region.  */
+/* Load a single line into pbuf.
 
-static void
-load_line (FILE * input, char *buffer, char *filename, int linenum)
+   If pbuf points to a NULL pointer, it is allocated.
+   We truncate lines that are too long, unless we're dealing with
+   preprocessor lines or if the option -ffixed-line-length-none is set,
+   in which case we reallocate the buffer to fit the entire line, if
+   need be.
+   In fixed mode, we expand a tab that occurs within the statement
+   label region to expand to spaces that leave the next character in
+   the source region.
+   load_line returns wether the line was truncated.  */
+
+static int
+load_line (FILE * input, char **pbuf)
 {
-  int c, maxlen, i, trunc_flag, preprocessor_flag;
+  int c, maxlen, i, preprocessor_flag;
+  int trunc_flag = 0;
+  static int buflen = 0;
+  char *buffer;
 
-  maxlen = (gfc_current_form == FORM_FREE) 
-    ? 132 
-    : gfc_option.fixed_line_length;
+  /* Determine the maximum allowed line length.  */
+  if (gfc_current_form == FORM_FREE)
+    maxlen = GFC_MAX_LINE;
+  else
+    maxlen = gfc_option.fixed_line_length;
+
+  if (*pbuf == NULL)
+    {
+      /* Allocate the line buffer, storing its length into buflen.  */
+      if (maxlen > 0)
+       buflen = maxlen;
+      else
+       buflen = GFC_MAX_LINE;
+
+      *pbuf = gfc_getmem (buflen + 1);
+    }
 
   i = 0;
+  buffer = *pbuf;
 
   preprocessor_flag = 0;
   c = fgetc (input);
   if (c == '#')
-    /* Don't truncate preprocessor lines.  */
+    /* In order to not truncate preprocessor lines, we have to
+       remember that this is one.  */
     preprocessor_flag = 1;
   ungetc (c, input);
 
@@ -716,7 +740,7 @@ load_line (FILE * input, char *buffer, char *filename, int linenum)
        }
 
       if (gfc_current_form == FORM_FIXED && c == '\t' && i <= 6)
-       {                       /* Tab expandsion.  */
+       {                       /* Tab expansion.  */
          while (i <= 6)
            {
              *buffer++ = ' ';
@@ -729,31 +753,41 @@ load_line (FILE * input, char *buffer, char *filename, int linenum)
       *buffer++ = c;
       i++;
 
-      if (i >= maxlen && !preprocessor_flag)
-       {                       /* Truncate the rest of the line.  */
-         trunc_flag = 1;
-
+      if (i >= buflen && (maxlen == 0 || preprocessor_flag))
+       {
+         /* Reallocate line buffer to double size to hold the
+            overlong line.  */
+         buflen = buflen * 2;
+         *pbuf = xrealloc (*pbuf, buflen);
+         buffer = (*pbuf)+i;
+       }
+      else if (i >= buflen)
+       {                       
+         /* Truncate the rest of the line.  */
          for (;;)
            {
              c = fgetc (input);
              if (c == '\n' || c == EOF)
                break;
 
-             if (gfc_option.warn_line_truncation
-                 && trunc_flag
-                 && !gfc_is_whitespace (c))
-               {
-                 gfc_warning_now ("%s:%d: Line is being truncated",
-                                  filename, linenum);
-                 trunc_flag = 0;
-               }
+             trunc_flag = 1;
            }
 
          ungetc ('\n', input);
        }
     }
 
+  /* Pad lines to the selected line length in fixed form.  */
+  if (gfc_current_form == FORM_FIXED
+      && gfc_option.fixed_line_length > 0
+      && !preprocessor_flag
+      && c != EOF)
+    while (i++ < buflen)
+      *buffer++ = ' ';
+
   *buffer = '\0';
+
+  return trunc_flag;
 }
 
 
@@ -761,7 +795,7 @@ load_line (FILE * input, char *buffer, char *filename, int linenum)
    the file stack.  */
 
 static gfc_file *
-get_file (char *name)
+get_file (char *name, enum lc_reason reason ATTRIBUTE_UNUSED)
 {
   gfc_file *f;
 
@@ -777,6 +811,10 @@ get_file (char *name)
   if (current_file != NULL)
     f->inclusion_line = current_file->line;
 
+#ifdef USE_MAPPED_LOCATION
+  linemap_add (&line_table, reason, false, f->filename, 1);
+#endif
+
   return f;
 }
 
@@ -790,6 +828,7 @@ preprocessor_line (char *c)
   int i, line;
   char *filename;
   gfc_file *f;
+  int escaped;
 
   c++;
   while (*c == ' ' || *c == '\t')
@@ -800,19 +839,46 @@ preprocessor_line (char *c)
 
   line = atoi (c);
 
+  /* Set new line number.  */
+  current_file->line = line;
+
   c = strchr (c, ' '); 
   if (c == NULL)
-    /* Something we don't understand has happened.  */
+    /* No file name given.  */
+    return;
+
+
+
+  /* Skip spaces.  */
+  while (*c == ' ' || *c == '\t')
+    c++;
+
+  /* Skip quote.  */
+  if (*c != '"')
     goto bad_cpp_line;
-  c += 2;     /* Skip space and quote.  */
+  ++c;
+
   filename = c;
 
-  c = strchr (c, '"'); /* Make filename end at quote.  */
-  if (c == NULL)
+  /* Make filename end at quote.  */
+  escaped = false;
+  while (*c && ! (! escaped && *c == '"'))
+    {
+      if (escaped)
+        escaped = false;
+      else
+        escaped = *c == '\\';
+      ++c;
+    }
+
+  if (! *c)
     /* Preprocessor line has no closing quote.  */
     goto bad_cpp_line;
+
   *c++ = '\0';
 
+
+
   /* Get flags.  */
   
   flag[1] = flag[2] = flag[3] = flag[4] = flag[5] = false;
@@ -834,7 +900,7 @@ preprocessor_line (char *c)
   
   if (flag[1] || flag[3]) /* Starting new file.  */
     {
-      f = get_file (filename);
+      f = get_file (filename, LC_RENAME);
       f->up = current_file;
       current_file = f;
     }
@@ -844,8 +910,6 @@ preprocessor_line (char *c)
       current_file = current_file->up;
     }
   
-  current_file->line = line;
-  
   /* The name of the file can be a temporary file produced by
      cpp. Replace the name if it is different.  */
   
@@ -859,7 +923,7 @@ preprocessor_line (char *c)
   return;
 
  bad_cpp_line:
-  gfc_warning_now ("%s:%d: Unknown preprocessor directive", 
+  gfc_warning_now ("%s:%d: Illegal preprocessor directive", 
                   current_file->filename, current_file->line);
   current_file->line++;
 }
@@ -911,7 +975,7 @@ include_line (char *line)
   if (*c != '\0' && *c != '!')
     return false;
 
-  /* We have an include line at this point. */
+  /* We have an include line at this point.  */
 
   *stop = '\0'; /* It's ok to trash the buffer, as this line won't be
                   read by anything else.  */
@@ -925,7 +989,7 @@ include_line (char *line)
 static try
 load_file (char *filename, bool initial)
 {
-  char line[GFC_MAX_LINE+1];
+  char *line;
   gfc_linebuf *b;
   gfc_file *f;
   FILE *input;
@@ -959,14 +1023,15 @@ load_file (char *filename, bool initial)
 
   /* Load the file.  */
 
-  f = get_file (filename);
+  f = get_file (filename, initial ? LC_RENAME : LC_ENTER);
   f->up = current_file;
   current_file = f;
   current_file->line = 1;
+  line = NULL;
 
   for (;;) 
     {
-      load_line (input, line, filename, current_file->line);
+      int trunc = load_line (input, &line);
 
       len = strlen (line);
       if (feof (input) && len == 0)
@@ -989,10 +1054,16 @@ load_file (char *filename, bool initial)
 
       /* Add line.  */
 
-      b = gfc_getmem (sizeof (gfc_linebuf) + len + 1);
+      b = gfc_getmem (gfc_linebuf_header_size + len + 1);
 
+#ifdef USE_MAPPED_LOCATION
+      b->location
+       = linemap_line_start (&line_table, current_file->line++, 120);
+#else
       b->linenum = current_file->line++;
+#endif
       b->file = current_file;
+      b->truncated = trunc;
       strcpy (b->line, line);
 
       if (line_head == NULL)
@@ -1003,15 +1074,21 @@ load_file (char *filename, bool initial)
       line_tail = b;
     }
 
+  /* Release the line buffer allocated in load_line.  */
+  gfc_free (line);
+
   fclose (input);
 
   current_file = current_file->up;
+#ifdef USE_MAPPED_LOCATION
+  linemap_add (&line_table, LC_LEAVE, 0, NULL, 0);
+#endif
   return SUCCESS;
 }
 
 
 /* Determine the source form from the filename extension.  We assume
-   case insensitivity. */
+   case insensitivity.  */
 
 static gfc_source_form
 form_from_filename (const char *filename)
@@ -1123,7 +1200,12 @@ gfc_new_file (const char *filename, gfc_source_form form)
 #if 0 /* Debugging aid.  */
   for (; line_head; line_head = line_head->next)
     gfc_status ("%s:%3d %s\n", line_head->file->filename, 
-               line_head->linenum, line_head->line);
+#ifdef USE_MAPPED_LOCATION
+               LOCATION_LINE (line_head->location),
+#else
+               line_head->linenum,
+#endif
+               line_head->line);
 
   exit (0);
 #endif
This page took 0.043106 seconds and 5 git commands to generate.