diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -65,6 +65,7 @@ ExternalFileUnit *GetExternalFileUnit() const; // null if internal unit MutableModes &mutableModes(); void BeginReadingRecord(); + void FinishReadingRecord(); bool Inquire(InquiryKeywordHash, char *, std::size_t); bool Inquire(InquiryKeywordHash, bool &); bool Inquire(InquiryKeywordHash, std::int64_t, bool &); // PENDING= @@ -123,7 +124,7 @@ std::optional GetNextDataEdit(IoStatementState &, int = 1); ExternalFileUnit *GetExternalFileUnit() const { return nullptr; } void BeginReadingRecord() {} - + void FinishReadingRecord() {} bool Inquire(InquiryKeywordHash, char *, std::size_t); bool Inquire(InquiryKeywordHash, bool &); bool Inquire(InquiryKeywordHash, std::int64_t, bool &); @@ -269,9 +270,7 @@ void HandleRelativePosition(std::int64_t); void HandleAbsolutePosition(std::int64_t); void BeginReadingRecord(); - -private: - bool beganReading_{false}; + void FinishReadingRecord(); }; template diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -236,11 +236,13 @@ template int ExternalIoStatementState::EndIoStatement() { if constexpr (DIR == Direction::Input) { BeginReadingRecord(); // in case of READ with no data items - } - if (!unit().nonAdvancing && GetIoStat() != IostatEnd) { - unit().AdvanceRecord(*this); - } - if constexpr (DIR == Direction::Output) { + if (!unit().nonAdvancing) { + FinishReadingRecord(); + } + } else { + if (!unit().nonAdvancing) { + unit().AdvanceRecord(*this); + } unit().FlushIfTerminal(*this); } return ExternalIoStatementBase::EndIoStatement(); @@ -315,10 +317,20 @@ template void ExternalIoStatementState::BeginReadingRecord() { if constexpr (DIR == Direction::Input) { - if (!beganReading_) { - beganReading_ = true; - unit().BeginReadingRecord(*this); - } + unit().BeginReadingRecord(*this); + } else { + Crash("ExternalIoStatementState::BeginReadingRecord() " + "called"); + } +} + +template +void ExternalIoStatementState::FinishReadingRecord() { + if constexpr (DIR == Direction::Input) { + unit().FinishReadingRecord(*this); + } else { + Crash("ExternalIoStatementState::FinishReadingRecord() " + "called"); } } diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -78,6 +78,7 @@ std::optional GetCurrentChar(IoErrorHandler &); void SetLeftTabLimit(); void BeginReadingRecord(IoErrorHandler &); + void FinishReadingRecord(IoErrorHandler &); bool AdvanceRecord(IoErrorHandler &); void BackspaceRecord(IoErrorHandler &); void FlushIfTerminal(IoErrorHandler &); @@ -105,6 +106,7 @@ int unitNumber_{-1}; Direction direction_{Direction::Output}; bool impliedEndfile_{false}; // seq. output has taken place + bool beganReadingRecord_{false}; Lock lock_; diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -349,6 +349,10 @@ void ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) { RUNTIME_CHECK(handler, direction_ == Direction::Input); + if (beganReadingRecord_) { + return; + } + beganReadingRecord_ = true; if (access == Access::Sequential) { if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) { handler.SignalEnd(); @@ -367,28 +371,37 @@ } } +void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) { + RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_); + beganReadingRecord_ = false; + if (access == Access::Sequential) { + RUNTIME_CHECK(handler, recordLength.has_value()); + if (isFixedRecordLength) { + frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; + recordOffsetInFrame_ = 0; + } else if (isUnformatted) { + // Retain footer in frame for more efficient BACKSPACE + frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; + recordOffsetInFrame_ = sizeof(std::uint32_t); + recordLength.reset(); + } else { // formatted + if (Frame()[recordOffsetInFrame_ + *recordLength] == '\r') { + ++recordOffsetInFrame_; + } + recordOffsetInFrame_ += *recordLength + 1; + RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ - 1] == '\n'); + recordLength.reset(); + } + } + ++currentRecordNumber; + BeginRecord(); +} + bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) { bool ok{true}; if (direction_ == Direction::Input) { - if (access == Access::Sequential) { - RUNTIME_CHECK(handler, recordLength.has_value()); - if (isFixedRecordLength) { - frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; - recordOffsetInFrame_ = 0; - } else if (isUnformatted) { - // Retain footer in frame for more efficient BACKSPACE - frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength; - recordOffsetInFrame_ = sizeof(std::uint32_t); - recordLength.reset(); - } else { // formatted - if (Frame()[recordOffsetInFrame_ + *recordLength] == '\r') { - ++recordOffsetInFrame_; - } - recordOffsetInFrame_ += *recordLength + 1; - RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ - 1] == '\n'); - recordLength.reset(); - } - } + FinishReadingRecord(handler); + BeginReadingRecord(handler); } else { // Direction::Output if (!isUnformatted) { if (isFixedRecordLength && recordLength) { @@ -406,9 +419,9 @@ recordOffsetInFrame_ + recordLength.value_or(furthestPositionInRecord); recordOffsetInFrame_ = 0; impliedEndfile_ = true; + ++currentRecordNumber; + BeginRecord(); } - ++currentRecordNumber; - BeginRecord(); return ok; }