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] Fix Fortran FMT_T handling


Hi!

The following testcase (origin from
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=166480
testcase) fails to read the numbers correctly.  The problem is that on the
second line when skipping characters formatted_transfer overwrites
FMT_T's f->u.n (i.e. position to which chars should be skipped) with
skips (the number of chars that it wants to be skipped yb read_x routine).
But this means that from that point on the original f->u.n value is lost
and on the next (3rd) line it will work as t6 rather than the requested t7.

As read_x is an internal function, I think it should be ok to change it's
argument.  If not, alternatively f->u.n could be saved into a local
variable, overwritten and after read_x returns restored.

Ok for HEAD/4.0?

2005-09-02  Jakub Jelinek  <jakub@redhat.com>

	* io/read.c (read_x): Take int argument instead of fnode * and
	digging the N from F->u.n.
	* io/io.h (read_x): Adjust prototype.
	* io/transfer.c (formatted_transfer): Adjust callers.  Don't clobber
	f->u.n for FMT_T.

	* gfortran.dg/fmt_t_1.f90: New test.

--- libgfortran/io/io.h.jj	2005-08-29 10:25:04.000000000 +0200
+++ libgfortran/io/io.h	2005-09-02 19:20:31.000000000 +0200
@@ -589,7 +589,7 @@ internal_proto(read_f);
 extern void read_l (fnode *, char *, int);
 internal_proto(read_l);
 
-extern void read_x (fnode *);
+extern void read_x (int);
 internal_proto(read_x);
 
 extern void read_radix (fnode *, char *, int, int);
--- libgfortran/io/transfer.c.jj	2005-08-27 10:13:09.000000000 +0200
+++ libgfortran/io/transfer.c	2005-09-02 19:20:47.000000000 +0200
@@ -705,7 +705,7 @@ formatted_transfer (bt type, void *p, in
 	  /* Writes occur just before the switch on f->format, above, so that
 	     trailing blanks are suppressed.  */
 	  if (g.mode == READING)
-	    read_x (f);
+	    read_x (f->u.n);
 
 	  break;
 
@@ -736,10 +736,7 @@ formatted_transfer (bt type, void *p, in
 	  if (g.mode == READING)
 	    {
 	      if (skips > 0)
-		{
-		  f->u.n = skips;
-		  read_x (f);
-		}
+		read_x (skips);
 	      if (skips < 0)
 		{
 		  move_pos_offset (current_unit->s, skips);
--- libgfortran/io/read.c.jj	2005-09-02 09:01:45.000000000 +0200
+++ libgfortran/io/read.c	2005-09-02 19:20:44.000000000 +0200
@@ -831,12 +831,8 @@ read_f (fnode * f, char *dest, int lengt
  * and never look at it. */
 
 void
-read_x (fnode * f)
+read_x (int n)
 {
-  int n;
-
-  n = f->u.n;
-
   if ((current_unit->flags.pad == PAD_NO || is_internal_unit ())
       && current_unit->bytes_left < n)
     n = current_unit->bytes_left;
--- gcc/testsuite/gfortran.dg/fmt_t_1.f90.jj	2005-09-02 19:20:04.000000000 +0200
+++ gcc/testsuite/gfortran.dg/fmt_t_1.f90	2005-09-02 19:34:42.000000000 +0200
@@ -0,0 +1,14 @@
+! { dg-do run }
+      integer nin, nrow, vec(15)
+      nin = 1
+      open (unit = nin)
+      write (nin, fmt='(a)') '001    1 2 3 4 5 6'
+      write (nin, fmt='(a)') '000000 7 8 9101112'
+      write (nin, fmt='(a)') '000000131415'
+      close (nin)
+      open (unit = nin)
+      read (nin, fmt='(i6, (t7, 6i2))') nrow, (vec(i), i=1,15)
+      close (nin)
+      if (nrow.ne.1) call abort
+      if (any (vec.ne.(/1,2,3,4,5,6,7,8,9,10,11,12,13,14,15/))) call abort
+      end

	Jakub


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