[gfortran] patch for pr15472 and sequential unformatted I/O
Bud Davis
bdavis@gcc.gnu.org
Fri Jul 2 04:58:00 GMT 2004
this patch fixes the PR and about 3 other problems that were keeping
unformatted sequential I/O from working.
it uses 32 bit record length markers on systems with offset_t == 32 bits
and 64 bit record length markers on systems with offset_t == 64. same as
before, it just now works.
i couldn't test these limits because none of the systems i use have
enough memory to create a 2GB or 2GB+ array, but it worked until i ran
out of memory.
tested on i686/gnu/linux FC1 and i686/FreeBSD 5.2 with no additional
test suite failures.
--bud
2004-07-02 Bud Davis <bdavis9659@comcast.net>
PR gfortran/15472
* io/transfer.c(us_write): set recl for seq unform writes to max size.
* io/transfer.c(data_transfer_init): handle un-opened seq unform unit.
* io/unix.c(fd_alloc_w_at): deal with writes in the middle of the
buffer.
* io/unix.c(is_seekable): set based upon the file/device, not the
method being used to access it (fd or mmap).
New test suite file:
! pr 15472
! sequential access files
!
! this test verifies the most basic sequential unformatted I/O
! write 3 records of various sizes
! then read them back
! and compare with what was written
!
implicit none
integer size
parameter(size=100)
logical debug
data debug /.FALSE./
! set debug to true for help in debugging failures.
integer m(2)
integer n
real*4 r(size)
integer i
m(1) = Z'11111111'
m(2) = Z'22222222'
n = Z'33333333'
do i = 1,size
r(i) = i
end do
write(9)m ! an array of 2
write(9)n ! an integer
write(9)r ! an array of reals
! zero all the results so we can compare after they are read back
do i = 1,size
r(i) = 0
end do
m(1) = 0
m(2) = 0
n = 0
rewind(9)
read(9)m
read(9)n
read(9)r
!
! check results
if (m(1).ne.Z'11111111') then
if (debug) then
print '(A,Z8)','m(1) incorrect. m(1) = ',m(1)
else
call abort
endif
endif
if (m(2).ne.Z'22222222') then
if (debug) then
print '(A,Z8)','m(2) incorrect. m(2) = ',m(2)
else
call abort
endif
endif
if (n.ne.Z'33333333') then
if (debug) then
print '(A,Z8)','n incorrect. n = ',n
else
call abort
endif
endif
do i = 1,size
if (int(r(i)).ne.i) then
if (debug) then
print*,'element ',i,' was ',r(i),' should be ',i
else
call abort
endif
endif
end do
! use hexdump to look at the file "fort.9"
if (debug) then
close(9)
else
close(9,status='DELETE')
endif
end
Index: gcc/libgfortran/io/transfer.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/transfer.c,v
retrieving revision 1.7
diff -c -3 -p -r1.7 transfer.c
*** gcc/libgfortran/io/transfer.c 22 Jun 2004 00:43:55 -0000 1.7
--- gcc/libgfortran/io/transfer.c 2 Jul 2004 04:11:23 -0000
*************** us_write (void)
*** 835,840 ****
--- 835,845 ----
if (sfree (current_unit->s) == FAILURE)
generate_error (ERROR_OS, NULL);
+ /* for sequential unformatted, we write until we have more bytes than
+ can fit in the record markers. if disk space runs out first it will
+ error on the write */
+ current_unit->recl = g.max_offset;
+
current_unit->bytes_left = current_unit->recl;
}
*************** data_transfer_init (int read_flag)
*** 890,896 ****
memset (&u_flags, '\0', sizeof (u_flags));
u_flags.access = ACCESS_SEQUENTIAL;
u_flags.action = ACTION_READWRITE;
! u_flags.form = FORM_UNSPECIFIED;
u_flags.delim = DELIM_UNSPECIFIED;
u_flags.blank = BLANK_UNSPECIFIED;
u_flags.pad = PAD_UNSPECIFIED;
--- 895,905 ----
memset (&u_flags, '\0', sizeof (u_flags));
u_flags.access = ACCESS_SEQUENTIAL;
u_flags.action = ACTION_READWRITE;
! /* is it unformatted ?*/
! if (ioparm.format == NULL && !ioparm.list_format)
! u_flags.form = FORM_UNFORMATTED;
! else
! u_flags.form = FORM_UNSPECIFIED;
u_flags.delim = DELIM_UNSPECIFIED;
u_flags.blank = BLANK_UNSPECIFIED;
u_flags.pad = PAD_UNSPECIFIED;
Index: gcc/libgfortran/io/unix.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/unix.c,v
retrieving revision 1.6
diff -c -3 -p -r1.6 unix.c
*** gcc/libgfortran/io/unix.c 26 Jun 2004 11:49:06 -0000 1.6
--- gcc/libgfortran/io/unix.c 2 Jul 2004 04:11:32 -0000
*************** typedef struct
*** 90,96 ****
gfc_offset physical_offset; /* Current physical file offset */
gfc_offset logical_offset; /* Current logical file offset */
gfc_offset dirty_offset; /* Start of modified bytes in buffer */
! gfc_offset file_length; /* Length of the file, -1 if not seekable. */
char *buffer;
int len; /* Physical length of the current buffer */
--- 90,96 ----
gfc_offset physical_offset; /* Current physical file offset */
gfc_offset logical_offset; /* Current logical file offset */
gfc_offset dirty_offset; /* Start of modified bytes in buffer */
! gfc_offset file_length; /* Length of the file, -1 if not seekable. */
char *buffer;
int len; /* Physical length of the current buffer */
*************** fd_alloc_w_at (unix_stream * s, int *len
*** 416,423 ****
{
if (s->dirty_offset + s->ndirty == where)
s->ndirty += *len;
else
! fd_flush (s); /* Can't combine two dirty blocks */
}
s->logical_offset = where + *len;
--- 416,431 ----
{
if (s->dirty_offset + s->ndirty == where)
s->ndirty += *len;
+ else if (where <= s->dirty_offset && where >= s->buffer_offset)
+ {
+ s->dirty_offset = where;
+ s->ndirty = s->ndirty ;
+ }
+ else if (where > s->dirty_offset && where < s->ndirty + s->dirty_offset)
+ ; /* right in the middle, do nothing */
else
! fd_flush (s); /* Can't combine two dirty blocks */
!
}
s->logical_offset = where + *len;
*************** file_position (stream * s)
*** 1390,1397 ****
int
is_seekable (stream * s)
{
!
! return ((unix_stream *) s)->mmaped;
}
try
--- 1398,1407 ----
int
is_seekable (stream * s)
{
! /* by convention, if file_length == -1, the file is not seekable
! note that a mmapped file is always seekable, an fd_ file may
! or may not be. */
! return ((unix_stream *) s)->file_length!=-1;
}
try
More information about the Fortran
mailing list