}
template <Direction DIR, template <Direction> class STATE, typename... A>
-Cookie BeginExternalListIO(const char *what, int unitNumber,
- const char *sourceFile, int sourceLine, A &&...xs) {
+Cookie BeginExternalListIO(
+ int unitNumber, const char *sourceFile, int sourceLine, A &&...xs) {
Terminator terminator{sourceFile, sourceLine};
if (unitNumber == DefaultUnit) {
unitNumber = DIR == Direction::Input ? 5 : 6;
if (!unit.isUnformatted.has_value()) {
unit.isUnformatted = false;
}
+ Iostat iostat{IostatOk};
if (*unit.isUnformatted) {
- terminator.Crash("%s attempted on unformatted file", what);
- return nullptr;
+ iostat = IostatFormattedIoOnUnformattedUnit;
}
if (ChildIo * child{unit.GetChildIo()}) {
- return child->CheckFormattingAndDirection(terminator, what, false, DIR)
- ? &child->BeginIoStatement<ChildListIoStatementState<DIR>>(
- *child, sourceFile, sourceLine)
- : nullptr;
+ if (iostat == IostatOk) {
+ iostat = child->CheckFormattingAndDirection(false, DIR);
+ }
+ if (iostat == IostatOk) {
+ return &child->BeginIoStatement<ChildListIoStatementState<DIR>>(
+ *child, sourceFile, sourceLine);
+ } else {
+ return &child->BeginIoStatement<ErroneousIoStatementState>(
+ iostat, sourceFile, sourceLine);
+ }
} else {
- if (unit.access == Access::Direct) {
- terminator.Crash("%s attempted on direct access file", what);
- return nullptr;
+ if (iostat == IostatOk && unit.access == Access::Direct) {
+ iostat = IostatListIoOnDirectAccessUnit;
+ }
+ if (iostat == IostatOk) {
+ iostat = unit.SetDirection(DIR);
+ }
+ if (iostat == IostatOk) {
+ return &unit.BeginIoStatement<STATE<DIR>>(
+ std::forward<A>(xs)..., unit, sourceFile, sourceLine);
+ } else {
+ return &unit.BeginIoStatement<ErroneousIoStatementState>(
+ iostat, sourceFile, sourceLine);
}
- IoErrorHandler handler{terminator};
- unit.SetDirection(DIR, handler);
- IoStatementState &io{unit.BeginIoStatement<STATE<DIR>>(
- std::forward<A>(xs)..., unit, sourceFile, sourceLine)};
- return &io;
}
}
Cookie IONAME(BeginExternalListOutput)(
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
return BeginExternalListIO<Direction::Output, ExternalListIoStatementState>(
- "List-directed output", unitNumber, sourceFile, sourceLine);
+ unitNumber, sourceFile, sourceLine);
}
Cookie IONAME(BeginExternalListInput)(
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
return BeginExternalListIO<Direction::Input, ExternalListIoStatementState>(
- "List-directed input", unitNumber, sourceFile, sourceLine);
+ unitNumber, sourceFile, sourceLine);
}
template <Direction DIR>
}
ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreateAnonymous(
unitNumber, DIR, false /*!unformatted*/, terminator)};
+ Iostat iostat{IostatOk};
if (!unit.isUnformatted.has_value()) {
unit.isUnformatted = false;
}
if (*unit.isUnformatted) {
- terminator.Crash("Formatted I/O attempted on unformatted file");
- return nullptr;
+ iostat = IostatFormattedIoOnUnformattedUnit;
}
if (ChildIo * child{unit.GetChildIo()}) {
- return child->CheckFormattingAndDirection(terminator,
- DIR == Direction::Output ? "formatted output"
- : "formatted input",
- false, DIR)
- ? &child->BeginIoStatement<ChildFormattedIoStatementState<DIR>>(
- *child, format, formatLength, sourceFile, sourceLine)
- : nullptr;
+ if (iostat == IostatOk) {
+ iostat = child->CheckFormattingAndDirection(false, DIR);
+ }
+ if (iostat == IostatOk) {
+ return &child->BeginIoStatement<ChildFormattedIoStatementState<DIR>>(
+ *child, format, formatLength, sourceFile, sourceLine);
+ } else {
+ return &child->BeginIoStatement<ErroneousIoStatementState>(
+ iostat, sourceFile, sourceLine);
+ }
} else {
- IoErrorHandler handler{terminator};
- unit.SetDirection(DIR, handler);
- IoStatementState &io{
- unit.BeginIoStatement<ExternalFormattedIoStatementState<DIR>>(
- unit, format, formatLength, sourceFile, sourceLine)};
- return &io;
+ if (iostat == IostatOk) {
+ iostat = unit.SetDirection(DIR);
+ }
+ if (iostat == IostatOk) {
+ return &unit.BeginIoStatement<ExternalFormattedIoStatementState<DIR>>(
+ unit, format, formatLength, sourceFile, sourceLine);
+ } else {
+ return &unit.BeginIoStatement<ErroneousIoStatementState>(
+ iostat, sourceFile, sourceLine);
+ }
}
}
Terminator terminator{sourceFile, sourceLine};
ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreateAnonymous(
unitNumber, DIR, true /*unformatted*/, terminator)};
+ Iostat iostat{IostatOk};
if (!unit.isUnformatted.has_value()) {
unit.isUnformatted = true;
}
if (!*unit.isUnformatted) {
- terminator.Crash("Unformatted I/O attempted on formatted file");
+ iostat = IostatUnformattedIoOnFormattedUnit;
}
if (ChildIo * child{unit.GetChildIo()}) {
- return child->CheckFormattingAndDirection(terminator,
- DIR == Direction::Output ? "unformatted output"
- : "unformatted input",
- true, DIR)
- ? &child->BeginIoStatement<ChildUnformattedIoStatementState<DIR>>(
- *child, sourceFile, sourceLine)
- : nullptr;
+ if (iostat == IostatOk) {
+ iostat = child->CheckFormattingAndDirection(true, DIR);
+ }
+ if (iostat == IostatOk) {
+ return &child->BeginIoStatement<ChildUnformattedIoStatementState<DIR>>(
+ *child, sourceFile, sourceLine);
+ } else {
+ return &child->BeginIoStatement<ErroneousIoStatementState>(
+ iostat, sourceFile, sourceLine);
+ }
} else {
- IoStatementState &io{
- unit.BeginIoStatement<ExternalUnformattedIoStatementState<DIR>>(
- unit, sourceFile, sourceLine)};
- IoErrorHandler handler{terminator};
- unit.SetDirection(DIR, handler);
- if constexpr (DIR == Direction::Output) {
- if (unit.access == Access::Sequential) {
- // Create space for (sub)record header to be completed by
- // ExternalFileUnit::AdvanceRecord()
- unit.recordLength.reset(); // in case of prior BACKSPACE
- io.Emit("\0\0\0\0", 4); // placeholder for record length header
+ if (iostat == IostatOk) {
+ iostat = unit.SetDirection(DIR);
+ }
+ if (iostat == IostatOk) {
+ IoStatementState &io{
+ unit.BeginIoStatement<ExternalUnformattedIoStatementState<DIR>>(
+ unit, sourceFile, sourceLine)};
+ if constexpr (DIR == Direction::Output) {
+ if (unit.access == Access::Sequential) {
+ // Create space for (sub)record header to be completed by
+ // ExternalFileUnit::AdvanceRecord()
+ unit.recordLength.reset(); // in case of prior BACKSPACE
+ io.Emit("\0\0\0\0", 4); // placeholder for record length header
+ }
}
+ return &io;
+ } else {
+ return &unit.BeginIoStatement<ErroneousIoStatementState>(
+ iostat, sourceFile, sourceLine);
}
- return &io;
}
}
GetUnitMap().DestroyClosed(*this); // destroys *this
}
-bool ExternalFileUnit::SetDirection(
- Direction direction, IoErrorHandler &handler) {
+Iostat ExternalFileUnit::SetDirection(Direction direction) {
if (direction == Direction::Input) {
if (mayRead()) {
direction_ = Direction::Input;
- return true;
+ return IostatOk;
} else {
- handler.SignalError(IostatReadFromWriteOnly,
- "READ(UNIT=%d) with ACTION='WRITE'", unitNumber());
- return false;
+ return IostatReadFromWriteOnly;
}
} else {
if (mayWrite()) {
direction_ = Direction::Output;
- return true;
+ return IostatOk;
} else {
- handler.SignalError(IostatWriteToReadOnly,
- "WRITE(UNIT=%d) with ACTION='READ'", unitNumber());
- return false;
+ return IostatWriteToReadOnly;
}
}
}
ExternalFileUnit &out{newUnitMap->LookUpOrCreate(6, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
out.Predefine(1);
- out.SetDirection(Direction::Output, handler);
+ handler.SignalError(out.SetDirection(Direction::Output));
out.isUnformatted = false;
defaultOutput = &out;
ExternalFileUnit &in{newUnitMap->LookUpOrCreate(5, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
in.Predefine(0);
- in.SetDirection(Direction::Input, handler);
+ handler.SignalError(in.SetDirection(Direction::Input));
in.isUnformatted = false;
defaultInput = ∈
ExternalFileUnit &error{newUnitMap->LookUpOrCreate(0, terminator, wasExtant)};
RUNTIME_CHECK(terminator, !wasExtant);
error.Predefine(2);
- error.SetDirection(Direction::Output, handler);
+ handler.SignalError(error.SetDirection(Direction::Output));
error.isUnformatted = false;
errorOutput = &error;
u_.emplace<std::monostate>();
}
-bool ChildIo::CheckFormattingAndDirection(Terminator &terminator,
- const char *what, bool unformatted, Direction direction) {
+Iostat ChildIo::CheckFormattingAndDirection(
+ bool unformatted, Direction direction) {
bool parentIsInput{!parent_.get_if<IoDirectionState<Direction::Output>>()};
bool parentIsFormatted{parentIsInput
? parent_.get_if<FormattedIoStatementState<Direction::Input>>() !=
nullptr};
bool parentIsUnformatted{!parentIsFormatted};
if (unformatted != parentIsUnformatted) {
- terminator.Crash("Child %s attempted on %s parent I/O unit", what,
- parentIsUnformatted ? "unformatted" : "formatted");
- return false;
+ return unformatted ? IostatUnformattedChildOnFormattedParent
+ : IostatFormattedChildOnUnformattedParent;
} else if (parentIsInput != (direction == Direction::Input)) {
- terminator.Crash("Child %s attempted on %s parent I/O unit", what,
- parentIsInput ? "input" : "output");
- return false;
+ return parentIsInput ? IostatChildOutputToInputParent
+ : IostatChildInputFromOutputParent;
} else {
- return true;
+ return IostatOk;
}
}