FLANG
io-api-common.h
1//===-- runtime/io-api-common.h ---------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FLANG_RUNTIME_IO_API_COMMON_H_
10#define FLANG_RUNTIME_IO_API_COMMON_H_
11
12#include "io-stmt.h"
13#include "terminator.h"
14#include "unit.h"
15#include "flang/Common/api-attrs.h"
16#include "flang/Common/optional.h"
17#include "flang/Runtime/io-api.h"
18
19namespace Fortran::runtime::io {
20
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)
25 .release()
26 ->ioStatementState()};
27 if (iostat != IostatOk) {
28 cookie->GetIoErrorHandler().SetPendingError(iostat);
29 }
30 return cookie;
31}
32
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};
37 handler.HasIoStat();
38 if (ExternalFileUnit *
39 unit{ExternalFileUnit::LookUpOrCreateAnonymous(
40 unitNumber, direction, isUnformatted, handler)}) {
41 errorCookie = nullptr;
42 return unit;
43 } else {
44 auto iostat{static_cast<enum Iostat>(handler.GetIoStat())};
45 errorCookie = NoopUnit(terminator, unitNumber,
46 iostat != IostatOk ? iostat : IostatBadUnitNumber);
47 return nullptr;
48 }
49}
50
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)};
58 if (!unit) {
59 return errorCookie;
60 }
61 if (!unit->isUnformatted.has_value()) {
62 unit->isUnformatted = false;
63 }
64 Iostat iostat{IostatOk};
65 if (*unit->isUnformatted) {
66 iostat = IostatFormattedIoOnUnformattedUnit;
67 }
68 if (ChildIo * child{unit->GetChildIo()}) {
69 if (iostat == IostatOk) {
70 iostat = child->CheckFormattingAndDirection(false, DIR);
71 }
72 if (iostat == IostatOk) {
73 return &child->BeginIoStatement<ChildListIoStatementState<DIR>>(
74 *child, sourceFile, sourceLine);
75 } else {
76 return &child->BeginIoStatement<ErroneousIoStatementState>(
77 iostat, nullptr /* no unit */, sourceFile, sourceLine);
78 }
79 } else {
80 if (iostat == IostatOk && unit->access == Access::Direct) {
81 iostat = IostatListIoOnDirectAccessUnit;
82 }
83 if (iostat == IostatOk) {
84 iostat = unit->SetDirection(DIR);
85 }
86 if (iostat == IostatOk) {
87 return &unit->BeginIoStatement<STATE<DIR>>(
88 terminator, std::forward<A>(xs)..., *unit, sourceFile, sourceLine);
89 } else {
90 return &unit->BeginIoStatement<ErroneousIoStatementState>(
91 terminator, iostat, unit, sourceFile, sourceLine);
92 }
93 }
94}
95
96} // namespace Fortran::runtime::io
97#endif // FLANG_RUNTIME_IO_API_COMMON_H_