re PR fortran/78881 ([F03] reading from string with DTIO procedure does not work properly)
2017-03-25 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR libgfortran/78881 * io/io.h (st_parameter_dt): Rename unused component last_char to child_saved_iostat. Move comment to gfc_unit. * io/list_read.c (list_formatted_read_scalar): After call to child READ procedure, save the returned iostat value for later check. (finish_list_read): Only finish READ if child_saved_iostat was OK. * io/transfer.c (read_sf_internal): If there is a saved character in last character, seek back one. Add a new check for EOR condition. (read_sf): If there is a saved character in last character, seek back one. (formatted_transfer_scalar_read): Initialize last character before invoking child procedure. (data_transfer_init): If child dtio, set advance status to nonadvancing. Move update of size and check for EOR condition to before child dtio return. * gfortran.dg/dtio_26.f90: New test. From-SVN: r246478
This commit is contained in:
parent
4103668640
commit
1f10d710e3
@ -1,3 +1,8 @@
|
|||||||
|
2017-03-25 Jerry DeLisle <jvdelisle@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR libgfortran/78881
|
||||||
|
* gfortran.dg/dtio_26.f90: New test.
|
||||||
|
|
||||||
2017-03-25 Paul Thomas <pault@gcc.gnu.org>
|
2017-03-25 Paul Thomas <pault@gcc.gnu.org>
|
||||||
|
|
||||||
PR fortran/80156
|
PR fortran/80156
|
||||||
|
69
gcc/testsuite/gfortran.dg/dtio_26.f03
Normal file
69
gcc/testsuite/gfortran.dg/dtio_26.f03
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
! { dg-do run }
|
||||||
|
! PR78881 test for correct end of record condition and ignoring advance=
|
||||||
|
module t_m
|
||||||
|
use, intrinsic :: iso_fortran_env, only : iostat_end, iostat_eor, output_unit
|
||||||
|
implicit none
|
||||||
|
type, public :: t
|
||||||
|
character(len=:), allocatable :: m_s
|
||||||
|
contains
|
||||||
|
procedure, pass(this) :: read_t
|
||||||
|
generic :: read(formatted) => read_t
|
||||||
|
end type t
|
||||||
|
contains
|
||||||
|
subroutine read_t(this, lun, iotype, vlist, istat, imsg)
|
||||||
|
class(t), intent(inout) :: this
|
||||||
|
integer, intent(in) :: lun
|
||||||
|
character(len=*), intent(in) :: iotype
|
||||||
|
integer, intent(in) :: vlist(:)
|
||||||
|
integer, intent(out) :: istat
|
||||||
|
character(len=*), intent(inout) :: imsg
|
||||||
|
character(len=1) :: c
|
||||||
|
integer :: i
|
||||||
|
i = 0 ; imsg=''
|
||||||
|
loop_read: do
|
||||||
|
i = i + 1
|
||||||
|
read( unit=lun, fmt='(a1)', iostat=istat, iomsg=imsg) c
|
||||||
|
select case ( istat )
|
||||||
|
case ( 0 )
|
||||||
|
if (i.eq.1 .and. c.ne.'h') exit loop_read
|
||||||
|
!write( output_unit, fmt=sfmt) "i = ", i, ", c = ", c
|
||||||
|
case ( iostat_end )
|
||||||
|
!write( output_unit, fmt=sfmt) "i = ", i, ", istat = iostat_end"
|
||||||
|
exit loop_read
|
||||||
|
case ( iostat_eor )
|
||||||
|
!write( output_unit, fmt=sfmt) "i = ", i, ", istat = iostat_eor"
|
||||||
|
exit loop_read
|
||||||
|
case default
|
||||||
|
!write( output_unit, fmt=sfmt) "i = ", i, ", istat = ", istat
|
||||||
|
exit loop_read
|
||||||
|
end select
|
||||||
|
if (i.gt.10) exit loop_read
|
||||||
|
end do loop_read
|
||||||
|
end subroutine read_t
|
||||||
|
end module t_m
|
||||||
|
|
||||||
|
program p
|
||||||
|
use t_m, only : t
|
||||||
|
implicit none
|
||||||
|
|
||||||
|
character(len=:), allocatable :: s
|
||||||
|
type(t) :: foo
|
||||||
|
character(len=256) :: imsg
|
||||||
|
integer :: istat
|
||||||
|
|
||||||
|
open(10, status="scratch")
|
||||||
|
write(10,'(a)') 'hello'
|
||||||
|
rewind(10)
|
||||||
|
read(unit=10, fmt='(dt)', iostat=istat, iomsg=imsg) foo
|
||||||
|
if (imsg.ne."End of record") call abort
|
||||||
|
rewind(10)
|
||||||
|
read(unit=10, fmt=*, iostat=istat, iomsg=imsg) foo
|
||||||
|
if (imsg.ne."End of record") call abort
|
||||||
|
s = "hello"
|
||||||
|
read( unit=s, fmt='(dt)', iostat=istat, iomsg=imsg) foo
|
||||||
|
if (imsg.ne."End of record") call abort
|
||||||
|
read( unit=s, fmt=*, iostat=istat, iomsg=imsg) foo
|
||||||
|
if (imsg.ne."End of record") call abort
|
||||||
|
end program p
|
||||||
|
|
||||||
|
! { dg-final { cleanup-modules "t_m" } }
|
@ -1,3 +1,21 @@
|
|||||||
|
2017-03-25 Jerry DeLisle <jvdelisle@gcc.gnu.org>
|
||||||
|
|
||||||
|
PR libgfortran/78881
|
||||||
|
* io/io.h (st_parameter_dt): Rename unused component last_char to
|
||||||
|
child_saved_iostat. Move comment to gfc_unit.
|
||||||
|
* io/list_read.c (list_formatted_read_scalar): After call to
|
||||||
|
child READ procedure, save the returned iostat value for later
|
||||||
|
check. (finish_list_read): Only finish READ if child_saved_iostat
|
||||||
|
was OK.
|
||||||
|
* io/transfer.c (read_sf_internal): If there is a saved character
|
||||||
|
in last character, seek back one. Add a new check for EOR
|
||||||
|
condition. (read_sf): If there is a saved character
|
||||||
|
in last character, seek back one. (formatted_transfer_scalar_read):
|
||||||
|
Initialize last character before invoking child procedure.
|
||||||
|
(data_transfer_init): If child dtio, set advance
|
||||||
|
status to nonadvancing. Move update of size and check for EOR
|
||||||
|
condition to before child dtio return.
|
||||||
|
|
||||||
2017-03-17 Thomas Koenig <tkoenig@gcc.gnu.org>
|
2017-03-17 Thomas Koenig <tkoenig@gcc.gnu.org>
|
||||||
|
|
||||||
PR libfortran/79956
|
PR libfortran/79956
|
||||||
|
@ -534,10 +534,7 @@ typedef struct st_parameter_dt
|
|||||||
unsigned expanded_read : 1;
|
unsigned expanded_read : 1;
|
||||||
/* 13 unused bits. */
|
/* 13 unused bits. */
|
||||||
|
|
||||||
/* Used for ungetc() style functionality. Possible values
|
int child_saved_iostat;
|
||||||
are an unsigned char, EOF, or EOF - 1 used to mark the
|
|
||||||
field as not valid. */
|
|
||||||
int last_char; /* No longer used, moved to gfc_unit. */
|
|
||||||
int nml_delim;
|
int nml_delim;
|
||||||
int repeat_count;
|
int repeat_count;
|
||||||
int saved_length;
|
int saved_length;
|
||||||
@ -701,6 +698,10 @@ typedef struct gfc_unit
|
|||||||
|
|
||||||
/* DTIO Parent/Child procedure, 0 = parent, >0 = child level. */
|
/* DTIO Parent/Child procedure, 0 = parent, >0 = child level. */
|
||||||
int child_dtio;
|
int child_dtio;
|
||||||
|
|
||||||
|
/* Used for ungetc() style functionality. Possible values
|
||||||
|
are an unsigned char, EOF, or EOF - 1 used to mark the
|
||||||
|
field as not valid. */
|
||||||
int last_char;
|
int last_char;
|
||||||
bool has_size;
|
bool has_size;
|
||||||
GFC_IO_INT size_used;
|
GFC_IO_INT size_used;
|
||||||
|
@ -2221,6 +2221,7 @@ list_formatted_read_scalar (st_parameter_dt *dtp, bt type, void *p,
|
|||||||
dtp->u.p.fdtio_ptr (p, &unit, iotype, &vlist,
|
dtp->u.p.fdtio_ptr (p, &unit, iotype, &vlist,
|
||||||
child_iostat, child_iomsg,
|
child_iostat, child_iomsg,
|
||||||
iotype_len, child_iomsg_len);
|
iotype_len, child_iomsg_len);
|
||||||
|
dtp->u.p.child_saved_iostat = *child_iostat;
|
||||||
dtp->u.p.current_unit->child_dtio--;
|
dtp->u.p.current_unit->child_dtio--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2352,6 +2353,8 @@ finish_list_read (st_parameter_dt *dtp)
|
|||||||
/* Set the next_char and push_char worker functions. */
|
/* Set the next_char and push_char worker functions. */
|
||||||
set_workers (dtp);
|
set_workers (dtp);
|
||||||
|
|
||||||
|
if (likely (dtp->u.p.child_saved_iostat == LIBERROR_OK))
|
||||||
|
{
|
||||||
c = next_char (dtp);
|
c = next_char (dtp);
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
{
|
{
|
||||||
@ -2362,6 +2365,7 @@ finish_list_read (st_parameter_dt *dtp)
|
|||||||
if (c != '\n')
|
if (c != '\n')
|
||||||
eat_line (dtp);
|
eat_line (dtp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free_line (dtp);
|
free_line (dtp);
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ static char *
|
|||||||
read_sf_internal (st_parameter_dt *dtp, int * length)
|
read_sf_internal (st_parameter_dt *dtp, int * length)
|
||||||
{
|
{
|
||||||
static char *empty_string[0];
|
static char *empty_string[0];
|
||||||
char *base;
|
char *base = NULL;
|
||||||
int lorig;
|
int lorig;
|
||||||
|
|
||||||
/* Zero size array gives internal unit len of 0. Nothing to read. */
|
/* Zero size array gives internal unit len of 0. Nothing to read. */
|
||||||
@ -244,6 +244,15 @@ read_sf_internal (st_parameter_dt *dtp, int * length)
|
|||||||
return (char*) empty_string;
|
return (char*) empty_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* There are some cases with mixed DTIO where we have read a character
|
||||||
|
and saved it in the last character buffer, so we need to backup. */
|
||||||
|
if (unlikely (dtp->u.p.current_unit->child_dtio > 0 &&
|
||||||
|
dtp->u.p.current_unit->last_char != EOF - 1))
|
||||||
|
{
|
||||||
|
dtp->u.p.current_unit->last_char = EOF - 1;
|
||||||
|
sseek (dtp->u.p.current_unit->s, -1, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
lorig = *length;
|
lorig = *length;
|
||||||
if (is_char4_unit(dtp))
|
if (is_char4_unit(dtp))
|
||||||
{
|
{
|
||||||
@ -263,6 +272,12 @@ read_sf_internal (st_parameter_dt *dtp, int * length)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (base && *base == 0)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dtp->u.p.current_unit->bytes_left -= *length;
|
dtp->u.p.current_unit->bytes_left -= *length;
|
||||||
|
|
||||||
if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
|
if (((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0) ||
|
||||||
@ -304,6 +319,15 @@ read_sf (st_parameter_dt *dtp, int * length)
|
|||||||
return (char*) empty_string;
|
return (char*) empty_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* There are some cases with mixed DTIO where we have read a character
|
||||||
|
and saved it in the last character buffer, so we need to backup. */
|
||||||
|
if (unlikely (dtp->u.p.current_unit->child_dtio > 0 &&
|
||||||
|
dtp->u.p.current_unit->last_char != EOF - 1))
|
||||||
|
{
|
||||||
|
dtp->u.p.current_unit->last_char = EOF - 1;
|
||||||
|
fbuf_seek (dtp->u.p.current_unit, -1, SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
n = seen_comma = 0;
|
n = seen_comma = 0;
|
||||||
|
|
||||||
/* Read data into format buffer and scan through it. */
|
/* Read data into format buffer and scan through it. */
|
||||||
@ -1499,6 +1523,7 @@ formatted_transfer_scalar_read (st_parameter_dt *dtp, bt type, void *p, int kind
|
|||||||
|
|
||||||
/* Call the user defined formatted READ procedure. */
|
/* Call the user defined formatted READ procedure. */
|
||||||
dtp->u.p.current_unit->child_dtio++;
|
dtp->u.p.current_unit->child_dtio++;
|
||||||
|
dtp->u.p.current_unit->last_char = EOF - 1;
|
||||||
dtp->u.p.fdtio_ptr (p, &unit, iotype, f->u.udf.vlist,
|
dtp->u.p.fdtio_ptr (p, &unit, iotype, f->u.udf.vlist,
|
||||||
child_iostat, child_iomsg,
|
child_iostat, child_iomsg,
|
||||||
iotype_len, child_iomsg_len);
|
iotype_len, child_iomsg_len);
|
||||||
@ -2856,6 +2881,11 @@ data_transfer_init (st_parameter_dt *dtp, int read_flag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Child IO is non-advancing and any ADVANCE= specifier is ignored.
|
||||||
|
F2008 9.6.2.4 */
|
||||||
|
if (dtp->u.p.current_unit->child_dtio > 0)
|
||||||
|
dtp->u.p.advance_status = ADVANCE_NO;
|
||||||
|
|
||||||
if (read_flag)
|
if (read_flag)
|
||||||
{
|
{
|
||||||
dtp->u.p.current_unit->previous_nonadvancing_write = 0;
|
dtp->u.p.current_unit->previous_nonadvancing_write = 0;
|
||||||
@ -3856,6 +3886,15 @@ finalize_transfer (st_parameter_dt *dtp)
|
|||||||
namelist_write (dtp);
|
namelist_write (dtp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
|
||||||
|
*dtp->size = dtp->u.p.current_unit->size_used;
|
||||||
|
|
||||||
|
if (dtp->u.p.eor_condition)
|
||||||
|
{
|
||||||
|
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (dtp->u.p.current_unit && (dtp->u.p.current_unit->child_dtio > 0))
|
if (dtp->u.p.current_unit && (dtp->u.p.current_unit->child_dtio > 0))
|
||||||
{
|
{
|
||||||
if (cf & IOPARM_DT_HAS_FORMAT)
|
if (cf & IOPARM_DT_HAS_FORMAT)
|
||||||
@ -3866,15 +3905,6 @@ finalize_transfer (st_parameter_dt *dtp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dtp->common.flags & IOPARM_DT_HAS_SIZE) != 0)
|
|
||||||
*dtp->size = dtp->u.p.current_unit->size_used;
|
|
||||||
|
|
||||||
if (dtp->u.p.eor_condition)
|
|
||||||
{
|
|
||||||
generate_error (&dtp->common, LIBERROR_EOR, NULL);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
|
if ((dtp->common.flags & IOPARM_LIBRETURN_MASK) != IOPARM_LIBRETURN_OK)
|
||||||
{
|
{
|
||||||
if (dtp->u.p.current_unit && current_mode (dtp) == UNFORMATTED_SEQUENTIAL)
|
if (dtp->u.p.current_unit && current_mode (dtp) == UNFORMATTED_SEQUENTIAL)
|
||||||
|
Loading…
Reference in New Issue
Block a user