1 //===-- runtime/io-stmt.h ---------------------------------------*- C++ -*-===//
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 // Representations of the state of an I/O statement in progress
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/visit.h"
20 #include "flang/Runtime/descriptor.h"
21 #include "flang/Runtime/io-api.h"
23 #include <type_traits>
26 namespace Fortran::runtime::io
{
28 class ExternalFileUnit
;
31 class OpenStatementState
;
32 class InquireUnitState
;
33 class InquireNoUnitState
;
34 class InquireUnconnectedFileState
;
35 class InquireIOLengthState
;
36 class ExternalMiscIoStatementState
;
37 class CloseStatementState
;
38 class NoopStatementState
; // CLOSE or FLUSH on unknown unit
39 class ErroneousIoStatementState
;
41 template <Direction
, typename CHAR
= char>
42 class InternalFormattedIoStatementState
;
43 template <Direction
> class InternalListIoStatementState
;
44 template <Direction
, typename CHAR
= char>
45 class ExternalFormattedIoStatementState
;
46 template <Direction
> class ExternalListIoStatementState
;
47 template <Direction
> class ExternalUnformattedIoStatementState
;
48 template <Direction
, typename CHAR
= char> class ChildFormattedIoStatementState
;
49 template <Direction
> class ChildListIoStatementState
;
50 template <Direction
> class ChildUnformattedIoStatementState
;
52 struct InputStatementState
{};
53 struct OutputStatementState
{};
54 template <Direction D
>
55 using IoDirectionState
= std::conditional_t
<D
== Direction::Input
,
56 InputStatementState
, OutputStatementState
>;
58 // Common state for all kinds of formatted I/O
59 template <Direction D
> class FormattedIoStatementState
{};
60 template <> class FormattedIoStatementState
<Direction::Input
> {
62 std::size_t GetEditDescriptorChars() const;
66 // Account of characters read for edit descriptors (i.e., formatted I/O
67 // with a FORMAT, not list-directed or NAMELIST), not including padding.
68 std::size_t chars_
{0}; // for READ(SIZE=)
71 // The Cookie type in the I/O API is a pointer (for C) to this class.
72 class IoStatementState
{
74 template <typename A
> explicit IoStatementState(A
&x
) : u_
{x
} {}
76 // These member functions each project themselves into the active alternative.
77 // They're used by per-data-item routines in the I/O API (e.g., OutputReal64)
78 // to interact with the state of the I/O statement in progress.
79 // This design avoids virtual member functions and function pointers,
80 // which may not have good support in some runtime environments.
82 // CompleteOperation() is the last opportunity to raise an I/O error.
83 // It is called by EndIoStatement(), but it can be invoked earlier to
84 // catch errors for (e.g.) GetIoMsg() and GetNewUnit(). If called
85 // more than once, it is a no-op.
86 void CompleteOperation();
87 // Completes an I/O statement and reclaims storage.
90 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
91 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
92 std::size_t GetNextInputBytes(const char *&);
93 bool AdvanceRecord(int = 1);
94 void BackspaceRecord();
95 void HandleRelativePosition(std::int64_t);
96 void HandleAbsolutePosition(std::int64_t); // for r* in list I/O
97 std::optional
<DataEdit
> GetNextDataEdit(int maxRepeat
= 1);
98 ExternalFileUnit
*GetExternalFileUnit() const; // null if internal unit
99 bool BeginReadingRecord();
100 void FinishReadingRecord();
101 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
102 bool Inquire(InquiryKeywordHash
, bool &);
103 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &); // PENDING=
104 bool Inquire(InquiryKeywordHash
, std::int64_t &);
105 std::int64_t InquirePos();
106 void GotChar(signed int = 1); // for READ(SIZE=); can be <0
108 MutableModes
&mutableModes();
109 ConnectionState
&GetConnectionState();
110 IoErrorHandler
&GetIoErrorHandler() const;
112 // N.B.: this also works with base classes
113 template <typename A
> A
*get_if() const {
114 return common::visit(
116 if constexpr (std::is_convertible_v
<decltype(x
.get()), A
&>) {
124 // Vacant after the end of the current record
125 std::optional
<char32_t
> GetCurrentChar(std::size_t &byteCount
);
127 // For fixed-width fields, return the number of remaining characters.
128 // Skip over leading blanks.
129 std::optional
<int> CueUpInput(const DataEdit
&edit
) {
130 std::optional
<int> remaining
;
131 if (edit
.IsListDirected()) {
132 std::size_t byteCount
{0};
133 GetNextNonBlank(byteCount
);
135 if (edit
.width
.value_or(0) > 0) {
136 remaining
= *edit
.width
;
138 SkipSpaces(remaining
);
143 std::optional
<char32_t
> SkipSpaces(std::optional
<int> &remaining
) {
144 while (!remaining
|| *remaining
> 0) {
145 std::size_t byteCount
{0};
146 if (auto ch
{GetCurrentChar(byteCount
)}) {
147 if (*ch
!= ' ' && *ch
!= '\t') {
151 if (static_cast<std::size_t>(*remaining
) < byteCount
) {
155 *remaining
-= byteCount
;
157 HandleRelativePosition(byteCount
);
165 // Acquires the next input character, respecting any applicable field width
166 // or separator character.
167 std::optional
<char32_t
> NextInField(
168 std::optional
<int> &remaining
, const DataEdit
&);
170 // Detect and signal any end-of-record condition after input.
171 // Returns true if at EOR and remaining input should be padded with blanks.
172 bool CheckForEndOfRecord();
174 // Skips spaces, advances records, and ignores NAMELIST comments
175 std::optional
<char32_t
> GetNextNonBlank(std::size_t &byteCount
) {
176 auto ch
{GetCurrentChar(byteCount
)};
177 bool inNamelist
{mutableModes().inNamelist
};
178 while (!ch
|| *ch
== ' ' || *ch
== '\t' || (inNamelist
&& *ch
== '!')) {
179 if (ch
&& (*ch
== ' ' || *ch
== '\t')) {
180 HandleRelativePosition(byteCount
);
181 } else if (!AdvanceRecord()) {
184 ch
= GetCurrentChar(byteCount
);
189 template <Direction D
> bool CheckFormattedStmtType(const char *name
) {
190 if (get_if
<FormattedIoStatementState
<D
>>()) {
193 auto &handler
{GetIoErrorHandler()};
194 if (!handler
.InError()) {
195 handler
.Crash("%s called for I/O statement that is not formatted %s",
196 name
, D
== Direction::Output
? "output" : "input");
203 std::variant
<std::reference_wrapper
<OpenStatementState
>,
204 std::reference_wrapper
<CloseStatementState
>,
205 std::reference_wrapper
<NoopStatementState
>,
206 std::reference_wrapper
<
207 InternalFormattedIoStatementState
<Direction::Output
>>,
208 std::reference_wrapper
<
209 InternalFormattedIoStatementState
<Direction::Input
>>,
210 std::reference_wrapper
<InternalListIoStatementState
<Direction::Output
>>,
211 std::reference_wrapper
<InternalListIoStatementState
<Direction::Input
>>,
212 std::reference_wrapper
<
213 ExternalFormattedIoStatementState
<Direction::Output
>>,
214 std::reference_wrapper
<
215 ExternalFormattedIoStatementState
<Direction::Input
>>,
216 std::reference_wrapper
<ExternalListIoStatementState
<Direction::Output
>>,
217 std::reference_wrapper
<ExternalListIoStatementState
<Direction::Input
>>,
218 std::reference_wrapper
<
219 ExternalUnformattedIoStatementState
<Direction::Output
>>,
220 std::reference_wrapper
<
221 ExternalUnformattedIoStatementState
<Direction::Input
>>,
222 std::reference_wrapper
<ChildFormattedIoStatementState
<Direction::Output
>>,
223 std::reference_wrapper
<ChildFormattedIoStatementState
<Direction::Input
>>,
224 std::reference_wrapper
<ChildListIoStatementState
<Direction::Output
>>,
225 std::reference_wrapper
<ChildListIoStatementState
<Direction::Input
>>,
226 std::reference_wrapper
<
227 ChildUnformattedIoStatementState
<Direction::Output
>>,
228 std::reference_wrapper
<
229 ChildUnformattedIoStatementState
<Direction::Input
>>,
230 std::reference_wrapper
<InquireUnitState
>,
231 std::reference_wrapper
<InquireNoUnitState
>,
232 std::reference_wrapper
<InquireUnconnectedFileState
>,
233 std::reference_wrapper
<InquireIOLengthState
>,
234 std::reference_wrapper
<ExternalMiscIoStatementState
>,
235 std::reference_wrapper
<ErroneousIoStatementState
>>
239 // Base class for all per-I/O statement state classes.
240 class IoStatementBase
: public IoErrorHandler
{
242 using IoErrorHandler::IoErrorHandler
;
244 bool completedOperation() const { return completedOperation_
; }
246 void CompleteOperation() { completedOperation_
= true; }
247 int EndIoStatement() { return GetIoStat(); }
249 // These are default no-op backstops that can be overridden by descendants.
250 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
251 bool Receive(char *, std::size_t bytes
, std::size_t elementBytes
= 0);
252 std::size_t GetNextInputBytes(const char *&);
253 bool AdvanceRecord(int);
254 void BackspaceRecord();
255 void HandleRelativePosition(std::int64_t);
256 void HandleAbsolutePosition(std::int64_t);
257 std::optional
<DataEdit
> GetNextDataEdit(
258 IoStatementState
&, int maxRepeat
= 1);
259 ExternalFileUnit
*GetExternalFileUnit() const;
260 bool BeginReadingRecord();
261 void FinishReadingRecord();
262 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
263 bool Inquire(InquiryKeywordHash
, bool &);
264 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
265 bool Inquire(InquiryKeywordHash
, std::int64_t &);
266 std::int64_t InquirePos();
268 void BadInquiryKeywordHashCrash(InquiryKeywordHash
);
271 bool completedOperation_
{false};
274 // Common state for list-directed & NAMELIST I/O, both internal & external
275 template <Direction
> class ListDirectedStatementState
;
277 class ListDirectedStatementState
<Direction::Output
>
278 : public FormattedIoStatementState
<Direction::Output
> {
280 bool EmitLeadingSpaceOrAdvance(
281 IoStatementState
&, std::size_t = 1, bool isCharacter
= false);
282 std::optional
<DataEdit
> GetNextDataEdit(
283 IoStatementState
&, int maxRepeat
= 1);
284 bool lastWasUndelimitedCharacter() const {
285 return lastWasUndelimitedCharacter_
;
287 void set_lastWasUndelimitedCharacter(bool yes
= true) {
288 lastWasUndelimitedCharacter_
= yes
;
292 bool lastWasUndelimitedCharacter_
{false};
295 class ListDirectedStatementState
<Direction::Input
>
296 : public FormattedIoStatementState
<Direction::Input
> {
298 bool inNamelistArray() const { return inNamelistArray_
; }
299 void set_inNamelistArray(bool yes
= true) { inNamelistArray_
= yes
; }
301 // Skips value separators, handles repetition and null values.
302 // Vacant when '/' appears; present with descriptor == ListDirectedNullValue
303 // when a null value appears.
304 std::optional
<DataEdit
> GetNextDataEdit(
305 IoStatementState
&, int maxRepeat
= 1);
307 // Each NAMELIST input item is treated like a distinct list-directed
308 // input statement. This member function resets some state so that
309 // repetition and null values work correctly for each successive
310 // NAMELIST input item.
311 void ResetForNextNamelistItem(bool inNamelistArray
) {
314 realPart_
= imaginaryPart_
= false;
315 inNamelistArray_
= inNamelistArray
;
319 int remaining_
{0}; // for "r*" repetition
320 std::optional
<SavedPosition
> repeatPosition_
;
321 bool eatComma_
{false}; // consume comma after previously read item
322 bool hitSlash_
{false}; // once '/' is seen, nullify further items
323 bool realPart_
{false};
324 bool imaginaryPart_
{false};
325 bool inNamelistArray_
{false};
328 template <Direction
DIR>
329 class InternalIoStatementState
: public IoStatementBase
,
330 public IoDirectionState
<DIR> {
333 std::conditional_t
<DIR == Direction::Input
, const char *, char *>;
334 InternalIoStatementState(Buffer
, std::size_t,
335 const char *sourceFile
= nullptr, int sourceLine
= 0);
336 InternalIoStatementState(
337 const Descriptor
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
338 int EndIoStatement();
340 bool Emit(const char *data
, std::size_t bytes
, std::size_t elementBytes
= 0);
341 std::size_t GetNextInputBytes(const char *&);
342 bool AdvanceRecord(int = 1);
343 void BackspaceRecord();
344 ConnectionState
&GetConnectionState() { return unit_
; }
345 MutableModes
&mutableModes() { return unit_
.modes
; }
346 void HandleRelativePosition(std::int64_t);
347 void HandleAbsolutePosition(std::int64_t);
348 std::int64_t InquirePos();
352 InternalDescriptorUnit
<DIR> unit_
;
355 template <Direction
DIR, typename CHAR
>
356 class InternalFormattedIoStatementState
357 : public InternalIoStatementState
<DIR>,
358 public FormattedIoStatementState
<DIR> {
360 using CharType
= CHAR
;
361 using typename InternalIoStatementState
<DIR>::Buffer
;
362 InternalFormattedIoStatementState(Buffer internal
, std::size_t internalLength
,
363 const CharType
*format
, std::size_t formatLength
,
364 const Descriptor
*formatDescriptor
= nullptr,
365 const char *sourceFile
= nullptr, int sourceLine
= 0);
366 InternalFormattedIoStatementState(const Descriptor
&, const CharType
*format
,
367 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
368 const char *sourceFile
= nullptr, int sourceLine
= 0);
369 IoStatementState
&ioStatementState() { return ioStatementState_
; }
370 void CompleteOperation();
371 int EndIoStatement();
372 std::optional
<DataEdit
> GetNextDataEdit(
373 IoStatementState
&, int maxRepeat
= 1) {
374 return format_
.GetNextDataEdit(*this, maxRepeat
);
378 IoStatementState ioStatementState_
; // points to *this
379 using InternalIoStatementState
<DIR>::unit_
;
380 // format_ *must* be last; it may be partial someday
381 FormatControl
<InternalFormattedIoStatementState
> format_
;
384 template <Direction
DIR>
385 class InternalListIoStatementState
: public InternalIoStatementState
<DIR>,
386 public ListDirectedStatementState
<DIR> {
388 using typename InternalIoStatementState
<DIR>::Buffer
;
389 InternalListIoStatementState(Buffer internal
, std::size_t internalLength
,
390 const char *sourceFile
= nullptr, int sourceLine
= 0);
391 InternalListIoStatementState(
392 const Descriptor
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
393 IoStatementState
&ioStatementState() { return ioStatementState_
; }
394 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
397 IoStatementState ioStatementState_
; // points to *this
398 using InternalIoStatementState
<DIR>::unit_
;
401 class ExternalIoStatementBase
: public IoStatementBase
{
403 ExternalIoStatementBase(
404 ExternalFileUnit
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
405 ExternalFileUnit
&unit() { return unit_
; }
406 MutableModes
&mutableModes();
407 ConnectionState
&GetConnectionState();
408 int asynchronousID() const { return asynchronousID_
; }
409 int EndIoStatement();
410 ExternalFileUnit
*GetExternalFileUnit() const { return &unit_
; }
411 void SetAsynchronous();
412 std::int64_t InquirePos();
415 ExternalFileUnit
&unit_
;
416 int asynchronousID_
{-1};
419 template <Direction
DIR>
420 class ExternalIoStatementState
: public ExternalIoStatementBase
,
421 public IoDirectionState
<DIR> {
423 ExternalIoStatementState(
424 ExternalFileUnit
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
425 MutableModes
&mutableModes() { return mutableModes_
; }
426 void CompleteOperation();
427 int EndIoStatement();
428 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
429 std::size_t GetNextInputBytes(const char *&);
430 bool AdvanceRecord(int = 1);
431 void BackspaceRecord();
432 void HandleRelativePosition(std::int64_t);
433 void HandleAbsolutePosition(std::int64_t);
434 bool BeginReadingRecord();
435 void FinishReadingRecord();
438 // These are forked from ConnectionState's modes at the beginning
439 // of each formatted I/O statement so they may be overridden by control
440 // edit descriptors during the statement.
441 MutableModes mutableModes_
;
444 template <Direction
DIR, typename CHAR
>
445 class ExternalFormattedIoStatementState
446 : public ExternalIoStatementState
<DIR>,
447 public FormattedIoStatementState
<DIR> {
449 using CharType
= CHAR
;
450 ExternalFormattedIoStatementState(ExternalFileUnit
&, const CharType
*format
,
451 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
452 const char *sourceFile
= nullptr, int sourceLine
= 0);
453 void CompleteOperation();
454 int EndIoStatement();
455 std::optional
<DataEdit
> GetNextDataEdit(
456 IoStatementState
&, int maxRepeat
= 1) {
457 return format_
.GetNextDataEdit(*this, maxRepeat
);
461 FormatControl
<ExternalFormattedIoStatementState
> format_
;
464 template <Direction
DIR>
465 class ExternalListIoStatementState
: public ExternalIoStatementState
<DIR>,
466 public ListDirectedStatementState
<DIR> {
468 using ExternalIoStatementState
<DIR>::ExternalIoStatementState
;
469 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
472 template <Direction
DIR>
473 class ExternalUnformattedIoStatementState
474 : public ExternalIoStatementState
<DIR> {
476 using ExternalIoStatementState
<DIR>::ExternalIoStatementState
;
477 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
480 template <Direction
DIR>
481 class ChildIoStatementState
: public IoStatementBase
,
482 public IoDirectionState
<DIR> {
484 ChildIoStatementState(
485 ChildIo
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
486 ChildIo
&child() { return child_
; }
487 MutableModes
&mutableModes();
488 ConnectionState
&GetConnectionState();
489 ExternalFileUnit
*GetExternalFileUnit() const;
490 int EndIoStatement();
491 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
492 std::size_t GetNextInputBytes(const char *&);
493 void HandleRelativePosition(std::int64_t);
494 void HandleAbsolutePosition(std::int64_t);
500 template <Direction
DIR, typename CHAR
>
501 class ChildFormattedIoStatementState
: public ChildIoStatementState
<DIR>,
502 public FormattedIoStatementState
<DIR> {
504 using CharType
= CHAR
;
505 ChildFormattedIoStatementState(ChildIo
&, const CharType
*format
,
506 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
507 const char *sourceFile
= nullptr, int sourceLine
= 0);
508 MutableModes
&mutableModes() { return mutableModes_
; }
509 void CompleteOperation();
510 int EndIoStatement();
511 bool AdvanceRecord(int = 1);
512 std::optional
<DataEdit
> GetNextDataEdit(
513 IoStatementState
&, int maxRepeat
= 1) {
514 return format_
.GetNextDataEdit(*this, maxRepeat
);
518 MutableModes mutableModes_
;
519 FormatControl
<ChildFormattedIoStatementState
> format_
;
522 template <Direction
DIR>
523 class ChildListIoStatementState
: public ChildIoStatementState
<DIR>,
524 public ListDirectedStatementState
<DIR> {
526 using ChildIoStatementState
<DIR>::ChildIoStatementState
;
527 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
530 template <Direction
DIR>
531 class ChildUnformattedIoStatementState
: public ChildIoStatementState
<DIR> {
533 using ChildIoStatementState
<DIR>::ChildIoStatementState
;
534 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
538 class OpenStatementState
: public ExternalIoStatementBase
{
540 OpenStatementState(ExternalFileUnit
&unit
, bool wasExtant
,
541 const char *sourceFile
= nullptr, int sourceLine
= 0)
542 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
}, wasExtant_
{
544 bool wasExtant() const { return wasExtant_
; }
545 void set_status(OpenStatus status
) { status_
= status
; } // STATUS=
546 void set_path(const char *, std::size_t); // FILE=
547 void set_position(Position position
) { position_
= position
; } // POSITION=
548 void set_action(Action action
) { action_
= action
; } // ACTION=
549 void set_convert(Convert convert
) { convert_
= convert
; } // CONVERT=
550 void set_access(Access access
) { access_
= access
; } // ACCESS=
551 void set_isUnformatted(bool yes
= true) { isUnformatted_
= yes
; } // FORM=
553 void CompleteOperation();
554 int EndIoStatement();
558 std::optional
<OpenStatus
> status_
;
559 std::optional
<Position
> position_
;
560 std::optional
<Action
> action_
;
561 Convert convert_
{Convert::Unknown
};
562 OwningPtr
<char> path_
;
563 std::size_t pathLength_
;
564 std::optional
<bool> isUnformatted_
;
565 std::optional
<Access
> access_
;
568 class CloseStatementState
: public ExternalIoStatementBase
{
570 CloseStatementState(ExternalFileUnit
&unit
, const char *sourceFile
= nullptr,
572 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
} {}
573 void set_status(CloseStatus status
) { status_
= status
; }
574 int EndIoStatement();
577 CloseStatus status_
{CloseStatus::Keep
};
580 // For CLOSE(bad unit), WAIT(bad unit, ID=nonzero), INQUIRE(unconnected unit),
581 // and recoverable BACKSPACE(bad unit)
582 class NoUnitIoStatementState
: public IoStatementBase
{
584 IoStatementState
&ioStatementState() { return ioStatementState_
; }
585 MutableModes
&mutableModes() { return connection_
.modes
; }
586 ConnectionState
&GetConnectionState() { return connection_
; }
587 int badUnitNumber() const { return badUnitNumber_
; }
588 void CompleteOperation();
589 int EndIoStatement();
592 template <typename A
>
593 NoUnitIoStatementState(A
&stmt
, const char *sourceFile
= nullptr,
594 int sourceLine
= 0, int badUnitNumber
= -1)
595 : IoStatementBase
{sourceFile
, sourceLine
}, ioStatementState_
{stmt
},
596 badUnitNumber_
{badUnitNumber
} {}
599 IoStatementState ioStatementState_
; // points to *this
600 ConnectionState connection_
;
604 class NoopStatementState
: public NoUnitIoStatementState
{
607 const char *sourceFile
= nullptr, int sourceLine
= 0, int unitNumber
= -1)
608 : NoUnitIoStatementState
{*this, sourceFile
, sourceLine
, unitNumber
} {}
609 void set_status(CloseStatus
) {} // discards
612 extern template class InternalIoStatementState
<Direction::Output
>;
613 extern template class InternalIoStatementState
<Direction::Input
>;
614 extern template class InternalFormattedIoStatementState
<Direction::Output
>;
615 extern template class InternalFormattedIoStatementState
<Direction::Input
>;
616 extern template class InternalListIoStatementState
<Direction::Output
>;
617 extern template class InternalListIoStatementState
<Direction::Input
>;
618 extern template class ExternalIoStatementState
<Direction::Output
>;
619 extern template class ExternalIoStatementState
<Direction::Input
>;
620 extern template class ExternalFormattedIoStatementState
<Direction::Output
>;
621 extern template class ExternalFormattedIoStatementState
<Direction::Input
>;
622 extern template class ExternalListIoStatementState
<Direction::Output
>;
623 extern template class ExternalListIoStatementState
<Direction::Input
>;
624 extern template class ExternalUnformattedIoStatementState
<Direction::Output
>;
625 extern template class ExternalUnformattedIoStatementState
<Direction::Input
>;
626 extern template class ChildIoStatementState
<Direction::Output
>;
627 extern template class ChildIoStatementState
<Direction::Input
>;
628 extern template class ChildFormattedIoStatementState
<Direction::Output
>;
629 extern template class ChildFormattedIoStatementState
<Direction::Input
>;
630 extern template class ChildListIoStatementState
<Direction::Output
>;
631 extern template class ChildListIoStatementState
<Direction::Input
>;
632 extern template class ChildUnformattedIoStatementState
<Direction::Output
>;
633 extern template class ChildUnformattedIoStatementState
<Direction::Input
>;
635 extern template class FormatControl
<
636 InternalFormattedIoStatementState
<Direction::Output
>>;
637 extern template class FormatControl
<
638 InternalFormattedIoStatementState
<Direction::Input
>>;
639 extern template class FormatControl
<
640 ExternalFormattedIoStatementState
<Direction::Output
>>;
641 extern template class FormatControl
<
642 ExternalFormattedIoStatementState
<Direction::Input
>>;
643 extern template class FormatControl
<
644 ChildFormattedIoStatementState
<Direction::Output
>>;
645 extern template class FormatControl
<
646 ChildFormattedIoStatementState
<Direction::Input
>>;
648 class InquireUnitState
: public ExternalIoStatementBase
{
650 InquireUnitState(ExternalFileUnit
&unit
, const char *sourceFile
= nullptr,
652 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
653 bool Inquire(InquiryKeywordHash
, bool &);
654 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
655 bool Inquire(InquiryKeywordHash
, std::int64_t &);
658 class InquireNoUnitState
: public NoUnitIoStatementState
{
660 InquireNoUnitState(const char *sourceFile
= nullptr, int sourceLine
= 0,
661 int badUnitNumber
= -1);
662 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
663 bool Inquire(InquiryKeywordHash
, bool &);
664 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
665 bool Inquire(InquiryKeywordHash
, std::int64_t &);
668 class InquireUnconnectedFileState
: public NoUnitIoStatementState
{
670 InquireUnconnectedFileState(OwningPtr
<char> &&path
,
671 const char *sourceFile
= nullptr, int sourceLine
= 0);
672 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
673 bool Inquire(InquiryKeywordHash
, bool &);
674 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
675 bool Inquire(InquiryKeywordHash
, std::int64_t &);
678 OwningPtr
<char> path_
; // trimmed and NUL terminated
681 class InquireIOLengthState
: public NoUnitIoStatementState
,
682 public OutputStatementState
{
684 InquireIOLengthState(const char *sourceFile
= nullptr, int sourceLine
= 0);
685 std::size_t bytes() const { return bytes_
; }
686 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
689 std::size_t bytes_
{0};
692 class ExternalMiscIoStatementState
: public ExternalIoStatementBase
{
694 enum Which
{ Flush
, Backspace
, Endfile
, Rewind
, Wait
};
695 ExternalMiscIoStatementState(ExternalFileUnit
&unit
, Which which
,
696 const char *sourceFile
= nullptr, int sourceLine
= 0)
697 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
}, which_
{which
} {}
698 void CompleteOperation();
699 int EndIoStatement();
705 class ErroneousIoStatementState
: public IoStatementBase
{
707 explicit ErroneousIoStatementState(Iostat iostat
,
708 ExternalFileUnit
*unit
= nullptr, const char *sourceFile
= nullptr,
710 : IoStatementBase
{sourceFile
, sourceLine
}, unit_
{unit
} {
711 SetPendingError(iostat
);
713 int EndIoStatement();
714 ConnectionState
&GetConnectionState() { return connection_
; }
715 MutableModes
&mutableModes() { return connection_
.modes
; }
718 ConnectionState connection_
;
719 ExternalFileUnit
*unit_
{nullptr};
722 } // namespace Fortran::runtime::io
723 #endif // FORTRAN_RUNTIME_IO_STMT_H_