PR 44292 Handle large record lengths
authorJanne Blomqvist <jb@gcc.gnu.org>
Sat, 18 Nov 2017 22:05:13 +0000 (00:05 +0200)
committerJanne Blomqvist <jb@gcc.gnu.org>
Sat, 18 Nov 2017 22:05:13 +0000 (00:05 +0200)
Now that the ABI supports large record lengths, there's a few places
in libgfortran where we need to use larger types. For internal units
which by definition are in-memory, it's enought to use ptrdiff_t, for
external units gfc_offset.

Regtested on x86_64-pc-linux-gnu?

libgfortran/ChangeLog:

2017-11-19  Janne Blomqvist  <jb@gcc.gnu.org>

        PR fortran/44292
* io/transfer.c (skip_record): Use gfc_offset to handle large
records.
(next_record_r): Likewise.
(sset): Likewise.
(next_record_w): Use gfc_offset/ptrdiff_t appropriately.

From-SVN: r254918

libgfortran/ChangeLog
libgfortran/io/transfer.c

index 3af699d..2408451 100644 (file)
@@ -1,3 +1,12 @@
+2017-11-19  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       PR fortran/44292
+       * io/transfer.c (skip_record): Use gfc_offset to handle large
+       records.
+       (next_record_r): Likewise.
+       (sset): Likewise.
+       (next_record_w): Use gfc_offset/ptrdiff_t appropriately.
+
 2017-11-18  Janne Blomqvist  <jb@gcc.gnu.org>
 
        PR fortran/83036
index 5296370..c173447 100644 (file)
@@ -3290,7 +3290,7 @@ next_array_record (st_parameter_dt *dtp, array_loop_spec *ls, int *finished)
    position.  */
 
 static void
-skip_record (st_parameter_dt *dtp, ssize_t bytes)
+skip_record (st_parameter_dt *dtp, gfc_offset bytes)
 {
   ssize_t rlength, readb;
 #define MAX_READ 4096
@@ -3367,7 +3367,6 @@ static void
 next_record_r (st_parameter_dt *dtp, int done)
 {
   gfc_offset record;
-  int bytes_left;
   char p;
   int cc;
 
@@ -3419,7 +3418,7 @@ next_record_r (st_parameter_dt *dtp, int done)
            }
          else
            {
-             bytes_left = (int) dtp->u.p.current_unit->bytes_left;
+             gfc_offset bytes_left = dtp->u.p.current_unit->bytes_left;
              bytes_left = min_off (bytes_left,
                      ssize (dtp->u.p.current_unit->s)
                      - stell (dtp->u.p.current_unit->s));
@@ -3590,12 +3589,13 @@ next_record_w_unf (st_parameter_dt *dtp, int next_subrecord)
 /* Utility function like memset() but operating on streams. Return
    value is same as for POSIX write().  */
 
-static ssize_t
-sset (stream *s, int c, ssize_t nbyte)
+static gfc_offset
+sset (stream *s, int c, gfc_offset nbyte)
 {
 #define WRITE_CHUNK 256
   char p[WRITE_CHUNK];
-  ssize_t bytes_left, trans;
+  gfc_offset bytes_left;
+  ssize_t trans;
 
   if (nbyte < WRITE_CHUNK)
     memset (p, c, nbyte);
@@ -3645,11 +3645,10 @@ next_record_cc (st_parameter_dt *dtp)
 static void
 next_record_w (st_parameter_dt *dtp, int done)
 {
-  gfc_offset m, record, max_pos;
-  int length;
+  gfc_offset max_pos_off;
 
   /* Zero counters for X- and T-editing.  */
-  max_pos = dtp->u.p.max_pos;
+  max_pos_off = dtp->u.p.max_pos;
   dtp->u.p.max_pos = dtp->u.p.skips = dtp->u.p.pending_spaces = 0;
 
   switch (current_mode (dtp))
@@ -3674,7 +3673,7 @@ next_record_w (st_parameter_dt *dtp, int done)
     case UNFORMATTED_DIRECT:
       if (dtp->u.p.current_unit->bytes_left > 0)
        {
-         length = (int) dtp->u.p.current_unit->bytes_left;
+         gfc_offset length = dtp->u.p.current_unit->bytes_left;
          if (sset (dtp->u.p.current_unit->s, 0, length) != length)
            goto io_error;
        }
@@ -3691,11 +3690,14 @@ next_record_w (st_parameter_dt *dtp, int done)
       if (is_internal_unit (dtp))
        {
          char *p;
+         /* Internal unit, so must fit in memory.  */
+         ptrdiff_t length, m, record;
+         ptrdiff_t max_pos = max_pos_off;
          if (is_array_io (dtp))
            {
              int finished;
 
-             length = (int) dtp->u.p.current_unit->bytes_left;
+             length = dtp->u.p.current_unit->bytes_left;
 
              /* If the farthest position reached is greater than current
              position, adjust the position and set length to pad out
@@ -3705,14 +3707,14 @@ next_record_w (st_parameter_dt *dtp, int done)
                        - dtp->u.p.current_unit->bytes_left;
              if (max_pos > m)
                {
-                 length = (int) (max_pos - m);
+                 length = (max_pos - m);
                  if (sseek (dtp->u.p.current_unit->s,
                             length, SEEK_CUR) < 0)
                    {
                      generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
                      return;
                    }
-                 length = (int) (dtp->u.p.current_unit->recl - max_pos);
+                 length = ((ptrdiff_t) dtp->u.p.current_unit->recl - max_pos);
                }
 
              p = write_block (dtp, length);
@@ -3735,7 +3737,7 @@ next_record_w (st_parameter_dt *dtp, int done)
                dtp->u.p.current_unit->endfile = AT_ENDFILE;
 
              /* Now seek to this record */
-             record = record * dtp->u.p.current_unit->recl;
+             record = record * ((ptrdiff_t) dtp->u.p.current_unit->recl);
 
              if (sseek (dtp->u.p.current_unit->s, record, SEEK_SET) < 0)
                {
@@ -3758,17 +3760,18 @@ next_record_w (st_parameter_dt *dtp, int done)
                        - dtp->u.p.current_unit->bytes_left;
                  if (max_pos > m)
                    {
-                     length = (int) (max_pos - m);
+                     length = max_pos - m;
                      if (sseek (dtp->u.p.current_unit->s,
                                 length, SEEK_CUR) < 0)
                        {
                          generate_error (&dtp->common, LIBERROR_INTERNAL_UNIT, NULL);
                          return;
                        }
-                     length = (int) (dtp->u.p.current_unit->recl - max_pos);
+                     length = (ptrdiff_t) dtp->u.p.current_unit->recl
+                       - max_pos;
                    }
                  else
-                   length = (int) dtp->u.p.current_unit->bytes_left;
+                   length = dtp->u.p.current_unit->bytes_left;
                }
              if (length > 0)
                {