From 59afe4b424016454a2a119a26743d0b75c46e9bc Mon Sep 17 00:00:00 2001
From: Thomas Koenig <Thomas.Koenig@online.de>
Date: Sun, 10 Apr 2005 08:35:39 +0000
Subject: [PATCH] [multiple changes]

2005-04-10  Thomas Koenig <Thomas.Koenig@online.de>

        PR libfortran/17992
        PR libfortran/19568
        PR libfortran/19595
        PR libfortran/20005
        PR libfortran/20092
        PR libfortran/20131
        PR libfortran/20138
        PR libfortran/20661
        PR libfortran/20744
        * io/transfer.c (top level): eor_condition: New static variable.
        (read_sf): Remove unnecessary zeroing of buffer (there is enough
        information in its length).
        Return a string of length 0 (to be padded by caller) if EOR was
        seen previously.
        Remove erroneous special casing of EOR for standard input.
        Set eor_condition for non-advancing I/O if an end of line was
        detected.
        Increment ioparm.size if necessary.
        (formatted_transfer):  Skip the function if there is an EOR condition.
        (data_transfer_init):  Initialize eor_condition to zero (false).
        (next_record_r):  Clear sf_seen_eor if a \n has been seen already.
        (finalize_transfer):  If there is an EOR condition, raise the error.

2005-04-10   Thomas Koenig  <Thomas.Koenig@online.de>

        * eor_handling_1.f90: New test case.
        * eor_handling_2.f90: New test case.
        * eor_handling_3.f90: New test case.
        * eor_handling_4.f90: New test case.
        * eor_handling_5.f90: New test case.
        * noadv_size.f90: New test case.
        * pad_no.f90: New test case.

From-SVN: r97943
---
 gcc/testsuite/ChangeLog                      | 10 +++++
 gcc/testsuite/gfortran.dg/eor_handling_1.f90 | 14 ++++++
 gcc/testsuite/gfortran.dg/eor_handling_2.f90 | 13 ++++++
 gcc/testsuite/gfortran.dg/eor_handling_3.f90 | 13 ++++++
 gcc/testsuite/gfortran.dg/eor_handling_4.f90 | 17 ++++++++
 gcc/testsuite/gfortran.dg/eor_handling_5.f90 | 19 +++++++++
 gcc/testsuite/gfortran.dg/noadv_size.f90     | 11 +++++
 gcc/testsuite/gfortran.dg/pad_no.f90         | 15 +++++++
 libgfortran/ChangeLog                        | 25 +++++++++++
 libgfortran/io/transfer.c                    | 45 ++++++++++++++++----
 10 files changed, 174 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/eor_handling_1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/eor_handling_2.f90
 create mode 100644 gcc/testsuite/gfortran.dg/eor_handling_3.f90
 create mode 100644 gcc/testsuite/gfortran.dg/eor_handling_4.f90
 create mode 100644 gcc/testsuite/gfortran.dg/eor_handling_5.f90
 create mode 100644 gcc/testsuite/gfortran.dg/noadv_size.f90
 create mode 100644 gcc/testsuite/gfortran.dg/pad_no.f90

diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 59255c0a50c2..a55aec878465 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2005-04-10  Thomas Koenig  <Thomas.Koenig@online.de>
+
+	* eor_handling_1.f90: New test case.
+	* eor_handling_2.f90: New test case.
+	* eor_handling_3.f90: New test case.
+	* eor_handling_4.f90: New test case.
+	* eor_handling_5.f90: New test case.
+	* noadv_size.f90: New test case.
+	* pad_no.f90: New test case.
+
 2005-04-10  Richard Sandiford  <rsandifo@redhat.com>
 
 	* gcc.c-torture/execute/20050410-1.c: New test.
diff --git a/gcc/testsuite/gfortran.dg/eor_handling_1.f90 b/gcc/testsuite/gfortran.dg/eor_handling_1.f90
new file mode 100644
index 000000000000..241f8a0fe4e0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eor_handling_1.f90
@@ -0,0 +1,14 @@
+! { dg-do run }
+! PR 17992:  Reading an empty file should yield zero with pad='YES'
+! (which is the default).
+! Test case supplied by milan@cmm.ki.si.
+program main
+  open(77,status='scratch')
+  write(77,'(A)') '',''
+  rewind(77)
+  i = 42
+  j = 42
+  read(77,'(/2i2)') i,j
+  if (i /= 0 .or. j /= 0) call abort
+  close(77)
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eor_handling_2.f90 b/gcc/testsuite/gfortran.dg/eor_handling_2.f90
new file mode 100644
index 000000000000..5eb62f8a894b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eor_handling_2.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! PR 19568:  Don't read across end of line when the format is longer
+!            than the line length and pad='yes' (default)
+program main
+  character(len=1) c1(10),c2(10)
+  open(77,status='scratch')
+  write(77,'(A)') 'Line 1','Line 2','Line 3'
+  rewind(77)
+  read(77,'(10A1)'), c1
+  read(77,'(10A1)'), c2
+  if (c1(1) /= 'L' .or. c2(1) /= 'L') call abort
+  close(77)
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eor_handling_3.f90 b/gcc/testsuite/gfortran.dg/eor_handling_3.f90
new file mode 100644
index 000000000000..4225e867a85f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eor_handling_3.f90
@@ -0,0 +1,13 @@
+! { dg-do run }
+! PR 19595:  Handle end-of-record condition with pad=yes (default)
+program main
+  integer i1, i2
+  open(77,status='scratch')
+  write (77,'(A)') '123','456'
+  rewind(77)
+  read(77,'(2I2)',advance='no',eor=100) i1,i2
+  call abort
+100 continue
+  if (i1 /= 12 .or. i2 /= 3) call abort
+  close(77)
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eor_handling_4.f90 b/gcc/testsuite/gfortran.dg/eor_handling_4.f90
new file mode 100644
index 000000000000..300c10b820aa
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eor_handling_4.f90
@@ -0,0 +1,17 @@
+! { dg-do run }
+! PR 20092, 20131:  Handle end-of-record condition with pad=yes (default)
+! for standard input.  This test case only really tests  anything if,
+! by changing unit 5, you get to manipulate the standard input.
+program main
+  character(len=1) a(80)
+  close(5)
+  open(5,status="scratch")
+  write(5,'(A)') 'one', 'two', 's'
+  rewind(5)
+  do i=1,4
+     read(5,'(80a1)') a
+     if (a(1) == 's') goto 100
+  end do
+  call abort
+100 continue
+end program main
diff --git a/gcc/testsuite/gfortran.dg/eor_handling_5.f90 b/gcc/testsuite/gfortran.dg/eor_handling_5.f90
new file mode 100644
index 000000000000..c116fb7bdeaf
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/eor_handling_5.f90
@@ -0,0 +1,19 @@
+! { dg-do run }
+! PR 20661: Handle non-advancing I/O with iostat
+! Test case by Walt Brainerd, The Fortran Company
+
+program fc002
+   character(len=1) :: c
+   integer :: k,k2
+   character(len=*), parameter :: f="(a)"
+   open(11,status="scratch", iostat=k)
+   if (k /= 0) call abort
+   write(11,f) "x"
+   rewind (11)
+   read(11, f, advance="no", iostat=k) c
+   if (k /= 0) call abort
+   read(11, f, advance="no", iostat=k) c
+   if (k >= 0) call abort
+   read(11, f, advance="no", iostat=k2) c
+   if (k2 >= 0 .or. k == k2) call abort
+end program fc002
diff --git a/gcc/testsuite/gfortran.dg/noadv_size.f90 b/gcc/testsuite/gfortran.dg/noadv_size.f90
new file mode 100644
index 000000000000..a3a88b18ca72
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/noadv_size.f90
@@ -0,0 +1,11 @@
+! { dg-do run }
+! PR 20774: Handle size parameter for non-advancing I/O correctly
+program main
+  open(77,status='scratch')
+  write(77,'(A)') '123'
+  rewind(77)
+  read(77,'(2I2)',advance='no',iostat=k,size=n) i1,i2
+  if (k >=0) call abort
+  if (n /= 3) call abort
+  if (i1 /= 12 .or. i2 /= 3) call abort
+end program main
diff --git a/gcc/testsuite/gfortran.dg/pad_no.f90 b/gcc/testsuite/gfortran.dg/pad_no.f90
new file mode 100644
index 000000000000..c023adec815e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pad_no.f90
@@ -0,0 +1,15 @@
+! { dg-do run }
+! Test correct operation for pad='no'.
+program main
+  character(len=1) line(2)
+  line = 'x'
+  open(77,status='scratch',pad='no')
+  write(77,'(A)') 'a','b'
+  rewind(77)
+  read(77,'(2A)',iostat=i) line(1)
+  if (line(1) /= 'a' .or. line(2) /= 'x') call abort
+  rewind(77)
+  line = 'y'
+  read(77,'(2A)',iostat=i,advance='no') line
+  if (line(1) /= 'a' .or. line(2) /= 'y') call abort
+end program main
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 46fc3b3dedf8..fcb4ff3ae883 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,28 @@
+2005-04-10  Thomas Koenig <Thomas.Koenig@online.de>
+
+	PR libfortran/17992
+	PR libfortran/19568
+	PR libfortran/19595
+	PR libfortran/20005
+	PR libfortran/20092
+	PR libfortran/20131
+	PR libfortran/20138
+	PR libfortran/20661
+	PR libfortran/20744
+	* io/transfer.c (top level): eor_condition: New static variable.
+	(read_sf): Remove unnecessary zeroing of buffer (there is enough
+	information in its length).
+	Return a string of length 0 (to be padded by caller) if EOR was
+	seen previously.
+	Remove erroneous special casing of EOR for standard input.
+	Set eor_condition for non-advancing I/O if an end of line was
+	detected.
+	Increment ioparm.size if necessary.
+	(formatted_transfer):  Skip the function if there is an EOR condition.
+	(data_transfer_init):  Initialize eor_condition to zero (false).
+	(next_record_r):  Clear sf_seen_eor if a \n has been seen already.
+	(finalize_transfer):  If there is an EOR condition, raise the error.
+
 2005-04-09  Bud Davis  <bdavis@gfortran.org>
             Steven G. Kargl <kargls@comcast.net>
 
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index f86a85272458..77e943964d8a 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -79,6 +79,7 @@ export_proto(transfer_complex);
 
 gfc_unit *current_unit = NULL;
 static int sf_seen_eor = 0;
+static int eor_condition = 0;
 
 char scratch[SCRATCH_SIZE] = { };
 static char *line_buffer = NULL;
@@ -150,7 +151,13 @@ read_sf (int *length)
   else
     p = base = data;
 
-  memset(base,'\0',*length);
+  /* If we have seen an eor previously, return a length of 0.  The
+     caller is responsible for correctly padding the input field.  */
+  if (sf_seen_eor)
+    {
+      *length = 0;
+      return base;
+    }
 
   current_unit->bytes_left = options.default_recl;
   readlen = 1;
@@ -179,13 +186,16 @@ read_sf (int *length)
 
       if (readlen < 1 || *q == '\n' || *q == '\r')
 	{
-	  /* ??? What is this for?  */
-          if (current_unit->unit_number == options.stdin_unit)
-            {
-              if (n <= 0)
-                continue;
-            }
 	  /* Unexpected end of line.  */
+
+	  /* If we see an EOR during non-advancing I/O, we need to skip
+	     the rest of the I/O statement.  Set the corresponding flag.  */
+	  if (advance_status == ADVANCE_NO)
+	    eor_condition = 1;
+
+	  /* Without padding, terminate the I/O statement without assigning
+	     the value.  With padding, the value still needs to be assigned,
+	     so we can just continue with a short read.  */
 	  if (current_unit->flags.pad == PAD_NO)
 	    {
 	      generate_error (ERROR_EOR, NULL);
@@ -204,6 +214,9 @@ read_sf (int *length)
     }
   while (n < *length);
 
+  if (ioparm.size != NULL)
+    *ioparm.size += *length;
+
   return base;
 }
 
@@ -434,6 +447,11 @@ formatted_transfer (bt type, void *p, int len)
   if (type == BT_COMPLEX)
     type = BT_REAL;
 
+  /* If there's an EOR condition, we simulate finalizing the transfer
+     by doing nothing.  */
+  if (eor_condition)
+    return;
+
   for (;;)
     {
       /* If reversion has occurred and there is another real data item,
@@ -1121,6 +1139,7 @@ data_transfer_init (int read_flag)
   g.first_item = 1;
   g.item_count = 0;
   sf_seen_eor = 0;
+  eor_condition = 0;
 
   pre_position ();
 
@@ -1236,7 +1255,10 @@ next_record_r (int done)
       length = 1;
       /* sf_read has already terminated input because of an '\n'  */
       if (sf_seen_eor) 
-         break;
+	{
+	  sf_seen_eor=0;
+	  break;
+	}
 
       do
         {
@@ -1402,6 +1424,13 @@ next_record (int done)
 static void
 finalize_transfer (void)
 {
+
+  if (eor_condition)
+    {
+      generate_error (ERROR_EOR, NULL);
+      return;
+    }
+
   if (ioparm.library_return != LIBRARY_OK)
     return;
 
-- 
GitLab