//===-- runtime/io-api-common.h ---------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef FLANG_RUNTIME_IO_API_COMMON_H_ #define FLANG_RUNTIME_IO_API_COMMON_H_ #include "io-stmt.h" #include "terminator.h" #include "unit.h" #include "flang/Common/api-attrs.h" #include "flang/Common/optional.h" #include "flang/Runtime/io-api.h" namespace Fortran::runtime::io { static inline RT_API_ATTRS Cookie NoopUnit(const Terminator &terminator, int unitNumber, enum Iostat iostat = IostatOk) { Cookie cookie{&New{terminator}( terminator.sourceFileName(), terminator.sourceLine(), unitNumber) .release() ->ioStatementState()}; if (iostat != IostatOk) { cookie->GetIoErrorHandler().SetPendingError(iostat); } return cookie; } static inline RT_API_ATTRS ExternalFileUnit *GetOrCreateUnit(int unitNumber, Direction direction, Fortran::common::optional isUnformatted, const Terminator &terminator, Cookie &errorCookie) { IoErrorHandler handler{terminator}; handler.HasIoStat(); if (ExternalFileUnit * unit{ExternalFileUnit::LookUpOrCreateAnonymous( unitNumber, direction, isUnformatted, handler)}) { errorCookie = nullptr; return unit; } else { auto iostat{static_cast(handler.GetIoStat())}; errorCookie = NoopUnit(terminator, unitNumber, iostat != IostatOk ? iostat : IostatBadUnitNumber); return nullptr; } } template class STATE, typename... A> RT_API_ATTRS Cookie BeginExternalListIO( int unitNumber, const char *sourceFile, int sourceLine, A &&...xs) { Terminator terminator{sourceFile, sourceLine}; Cookie errorCookie{nullptr}; ExternalFileUnit *unit{GetOrCreateUnit( unitNumber, DIR, false /*!unformatted*/, terminator, errorCookie)}; if (!unit) { return errorCookie; } if (!unit->isUnformatted.has_value()) { unit->isUnformatted = false; } Iostat iostat{IostatOk}; if (*unit->isUnformatted) { iostat = IostatFormattedIoOnUnformattedUnit; } if (ChildIo * child{unit->GetChildIo()}) { if (iostat == IostatOk) { iostat = child->CheckFormattingAndDirection(false, DIR); } if (iostat == IostatOk) { return &child->BeginIoStatement>( *child, sourceFile, sourceLine); } else { return &child->BeginIoStatement( iostat, nullptr /* no unit */, sourceFile, sourceLine); } } else { if (iostat == IostatOk && unit->access == Access::Direct) { iostat = IostatListIoOnDirectAccessUnit; } if (iostat == IostatOk) { iostat = unit->SetDirection(DIR); } if (iostat == IostatOk) { return &unit->BeginIoStatement>( terminator, std::forward(xs)..., *unit, sourceFile, sourceLine); } else { return &unit->BeginIoStatement( terminator, iostat, unit, sourceFile, sourceLine); } } } } // namespace Fortran::runtime::io #endif // FLANG_RUNTIME_IO_API_COMMON_H_