//===-- runtime/stop.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 "stop.h" #include "file.h" #include "io-error.h" #include "terminator.h" #include "unit.h" #include #include #include extern "C" { static void DescribeIEEESignaledExceptions() { #ifdef fetestexcept // a macro in some environments; omit std:: auto excepts{fetestexcept(FE_ALL_EXCEPT)}; #else auto excepts{std::fetestexcept(FE_ALL_EXCEPT)}; #endif if (excepts) { std::fputs("IEEE arithmetic exceptions signaled:", stderr); if (excepts & FE_DIVBYZERO) { std::fputs(" DIVBYZERO", stderr); } if (excepts & FE_INEXACT) { std::fputs(" INEXACT", stderr); } if (excepts & FE_INVALID) { std::fputs(" INVALID", stderr); } if (excepts & FE_OVERFLOW) { std::fputs(" OVERFLOW", stderr); } if (excepts & FE_UNDERFLOW) { std::fputs(" UNDERFLOW", stderr); } } } static void CloseAllExternalUnits(const char *why) { Fortran::runtime::io::IoErrorHandler handler{why}; Fortran::runtime::io::ExternalFileUnit::CloseAll(handler); } [[noreturn]] void RTNAME(StopStatement)( int code, bool isErrorStop, bool quiet) { CloseAllExternalUnits("STOP statement"); if (!quiet) { if (code != EXIT_SUCCESS) { std::fprintf(stderr, "Fortran %s: code %d\n", isErrorStop ? "ERROR STOP" : "STOP", code); } DescribeIEEESignaledExceptions(); } std::exit(code); } [[noreturn]] void RTNAME(StopStatementText)( const char *code, bool isErrorStop, bool quiet) { CloseAllExternalUnits("STOP statement"); if (!quiet) { std::fprintf( stderr, "Fortran %s: %s\n", isErrorStop ? "ERROR STOP" : "STOP", code); DescribeIEEESignaledExceptions(); } std::exit(EXIT_FAILURE); } void RTNAME(PauseStatement)() { if (Fortran::runtime::io::IsATerminal(0)) { Fortran::runtime::io::IoErrorHandler handler{"PAUSE statement"}; Fortran::runtime::io::ExternalFileUnit::FlushAll(handler); std::fputs("Fortran PAUSE: hit RETURN to continue:", stderr); std::fflush(nullptr); if (std::fgetc(stdin) == EOF) { CloseAllExternalUnits("PAUSE statement"); std::exit(EXIT_SUCCESS); } } } [[noreturn]] void RTNAME(FailImageStatement)() { Fortran::runtime::NotifyOtherImagesOfFailImageStatement(); CloseAllExternalUnits("FAIL IMAGE statement"); std::exit(EXIT_FAILURE); } [[noreturn]] void RTNAME(ProgramEndStatement)() { CloseAllExternalUnits("END statement"); std::exit(EXIT_SUCCESS); } }