1651f58bfSDiana Picus //===-- runtime/stop.cpp --------------------------------------------------===//
2352d347aSAlexis Perry //
3352d347aSAlexis Perry // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4352d347aSAlexis Perry // See https://llvm.org/LICENSE.txt for license information.
5352d347aSAlexis Perry // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6352d347aSAlexis Perry //
7352d347aSAlexis Perry //===----------------------------------------------------------------------===//
8352d347aSAlexis Perry
9830c0b90SPeter Klausler #include "flang/Runtime/stop.h"
104a0af824SPeter Klausler #include "environment.h"
115d5b9682Speter klausler #include "file.h"
12f7be2518Speter klausler #include "io-error.h"
13352d347aSAlexis Perry #include "terminator.h"
14f7be2518Speter klausler #include "unit.h"
15352d347aSAlexis Perry #include <cfenv>
16352d347aSAlexis Perry #include <cstdio>
17352d347aSAlexis Perry #include <cstdlib>
18352d347aSAlexis Perry
19352d347aSAlexis Perry extern "C" {
20352d347aSAlexis Perry
DescribeIEEESignaledExceptions()21352d347aSAlexis Perry static void DescribeIEEESignaledExceptions() {
22352d347aSAlexis Perry #ifdef fetestexcept // a macro in some environments; omit std::
23352d347aSAlexis Perry auto excepts{fetestexcept(FE_ALL_EXCEPT)};
24352d347aSAlexis Perry #else
25352d347aSAlexis Perry auto excepts{std::fetestexcept(FE_ALL_EXCEPT)};
26352d347aSAlexis Perry #endif
27352d347aSAlexis Perry if (excepts) {
28352d347aSAlexis Perry std::fputs("IEEE arithmetic exceptions signaled:", stderr);
29352d347aSAlexis Perry if (excepts & FE_DIVBYZERO) {
30352d347aSAlexis Perry std::fputs(" DIVBYZERO", stderr);
31352d347aSAlexis Perry }
32352d347aSAlexis Perry if (excepts & FE_INEXACT) {
33352d347aSAlexis Perry std::fputs(" INEXACT", stderr);
34352d347aSAlexis Perry }
35352d347aSAlexis Perry if (excepts & FE_INVALID) {
36352d347aSAlexis Perry std::fputs(" INVALID", stderr);
37352d347aSAlexis Perry }
38352d347aSAlexis Perry if (excepts & FE_OVERFLOW) {
39352d347aSAlexis Perry std::fputs(" OVERFLOW", stderr);
40352d347aSAlexis Perry }
41352d347aSAlexis Perry if (excepts & FE_UNDERFLOW) {
42352d347aSAlexis Perry std::fputs(" UNDERFLOW", stderr);
43352d347aSAlexis Perry }
44cbff0c75Speter klausler std::fputc('\n', stderr);
45352d347aSAlexis Perry }
46352d347aSAlexis Perry }
47352d347aSAlexis Perry
CloseAllExternalUnits(const char * why)4827505565Speter klausler static void CloseAllExternalUnits(const char *why) {
4927505565Speter klausler Fortran::runtime::io::IoErrorHandler handler{why};
5027505565Speter klausler Fortran::runtime::io::ExternalFileUnit::CloseAll(handler);
5127505565Speter klausler }
5227505565Speter klausler
RTNAME(StopStatement)53352d347aSAlexis Perry [[noreturn]] void RTNAME(StopStatement)(
54352d347aSAlexis Perry int code, bool isErrorStop, bool quiet) {
5527505565Speter klausler CloseAllExternalUnits("STOP statement");
564a0af824SPeter Klausler if (Fortran::runtime::executionEnvironment.noStopMessage && code == 0) {
574a0af824SPeter Klausler quiet = true;
584a0af824SPeter Klausler }
59352d347aSAlexis Perry if (!quiet) {
60cbff0c75Speter klausler std::fprintf(stderr, "Fortran %s", isErrorStop ? "ERROR STOP" : "STOP");
61352d347aSAlexis Perry if (code != EXIT_SUCCESS) {
62cbff0c75Speter klausler std::fprintf(stderr, ": code %d\n", code);
63352d347aSAlexis Perry }
64cbff0c75Speter klausler std::fputc('\n', stderr);
65352d347aSAlexis Perry DescribeIEEESignaledExceptions();
66352d347aSAlexis Perry }
67352d347aSAlexis Perry std::exit(code);
68352d347aSAlexis Perry }
69352d347aSAlexis Perry
RTNAME(StopStatementText)70352d347aSAlexis Perry [[noreturn]] void RTNAME(StopStatementText)(
713261aefcSpeter klausler const char *code, std::size_t length, bool isErrorStop, bool quiet) {
7227505565Speter klausler CloseAllExternalUnits("STOP statement");
73352d347aSAlexis Perry if (!quiet) {
747796d81aSJean Perier if (Fortran::runtime::executionEnvironment.noStopMessage && !isErrorStop) {
757796d81aSJean Perier std::fprintf(stderr, "%.*s\n", static_cast<int>(length), code);
767796d81aSJean Perier } else {
773261aefcSpeter klausler std::fprintf(stderr, "Fortran %s: %.*s\n",
783261aefcSpeter klausler isErrorStop ? "ERROR STOP" : "STOP", static_cast<int>(length), code);
797796d81aSJean Perier }
80352d347aSAlexis Perry DescribeIEEESignaledExceptions();
81352d347aSAlexis Perry }
827796d81aSJean Perier if (isErrorStop) {
83352d347aSAlexis Perry std::exit(EXIT_FAILURE);
847796d81aSJean Perier } else {
857796d81aSJean Perier std::exit(EXIT_SUCCESS);
867796d81aSJean Perier }
87352d347aSAlexis Perry }
88352d347aSAlexis Perry
StartPause()893261aefcSpeter klausler static bool StartPause() {
905d5b9682Speter klausler if (Fortran::runtime::io::IsATerminal(0)) {
915d5b9682Speter klausler Fortran::runtime::io::IoErrorHandler handler{"PAUSE statement"};
925d5b9682Speter klausler Fortran::runtime::io::ExternalFileUnit::FlushAll(handler);
933261aefcSpeter klausler return true;
943261aefcSpeter klausler }
953261aefcSpeter klausler return false;
963261aefcSpeter klausler }
973261aefcSpeter klausler
EndPause()983261aefcSpeter klausler static void EndPause() {
995d5b9682Speter klausler std::fflush(nullptr);
1005d5b9682Speter klausler if (std::fgetc(stdin) == EOF) {
1015d5b9682Speter klausler CloseAllExternalUnits("PAUSE statement");
1025d5b9682Speter klausler std::exit(EXIT_SUCCESS);
1035d5b9682Speter klausler }
1045d5b9682Speter klausler }
1053261aefcSpeter klausler
RTNAME(PauseStatement)1063261aefcSpeter klausler void RTNAME(PauseStatement)() {
1073261aefcSpeter klausler if (StartPause()) {
1083261aefcSpeter klausler std::fputs("Fortran PAUSE: hit RETURN to continue:", stderr);
1093261aefcSpeter klausler EndPause();
1103261aefcSpeter klausler }
1113261aefcSpeter klausler }
1123261aefcSpeter klausler
RTNAME(PauseStatementInt)1133261aefcSpeter klausler void RTNAME(PauseStatementInt)(int code) {
1143261aefcSpeter klausler if (StartPause()) {
1153261aefcSpeter klausler std::fprintf(stderr, "Fortran PAUSE %d: hit RETURN to continue:", code);
1163261aefcSpeter klausler EndPause();
1173261aefcSpeter klausler }
1183261aefcSpeter klausler }
1193261aefcSpeter klausler
RTNAME(PauseStatementText)1203261aefcSpeter klausler void RTNAME(PauseStatementText)(const char *code, std::size_t length) {
1213261aefcSpeter klausler if (StartPause()) {
1223261aefcSpeter klausler std::fprintf(stderr,
1233261aefcSpeter klausler "Fortran PAUSE %.*s: hit RETURN to continue:", static_cast<int>(length),
1243261aefcSpeter klausler code);
1253261aefcSpeter klausler EndPause();
1263261aefcSpeter klausler }
1275d5b9682Speter klausler }
1285d5b9682Speter klausler
RTNAME(FailImageStatement)129352d347aSAlexis Perry [[noreturn]] void RTNAME(FailImageStatement)() {
130352d347aSAlexis Perry Fortran::runtime::NotifyOtherImagesOfFailImageStatement();
13127505565Speter klausler CloseAllExternalUnits("FAIL IMAGE statement");
132352d347aSAlexis Perry std::exit(EXIT_FAILURE);
133352d347aSAlexis Perry }
134f7be2518Speter klausler
RTNAME(ProgramEndStatement)135f7be2518Speter klausler [[noreturn]] void RTNAME(ProgramEndStatement)() {
13627505565Speter klausler CloseAllExternalUnits("END statement");
137f7be2518Speter klausler std::exit(EXIT_SUCCESS);
138f7be2518Speter klausler }
139faa18428Speter klausler
RTNAME(Exit)140faa18428Speter klausler [[noreturn]] void RTNAME(Exit)(int status) {
141faa18428Speter klausler CloseAllExternalUnits("CALL EXIT()");
142faa18428Speter klausler std::exit(status);
143faa18428Speter klausler }
144faa18428Speter klausler
RTNAME(Abort)145faa18428Speter klausler [[noreturn]] void RTNAME(Abort)() { std::abort(); }
146eb933225SPeter Steinfeld
RTNAME(ReportFatalUserError)147*93ee5882SPeter Steinfeld [[noreturn]] void RTNAME(ReportFatalUserError)(
148eb933225SPeter Steinfeld const char *message, const char *source, int line) {
149eb933225SPeter Steinfeld Fortran::runtime::Terminator{source, line}.Crash(message);
150eb933225SPeter Steinfeld }
151352d347aSAlexis Perry }
152