Skip to content

Commit

Permalink
[flang] Emit unformatted headers & footers even with RECL=
Browse files Browse the repository at this point in the history
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
  • Loading branch information
klausler committed Oct 22, 2021
1 parent 93139a3 commit b03628d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 15 deletions.
4 changes: 2 additions & 2 deletions flang/runtime/io-api.cpp
Expand Up @@ -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
}
Expand Down
27 changes: 14 additions & 13 deletions flang/runtime/unit.cpp
Expand Up @@ -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)};
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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());
Expand Down

0 comments on commit b03628d

Please sign in to comment.