This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch, libfortran][Regression] PR43265 No EOF condition if reading with '(x)' from an empty file


Hi,

The attached patch fixes this PR by extracting the code in read_sf used by
read_x and putting it into read_x. This re-factoring includes getting rid of the no_error parameter from read_sf and trimming down the code to a minimum needed by read_x. Handling of EOF and EOR conditions within read_x are now tailored for read_x. This adds a check of the item count so that trailing X format specifiers will not produce an EOF, but leading X format specifiers will.


The two test cases given test these conditions.

I also deleted an incorrect use of hit_eof found in read_sf. This eliminated a
wrong code found when the format is modified from (1x,a3,1x,a3,1x,a3,1x,a3,10x)
to (1x,a3,1x,a3,1x,a3,1x,a3) in read_x_past.f, updated to test this.

Regression tested and NIST tested on x86-64. OK for trunk.

Regards,

Jerry

2010-03-07 Jerry DeLisle <jvdelisle@gcc.gnu.org>

    PR libfortran/43265
    * io/read.c: Include fbuf.h and unix.h to enable lower level I/O for
    read_x. (read_x): Replace the use of read_sf with equivalent lower level
    I/O, eliminating unneeded code and handling EOF and EOR conditions.
    * io/io.h: Revise prototype for read_sf.
    * io/transfer.c (read_sf): Delete no_error parameter and all uses of it.
    (read_block_form): Likewise.
    (next_record_r): Delete wrong code call to hit_eof.
Index: read.c
===================================================================
--- read.c	(revision 157269)
+++ read.c	(working copy)
@@ -24,7 +24,9 @@ see the files COPYING3 and COPYING.RUNTIME respect
 <http://www.gnu.org/licenses/>.  */
 
 #include "io.h"
+#include "fbuf.h"
 #include "format.h"
+#include "unix.h"
 #include <string.h>
 #include <errno.h>
 #include <ctype.h>
@@ -1022,16 +1024,70 @@ bad_float:
  * and never look at it. */
 
 void
-read_x (st_parameter_dt * dtp, int n)
+read_x (st_parameter_dt *dtp, int n)
 {
+  int length;
+  char *p, q;
+
   if ((dtp->u.p.current_unit->pad_status == PAD_NO || is_internal_unit (dtp))
        && dtp->u.p.current_unit->bytes_left < n)
     n = dtp->u.p.current_unit->bytes_left;
+    
+  if (n == 0)
+    return;
 
-  dtp->u.p.sf_read_comma = 0;
-  if (n > 0)
-    read_sf (dtp, &n, 1);
-  dtp->u.p.sf_read_comma = 1;
+  length = n;
+
+  if (is_internal_unit (dtp))
+    {
+      p = mem_alloc_r (dtp->u.p.current_unit->s, &length);
+      if (unlikely (length < n))
+	n = length;
+      goto done;
+    }
+
+  p = fbuf_read (dtp->u.p.current_unit, &length);
+  if (p == NULL || (length == 0 && dtp->u.p.item_count == 1))
+    {
+      hit_eof (dtp);
+      return;
+    }
+
+  n = 0;
+  while (n < length)
+    {
+      q = *p;
+      if (q == '\n' || q == '\r')
+	{
+	  /* Unexpected end of line. Set the position.  */
+	  fbuf_seek (dtp->u.p.current_unit, n + 1 ,SEEK_CUR);
+	  dtp->u.p.sf_seen_eor = 1;
+
+	  /* If we encounter a CR, it might be a CRLF.  */
+	  if (q == '\r') /* Probably a CRLF */
+	    {
+	      /* See if there is an LF. Use fbuf_read rather then fbuf_getc so
+		 the position is not advanced unless it really is an LF.  */
+	      int readlen = 1;
+	      p = fbuf_read (dtp->u.p.current_unit, &readlen);
+	      if (*p == '\n' && readlen == 1)
+	        {
+		  dtp->u.p.sf_seen_eor = 2;
+		  fbuf_seek (dtp->u.p.current_unit, 1 ,SEEK_CUR);
+		}
+	    }
+	  goto done;
+	}
+      n++;
+      p++;
+    } 
+
+  fbuf_seek (dtp->u.p.current_unit, n, SEEK_CUR);
+  
+ done:
+  if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
+    dtp->u.p.size_used += (GFC_IO_INT) n;
+  dtp->u.p.current_unit->bytes_left -= n;
   dtp->u.p.current_unit->strm_pos += (gfc_offset) n;
 }
 
Index: io.h
===================================================================
--- io.h	(revision 157269)
+++ io.h	(working copy)
@@ -642,7 +642,7 @@ internal_proto(type_name);
 extern void * read_block_form (st_parameter_dt *, int *);
 internal_proto(read_block_form);
 
-extern char *read_sf (st_parameter_dt *, int *, int);
+extern char *read_sf (st_parameter_dt *, int *);
 internal_proto(read_sf);
 
 extern void *write_block (st_parameter_dt *, int);
Index: transfer.c
===================================================================
--- transfer.c	(revision 157269)
+++ transfer.c	(working copy)
@@ -192,22 +192,12 @@ current_mode (st_parameter_dt *dtp)
    heap.  Hopefully this won't happen very often.  */
 
 char *
-read_sf (st_parameter_dt *dtp, int * length, int no_error)
+read_sf (st_parameter_dt *dtp, int * length)
 {
   static char *empty_string[0];
   char *base, *p, q;
   int n, lorig, memread, seen_comma;
 
-  /* If we hit EOF previously with the no_error flag set (i.e. X, T,
-     TR edit descriptors), and we now try to read again, this time
-     without setting no_error.  */
-  if (!no_error && dtp->u.p.at_eof)
-    {
-      *length = 0;
-      hit_eof (dtp);
-      return NULL;
-    }
-
   /* If we have seen an eor previously, return a length of 0.  The
      caller is responsible for correctly padding the input field.  */
   if (dtp->u.p.sf_seen_eor)
@@ -273,8 +263,6 @@ char *
 	     so we can just continue with a short read.  */
 	  if (dtp->u.p.current_unit->pad_status == PAD_NO)
 	    {
-	      if (likely (no_error))
-		break;
 	      generate_error (&dtp->common, LIBERROR_EOR, NULL);
 	      return NULL;
 	    }
@@ -304,7 +292,7 @@ char *
      some other stuff. Set the relevant flags.  */
   if (lorig > *length && !dtp->u.p.sf_seen_eor && !seen_comma)
     {
-      if (n > 0 || no_error)
+      if (n > 0)
         {
 	  if (dtp->u.p.advance_status == ADVANCE_NO)
 	    {
@@ -386,7 +374,7 @@ read_block_form (st_parameter_dt *dtp, int * nbyte
       (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
        dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
     {
-      source = read_sf (dtp, nbytes, 0);
+      source = read_sf (dtp, nbytes);
       dtp->u.p.current_unit->strm_pos +=
 	(gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor);
       return source;
@@ -2822,8 +2810,6 @@ next_record_r (st_parameter_dt *dtp)
 		{
                   if (errno != 0)
                     generate_error (&dtp->common, LIBERROR_OS, NULL);
-                  else
-                    hit_eof (dtp);
 		  break;
                 }
 	      

Attachment: read_x_eof.f90
Description: Text document

Attachment: read_x_past.f
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]