//===-- runtime/unit.cpp --------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "unit.h"
#include "environment.h"
#include "io-error.h"
#include "lock.h"
#include "unit-map.h"
#include <cstdio>
#include <limits>
#include <utility>

namespace Fortran::runtime::io {

// The per-unit data structures are created on demand so that Fortran I/O
// should work without a Fortran main program.
static Lock unitMapLock;
static UnitMap *unitMap{nullptr};
static ExternalFileUnit *defaultInput{nullptr}; // unit 5
static ExternalFileUnit *defaultOutput{nullptr}; // unit 6
static ExternalFileUnit *errorOutput{nullptr}; // unit 0 extension

void FlushOutputOnCrash(const Terminator &terminator) {
  if (!defaultOutput && !errorOutput) {
    return;
  }
  IoErrorHandler handler{terminator};
  handler.HasIoStat(); // prevent nested crash if flush has error
  CriticalSection critical{unitMapLock};
  if (defaultOutput) {
    defaultOutput->FlushOutput(handler);
  }
  if (errorOutput) {
    errorOutput->FlushOutput(handler);
  }
}

ExternalFileUnit *ExternalFileUnit::LookUp(int unit) {
  return GetUnitMap().LookUp(unit);
}

ExternalFileUnit &ExternalFileUnit::LookUpOrCrash(
    int unit, const Terminator &terminator) {
  ExternalFileUnit *file{LookUp(unit)};
  if (!file) {
    terminator.Crash("Not an open I/O unit number: %d", unit);
  }
  return *file;
}

ExternalFileUnit &ExternalFileUnit::LookUpOrCreate(
    int unit, const Terminator &terminator, bool &wasExtant) {
  return GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant);
}

ExternalFileUnit &ExternalFileUnit::LookUpOrCreateAnonymous(int unit,
    Direction dir, std::optional<bool> isUnformatted,
    const Terminator &terminator) {
  bool exists{false};
  ExternalFileUnit &result{
      GetUnitMap().LookUpOrCreate(unit, terminator, exists)};
  if (!exists) {
    IoErrorHandler handler{terminator};
    result.OpenAnonymousUnit(
        dir == Direction::Input ? OpenStatus::Unknown : OpenStatus::Replace,
        Action::ReadWrite, Position::Rewind, Convert::Native, handler);
    result.isUnformatted = isUnformatted;
  }
  return result;
}

ExternalFileUnit *ExternalFileUnit::LookUp(const char *path) {
  return GetUnitMap().LookUp(path);
}

ExternalFileUnit &ExternalFileUnit::CreateNew(
    int unit, const Terminator &terminator) {
  bool wasExtant{false};
  ExternalFileUnit &result{
      GetUnitMap().LookUpOrCreate(unit, terminator, wasExtant)};
  RUNTIME_CHECK(terminator, !wasExtant);
  return result;
}

ExternalFileUnit *ExternalFileUnit::LookUpForClose(int unit) {
  return GetUnitMap().LookUpForClose(unit);
}

ExternalFileUnit &ExternalFileUnit::NewUnit(
    const Terminator &terminator, bool forChildIo) {
  ExternalFileUnit &unit{GetUnitMap().NewUnit(terminator)};
  unit.createdForInternalChildIo_ = forChildIo;
  return unit;
}

void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
    std::optional<Action> action, Position position, OwningPtr<char> &&newPath,
    std::size_t newPathLength, Convert convert, IoErrorHandler &handler) {
  if (executionEnvironment.conversion != Convert::Unknown) {
    convert = executionEnvironment.conversion;
  }
  swapEndianness_ = convert == Convert::Swap ||
      (convert == Convert::LittleEndian && !isHostLittleEndian) ||
      (convert == Convert::BigEndian && isHostLittleEndian);
  if (IsOpen()) {
    bool isSamePath{newPath.get() && path() && pathLength() == newPathLength &&
        std::memcmp(path(), newPath.get(), newPathLength) == 0};
    if (status && *status != OpenStatus::Old && isSamePath) {
      handler.SignalError("OPEN statement for connected unit may not have "
                          "explicit STATUS= other than 'OLD'");
      return;
    }
    if (!newPath.get() || isSamePath) {
      // OPEN of existing unit, STATUS='OLD' or unspecified, not new FILE=
      newPath.reset();
      return;
    }
    // Otherwise, OPEN on open unit with new FILE= implies CLOSE
    DoImpliedEndfile(handler);
    FlushOutput(handler);
    Close(CloseStatus::Keep, handler);
  }
  set_path(std::move(newPath), newPathLength);
  Open(status.value_or(OpenStatus::Unknown), action, position, handler);
  auto totalBytes{knownSize()};
  if (access == Access::Direct) {
    if (!isFixedRecordLength || !recordLength) {
      handler.SignalError(IostatOpenBadRecl,
          "OPEN(UNIT=%d,ACCESS='DIRECT'): record length is not known",
          unitNumber());
    } else if (*recordLength <= 0) {
      handler.SignalError(IostatOpenBadRecl,
          "OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is invalid",
          unitNumber(), static_cast<std::intmax_t>(*recordLength));
    } else if (totalBytes && (*totalBytes % *recordLength != 0)) {
      handler.SignalError(IostatOpenBadAppend,
          "OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is not an "
          "even divisor of the file size %jd",
          unitNumber(), static_cast<std::intmax_t>(*recordLength),
          static_cast<std::intmax_t>(*totalBytes));
    }
  }
  endfileRecordNumber.reset();
  currentRecordNumber = 1;
  if (totalBytes && recordLength && *recordLength) {
    endfileRecordNumber = 1 + (*totalBytes / *recordLength);
  }
  if (position == Position::Append) {
    if (!endfileRecordNumber) {
      // Fake it so that we can backspace relative from the end
      endfileRecordNumber = std::numeric_limits<std::int64_t>::max() - 2;
    }
    currentRecordNumber = *endfileRecordNumber;
  }
}

void ExternalFileUnit::OpenAnonymousUnit(std::optional<OpenStatus> status,
    std::optional<Action> action, Position position, Convert convert,
    IoErrorHandler &handler) {
  // I/O to an unconnected unit reads/creates a local file, e.g. fort.7
  std::size_t pathMaxLen{32};
  auto path{SizedNew<char>{handler}(pathMaxLen)};
  std::snprintf(path.get(), pathMaxLen, "fort.%d", unitNumber_);
  OpenUnit(status, action, position, std::move(path), std::strlen(path.get()),
      convert, handler);
}

void ExternalFileUnit::CloseUnit(CloseStatus status, IoErrorHandler &handler) {
  DoImpliedEndfile(handler);
  FlushOutput(handler);
  Close(status, handler);
}

void ExternalFileUnit::DestroyClosed() {
  GetUnitMap().DestroyClosed(*this); // destroys *this
}

bool ExternalFileUnit::SetDirection(
    Direction direction, IoErrorHandler &handler) {
  if (direction == Direction::Input) {
    if (mayRead()) {
      direction_ = Direction::Input;
      return true;
    } else {
      handler.SignalError(IostatReadFromWriteOnly,
          "READ(UNIT=%d) with ACTION='WRITE'", unitNumber());
      return false;
    }
  } else {
    if (mayWrite()) {
      direction_ = Direction::Output;
      return true;
    } else {
      handler.SignalError(IostatWriteToReadOnly,
          "WRITE(UNIT=%d) with ACTION='READ'", unitNumber());
      return false;
    }
  }
}

UnitMap &ExternalFileUnit::GetUnitMap() {
  if (unitMap) {
    return *unitMap;
  }
  CriticalSection critical{unitMapLock};
  if (unitMap) {
    return *unitMap;
  }
  Terminator terminator{__FILE__, __LINE__};
  IoErrorHandler handler{terminator};
  UnitMap *newUnitMap{New<UnitMap>{terminator}().release()};

  bool wasExtant{false};
  ExternalFileUnit &out{newUnitMap->LookUpOrCreate(6, terminator, wasExtant)};
  RUNTIME_CHECK(terminator, !wasExtant);
  out.Predefine(1);
  out.SetDirection(Direction::Output, handler);
  out.isUnformatted = false;
  defaultOutput = &out;

  ExternalFileUnit &in{newUnitMap->LookUpOrCreate(5, terminator, wasExtant)};
  RUNTIME_CHECK(terminator, !wasExtant);
  in.Predefine(0);
  in.SetDirection(Direction::Input, handler);
  in.isUnformatted = false;
  defaultInput = &in;

  ExternalFileUnit &error{newUnitMap->LookUpOrCreate(0, terminator, wasExtant)};
  RUNTIME_CHECK(terminator, !wasExtant);
  error.Predefine(2);
  error.SetDirection(Direction::Output, handler);
  error.isUnformatted = false;
  errorOutput = &error;

  // TODO: Set UTF-8 mode from the environment
  unitMap = newUnitMap;
  return *unitMap;
}

void ExternalFileUnit::CloseAll(IoErrorHandler &handler) {
  CriticalSection critical{unitMapLock};
  if (unitMap) {
    unitMap->CloseAll(handler);
    FreeMemoryAndNullify(unitMap);
  }
  defaultOutput = nullptr;
  defaultInput = nullptr;
  errorOutput = nullptr;
}

void ExternalFileUnit::FlushAll(IoErrorHandler &handler) {
  CriticalSection critical{unitMapLock};
  if (unitMap) {
    unitMap->FlushAll(handler);
  }
}

static void SwapEndianness(
    char *data, std::size_t bytes, std::size_t elementBytes) {
  if (elementBytes > 1) {
    auto half{elementBytes >> 1};
    for (std::size_t j{0}; j + elementBytes <= bytes; j += elementBytes) {
      for (std::size_t k{0}; k < half; ++k) {
        std::swap(data[j + k], data[j + elementBytes - 1 - k]);
      }
    }
  }
}

bool ExternalFileUnit::Emit(const char *data, std::size_t bytes,
    std::size_t elementBytes, IoErrorHandler &handler) {
  auto furthestAfter{std::max(furthestPositionInRecord,
      positionInRecord + static_cast<std::int64_t>(bytes))};
  if (recordLength) {
    // It is possible for recordLength to have a value now for a
    // variable-length output record if the previous operation
    // was a BACKSPACE or non advancing input statement.
    if (!isFixedRecordLength) {
      recordLength.reset();
      beganReadingRecord_ = false;
    } else if (furthestAfter > *recordLength) {
      handler.SignalError(IostatRecordWriteOverrun,
          "Attempt to write %zd bytes to position %jd in a fixed-size record "
          "of %jd bytes",
          bytes, static_cast<std::intmax_t>(positionInRecord),
          static_cast<std::intmax_t>(*recordLength));
      return false;
    }
  }
  WriteFrame(frameOffsetInFile_, recordOffsetInFrame_ + furthestAfter, handler);
  if (positionInRecord > furthestPositionInRecord) {
    std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord, ' ',
        positionInRecord - furthestPositionInRecord);
  }
  char *to{Frame() + recordOffsetInFrame_ + positionInRecord};
  std::memcpy(to, data, bytes);
  if (swapEndianness_) {
    SwapEndianness(to, bytes, elementBytes);
  }
  positionInRecord += bytes;
  furthestPositionInRecord = furthestAfter;
  return true;
}

bool ExternalFileUnit::Receive(char *data, std::size_t bytes,
    std::size_t elementBytes, IoErrorHandler &handler) {
  RUNTIME_CHECK(handler, direction_ == Direction::Input);
  auto furthestAfter{std::max(furthestPositionInRecord,
      positionInRecord + static_cast<std::int64_t>(bytes))};
  if (furthestAfter > recordLength.value_or(furthestAfter)) {
    handler.SignalError(IostatRecordReadOverrun,
        "Attempt to read %zd bytes at position %jd in a record of %jd bytes",
        bytes, static_cast<std::intmax_t>(positionInRecord),
        static_cast<std::intmax_t>(*recordLength));
    return false;
  }
  auto need{recordOffsetInFrame_ + furthestAfter};
  auto got{ReadFrame(frameOffsetInFile_, need, handler)};
  if (got >= need) {
    std::memcpy(data, Frame() + recordOffsetInFrame_ + positionInRecord, bytes);
    if (swapEndianness_) {
      SwapEndianness(data, bytes, elementBytes);
    }
    positionInRecord += bytes;
    furthestPositionInRecord = furthestAfter;
    return true;
  } else {
    // EOF or error: can be handled & has been signaled
    endfileRecordNumber = currentRecordNumber;
    return false;
  }
}

std::size_t ExternalFileUnit::GetNextInputBytes(
    const char *&p, IoErrorHandler &handler) {
  RUNTIME_CHECK(handler, direction_ == Direction::Input);
  p = FrameNextInput(handler, 1);
  return p ? recordLength.value_or(positionInRecord + 1) - positionInRecord : 0;
}

std::optional<char32_t> ExternalFileUnit::GetCurrentChar(
    IoErrorHandler &handler) {
  const char *p{nullptr};
  std::size_t bytes{GetNextInputBytes(p, handler)};
  if (bytes == 0) {
    return std::nullopt;
  } else {
    // TODO: UTF-8 decoding; may have to get more bytes in a loop
    return *p;
  }
}

const char *ExternalFileUnit::FrameNextInput(
    IoErrorHandler &handler, std::size_t bytes) {
  RUNTIME_CHECK(handler, isUnformatted.has_value() && !*isUnformatted);
  if (static_cast<std::int64_t>(positionInRecord + bytes) <=
      recordLength.value_or(positionInRecord + bytes)) {
    auto at{recordOffsetInFrame_ + positionInRecord};
    auto need{static_cast<std::size_t>(at + bytes)};
    auto got{ReadFrame(frameOffsetInFile_, need, handler)};
    SetSequentialVariableFormattedRecordLength();
    if (got >= need) {
      return Frame() + at;
    }
    handler.SignalEnd();
    endfileRecordNumber = currentRecordNumber;
  }
  return nullptr;
}

bool ExternalFileUnit::SetSequentialVariableFormattedRecordLength() {
  if (recordLength || access != Access::Sequential) {
    return true;
  } else if (FrameLength() > recordOffsetInFrame_) {
    const char *record{Frame() + recordOffsetInFrame_};
    std::size_t bytes{FrameLength() - recordOffsetInFrame_};
    if (const char *nl{
            reinterpret_cast<const char *>(std::memchr(record, '\n', bytes))}) {
      recordLength = nl - record;
      if (*recordLength > 0 && record[*recordLength - 1] == '\r') {
        --*recordLength;
      }
      return true;
    }
  }
  return false;
}

void ExternalFileUnit::SetLeftTabLimit() {
  leftTabLimit = furthestPositionInRecord;
  positionInRecord = furthestPositionInRecord;
}

bool ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
  RUNTIME_CHECK(handler, direction_ == Direction::Input);
  if (!beganReadingRecord_) {
    beganReadingRecord_ = true;
    if (access == Access::Sequential) {
      if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) {
        handler.SignalEnd();
      } else if (isFixedRecordLength && access == Access::Direct) {
        RUNTIME_CHECK(handler, recordLength.has_value());
        auto need{
            static_cast<std::size_t>(recordOffsetInFrame_ + *recordLength)};
        auto got{ReadFrame(frameOffsetInFile_, need, handler)};
        if (got < need) {
          handler.SignalEnd();
        }
      } else {
        RUNTIME_CHECK(handler, isUnformatted.has_value());
        if (isUnformatted.value_or(false)) {
          BeginSequentialVariableUnformattedInputRecord(handler);
        } else { // formatted
          BeginSequentialVariableFormattedInputRecord(handler);
        }
      }
    }
  }
  RUNTIME_CHECK(handler,
      access != Access::Sequential || recordLength.has_value() ||
          handler.InError());
  return !handler.InError();
}

void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
  RUNTIME_CHECK(handler, direction_ == Direction::Input && beganReadingRecord_);
  beganReadingRecord_ = false;
  if (handler.InError() && handler.GetIoStat() != IostatEor) {
    // avoid bogus crashes in END/ERR circumstances
  } else if (access == Access::Sequential) {
    RUNTIME_CHECK(handler, recordLength.has_value());
    recordOffsetInFrame_ += *recordLength;
    if (isFixedRecordLength && access == Access::Direct) {
      frameOffsetInFile_ += recordOffsetInFrame_;
      recordOffsetInFrame_ = 0;
    } else {
      RUNTIME_CHECK(handler, isUnformatted.has_value());
      recordLength.reset();
      if (isUnformatted.value_or(false)) {
        // Retain footer in frame for more efficient BACKSPACE
        frameOffsetInFile_ += recordOffsetInFrame_;
        recordOffsetInFrame_ = sizeof(std::uint32_t);
      } else { // formatted
        if (FrameLength() > recordOffsetInFrame_ &&
            Frame()[recordOffsetInFrame_] == '\r') {
          ++recordOffsetInFrame_;
        }
        if (FrameLength() >= recordOffsetInFrame_ &&
            Frame()[recordOffsetInFrame_] == '\n') {
          ++recordOffsetInFrame_;
        }
        if (!pinnedFrame || mayPosition()) {
          frameOffsetInFile_ += recordOffsetInFrame_;
          recordOffsetInFrame_ = 0;
        }
      }
    }
  }
  ++currentRecordNumber;
  BeginRecord();
}

bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
  if (direction_ == Direction::Input) {
    FinishReadingRecord(handler);
    return BeginReadingRecord(handler);
  } else { // Direction::Output
    bool ok{true};
    RUNTIME_CHECK(handler, isUnformatted.has_value());
    if (isFixedRecordLength && recordLength &&
        furthestPositionInRecord < *recordLength) {
      // Pad remainder of fixed length record
      WriteFrame(
          frameOffsetInFile_, recordOffsetInFrame_ + *recordLength, handler);
      std::memset(Frame() + recordOffsetInFrame_ + furthestPositionInRecord,
          isUnformatted.value_or(false) ? 0 : ' ',
          *recordLength - furthestPositionInRecord);
      furthestPositionInRecord = *recordLength;
    }
    if (!(isFixedRecordLength && access == Access::Direct)) {
      positionInRecord = furthestPositionInRecord;
      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
        // record with its length as its header.  These four bytes were skipped
        // over in BeginUnformattedIO<Output>().
        // TODO: Break very large records up into subrecords with negative
        // headers &/or footers
        std::uint32_t length;
        length = furthestPositionInRecord - sizeof length;
        ok = ok &&
            Emit(reinterpret_cast<const char *>(&length), sizeof length,
                sizeof length, handler);
        positionInRecord = 0;
        ok = ok &&
            Emit(reinterpret_cast<const char *>(&length), sizeof length,
                sizeof length, handler);
      } else {
        // Terminate formatted variable length record
        ok = ok && Emit("\n", 1, 1, handler); // TODO: Windows CR+LF
      }
    }
    CommitWrites();
    impliedEndfile_ = true;
    ++currentRecordNumber;
    if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) {
      endfileRecordNumber.reset();
    }
    return ok;
  }
}

void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
  if (access != Access::Sequential) {
    handler.SignalError(IostatBackspaceNonSequential,
        "BACKSPACE(UNIT=%d) on non-sequential file", unitNumber());
  } else {
    if (endfileRecordNumber && currentRecordNumber > *endfileRecordNumber) {
      // BACKSPACE after explicit ENDFILE
      currentRecordNumber = *endfileRecordNumber;
    } else {
      DoImpliedEndfile(handler);
      if (frameOffsetInFile_ + recordOffsetInFrame_ > 0) {
        --currentRecordNumber;
        if (isFixedRecordLength && access == Access::Direct) {
          BackspaceFixedRecord(handler);
        } else {
          RUNTIME_CHECK(handler, isUnformatted.has_value());
          if (isUnformatted.value_or(false)) {
            BackspaceVariableUnformattedRecord(handler);
          } else {
            BackspaceVariableFormattedRecord(handler);
          }
        }
      }
    }
    BeginRecord();
  }
}

void ExternalFileUnit::FlushOutput(IoErrorHandler &handler) {
  if (!mayPosition()) {
    auto frameAt{FrameAt()};
    if (frameOffsetInFile_ >= frameAt &&
        frameOffsetInFile_ <
            static_cast<std::int64_t>(frameAt + FrameLength())) {
      // A Flush() that's about to happen to a non-positionable file
      // needs to advance frameOffsetInFile_ to prevent attempts at
      // impossible seeks
      CommitWrites();
    }
  }
  Flush(handler);
}

void ExternalFileUnit::FlushIfTerminal(IoErrorHandler &handler) {
  if (isTerminal()) {
    FlushOutput(handler);
  }
}

void ExternalFileUnit::Endfile(IoErrorHandler &handler) {
  if (access != Access::Sequential) {
    handler.SignalError(IostatEndfileNonSequential,
        "ENDFILE(UNIT=%d) on non-sequential file", unitNumber());
  } else if (!mayWrite()) {
    handler.SignalError(IostatEndfileUnwritable,
        "ENDFILE(UNIT=%d) on read-only file", unitNumber());
  } else if (endfileRecordNumber &&
      currentRecordNumber > *endfileRecordNumber) {
    // ENDFILE after ENDFILE
  } else {
    DoEndfile(handler);
    // Explicit ENDFILE leaves position *after* the endfile record
    RUNTIME_CHECK(handler, endfileRecordNumber.has_value());
    currentRecordNumber = *endfileRecordNumber + 1;
  }
}

void ExternalFileUnit::Rewind(IoErrorHandler &handler) {
  if (access == Access::Direct) {
    handler.SignalError(IostatRewindNonSequential,
        "REWIND(UNIT=%d) on non-sequential file", unitNumber());
  } else {
    DoImpliedEndfile(handler);
    SetPosition(0);
    currentRecordNumber = 1;
  }
}

void ExternalFileUnit::EndIoStatement() {
  io_.reset();
  u_.emplace<std::monostate>();
  lock_.Drop();
}

void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
    IoErrorHandler &handler) {
  std::int32_t header{0}, footer{0};
  std::size_t need{recordOffsetInFrame_ + sizeof header};
  std::size_t got{ReadFrame(frameOffsetInFile_, need, handler)};
  // Try to emit informative errors to help debug corrupted files.
  const char *error{nullptr};
  if (got < need) {
    if (got == recordOffsetInFrame_) {
      handler.SignalEnd();
    } else {
      error = "Unformatted variable-length sequential file input failed at "
              "record #%jd (file offset %jd): truncated record header";
    }
  } else {
    std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
    recordLength = sizeof header + header; // does not include footer
    need = recordOffsetInFrame_ + *recordLength + sizeof footer;
    got = ReadFrame(frameOffsetInFile_, need, handler);
    if (got < need) {
      error = "Unformatted variable-length sequential file input failed at "
              "record #%jd (file offset %jd): hit EOF reading record with "
              "length %jd bytes";
    } else {
      std::memcpy(&footer, Frame() + recordOffsetInFrame_ + *recordLength,
          sizeof footer);
      if (footer != header) {
        error = "Unformatted variable-length sequential file input failed at "
                "record #%jd (file offset %jd): record header has length %jd "
                "that does not match record footer (%jd)";
      }
    }
  }
  if (error) {
    handler.SignalError(error, static_cast<std::intmax_t>(currentRecordNumber),
        static_cast<std::intmax_t>(frameOffsetInFile_),
        static_cast<std::intmax_t>(header), static_cast<std::intmax_t>(footer));
    // TODO: error recovery
  }
  positionInRecord = sizeof header;
}

void ExternalFileUnit::BeginSequentialVariableFormattedInputRecord(
    IoErrorHandler &handler) {
  if (this == defaultInput) {
    if (defaultOutput) {
      defaultOutput->FlushOutput(handler);
    }
    if (errorOutput) {
      errorOutput->FlushOutput(handler);
    }
  }
  std::size_t length{0};
  do {
    std::size_t need{length + 1};
    length =
        ReadFrame(frameOffsetInFile_, recordOffsetInFrame_ + need, handler) -
        recordOffsetInFrame_;
    if (length < need) {
      if (length > 0) {
        // final record w/o \n
        recordLength = length;
      } else {
        handler.SignalEnd();
      }
      break;
    }
  } while (!SetSequentialVariableFormattedRecordLength());
}

void ExternalFileUnit::BackspaceFixedRecord(IoErrorHandler &handler) {
  RUNTIME_CHECK(handler, recordLength.has_value());
  if (frameOffsetInFile_ < *recordLength) {
    handler.SignalError(IostatBackspaceAtFirstRecord);
  } else {
    frameOffsetInFile_ -= *recordLength;
  }
}

void ExternalFileUnit::BackspaceVariableUnformattedRecord(
    IoErrorHandler &handler) {
  std::int32_t header{0}, footer{0};
  auto headerBytes{static_cast<std::int64_t>(sizeof header)};
  frameOffsetInFile_ += recordOffsetInFrame_;
  recordOffsetInFrame_ = 0;
  if (frameOffsetInFile_ <= headerBytes) {
    handler.SignalError(IostatBackspaceAtFirstRecord);
    return;
  }
  // Error conditions here cause crashes, not file format errors, because the
  // validity of the file structure before the current record will have been
  // checked informatively in NextSequentialVariableUnformattedInputRecord().
  std::size_t got{
      ReadFrame(frameOffsetInFile_ - headerBytes, headerBytes, handler)};
  RUNTIME_CHECK(handler, got >= sizeof footer);
  std::memcpy(&footer, Frame(), sizeof footer);
  recordLength = footer;
  RUNTIME_CHECK(handler, frameOffsetInFile_ >= *recordLength + 2 * headerBytes);
  frameOffsetInFile_ -= *recordLength + 2 * headerBytes;
  if (frameOffsetInFile_ >= headerBytes) {
    frameOffsetInFile_ -= headerBytes;
    recordOffsetInFrame_ = headerBytes;
  }
  auto need{static_cast<std::size_t>(
      recordOffsetInFrame_ + sizeof header + *recordLength)};
  got = ReadFrame(frameOffsetInFile_, need, handler);
  RUNTIME_CHECK(handler, got >= need);
  std::memcpy(&header, Frame() + recordOffsetInFrame_, sizeof header);
  RUNTIME_CHECK(handler, header == *recordLength);
}

// There's no portable memrchr(), unfortunately, and strrchr() would
// fail on a record with a NUL, so we have to do it the hard way.
static const char *FindLastNewline(const char *str, std::size_t length) {
  for (const char *p{str + length}; p-- > str;) {
    if (*p == '\n') {
      return p;
    }
  }
  return nullptr;
}

void ExternalFileUnit::BackspaceVariableFormattedRecord(
    IoErrorHandler &handler) {
  // File offset of previous record's newline
  auto prevNL{
      frameOffsetInFile_ + static_cast<std::int64_t>(recordOffsetInFrame_) - 1};
  if (prevNL < 0) {
    handler.SignalError(IostatBackspaceAtFirstRecord);
    return;
  }
  while (true) {
    if (frameOffsetInFile_ < prevNL) {
      if (const char *p{
              FindLastNewline(Frame(), prevNL - 1 - frameOffsetInFile_)}) {
        recordOffsetInFrame_ = p - Frame() + 1;
        recordLength = prevNL - (frameOffsetInFile_ + recordOffsetInFrame_);
        break;
      }
    }
    if (frameOffsetInFile_ == 0) {
      recordOffsetInFrame_ = 0;
      recordLength = prevNL;
      break;
    }
    frameOffsetInFile_ -= std::min<std::int64_t>(frameOffsetInFile_, 1024);
    auto need{static_cast<std::size_t>(prevNL + 1 - frameOffsetInFile_)};
    auto got{ReadFrame(frameOffsetInFile_, need, handler)};
    RUNTIME_CHECK(handler, got >= need);
  }
  RUNTIME_CHECK(handler, Frame()[recordOffsetInFrame_ + *recordLength] == '\n');
  if (*recordLength > 0 &&
      Frame()[recordOffsetInFrame_ + *recordLength - 1] == '\r') {
    --*recordLength;
  }
}

void ExternalFileUnit::DoImpliedEndfile(IoErrorHandler &handler) {
  if (impliedEndfile_) {
    impliedEndfile_ = false;
    if (access == Access::Sequential && mayPosition()) {
      DoEndfile(handler);
    }
  }
}

void ExternalFileUnit::DoEndfile(IoErrorHandler &handler) {
  endfileRecordNumber = currentRecordNumber;
  Truncate(frameOffsetInFile_ + recordOffsetInFrame_, handler);
  BeginRecord();
  impliedEndfile_ = false;
}

void ExternalFileUnit::CommitWrites() {
  frameOffsetInFile_ +=
      recordOffsetInFrame_ + recordLength.value_or(furthestPositionInRecord);
  recordOffsetInFrame_ = 0;
  BeginRecord();
}

ChildIo &ExternalFileUnit::PushChildIo(IoStatementState &parent) {
  OwningPtr<ChildIo> current{std::move(child_)};
  Terminator &terminator{parent.GetIoErrorHandler()};
  OwningPtr<ChildIo> next{New<ChildIo>{terminator}(parent, std::move(current))};
  child_.reset(next.release());
  return *child_;
}

void ExternalFileUnit::PopChildIo(ChildIo &child) {
  if (child_.get() != &child) {
    child.parent().GetIoErrorHandler().Crash(
        "ChildIo being popped is not top of stack");
  }
  child_.reset(child.AcquirePrevious().release()); // deletes top child
}

void ChildIo::EndIoStatement() {
  io_.reset();
  u_.emplace<std::monostate>();
}

bool ChildIo::CheckFormattingAndDirection(Terminator &terminator,
    const char *what, bool unformatted, Direction direction) {
  bool parentIsInput{!parent_.get_if<IoDirectionState<Direction::Output>>()};
  bool parentIsFormatted{parentIsInput
          ? parent_.get_if<FormattedIoStatementState<Direction::Input>>() !=
              nullptr
          : parent_.get_if<FormattedIoStatementState<Direction::Output>>() !=
              nullptr};
  bool parentIsUnformatted{!parentIsFormatted};
  if (unformatted != parentIsUnformatted) {
    terminator.Crash("Child %s attempted on %s parent I/O unit", what,
        parentIsUnformatted ? "unformatted" : "formatted");
    return false;
  } else if (parentIsInput != (direction == Direction::Input)) {
    terminator.Crash("Child %s attempted on %s parent I/O unit", what,
        parentIsInput ? "input" : "output");
    return false;
  } else {
    return true;
  }
}

} // namespace Fortran::runtime::io
