@@ -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>
181185Cookie 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=)
225231Cookie 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
232240Cookie 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
248292void 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}
0 commit comments