summaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog24
-rw-r--r--libgfortran/io/transfer.c106
-rw-r--r--libgfortran/io/write_float.def3
-rw-r--r--libgfortran/runtime/main.c3
4 files changed, 109 insertions, 27 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 36c0098cab2..765bbd78b3e 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,27 @@
+2008-12-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/38291
+ * io/transfer.c (data_transfer_init): Add fbuf_flush inadvertently
+ ommitted. Add check for invalid use of REC= with ACCESS="stream". Fix
+ comment.
+
+2008-12-06 Adam Nemet <anemet@caviumnetworks.com>
+
+ * runtime/main.c (store_exe_path): Don't crash if argv0 is NULL.
+
+2008-12-05 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/38291
+ * io/transfer.c (data_transfer_init): Add checks for POS= valid range.
+ Add check for unit opened with ACCESS="stream". Flush and seek if
+ current stream position does not match. Check ENDFILE on read.
+
+2008-12-04 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/38285
+ * write_float.def (WRITE_FLOAT): Zero the float value for special case
+ only if scale_factor = 0.
+
2008-11-23 Thomas Koenig <tkoenig@gcc.gnu.org>
PR libfortran/38234
diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c
index c4fae32bead..318d2215ee2 100644
--- a/libgfortran/io/transfer.c
+++ b/libgfortran/io/transfer.c
@@ -1967,7 +1967,7 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
return;
}
- /* Check the record or position number. */
+ /* Check the record number. */
if (dtp->u.p.current_unit->flags.access == ACCESS_DIRECT
&& (cf & IOPARM_DT_HAS_REC) == 0)
@@ -1986,6 +1986,15 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
return;
}
+ if (dtp->u.p.current_unit->flags.access == ACCESS_STREAM
+ && (cf & IOPARM_DT_HAS_REC) != 0)
+ {
+ generate_error (&dtp->common, LIBERROR_OPTION_CONFLICT,
+ "Record number not allowed for stream access "
+ "data transfer");
+ return;
+ }
+
/* Process the ADVANCE option. */
dtp->u.p.advance_status
@@ -2116,6 +2125,65 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
if (dtp->u.p.current_unit->pad_status == PAD_UNSPECIFIED)
dtp->u.p.current_unit->pad_status = dtp->u.p.current_unit->flags.pad;
+
+ /* Check the POS= specifier: that it is in range and that it is used with a
+ unit that has been connected for STREAM access. F2003 9.5.1.10. */
+
+ if (((cf & IOPARM_DT_HAS_POS) != 0))
+ {
+ if (is_stream_io (dtp))
+ {
+
+ if (dtp->pos <= 0)
+ {
+ generate_error (&dtp->common, LIBERROR_BAD_OPTION,
+ "POS=specifier must be positive");
+ return;
+ }
+
+ if (dtp->rec >= dtp->u.p.current_unit->maxrec)
+ {
+ generate_error (&dtp->common, LIBERROR_BAD_OPTION,
+ "POS=specifier too large");
+ return;
+ }
+
+ dtp->rec = dtp->pos;
+
+ if (dtp->u.p.mode == READING)
+ {
+ /* Required for compatibility between 4.3 and 4.4 runtime. Check
+ to see if we might be reading what we wrote before */
+ if (dtp->u.p.current_unit->mode == WRITING)
+ {
+ fbuf_flush (dtp->u.p.current_unit, 1);
+ flush(dtp->u.p.current_unit->s);
+ }
+
+ if (dtp->pos < file_length (dtp->u.p.current_unit->s))
+ dtp->u.p.current_unit->endfile = NO_ENDFILE;
+ }
+
+ if (dtp->pos != dtp->u.p.current_unit->strm_pos)
+ {
+ fbuf_flush (dtp->u.p.current_unit, 1);
+ flush (dtp->u.p.current_unit->s);
+ if (sseek (dtp->u.p.current_unit->s, dtp->pos - 1) == FAILURE)
+ {
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ return;
+ }
+ dtp->u.p.current_unit->strm_pos = dtp->pos;
+ }
+ }
+ else
+ {
+ generate_error (&dtp->common, LIBERROR_BAD_OPTION,
+ "POS=specifier not allowed, "
+ "Try OPEN with ACCESS='stream'");
+ return;
+ }
+ }
/* Sanity checks on the record number. */
if ((cf & IOPARM_DT_HAS_REC) != 0)
@@ -2139,10 +2207,10 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
if (dtp->u.p.mode == READING
&& dtp->u.p.current_unit->mode == WRITING
&& !is_internal_unit (dtp))
- {
- fbuf_flush (dtp->u.p.current_unit, 1);
+ {
+ fbuf_flush (dtp->u.p.current_unit, 1);
flush(dtp->u.p.current_unit->s);
- }
+ }
/* Check whether the record exists to be read. Only
a partial record needs to exist. */
@@ -2156,29 +2224,17 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
}
/* Position the file. */
- if (!is_stream_io (dtp))
+ if (sseek (dtp->u.p.current_unit->s, (gfc_offset) (dtp->rec - 1)
+ * dtp->u.p.current_unit->recl) == FAILURE)
{
- if (sseek (dtp->u.p.current_unit->s, (gfc_offset) (dtp->rec - 1)
- * dtp->u.p.current_unit->recl) == FAILURE)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
+ generate_error (&dtp->common, LIBERROR_OS, NULL);
+ return;
}
- else
- {
- if (dtp->u.p.current_unit->strm_pos != dtp->rec)
- {
- fbuf_flush (dtp->u.p.current_unit, 1);
- flush (dtp->u.p.current_unit->s);
- if (sseek (dtp->u.p.current_unit->s, dtp->rec - 1) == FAILURE)
- {
- generate_error (&dtp->common, LIBERROR_OS, NULL);
- return;
- }
- dtp->u.p.current_unit->strm_pos = dtp->rec;
- }
- }
+
+ /* This is required to maintain compatibility between
+ 4.3 and 4.4 runtime. */
+ if (is_stream_io (dtp))
+ dtp->u.p.current_unit->strm_pos = dtp->rec;
}
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index 8bb4123084f..d8799f2ae03 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -760,7 +760,8 @@ sprintf (buffer, "%+-#" STR(MIN_FIELD_WIDTH) ".*" \
return;\
}\
tmp = sign_bit ? -tmp : tmp;\
- if (f->u.real.d == 0 && f->format == FMT_F)\
+ if (f->u.real.d == 0 && f->format == FMT_F\
+ && dtp->u.p.scale_factor == 0)\
{\
if (tmp < 0.5)\
tmp = 0.0;\
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index 71b481a7deb..947b3985238 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -111,7 +111,8 @@ store_exe_path (const char * argv0)
char buf[PATH_MAX], *cwd, *path;
- if (argv0[0] == '/')
+ /* On the simulator argv is not set. */
+ if (argv0 == NULL || argv0[0] == '/')
{
exe_path = argv0;
please_free_exe_path_when_done = 0;