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(std::size_t afterReading
);
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 inNamelistSequence() const { return inNamelistSequence_
; }
300 // Skips value separators, handles repetition and null values.
301 // Vacant when '/' appears; present with descriptor == ListDirectedNullValue
302 // when a null value appears.
303 std::optional
<DataEdit
> GetNextDataEdit(
304 IoStatementState
&, int maxRepeat
= 1);
306 // Each NAMELIST input item is treated like a distinct list-directed
307 // input statement. This member function resets some state so that
308 // repetition and null values work correctly for each successive
309 // NAMELIST input item.
310 void ResetForNextNamelistItem(bool inNamelistSequence
) {
313 realPart_
= imaginaryPart_
= false;
314 inNamelistSequence_
= inNamelistSequence
;
318 int remaining_
{0}; // for "r*" repetition
319 std::optional
<SavedPosition
> repeatPosition_
;
320 bool eatComma_
{false}; // consume comma after previously read item
321 bool hitSlash_
{false}; // once '/' is seen, nullify further items
322 bool realPart_
{false};
323 bool imaginaryPart_
{false};
324 bool inNamelistSequence_
{false};
327 template <Direction
DIR>
328 class InternalIoStatementState
: public IoStatementBase
,
329 public IoDirectionState
<DIR> {
332 std::conditional_t
<DIR == Direction::Input
, const char *, char *>;
333 InternalIoStatementState(Buffer
, std::size_t,
334 const char *sourceFile
= nullptr, int sourceLine
= 0);
335 InternalIoStatementState(
336 const Descriptor
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
337 int EndIoStatement();
339 bool Emit(const char *data
, std::size_t bytes
, std::size_t elementBytes
= 0);
340 std::size_t GetNextInputBytes(const char *&);
341 bool AdvanceRecord(int = 1);
342 void BackspaceRecord();
343 ConnectionState
&GetConnectionState() { return unit_
; }
344 MutableModes
&mutableModes() { return unit_
.modes
; }
345 void HandleRelativePosition(std::int64_t);
346 void HandleAbsolutePosition(std::int64_t);
347 std::int64_t InquirePos();
351 InternalDescriptorUnit
<DIR> unit_
;
354 template <Direction
DIR, typename CHAR
>
355 class InternalFormattedIoStatementState
356 : public InternalIoStatementState
<DIR>,
357 public FormattedIoStatementState
<DIR> {
359 using CharType
= CHAR
;
360 using typename InternalIoStatementState
<DIR>::Buffer
;
361 InternalFormattedIoStatementState(Buffer internal
, std::size_t internalLength
,
362 const CharType
*format
, std::size_t formatLength
,
363 const Descriptor
*formatDescriptor
= nullptr,
364 const char *sourceFile
= nullptr, int sourceLine
= 0);
365 InternalFormattedIoStatementState(const Descriptor
&, const CharType
*format
,
366 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
367 const char *sourceFile
= nullptr, int sourceLine
= 0);
368 IoStatementState
&ioStatementState() { return ioStatementState_
; }
369 void CompleteOperation();
370 int EndIoStatement();
371 std::optional
<DataEdit
> GetNextDataEdit(
372 IoStatementState
&, int maxRepeat
= 1) {
373 return format_
.GetNextDataEdit(*this, maxRepeat
);
377 IoStatementState ioStatementState_
; // points to *this
378 using InternalIoStatementState
<DIR>::unit_
;
379 // format_ *must* be last; it may be partial someday
380 FormatControl
<InternalFormattedIoStatementState
> format_
;
383 template <Direction
DIR>
384 class InternalListIoStatementState
: public InternalIoStatementState
<DIR>,
385 public ListDirectedStatementState
<DIR> {
387 using typename InternalIoStatementState
<DIR>::Buffer
;
388 InternalListIoStatementState(Buffer internal
, std::size_t internalLength
,
389 const char *sourceFile
= nullptr, int sourceLine
= 0);
390 InternalListIoStatementState(
391 const Descriptor
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
392 IoStatementState
&ioStatementState() { return ioStatementState_
; }
393 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
396 IoStatementState ioStatementState_
; // points to *this
397 using InternalIoStatementState
<DIR>::unit_
;
400 class ExternalIoStatementBase
: public IoStatementBase
{
402 ExternalIoStatementBase(
403 ExternalFileUnit
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
404 ExternalFileUnit
&unit() { return unit_
; }
405 MutableModes
&mutableModes();
406 ConnectionState
&GetConnectionState();
407 int asynchronousID() const { return asynchronousID_
; }
408 int EndIoStatement();
409 ExternalFileUnit
*GetExternalFileUnit() const { return &unit_
; }
410 void SetAsynchronous();
411 std::int64_t InquirePos();
414 ExternalFileUnit
&unit_
;
415 int asynchronousID_
{-1};
418 template <Direction
DIR>
419 class ExternalIoStatementState
: public ExternalIoStatementBase
,
420 public IoDirectionState
<DIR> {
422 ExternalIoStatementState(
423 ExternalFileUnit
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
424 MutableModes
&mutableModes() { return mutableModes_
; }
425 void CompleteOperation();
426 int EndIoStatement();
427 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
428 std::size_t GetNextInputBytes(const char *&);
429 bool AdvanceRecord(int = 1);
430 void BackspaceRecord();
431 void HandleRelativePosition(std::int64_t);
432 void HandleAbsolutePosition(std::int64_t);
433 bool BeginReadingRecord();
434 void FinishReadingRecord();
437 // These are forked from ConnectionState's modes at the beginning
438 // of each formatted I/O statement so they may be overridden by control
439 // edit descriptors during the statement.
440 MutableModes mutableModes_
;
443 template <Direction
DIR, typename CHAR
>
444 class ExternalFormattedIoStatementState
445 : public ExternalIoStatementState
<DIR>,
446 public FormattedIoStatementState
<DIR> {
448 using CharType
= CHAR
;
449 ExternalFormattedIoStatementState(ExternalFileUnit
&, const CharType
*format
,
450 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
451 const char *sourceFile
= nullptr, int sourceLine
= 0);
452 void CompleteOperation();
453 int EndIoStatement();
454 std::optional
<DataEdit
> GetNextDataEdit(
455 IoStatementState
&, int maxRepeat
= 1) {
456 return format_
.GetNextDataEdit(*this, maxRepeat
);
460 FormatControl
<ExternalFormattedIoStatementState
> format_
;
463 template <Direction
DIR>
464 class ExternalListIoStatementState
: public ExternalIoStatementState
<DIR>,
465 public ListDirectedStatementState
<DIR> {
467 using ExternalIoStatementState
<DIR>::ExternalIoStatementState
;
468 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
471 template <Direction
DIR>
472 class ExternalUnformattedIoStatementState
473 : public ExternalIoStatementState
<DIR> {
475 using ExternalIoStatementState
<DIR>::ExternalIoStatementState
;
476 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
479 template <Direction
DIR>
480 class ChildIoStatementState
: public IoStatementBase
,
481 public IoDirectionState
<DIR> {
483 ChildIoStatementState(
484 ChildIo
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
485 ChildIo
&child() { return child_
; }
486 MutableModes
&mutableModes();
487 ConnectionState
&GetConnectionState();
488 ExternalFileUnit
*GetExternalFileUnit() const;
489 int EndIoStatement();
490 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
491 std::size_t GetNextInputBytes(const char *&);
492 void HandleRelativePosition(std::int64_t);
493 void HandleAbsolutePosition(std::int64_t);
499 template <Direction
DIR, typename CHAR
>
500 class ChildFormattedIoStatementState
: public ChildIoStatementState
<DIR>,
501 public FormattedIoStatementState
<DIR> {
503 using CharType
= CHAR
;
504 ChildFormattedIoStatementState(ChildIo
&, const CharType
*format
,
505 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
506 const char *sourceFile
= nullptr, int sourceLine
= 0);
507 MutableModes
&mutableModes() { return mutableModes_
; }
508 void CompleteOperation();
509 int EndIoStatement();
510 bool AdvanceRecord(int = 1);
511 std::optional
<DataEdit
> GetNextDataEdit(
512 IoStatementState
&, int maxRepeat
= 1) {
513 return format_
.GetNextDataEdit(*this, maxRepeat
);
517 MutableModes mutableModes_
;
518 FormatControl
<ChildFormattedIoStatementState
> format_
;
521 template <Direction
DIR>
522 class ChildListIoStatementState
: public ChildIoStatementState
<DIR>,
523 public ListDirectedStatementState
<DIR> {
525 using ChildIoStatementState
<DIR>::ChildIoStatementState
;
526 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
529 template <Direction
DIR>
530 class ChildUnformattedIoStatementState
: public ChildIoStatementState
<DIR> {
532 using ChildIoStatementState
<DIR>::ChildIoStatementState
;
533 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
537 class OpenStatementState
: public ExternalIoStatementBase
{
539 OpenStatementState(ExternalFileUnit
&unit
, bool wasExtant
, bool isNewUnit
,
540 const char *sourceFile
= nullptr, int sourceLine
= 0)
541 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
},
542 wasExtant_
{wasExtant
}, isNewUnit_
{isNewUnit
} {}
543 bool wasExtant() const { return wasExtant_
; }
544 void set_status(OpenStatus status
) { status_
= status
; } // STATUS=
545 void set_path(const char *, std::size_t); // FILE=
546 void set_position(Position position
) { position_
= position
; } // POSITION=
547 void set_action(Action action
) { action_
= action
; } // ACTION=
548 void set_convert(Convert convert
) { convert_
= convert
; } // CONVERT=
549 void set_access(Access access
) { access_
= access
; } // ACCESS=
550 void set_isUnformatted(bool yes
= true) { isUnformatted_
= yes
; } // FORM=
552 void CompleteOperation();
553 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_