Mercurial > hg > CbC > CbC_llvm
diff flang/runtime/io-error.cpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | |
children | 2e18cbf3894f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flang/runtime/io-error.cpp Mon May 25 11:55:54 2020 +0900 @@ -0,0 +1,108 @@ +//===-- runtime/io-error.cpp ------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "io-error.h" +#include "config.h" +#include "magic-numbers.h" +#include "tools.h" +#include <cerrno> +#include <cstdarg> +#include <cstdio> +#include <cstring> + +namespace Fortran::runtime::io { + +void IoErrorHandler::Begin(const char *sourceFileName, int sourceLine) { + flags_ = 0; + ioStat_ = 0; + ioMsg_.reset(); + SetLocation(sourceFileName, sourceLine); +} + +void IoErrorHandler::SignalError(int iostatOrErrno, const char *msg, ...) { + if (iostatOrErrno == IostatEnd && (flags_ & hasEnd)) { + if (!ioStat_ || ioStat_ < IostatEnd) { + ioStat_ = IostatEnd; + } + } else if (iostatOrErrno == IostatEor && (flags_ & hasEor)) { + if (!ioStat_ || ioStat_ < IostatEor) { + ioStat_ = IostatEor; // least priority + } + } else if (iostatOrErrno != IostatOk) { + if (flags_ & (hasIoStat | hasErr)) { + if (ioStat_ <= 0) { + ioStat_ = iostatOrErrno; // priority over END=/EOR= + if (msg && (flags_ & hasIoMsg)) { + char buffer[256]; + va_list ap; + va_start(ap, msg); + std::vsnprintf(buffer, sizeof buffer, msg, ap); + ioMsg_ = SaveDefaultCharacter(buffer, std::strlen(buffer) + 1, *this); + } + } + } else if (msg) { + va_list ap; + va_start(ap, msg); + CrashArgs(msg, ap); + } else if (const char *errstr{IostatErrorString(iostatOrErrno)}) { + Crash(errstr); + } else { + Crash("I/O error (errno=%d): %s", iostatOrErrno, + std::strerror(iostatOrErrno)); + } + } +} + +void IoErrorHandler::SignalError(int iostatOrErrno) { + SignalError(iostatOrErrno, nullptr); +} + +void IoErrorHandler::SignalErrno() { SignalError(errno); } + +void IoErrorHandler::SignalEnd() { SignalError(IostatEnd); } + +void IoErrorHandler::SignalEor() { SignalError(IostatEor); } + +bool IoErrorHandler::GetIoMsg(char *buffer, std::size_t bufferLength) { + const char *msg{ioMsg_.get()}; + if (!msg) { + msg = IostatErrorString(ioStat_); + } + if (msg) { + ToFortranDefaultCharacter(buffer, bufferLength, msg); + return true; + } + + char *newBuf; + // Following code is taken from llvm/lib/Support/Errno.cpp + // in LLVM v9.0.1 +#if HAVE_STRERROR_R + // strerror_r is thread-safe. +#if defined(__GLIBC__) && defined(_GNU_SOURCE) + // glibc defines its own incompatible version of strerror_r + // which may not use the buffer supplied. + newBuf = ::strerror_r(ioStat_, buffer, bufferLength); +#else + return ::strerror_r(ioStat_, buffer, bufferLength) == 0; +#endif +#elif HAVE_DECL_STRERROR_S // "Windows Secure API" + return ::strerror_s(buffer, bufferLength, ioStat_) == 0; +#elif HAVE_STRERROR + // Copy the thread un-safe result of strerror into + // the buffer as fast as possible to minimize impact + // of collision of strerror in multiple threads. + newBuf = strerror(ioStat_); +#else + // Strange that this system doesn't even have strerror + return false; +#endif + ::strncpy(buffer, newBuf, bufferLength - 1); + buffer[bufferLength - 1] = '\n'; + return true; +} +} // namespace Fortran::runtime::io