template <Direction DIR> int ExternalIoStatementState<DIR>::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();
template <Direction DIR>
void ExternalIoStatementState<DIR>::BeginReadingRecord() {
if constexpr (DIR == Direction::Input) {
- if (!beganReading_) {
- beganReading_ = true;
- unit().BeginReadingRecord(*this);
- }
+ unit().BeginReadingRecord(*this);
+ } else {
+ Crash("ExternalIoStatementState<Direction::Output>::BeginReadingRecord() "
+ "called");
+ }
+}
+
+template <Direction DIR>
+void ExternalIoStatementState<DIR>::FinishReadingRecord() {
+ if constexpr (DIR == Direction::Input) {
+ unit().FinishReadingRecord(*this);
+ } else {
+ Crash("ExternalIoStatementState<Direction::Output>::FinishReadingRecord() "
+ "called");
}
}
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=
std::optional<DataEdit> 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 &);
void HandleRelativePosition(std::int64_t);
void HandleAbsolutePosition(std::int64_t);
void BeginReadingRecord();
-
-private:
- bool beganReading_{false};
+ void FinishReadingRecord();
};
template <Direction DIR, typename CHAR>
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();
}
}
+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) {
recordOffsetInFrame_ + recordLength.value_or(furthestPositionInRecord);
recordOffsetInFrame_ = 0;
impliedEndfile_ = true;
+ ++currentRecordNumber;
+ BeginRecord();
}
- ++currentRecordNumber;
- BeginRecord();
return ok;
}
std::optional<char32_t> GetCurrentChar(IoErrorHandler &);
void SetLeftTabLimit();
void BeginReadingRecord(IoErrorHandler &);
+ void FinishReadingRecord(IoErrorHandler &);
bool AdvanceRecord(IoErrorHandler &);
void BackspaceRecord(IoErrorHandler &);
void FlushIfTerminal(IoErrorHandler &);
int unitNumber_{-1};
Direction direction_{Direction::Output};
bool impliedEndfile_{false}; // seq. output has taken place
+ bool beganReadingRecord_{false};
Lock lock_;