mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-28 20:41:07 +00:00
[flang] Allow record advancement in external formatted sequential READ
The '/' control edit descriptor causes a runtime crash for an external formatted sequential READ because the AdvanceRecord() member function for external units implemented only the tasks to finish reading the current record. Split those out into a new FinishReadingRecord() member function, call that instead from EndIoStatement(), and change AdvanceRecord() to both finish reading the current record and to begin reading the next one. Differential revision: https://reviews.llvm.org/D88607
This commit is contained in:
parent
d689570d7d
commit
e24f0ac7a3
@ -236,11 +236,13 @@ int NoUnitIoStatementState::EndIoStatement() {
|
||||
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();
|
||||
@ -315,10 +317,20 @@ void ExternalIoStatementState<DIR>::HandleRelativePosition(std::int64_t n) {
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
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 @@ struct IoStatementBase : public DefaultFormatControlCallbacks {
|
||||
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 &);
|
||||
@ -269,9 +270,7 @@ public:
|
||||
void HandleRelativePosition(std::int64_t);
|
||||
void HandleAbsolutePosition(std::int64_t);
|
||||
void BeginReadingRecord();
|
||||
|
||||
private:
|
||||
bool beganReading_{false};
|
||||
void FinishReadingRecord();
|
||||
};
|
||||
|
||||
template <Direction DIR, typename CHAR>
|
||||
|
@ -349,6 +349,10 @@ void ExternalFileUnit::SetLeftTabLimit() {
|
||||
|
||||
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::BeginReadingRecord(IoErrorHandler &handler) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
|
||||
recordOffsetInFrame_ + recordLength.value_or(furthestPositionInRecord);
|
||||
recordOffsetInFrame_ = 0;
|
||||
impliedEndfile_ = true;
|
||||
++currentRecordNumber;
|
||||
BeginRecord();
|
||||
}
|
||||
++currentRecordNumber;
|
||||
BeginRecord();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
std::optional<char32_t> GetCurrentChar(IoErrorHandler &);
|
||||
void SetLeftTabLimit();
|
||||
void BeginReadingRecord(IoErrorHandler &);
|
||||
void FinishReadingRecord(IoErrorHandler &);
|
||||
bool AdvanceRecord(IoErrorHandler &);
|
||||
void BackspaceRecord(IoErrorHandler &);
|
||||
void FlushIfTerminal(IoErrorHandler &);
|
||||
@ -105,6 +106,7 @@ private:
|
||||
int unitNumber_{-1};
|
||||
Direction direction_{Direction::Output};
|
||||
bool impliedEndfile_{false}; // seq. output has taken place
|
||||
bool beganReadingRecord_{false};
|
||||
|
||||
Lock lock_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user