9#ifndef FLANG_RUNTIME_IO_API_COMMON_H_
10#define FLANG_RUNTIME_IO_API_COMMON_H_
13#include "terminator.h"
15#include "flang/Common/api-attrs.h"
16#include "flang/Common/optional.h"
17#include "flang/Runtime/io-api.h"
19namespace Fortran::runtime::io {
21static inline RT_API_ATTRS Cookie NoopUnit(
const Terminator &terminator,
22 int unitNumber,
enum Iostat iostat = IostatOk) {
23 Cookie cookie{&New<NoopStatementState>{terminator}(
24 terminator.sourceFileName(), terminator.sourceLine(), unitNumber)
26 ->ioStatementState()};
27 if (iostat != IostatOk) {
28 cookie->GetIoErrorHandler().SetPendingError(iostat);
33static inline RT_API_ATTRS ExternalFileUnit *GetOrCreateUnit(
int unitNumber,
34 Direction direction, Fortran::common::optional<bool> isUnformatted,
35 const Terminator &terminator, Cookie &errorCookie) {
36 IoErrorHandler handler{terminator};
38 if (ExternalFileUnit *
39 unit{ExternalFileUnit::LookUpOrCreateAnonymous(
40 unitNumber, direction, isUnformatted, handler)}) {
41 errorCookie =
nullptr;
44 auto iostat{
static_cast<enum Iostat
>(handler.GetIoStat())};
45 errorCookie = NoopUnit(terminator, unitNumber,
46 iostat != IostatOk ? iostat : IostatBadUnitNumber);
51template <Direction DIR,
template <Direction>
class STATE,
typename... A>
52RT_API_ATTRS Cookie BeginExternalListIO(
53 int unitNumber,
const char *sourceFile,
int sourceLine, A &&...xs) {
54 Terminator terminator{sourceFile, sourceLine};
55 Cookie errorCookie{
nullptr};
56 ExternalFileUnit *unit{GetOrCreateUnit(
57 unitNumber, DIR,
false , terminator, errorCookie)};
61 if (!unit->isUnformatted.has_value()) {
62 unit->isUnformatted =
false;
64 Iostat iostat{IostatOk};
65 if (*unit->isUnformatted) {
66 iostat = IostatFormattedIoOnUnformattedUnit;
68 if (ChildIo * child{unit->GetChildIo()}) {
69 if (iostat == IostatOk) {
70 iostat = child->CheckFormattingAndDirection(
false, DIR);
72 if (iostat == IostatOk) {
73 return &child->BeginIoStatement<ChildListIoStatementState<DIR>>(
74 *child, sourceFile, sourceLine);
76 return &child->BeginIoStatement<ErroneousIoStatementState>(
77 iostat,
nullptr , sourceFile, sourceLine);
80 if (iostat == IostatOk && unit->access == Access::Direct) {
81 iostat = IostatListIoOnDirectAccessUnit;
83 if (iostat == IostatOk) {
84 iostat = unit->SetDirection(DIR);
86 if (iostat == IostatOk) {
87 return &unit->BeginIoStatement<STATE<DIR>>(
88 terminator, std::forward<A>(xs)..., *unit, sourceFile, sourceLine);
90 return &unit->BeginIoStatement<ErroneousIoStatementState>(
91 terminator, iostat, unit, sourceFile, sourceLine);