11#ifndef FORTRAN_RUNTIME_IO_STMT_H_
12#define FORTRAN_RUNTIME_IO_STMT_H_
14#include "connection.h"
17#include "internal-unit.h"
19#include "flang/Common/optional.h"
20#include "flang/Common/reference-wrapper.h"
21#include "flang/Common/visit.h"
22#include "flang/Runtime/descriptor.h"
23#include "flang/Runtime/io-api.h"
24#include <flang/Common/variant.h>
28namespace Fortran::runtime::io {
30class ExternalFileUnit;
33class OpenStatementState;
34class InquireUnitState;
35class InquireNoUnitState;
36class InquireUnconnectedFileState;
37class InquireIOLengthState;
38class ExternalMiscIoStatementState;
39class CloseStatementState;
40class NoopStatementState;
41class ErroneousIoStatementState;
43template <Direction,
typename CHAR =
char>
44class InternalFormattedIoStatementState;
45template <Direction>
class InternalListIoStatementState;
46template <Direction,
typename CHAR =
char>
47class ExternalFormattedIoStatementState;
48template <Direction>
class ExternalListIoStatementState;
49template <Direction>
class ExternalUnformattedIoStatementState;
50template <Direction,
typename CHAR =
char>
class ChildFormattedIoStatementState;
51template <Direction>
class ChildListIoStatementState;
52template <Direction>
class ChildUnformattedIoStatementState;
57using IoDirectionState = std::conditional_t<D == Direction::Input,
64 RT_API_ATTRS std::size_t GetEditDescriptorChars()
const;
65 RT_API_ATTRS
void GotChar(
int);
70 std::size_t chars_{0};
76 template <
typename A>
explicit RT_API_ATTRS
IoStatementState(A &x) : u_{x} {}
88 RT_API_ATTRS
void CompleteOperation();
90 RT_API_ATTRS
int EndIoStatement();
92 RT_API_ATTRS
bool Emit(
93 const char *, std::size_t bytes, std::size_t elementBytes = 0);
94 RT_API_ATTRS
bool Receive(
char *, std::size_t, std::size_t elementBytes = 0);
95 RT_API_ATTRS std::size_t GetNextInputBytes(
const char *&);
96 RT_API_ATTRS std::size_t ViewBytesInRecord(
const char *&,
bool forward)
const;
97 RT_API_ATTRS
bool AdvanceRecord(
int = 1);
98 RT_API_ATTRS
void BackspaceRecord();
99 RT_API_ATTRS
void HandleRelativePosition(std::int64_t byteOffset);
100 RT_API_ATTRS
void HandleAbsolutePosition(
101 std::int64_t byteOffset);
102 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
105 GetExternalFileUnit()
const;
106 RT_API_ATTRS
bool BeginReadingRecord();
107 RT_API_ATTRS
void FinishReadingRecord();
108 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
char *, std::size_t);
109 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
bool &);
110 RT_API_ATTRS
bool Inquire(
111 InquiryKeywordHash, std::int64_t,
bool &);
112 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t &);
113 RT_API_ATTRS std::int64_t InquirePos();
114 RT_API_ATTRS
void GotChar(
signed int = 1);
121 template <
typename A> RT_API_ATTRS A *get_if()
const {
122 return common::visit(
124 if constexpr (std::is_convertible_v<
decltype(x.get()), A &>) {
133 RT_API_ATTRS Fortran::common::optional<char32_t> GetCurrentChar(
134 std::size_t &byteCount);
142 RT_API_ATTRS Fortran::common::optional<int> CueUpInput(
const DataEdit &edit) {
143 Fortran::common::optional<int> remaining;
144 if (edit.IsListDirected()) {
145 std::size_t byteCount{0};
146 GetNextNonBlank(byteCount);
148 if (edit.width.value_or(0) > 0) {
149 remaining = *edit.width;
150 if (
int bytesPerChar{GetConnectionState().internalIoCharKind};
152 *remaining *= bytesPerChar;
155 SkipSpaces(remaining);
160 RT_API_ATTRS Fortran::common::optional<char32_t> SkipSpaces(
161 Fortran::common::optional<int> &remaining) {
162 while (!remaining || *remaining > 0) {
163 std::size_t byteCount{0};
164 if (
auto ch{GetCurrentChar(byteCount)}) {
165 if (*ch !=
' ' && *ch !=
'\t') {
169 if (
static_cast<std::size_t
>(*remaining) < byteCount) {
173 *remaining -= byteCount;
175 HandleRelativePosition(byteCount);
180 return Fortran::common::nullopt;
185 RT_API_ATTRS Fortran::common::optional<char32_t> NextInField(
186 Fortran::common::optional<int> &remaining,
const DataEdit &);
190 RT_API_ATTRS
bool CheckForEndOfRecord(std::size_t afterReading);
193 RT_API_ATTRS Fortran::common::optional<char32_t> GetNextNonBlank(
194 std::size_t &byteCount) {
195 auto ch{GetCurrentChar(byteCount)};
196 bool inNamelist{mutableModes().inNamelist};
197 while (!ch || *ch ==
' ' || *ch ==
'\t' || *ch ==
'\n' ||
198 (inNamelist && *ch ==
'!')) {
199 if (ch && (*ch ==
' ' || *ch ==
'\t' || *ch ==
'\n')) {
200 HandleRelativePosition(byteCount);
201 }
else if (!AdvanceRecord()) {
202 return Fortran::common::nullopt;
204 ch = GetCurrentChar(byteCount);
209 template <Direction D>
210 RT_API_ATTRS
bool CheckFormattedStmtType(
const char *name) {
214 auto &handler{GetIoErrorHandler()};
215 if (!handler.InError()) {
216 handler.Crash(
"%s called for I/O statement that is not formatted %s",
217 name, D == Direction::Output ?
"output" :
"input");
224 std::variant<Fortran::common::reference_wrapper<OpenStatementState>,
225 Fortran::common::reference_wrapper<CloseStatementState>,
226 Fortran::common::reference_wrapper<NoopStatementState>,
227 Fortran::common::reference_wrapper<
229 Fortran::common::reference_wrapper<
231 Fortran::common::reference_wrapper<
233 Fortran::common::reference_wrapper<
235 Fortran::common::reference_wrapper<
237 Fortran::common::reference_wrapper<
239 Fortran::common::reference_wrapper<
241 Fortran::common::reference_wrapper<
243 Fortran::common::reference_wrapper<
245 Fortran::common::reference_wrapper<
247 Fortran::common::reference_wrapper<
249 Fortran::common::reference_wrapper<
251 Fortran::common::reference_wrapper<
253 Fortran::common::reference_wrapper<
255 Fortran::common::reference_wrapper<
257 Fortran::common::reference_wrapper<
259 Fortran::common::reference_wrapper<InquireUnitState>,
260 Fortran::common::reference_wrapper<InquireNoUnitState>,
261 Fortran::common::reference_wrapper<InquireUnconnectedFileState>,
262 Fortran::common::reference_wrapper<InquireIOLengthState>,
263 Fortran::common::reference_wrapper<ExternalMiscIoStatementState>,
264 Fortran::common::reference_wrapper<ErroneousIoStatementState>>
271 using IoErrorHandler::IoErrorHandler;
273 RT_API_ATTRS
bool completedOperation()
const {
return completedOperation_; }
275 RT_API_ATTRS
void CompleteOperation() { completedOperation_ =
true; }
276 RT_API_ATTRS
int EndIoStatement() {
return GetIoStat(); }
279 RT_API_ATTRS
bool Emit(
280 const char *, std::size_t bytes, std::size_t elementBytes = 0);
281 RT_API_ATTRS
bool Receive(
282 char *, std::size_t bytes, std::size_t elementBytes = 0);
283 RT_API_ATTRS std::size_t GetNextInputBytes(
const char *&);
284 RT_API_ATTRS std::size_t ViewBytesInRecord(
const char *&,
bool forward)
const;
285 RT_API_ATTRS
bool AdvanceRecord(
int);
286 RT_API_ATTRS
void BackspaceRecord();
287 RT_API_ATTRS
void HandleRelativePosition(std::int64_t);
288 RT_API_ATTRS
void HandleAbsolutePosition(std::int64_t);
289 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
292 RT_API_ATTRS
bool BeginReadingRecord();
293 RT_API_ATTRS
void FinishReadingRecord();
294 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
char *, std::size_t);
295 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
bool &);
296 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t,
bool &);
297 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t &);
298 RT_API_ATTRS std::int64_t InquirePos();
300 RT_API_ATTRS
void BadInquiryKeywordHashCrash(InquiryKeywordHash);
302 RT_API_ATTRS
void ReportUnsupportedChildIo()
const {
303 Crash(
"not yet implemented: child IO");
307 bool completedOperation_{
false};
316 RT_API_ATTRS
bool EmitLeadingSpaceOrAdvance(
318 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
320 RT_API_ATTRS
bool lastWasUndelimitedCharacter()
const {
321 return lastWasUndelimitedCharacter_;
323 RT_API_ATTRS
void set_lastWasUndelimitedCharacter(
bool yes =
true) {
324 lastWasUndelimitedCharacter_ = yes;
328 bool lastWasUndelimitedCharacter_{
false};
334 RT_API_ATTRS
bool inNamelistSequence()
const {
return inNamelistSequence_; }
335 RT_API_ATTRS
int EndIoStatement();
340 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
347 RT_API_ATTRS
void ResetForNextNamelistItem(
bool inNamelistSequence) {
349 if (repeatPosition_) {
350 repeatPosition_->Cancel();
353 realPart_ = imaginaryPart_ =
false;
354 inNamelistSequence_ = inNamelistSequence;
359 Fortran::common::optional<SavedPosition> repeatPosition_;
360 bool eatComma_{
false};
361 bool hitSlash_{
false};
362 bool realPart_{
false};
363 bool imaginaryPart_{
false};
364 bool inNamelistSequence_{
false};
367template <Direction DIR>
369 public IoDirectionState<DIR> {
372 std::conditional_t<DIR == Direction::Input, const char *, char *>;
374 const char *sourceFile =
nullptr,
int sourceLine = 0);
376 const Descriptor &,
const char *sourceFile =
nullptr,
int sourceLine = 0);
377 RT_API_ATTRS
int EndIoStatement();
379 RT_API_ATTRS
bool Emit(
380 const char *data, std::size_t bytes, std::size_t elementBytes = 0);
381 RT_API_ATTRS std::size_t GetNextInputBytes(
const char *&);
382 RT_API_ATTRS
bool AdvanceRecord(
int = 1);
383 RT_API_ATTRS
void BackspaceRecord();
385 RT_API_ATTRS
MutableModes &mutableModes() {
return unit_.modes; }
386 RT_API_ATTRS
void HandleRelativePosition(std::int64_t);
387 RT_API_ATTRS
void HandleAbsolutePosition(std::int64_t);
388 RT_API_ATTRS std::int64_t InquirePos();
395template <Direction DIR,
typename CHAR>
400 using CharType = CHAR;
401 using typename InternalIoStatementState<DIR>::Buffer;
403 std::size_t internalLength,
const CharType *format,
404 std::size_t formatLength,
const Descriptor *formatDescriptor =
nullptr,
405 const char *sourceFile =
nullptr,
int sourceLine = 0);
407 const CharType *format, std::size_t formatLength,
409 const char *sourceFile =
nullptr,
int sourceLine = 0);
411 return ioStatementState_;
413 RT_API_ATTRS
void CompleteOperation();
414 RT_API_ATTRS
int EndIoStatement();
415 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
417 return format_.GetNextDataEdit(*
this, maxRepeat);
427template <Direction DIR>
431 using typename InternalIoStatementState<DIR>::Buffer;
433 std::size_t internalLength,
const char *sourceFile =
nullptr,
436 const Descriptor &,
const char *sourceFile =
nullptr,
int sourceLine = 0);
438 return ioStatementState_;
441 RT_API_ATTRS
void CompleteOperation();
442 RT_API_ATTRS
int EndIoStatement();
457 RT_API_ATTRS
int asynchronousID()
const {
return asynchronousID_; }
458 RT_API_ATTRS
void set_destroy(
bool yes =
true) { destroy_ = yes; }
459 RT_API_ATTRS
int EndIoStatement();
460 RT_API_ATTRS
ExternalFileUnit *GetExternalFileUnit()
const {
return &unit_; }
461 RT_API_ATTRS
void SetAsynchronous();
462 RT_API_ATTRS std::int64_t InquirePos();
466 int asynchronousID_{-1};
467 bool destroy_{
false};
470template <Direction DIR>
472 public IoDirectionState<DIR> {
476 RT_API_ATTRS
MutableModes &mutableModes() {
return mutableModes_; }
477 RT_API_ATTRS
void CompleteOperation();
478 RT_API_ATTRS
int EndIoStatement();
479 RT_API_ATTRS
bool Emit(
480 const char *, std::size_t bytes, std::size_t elementBytes = 0);
481 RT_API_ATTRS std::size_t GetNextInputBytes(
const char *&);
482 RT_API_ATTRS std::size_t ViewBytesInRecord(
const char *&,
bool forward)
const;
483 RT_API_ATTRS
bool AdvanceRecord(
int = 1);
484 RT_API_ATTRS
void BackspaceRecord();
485 RT_API_ATTRS
void HandleRelativePosition(std::int64_t);
486 RT_API_ATTRS
void HandleAbsolutePosition(std::int64_t);
487 RT_API_ATTRS
bool BeginReadingRecord();
488 RT_API_ATTRS
void FinishReadingRecord();
497template <Direction DIR,
typename CHAR>
502 using CharType = CHAR;
504 const CharType *format, std::size_t formatLength,
506 const char *sourceFile =
nullptr,
int sourceLine = 0);
507 RT_API_ATTRS
void CompleteOperation();
508 RT_API_ATTRS
int EndIoStatement();
509 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
511 return format_.GetNextDataEdit(*
this, maxRepeat);
518template <Direction DIR>
524 RT_API_ATTRS
int EndIoStatement();
527template <Direction DIR>
532 RT_API_ATTRS
bool Receive(
char *, std::size_t, std::size_t elementBytes = 0);
535template <Direction DIR>
537 public IoDirectionState<DIR> {
540 ChildIo &,
const char *sourceFile =
nullptr,
int sourceLine = 0);
541 RT_API_ATTRS
ChildIo &child() {
return child_; }
545 RT_API_ATTRS
int EndIoStatement();
546 RT_API_ATTRS
bool Emit(
547 const char *, std::size_t bytes, std::size_t elementBytes = 0);
548 RT_API_ATTRS std::size_t GetNextInputBytes(
const char *&);
549 RT_API_ATTRS std::size_t ViewBytesInRecord(
const char *&,
bool forward)
const;
550 RT_API_ATTRS
void HandleRelativePosition(std::int64_t);
551 RT_API_ATTRS
void HandleAbsolutePosition(std::int64_t);
557template <Direction DIR,
typename CHAR>
561 using CharType = CHAR;
563 std::size_t formatLength,
const Descriptor *formatDescriptor =
nullptr,
564 const char *sourceFile =
nullptr,
int sourceLine = 0);
565 RT_API_ATTRS
MutableModes &mutableModes() {
return mutableModes_; }
566 RT_API_ATTRS
void CompleteOperation();
567 RT_API_ATTRS
int EndIoStatement();
568 RT_API_ATTRS
bool AdvanceRecord(
int = 1);
569 RT_API_ATTRS Fortran::common::optional<DataEdit> GetNextDataEdit(
571 return format_.GetNextDataEdit(*
this, maxRepeat);
579template <Direction DIR>
585 RT_API_ATTRS
int EndIoStatement();
588template <Direction DIR>
592 RT_API_ATTRS
bool Receive(
char *, std::size_t, std::size_t elementBytes = 0);
599 bool isNewUnit,
const char *sourceFile =
nullptr,
int sourceLine = 0)
601 wasExtant_{wasExtant}, isNewUnit_{isNewUnit} {}
602 RT_API_ATTRS
bool wasExtant()
const {
return wasExtant_; }
603 RT_API_ATTRS
void set_status(OpenStatus status) {
606 RT_API_ATTRS
void set_path(
const char *, std::size_t);
607 RT_API_ATTRS
void set_position(Position position) {
608 position_ = position;
610 RT_API_ATTRS
void set_action(Action action) { action_ = action; }
611 RT_API_ATTRS
void set_convert(Convert convert) {
614 RT_API_ATTRS
void set_access(Access access) { access_ = access; }
615 RT_API_ATTRS
void set_isUnformatted(
bool yes =
true) {
616 isUnformatted_ = yes;
619 RT_API_ATTRS
void CompleteOperation();
620 RT_API_ATTRS
int EndIoStatement();
625 Fortran::common::optional<OpenStatus> status_;
626 Fortran::common::optional<Position> position_;
627 Fortran::common::optional<Action> action_;
628 Convert convert_{Convert::Unknown};
630 std::size_t pathLength_;
631 Fortran::common::optional<bool> isUnformatted_;
632 Fortran::common::optional<Access> access_;
638 const char *sourceFile =
nullptr,
int sourceLine = 0)
640 RT_API_ATTRS
void set_status(CloseStatus status) { status_ = status; }
641 RT_API_ATTRS
int EndIoStatement();
644 CloseStatus status_{CloseStatus::Keep};
652 return ioStatementState_;
654 RT_API_ATTRS
MutableModes &mutableModes() {
return connection_.modes; }
655 RT_API_ATTRS
ConnectionState &GetConnectionState() {
return connection_; }
656 RT_API_ATTRS
int badUnitNumber()
const {
return badUnitNumber_; }
657 RT_API_ATTRS
void CompleteOperation();
658 RT_API_ATTRS
int EndIoStatement();
661 template <
typename A>
663 int sourceLine = 0,
int badUnitNumber = -1)
665 badUnitNumber_{badUnitNumber} {}
676 const char *sourceFile =
nullptr,
int sourceLine = 0,
int unitNumber = -1)
678 RT_API_ATTRS
void set_status(CloseStatus) {}
720 const char *sourceFile =
nullptr,
int sourceLine = 0);
721 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
char *, std::size_t);
722 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
bool &);
723 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t,
bool &);
724 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t &);
730 int sourceLine = 0,
int badUnitNumber = -1);
731 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
char *, std::size_t);
732 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
bool &);
733 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t,
bool &);
734 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t &);
740 const char *sourceFile =
nullptr,
int sourceLine = 0);
741 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
char *, std::size_t);
742 RT_API_ATTRS
bool Inquire(InquiryKeywordHash,
bool &);
743 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t,
bool &);
744 RT_API_ATTRS
bool Inquire(InquiryKeywordHash, std::int64_t &);
754 const char *sourceFile =
nullptr,
int sourceLine = 0);
755 RT_API_ATTRS std::size_t bytes()
const {
return bytes_; }
756 RT_API_ATTRS
bool Emit(
757 const char *, std::size_t bytes, std::size_t elementBytes = 0);
760 std::size_t bytes_{0};
765 enum Which { Flush, Backspace, Endfile, Rewind, Wait };
767 const char *sourceFile =
nullptr,
int sourceLine = 0)
769 RT_API_ATTRS
void CompleteOperation();
770 RT_API_ATTRS
int EndIoStatement();
782 SetPendingError(iostat);
784 RT_API_ATTRS
int EndIoStatement();
785 RT_API_ATTRS
ConnectionState &GetConnectionState() {
return connection_; }
786 RT_API_ATTRS
MutableModes &mutableModes() {
return connection_.modes; }
Definition: descriptor.h:138
Definition: io-stmt.h:537
Definition: io-stmt.h:581
Definition: io-stmt.h:635
Definition: io-stmt.h:776
Definition: io-stmt.h:449
Definition: io-stmt.h:472
Definition: io-stmt.h:520
Definition: io-stmt.h:763
Definition: io-stmt.h:751
Definition: io-stmt.h:727
Definition: io-stmt.h:737
Definition: io-stmt.h:717
Definition: internal-unit.h:25
Definition: io-stmt.h:369
Definition: io-stmt.h:429
Definition: io-error.h:26
Definition: io-stmt.h:269
Definition: io-stmt.h:311
Definition: io-stmt.h:649
Definition: io-stmt.h:673
Definition: io-stmt.h:596
Definition: connection.h:47