[flang] Emit unformatted headers & footers even with RECL=

The runtime library was emitting unformatted record headers and
footers when an external unit had no fixed RECL=.  This is wrong
for sequential files, which should have headers & footers even
with RECL.  Change to omit headers & footers from unformatted
I/O only for direct access files.

Differential Revision: https://reviews.llvm.org/D112243
This commit is contained in:
peter klausler 2021-10-19 14:46:23 -07:00
parent 93139a3c32
commit b03628d986
2 changed files with 16 additions and 15 deletions

View File

@ -268,9 +268,9 @@ Cookie BeginUnformattedIO(
IoErrorHandler handler{terminator};
unit.SetDirection(DIR, handler);
if constexpr (DIR == Direction::Output) {
if (unit.access == Access::Sequential && !unit.isFixedRecordLength) {
if (unit.access == Access::Sequential) {
// Create space for (sub)record header to be completed by
// ExternalUnformattedIoStatementState<Direction::Output>::EndIoStatement()
// ExternalFileUnit::AdvanceRecord()
unit.recordLength.reset(); // in case of prior BACKSPACE
io.Emit("\0\0\0\0", 4); // placeholder for record length header
}

View File

@ -375,7 +375,7 @@ bool ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
if (access == Access::Sequential) {
if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) {
handler.SignalEnd();
} else if (isFixedRecordLength) {
} else if (isFixedRecordLength && access == Access::Direct) {
RUNTIME_CHECK(handler, recordLength.has_value());
auto need{
static_cast<std::size_t>(recordOffsetInFrame_ + *recordLength)};
@ -406,7 +406,7 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
// avoid bogus crashes in END/ERR circumstances
} else if (access == Access::Sequential) {
RUNTIME_CHECK(handler, recordLength.has_value());
if (isFixedRecordLength) {
if (isFixedRecordLength && access == Access::Direct) {
frameOffsetInFile_ += recordOffsetInFrame_ + *recordLength;
recordOffsetInFrame_ = 0;
} else {
@ -444,17 +444,17 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
} else { // Direction::Output
bool ok{true};
RUNTIME_CHECK(handler, isUnformatted.has_value());
if (isFixedRecordLength && recordLength) {
if (isFixedRecordLength && recordLength &&
furthestPositionInRecord < *recordLength) {
// Pad remainder of fixed length record
if (furthestPositionInRecord < *recordLength) {
WriteFrame(
frameOffsetInFile_, recordOffsetInFrame_ + *recordLength, handler);
std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
isUnformatted.value_or(false) ? 0 : ' ',
*recordLength - furthestPositionInRecord);
}
} else {
positionInRecord = furthestPositionInRecord;
WriteFrame(
frameOffsetInFile_, recordOffsetInFrame_ + *recordLength, handler);
std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
isUnformatted.value_or(false) ? 0 : ' ',
*recordLength - furthestPositionInRecord);
furthestPositionInRecord = *recordLength;
}
if (!(isFixedRecordLength && access == Access::Direct)) {
if (isUnformatted.value_or(false)) {
// Append the length of a sequential unformatted variable-length record
// as its footer, then overwrite the reserved first four bytes of the
@ -464,6 +464,7 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
// headers &/or footers
std::uint32_t length;
length = furthestPositionInRecord - sizeof length;
positionInRecord = furthestPositionInRecord;
ok = ok &&
Emit(reinterpret_cast<const char *>(&length), sizeof length,
sizeof length, handler);
@ -498,7 +499,7 @@ void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
DoImpliedEndfile(handler);
if (frameOffsetInFile_ + recordOffsetInFrame_ > 0) {
--currentRecordNumber;
if (isFixedRecordLength) {
if (isFixedRecordLength && access == Access::Direct) {
BackspaceFixedRecord(handler);
} else {
RUNTIME_CHECK(handler, isUnformatted.has_value());