From 42f670fb492be9b97b00a69b5ec42ab41b5e4d79 Mon Sep 17 00:00:00 2001 From: jb Date: Sat, 18 Nov 2017 22:05:13 +0000 Subject: [PATCH] PR 44292 Handle large record lengths 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 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@254918 138bc75d-0d04-0410-961f-82ee72b054a4 --- libgfortran/ChangeLog | 9 +++++++++ libgfortran/io/transfer.c | 37 ++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 3af699d1640..24084517a62 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,12 @@ +2017-11-19 Janne Blomqvist + + 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 PR fortran/83036 diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index 529637061b1..c17344742b1 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -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) { -- 2.11.4.GIT