1 //===-- runtime/io-api-common.h ---------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
19 namespace Fortran::runtime::io
{
21 static 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
);
33 static 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
);
51 template <Direction
DIR, template <Direction
> class STATE
, typename
... A
>
52 RT_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 /*!unformatted*/, 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 /* no unit */, 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
);
96 } // namespace Fortran::runtime::io
97 #endif // FLANG_RUNTIME_IO_API_COMMON_H_