aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran/io')
-rw-r--r--libgfortran/io/inquire.c4
-rw-r--r--libgfortran/io/io.h5
-rw-r--r--libgfortran/io/open.c6
-rw-r--r--libgfortran/io/transfer.c4
-rw-r--r--libgfortran/io/unit.c33
5 files changed, 36 insertions, 16 deletions
diff --git a/libgfortran/io/inquire.c b/libgfortran/io/inquire.c
index fe353c55314..848a08f6157 100644
--- a/libgfortran/io/inquire.c
+++ b/libgfortran/io/inquire.c
@@ -218,7 +218,9 @@ inquire_via_unit (st_parameter_inquire *iqp, gfc_unit *u)
}
if ((cf & IOPARM_INQUIRE_HAS_RECL_OUT) != 0)
- *iqp->recl_out = (u != NULL) ? u->recl : 0;
+ /* F2018 (N2137) 12.10.2.26: If there is no connection, recl is
+ assigned the value -1. */
+ *iqp->recl_out = (u != NULL) ? u->recl : -1;
if ((cf & IOPARM_INQUIRE_HAS_STRM_POS_OUT) != 0)
*iqp->strm_pos_out = (u != NULL) ? u->strm_pos : 0;
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 50db35e1cff..fd48bf19e9b 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -735,6 +735,11 @@ gfc_saved_unit;
extern gfc_offset max_offset;
internal_proto(max_offset);
+/* Default RECL for sequential access if not given in OPEN statement,
+ computed at library initialization time. */
+extern gfc_offset default_recl;
+internal_proto(default_recl);
+
/* Unit tree root. */
extern gfc_unit *unit_root;
internal_proto(unit_root);
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index fab20653c77..05e1773c841 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -586,7 +586,7 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
else
{
u->flags.has_recl = 0;
- u->recl = max_offset;
+ u->recl = default_recl;
if (compile_options.max_subrecord_length)
{
u->recl_subrecord = compile_options.max_subrecord_length;
@@ -622,7 +622,9 @@ new_unit (st_parameter_open *opp, gfc_unit *u, unit_flags *flags)
if (flags->access == ACCESS_STREAM)
{
u->maxrec = max_offset;
- u->recl = 1;
+ /* F2018 (N2137) 12.10.2.26: If the connection is for stream
+ access recl is assigned the value -2. */
+ u->recl = -2;
u->bytes_left = 1;
u->strm_pos = stell (u->s) + 1;
}
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index acaa88a01f9..1ac4c5164e9 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -451,7 +451,7 @@ read_block_form (st_parameter_dt *dtp, int *nbytes)
/* For preconnected units with default record length, set bytes left
to unit record length and proceed, otherwise error. */
if (dtp->u.p.current_unit->unit_number == options.stdin_unit
- && dtp->u.p.current_unit->recl == DEFAULT_RECL)
+ && dtp->u.p.current_unit->recl == default_recl)
dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
else
{
@@ -757,7 +757,7 @@ write_block (st_parameter_dt *dtp, int length)
== options.stdout_unit
|| dtp->u.p.current_unit->unit_number
== options.stderr_unit)
- && dtp->u.p.current_unit->recl == DEFAULT_RECL))
+ && dtp->u.p.current_unit->recl == default_recl))
dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
else
{
diff --git a/libgfortran/io/unit.c b/libgfortran/io/unit.c
index e62f9b839d4..fbb33046dee 100644
--- a/libgfortran/io/unit.c
+++ b/libgfortran/io/unit.c
@@ -95,7 +95,10 @@ static int newunit_lwi;
#define CACHE_SIZE 3
static gfc_unit *unit_cache[CACHE_SIZE];
+
gfc_offset max_offset;
+gfc_offset default_recl;
+
gfc_unit *unit_root;
#ifdef __GTHREAD_MUTEX_INIT
__gthread_mutex_t unit_lock = __GTHREAD_MUTEX_INIT;
@@ -575,7 +578,6 @@ void
init_units (void)
{
gfc_unit *u;
- unsigned int i;
#ifdef HAVE_NEWLOCALE
c_locale = newlocale (0, "C", 0);
@@ -589,6 +591,22 @@ init_units (void)
__GTHREAD_MUTEX_INIT_FUNCTION (&unit_lock);
#endif
+ if (sizeof (max_offset) == 8)
+ {
+ max_offset = GFC_INTEGER_8_HUGE;
+ /* Why this weird value? Because if the recl specifier in the
+ inquire statement is a 4 byte value, u->recl is truncated,
+ and this trick ensures it becomes HUGE(0) rather than -1.
+ The full 8 byte value of default_recl is still 0.99999999 *
+ max_offset which is large enough for all practical
+ purposes. */
+ default_recl = max_offset & ~(1LL<<31);
+ }
+ else if (sizeof (max_offset) == 4)
+ max_offset = default_recl = GFC_INTEGER_4_HUGE;
+ else
+ internal_error (NULL, "sizeof (max_offset) must be 4 or 8");
+
if (options.stdin_unit >= 0)
{ /* STDIN */
u = insert_unit (options.stdin_unit);
@@ -611,7 +629,7 @@ init_units (void)
u->flags.share = SHARE_UNSPECIFIED;
u->flags.cc = CC_LIST;
- u->recl = options.default_recl;
+ u->recl = default_recl;
u->endfile = NO_ENDFILE;
u->filename = strdup (stdin_name);
@@ -642,7 +660,7 @@ init_units (void)
u->flags.share = SHARE_UNSPECIFIED;
u->flags.cc = CC_LIST;
- u->recl = options.default_recl;
+ u->recl = default_recl;
u->endfile = AT_ENDFILE;
u->filename = strdup (stdout_name);
@@ -672,7 +690,7 @@ init_units (void)
u->flags.share = SHARE_UNSPECIFIED;
u->flags.cc = CC_LIST;
- u->recl = options.default_recl;
+ u->recl = default_recl;
u->endfile = AT_ENDFILE;
u->filename = strdup (stderr_name);
@@ -682,13 +700,6 @@ init_units (void)
__gthread_mutex_unlock (&u->lock);
}
-
- /* Calculate the maximum file offset in a portable manner.
- max will be the largest signed number for the type gfc_offset.
- set a 1 in the LSB and keep a running sum, stopping at MSB-1 bit. */
- max_offset = 0;
- for (i = 0; i < sizeof (max_offset) * 8 - 1; i++)
- max_offset = max_offset + ((gfc_offset) 1 << i);
}