Index: flang/runtime/io-api.cpp =================================================================== --- flang/runtime/io-api.cpp +++ flang/runtime/io-api.cpp @@ -634,44 +634,22 @@ bool IONAME(SetPos)(Cookie cookie, std::int64_t pos) { IoStatementState &io{*cookie}; - ConnectionState &connection{io.GetConnectionState()}; IoErrorHandler &handler{io.GetIoErrorHandler()}; - if (connection.access != Access::Stream) { - handler.SignalError("POS= may not appear unless ACCESS='STREAM'"); - return false; - } - if (pos < 1) { // POS=1 is beginning of file (12.6.2.11) - handler.SignalError("POS=%zd is invalid", static_cast(pos)); - return false; - } if (auto *unit{io.GetExternalFileUnit()}) { - unit->SetPosition(pos - 1, handler); - return true; + return unit->SetStreamPos(pos, handler); } else if (!io.get_if()) { - io.GetIoErrorHandler().Crash("SetPos() called on internal unit"); + handler.Crash("SetPos() called on internal unit"); } return false; } bool IONAME(SetRec)(Cookie cookie, std::int64_t rec) { IoStatementState &io{*cookie}; - ConnectionState &connection{io.GetConnectionState()}; IoErrorHandler &handler{io.GetIoErrorHandler()}; - if (connection.access != Access::Direct) { - handler.SignalError("REC= may not appear unless ACCESS='DIRECT'"); - return false; - } - if (!connection.openRecl) { - handler.SignalError("RECL= was not specified"); - return false; - } - if (rec < 1) { - handler.SignalError("REC=%zd is invalid", static_cast(rec)); - return false; - } - connection.currentRecordNumber = rec; if (auto *unit{io.GetExternalFileUnit()}) { - unit->SetPosition((rec - 1) * *connection.openRecl, handler); + unit->SetDirectRec(rec, handler); + } else if (!io.get_if()) { + handler.Crash("SetRec() called on internal unit"); } return true; } Index: flang/runtime/unit.h =================================================================== --- flang/runtime/unit.h +++ flang/runtime/unit.h @@ -94,7 +94,8 @@ void Endfile(IoErrorHandler &); void Rewind(IoErrorHandler &); void EndIoStatement(); - void SetPosition(std::int64_t, IoErrorHandler &); // zero-based + bool SetStreamPos(std::int64_t, IoErrorHandler &); // one-based, for POS= + bool SetDirectRec(std::int64_t, IoErrorHandler &); // one-based, for REC= std::int64_t InquirePos() const { // 12.6.2.11 defines POS=1 as the beginning of file return frameOffsetInFile_ + recordOffsetInFrame_ + positionInRecord + 1; @@ -110,6 +111,7 @@ private: static UnitMap &GetUnitMap(); const char *FrameNextInput(IoErrorHandler &, std::size_t); + void SetPosition(std::int64_t, IoErrorHandler &); // zero-based void BeginSequentialVariableUnformattedInputRecord(IoErrorHandler &); void BeginVariableFormattedInputRecord(IoErrorHandler &); void BackspaceFixedRecord(IoErrorHandler &); Index: flang/runtime/unit.cpp =================================================================== --- flang/runtime/unit.cpp +++ flang/runtime/unit.cpp @@ -655,6 +655,45 @@ BeginRecord(); } +bool ExternalFileUnit::SetStreamPos( + std::int64_t oneBasedPos, IoErrorHandler &handler) { + if (access != Access::Stream) { + handler.SignalError("POS= may not appear unless ACCESS='STREAM'"); + return false; + } + if (oneBasedPos < 1) { // POS=1 is beginning of file (12.6.2.11) + handler.SignalError( + "POS=%zd is invalid", static_cast(oneBasedPos)); + return false; + } + SetPosition(oneBasedPos - 1, handler); + // We no longer know which record we're in. Set currentRecordNumber to + // a large value from whence we can both advance and backspace. + currentRecordNumber = std::numeric_limits::max() / 2; + endfileRecordNumber.reset(); + return true; +} + +bool ExternalFileUnit::SetDirectRec( + std::int64_t oneBasedRec, IoErrorHandler &handler) { + if (access != Access::Direct) { + handler.SignalError("REC= may not appear unless ACCESS='DIRECT'"); + return false; + } + if (!openRecl) { + handler.SignalError("RECL= was not specified"); + return false; + } + if (oneBasedRec < 1) { + handler.SignalError( + "REC=%zd is invalid", static_cast(oneBasedRec)); + return false; + } + currentRecordNumber = oneBasedRec; + SetPosition((oneBasedRec - 1) * *openRecl, handler); + return true; +} + void ExternalFileUnit::EndIoStatement() { io_.reset(); u_.emplace();