98 lines · c
1//===-- lib/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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef FLANG_RT_RUNTIME_IO_API_COMMON_H_10#define FLANG_RT_RUNTIME_IO_API_COMMON_H_11 12#include "unit.h"13#include "flang-rt/runtime/io-stmt.h"14#include "flang-rt/runtime/terminator.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, 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 /*!unformatted*/, 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::io97#endif // FLANG_RT_RUNTIME_IO_API_COMMON_H_98