FLANG

unit.h
1 //===-- runtime/unit.h ------------------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 // Fortran external I/O units
10
11 #ifndef FORTRAN_RUNTIME_IO_UNIT_H_
12 #define FORTRAN_RUNTIME_IO_UNIT_H_
13
14 #include "buffer.h"
15 #include "connection.h"
16 #include "file.h"
17 #include "format.h"
18 #include "io-error.h"
19 #include "io-stmt.h"
20 #include "lock.h"
21 #include "memory.h"
22 #include "terminator.h"
23 #include <cstdlib>
24 #include <cstring>
25 #include <optional>
26 #include <variant>
27
28 namespace Fortran::runtime::io {
29
30 class UnitMap;
31
32 class ExternalFileUnit : public ConnectionState,
33 public OpenFile,
34 public FileFrame<ExternalFileUnit> {
35 public:
36 explicit ExternalFileUnit(int unitNumber) : unitNumber_{unitNumber} {}
37 int unitNumber() const { return unitNumber_; }
38
39 static ExternalFileUnit *LookUp(int unit);
40 static ExternalFileUnit &LookUpOrCrash(int unit, const Terminator &);
41 static ExternalFileUnit &LookUpOrCreate(
42 int unit, const Terminator &, bool &wasExtant);
43 static ExternalFileUnit &LookUpOrCreateAnonymous(
44 int unit, Direction, bool isUnformatted, const Terminator &);
45 static ExternalFileUnit &CreateNew(int unit, const Terminator &);
46 static ExternalFileUnit *LookUpForClose(int unit);
47 static int NewUnit(const Terminator &);
48 static void CloseAll(IoErrorHandler &);
49 static void FlushAll(IoErrorHandler &);
50
51 void OpenUnit(OpenStatus, Position, OwningPtr<char> &&path,
52 std::size_t pathLength, IoErrorHandler &);
53 void CloseUnit(CloseStatus, IoErrorHandler &);
54 void DestroyClosed();
55
56 bool SetDirection(Direction, IoErrorHandler &);
57
58 template <typename A, typename... X>
59 IoStatementState &BeginIoStatement(X &&... xs) {
60 // TODO: Child data transfer statements vs. locking
61 lock_.Take(); // dropped in EndIoStatement()
62 A &state{u_.emplace<A>(std::forward<X>(xs)...)};
63 if constexpr (!std::is_same_v<A, OpenStatementState>) {
64 state.mutableModes() = ConnectionState::modes;
65 }
66 io_.emplace(state);
67 return *io_;
68 }
69
70 bool Emit(const char *, std::size_t, IoErrorHandler &);
71 bool Receive(char *, std::size_t, IoErrorHandler &);
72 std::optional<char32_t> GetCurrentChar(IoErrorHandler &);
73 void SetLeftTabLimit();
74 void BeginReadingRecord(IoErrorHandler &);
75 bool AdvanceRecord(IoErrorHandler &);
76 void BackspaceRecord(IoErrorHandler &);
77 void FlushIfTerminal(IoErrorHandler &);
78 void Endfile(IoErrorHandler &);
79 void Rewind(IoErrorHandler &);
80 void EndIoStatement();
81 void SetPosition(std::int64_t pos) {
82 frameOffsetInFile_ = pos;
83 recordOffsetInFrame_ = 0;
84 BeginRecord();
85 }
86
87 private:
88 static UnitMap &GetUnitMap();
89 const char *FrameNextInput(IoErrorHandler &, std::size_t);
90 void BeginSequentialVariableUnformattedInputRecord(IoErrorHandler &);
91 void BeginSequentialVariableFormattedInputRecord(IoErrorHandler &);
92 void BackspaceFixedRecord(IoErrorHandler &);
93 void BackspaceVariableUnformattedRecord(IoErrorHandler &);
94 void BackspaceVariableFormattedRecord(IoErrorHandler &);
95 bool SetSequentialVariableFormattedRecordLength();
96 void DoImpliedEndfile(IoErrorHandler &);
97 void DoEndfile(IoErrorHandler &);
98
99 int unitNumber_{-1};
100 Direction direction_{Direction::Output};
101 bool impliedEndfile_{false}; // seq. output has taken place
102
103 Lock lock_;
104
105 // When an I/O statement is in progress on this unit, holds its state.
106 std::variant<std::monostate, OpenStatementState, CloseStatementState,
107 ExternalFormattedIoStatementState<Direction::Output>,
108 ExternalFormattedIoStatementState<Direction::Input>,
109 ExternalListIoStatementState<Direction::Output>,
110 ExternalListIoStatementState<Direction::Input>,
111 UnformattedIoStatementState<Direction::Output>,
112 UnformattedIoStatementState<Direction::Input>,
113 ExternalMiscIoStatementState>
114 u_;
115
116 // Points to the active alternative (if any) in u_ for use as a Cookie
117 std::optional<IoStatementState> io_;
118
119 // Subtle: The beginning of the frame can't be allowed to advance
120 // during a single list-directed READ due to the possibility of a
121 // multi-record CHARACTER value with a "r*" repeat count. So we
122 // manage the frame and the current record therein separately.
123 std::int64_t frameOffsetInFile_{0};
124 std::size_t recordOffsetInFrame_{0}; // of currentRecordNumber
125 };
126
127 } // namespace Fortran::runtime::io
128 #endif // FORTRAN_RUNTIME_IO_UNIT_H_
Fortran::runtime::io::ExternalFormattedIoStatementState
Definition: io-stmt.h:36
Fortran::runtime::io::OpenFile
Definition: file.h:25
Fortran::runtime::io::UnformattedIoStatementState
Definition: io-stmt.h:38
Fortran::runtime::io::CloseStatementState
Definition: io-stmt.h:310
Fortran::runtime::Terminator
Definition: terminator.h:21
Fortran::runtime::io::IoStatementState
Definition: io-stmt.h:42
Fortran::runtime::io::IoErrorHandler
Definition: io-error.h:26
Fortran::runtime::io::ExternalMiscIoStatementState
Definition: io-stmt.h:360
Fortran::runtime::io::ExternalFileUnit
Definition: unit.h:32
Fortran::runtime::Lock
Definition: lock.h:32
Fortran::runtime::io::ExternalListIoStatementState
Definition: io-stmt.h:37
Fortran::runtime::io::FileFrame
Definition: buffer.h:30
Fortran::runtime::io::ConnectionState
Definition: connection.h:35
Fortran::runtime::io::UnitMap
Definition: unit-map.h:22
Fortran::runtime::io::OpenStatementState
Definition: io-stmt.h:290