diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 5f9ddaf668f..9d753296445 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,20 @@ +2014-06-08 Janne Blomqvist + + PR libfortran/56981 + * io/unix.h (struct stream_vtable): Add new member function, + markeor. + (smarkeor): New inline function. + (flush_if_unbuffered): Remove prototype. + * io/unix.c (raw_markeor): New function. + (raw_vtable): Initialize markeor member. + (buf_markeor): New function. + (buf_vtable): Initialize markeor member. + (mem_vtable): Likewise. + (mem4_vtable): Likewise. + (flush_if_unbuffered): Remove function. + * io/transfer.c (next_record): Call smarkeor instead of + flush_if_unbuffered. + 2014-05-27 Uros Bizjak * intrinsics/getcwd.c: Include stdlib.h. diff --git a/libgfortran/io/transfer.c b/libgfortran/io/transfer.c index cfe92ca0655..cc0132c80f7 100644 --- a/libgfortran/io/transfer.c +++ b/libgfortran/io/transfer.c @@ -3512,7 +3512,7 @@ next_record (st_parameter_dt *dtp, int done) pre_position (dtp); fbuf_flush (dtp->u.p.current_unit, dtp->u.p.mode); - flush_if_unbuffered (dtp->u.p.current_unit->s); + smarkeor (dtp->u.p.current_unit->s); } diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c index 3721b71f994..c9866d3495a 100644 --- a/libgfortran/io/unix.c +++ b/libgfortran/io/unix.c @@ -421,6 +421,12 @@ raw_close (unix_stream * s) return retval; } +static int +raw_markeor (unix_stream * s __attribute__ ((unused))) +{ + return 0; +} + static const struct stream_vtable raw_vtable = { .read = (void *) raw_read, .write = (void *) raw_write, @@ -429,7 +435,8 @@ static const struct stream_vtable raw_vtable = { .size = (void *) raw_size, .trunc = (void *) raw_truncate, .close = (void *) raw_close, - .flush = (void *) raw_flush + .flush = (void *) raw_flush, + .markeor = (void *) raw_markeor }; static int @@ -584,6 +591,23 @@ buf_write (unix_stream * s, const void * buf, ssize_t nbyte) return nbyte; } + +/* "Unbuffered" really means I/O statement buffering. For formatted + I/O, the fbuf manages this, and then uses raw I/O. For unformatted + I/O, buffered I/O is used, and the buffer is flushed at the end of + each I/O statement, where this function is called. Alternatively, + the buffer is flushed at the end of the record if the buffer is + more than half full; this prevents needless seeking back and forth + when writing sequential unformatted. */ + +static int +buf_markeor (unix_stream * s) +{ + if (s->unbuffered || s->ndirty >= BUFFER_SIZE / 2) + return buf_flush (s); + return 0; +} + static gfc_offset buf_seek (unix_stream * s, gfc_offset offset, int whence) { @@ -651,7 +675,8 @@ static const struct stream_vtable buf_vtable = { .size = (void *) buf_size, .trunc = (void *) buf_truncate, .close = (void *) buf_close, - .flush = (void *) buf_flush + .flush = (void *) buf_flush, + .markeor = (void *) buf_markeor }; static int @@ -910,7 +935,8 @@ static const struct stream_vtable mem_vtable = { .size = (void *) buf_size, .trunc = (void *) mem_truncate, .close = (void *) mem_close, - .flush = (void *) mem_flush + .flush = (void *) mem_flush, + .markeor = (void *) raw_markeor }; static const struct stream_vtable mem4_vtable = { @@ -923,7 +949,8 @@ static const struct stream_vtable mem4_vtable = { .size = (void *) buf_size, .trunc = (void *) mem_truncate, .close = (void *) mem_close, - .flush = (void *) mem_flush + .flush = (void *) mem_flush, + .markeor = (void *) raw_markeor }; /********************************************************************* @@ -972,21 +999,6 @@ open_internal4 (char *base, int length, gfc_offset offset) } -/* "Unbuffered" really means I/O statement buffering. For formatted - I/O, the fbuf manages this, and then uses raw I/O. For unformatted - I/O, buffered I/O is used, and the buffer is flushed at the end of - each I/O statement, where this function is called. */ - -int -flush_if_unbuffered (stream* s) -{ - unix_stream* us = (unix_stream*) s; - if (us->unbuffered) - return sflush (s); - return 0; -} - - /* fd_to_stream()-- Given an open file descriptor, build a stream * around it. */ diff --git a/libgfortran/io/unix.h b/libgfortran/io/unix.h index 910f2c2e650..0f696df5dac 100644 --- a/libgfortran/io/unix.h +++ b/libgfortran/io/unix.h @@ -38,6 +38,7 @@ struct stream_vtable int (* const trunc) (struct stream *, gfc_offset); int (* const flush) (struct stream *); int (* const close) (struct stream *); + int (* const markeor) (struct stream *); }; struct stream @@ -94,6 +95,12 @@ sclose (stream * s) return s->vptr->close (s); } +static inline int +smarkeor (stream * s) +{ + return s->vptr->markeor (s); +} + extern int compare_files (stream *, stream *); internal_proto(compare_files); @@ -167,9 +174,6 @@ internal_proto(inquire_readwrite); extern void flush_if_preconnected (stream *); internal_proto(flush_if_preconnected); -extern int flush_if_unbuffered (stream*); -internal_proto(flush_if_unbuffered); - extern int stream_isatty (stream *); internal_proto(stream_isatty);