diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -235,6 +235,7 @@ if (unit.access == Access::Sequential && !unit.isFixedRecordLength) { // Create space for (sub)record header to be completed by // UnformattedIoStatementState::EndIoStatement() + unit.recordLength.reset(); // in case of prior BACKSPACE io.Emit("\0\0\0\0", 4); // placeholder for record length header } } diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -132,16 +132,17 @@ static_cast(*totalBytes)); } } + endfileRecordNumber.reset(); + currentRecordNumber = 1; + if (totalBytes && recordLength && *recordLength) { + endfileRecordNumber = 1 + (*totalBytes / *recordLength); + } if (position == Position::Append) { - if (totalBytes && recordLength && *recordLength) { - endfileRecordNumber = 1 + (*totalBytes / *recordLength); - } else { + if (!endfileRecordNumber) { // Fake it so that we can backspace relative from the end - endfileRecordNumber = std::numeric_limits::max() - 1; + endfileRecordNumber = std::numeric_limits::max() - 2; } currentRecordNumber = *endfileRecordNumber; - } else { - currentRecordNumber = 1; } } @@ -374,7 +375,9 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) { RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_); beganReadingRecord_ = false; - if (access == Access::Sequential) { + if (handler.GetIoStat() != IostatOk) { + // avoid bogus crashes in END/ERR circumstances + } else if (access == Access::Sequential) { RUNTIME_CHECK(handler, recordLength.has_value()); if (isFixedRecordLength) { frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; @@ -430,16 +433,22 @@ handler.SignalError(IostatBackspaceNonSequential, "BACKSPACE(UNIT=%d) on non-sequential file", unitNumber()); } else { - DoImpliedEndfile(handler); - --currentRecordNumber; - BeginRecord(); - if (isFixedRecordLength) { - BackspaceFixedRecord(handler); - } else if (isUnformatted) { - BackspaceVariableUnformattedRecord(handler); + if (endfileRecordNumber && currentRecordNumber > *endfileRecordNumber) { + // BACKSPACE after ENDFILE } else { - BackspaceVariableFormattedRecord(handler); + DoImpliedEndfile(handler); + if (frameOffsetInFile_ + recordOffsetInFrame_ > 0) { + --currentRecordNumber; + if (isFixedRecordLength) { + BackspaceFixedRecord(handler); + } else if (isUnformatted) { + BackspaceVariableUnformattedRecord(handler); + } else { + BackspaceVariableFormattedRecord(handler); + } + } } + BeginRecord(); } } @@ -456,8 +465,12 @@ } else if (!mayWrite()) { handler.SignalError(IostatEndfileUnwritable, "ENDFILE(UNIT=%d) on read-only file", unitNumber()); + } else if (endfileRecordNumber && + currentRecordNumber > *endfileRecordNumber) { + // ENDFILE after ENDFILE } else { DoEndfile(handler); + ++currentRecordNumber; } } @@ -469,7 +482,6 @@ DoImpliedEndfile(handler); SetPosition(0); currentRecordNumber = 1; - // TODO: reset endfileRecordNumber? } }