This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran 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]

Re: [Patch, libgfortran, 4.5] PR25561, 37754: New low level I/O library


Dominique Dhumieres wrote:
> Now the bad news: I see two regressions on my own tests:

I have now fixed these two issues; the attached patch is to be applied
on top of my original patch.

> (1) the following test aborts:
> 
> character(len=20) :: b
> ! write something no advance
> open(10,FILE="fort.10",POSITION="REWIND")
> write(10, '(a,t1,a)',advance='no') 'XXXXXX', 'ABC'
> close(10)
> ! append some data
> open(10,FILE="fort.10",POSITION="APPEND")
> write(10, '(a)') 'DEF'
> close(10)
> ! check what is in the first record
> open(10,FILE="fort.10",POSITION="REWIND")
> read(10,'(a)') b
> IF (b.NE."ABCXXX") CALL ABORT()
> END

This was due to incorrectly resetting the format buffer when truncating
the file in write mode. This lost the bytes left in the record due to
advance='no'.

This bug also happened only on the second run of the test, since only in
that case was the endfile flag set to NO_ENDFILE, and the truncation
occurred (in transfer.c:st_write_done).

> (2) countlines.f does not work correctly on file containing the ascii 
> character 255,

fbuf_getc() must cast the return value to unsigned char, otherwise the
caller thinks it hit EOF, and hence countlines.f showed an extra line.

Once again, thanks Dominique for testing the patch and reporting the issues!


-- 
Janne Blomqvist
diff --git a/libgfortran/io/fbuf.c b/libgfortran/io/fbuf.c
index bcf66d0..a496365 100644
--- a/libgfortran/io/fbuf.c
+++ b/libgfortran/io/fbuf.c
@@ -267,7 +267,7 @@ fbuf_getc_refill (gfc_unit * u)
   p = fbuf_read (u, &nread);
 
   if (p && nread > 0)
-    return u->fbuf->buf[u->fbuf->pos++];
+    return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
   else
     return EOF;
 }
diff --git a/libgfortran/io/file_pos.c b/libgfortran/io/file_pos.c
index c621628..ecee101 100644
--- a/libgfortran/io/file_pos.c
+++ b/libgfortran/io/file_pos.c
@@ -351,8 +351,12 @@ st_rewind (st_parameter_filepos *fpp)
 	       file now.  Reset to read mode so two consecutive rewind
 	       statements do not delete the file contents.  */
 	  if (u->mode == WRITING)
-            /* unit_truncate takes care of flushing.  */
-	    unit_truncate (u, stell (u->s), &fpp->common);
+	    {
+	      /* unit_truncate takes care of flushing.  */
+	      unit_truncate (u, stell (u->s), &fpp->common);
+	      /* .. but we still need to reset since we're going to seek.  */
+	      fbuf_reset (u);
+	    }
           else
             {
               /* Make sure buffers are reset.  */
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index ed56a9e..f173165 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -1018,7 +1018,7 @@ static inline int
 fbuf_getc (gfc_unit * u)
 {
   if (u->fbuf->pos < u->fbuf->act)
-    return u->fbuf->buf[u->fbuf->pos++];
+    return (unsigned char) u->fbuf->buf[u->fbuf->pos++];
   return fbuf_getc_refill (u);
 }
 
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index bb2e125..f305406 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -720,7 +720,12 @@ unit_truncate (gfc_unit * u, gfc_offset pos, st_parameter_common * common)
 
   /* Make sure format buffer is flushed.  */
   if (u->flags.form == FORM_FORMATTED)
-    pos += fbuf_reset (u);
+    {
+      if (u->mode == READING)
+	pos += fbuf_reset (u);
+      else
+	fbuf_flush (u, u->mode);
+    }
   
   /* Don't try to truncate a special file, just pretend that it
      succeeds.  */

Attachment: signature.asc
Description: OpenPGP digital signature


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