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 byteOffset
);
96 void HandleAbsolutePosition(std::int64_t byteOffset
); // 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 // The "remaining" arguments to CueUpInput(), SkipSpaces(), & NextInField()
128 // are always in units of bytes, not characters; the distinction matters
129 // for internal input from CHARACTER(KIND=2 and 4).
131 // For fixed-width fields, return the number of remaining bytes.
132 // Skip over leading blanks.
133 std::optional
<int> CueUpInput(const DataEdit
&edit
) {
134 std::optional
<int> remaining
;
135 if (edit
.IsListDirected()) {
136 std::size_t byteCount
{0};
137 GetNextNonBlank(byteCount
);
139 if (edit
.width
.value_or(0) > 0) {
140 remaining
= *edit
.width
;
141 if (int bytesPerChar
{GetConnectionState().internalIoCharKind
};
143 *remaining
*= bytesPerChar
;
146 SkipSpaces(remaining
);
151 std::optional
<char32_t
> SkipSpaces(std::optional
<int> &remaining
) {
152 while (!remaining
|| *remaining
> 0) {
153 std::size_t byteCount
{0};
154 if (auto ch
{GetCurrentChar(byteCount
)}) {
155 if (*ch
!= ' ' && *ch
!= '\t') {
159 if (static_cast<std::size_t>(*remaining
) < byteCount
) {
163 *remaining
-= byteCount
;
165 HandleRelativePosition(byteCount
);
173 // Acquires the next input character, respecting any applicable field width
174 // or separator character.
175 std::optional
<char32_t
> NextInField(
176 std::optional
<int> &remaining
, const DataEdit
&);
178 // Detect and signal any end-of-record condition after input.
179 // Returns true if at EOR and remaining input should be padded with blanks.
180 bool CheckForEndOfRecord(std::size_t afterReading
);
182 // Skips spaces, advances records, and ignores NAMELIST comments
183 std::optional
<char32_t
> GetNextNonBlank(std::size_t &byteCount
) {
184 auto ch
{GetCurrentChar(byteCount
)};
185 bool inNamelist
{mutableModes().inNamelist
};
186 while (!ch
|| *ch
== ' ' || *ch
== '\t' || (inNamelist
&& *ch
== '!')) {
187 if (ch
&& (*ch
== ' ' || *ch
== '\t')) {
188 HandleRelativePosition(byteCount
);
189 } else if (!AdvanceRecord()) {
192 ch
= GetCurrentChar(byteCount
);
197 template <Direction D
> bool CheckFormattedStmtType(const char *name
) {
198 if (get_if
<FormattedIoStatementState
<D
>>()) {
201 auto &handler
{GetIoErrorHandler()};
202 if (!handler
.InError()) {
203 handler
.Crash("%s called for I/O statement that is not formatted %s",
204 name
, D
== Direction::Output
? "output" : "input");
211 std::variant
<std::reference_wrapper
<OpenStatementState
>,
212 std::reference_wrapper
<CloseStatementState
>,
213 std::reference_wrapper
<NoopStatementState
>,
214 std::reference_wrapper
<
215 InternalFormattedIoStatementState
<Direction::Output
>>,
216 std::reference_wrapper
<
217 InternalFormattedIoStatementState
<Direction::Input
>>,
218 std::reference_wrapper
<InternalListIoStatementState
<Direction::Output
>>,
219 std::reference_wrapper
<InternalListIoStatementState
<Direction::Input
>>,
220 std::reference_wrapper
<
221 ExternalFormattedIoStatementState
<Direction::Output
>>,
222 std::reference_wrapper
<
223 ExternalFormattedIoStatementState
<Direction::Input
>>,
224 std::reference_wrapper
<ExternalListIoStatementState
<Direction::Output
>>,
225 std::reference_wrapper
<ExternalListIoStatementState
<Direction::Input
>>,
226 std::reference_wrapper
<
227 ExternalUnformattedIoStatementState
<Direction::Output
>>,
228 std::reference_wrapper
<
229 ExternalUnformattedIoStatementState
<Direction::Input
>>,
230 std::reference_wrapper
<ChildFormattedIoStatementState
<Direction::Output
>>,
231 std::reference_wrapper
<ChildFormattedIoStatementState
<Direction::Input
>>,
232 std::reference_wrapper
<ChildListIoStatementState
<Direction::Output
>>,
233 std::reference_wrapper
<ChildListIoStatementState
<Direction::Input
>>,
234 std::reference_wrapper
<
235 ChildUnformattedIoStatementState
<Direction::Output
>>,
236 std::reference_wrapper
<
237 ChildUnformattedIoStatementState
<Direction::Input
>>,
238 std::reference_wrapper
<InquireUnitState
>,
239 std::reference_wrapper
<InquireNoUnitState
>,
240 std::reference_wrapper
<InquireUnconnectedFileState
>,
241 std::reference_wrapper
<InquireIOLengthState
>,
242 std::reference_wrapper
<ExternalMiscIoStatementState
>,
243 std::reference_wrapper
<ErroneousIoStatementState
>>
247 // Base class for all per-I/O statement state classes.
248 class IoStatementBase
: public IoErrorHandler
{
250 using IoErrorHandler::IoErrorHandler
;
252 bool completedOperation() const { return completedOperation_
; }
254 void CompleteOperation() { completedOperation_
= true; }
255 int EndIoStatement() { return GetIoStat(); }
257 // These are default no-op backstops that can be overridden by descendants.
258 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
259 bool Receive(char *, std::size_t bytes
, std::size_t elementBytes
= 0);
260 std::size_t GetNextInputBytes(const char *&);
261 bool AdvanceRecord(int);
262 void BackspaceRecord();
263 void HandleRelativePosition(std::int64_t);
264 void HandleAbsolutePosition(std::int64_t);
265 std::optional
<DataEdit
> GetNextDataEdit(
266 IoStatementState
&, int maxRepeat
= 1);
267 ExternalFileUnit
*GetExternalFileUnit() const;
268 bool BeginReadingRecord();
269 void FinishReadingRecord();
270 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
271 bool Inquire(InquiryKeywordHash
, bool &);
272 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
273 bool Inquire(InquiryKeywordHash
, std::int64_t &);
274 std::int64_t InquirePos();
276 void BadInquiryKeywordHashCrash(InquiryKeywordHash
);
279 bool completedOperation_
{false};
282 // Common state for list-directed & NAMELIST I/O, both internal & external
283 template <Direction
> class ListDirectedStatementState
;
285 class ListDirectedStatementState
<Direction::Output
>
286 : public FormattedIoStatementState
<Direction::Output
> {
288 bool EmitLeadingSpaceOrAdvance(
289 IoStatementState
&, std::size_t = 1, bool isCharacter
= false);
290 std::optional
<DataEdit
> GetNextDataEdit(
291 IoStatementState
&, int maxRepeat
= 1);
292 bool lastWasUndelimitedCharacter() const {
293 return lastWasUndelimitedCharacter_
;
295 void set_lastWasUndelimitedCharacter(bool yes
= true) {
296 lastWasUndelimitedCharacter_
= yes
;
300 bool lastWasUndelimitedCharacter_
{false};
303 class ListDirectedStatementState
<Direction::Input
>
304 : public FormattedIoStatementState
<Direction::Input
> {
306 bool inNamelistSequence() const { return inNamelistSequence_
; }
307 int EndIoStatement();
309 // Skips value separators, handles repetition and null values.
310 // Vacant when '/' appears; present with descriptor == ListDirectedNullValue
311 // when a null value appears.
312 std::optional
<DataEdit
> GetNextDataEdit(
313 IoStatementState
&, int maxRepeat
= 1);
315 // Each NAMELIST input item is treated like a distinct list-directed
316 // input statement. This member function resets some state so that
317 // repetition and null values work correctly for each successive
318 // NAMELIST input item.
319 void ResetForNextNamelistItem(bool inNamelistSequence
) {
321 if (repeatPosition_
) {
322 repeatPosition_
->Cancel();
325 realPart_
= imaginaryPart_
= false;
326 inNamelistSequence_
= inNamelistSequence
;
330 int remaining_
{0}; // for "r*" repetition
331 std::optional
<SavedPosition
> repeatPosition_
;
332 bool eatComma_
{false}; // consume comma after previously read item
333 bool hitSlash_
{false}; // once '/' is seen, nullify further items
334 bool realPart_
{false};
335 bool imaginaryPart_
{false};
336 bool inNamelistSequence_
{false};
339 template <Direction
DIR>
340 class InternalIoStatementState
: public IoStatementBase
,
341 public IoDirectionState
<DIR> {
344 std::conditional_t
<DIR == Direction::Input
, const char *, char *>;
345 InternalIoStatementState(Buffer
, std::size_t,
346 const char *sourceFile
= nullptr, int sourceLine
= 0);
347 InternalIoStatementState(
348 const Descriptor
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
349 int EndIoStatement();
351 bool Emit(const char *data
, std::size_t bytes
, std::size_t elementBytes
= 0);
352 std::size_t GetNextInputBytes(const char *&);
353 bool AdvanceRecord(int = 1);
354 void BackspaceRecord();
355 ConnectionState
&GetConnectionState() { return unit_
; }
356 MutableModes
&mutableModes() { return unit_
.modes
; }
357 void HandleRelativePosition(std::int64_t);
358 void HandleAbsolutePosition(std::int64_t);
359 std::int64_t InquirePos();
363 InternalDescriptorUnit
<DIR> unit_
;
366 template <Direction
DIR, typename CHAR
>
367 class InternalFormattedIoStatementState
368 : public InternalIoStatementState
<DIR>,
369 public FormattedIoStatementState
<DIR> {
371 using CharType
= CHAR
;
372 using typename InternalIoStatementState
<DIR>::Buffer
;
373 InternalFormattedIoStatementState(Buffer internal
, std::size_t internalLength
,
374 const CharType
*format
, std::size_t formatLength
,
375 const Descriptor
*formatDescriptor
= nullptr,
376 const char *sourceFile
= nullptr, int sourceLine
= 0);
377 InternalFormattedIoStatementState(const Descriptor
&, const CharType
*format
,
378 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
379 const char *sourceFile
= nullptr, int sourceLine
= 0);
380 IoStatementState
&ioStatementState() { return ioStatementState_
; }
381 void CompleteOperation();
382 int EndIoStatement();
383 std::optional
<DataEdit
> GetNextDataEdit(
384 IoStatementState
&, int maxRepeat
= 1) {
385 return format_
.GetNextDataEdit(*this, maxRepeat
);
389 IoStatementState ioStatementState_
; // points to *this
390 using InternalIoStatementState
<DIR>::unit_
;
391 // format_ *must* be last; it may be partial someday
392 FormatControl
<InternalFormattedIoStatementState
> format_
;
395 template <Direction
DIR>
396 class InternalListIoStatementState
: public InternalIoStatementState
<DIR>,
397 public ListDirectedStatementState
<DIR> {
399 using typename InternalIoStatementState
<DIR>::Buffer
;
400 InternalListIoStatementState(Buffer internal
, std::size_t internalLength
,
401 const char *sourceFile
= nullptr, int sourceLine
= 0);
402 InternalListIoStatementState(
403 const Descriptor
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
404 IoStatementState
&ioStatementState() { return ioStatementState_
; }
405 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
406 int EndIoStatement();
409 IoStatementState ioStatementState_
; // points to *this
410 using InternalIoStatementState
<DIR>::unit_
;
413 class ExternalIoStatementBase
: public IoStatementBase
{
415 ExternalIoStatementBase(
416 ExternalFileUnit
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
417 ExternalFileUnit
&unit() { return unit_
; }
418 MutableModes
&mutableModes();
419 ConnectionState
&GetConnectionState();
420 int asynchronousID() const { return asynchronousID_
; }
421 int EndIoStatement();
422 ExternalFileUnit
*GetExternalFileUnit() const { return &unit_
; }
423 void SetAsynchronous();
424 std::int64_t InquirePos();
427 ExternalFileUnit
&unit_
;
428 int asynchronousID_
{-1};
431 template <Direction
DIR>
432 class ExternalIoStatementState
: public ExternalIoStatementBase
,
433 public IoDirectionState
<DIR> {
435 ExternalIoStatementState(
436 ExternalFileUnit
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
437 MutableModes
&mutableModes() { return mutableModes_
; }
438 void CompleteOperation();
439 int EndIoStatement();
440 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
441 std::size_t GetNextInputBytes(const char *&);
442 bool AdvanceRecord(int = 1);
443 void BackspaceRecord();
444 void HandleRelativePosition(std::int64_t);
445 void HandleAbsolutePosition(std::int64_t);
446 bool BeginReadingRecord();
447 void FinishReadingRecord();
450 // These are forked from ConnectionState's modes at the beginning
451 // of each formatted I/O statement so they may be overridden by control
452 // edit descriptors during the statement.
453 MutableModes mutableModes_
;
456 template <Direction
DIR, typename CHAR
>
457 class ExternalFormattedIoStatementState
458 : public ExternalIoStatementState
<DIR>,
459 public FormattedIoStatementState
<DIR> {
461 using CharType
= CHAR
;
462 ExternalFormattedIoStatementState(ExternalFileUnit
&, const CharType
*format
,
463 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
464 const char *sourceFile
= nullptr, int sourceLine
= 0);
465 void CompleteOperation();
466 int EndIoStatement();
467 std::optional
<DataEdit
> GetNextDataEdit(
468 IoStatementState
&, int maxRepeat
= 1) {
469 return format_
.GetNextDataEdit(*this, maxRepeat
);
473 FormatControl
<ExternalFormattedIoStatementState
> format_
;
476 template <Direction
DIR>
477 class ExternalListIoStatementState
: public ExternalIoStatementState
<DIR>,
478 public ListDirectedStatementState
<DIR> {
480 using ExternalIoStatementState
<DIR>::ExternalIoStatementState
;
481 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
482 int EndIoStatement();
485 template <Direction
DIR>
486 class ExternalUnformattedIoStatementState
487 : public ExternalIoStatementState
<DIR> {
489 using ExternalIoStatementState
<DIR>::ExternalIoStatementState
;
490 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
493 template <Direction
DIR>
494 class ChildIoStatementState
: public IoStatementBase
,
495 public IoDirectionState
<DIR> {
497 ChildIoStatementState(
498 ChildIo
&, const char *sourceFile
= nullptr, int sourceLine
= 0);
499 ChildIo
&child() { return child_
; }
500 MutableModes
&mutableModes();
501 ConnectionState
&GetConnectionState();
502 ExternalFileUnit
*GetExternalFileUnit() const;
503 int EndIoStatement();
504 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
505 std::size_t GetNextInputBytes(const char *&);
506 void HandleRelativePosition(std::int64_t);
507 void HandleAbsolutePosition(std::int64_t);
513 template <Direction
DIR, typename CHAR
>
514 class ChildFormattedIoStatementState
: public ChildIoStatementState
<DIR>,
515 public FormattedIoStatementState
<DIR> {
517 using CharType
= CHAR
;
518 ChildFormattedIoStatementState(ChildIo
&, const CharType
*format
,
519 std::size_t formatLength
, const Descriptor
*formatDescriptor
= nullptr,
520 const char *sourceFile
= nullptr, int sourceLine
= 0);
521 MutableModes
&mutableModes() { return mutableModes_
; }
522 void CompleteOperation();
523 int EndIoStatement();
524 bool AdvanceRecord(int = 1);
525 std::optional
<DataEdit
> GetNextDataEdit(
526 IoStatementState
&, int maxRepeat
= 1) {
527 return format_
.GetNextDataEdit(*this, maxRepeat
);
531 MutableModes mutableModes_
;
532 FormatControl
<ChildFormattedIoStatementState
> format_
;
535 template <Direction
DIR>
536 class ChildListIoStatementState
: public ChildIoStatementState
<DIR>,
537 public ListDirectedStatementState
<DIR> {
539 using ChildIoStatementState
<DIR>::ChildIoStatementState
;
540 using ListDirectedStatementState
<DIR>::GetNextDataEdit
;
541 int EndIoStatement();
544 template <Direction
DIR>
545 class ChildUnformattedIoStatementState
: public ChildIoStatementState
<DIR> {
547 using ChildIoStatementState
<DIR>::ChildIoStatementState
;
548 bool Receive(char *, std::size_t, std::size_t elementBytes
= 0);
552 class OpenStatementState
: public ExternalIoStatementBase
{
554 OpenStatementState(ExternalFileUnit
&unit
, bool wasExtant
, bool isNewUnit
,
555 const char *sourceFile
= nullptr, int sourceLine
= 0)
556 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
},
557 wasExtant_
{wasExtant
}, isNewUnit_
{isNewUnit
} {}
558 bool wasExtant() const { return wasExtant_
; }
559 void set_status(OpenStatus status
) { status_
= status
; } // STATUS=
560 void set_path(const char *, std::size_t); // FILE=
561 void set_position(Position position
) { position_
= position
; } // POSITION=
562 void set_action(Action action
) { action_
= action
; } // ACTION=
563 void set_convert(Convert convert
) { convert_
= convert
; } // CONVERT=
564 void set_access(Access access
) { access_
= access
; } // ACCESS=
565 void set_isUnformatted(bool yes
= true) { isUnformatted_
= yes
; } // FORM=
567 void CompleteOperation();
568 int EndIoStatement();
573 std::optional
<OpenStatus
> status_
;
574 std::optional
<Position
> position_
;
575 std::optional
<Action
> action_
;
576 Convert convert_
{Convert::Unknown
};
577 OwningPtr
<char> path_
;
578 std::size_t pathLength_
;
579 std::optional
<bool> isUnformatted_
;
580 std::optional
<Access
> access_
;
583 class CloseStatementState
: public ExternalIoStatementBase
{
585 CloseStatementState(ExternalFileUnit
&unit
, const char *sourceFile
= nullptr,
587 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
} {}
588 void set_status(CloseStatus status
) { status_
= status
; }
589 int EndIoStatement();
592 CloseStatus status_
{CloseStatus::Keep
};
595 // For CLOSE(bad unit), WAIT(bad unit, ID=nonzero), INQUIRE(unconnected unit),
596 // and recoverable BACKSPACE(bad unit)
597 class NoUnitIoStatementState
: public IoStatementBase
{
599 IoStatementState
&ioStatementState() { return ioStatementState_
; }
600 MutableModes
&mutableModes() { return connection_
.modes
; }
601 ConnectionState
&GetConnectionState() { return connection_
; }
602 int badUnitNumber() const { return badUnitNumber_
; }
603 void CompleteOperation();
604 int EndIoStatement();
607 template <typename A
>
608 NoUnitIoStatementState(A
&stmt
, const char *sourceFile
= nullptr,
609 int sourceLine
= 0, int badUnitNumber
= -1)
610 : IoStatementBase
{sourceFile
, sourceLine
}, ioStatementState_
{stmt
},
611 badUnitNumber_
{badUnitNumber
} {}
614 IoStatementState ioStatementState_
; // points to *this
615 ConnectionState connection_
;
619 class NoopStatementState
: public NoUnitIoStatementState
{
622 const char *sourceFile
= nullptr, int sourceLine
= 0, int unitNumber
= -1)
623 : NoUnitIoStatementState
{*this, sourceFile
, sourceLine
, unitNumber
} {}
624 void set_status(CloseStatus
) {} // discards
627 extern template class InternalIoStatementState
<Direction::Output
>;
628 extern template class InternalIoStatementState
<Direction::Input
>;
629 extern template class InternalFormattedIoStatementState
<Direction::Output
>;
630 extern template class InternalFormattedIoStatementState
<Direction::Input
>;
631 extern template class InternalListIoStatementState
<Direction::Output
>;
632 extern template class InternalListIoStatementState
<Direction::Input
>;
633 extern template class ExternalIoStatementState
<Direction::Output
>;
634 extern template class ExternalIoStatementState
<Direction::Input
>;
635 extern template class ExternalFormattedIoStatementState
<Direction::Output
>;
636 extern template class ExternalFormattedIoStatementState
<Direction::Input
>;
637 extern template class ExternalListIoStatementState
<Direction::Output
>;
638 extern template class ExternalListIoStatementState
<Direction::Input
>;
639 extern template class ExternalUnformattedIoStatementState
<Direction::Output
>;
640 extern template class ExternalUnformattedIoStatementState
<Direction::Input
>;
641 extern template class ChildIoStatementState
<Direction::Output
>;
642 extern template class ChildIoStatementState
<Direction::Input
>;
643 extern template class ChildFormattedIoStatementState
<Direction::Output
>;
644 extern template class ChildFormattedIoStatementState
<Direction::Input
>;
645 extern template class ChildListIoStatementState
<Direction::Output
>;
646 extern template class ChildListIoStatementState
<Direction::Input
>;
647 extern template class ChildUnformattedIoStatementState
<Direction::Output
>;
648 extern template class ChildUnformattedIoStatementState
<Direction::Input
>;
650 extern template class FormatControl
<
651 InternalFormattedIoStatementState
<Direction::Output
>>;
652 extern template class FormatControl
<
653 InternalFormattedIoStatementState
<Direction::Input
>>;
654 extern template class FormatControl
<
655 ExternalFormattedIoStatementState
<Direction::Output
>>;
656 extern template class FormatControl
<
657 ExternalFormattedIoStatementState
<Direction::Input
>>;
658 extern template class FormatControl
<
659 ChildFormattedIoStatementState
<Direction::Output
>>;
660 extern template class FormatControl
<
661 ChildFormattedIoStatementState
<Direction::Input
>>;
663 class InquireUnitState
: public ExternalIoStatementBase
{
665 InquireUnitState(ExternalFileUnit
&unit
, const char *sourceFile
= nullptr,
667 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
668 bool Inquire(InquiryKeywordHash
, bool &);
669 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
670 bool Inquire(InquiryKeywordHash
, std::int64_t &);
673 class InquireNoUnitState
: public NoUnitIoStatementState
{
675 InquireNoUnitState(const char *sourceFile
= nullptr, int sourceLine
= 0,
676 int badUnitNumber
= -1);
677 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
678 bool Inquire(InquiryKeywordHash
, bool &);
679 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
680 bool Inquire(InquiryKeywordHash
, std::int64_t &);
683 class InquireUnconnectedFileState
: public NoUnitIoStatementState
{
685 InquireUnconnectedFileState(OwningPtr
<char> &&path
,
686 const char *sourceFile
= nullptr, int sourceLine
= 0);
687 bool Inquire(InquiryKeywordHash
, char *, std::size_t);
688 bool Inquire(InquiryKeywordHash
, bool &);
689 bool Inquire(InquiryKeywordHash
, std::int64_t, bool &);
690 bool Inquire(InquiryKeywordHash
, std::int64_t &);
693 OwningPtr
<char> path_
; // trimmed and NUL terminated
696 class InquireIOLengthState
: public NoUnitIoStatementState
,
697 public OutputStatementState
{
699 InquireIOLengthState(const char *sourceFile
= nullptr, int sourceLine
= 0);
700 std::size_t bytes() const { return bytes_
; }
701 bool Emit(const char *, std::size_t bytes
, std::size_t elementBytes
= 0);
704 std::size_t bytes_
{0};
707 class ExternalMiscIoStatementState
: public ExternalIoStatementBase
{
709 enum Which
{ Flush
, Backspace
, Endfile
, Rewind
, Wait
};
710 ExternalMiscIoStatementState(ExternalFileUnit
&unit
, Which which
,
711 const char *sourceFile
= nullptr, int sourceLine
= 0)
712 : ExternalIoStatementBase
{unit
, sourceFile
, sourceLine
}, which_
{which
} {}
713 void CompleteOperation();
714 int EndIoStatement();
720 class ErroneousIoStatementState
: public IoStatementBase
{
722 explicit ErroneousIoStatementState(Iostat iostat
,
723 ExternalFileUnit
*unit
= nullptr, const char *sourceFile
= nullptr,
725 : IoStatementBase
{sourceFile
, sourceLine
}, unit_
{unit
} {
726 SetPendingError(iostat
);
728 int EndIoStatement();
729 ConnectionState
&GetConnectionState() { return connection_
; }
730 MutableModes
&mutableModes() { return connection_
.modes
; }
733 ConnectionState connection_
;
734 ExternalFileUnit
*unit_
{nullptr};
737 } // namespace Fortran::runtime::io
738 #endif // FORTRAN_RUNTIME_IO_STMT_H_