diff --git a/runtime/flang/backspace.c b/runtime/flang/backspace.c index 8b9aef71ce4..b34511f433e 100644 --- a/runtime/flang/backspace.c +++ b/runtime/flang/backspace.c @@ -74,19 +74,19 @@ _f90io_backspace(__INT_T *unit, __INT_T *bitv, __INT_T *iostat, int swap_bytes) if (f->nonadvance) { f->nonadvance = FALSE; + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); #if defined(WINNT) - if (__fortio_binary_mode(f->fp)) - __io_fputc('\r', f->fp); + if (__fortio_binary_mode(f->__io_fp)) + __io_fputc('\r', f->__io_fp); #endif - __io_fputc('\n', f->fp); - if (__io_ferror(f->fp)) + __io_fputc('\n', f->__io_fp); + if (__io_ferror(f->__io_fp)) return __io_errno(); } - fp = f->fp; /* if already at the beginning just return without error */ /* if (f->nextrec < 2) */ - if (__io_ftell(fp) == 0) /* use ftell in case file opened 'append' */ + if (FIO_FCB_FTELL(f) == 0) /* use ftell in case file opened 'append' */ return 0; if (f->form == FIO_UNFORMATTED) { /* CASE 1: unformatted file */ @@ -95,6 +95,9 @@ _f90io_backspace(__INT_T *unit, __INT_T *bitv, __INT_T *iostat, int swap_bytes) so back up over trailing length field, read the size, then back up over the record and both length fields */ + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __fortio_error(__io_errno())); + fp = f->__io_fp; + rec_continued: if (__io_fseek(fp, -((seekoffx_t)RCWSZ), SEEK_CUR) != 0) return __fortio_error(__io_errno()); @@ -112,17 +115,21 @@ _f90io_backspace(__INT_T *unit, __INT_T *bitv, __INT_T *iostat, int swap_bytes) goto rec_continued; f->coherent = 0; /* avoid unnecessary seek later on */ } else { /* CASE 2: formatted file */ + int ch; seekoffx_t pos; assert(f->form == FIO_FORMATTED); - pos = __io_ftell(fp) - 1; + pos = FIO_FCB_FTELL(f) - 1L; assert(pos >= 0); while (TRUE) { if (pos > 0) --pos; - if (__io_fseek(fp, pos, SEEK_SET) != 0) - return __fortio_error(__io_errno()); + FIO_FCB_FSEEK_SET(f, pos, return __fortio_error(__io_errno())); - if (pos == 0 || __io_fgetc(fp) == '\n') { + if (pos == 0) + ch = 0; + else + FIO_FCB_BUFFERED_GETC(ch, f, return __fortio_error(__io_errno())); + if (pos == 0 || ch == '\n') { /* must set coherent flag to 'read' in case the next operation on this file is a write: */ f->coherent = 2 /*read*/; diff --git a/runtime/flang/close.c b/runtime/flang/close.c index d1d14c1ee85..217dcbf4e5a 100644 --- a/runtime/flang/close.c +++ b/runtime/flang/close.c @@ -47,16 +47,16 @@ __fortio_close(FIO_FCB *f, int flag) if (f->nonadvance) { f->nonadvance = FALSE; #if defined(WINNT) - if (__fortio_binary_mode(f->fp)) - __io_fputc('\r', f->fp); + if (__fortio_binary_mode(f->__io_fp)) + __io_fputc('\r', f->__io_fp); #endif - __io_fputc('\n', f->fp); - if (__io_ferror(f->fp)) + __io_fputc('\n', f->__io_fp); + if (__io_ferror(f->__io_fp)) return __io_errno(); } if (!f->stdunit) { - if (__io_fclose(f->fp) != 0) { + if (__io_fclose(f->__io_fp) != 0) { return __fortio_error(__io_errno()); } if (flag == 0 && f->dispose == FIO_DELETE) @@ -79,7 +79,7 @@ __fortio_close(FIO_FCB *f, int flag) #if defined(TARGET_OSX) if (f->unit != 5 && f->unit != -5) #endif - if (__io_fflush(f->fp) != 0) + if (__io_fflush(f->__io_fp) != 0) return __fortio_error(__io_errno()); } @@ -201,10 +201,10 @@ __fortio_cleanup(void) * consequently, need to extract the 'next' field now. */ f_next = f->next; - if (f->fp == NULL) { /* open? */ + if (f->__io_fp == NULL) { /* open? */ continue; } - __io_fflush(f->fp); + __io_fflush(f->__io_fp); if (f->stdunit) { /* standard unit? */ continue; } diff --git a/runtime/flang/error.c b/runtime/flang/error.c index 7db08cf730c..159c210c6c6 100644 --- a/runtime/flang/error.c +++ b/runtime/flang/error.c @@ -443,10 +443,11 @@ __fortio_error(int errval) } fioFcbTbls.error = TRUE; - if (fdesc && fdesc->fp && fdesc->acc == FIO_DIRECT) { + if (fdesc && fdesc->__io_fp && fdesc->acc == FIO_DIRECT) { /* leave file in consistent state: */ fdesc->nextrec = 1; - __io_fseek(fdesc->fp, 0L, SEEK_SET); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(fdesc); + __io_fseek(fdesc->__io_fp, 0L, SEEK_SET); } if ((iobitv & FIO_BITV_EOR) && (errval == FIO_ETOOBIG)) { @@ -837,7 +838,7 @@ win_set_binary(FIO_FCB *f) { FILE *fil; - fil = f->fp; + fil = f->__io_fp; if (!__fort_isatty(__fort_getfd(fil))) { __fortio_setmode_binary(fil); } @@ -863,7 +864,7 @@ __fortio_init(void) /* preconnect stdin as unit -5 for * unit specifier */ f = __fortio_alloc_fcb(); - f->fp = __io_stdin(); + f->__io_fp = __io_stdin(); f->unit = -5; f->name = "stdin "; f->reclen = 0; @@ -894,7 +895,7 @@ __fortio_init(void) /* preconnect stdout as unit -6 for * unit specifier */ f = __fortio_alloc_fcb(); - f->fp = __io_stdout(); + f->__io_fp = __io_stdout(); f->unit = -6; f->name = "stdout "; f->reclen = 0; @@ -925,7 +926,7 @@ __fortio_init(void) /* preconnect stdin as unit 5 */ f = __fortio_alloc_fcb(); - f->fp = __io_stdin(); + f->__io_fp = __io_stdin(); f->unit = 5; f->name = "stdin "; f->reclen = 0; @@ -956,7 +957,7 @@ __fortio_init(void) /* preconnect stdout as unit 6 */ f = __fortio_alloc_fcb(); - f->fp = __io_stdout(); + f->__io_fp = __io_stdout(); f->unit = 6; f->name = "stdout "; f->reclen = 0; @@ -987,7 +988,7 @@ __fortio_init(void) /* preconnect stderr as unit 0 */ f = __fortio_alloc_fcb(); - f->fp = __io_stderr(); + f->__io_fp = __io_stderr(); f->unit = 0; f->name = "stderr "; f->reclen = 0; diff --git a/runtime/flang/flush.c b/runtime/flang/flush.c index da6f9dc2ebd..e354564344c 100644 --- a/runtime/flang/flush.c +++ b/runtime/flang/flush.c @@ -54,7 +54,7 @@ __INT_T *iostat; } } - if (__io_fflush(f->fp) != 0) { + if (__io_fflush(f->__io_fp) != 0) { s = __fortio_error(__io_errno()); __fortio_errend03(); return s; diff --git a/runtime/flang/fmtread.c b/runtime/flang/fmtread.c index ff24d31155d..0e816b15d2a 100644 --- a/runtime/flang/fmtread.c +++ b/runtime/flang/fmtread.c @@ -3221,7 +3221,7 @@ fr_read_record(void) g->rec_buff += g->rec_len; /* point to next record */ } else { /* external file */ FIO_FCB *f = g->fcb; - FILE *fp = f->fp; + if (f->pread) { int idx = 0; char *p = f->pread; @@ -3230,7 +3230,7 @@ fr_read_record(void) while (TRUE) { /* read one char per iteration until '\n' */ int c = *(p++); if (c == EOF) { - if (__io_feof(fp)) { + if (__io_feof(f->__io_fp)) { if (idx) break; return FIO_EEOF; @@ -3264,15 +3264,18 @@ fr_read_record(void) if (f->acc == FIO_DIRECT) { if (f->nextrec > f->maxrec + 1) return FIO_EDREAD; /* attempt to read non-existent rec */ - if (__io_fread(g->rec_buff, 1, g->rec_len, fp) != g->rec_len) + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + if (__io_fread(g->rec_buff, 1, g->rec_len, f->__io_fp) != g->rec_len) return __io_errno(); } else { /* sequential read */ idx = 0; while (TRUE) { /* read one char per iteration until '\n' */ - int c = __io_fgetc(fp); + int c; + + FIO_FCB_BUFFERED_GETC(c, f, return __io_errno()); if (c == EOF) { - if (__io_feof(fp)) { + if (__io_feof(f->__io_fp)) { if (idx) break; if (g->nonadvance && !g->eor_seen && g->rec_len != 0) @@ -3284,12 +3287,12 @@ fr_read_record(void) return __io_errno(); } if (c == '\r' && EOR_CRLF) { - c = __io_fgetc(fp); + FIO_FCB_BUFFERED_GETC(c, f, return __io_errno()); if (c == '\n') { g->eor_len = 2; break; } - __io_ungetc(c, fp); + FIO_FCB_BUFFERED_UNGETC(c, f); c = '\r'; } if (c == '\n') { @@ -3382,7 +3385,7 @@ _f90io_fmtr_end(void) int i; i = g->rec_len - g->curr_pos + g->eor_len; --(g->fcb->nextrec); /* decr errmsg recnum */ - if (__io_fseek(g->fcb->fp, (seekoffx_t)-i, SEEK_CUR) != 0) { + FIO_FCB_FSEEK_CUR(g->fcb, (seekoffx_t)-i, { if (g->fcb->stdunit) { /* * Can't seek stdin, but need to leave the postion @@ -3393,7 +3396,7 @@ _f90io_fmtr_end(void) return 0; } return __fortio_error(__io_errno()); - } + }); } } } diff --git a/runtime/flang/fmtwrite.c b/runtime/flang/fmtwrite.c index 1e8ca73a97d..9eb433a4f04 100644 --- a/runtime/flang/fmtwrite.c +++ b/runtime/flang/fmtwrite.c @@ -2617,19 +2617,22 @@ fw_write_record(void) FIO_FCB *f = g->fcb; if (f->acc == FIO_DIRECT) { - if (FWRITE(g->rec_buff, 1, g->rec_len, f->fp) != (int)g->rec_len) + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + if (FWRITE(g->rec_buff, 1, g->rec_len, f->__io_fp) != (int)g->rec_len) return __io_errno(); } else { /* sequential write */ if (g->nonadvance) { if (g->curr_pos >= g->max_pos) { g->max_pos = g->curr_pos; fw_check_size(g->max_pos); - if (FWRITE(g->rec_buff, 1, g->max_pos, f->fp) != (int)g->max_pos) + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + if (FWRITE(g->rec_buff, 1, g->max_pos, f->__io_fp) != (int)g->max_pos) return __io_errno(); } else if (g->curr_pos < g->max_pos) { long len = g->max_pos - g->curr_pos; - if (FWRITE(g->rec_buff, 1, g->curr_pos, f->fp) != (int)g->curr_pos) + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + if (FWRITE(g->rec_buff, 1, g->curr_pos, f->__io_fp) != (int)g->curr_pos) return __io_errno(); g->fcb->skip = len; g->fcb->skip_buff = malloc(len); @@ -2637,20 +2640,22 @@ fw_write_record(void) } f->nonadvance = TRUE; /* do it later */ } else { - if (FWRITE(g->rec_buff, 1, g->max_pos, f->fp) != (int)g->max_pos) + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + if (FWRITE(g->rec_buff, 1, g->max_pos, f->__io_fp) != (int)g->max_pos) return __io_errno(); f->nonadvance = FALSE; /* do it now */ if (!(g->suppress_crlf)) { + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); /* append carriage return */ #if defined(WINNT) - if (__fortio_binary_mode(f->fp)) - __io_fputc('\r', f->fp); + if (__fortio_binary_mode(f->__io_fp)) + __io_fputc('\r', f->__io_fp); #endif /* if (g->max_pos > 0)*/ - __io_fputc('\n', f->fp); - if (__io_ferror(f->fp)) + __io_fputc('\n', f->__io_fp); + if (__io_ferror(f->__io_fp)) return __io_errno(); - } else if (fflush(f->fp) != 0) + } else if (fflush(f->__io_fp) != 0) return __io_errno(); } } diff --git a/runtime/flang/fstat3f.c b/runtime/flang/fstat3f.c index 960cb96d7b2..7c007c1d04d 100644 --- a/runtime/flang/fstat3f.c +++ b/runtime/flang/fstat3f.c @@ -35,7 +35,7 @@ int ENT3F(FSTAT, fstat)(int *lu, int *statb) f = __fio_find_unit(*lu); if (f && !FIO_FCB_STDUNIT(f)) { - /* need a way to get f->fp's fildes */ + /* need a way to get f->__io_fp's fildes */ if (i = _stat32(FIO_FCB_NAME(f), &b)) i = __io_errno(); } else { @@ -78,7 +78,7 @@ int ENT3F(FSTAT, fstat)(int *lu, int *statb) f = __fio_find_unit(*lu); if (f && !FIO_FCB_STDUNIT(f)) { - /** need a way to get f->fp's fildes **/ + /** need a way to get f->__io_fp's fildes **/ if ((i = stat(FIO_FCB_NAME(f), &b))) i = __io_errno(); } else { diff --git a/runtime/flang/fstat643f.c b/runtime/flang/fstat643f.c index 43a9dd9aefc..e9480308c77 100644 --- a/runtime/flang/fstat643f.c +++ b/runtime/flang/fstat643f.c @@ -59,7 +59,7 @@ int ENT3F(FSTAT64, fstat64)(int *lu, long long *statb) f = __fio_find_unit(*lu); if (f && !FIO_FCB_STDUNIT(f)) { - /** need a way to get f->fp's fildes **/ + /** need a way to get f->__io_fp's fildes **/ if (i = _stat64(FIO_FCB_NAME(f), bp)) i = __io_errno(); } else { @@ -102,7 +102,7 @@ int ENT3F(FSTAT64, fstat64)(int *lu, long long *statb) f = __fio_find_unit(*lu); if (f && !FIO_FCB_STDUNIT(f)) { - /** need a way to get f->fp's fildes **/ + /** need a way to get f->__io_fp's fildes **/ if ((i = stat(FIO_FCB_NAME(f), &b))) i = __io_errno(); } else { diff --git a/runtime/flang/global.h b/runtime/flang/global.h index 587a143137e..7c3a8e9daa6 100644 --- a/runtime/flang/global.h +++ b/runtime/flang/global.h @@ -181,13 +181,16 @@ extern char *strcpy(); #define ILLEGAL_UNIT(u) \ ((u) < 0 && ((u) > FIRST_NEWUNIT || (u) <= next_newunit)) +#define FIO_FCB_IO_BUFFSIZE 32768U +#define FIO_FCB_GETC_BUFFSIZE 32768U + /* Fortran I/O file control block struct */ typedef struct fcb { struct fcb *next; /* pointer to next fcb in avail or allocd * list. */ - FILE *fp; /* UNIX file pointer from fopen(). Note that a + FILE *__io_fp; /* UNIX file pointer from fopen(). Note that a * non-NULL value for this field is what * indicates that a particular FCB is in use. */ @@ -277,8 +280,122 @@ typedef struct fcb { char *pback; /* need to keep track of the last line read * used in nmlread too. */ + char *getc_buffer; /* pointer to buffer utilized by fgetc() replacement code */ + unsigned getc_inbuffer; /* how many characters waiting */ + int getc_bufpos; /* current character to process */ + long getc_filepos; /* tracking position in file for ftell() replacement */ + sbool getc_buffer_notuse; /* blocking use of fgetc() replacement code */ + sbool getc_has_ungetc; /* ungetc() was called while using fgetc() replacement code */ + int getc_ungetc; /* character passed to ungetc() replacement */ } FIO_FCB; +#define FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, on_error) if (0 <= ((fcb)->getc_bufpos)) { \ + (fcb)->getc_bufpos = -1; \ + if (__io_feof((fcb)->__io_fp)) \ + __io_clearerr((fcb)->__io_fp); \ + if (__io_fseek((fcb)->__io_fp, (fcb)->getc_filepos, SEEK_SET) != 0) \ + on_error; \ +} + +#define FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_TESTING_EOF(fcb, on_error) if (0 <= ((fcb)->getc_bufpos)) { \ + char buff = 0; \ + \ + (fcb)->getc_bufpos = -1; \ + if (__io_feof((fcb)->__io_fp)) { \ + __io_clearerr((fcb)->__io_fp); \ + buff = 1; \ + } \ + if (__io_fseek((fcb)->__io_fp, (fcb)->getc_filepos, SEEK_SET) != 0) \ + on_error; \ + if (buff) { \ + __io_fread(&buff, sizeof(char), 1U, (fcb)->__io_fp); \ + if (!__io_feof((fcb)->__io_fp)) \ + if (__io_fseek((fcb)->__io_fp, (fcb)->getc_filepos, SEEK_SET) != 0) \ + on_error; \ + } \ +} + +#define FIO_FCB_INVALIDATE_GETC_BUFFER_FULLY(fcb, on_error) do { \ + (fcb)->getc_buffer_notuse = TRUE; \ + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_TESTING_EOF(fcb, on_error); \ +} while (0) + +#define FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(fcb) (fcb)->getc_bufpos = -1 + +#define FIO_FCB_FSEEK_CUR(fcb, offset, on_error) if (0 <= ((fcb)->getc_bufpos)) { \ + (fcb)->getc_bufpos = -1; \ + if (__io_feof((fcb)->__io_fp)) \ + __io_clearerr((fcb)->__io_fp); \ + if (__io_fseek((fcb)->__io_fp, (fcb)->getc_filepos + (offset), SEEK_SET) != 0) \ + on_error; \ +} else \ +{ \ + if (__io_fseek((fcb)->__io_fp, (offset), SEEK_CUR) != 0) \ + on_error; \ +} + +#define FIO_FCB_FSEEK_SET(fcb, offset, on_error) if (0 <= ((fcb)->getc_bufpos)) { \ + long tmp = ((fcb)->getc_bufpos) + ((offset) - ((fcb)->getc_filepos)); \ + (fcb)->getc_filepos = offset; \ + if ((0L <= tmp) && (tmp < ((fcb)->getc_inbuffer))) { \ + (fcb)->getc_bufpos = tmp; \ + } else { \ + (fcb)->getc_bufpos = -1; \ + if (__io_feof((fcb)->__io_fp)) \ + __io_clearerr((fcb)->__io_fp); \ + if (__io_fseek((fcb)->__io_fp, (offset), SEEK_SET) != 0) \ + on_error; \ + } \ +} else \ +{ \ + if (__io_fseek((fcb)->__io_fp, (offset), SEEK_SET) != 0) \ + on_error; \ +} + +#define FIO_FCB_BUFFERED_GETC(c, fcb, on_error) do { \ + if ((fcb)->getc_buffer_notuse) { \ + (c) = __io_fgetc((fcb)->__io_fp); \ + } else { \ + if (0 > ((fcb)->getc_bufpos)) { \ + (fcb)->getc_filepos = __io_ftell((fcb)->__io_fp); \ + if (0L > (fcb)->getc_filepos) \ + on_error; \ + (fcb)->getc_inbuffer = 0U; \ + (fcb)->getc_bufpos = 0; \ + (fcb)->getc_has_ungetc = FALSE; \ + } \ + if ((fcb)->getc_has_ungetc) { \ + (c) = (fcb)->getc_ungetc; \ + (fcb)->getc_has_ungetc = FALSE; \ + } else { \ + if (!(((unsigned)((fcb)->getc_bufpos)) < (fcb)->getc_inbuffer)) { \ + (fcb)->getc_bufpos = 0; \ + (fcb)->getc_inbuffer = __io_fread((fcb)->getc_buffer, sizeof(char), FIO_FCB_GETC_BUFFSIZE, (fcb)->__io_fp); \ + } \ + if (((unsigned)((fcb)->getc_bufpos)) < (fcb)->getc_inbuffer) { \ + (c) = (fcb)->getc_buffer[(fcb)->getc_bufpos]; \ + (fcb)->getc_bufpos++; \ + (fcb)->getc_filepos++; \ + } else { \ + (c) = EOF; \ + } \ + } \ + } \ +} while (0) + +#define FIO_FCB_BUFFERED_UNGETC(c, fcb) do { \ + if ((fcb)->getc_buffer_notuse) { \ + (c) = __io_ungetc((c), (fcb)->__io_fp); \ + } else { \ + (fcb)->getc_ungetc = (c); \ + (fcb)->getc_has_ungetc = TRUE; \ + } \ +} while (0) + +#define FIO_FCB_FTELL(fcb) ((0 <= ((fcb)->getc_bufpos)) ? (fcb)->getc_filepos : __io_ftell((fcb)->__io_fp)) + +#define FIO_FCB_FTELLX(fcb) ((0 <= ((fcb)->getc_bufpos)) ? (fcb)->getc_filepos : __io_ftellx((fcb)->__io_fp)) + /* * FIO_FCB flags were moved to a separate header file because some low * level routines (rounding in particular) need to access them without diff --git a/runtime/flang/inquire.c b/runtime/flang/inquire.c index b10a23b548e..243026c8f06 100644 --- a/runtime/flang/inquire.c +++ b/runtime/flang/inquire.c @@ -332,19 +332,22 @@ inquire(__INT_T *unit, char *file_ptr, __INT_T *bitv, __INT_T *iostat, *pending = FTN_FALSE; } if (pos) { - if (f != NULL) - *pos = __io_ftellx(f->fp) + 1; + if (f != NULL) { + *pos = FIO_FCB_FTELLX(f) + 1; + } } if (size) { FILE *lcl_fp; if (f != NULL) { seekoffx_t currpos; - lcl_fp = f->fp; - currpos = (seekoffx_t)__io_ftellx(f->fp); - if (__io_fseek(f->fp, 0L, SEEK_END) != 0) + lcl_fp = NULL; + currpos = (seekoffx_t)FIO_FCB_FTELLX(f); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, 0L, SEEK_END) != 0) return (__fortio_error(__io_errno())); - *size = __io_ftellx(f->fp); - __io_fseek(f->fp, currpos, SEEK_SET); + *size = FIO_FCB_FTELLX(f); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + __io_fseek(f->__io_fp, currpos, SEEK_SET); } else if (file_ptr != NULL) { /* inquire by file and not connected */ char btmpnam[MAX_NAMELEN + 1]; char *tmpnam; @@ -1483,17 +1486,20 @@ ENTF90IO(INQUIRE2A, inquire2a) *pending = FTN_FALSE; } if (pos != NULL) { - if (f != NULL) - *pos = __io_ftellx(f->fp) + 1; + if (f != NULL) { + *pos = FIO_FCB_FTELLX(f) + 1; + } } if (size != NULL) { if (f != NULL) { seekoffx_t currpos; - currpos = (seekoffx_t)__io_ftellx(f->fp); - if (__io_fseek(f->fp, 0L, SEEK_END) != 0) + currpos = (seekoffx_t)FIO_FCB_FTELLX(f); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, 0L, SEEK_END) != 0) return (__fortio_error(__io_errno())); - *size = __io_ftellx(f->fp); - __io_fseek(f->fp, currpos, SEEK_SET); + *size = FIO_FCB_FTELLX(f); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + __io_fseek(f->__io_fp, currpos, SEEK_SET); } else *size = -1; } diff --git a/runtime/flang/ldread.c b/runtime/flang/ldread.c index 931ba1bcc2b..ed014c49d79 100644 --- a/runtime/flang/ldread.c +++ b/runtime/flang/ldread.c @@ -1582,7 +1582,7 @@ read_record(void) p = alloc_rbuf(byte_cnt, TRUE); ch = *f++; if (ch == EOF) { - if (__io_feof(fcb->fp)) { + if (__io_feof(fcb->__io_fp)) { if (byte_cnt) break; return FIO_EEOF; @@ -1611,7 +1611,8 @@ read_record(void) (void) alloc_rbuf(byte_cnt, FALSE); if (fcb->nextrec > fcb->maxrec + 1) return FIO_EDREAD; /* attempt to read non-existent rec */ - if (__io_fread(rbufp, byte_cnt, 1, fcb->fp) != 1) + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __io_errno()); + if (__io_fread(rbufp, byte_cnt, 1, fcb->__io_fp) != 1) return __io_errno(); } else { /* sequential read */ @@ -1624,9 +1625,9 @@ read_record(void) while (TRUE) { if (byte_cnt >= rbuf_size) p = alloc_rbuf(byte_cnt, TRUE); - ch = __io_fgetc(fcb->fp); + FIO_FCB_BUFFERED_GETC(ch, fcb, return __io_errno()); if (ch == EOF) { - if (__io_feof(fcb->fp)) { + if (__io_feof(fcb->__io_fp)) { if (byte_cnt) break; return FIO_EEOF; @@ -1634,10 +1635,10 @@ read_record(void) return __io_errno(); } if (ch == '\r' && EOR_CRLF) { - ch = __io_fgetc(fcb->fp); + FIO_FCB_BUFFERED_GETC(ch, fcb, return __io_errno()); if (ch == '\n') break; - __io_ungetc(ch, fcb->fp); + FIO_FCB_BUFFERED_UNGETC(ch, fcb); ch = '\r'; } if (ch == '\n') @@ -1699,8 +1700,7 @@ skip_record(void) if (fcb->acc == FIO_DIRECT) { if (fcb->nextrec > fcb->maxrec + 1) return FIO_EDREAD; /* attempt to read non-existent rec */ - if (__io_fseek(fcb->fp, (seekoffx_t)rec_len, SEEK_CUR) != 0) - return __io_errno(); + FIO_FCB_FSEEK_CUR(fcb, (seekoffx_t)rec_len, return __io_errno()); fcb->coherent = 0; } else { /* sequential read */ @@ -1708,9 +1708,9 @@ skip_record(void) int bt = 0; while (TRUE) { - ch = __io_fgetc(fcb->fp); + FIO_FCB_BUFFERED_GETC(ch, fcb, return __io_errno()); if (ch == EOF) { - if (__io_feof(fcb->fp)) { + if (__io_feof(fcb->__io_fp)) { if (bt) break; return FIO_EEOF; @@ -1719,10 +1719,10 @@ skip_record(void) } #if defined(WINNT) if (ch == '\r') { - ch = __io_fgetc(fcb->fp); + FIO_FCB_BUFFERED_GETC(ch, fcb, return __io_errno()); if (ch == '\n') break; - __io_ungetc(ch, fcb->fp); + FIO_FCB_BUFFERED_UNGETC(ch, fcb); ch = '\r'; } #endif diff --git a/runtime/flang/ldwrite.c b/runtime/flang/ldwrite.c index 24018624a35..a0e4df86241 100644 --- a/runtime/flang/ldwrite.c +++ b/runtime/flang/ldwrite.c @@ -815,30 +815,35 @@ write_item(char *p, int len) in_curp += len; } else { /* external file */ if (byte_cnt == 0) { /* prepend a blank to a new record */ - if (FWRITE(" ", 1, 1, fcb->fp) != 1) + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __io_errno()); + if (FWRITE(" ", 1, 1, fcb->__io_fp) != 1) return __io_errno(); newlen++; } if (fcb->acc == FIO_DIRECT) { if (newlen > rec_len) return FIO_ETOOBIG; - if (len && FWRITE(p, len, 1, fcb->fp) != 1) - return __io_errno(); + if (len) { + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __io_errno()); + if (FWRITE(p, len, 1, fcb->__io_fp) != 1) + return __io_errno(); + } } else { /* sequential write */ /* split lines if necessary; watch for the case where a long character item is the first item for the record. */ + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __io_errno()); if (byte_cnt && ((fcb->reclen && newlen > fcb->reclen) || (!fcb->reclen && newlen > 79))) { ret_err = write_record(); if (ret_err) return ret_err; - if (FWRITE(" ", 1, 1, fcb->fp) != 1) + if (FWRITE(" ", 1, 1, fcb->__io_fp) != 1) return __io_errno(); newlen = len + 1; record_written = FALSE; } - if (len && FWRITE(p, len, 1, fcb->fp) != 1) + if (len && FWRITE(p, len, 1, fcb->__io_fp) != 1) return __io_errno(); } } @@ -870,21 +875,23 @@ write_record(void) int j, n; pad = rec_len - byte_cnt; n = pad / BL_BUFSZ; + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __io_errno()); for (j = 0; j < n; j++) - if (FWRITE(BL_BUF, BL_BUFSZ, 1, fcb->fp) != 1) + if (FWRITE(BL_BUF, BL_BUFSZ, 1, fcb->__io_fp) != 1) return __io_errno(); if ((j = pad - (n * BL_BUFSZ)) != 0) - if (FWRITE(BL_BUF, j, 1, fcb->fp) != 1) + if (FWRITE(BL_BUF, j, 1, fcb->__io_fp) != 1) return __io_errno(); } } else { /* sequential write: append carriage return */ + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __io_errno()); #if defined(WINNT) - if (__fortio_binary_mode(fcb->fp)) - if (FWRITE("\r", 1, 1, fcb->fp) != 1) + if (__fortio_binary_mode(fcb->__io_fp)) + if (FWRITE("\r", 1, 1, fcb->__io_fp) != 1) return __io_errno(); #endif - if (FWRITE("\n", 1, 1, fcb->fp) != 1) + if (FWRITE("\n", 1, 1, fcb->__io_fp) != 1) return __io_errno(); } ++(fcb->nextrec); @@ -919,7 +926,8 @@ _f90io_ldw_end() if (fcb->nonadvance) { fcb->nonadvance = FALSE; } else { - if (FWRITE(" ", 1, 1, fcb->fp) != 1) + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return __fortio_error(__io_errno())); + if (FWRITE(" ", 1, 1, fcb->__io_fp) != 1) return __fortio_error(__io_errno()); byte_cnt = 1; record_written = FALSE; diff --git a/runtime/flang/nmlread.c b/runtime/flang/nmlread.c index 1128bcbe627..bd1f2fdfe3f 100644 --- a/runtime/flang/nmlread.c +++ b/runtime/flang/nmlread.c @@ -209,7 +209,8 @@ _f90io_nmlr_init(__INT_T *unit, } f->skip = 0; - gblfp = f->fp; + FIO_FCB_INVALIDATE_GETC_BUFFER_FULLY(f, return ERR_FLAG); + gblfp = f->__io_fp; internal_file = FALSE; gbl->decimal = f->decimal; gbl->unit = unit; @@ -2180,12 +2181,13 @@ read_record(void) p = rbufp; byte_cnt = 0; + FIO_FCB_INVALIDATE_GETC_BUFFER_FULLY(f, return __io_errno()); while (TRUE) { if (byte_cnt >= rbuf_size) p = alloc_rbuf(byte_cnt, TRUE); - ch = __io_fgetc(f->fp); + ch = __io_fgetc(f->__io_fp); if (ch == EOF) { - if (__io_feof(f->fp)) { + if (__io_feof(f->__io_fp)) { if (byte_cnt) break; return FIO_EEOF; @@ -2193,10 +2195,10 @@ read_record(void) return __io_errno(); } if (ch == '\r' && EOR_CRLF) { - ch = __io_fgetc(f->fp); + ch = __io_fgetc(f->__io_fp); if (ch == '\n') break; - __io_ungetc(ch, f->fp); + __io_ungetc(ch, f->__io_fp); ch = '\r'; } if (ch == '\n') diff --git a/runtime/flang/nmlwrite.c b/runtime/flang/nmlwrite.c index 4612228bf39..d97249e90ef 100644 --- a/runtime/flang/nmlwrite.c +++ b/runtime/flang/nmlwrite.c @@ -324,7 +324,7 @@ emit_eol(void) if (!internal_file) { #if defined(WINNT) - if (__fortio_binary_mode(f->fp)) { + if (__fortio_binary_mode(f->__io_fp)) { ret_err = write_char('\r'); if (ret_err) return ret_err; @@ -508,7 +508,8 @@ write_item(char *p, int len) __io_printf("write_item #%s#, len %d\n", p, len); if (!internal_file) { - if (len && FWRITE(p, len, 1, f->fp) != 1) + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + if (len && FWRITE(p, len, 1, f->__io_fp) != 1) return __io_errno(); return 0; } diff --git a/runtime/flang/open.c b/runtime/flang/open.c index d12c3e9b83c..7d038411d6a 100644 --- a/runtime/flang/open.c +++ b/runtime/flang/open.c @@ -38,6 +38,16 @@ static FIO_FCB *Fcb; /* pointer to the file control block */ int next_newunit = -13; +#define IO_BUFFERS 24 +static struct { + char io_buffer[FIO_FCB_IO_BUFFSIZE]; + char getc_buffer[FIO_FCB_GETC_BUFFSIZE]; +} io_buffers[IO_BUFFERS]; /* io_buffers are indexed by file decriptor IDs + * that are global across all threads of the + * process; only first IO_BUFFERS file IDs are + * buffered. + */ + /* --------------------------------------------------------------------- */ int ENTF90IO(GET_NEWUNIT, get_newunit)() @@ -139,9 +149,11 @@ __fortio_open(int unit, int action_flag, int status_flag, int dispose_flag, f->blank = blank_flag; if (pos_flag == FIO_REWIND) { - __io_fseek(f->fp, (seekoffx_t)0L, SEEK_SET); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + __io_fseek(f->__io_fp, (seekoffx_t)0L, SEEK_SET); } else if (pos_flag == FIO_APPEND) { - __io_fseek(f->fp, (seekoffx_t)0L, SEEK_END); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + __io_fseek(f->__io_fp, (seekoffx_t)0L, SEEK_END); } f->reclen = reclen * f->wordlen; @@ -241,8 +253,21 @@ __fortio_open(int unit, int action_flag, int status_flag, int dispose_flag, ***************************************************************/ f = __fortio_alloc_fcb(); + assert(f); + if (lcl_fp) { + fd = fileno(lcl_fp); + if (fd < 0) + goto free_fcb_err; + fd -= 3; /* we don't handle stdin, stdout and stderr */ + if ((fd >= 0) && (fd < IO_BUFFERS)) { + if (setvbuf(lcl_fp, io_buffers[fd].io_buffer, _IOFBF, FIO_FCB_IO_BUFFSIZE)) + goto free_fcb_err; + f->getc_buffer = io_buffers[fd].getc_buffer; + f->getc_buffer_notuse = FALSE; + } + } - f->fp = lcl_fp; + f->__io_fp = lcl_fp; assert(lcl_fp != NULL); f->unit = unit; f->action = action_flag; @@ -290,7 +315,7 @@ __fortio_open(int unit, int action_flag, int status_flag, int dispose_flag, if ((status_flag == FIO_OLD || status_flag == FIO_UNKNOWN) && pos_flag != FIO_APPEND) f->truncflag = TRUE; - if (status_flag != FIO_SCRATCH && __fortio_ispipe(f->fp)) { + if (status_flag != FIO_SCRATCH && __fortio_ispipe(f->__io_fp)) { f->truncflag = FALSE; f->ispipe = TRUE; } else if (pos_flag == FIO_APPEND) /* position file at end of file */ @@ -1080,7 +1105,8 @@ ENTF90IO(OPEN_ASYNCA, open_asynca)(__INT_T *istat, DCHAR(asy) DCLEN64(asy)) || Fcb->acc == FIO_DIRECT) && (!Fcb->byte_swap)) { - if (Fio_asy_open(Fcb->fp, &Fcb->asyptr) == -1) { + FIO_FCB_INVALIDATE_GETC_BUFFER_FULLY(Fcb, return __fortio_error(__io_errno())); + if (Fio_asy_open(Fcb->__io_fp, &Fcb->asyptr) == -1) { retval = __fortio_error(__io_errno()); } } diff --git a/runtime/flang/rewind.c b/runtime/flang/rewind.c index 2629532c95e..ef09df4be2d 100644 --- a/runtime/flang/rewind.c +++ b/runtime/flang/rewind.c @@ -50,20 +50,22 @@ _f90io_rewind(__INT_T *unit, __INT_T *bitv, __INT_T *iostat) } } + FIO_FCB_INVALIDATE_GETC_BUFFER(f, return __io_errno()); + /* append carriage return (maybe) */ if (f->nonadvance) { f->nonadvance = FALSE; #if defined(WINNT) - if (__fortio_binary_mode(f->fp)) - __io_fputc('\r', f->fp); + if (__fortio_binary_mode(f->__io_fp)) + __io_fputc('\r', f->__io_fp); #endif - __io_fputc('\n', f->fp); - if (__io_ferror(f->fp)) + __io_fputc('\n', f->__io_fp); + if (__io_ferror(f->__io_fp)) return __io_errno(); } - if (__io_fseek(f->fp, 0L, SEEK_SET) != 0) + if (__io_fseek(f->__io_fp, 0L, SEEK_SET) != 0) return __fortio_error(__io_errno()); f->nextrec = 1; diff --git a/runtime/flang/unf.c b/runtime/flang/unf.c index 3a35788e667..b3cd989989d 100644 --- a/runtime/flang/unf.c +++ b/runtime/flang/unf.c @@ -146,10 +146,11 @@ adjust_fpos(FIO_FCB *cur_file, long offset, int whence) { int retval; + FIO_FCB_INVALIDATE_GETC_BUFFER(cur_file, return -1); if (cur_file->asy_rw) { Fio_asy_fseek(cur_file->asyptr, offset, whence); } else { - retval = __io_fseek(cur_file->fp, offset, whence); + retval = __io_fseek(cur_file->__io_fp, offset, whence); } return retval; } @@ -241,12 +242,13 @@ write_unf_buf() static bool unf_fwrite(char *buf, size_t size, size_t num, FIO_FCB *fcb) { + FIO_FCB_INVALIDATE_GETC_BUFFER(fcb, return FALSE); if (fcb->asy_rw) { /* Do this write asynchronously. */ return (Fio_asy_write(fcb->asyptr, buf, size * num) == 0); } else { /* Do this write "normally." */ - return (FWRITE(buf, size, num, fcb->fp) == num); + return (FWRITE(buf, size, num, fcb->__io_fp) == num); } return FALSE; } @@ -373,8 +375,9 @@ __unf_init(bool read, bool byte_swap) /* sequential access - read reclen word */ if (!continued) Fcb->nextrec++; - if (__io_fread(&rec_len, RCWSZ, 1, Fcb->fp) != 1) { - if (__io_feof(Fcb->fp)) + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + if (__io_fread(&rec_len, RCWSZ, 1, Fcb->__io_fp) != 1) { + if (__io_feof(Fcb->__io_fp)) UNF_ERR(FIO_EEOF); UNF_ERR(__io_errno()); } @@ -507,8 +510,9 @@ __f90io_unf_read(int type, /* Type of data */ } return (0); } - if (__io_fread(item, nbytes, 1, Fcb->fp) != 1) { - if (__io_feof(Fcb->fp)) { + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(FIO_EDREAD); goto unfr_err; }); + if (__io_fread(item, nbytes, 1, Fcb->__io_fp) != 1) { + if (__io_feof(Fcb->__io_fp)) { ret_val = __fortio_error(FIO_EEOF); if (Fcb->partial) { Fcb->partial = 0; @@ -539,6 +543,7 @@ __f90io_unf_read(int type, /* Type of data */ /* copy 'length' items from stream into 'item', skipping by 'stride' */ + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(FIO_EDREAD); goto unfr_err; }); while (nbytes > 0) { int read_length; @@ -547,8 +552,8 @@ __f90io_unf_read(int type, /* Type of data */ bytes needed to fill the item (item_length - offset) */ read_length = (nbytes < item_length - offset ? nbytes : item_length - offset); - if (__io_fread(item + offset, read_length, 1, Fcb->fp) != 1) { - if (__io_feof(Fcb->fp)) + if (__io_fread(item + offset, read_length, 1, Fcb->__io_fp) != 1) { + if (__io_feof(Fcb->__io_fp)) ret_val = __fortio_error(FIO_EEOF); else ret_val = __fortio_error(__io_errno()); @@ -1179,12 +1184,11 @@ __unf_end(bool to_be_continued) * this only happens if we have a READ statement without any * items. */ - if (Fcb->acc != FIO_DIRECT) - ret_err = __io_fseek(Fcb->fp, (seekoffx_t)rec_len + RCWSZ, SEEK_CUR); - else - ret_err = __io_fseek(Fcb->fp, (seekoffx_t)rec_len, SEEK_CUR); - if (ret_err) - UNF_ERR(__io_errno()); + if (Fcb->acc != FIO_DIRECT) { + FIO_FCB_FSEEK_CUR(Fcb, (seekoffx_t)rec_len + RCWSZ, UNF_ERR(__io_errno())); + } else { + FIO_FCB_FSEEK_CUR(Fcb, (seekoffx_t)rec_len, UNF_ERR(__io_errno())); + } Fcb->coherent = 0; return 0; } @@ -1198,14 +1202,15 @@ __unf_end(bool to_be_continued) continue flags. */ if (to_be_continued) return 0; + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); while (continued) { - if (__io_fread(&rec_len, 4, 1, Fcb->fp) != 1) + if (__io_fread(&rec_len, 4, 1, Fcb->__io_fp) != 1) UNF_ERR(__io_errno()); if (!f90_old_huge_rec_fmt()) { - if (__io_fseek(Fcb->fp, -rec_len + 4, SEEK_CUR)) + if (__io_fseek(Fcb->__io_fp, -rec_len + 4, SEEK_CUR)) continued = (rec_len < 0); } else { - if (__io_fseek(Fcb->fp, (rec_len &= ~CONT_FLAG) + 4, SEEK_CUR)) + if (__io_fseek(Fcb->__io_fp, (rec_len &= ~CONT_FLAG) + 4, SEEK_CUR)) continued = (rec_len & CONT_FLAG); } UNF_ERR(__io_errno()); @@ -1223,7 +1228,8 @@ __unf_end(bool to_be_continued) if (Fcb->acc != FIO_DIRECT) { /* write 0 length record */ if (Fcb->binary) return 0; - ret_err = __fortio_zeropad(Fcb->fp, RCWSZ << 1); + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + ret_err = __fortio_zeropad(Fcb->__io_fp, RCWSZ << 1); if (ret_err != 0) UNF_ERR(ret_err); return 0; @@ -1294,7 +1300,8 @@ __unf_end(bool to_be_continued) UNF_ERR(__io_errno()); } else if (Fcb->reclen > unf_rec.u.s.bytecnt) { /* pad record for direct-access file: */ - ret_err = __fortio_zeropad(Fcb->fp, Fcb->reclen - unf_rec.u.s.bytecnt); + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + ret_err = __fortio_zeropad(Fcb->__io_fp, Fcb->reclen - unf_rec.u.s.bytecnt); if (ret_err != 0) UNF_ERR(ret_err); } @@ -1320,9 +1327,7 @@ skip_to_nextrec(void) } } else if (unf_rec.u.s.bytecnt < rec_len) { Fcb->coherent = 0; - if (__io_fseek(Fcb->fp, (seekoffx_t)(rec_len - unf_rec.u.s.bytecnt), - SEEK_CUR) != 0) - return (__io_errno()); + FIO_FCB_FSEEK_CUR(Fcb, (seekoffx_t)(rec_len - unf_rec.u.s.bytecnt), return __io_errno()); } return 0; } @@ -1486,8 +1491,9 @@ __f90io_usw_read(int type, /* Type of data */ /* read directly into item if possible (consecutive items) */ if (stride == item_length) { - if (__io_fread(item_ptr, nbytes, 1, Fcb->fp) != 1) { - if (__io_feof(Fcb->fp)) + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(__io_errno()); goto uswr_err; }); + if (__io_fread(item_ptr, nbytes, 1, Fcb->__io_fp) != 1) { + if (__io_feof(Fcb->__io_fp)) ret_val = __fortio_error(FIO_EEOF); else ret_val = __fortio_error(__io_errno()); @@ -1521,6 +1527,7 @@ __f90io_usw_read(int type, /* Type of data */ /* copy 'count' items from stream into 'item', skipping by 'stride' */ + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(__io_errno()); goto uswr_err; }); while (nbytes > 0) { int read_length; @@ -1529,8 +1536,8 @@ __f90io_usw_read(int type, /* Type of data */ bytes needed to fill the item (item_length - offset) */ read_length = (nbytes < item_length - offset ? nbytes : item_length - offset); - if (__io_fread(item + offset, read_length, 1, Fcb->fp) != 1) { - if (__io_feof(Fcb->fp)) + if (__io_fread(item + offset, read_length, 1, Fcb->__io_fp) != 1) { + if (__io_feof(Fcb->__io_fp)) ret_val = __fortio_error(FIO_EEOF); else ret_val = __fortio_error(__io_errno()); @@ -1743,7 +1750,8 @@ __f90io_usw_write(int type, /* data type of data (see above). */ if (!Fcb->binary) { bs_tmp = unf_rec.u.s.bytecnt + nbytes; __fortio_swap_bytes((char *)&bs_tmp, __INT, 1); - if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->fp)) != 1) { + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(__io_errno()); goto unf_write_err; }); + if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->__io_fp)) != 1) { ret_val = __fortio_error(__io_errno()); goto unf_write_err; } @@ -1797,7 +1805,8 @@ __f90io_usw_write(int type, /* data type of data (see above). */ if (!Fcb->binary) { bs_tmp = unf_rec.u.s.bytecnt; __fortio_swap_bytes((char *)&bs_tmp, __INT, 1); - if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->fp)) != 1) { + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(__io_errno()); goto unf_write_err; }); + if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->__io_fp)) != 1) { ret_val = __fortio_error(__io_errno()); goto unf_write_err; } @@ -1842,7 +1851,8 @@ __f90io_usw_write(int type, /* data type of data (see above). */ return __fortio_error(FIO_ENOMEM); (void) memcpy(pp, item, item_length); __fortio_swap_bytes(pp, type, item_length >> 1); - if ((FWRITE(pp, item_length, 1, Fcb->fp)) != 1) { + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, { ret_val = __fortio_error(__io_errno()); goto unf_write_err; }); + if ((FWRITE(pp, item_length, 1, Fcb->__io_fp)) != 1) { ret_val = __fortio_error(__io_errno()); goto unf_write_err; } @@ -2021,12 +2031,11 @@ __usw_end(bool to_be_continued) * this only happens if we have a READ statement without any * items. */ - if (Fcb->acc != FIO_DIRECT) - ret_err = __io_fseek(Fcb->fp, (seekoffx_t)rec_len + RCWSZ, SEEK_CUR); - else - ret_err = __io_fseek(Fcb->fp, (seekoffx_t)rec_len, SEEK_CUR); - if (ret_err) - UNF_ERR(__io_errno()); + if (Fcb->acc != FIO_DIRECT) { + FIO_FCB_FSEEK_CUR(Fcb, (seekoffx_t)rec_len + RCWSZ, UNF_ERR(__io_errno())); + } else { + FIO_FCB_FSEEK_CUR(Fcb, (seekoffx_t)rec_len, UNF_ERR(__io_errno())); + } Fcb->coherent = 0; return 0; } @@ -2040,17 +2049,18 @@ __usw_end(bool to_be_continued) continue flags. */ if (to_be_continued) return 0; + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); while (continued) { - if (__io_fread(&rec_len, 4, 1, Fcb->fp) != 1) + if (__io_fread(&rec_len, 4, 1, Fcb->__io_fp) != 1) UNF_ERR(__io_errno()); __fortio_swap_bytes((char *)&rec_len, __INT, 1); if (!f90_old_huge_rec_fmt()) { - if (__io_fseek(Fcb->fp, -rec_len + 4, SEEK_CUR)) { + if (__io_fseek(Fcb->__io_fp, -rec_len + 4, SEEK_CUR)) { UNF_ERR(__io_errno()); } continued = (rec_len < 0); } else { - if (__io_fseek(Fcb->fp, (rec_len &= ~CONT_FLAG) + 4, SEEK_CUR)) { + if (__io_fseek(Fcb->__io_fp, (rec_len &= ~CONT_FLAG) + 4, SEEK_CUR)) { UNF_ERR(__io_errno()); } continued = (rec_len & CONT_FLAG); @@ -2069,7 +2079,8 @@ __usw_end(bool to_be_continued) if (Fcb->acc != FIO_DIRECT) { /* write 0 length record */ if (Fcb->binary) return 0; - ret_err = __fortio_zeropad(Fcb->fp, RCWSZ << 1); + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + ret_err = __fortio_zeropad(Fcb->__io_fp, RCWSZ << 1); if (ret_err != 0) UNF_ERR(ret_err); return 0; @@ -2085,11 +2096,12 @@ __usw_end(bool to_be_continued) } bs_tmp = unf_rec.u.s.bytecnt; __fortio_swap_bytes((char *)&bs_tmp, __INT, 1); - if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->fp)) != 1) + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->__io_fp)) != 1) UNF_ERR(__io_errno()); if (WRITE_UNF_BUF) UNF_ERR(__io_errno()); - if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->fp)) != 1) + if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->__io_fp)) != 1) UNF_ERR(__io_errno()); return 0; } @@ -2108,14 +2120,15 @@ __usw_end(bool to_be_continued) __fortio_swap_bytes((char *)&bs_tmp, __INT, 1); if (unf_rec.u.s.bcnt != unf_rec.u.s.bytecnt || to_be_continued) { /* seek to record's beginning length word */ - if (__io_fseek(Fcb->fp, + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + if (__io_fseek(Fcb->__io_fp, (seekoffx_t)(-unf_rec.u.s.bytecnt) - (seekoffx_t)(RCWSZ), SEEK_CUR) != 0) UNF_ERR(__io_errno()); /* write record length at beginning of record */ - if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->fp)) != 1) + if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->__io_fp)) != 1) UNF_ERR(__io_errno()); - if (__io_fseek(Fcb->fp, (seekoffx_t)unf_rec.u.s.bytecnt, SEEK_CUR) != 0) + if (__io_fseek(Fcb->__io_fp, (seekoffx_t)unf_rec.u.s.bytecnt, SEEK_CUR) != 0) UNF_ERR(__io_errno()); if (to_be_continued && !continued) { bs_tmp = f90_old_huge_rec_fmt() ? -bs_tmp : bs_tmp & ~CONT_FLAG_SW; @@ -2127,11 +2140,12 @@ __usw_end(bool to_be_continued) bs_tmp = f90_old_huge_rec_fmt() ? bs_tmp : (bs_tmp | CONT_FLAG_SW); continued = to_be_continued; /* write record length at end of record */ - if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->fp)) != 1) + FIO_FCB_INVALIDATE_GETC_BUFFER(Fcb, UNF_ERR(__io_errno())); + if ((FWRITE(&bs_tmp, RCWSZ, 1, Fcb->__io_fp)) != 1) UNF_ERR(__io_errno()); } else if (Fcb->reclen > unf_rec.u.s.bytecnt) { /* pad record for direct-access file: */ - ret_err = __fortio_zeropad(Fcb->fp, Fcb->reclen - unf_rec.u.s.bytecnt); + ret_err = __fortio_zeropad(Fcb->__io_fp, Fcb->reclen - unf_rec.u.s.bytecnt); if (ret_err != 0) UNF_ERR(ret_err); } diff --git a/runtime/flang/utils.c b/runtime/flang/utils.c index c9a199aaa4b..1492ea09c93 100644 --- a/runtime/flang/utils.c +++ b/runtime/flang/utils.c @@ -66,7 +66,8 @@ __fortio_fiofcb_stdunit(FIO_FCB *f) extern FILE * __fortio_fiofcb_fp(FIO_FCB *f) { - return f->fp; + FIO_FCB_INVALIDATE_GETC_BUFFER_FULLY(f, return NULL); + return f->__io_fp; } extern short @@ -116,6 +117,8 @@ __fortio_alloc_fcb(void) } memset(p, 0, sizeof(FIO_FCB)); + p->getc_bufpos = -1; + p->getc_buffer_notuse = TRUE; p[0].next = fioFcbTbls.fcbs; /* add new FCB to front of list */ fioFcbTbls.fcbs = p; return p; @@ -212,7 +215,8 @@ extern FIO_FCB *__fortio_rwinit( --pos; else ERR(FIO_EPOSV); - if (__io_fseek(f->fp, (seekoffx_t)pos, SEEK_SET) != 0) + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, (seekoffx_t)pos, SEEK_SET) != 0) ERR(__io_errno()); f->coherent = 0; } @@ -241,7 +245,8 @@ extern FIO_FCB *__fortio_rwinit( --pos; else ERR(FIO_EPOSV); - if (__io_fseek(f->fp, (seekoffx_t)pos, SEEK_SET) != 0) + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, (seekoffx_t)pos, SEEK_SET) != 0) ERR(__io_errno()); f->coherent = 0; f->eof_flag = FALSE; /* clear it for the ensuing test */ @@ -275,14 +280,16 @@ extern FIO_FCB *__fortio_rwinit( seekoffx_t len; seekoffx_t sav_pos; - sav_pos = __io_ftell(f->fp); - if (__io_fseek(f->fp, (seekoffx_t)0, SEEK_END) != 0) + sav_pos = FIO_FCB_FTELL(f); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, (seekoffx_t)0, SEEK_END) != 0) ERR(__io_errno()); - len = __io_ftell(f->fp); + len = FIO_FCB_FTELL(f); f->partial = len % f->reclen; if (form == FIO_UNFORMATTED && f->partial) { /* allow read of partial record */ - if (__io_fseek(f->fp, sav_pos, SEEK_SET) != 0) + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, sav_pos, SEEK_SET) != 0) ERR(__io_errno()); } else { @@ -298,7 +305,7 @@ extern FIO_FCB *__fortio_rwinit( /* We recovered, so seek to the right point */ pos = f->reclen * (rec - 1); - if (__io_fseek(f->fp, (seekoffx_t)pos, SEEK_SET) != 0) + if (__io_fseek(f->__io_fp, (seekoffx_t)pos, SEEK_SET) != 0) ERR(__io_errno()); f->coherent = 0; } @@ -315,21 +322,24 @@ extern FIO_FCB *__fortio_rwinit( */ if (rec > f->maxrec + 1) { seekoffx_t len; - if (__io_fseek(f->fp, 0L, SEEK_END) != 0) + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, 0L, SEEK_END) != 0) ERR(__io_errno()); - len = __io_ftell(f->fp); + len = FIO_FCB_FTELL(f); f->maxrec = len / f->reclen; } /* Now go to next if-check with recomputed maxrec */ if (rec <= f->maxrec + 1) { pos = f->reclen * (rec - 1); - if (__io_fseek(f->fp, (seekoffx_t)pos, SEEK_SET) != 0) + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, (seekoffx_t)pos, SEEK_SET) != 0) ERR(__io_errno()); f->coherent = 0; } else { /* pad with (rec-maxrec-1)*reclen bytes: */ seekoffx_t bb = (rec - f->maxrec - 1) * f->reclen; + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); /* * It has been reported that extending the file by writing * to the file is very slow when the number of bytes is @@ -338,19 +348,19 @@ extern FIO_FCB *__fortio_rwinit( * complete the padding by writing a single byte. A write * is necessary after the fseek to ensure that the file's * physical size is increased. - if (__io_fseek(f->fp, 0L, SEEK_END) != 0) + if (__io_fseek(f->__io_fp, 0L, SEEK_END) != 0) ERR(__io_errno()); errflag = - __fortio_zeropad(f->fp, (rec-f->maxrec-1) * f->reclen); + __fortio_zeropad(f->__io_fp, (rec-f->maxrec-1) * f->reclen); */ /* With multiple writers, there is a chance that this could clobber a byte of data, but a very small chance now that we've added the recomputation of f->maxrec above */ - if (__io_fseek(f->fp, (seekoffx_t)(bb - 1), SEEK_END) != 0) + if (__io_fseek(f->__io_fp, (seekoffx_t)(bb - 1), SEEK_END) != 0) ERR(__io_errno()); - errflag = __fortio_zeropad(f->fp, 1); + errflag = __fortio_zeropad(f->__io_fp, 1); if (errflag != 0) ERR(errflag); f->coherent = 1; @@ -377,13 +387,15 @@ extern FIO_FCB *__fortio_rwinit( if (rec_specified) ERR(FIO_ECOMPAT); if (optype != 0 && f->truncflag) { - pos = __io_ftell(f->fp); - if (__io_fseek(f->fp, 0L, SEEK_END) != 0) + pos = FIO_FCB_FTELL(f); + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, 0L, SEEK_END) != 0) ERR(__io_errno()); f->coherent = 0; /* if not currently positioned at end of file, need to trunc: */ - if (pos != __io_ftell(f->fp)) { - if (__io_fseek(f->fp, (seekoffx_t)pos, SEEK_SET) != 0) + if (pos != FIO_FCB_FTELL(f)) { + FIO_FCB_INVALIDATE_GETC_BUFFER_BEFORE_FSEEK(f); + if (__io_fseek(f->__io_fp, (seekoffx_t)pos, SEEK_SET) != 0) ERR(__io_errno()); errflag = __fortio_trunc(f, pos); if (errflag != 0) @@ -397,7 +409,7 @@ extern FIO_FCB *__fortio_rwinit( f->nextrec = 1; if (f->coherent == 1) /* last operation was a write */ - fflush(f->fp); + fflush(f->__io_fp); f->coherent = 0; f->skip = 0; return f; @@ -415,7 +427,7 @@ extern FIO_FCB *__fortio_rwinit( if (optype != 2) { if (f->coherent && (f->coherent != 2 - optype)) { - (void)__io_fseek(f->fp, 0L, SEEK_CUR); + FIO_FCB_FSEEK_CUR(f, 0L, { }); f->skip = 0; } f->coherent = 2 - optype; /* write ==> 1, read ==> 2*/ @@ -580,8 +592,9 @@ void __fortio_swap_bytes( static int __fortio_trunc(FIO_FCB *p, seekoffx_t length) { - __io_fflush(p->fp); - if (ftruncate(__fort_getfd(p->fp), length)) + FIO_FCB_INVALIDATE_GETC_BUFFER(p, return __fortio_error(__io_errno())); + __io_fflush(p->__io_fp); + if (ftruncate(__fort_getfd(p->__io_fp), length)) return __fortio_error(__io_errno()); if (length == 0) { /*