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