Skip to content

Commit 5d5b968

Browse files
committed
[flang] Add fixes and missing stmts to I/O runtime API handlers (ext. I/O part 8)
Complete the rework of the initial implementation of external I/O to fix problems found in testing (tests to follow); add handlers for hitherto unimplemented PAUSE, FLUSH, ENDFILE, BACKSPACE, and REWIND statements. Reviewed By: tskeith, sscalpone Differential Revision: https://reviews.llvm.org/D83162
1 parent 120c5f1 commit 5d5b968

File tree

3 files changed

+84
-14
lines changed

3 files changed

+84
-14
lines changed

flang/runtime/io-api.cpp

+69-14
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@ Cookie BeginExternalListIO(
121121
terminator.Crash("List-directed I/O attempted on unformatted file");
122122
return nullptr;
123123
}
124+
IoErrorHandler handler{terminator};
125+
unit.SetDirection(DIR, handler);
124126
IoStatementState &io{unit.BeginIoStatement<ExternalListIoStatementState<DIR>>(
125127
unit, sourceFile, sourceLine)};
126128
if constexpr (DIR == Direction::Input) {
127-
io.AdvanceRecord();
129+
unit.BeginReadingRecord(handler);
128130
}
129131
return &io;
130132
}
@@ -154,11 +156,13 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
154156
terminator.Crash("Formatted I/O attempted on unformatted file");
155157
return nullptr;
156158
}
159+
IoErrorHandler handler{terminator};
160+
unit.SetDirection(DIR, handler);
157161
IoStatementState &io{
158162
unit.BeginIoStatement<ExternalFormattedIoStatementState<DIR>>(
159163
unit, format, formatLength, sourceFile, sourceLine)};
160164
if constexpr (DIR == Direction::Input) {
161-
io.AdvanceRecord();
165+
unit.BeginReadingRecord(handler);
162166
}
163167
return &io;
164168
}
@@ -181,17 +185,19 @@ template <Direction DIR>
181185
Cookie BeginUnformattedIO(
182186
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
183187
Terminator terminator{sourceFile, sourceLine};
184-
ExternalFileUnit &file{
188+
ExternalFileUnit &unit{
185189
ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
186-
if (!file.isUnformatted) {
190+
if (!unit.isUnformatted) {
187191
terminator.Crash("Unformatted output attempted on formatted file");
188192
}
189-
IoStatementState &io{file.BeginIoStatement<UnformattedIoStatementState<DIR>>(
190-
file, sourceFile, sourceLine)};
193+
IoStatementState &io{unit.BeginIoStatement<UnformattedIoStatementState<DIR>>(
194+
unit, sourceFile, sourceLine)};
195+
IoErrorHandler handler{terminator};
196+
unit.SetDirection(DIR, handler);
191197
if constexpr (DIR == Direction::Input) {
192-
io.AdvanceRecord();
198+
unit.BeginReadingRecord(handler);
193199
} else {
194-
if (file.access == Access::Sequential && !file.recordLength.has_value()) {
200+
if (unit.access == Access::Sequential && !unit.isFixedRecordLength) {
195201
// Create space for (sub)record header to be completed by
196202
// UnformattedIoStatementState<Direction::Output>::EndIoStatement()
197203
io.Emit("\0\0\0\0", 4); // placeholder for record length header
@@ -225,8 +231,10 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
225231
Cookie IONAME(BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
226232
const char *sourceFile, int sourceLine) {
227233
Terminator terminator{sourceFile, sourceLine};
228-
return IONAME(BeginOpenUnit)(
229-
ExternalFileUnit::NewUnit(terminator), sourceFile, sourceLine);
234+
ExternalFileUnit &unit{ExternalFileUnit::LookUpOrCreate(
235+
ExternalFileUnit::NewUnit(terminator), terminator)};
236+
return &unit.BeginIoStatement<OpenStatementState>(
237+
unit, false /*wasExtant*/, sourceFile, sourceLine);
230238
}
231239

232240
Cookie IONAME(BeginClose)(
@@ -243,6 +251,42 @@ Cookie IONAME(BeginClose)(
243251
}
244252
}
245253

254+
Cookie IONAME(BeginFlush)(
255+
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
256+
Terminator terminator{sourceFile, sourceLine};
257+
ExternalFileUnit &unit{
258+
ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
259+
return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
260+
unit, ExternalMiscIoStatementState::Flush, sourceFile, sourceLine);
261+
}
262+
263+
Cookie IONAME(BeginBackspace)(
264+
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
265+
Terminator terminator{sourceFile, sourceLine};
266+
ExternalFileUnit &unit{
267+
ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
268+
return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
269+
unit, ExternalMiscIoStatementState::Backspace, sourceFile, sourceLine);
270+
}
271+
272+
Cookie IONAME(BeginEndfile)(
273+
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
274+
Terminator terminator{sourceFile, sourceLine};
275+
ExternalFileUnit &unit{
276+
ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
277+
return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
278+
unit, ExternalMiscIoStatementState::Endfile, sourceFile, sourceLine);
279+
}
280+
281+
Cookie IONAME(BeginRewind)(
282+
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
283+
Terminator terminator{sourceFile, sourceLine};
284+
ExternalFileUnit &unit{
285+
ExternalFileUnit::LookUpOrCrash(unitNumber, terminator)};
286+
return &unit.BeginIoStatement<ExternalMiscIoStatementState>(
287+
unit, ExternalMiscIoStatementState::Rewind, sourceFile, sourceLine);
288+
}
289+
246290
// Control list items
247291

248292
void IONAME(EnableHandlers)(Cookie cookie, bool hasIoStat, bool hasErr,
@@ -388,7 +432,7 @@ bool IONAME(SetRec)(Cookie cookie, std::int64_t rec) {
388432
"REC= may not appear unless ACCESS='DIRECT'");
389433
return false;
390434
}
391-
if (!connection.recordLength) {
435+
if (!connection.isFixedRecordLength || !connection.recordLength) {
392436
io.GetIoErrorHandler().SignalError("RECL= was not specified");
393437
return false;
394438
}
@@ -640,10 +684,11 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
640684
if (n <= 0) {
641685
io.GetIoErrorHandler().SignalError("RECL= must be greater than zero");
642686
}
643-
if (open->wasExtant() && open->unit().recordLength.has_value() &&
644-
*open->unit().recordLength != static_cast<std::int64_t>(n)) {
687+
if (open->wasExtant() && open->unit().isFixedRecordLength &&
688+
open->unit().recordLength.value_or(n) != static_cast<std::int64_t>(n)) {
645689
open->SignalError("RECL= may not be changed for an open unit");
646690
}
691+
open->unit().isFixedRecordLength = true;
647692
open->unit().recordLength = n;
648693
return true;
649694
}
@@ -754,7 +799,17 @@ bool IONAME(OutputUnformattedBlock)(
754799
if (auto *unf{io.get_if<UnformattedIoStatementState<Direction::Output>>()}) {
755800
return unf->Emit(x, length);
756801
}
757-
io.GetIoErrorHandler().Crash("OutputUnformatted() called for an I/O "
802+
io.GetIoErrorHandler().Crash("OutputUnformattedBlock() called for an I/O "
803+
"statement that is not unformatted output");
804+
return false;
805+
}
806+
807+
bool IONAME(InputUnformattedBlock)(Cookie cookie, char *x, std::size_t length) {
808+
IoStatementState &io{*cookie};
809+
if (auto *unf{io.get_if<UnformattedIoStatementState<Direction::Input>>()}) {
810+
return unf->Receive(x, length);
811+
}
812+
io.GetIoErrorHandler().Crash("InputUnformattedBlock() called for an I/O "
758813
"statement that is not unformatted output");
759814
return false;
760815
}

flang/runtime/stop.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "stop.h"
10+
#include "file.h"
1011
#include "io-error.h"
1112
#include "terminator.h"
1213
#include "unit.h"
@@ -71,6 +72,19 @@ static void CloseAllExternalUnits(const char *why) {
7172
std::exit(EXIT_FAILURE);
7273
}
7374

75+
void RTNAME(PauseStatement)() {
76+
if (Fortran::runtime::io::IsATerminal(0)) {
77+
Fortran::runtime::io::IoErrorHandler handler{"PAUSE statement"};
78+
Fortran::runtime::io::ExternalFileUnit::FlushAll(handler);
79+
std::fputs("Fortran PAUSE: hit RETURN to continue:", stderr);
80+
std::fflush(nullptr);
81+
if (std::fgetc(stdin) == EOF) {
82+
CloseAllExternalUnits("PAUSE statement");
83+
std::exit(EXIT_SUCCESS);
84+
}
85+
}
86+
}
87+
7488
[[noreturn]] void RTNAME(FailImageStatement)() {
7589
Fortran::runtime::NotifyOtherImagesOfFailImageStatement();
7690
CloseAllExternalUnits("FAIL IMAGE statement");

flang/runtime/stop.h

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ NORETURN void RTNAME(StopStatement)(int code DEFAULT_VALUE(EXIT_SUCCESS),
2020
bool isErrorStop DEFAULT_VALUE(false), bool quiet DEFAULT_VALUE(false));
2121
NORETURN void RTNAME(StopStatementText)(const char *,
2222
bool isErrorStop DEFAULT_VALUE(false), bool quiet DEFAULT_VALUE(false));
23+
void RTNAME(PauseStatement)(NO_ARGUMENTS);
2324
NORETURN void RTNAME(FailImageStatement)(NO_ARGUMENTS);
2425
NORETURN void RTNAME(ProgramEndStatement)(NO_ARGUMENTS);
2526

0 commit comments

Comments
 (0)