lang.opt (fdec-include): New option.
authorJakub Jelinek <jakub@redhat.com>
Wed, 21 Nov 2018 08:07:51 +0000 (09:07 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 21 Nov 2018 08:07:51 +0000 (09:07 +0100)
* lang.opt (fdec-include): New option.
* options.c (set_dec_flags): Set also flag_dec_include.
* scanner.c (include_line): Change return type from bool to int.
In fixed form allow spaces in between include keyword letters.
For -fdec-include, allow in fixed form 0 in column 6.  With
-fdec-include return -1 if the parsed line is not full include
statement and it could be successfully completed on continuation
lines.
(include_stmt): New function.
(load_file): Adjust include_line caller.  If it returns -1, keep
trying include_stmt until it stops returning -1 whenever adding
further line of input.

* gfortran.dg/include_10.f: New test.
* gfortran.dg/include_10.inc: New file.
* gfortran.dg/include_11.f: New test.
* gfortran.dg/include_12.f: New test.
* gfortran.dg/include_13.f90: New test.
* gfortran.dg/gomp/include_1.f: New test.
* gfortran.dg/gomp/include_1.inc: New file.
* gfortran.dg/gomp/include_2.f90: New test.

Co-Authored-By: Mark Eggleston <mark.eggleston@codethink.com>
From-SVN: r266337

13 files changed:
gcc/fortran/ChangeLog
gcc/fortran/lang.opt
gcc/fortran/options.c
gcc/fortran/scanner.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/gomp/include_1.f [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/include_1.inc [new file with mode: 0644]
gcc/testsuite/gfortran.dg/gomp/include_2.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/include_10.f [new file with mode: 0644]
gcc/testsuite/gfortran.dg/include_10.inc [new file with mode: 0644]
gcc/testsuite/gfortran.dg/include_11.f [new file with mode: 0644]
gcc/testsuite/gfortran.dg/include_12.f [new file with mode: 0644]
gcc/testsuite/gfortran.dg/include_13.f90 [new file with mode: 0644]

index 15f594265b0a7bde92f6b9a684655b671496be10..455c74c60a31fec05c9c57055bbf526bc439a2c9 100644 (file)
@@ -1,3 +1,19 @@
+2018-11-21  Jakub Jelinek  <jakub@redhat.com>
+           Mark Eggleston  <mark.eggleston@codethink.com>
+
+       * lang.opt (fdec-include): New option.
+       * options.c (set_dec_flags): Set also flag_dec_include.
+       * scanner.c (include_line): Change return type from bool to int.
+       In fixed form allow spaces in between include keyword letters.
+       For -fdec-include, allow in fixed form 0 in column 6.  With
+       -fdec-include return -1 if the parsed line is not full include
+       statement and it could be successfully completed on continuation
+       lines.
+       (include_stmt): New function.
+       (load_file): Adjust include_line caller.  If it returns -1, keep
+       trying include_stmt until it stops returning -1 whenever adding
+       further line of input.
+
 2018-11-18  Thomas Koenig  <tkoenig@gcc.gnu.org>
 
        PR fortran/88073
index 2b7f2903761865dead2076210382f40d443df881..fe0c69342205a865ce39ba0909777e29d5d7ce39 100644 (file)
@@ -440,6 +440,10 @@ fdec
 Fortran Var(flag_dec)
 Enable all DEC language extensions.
 
+fdec-include
+Fortran Var(flag_dec_include)
+Enable legacy parsing of INCLUDE as statement.
+
 fdec-intrinsic-ints
 Fortran Var(flag_dec_intrinsic_ints)
 Enable kind-specific variants of integer intrinsic functions.
index 73f5389361d9b1d1e9bc2888cb2516574cde4049..e59ba31ba7bcbb07f543ab8e5636f8a5c4986e2f 100644 (file)
@@ -68,6 +68,7 @@ set_dec_flags (int value)
   flag_dec_intrinsic_ints |= value;
   flag_dec_static |= value;
   flag_dec_math |= value;
+  flag_dec_include |= value;
 }
 
 
index 55d6dafdb5dd46d68f28da929ace3939d070e97d..5b27ab5e52d9b97bbf0f1994035a676d1c6a255f 100644 (file)
@@ -2135,14 +2135,18 @@ static bool load_file (const char *, const char *, bool);
 /* include_line()-- Checks a line buffer to see if it is an include
    line.  If so, we call load_file() recursively to load the included
    file.  We never return a syntax error because a statement like
-   "include = 5" is perfectly legal.  We return false if no include was
-   processed or true if we matched an include.  */
+   "include = 5" is perfectly legal.  We return 0 if no include was
+   processed, 1 if we matched an include or -1 if include was
+   partially processed, but will need continuation lines.  */
 
-static bool
+static int
 include_line (gfc_char_t *line)
 {
   gfc_char_t quote, *c, *begin, *stop;
   char *filename;
+  const char *include = "include";
+  bool allow_continuation = flag_dec_include;
+  int i;
 
   c = line;
 
@@ -2158,42 +2162,133 @@ include_line (gfc_char_t *line)
       else
        {
          if ((*c == '!' || *c == 'c' || *c == 'C' || *c == '*')
-             && c[1] == '$' && (c[2] == ' ' || c[2] == '\t'))
+             && c[1] == '$' && c[2] == ' ')
            c += 3;
        }
     }
 
-  while (*c == ' ' || *c == '\t')
-    c++;
+  if (gfc_current_form == FORM_FREE)
+    {
+      while (*c == ' ' || *c == '\t')
+       c++;
+      if (gfc_wide_strncasecmp (c, "include", 7))
+       {
+         if (!allow_continuation)
+           return 0;
+         for (i = 0; i < 7; ++i)
+           {
+             gfc_char_t c1 = gfc_wide_tolower (*c);
+             if (c1 != (unsigned char) include[i])
+               break;
+             c++;
+           }
+         if (i == 0 || *c != '&')
+           return 0;
+         c++;
+         while (*c == ' ' || *c == '\t')
+           c++;
+         if (*c == '\0' || *c == '!')
+           return -1;
+         return 0;
+       }
 
-  if (gfc_wide_strncasecmp (c, "include", 7))
-    return false;
+      c += 7;
+    }
+  else
+    {
+      while (*c == ' ' || *c == '\t')
+       c++;
+      if (flag_dec_include && *c == '0' && c - line == 5)
+       {
+         c++;
+         while (*c == ' ' || *c == '\t')
+           c++;
+       }
+      if (c - line < 6)
+       allow_continuation = false;
+      for (i = 0; i < 7; ++i)
+       {
+         gfc_char_t c1 = gfc_wide_tolower (*c);
+         if (c1 != (unsigned char) include[i])
+           break;
+         c++;
+         while (*c == ' ' || *c == '\t')
+           c++;
+       }
+      if (!allow_continuation)
+       {
+         if (i != 7)
+           return 0;
+       }
+      else if (i != 7)
+       {
+         if (i == 0)
+           return 0;
+
+         /* At the end of line or comment this might be continued.  */
+         if (*c == '\0' || *c == '!')
+           return -1;
+
+         return 0;
+       }
+    }
 
-  c += 7;
   while (*c == ' ' || *c == '\t')
     c++;
 
   /* Find filename between quotes.  */
-  
+
   quote = *c++;
   if (quote != '"' && quote != '\'')
-    return false;
+    {
+      if (allow_continuation)
+       {
+         if (gfc_current_form == FORM_FREE)
+           {
+             if (quote == '&')
+               {
+                 while (*c == ' ' || *c == '\t')
+                   c++;
+                 if (*c == '\0' || *c == '!')
+                   return -1;
+               }
+           }
+         else if (quote == '\0' || quote == '!')
+           return -1;
+       }
+      return 0;
+    }
 
   begin = c;
 
+  bool cont = false;
   while (*c != quote && *c != '\0')
-    c++;
+    {
+      if (allow_continuation && gfc_current_form == FORM_FREE)
+       {
+         if (*c == '&')
+           cont = true;
+         else if (*c != ' ' && *c != '\t')
+           cont = false;
+       }
+      c++;
+    }
 
   if (*c == '\0')
-    return false;
+    {
+      if (allow_continuation
+         && (cont || gfc_current_form != FORM_FREE))
+       return -1;
+      return 0;
+    }
 
   stop = c++;
-  
+
   while (*c == ' ' || *c == '\t')
     c++;
 
   if (*c != '\0' && *c != '!')
-    return false;
+    return 0;
 
   /* We have an include line at this point.  */
 
@@ -2205,9 +2300,130 @@ include_line (gfc_char_t *line)
     exit (FATAL_EXIT_CODE);
 
   free (filename);
-  return true;
+  return 1;
 }
 
+/* Similarly, but try to parse an INCLUDE statement, using gfc_next_char etc.
+   APIs.  Return 1 if recognized as valid INCLUDE statement and load_file has
+   been called, 0 if it is not a valid INCLUDE statement and -1 if eof has
+   been encountered while parsing it.  */
+static int
+include_stmt (gfc_linebuf *b)
+{
+  int ret = 0, i, length;
+  const char *include = "include";
+  gfc_char_t c, quote = 0;
+  locus str_locus;
+  char *filename;
+
+  continue_flag = 0;
+  end_flag = 0;
+  gcc_attribute_flag = 0;
+  openmp_flag = 0;
+  openacc_flag = 0;
+  continue_count = 0;
+  continue_line = 0;
+  gfc_current_locus.lb = b;
+  gfc_current_locus.nextc = b->line;
+
+  gfc_skip_comments ();
+  gfc_gobble_whitespace ();
+
+  for (i = 0; i < 7; i++)
+    {
+      c = gfc_next_char ();
+      if (c != (unsigned char) include[i])
+       {
+         if (gfc_current_form == FORM_FIXED
+             && i == 0
+             && c == '0'
+             && gfc_current_locus.nextc == b->line + 6)
+           {
+             gfc_gobble_whitespace ();
+             i--;
+             continue;
+           }
+         gcc_assert (i != 0);
+         if (c == '\n')
+           {
+             gfc_advance_line ();
+             gfc_skip_comments ();
+             if (gfc_at_eof ())
+               ret = -1;
+           }
+         goto do_ret;
+       }
+    }
+  gfc_gobble_whitespace ();
+
+  c = gfc_next_char ();
+  if (c == '\'' || c == '"')
+    quote = c;
+  else
+    {
+      if (c == '\n')
+       {
+         gfc_advance_line ();
+         gfc_skip_comments ();
+         if (gfc_at_eof ())
+           ret = -1;
+       }
+      goto do_ret;
+    }
+
+  str_locus = gfc_current_locus;
+  length = 0;
+  do
+    {
+      c = gfc_next_char_literal (INSTRING_NOWARN);
+      if (c == quote)
+       break;
+      if (c == '\n')
+       {
+         gfc_advance_line ();
+         gfc_skip_comments ();
+         if (gfc_at_eof ())
+           ret = -1;
+         goto do_ret;
+       }
+      length++;
+    }
+  while (1);
+
+  gfc_gobble_whitespace ();
+  c = gfc_next_char ();
+  if (c != '\n')
+    goto do_ret;
+
+  gfc_current_locus = str_locus;
+  ret = 1;
+  filename = XNEWVEC (char, length + 1);
+  for (i = 0; i < length; i++)
+    {
+      c = gfc_next_char_literal (INSTRING_WARN);
+      gcc_assert (gfc_wide_fits_in_byte (c));
+      filename[i] = (unsigned char) c;
+    }
+  filename[length] = '\0';
+  if (!load_file (filename, NULL, false))
+    exit (FATAL_EXIT_CODE);
+
+  free (filename);
+
+do_ret:
+  continue_flag = 0;
+  end_flag = 0;
+  gcc_attribute_flag = 0;
+  openmp_flag = 0;
+  openacc_flag = 0;
+  continue_count = 0;
+  continue_line = 0;
+  memset (&gfc_current_locus, '\0', sizeof (locus));
+  memset (&openmp_locus, '\0', sizeof (locus));
+  memset (&openacc_locus, '\0', sizeof (locus));
+  memset (&gcc_attribute_locus, '\0', sizeof (locus));
+  return ret;
+}
 
 /* Load a file into memory by calling load_line until the file ends.  */
 
@@ -2215,7 +2431,7 @@ static bool
 load_file (const char *realfilename, const char *displayedname, bool initial)
 {
   gfc_char_t *line;
-  gfc_linebuf *b;
+  gfc_linebuf *b, *include_b = NULL;
   gfc_file *f;
   FILE *input;
   int len, line_len;
@@ -2318,6 +2534,7 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
   for (;;)
     {
       int trunc = load_line (input, &line, &line_len, NULL);
+      int inc_line;
 
       len = gfc_wide_strlen (line);
       if (feof (input) && len == 0)
@@ -2366,11 +2583,12 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
        }
 
       /* Preprocessed files have preprocessor lines added before the byte
-         order mark, so first_line is not about the first line of the file
+        order mark, so first_line is not about the first line of the file
         but the first line that's not a preprocessor line.  */
       first_line = false;
 
-      if (include_line (line))
+      inc_line = include_line (line);
+      if (inc_line > 0)
        {
          current_file->line++;
          continue;
@@ -2403,6 +2621,36 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
 
       while (file_changes_cur < file_changes_count)
        file_changes[file_changes_cur++].lb = b;
+
+      if (flag_dec_include)
+       {
+         if (include_b && b != include_b)
+           {
+             int inc_line2 = include_stmt (include_b);
+             if (inc_line2 == 0)
+               include_b = NULL;
+             else if (inc_line2 > 0)
+               {
+                 do
+                   {
+                     if (gfc_current_form == FORM_FIXED)
+                       {
+                         for (gfc_char_t *p = include_b->line; *p; p++)
+                           *p = ' ';
+                       }
+                     else
+                       include_b->line[0] = '\0';
+                      if (include_b == b)
+                       break;
+                     include_b = include_b->next;
+                   }
+                 while (1);
+                 include_b = NULL;
+               }
+           }
+         if (inc_line == -1 && !include_b)
+           include_b = b;
+       }
     }
 
   /* Release the line buffer allocated in load_line.  */
index b287dc555e96aed23650a82b7ee7c03c5abf6119..50c7f15b9c91e6b7de636561303f0f5269cf04d0 100644 (file)
@@ -1,3 +1,15 @@
+2018-11-21  Jakub Jelinek  <jakub@redhat.com>
+           Mark Eggleston  <mark.eggleston@codethink.com>
+
+       * gfortran.dg/include_10.f: New test.
+       * gfortran.dg/include_10.inc: New file.
+       * gfortran.dg/include_11.f: New test.
+       * gfortran.dg/include_12.f: New test.
+       * gfortran.dg/include_13.f90: New test.
+       * gfortran.dg/gomp/include_1.f: New test.
+       * gfortran.dg/gomp/include_1.inc: New file.
+       * gfortran.dg/gomp/include_2.f90: New test.
+
 2018-11-21  Andreas Krebbel  <krebbel@linux.ibm.com>
 
        * gcc.target/s390/vector/align-1.c: New test.
diff --git a/gcc/testsuite/gfortran.dg/gomp/include_1.f b/gcc/testsuite/gfortran.dg/gomp/include_1.f
new file mode 100644 (file)
index 0000000..715eb5b
--- /dev/null
@@ -0,0 +1,49 @@
+c { dg-do compile }
+c { dg-options "-fopenmp -fdec" }
+      subroutine foo
+      implicit none
+c$   0include 'include_1.inc'
+      i = 1
+      end subroutine foo
+      subroutine bar
+      implicit none
+      i
+C$   ;n
+     +c
+                 
+c   some comment
+
+*$   ll
+C comment line
+     uu
+     DD
+     ee'include_1.inc'
+      i = 1
+      end subroutine bar
+      subroutine baz
+      implicit none
+     0include
+     + 'include_1.inc'
+      i = 1
+      end subroutine baz
+      subroutine qux
+      implicit none
+!$     i   n   C   lude                                             'inc
+* another comment line
+     &lude_1.inc'
+      i = 1
+      end subroutine qux
+       subroutine quux
+       implicit none
+C$   0inc
+*$   1lud
+c$   2e                                                                '
+!$   3include_1.inc'
+      i = 1
+      end subroutine quux
+      program include_12
+      implicit none
+      include
+! comment
+c$   +'include_1.inc'
+      end program
diff --git a/gcc/testsuite/gfortran.dg/gomp/include_1.inc b/gcc/testsuite/gfortran.dg/gomp/include_1.inc
new file mode 100644 (file)
index 0000000..5dd841c
--- /dev/null
@@ -0,0 +1 @@
+      integer i
diff --git a/gcc/testsuite/gfortran.dg/gomp/include_2.f90 b/gcc/testsuite/gfortran.dg/gomp/include_2.f90
new file mode 100644 (file)
index 0000000..9c4ff15
--- /dev/null
@@ -0,0 +1,32 @@
+! { dg-do compile }
+! { dg-options "-fopenmp -fdec-include" }
+subroutine foo
+  implicit none
+!$  incl& ! comment1
+!$ &u&
+!$       &de           &     ! comment2
+!$ 'include&
+  &_1.inc'
+  i = 1
+end subroutine foo
+subroutine bar
+  implicit none
+!$ include &
+
+! comment3
+
+!$ "include_1.inc"
+  i = 1
+end subroutine bar
+subroutine baz
+  implicit none
+!$                                  include&
+!$ &'include_1.&
+!$ &inc'
+  i = 1
+end subroutine baz
+subroutine qux
+  implicit none
+!$  include '&
+include_1.inc'
+end subroutine qux
diff --git a/gcc/testsuite/gfortran.dg/include_10.f b/gcc/testsuite/gfortran.dg/include_10.f
new file mode 100644 (file)
index 0000000..7df2a19
--- /dev/null
@@ -0,0 +1,11 @@
+c { dg-do compile }
+      subroutine foo
+      implicit none
+      include 'include_10.inc'
+      i = 1
+      end subroutine foo
+      subroutine bar
+      implicit none
+      i n cl UD e'include_10.inc'
+      i = 1
+      end subroutine bar
diff --git a/gcc/testsuite/gfortran.dg/include_10.inc b/gcc/testsuite/gfortran.dg/include_10.inc
new file mode 100644 (file)
index 0000000..5dd841c
--- /dev/null
@@ -0,0 +1 @@
+      integer i
diff --git a/gcc/testsuite/gfortran.dg/include_11.f b/gcc/testsuite/gfortran.dg/include_11.f
new file mode 100644 (file)
index 0000000..0e68a78
--- /dev/null
@@ -0,0 +1,20 @@
+c { dg-do compile }
+      subroutine foo
+      implicit none
+c We used to accept following in fixed mode.  Shall we at least
+c warn about it?
+include 'include_10.inc'
+      i = 1
+      end subroutine foo
+      subroutine bar
+c Likewise here.
+      implicit none
+  include'include_10.inc'
+      i = 1
+      end subroutine bar
+      subroutine baz
+c And here.
+      implicit none
+     include 'include_10.inc'
+      i = 1
+      end subroutine baz
diff --git a/gcc/testsuite/gfortran.dg/include_12.f b/gcc/testsuite/gfortran.dg/include_12.f
new file mode 100644 (file)
index 0000000..4b3e3be
--- /dev/null
@@ -0,0 +1,65 @@
+c { dg-do compile }
+c { dg-options "-fdec-include" }
+      subroutine foo
+      implicit none
+     0include 'include_10.inc'
+      i = 1
+      end subroutine foo
+      subroutine bar
+      implicit none
+      i
+     ;n
+     +c
+                 
+c   some comment
+
+     ll
+C comment line
+     uu
+     DD
+     ee'include_10.inc'
+      i = 1
+      end subroutine bar
+      subroutine baz
+      implicit none
+     0include
+     + 'include_10.inc'
+      i = 1
+      end subroutine baz
+      subroutine qux
+      implicit none
+       i   n   C   lude                                             'inc
+* another comment line
+     &lude_10.inc'
+      i = 1
+      end subroutine qux
+       subroutine quux
+       implicit none
+     0inc
+     1lud
+     2e                                                                '
+     3include_10.inc'
+      i = 1
+      end subroutine quux
+      program include_12
+      implicit none
+      include
+! comment
+     +'include_10.inc'
+      end program
+      subroutine quuz
+      implicit none
+      integer include
+      include
+     +"include_10.inc"
+      i = 1
+      include
+     + = 2
+      write (*,*) include
+      end subroutine quuz
+      subroutine corge
+      implicit none
+      include
+     +'include_10.inc'
+      i = 1
+      end subroutine corge
diff --git a/gcc/testsuite/gfortran.dg/include_13.f90 b/gcc/testsuite/gfortran.dg/include_13.f90
new file mode 100644 (file)
index 0000000..418ee55
--- /dev/null
@@ -0,0 +1,44 @@
+! { dg-do compile }
+! { dg-options "-fdec" }
+subroutine foo
+  implicit none
+  incl& ! comment1
+&u&
+       &de           &     ! comment2
+'include&
+  &_10.inc'
+  i = 1
+end subroutine foo
+subroutine bar
+  implicit none
+include &
+
+! comment3
+
+"include_10.inc"
+  i = 1
+end subroutine bar
+subroutine baz
+  implicit none
+                                  include&
+&'include_10.&
+&inc'
+  i = 1
+end subroutine baz
+subroutine qux
+  implicit none
+  include '&
+include_10.inc'
+end subroutine qux
+subroutine quux
+  implicit none
+  include &
+  &'include_10.inc'
+  i = 1
+end subroutine quux
+subroutine quuz
+  implicit none
+  include &
+  &"include_10.inc"
+  i = 1
+end subroutine quuz