llvm-project
163 строки · 5.4 Кб
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
21namespace Fortran::runtime::io {
22RT_EXT_API_GROUP_BEGIN
23
24Cookie IODEF(BeginExternalListOutput)(
25ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
26return BeginExternalListIO<Direction::Output, ExternalListIoStatementState>(
27unitNumber, sourceFile, sourceLine);
28}
29
30enum Iostat IODEF(EndIoStatement)(Cookie cookie) {
31IoStatementState &io{*cookie};
32return static_cast<enum Iostat>(io.EndIoStatement());
33}
34
35template <int KIND, typename INT = CppTypeFor<TypeCategory::Integer, KIND>>
36inline RT_API_ATTRS bool FormattedScalarIntegerOutput(
37IoStatementState &io, INT x, const char *whence) {
38if (io.CheckFormattedStmtType<Direction::Output>(whence)) {
39auto edit{io.GetNextDataEdit()};
40return edit && EditIntegerOutput<KIND>(io, *edit, x);
41} else {
42return false;
43}
44}
45
46bool IODEF(OutputInteger8)(Cookie cookie, std::int8_t n) {
47return FormattedScalarIntegerOutput<1>(*cookie, n, "OutputInteger8");
48}
49
50bool IODEF(OutputInteger16)(Cookie cookie, std::int16_t n) {
51return FormattedScalarIntegerOutput<2>(*cookie, n, "OutputInteger16");
52}
53
54bool IODEF(OutputInteger32)(Cookie cookie, std::int32_t n) {
55return FormattedScalarIntegerOutput<4>(*cookie, n, "OutputInteger32");
56}
57
58bool IODEF(OutputInteger64)(Cookie cookie, std::int64_t n) {
59return FormattedScalarIntegerOutput<8>(*cookie, n, "OutputInteger64");
60}
61
62#ifdef __SIZEOF_INT128__
63bool IODEF(OutputInteger128)(Cookie cookie, common::int128_t n) {
64return FormattedScalarIntegerOutput<16>(*cookie, n, "OutputInteger128");
65}
66#endif
67
68template <int KIND,
69typename REAL = typename RealOutputEditing<KIND>::BinaryFloatingPoint>
70inline RT_API_ATTRS bool FormattedScalarRealOutput(
71IoStatementState &io, REAL x, const char *whence) {
72if (io.CheckFormattedStmtType<Direction::Output>(whence)) {
73auto edit{io.GetNextDataEdit()};
74return edit && RealOutputEditing<KIND>{io, x}.Edit(*edit);
75} else {
76return false;
77}
78}
79
80bool IODEF(OutputReal32)(Cookie cookie, float x) {
81return FormattedScalarRealOutput<4>(*cookie, x, "OutputReal32");
82}
83
84bool IODEF(OutputReal64)(Cookie cookie, double x) {
85return FormattedScalarRealOutput<8>(*cookie, x, "OutputReal64");
86}
87
88template <int KIND,
89typename REAL = typename RealOutputEditing<KIND>::BinaryFloatingPoint>
90inline RT_API_ATTRS bool FormattedScalarComplexOutput(
91IoStatementState &io, REAL re, REAL im, const char *whence) {
92if (io.CheckFormattedStmtType<Direction::Output>(whence)) {
93if (io.get_if<ListDirectedStatementState<Direction::Output>>() != nullptr) {
94DataEdit rEdit, iEdit;
95rEdit.descriptor = DataEdit::ListDirectedRealPart;
96iEdit.descriptor = DataEdit::ListDirectedImaginaryPart;
97rEdit.modes = iEdit.modes = io.mutableModes();
98return RealOutputEditing<KIND>{io, re}.Edit(rEdit) &&
99RealOutputEditing<KIND>{io, im}.Edit(iEdit);
100} else {
101auto reEdit{io.GetNextDataEdit()};
102if (reEdit && RealOutputEditing<KIND>{io, re}.Edit(*reEdit)) {
103auto imEdit{io.GetNextDataEdit()};
104return imEdit && RealOutputEditing<KIND>{io, im}.Edit(*imEdit);
105}
106}
107}
108return false;
109}
110
111bool IODEF(OutputComplex32)(Cookie cookie, float re, float im) {
112return FormattedScalarComplexOutput<4>(*cookie, re, im, "OutputComplex32");
113}
114
115bool IODEF(OutputComplex64)(Cookie cookie, double re, double im) {
116return FormattedScalarComplexOutput<8>(*cookie, re, im, "OutputComplex64");
117}
118
119bool IODEF(OutputAscii)(Cookie cookie, const char *x, std::size_t length) {
120IoStatementState &io{*cookie};
121if (!x) {
122io.GetIoErrorHandler().Crash("Null address for character output item");
123} else if (auto *listOutput{
124io.get_if<ListDirectedStatementState<Direction::Output>>()}) {
125return ListDirectedCharacterOutput(io, *listOutput, x, length);
126} else if (io.CheckFormattedStmtType<Direction::Output>("OutputAscii")) {
127auto edit{io.GetNextDataEdit()};
128return edit && EditCharacterOutput(io, *edit, x, length);
129} else {
130return false;
131}
132}
133
134bool IODEF(OutputLogical)(Cookie cookie, bool truth) {
135IoStatementState &io{*cookie};
136if (auto *listOutput{
137io.get_if<ListDirectedStatementState<Direction::Output>>()}) {
138return ListDirectedLogicalOutput(io, *listOutput, truth);
139} else if (io.CheckFormattedStmtType<Direction::Output>("OutputAscii")) {
140auto edit{io.GetNextDataEdit()};
141return edit && EditLogicalOutput(io, *edit, truth);
142} else {
143return 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
153void std::__libcpp_verbose_abort(char const *format, ...) {
154va_list list;
155va_start(list, format);
156std::vfprintf(stderr, format, list);
157va_end(list);
158
159std::abort();
160}
161#endif
162
163RT_EXT_API_GROUP_END
164