1 //===-- runtime/io-api-minimal.cpp ----------------------------------------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Implements the subset of the I/O statement API needed for basic 10 // list-directed output (PRINT *) of intrinsic types. 11 12 #include "edit-output.h" 13 #include "format.h" 14 #include "io-api-common.h" 15 #include "io-stmt.h" 16 #include "terminator.h" 17 #include "tools.h" 18 #include "unit.h" 19 #include "flang/Runtime/io-api.h" 20 21 namespace Fortran::runtime::io { 22 RT_EXT_API_GROUP_BEGIN 23 24 Cookie IODEF(BeginExternalListOutput)( 25 ExternalUnit unitNumber, const char *sourceFile, int sourceLine) { 26 return BeginExternalListIO<Direction::Output, ExternalListIoStatementState>( 27 unitNumber, sourceFile, sourceLine); 28 } 29 30 enum Iostat IODEF(EndIoStatement)(Cookie cookie) { 31 IoStatementState &io{*cookie}; 32 return static_cast<enum Iostat>(io.EndIoStatement()); 33 } 34 35 template <int KIND, typename INT = CppTypeFor<TypeCategory::Integer, KIND>> 36 inline RT_API_ATTRS bool FormattedScalarIntegerOutput( 37 IoStatementState &io, INT x, const char *whence) { 38 if (io.CheckFormattedStmtType<Direction::Output>(whence)) { 39 auto edit{io.GetNextDataEdit()}; 40 return edit && EditIntegerOutput<KIND>(io, *edit, x, /*isSigned=*/true); 41 } else { 42 return false; 43 } 44 } 45 46 bool IODEF(OutputInteger8)(Cookie cookie, std::int8_t n) { 47 return FormattedScalarIntegerOutput<1>(*cookie, n, "OutputInteger8"); 48 } 49 50 bool IODEF(OutputInteger16)(Cookie cookie, std::int16_t n) { 51 return FormattedScalarIntegerOutput<2>(*cookie, n, "OutputInteger16"); 52 } 53 54 bool IODEF(OutputInteger32)(Cookie cookie, std::int32_t n) { 55 return FormattedScalarIntegerOutput<4>(*cookie, n, "OutputInteger32"); 56 } 57 58 bool IODEF(OutputInteger64)(Cookie cookie, std::int64_t n) { 59 return FormattedScalarIntegerOutput<8>(*cookie, n, "OutputInteger64"); 60 } 61 62 #ifdef __SIZEOF_INT128__ 63 bool IODEF(OutputInteger128)(Cookie cookie, common::int128_t n) { 64 return FormattedScalarIntegerOutput<16>(*cookie, n, "OutputInteger128"); 65 } 66 #endif 67 68 template <int KIND, 69 typename REAL = typename RealOutputEditing<KIND>::BinaryFloatingPoint> 70 inline RT_API_ATTRS bool FormattedScalarRealOutput( 71 IoStatementState &io, REAL x, const char *whence) { 72 if (io.CheckFormattedStmtType<Direction::Output>(whence)) { 73 auto edit{io.GetNextDataEdit()}; 74 return edit && RealOutputEditing<KIND>{io, x}.Edit(*edit); 75 } else { 76 return false; 77 } 78 } 79 80 bool IODEF(OutputReal32)(Cookie cookie, float x) { 81 return FormattedScalarRealOutput<4>(*cookie, x, "OutputReal32"); 82 } 83 84 bool IODEF(OutputReal64)(Cookie cookie, double x) { 85 return FormattedScalarRealOutput<8>(*cookie, x, "OutputReal64"); 86 } 87 88 template <int KIND, 89 typename REAL = typename RealOutputEditing<KIND>::BinaryFloatingPoint> 90 inline RT_API_ATTRS bool FormattedScalarComplexOutput( 91 IoStatementState &io, REAL re, REAL im, const char *whence) { 92 if (io.CheckFormattedStmtType<Direction::Output>(whence)) { 93 if (io.get_if<ListDirectedStatementState<Direction::Output>>() != nullptr) { 94 DataEdit rEdit, iEdit; 95 rEdit.descriptor = DataEdit::ListDirectedRealPart; 96 iEdit.descriptor = DataEdit::ListDirectedImaginaryPart; 97 rEdit.modes = iEdit.modes = io.mutableModes(); 98 return RealOutputEditing<KIND>{io, re}.Edit(rEdit) && 99 RealOutputEditing<KIND>{io, im}.Edit(iEdit); 100 } else { 101 auto reEdit{io.GetNextDataEdit()}; 102 if (reEdit && RealOutputEditing<KIND>{io, re}.Edit(*reEdit)) { 103 auto imEdit{io.GetNextDataEdit()}; 104 return imEdit && RealOutputEditing<KIND>{io, im}.Edit(*imEdit); 105 } 106 } 107 } 108 return false; 109 } 110 111 bool IODEF(OutputComplex32)(Cookie cookie, float re, float im) { 112 return FormattedScalarComplexOutput<4>(*cookie, re, im, "OutputComplex32"); 113 } 114 115 bool IODEF(OutputComplex64)(Cookie cookie, double re, double im) { 116 return FormattedScalarComplexOutput<8>(*cookie, re, im, "OutputComplex64"); 117 } 118 119 bool IODEF(OutputAscii)(Cookie cookie, const char *x, std::size_t length) { 120 IoStatementState &io{*cookie}; 121 if (!x) { 122 io.GetIoErrorHandler().Crash("Null address for character output item"); 123 } else if (auto *listOutput{ 124 io.get_if<ListDirectedStatementState<Direction::Output>>()}) { 125 return ListDirectedCharacterOutput(io, *listOutput, x, length); 126 } else if (io.CheckFormattedStmtType<Direction::Output>("OutputAscii")) { 127 auto edit{io.GetNextDataEdit()}; 128 return edit && EditCharacterOutput(io, *edit, x, length); 129 } else { 130 return false; 131 } 132 } 133 134 bool IODEF(OutputLogical)(Cookie cookie, bool truth) { 135 IoStatementState &io{*cookie}; 136 if (auto *listOutput{ 137 io.get_if<ListDirectedStatementState<Direction::Output>>()}) { 138 return ListDirectedLogicalOutput(io, *listOutput, truth); 139 } else if (io.CheckFormattedStmtType<Direction::Output>("OutputAscii")) { 140 auto edit{io.GetNextDataEdit()}; 141 return edit && EditLogicalOutput(io, *edit, truth); 142 } else { 143 return false; 144 } 145 } 146 147 } // namespace Fortran::runtime::io 148 149 #if defined(_LIBCPP_VERBOSE_ABORT) 150 // Provide own definition for `std::__libcpp_verbose_abort` to avoid dependency 151 // on the version provided by libc++. 152 153 void std::__libcpp_verbose_abort(char const *format, ...) { 154 va_list list; 155 va_start(list, format); 156 std::vfprintf(stderr, format, list); 157 va_end(list); 158 159 std::abort(); 160 } 161 #endif 162 163 RT_EXT_API_GROUP_END 164