1 //===-- runtime/io-api-minimal.cpp ----------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // Implements the subset of the I/O statement API needed for basic
10 // list-directed output (PRINT *) of intrinsic types.
12 #include "edit-output.h"
14 #include "io-api-common.h"
16 #include "terminator.h"
19 #include "flang/Runtime/io-api.h"
21 namespace Fortran::runtime::io
{
22 RT_EXT_API_GROUP_BEGIN
24 Cookie
IODEF(BeginExternalListOutput
)(
25 ExternalUnit unitNumber
, const char *sourceFile
, int sourceLine
) {
26 return BeginExternalListIO
<Direction::Output
, ExternalListIoStatementState
>(
27 unitNumber
, sourceFile
, sourceLine
);
30 enum Iostat
IODEF(EndIoStatement
)(Cookie cookie
) {
31 IoStatementState
&io
{*cookie
};
32 return static_cast<enum Iostat
>(io
.EndIoStatement());
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
);
46 bool IODEF(OutputInteger8
)(Cookie cookie
, std::int8_t n
) {
47 return FormattedScalarIntegerOutput
<1>(*cookie
, n
, "OutputInteger8");
50 bool IODEF(OutputInteger16
)(Cookie cookie
, std::int16_t n
) {
51 return FormattedScalarIntegerOutput
<2>(*cookie
, n
, "OutputInteger16");
54 bool IODEF(OutputInteger32
)(Cookie cookie
, std::int32_t n
) {
55 return FormattedScalarIntegerOutput
<4>(*cookie
, n
, "OutputInteger32");
58 bool IODEF(OutputInteger64
)(Cookie cookie
, std::int64_t n
) {
59 return FormattedScalarIntegerOutput
<8>(*cookie
, n
, "OutputInteger64");
62 #ifdef __SIZEOF_INT128__
63 bool IODEF(OutputInteger128
)(Cookie cookie
, common::int128_t n
) {
64 return FormattedScalarIntegerOutput
<16>(*cookie
, n
, "OutputInteger128");
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
);
80 bool IODEF(OutputReal32
)(Cookie cookie
, float x
) {
81 return FormattedScalarRealOutput
<4>(*cookie
, x
, "OutputReal32");
84 bool IODEF(OutputReal64
)(Cookie cookie
, double x
) {
85 return FormattedScalarRealOutput
<8>(*cookie
, x
, "OutputReal64");
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
);
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
);
111 bool IODEF(OutputComplex32
)(Cookie cookie
, float re
, float im
) {
112 return FormattedScalarComplexOutput
<4>(*cookie
, re
, im
, "OutputComplex32");
115 bool IODEF(OutputComplex64
)(Cookie cookie
, double re
, double im
) {
116 return FormattedScalarComplexOutput
<8>(*cookie
, re
, im
, "OutputComplex64");
119 bool IODEF(OutputAscii
)(Cookie cookie
, const char *x
, std::size_t length
) {
120 IoStatementState
&io
{*cookie
};
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
);
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
);
147 } // namespace Fortran::runtime::io
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++.
153 void std::__libcpp_verbose_abort(char const *format
, ...) {
155 va_start(list
, format
);
156 std::vfprintf(stderr
, format
, list
);