FLANG

io-api.h
1 //===-- runtime/io-api.h ----------------------------------------*- C++ -*-===//
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 // Defines API between compiled code and I/O runtime library.
10
11 #ifndef FORTRAN_RUNTIME_IO_API_H_
12 #define FORTRAN_RUNTIME_IO_API_H_
13
14 #include "entry-names.h"
15 #include "iostat.h"
16 #include <cinttypes>
17 #include <cstddef>
18
19 namespace Fortran::runtime {
20 class Descriptor;
21 class NamelistGroup;
22 } // namespace Fortran::runtime
23
24 namespace Fortran::runtime::io {
25
26 class IoStatementState;
27 using Cookie = IoStatementState *;
28 using ExternalUnit = int;
29 using AsynchronousId = int;
30 static constexpr ExternalUnit DefaultUnit{-1}; // READ(*), WRITE(*), PRINT
31
32 extern "C" {
33
34 #define IONAME(name) RTNAME(io##name)
35
36 // These functions initiate data transfer statements (READ, WRITE, PRINT).
37 // Example: PRINT *, 666 is implemented as the series of calls:
38 // Cookie cookie{BeginExternalListOutput(DefaultUnit,__FILE__,__LINE__)};
39 // OutputInteger64(cookie, 666);
40 // EndIoStatement(cookie);
41
42 // Internal I/O initiation
43 // Internal I/O can loan the runtime library an optional block of memory
44 // in which the library can maintain state across the calls that implement
45 // the internal transfer; use of these blocks can reduce the need for dynamic
46 // memory allocation &/or thread-local storage. The block must be sufficiently
47 // aligned to hold a pointer.
48 constexpr std::size_t RecommendedInternalIoScratchAreaBytes(
49 int maxFormatParenthesesNestingDepth) {
50 return 32 + 8 * maxFormatParenthesesNestingDepth;
51 }
52
53 // Internal I/O to/from character arrays &/or non-default-kind character
54 // requires a descriptor, which is copied.
55 Cookie IONAME(BeginInternalArrayListOutput)(const Descriptor &,
56 void **scratchArea = nullptr, std::size_t scratchBytes = 0,
57 const char *sourceFile = nullptr, int sourceLine = 0);
58 Cookie IONAME(BeginInternalArrayListInput)(const Descriptor &,
59 void **scratchArea = nullptr, std::size_t scratchBytes = 0,
60 const char *sourceFile = nullptr, int sourceLine = 0);
61 Cookie IONAME(BeginInternalArrayFormattedOutput)(const Descriptor &,
62 const char *format, std::size_t formatLength, void **scratchArea = nullptr,
63 std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
64 int sourceLine = 0);
65 Cookie IONAME(BeginInternalArrayFormattedInput)(const Descriptor &,
66 const char *format, std::size_t formatLength, void **scratchArea = nullptr,
67 std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
68 int sourceLine = 0);
69
70 // Internal I/O to/from a default-kind character scalar can avoid a
71 // descriptor.
72 Cookie IONAME(BeginInternalListOutput)(char *internal,
73 std::size_t internalLength, void **scratchArea = nullptr,
74 std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
75 int sourceLine = 0);
76 Cookie IONAME(BeginInternalListInput)(const char *internal,
77 std::size_t internalLength, void **scratchArea = nullptr,
78 std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
79 int sourceLine = 0);
80 Cookie IONAME(BeginInternalFormattedOutput)(char *internal,
81 std::size_t internalLength, const char *format, std::size_t formatLength,
82 void **scratchArea = nullptr, std::size_t scratchBytes = 0,
83 const char *sourceFile = nullptr, int sourceLine = 0);
84 Cookie IONAME(BeginInternalFormattedInput)(const char *internal,
85 std::size_t internalLength, const char *format, std::size_t formatLength,
86 void **scratchArea = nullptr, std::size_t scratchBytes = 0,
87 const char *sourceFile = nullptr, int sourceLine = 0);
88
89 // Internal namelist I/O
90 Cookie IONAME(BeginInternalNamelistOutput)(const Descriptor &,
91 const NamelistGroup &, void **scratchArea = nullptr,
92 std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
93 int sourceLine = 0);
94 Cookie IONAME(BeginInternalNamelistInput)(const Descriptor &,
95 const NamelistGroup &, void **scratchArea = nullptr,
96 std::size_t scratchBytes = 0, const char *sourceFile = nullptr,
97 int sourceLine = 0);
98
99 // External synchronous I/O initiation
100 Cookie IONAME(BeginExternalListOutput)(ExternalUnit = DefaultUnit,
101 const char *sourceFile = nullptr, int sourceLine = 0);
102 Cookie IONAME(BeginExternalListInput)(ExternalUnit = DefaultUnit,
103 const char *sourceFile = nullptr, int sourceLine = 0);
104 Cookie IONAME(BeginExternalFormattedOutput)(const char *format, std::size_t,
105 ExternalUnit = DefaultUnit, const char *sourceFile = nullptr,
106 int sourceLine = 0);
107 Cookie IONAME(BeginExternalFormattedInput)(const char *format, std::size_t,
108 ExternalUnit = DefaultUnit, const char *sourceFile = nullptr,
109 int sourceLine = 0);
110 Cookie IONAME(BeginUnformattedOutput)(ExternalUnit = DefaultUnit,
111 const char *sourceFile = nullptr, int sourceLine = 0);
112 Cookie IONAME(BeginUnformattedInput)(ExternalUnit = DefaultUnit,
113 const char *sourceFile = nullptr, int sourceLine = 0);
114 Cookie IONAME(BeginExternalNamelistOutput)(const NamelistGroup &,
115 ExternalUnit = DefaultUnit, const char *sourceFile = nullptr,
116 int sourceLine = 0);
117 Cookie IONAME(BeginExternalNamelistInput)(const NamelistGroup &,
118 ExternalUnit = DefaultUnit, const char *sourceFile = nullptr,
119 int sourceLine = 0);
120
121 // Asynchronous I/O is supported (at most) for unformatted direct access
122 // block transfers.
123 AsynchronousId IONAME(BeginAsynchronousOutput)(ExternalUnit, std::int64_t REC,
124 const char *, std::size_t, const char *sourceFile = nullptr,
125 int sourceLine = 0);
126 AsynchronousId IONAME(BeginAsynchronousInput)(ExternalUnit, std::int64_t REC,
127 char *, std::size_t, const char *sourceFile = nullptr, int sourceLine = 0);
128 Cookie IONAME(BeginWait)(ExternalUnit, AsynchronousId);
129 Cookie IONAME(BeginWaitAll)(ExternalUnit);
130
131 // Other I/O statements
132 Cookie IONAME(BeginClose)(
133 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
134 Cookie IONAME(BeginFlush)(
135 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
136 Cookie IONAME(BeginBackspace)(
137 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
138 Cookie IONAME(BeginEndfile)(
139 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
140 Cookie IONAME(BeginRewind)(
141 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
142
143 // OPEN(UNIT=) and OPEN(NEWUNIT=) have distinct interfaces.
144 Cookie IONAME(BeginOpenUnit)(
145 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
146 Cookie IONAME(BeginOpenNewUnit)(
147 const char *sourceFile = nullptr, int sourceLine = 0);
148
149 // The variant forms of INQUIRE() statements have distinct interfaces.
150 // BeginInquireIoLength() is basically a no-op output statement.
151 Cookie IONAME(BeginInquireUnit)(
152 ExternalUnit, const char *sourceFile = nullptr, int sourceLine = 0);
153 Cookie IONAME(BeginInquireFile)(const char *, std::size_t, int kind = 1,
154 const char *sourceFile = nullptr, int sourceLine = 0);
155 Cookie IONAME(BeginInquireIoLength)(
156 const char *sourceFile = nullptr, int sourceLine = 0);
157
158 // If an I/O statement has any IOSTAT=, ERR=, END=, or EOR= specifiers,
159 // call EnableHandlers() immediately after the Begin...() call.
160 // An output or OPEN statement may not enable HasEnd or HasEor.
161 // This call makes the runtime library defer those particular error/end
162 // conditions to the EndIoStatement() call rather than terminating
163 // the image. E.g., for READ(*,*,END=666) A, B, (C(J),J=1,N)
164 // Cookie cookie{BeginExternalListInput(DefaultUnit,__FILE__,__LINE__)};
165 // EnableHandlers(cookie, false, false, true /*END=*/, false);
166 // if (InputReal64(cookie, &A)) {
167 // if (InputReal64(cookie, &B)) {
168 // for (int J{1}; J<=N; ++J) {
169 // if (!InputReal64(cookie, &C[J])) break;
170 // }
171 // }
172 // }
173 // if (EndIoStatement(cookie) == FORTRAN_RUTIME_IOSTAT_END) goto label666;
174 void IONAME(EnableHandlers)(Cookie, bool hasIoStat = false, bool hasErr = false,
175 bool hasEnd = false, bool hasEor = false, bool hasIoMsg = false);
176
177 // Control list options. These return false on a error that the
178 // Begin...() call has specified will be handled by the caller.
179 // The interfaces that pass a default-kind CHARACTER argument
180 // are limited to passing specific case-insensitive keyword values.
181 // ADVANCE=YES, NO
182 bool IONAME(SetAdvance)(Cookie, const char *, std::size_t);
183 // BLANK=NULL, ZERO
184 bool IONAME(SetBlank)(Cookie, const char *, std::size_t);
185 // DECIMAL=COMMA, POINT
186 bool IONAME(SetDecimal)(Cookie, const char *, std::size_t);
187 // DELIM=APOSTROPHE, QUOTE, NONE
188 bool IONAME(SetDelim)(Cookie, const char *, std::size_t);
189 // PAD=YES, NO
190 bool IONAME(SetPad)(Cookie, const char *, std::size_t);
191 bool IONAME(SetPos)(Cookie, std::int64_t);
192 bool IONAME(SetRec)(Cookie, std::int64_t);
193 // ROUND=UP, DOWN, ZERO, NEAREST, COMPATIBLE, PROCESSOR_DEFINED
194 bool IONAME(SetRound)(Cookie, const char *, std::size_t);
195 // SIGN=PLUS, SUPPRESS, PROCESSOR_DEFINED
196 bool IONAME(SetSign)(Cookie, const char *, std::size_t);
197
198 // Data item transfer for modes other than namelist.
199 // Any data object that can be passed as an actual argument without the
200 // use of a temporary can be transferred by means of a descriptor;
201 // vector-valued subscripts and coindexing will require elementwise
202 // transfers &/or data copies. Unformatted transfers to/from contiguous
203 // blocks of local image memory can avoid the descriptor, and there
204 // are specializations for the most common scalar types.
205 //
206 // These functions return false when the I/O statement has encountered an
207 // error or end-of-file/record condition that the caller has indicated
208 // should not cause termination of the image by the runtime library.
209 // Once the statement has encountered an error, all following items will be
210 // ignored and also return false; but compiled code should check for errors
211 // and avoid the following items when they might crash.
212 bool IONAME(OutputDescriptor)(Cookie, const Descriptor &);
213 bool IONAME(InputDescriptor)(Cookie, const Descriptor &);
214 bool IONAME(OutputUnformattedBlock)(Cookie, const char *, std::size_t);
215 bool IONAME(InputUnformattedBlock)(Cookie, char *, std::size_t);
216 bool IONAME(OutputInteger64)(Cookie, std::int64_t);
217 bool IONAME(InputInteger)(Cookie, std::int64_t &, int kind = 8);
218 bool IONAME(OutputReal32)(Cookie, float);
219 bool IONAME(InputReal32)(Cookie, float &);
220 bool IONAME(OutputReal64)(Cookie, double);
221 bool IONAME(InputReal64)(Cookie, double &);
222 bool IONAME(OutputComplex32)(Cookie, float, float);
223 bool IONAME(OutputComplex64)(Cookie, double, double);
224 bool IONAME(OutputAscii)(Cookie, const char *, std::size_t);
225 bool IONAME(InputAscii)(Cookie, char *, std::size_t);
226 bool IONAME(OutputLogical)(Cookie, bool);
227 bool IONAME(InputLogical)(Cookie, bool &);
228
229 // Additional specifier interfaces for the connection-list of
230 // on OPEN statement (only). SetBlank(), SetDecimal(),
231 // SetDelim(), GetIoMsg(), SetPad(), SetRound(), & SetSign()
232 // are also acceptable for OPEN.
233 // ACCESS=SEQUENTIAL, DIRECT, STREAM
234 bool IONAME(SetAccess)(Cookie, const char *, std::size_t);
235 // ACTION=READ, WRITE, or READWRITE
236 bool IONAME(SetAction)(Cookie, const char *, std::size_t);
237 // ASYNCHRONOUS=YES, NO
238 bool IONAME(SetAsynchronous)(Cookie, const char *, std::size_t);
239 // ENCODING=UTF-8, DEFAULT
240 bool IONAME(SetEncoding)(Cookie, const char *, std::size_t);
241 // FORM=FORMATTED, UNFORMATTED
242 bool IONAME(SetForm)(Cookie, const char *, std::size_t);
243 // POSITION=ASIS, REWIND, APPEND
244 bool IONAME(SetPosition)(Cookie, const char *, std::size_t);
245 bool IONAME(SetRecl)(Cookie, std::size_t); // RECL=
246
247 // STATUS can be set during an OPEN or CLOSE statement.
248 // For OPEN: STATUS=OLD, NEW, SCRATCH, REPLACE, UNKNOWN
249 // For CLOSE: STATUS=KEEP, DELETE
250 bool IONAME(SetStatus)(Cookie, const char *, std::size_t);
251
252 // SetFile() may pass a CHARACTER argument of non-default kind,
253 // and such filenames are converted to UTF-8 before being
254 // presented to the filesystem.
255 bool IONAME(SetFile)(Cookie, const char *, std::size_t chars, int kind = 1);
256
257 // Acquires the runtime-created unit number for OPEN(NEWUNIT=)
258 bool IONAME(GetNewUnit)(Cookie, int &, int kind = 4);
259
260 // READ(SIZE=), after all input items
261 bool IONAME(GetSize)(Cookie, std::int64_t, int kind = 8);
262
263 // INQUIRE(IOLENGTH=), after all output items
264 bool IONAME(GetIoLength)(Cookie, std::int64_t, int kind = 8);
265
266 // GetIoMsg() does not modify its argument unless an error or
267 // end-of-record/file condition is present.
268 void IONAME(GetIoMsg)(Cookie, char *, std::size_t); // IOMSG=
269
270 // INQUIRE() specifiers are mostly identified by their NUL-terminated
271 // case-insensitive names.
272 // ACCESS, ACTION, ASYNCHRONOUS, BLANK, DECIMAL, DELIM, DIRECT, ENCODING,
273 // FORM, FORMATTED, NAME, PAD, POSITION, READ, READWRITE, ROUND,
274 // SEQUENTIAL, SIGN, STREAM, UNFORMATTED, WRITE:
275 bool IONAME(InquireCharacter)(
276 Cookie, const char *specifier, char *, std::size_t);
277 // EXIST, NAMED, OPENED, and PENDING (without ID):
278 bool IONAME(InquireLogical)(Cookie, const char *specifier, bool &);
279 // PENDING with ID
280 bool IONAME(InquirePendingId)(Cookie, std::int64_t, bool &);
281 // NEXTREC, NUMBER, POS, RECL, SIZE
282 bool IONAME(InquireInteger64)(
283 Cookie, const char *specifier, std::int64_t &, int kind = 8);
284
285 // This function must be called to end an I/O statement, and its
286 // cookie value may not be used afterwards unless it is recycled
287 // by the runtime library to serve a later I/O statement.
288 // The return value can be used to implement IOSTAT=, ERR=, END=, & EOR=;
289 // store it into the IOSTAT= variable if there is one, and test
290 // it to implement the various branches. The error condition
291 // returned is guaranteed to only be one of the problems that the
292 // EnableHandlers() call has indicated should be handled in compiled code
293 // rather than by terminating the image.
294 enum Iostat IONAME(EndIoStatement)(Cookie);
295
296 } // extern "C"
297 } // namespace Fortran::runtime::io
298 #endif