Commit 59011a60 by Jerry DeLisle

re PR fortran/43265 (No EOF condition if reading with '(x)' from an empty file)

2010-03-17  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libfortran/43265
	* io/io.h: Delete prototype for read_sf, making it static.
	* io/read.c (read_x): Modify to call hit_eof if PAD="no".
	* io/transfer.c (read_sf_internal): New static function extracted from
	read_sf for use on internal units only. Handle empty string case.
	(read_sf): New factoring of this function, make it static.  Add special
	conditions for EOF based on ADVANCE="no", PAD="no", and whether any
	bytes have been previously read from the record.
	(read_block_form): Modify to call read_sf or read_sf_internal.
	(next_record_r): Add a done flag similar to next_record_w. Call hit_eof
	if internal array unit next record returns finished, meaning an EOF was
	found and not done, ie not the last record expected.  For external
	units call hit_eof if item_count is 1 or there are no pending spaces.
	(next_record): Update call to next_record_r.

From-SVN: r157527
parent 5408fbe8
2010-03-17 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR libfortran/43265
* io/io.h: Delete prototype for read_sf, making it static.
* io/read.c (read_x): Modify to call hit_eof if PAD="no".
* io/transfer.c (read_sf_internal): New static function extracted from
read_sf for use on internal units only. Handle empty string case.
(read_sf): New factoring of this function, make it static. Add special
conditions for EOF based on ADVANCE="no", PAD="no", and whether any
bytes have been previously read from the record.
(read_block_form): Modify to call read_sf or read_sf_internal.
(next_record_r): Add a done flag similar to next_record_w. Call hit_eof
if internal array unit next record returns finished, meaning an EOF was
found and not done, ie not the last record expected. For external
units call hit_eof if item_count is 1 or there are no pending spaces.
(next_record): Update call to next_record_r.
2010-03-12 Kai Tietz <kai.tietz@onevision.com> 2010-03-12 Kai Tietz <kai.tietz@onevision.com>
PR/42950 PR/42950
......
...@@ -642,9 +642,6 @@ internal_proto(type_name); ...@@ -642,9 +642,6 @@ internal_proto(type_name);
extern void * read_block_form (st_parameter_dt *, int *); extern void * read_block_form (st_parameter_dt *, int *);
internal_proto(read_block_form); internal_proto(read_block_form);
extern char *read_sf (st_parameter_dt *, int *);
internal_proto(read_sf);
extern void *write_block (st_parameter_dt *, int); extern void *write_block (st_parameter_dt *, int);
internal_proto(write_block); internal_proto(write_block);
......
...@@ -1047,11 +1047,22 @@ read_x (st_parameter_dt *dtp, int n) ...@@ -1047,11 +1047,22 @@ read_x (st_parameter_dt *dtp, int n)
} }
p = fbuf_read (dtp->u.p.current_unit, &length); p = fbuf_read (dtp->u.p.current_unit, &length);
if (p == NULL || (length == 0 && dtp->u.p.item_count == 1)) if (p == NULL)
{ {
hit_eof (dtp); hit_eof (dtp);
return; return;
} }
if (length == 0 && dtp->u.p.item_count == 1)
{
if (dtp->u.p.current_unit->pad_status == PAD_NO)
{
hit_eof (dtp);
return;
}
else
return;
}
n = 0; n = 0;
while (n < length) while (n < length)
......
...@@ -175,9 +175,7 @@ current_mode (st_parameter_dt *dtp) ...@@ -175,9 +175,7 @@ current_mode (st_parameter_dt *dtp)
} }
/* Mid level data transfer statements. These subroutines do reading /* Mid level data transfer statements. */
and writing in the style of salloc_r()/salloc_w() within the
current record. */
/* When reading sequential formatted records we have a problem. We /* When reading sequential formatted records we have a problem. We
don't know how long the line is until we read the trailing newline, don't know how long the line is until we read the trailing newline,
...@@ -190,13 +188,22 @@ current_mode (st_parameter_dt *dtp) ...@@ -190,13 +188,22 @@ current_mode (st_parameter_dt *dtp)
we hit the newline. For small allocations, we use a static buffer. we hit the newline. For small allocations, we use a static buffer.
For larger allocations, we are forced to allocate memory on the For larger allocations, we are forced to allocate memory on the
heap. Hopefully this won't happen very often. */ heap. Hopefully this won't happen very often. */
/* Read sequential file - internal unit */
char * char *
read_sf (st_parameter_dt *dtp, int * length) read_sf_internal (st_parameter_dt *dtp, int * length);
char *
read_sf_internal (st_parameter_dt *dtp, int * length)
{ {
static char *empty_string[0]; static char *empty_string[0];
char *base, *p, q; char *base;
int n, lorig, memread, seen_comma; int lorig;
/* Zero size array gives internal unit len of 0. Nothing to read. */
if (dtp->internal_unit_len == 0
&& dtp->u.p.current_unit->pad_status == PAD_NO)
hit_eof (dtp);
/* If we have seen an eor previously, return a length of 0. The /* If we have seen an eor previously, return a length of 0. The
caller is responsible for correctly padding the input field. */ caller is responsible for correctly padding the input field. */
...@@ -208,17 +215,40 @@ read_sf (st_parameter_dt *dtp, int * length) ...@@ -208,17 +215,40 @@ read_sf (st_parameter_dt *dtp, int * length)
return (char*) empty_string; return (char*) empty_string;
} }
if (is_internal_unit (dtp)) lorig = *length;
base = mem_alloc_r (dtp->u.p.current_unit->s, length);
if (unlikely (lorig > *length))
{ {
memread = *length; hit_eof (dtp);
base = mem_alloc_r (dtp->u.p.current_unit->s, length); return NULL;
if (unlikely (memread > *length)) }
{
hit_eof (dtp); dtp->u.p.current_unit->bytes_left -= *length;
return NULL;
} if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
n = *length; dtp->u.p.size_used += (GFC_IO_INT) *length;
goto done;
return base;
}
/* Read sequential file - external unit */
static char *
read_sf (st_parameter_dt *dtp, int * length)
{
static char *empty_string[0];
char *base, *p, q;
int n, lorig, seen_comma;
/* If we have seen an eor previously, return a length of 0. The
caller is responsible for correctly padding the input field. */
if (dtp->u.p.sf_seen_eor)
{
*length = 0;
/* Just return something that isn't a NULL pointer, otherwise the
caller thinks an error occured. */
return (char*) empty_string;
} }
n = seen_comma = 0; n = seen_comma = 0;
...@@ -307,11 +337,14 @@ read_sf (st_parameter_dt *dtp, int * length) ...@@ -307,11 +337,14 @@ read_sf (st_parameter_dt *dtp, int * length)
else else
dtp->u.p.at_eof = 1; dtp->u.p.at_eof = 1;
} }
else else if (dtp->u.p.advance_status == ADVANCE_NO
{ || dtp->u.p.current_unit->pad_status == PAD_NO
hit_eof (dtp); || dtp->u.p.current_unit->bytes_left
return NULL; == dtp->u.p.current_unit->recl)
} {
hit_eof (dtp);
return NULL;
}
} }
done: done:
...@@ -352,7 +385,8 @@ read_block_form (st_parameter_dt *dtp, int * nbytes) ...@@ -352,7 +385,8 @@ read_block_form (st_parameter_dt *dtp, int * nbytes)
dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl; dtp->u.p.current_unit->bytes_left = dtp->u.p.current_unit->recl;
else else
{ {
if (unlikely (dtp->u.p.current_unit->pad_status == PAD_NO)) if (unlikely (dtp->u.p.current_unit->pad_status == PAD_NO)
&& !is_internal_unit (dtp))
{ {
/* Not enough data left. */ /* Not enough data left. */
generate_error (&dtp->common, LIBERROR_EOR, NULL); generate_error (&dtp->common, LIBERROR_EOR, NULL);
...@@ -360,9 +394,10 @@ read_block_form (st_parameter_dt *dtp, int * nbytes) ...@@ -360,9 +394,10 @@ read_block_form (st_parameter_dt *dtp, int * nbytes)
} }
} }
if (unlikely (dtp->u.p.current_unit->bytes_left == 0)) if (unlikely (dtp->u.p.current_unit->bytes_left == 0
&& !is_internal_unit(dtp)))
{ {
hit_eof (dtp); hit_eof (dtp);
return NULL; return NULL;
} }
...@@ -374,7 +409,11 @@ read_block_form (st_parameter_dt *dtp, int * nbytes) ...@@ -374,7 +409,11 @@ read_block_form (st_parameter_dt *dtp, int * nbytes)
(dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL || (dtp->u.p.current_unit->flags.access == ACCESS_SEQUENTIAL ||
dtp->u.p.current_unit->flags.access == ACCESS_STREAM)) dtp->u.p.current_unit->flags.access == ACCESS_STREAM))
{ {
source = read_sf (dtp, nbytes); if (is_internal_unit (dtp))
source = read_sf_internal (dtp, nbytes);
else
source = read_sf (dtp, nbytes);
dtp->u.p.current_unit->strm_pos += dtp->u.p.current_unit->strm_pos +=
(gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor); (gfc_offset) (*nbytes + dtp->u.p.sf_seen_eor);
return source; return source;
...@@ -2731,7 +2770,7 @@ min_off (gfc_offset a, gfc_offset b) ...@@ -2731,7 +2770,7 @@ min_off (gfc_offset a, gfc_offset b)
/* Space to the next record for read mode. */ /* Space to the next record for read mode. */
static void static void
next_record_r (st_parameter_dt *dtp) next_record_r (st_parameter_dt *dtp, int done)
{ {
gfc_offset record; gfc_offset record;
int bytes_left; int bytes_left;
...@@ -2758,10 +2797,9 @@ next_record_r (st_parameter_dt *dtp) ...@@ -2758,10 +2797,9 @@ next_record_r (st_parameter_dt *dtp)
case FORMATTED_SEQUENTIAL: case FORMATTED_SEQUENTIAL:
/* read_sf has already terminated input because of an '\n', or /* read_sf has already terminated input because of an '\n', or
we have hit EOF. */ we have hit EOF. */
if (dtp->u.p.sf_seen_eor || dtp->u.p.at_eof) if (dtp->u.p.sf_seen_eor)
{ {
dtp->u.p.sf_seen_eor = 0; dtp->u.p.sf_seen_eor = 0;
dtp->u.p.at_eof = 0;
break; break;
} }
...@@ -2773,6 +2811,8 @@ next_record_r (st_parameter_dt *dtp) ...@@ -2773,6 +2811,8 @@ next_record_r (st_parameter_dt *dtp)
record = next_array_record (dtp, dtp->u.p.current_unit->ls, record = next_array_record (dtp, dtp->u.p.current_unit->ls,
&finished); &finished);
if (!done && finished)
hit_eof (dtp);
/* Now seek to this record. */ /* Now seek to this record. */
record = record * dtp->u.p.current_unit->recl; record = record * dtp->u.p.current_unit->recl;
...@@ -2810,7 +2850,8 @@ next_record_r (st_parameter_dt *dtp) ...@@ -2810,7 +2850,8 @@ next_record_r (st_parameter_dt *dtp)
{ {
if (errno != 0) if (errno != 0)
generate_error (&dtp->common, LIBERROR_OS, NULL); generate_error (&dtp->common, LIBERROR_OS, NULL);
else if (dtp->u.p.item_count == 1) else if (dtp->u.p.item_count == 1
|| dtp->u.p.pending_spaces == 0)
hit_eof (dtp); hit_eof (dtp);
break; break;
} }
...@@ -3151,7 +3192,7 @@ next_record (st_parameter_dt *dtp, int done) ...@@ -3151,7 +3192,7 @@ next_record (st_parameter_dt *dtp, int done)
dtp->u.p.current_unit->read_bad = 0; dtp->u.p.current_unit->read_bad = 0;
if (dtp->u.p.mode == READING) if (dtp->u.p.mode == READING)
next_record_r (dtp); next_record_r (dtp, done);
else else
next_record_w (dtp, done); next_record_w (dtp, done);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment