aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io/transfer.c
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2017-11-19 00:05:13 +0200
committerJanne Blomqvist <jb@gcc.gnu.org>2017-11-19 00:05:13 +0200
commit2563a16d3c7a56cd1e0cfe9b4ccb702edfb12312 (patch)
tree8e0e2ff952f1a8b84f943e814b65b68dfd0bbb94 /libgfortran/io/transfer.c
parenta7a389d6eee846a877b79c733d853cd2e6b162da (diff)
downloadgcc-2563a16d3c7a56cd1e0cfe9b4ccb702edfb12312.zip
gcc-2563a16d3c7a56cd1e0cfe9b4ccb702edfb12312.tar.gz
gcc-2563a16d3c7a56cd1e0cfe9b4ccb702edfb12312.tar.bz2
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 <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
Diffstat (limited to 'libgfortran/io/transfer.c')
-rw-r--r--libgfortran/io/transfer.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index 5296370..c173447 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)
{