@@ -121,10 +121,12 @@ Cookie BeginExternalListIO(
121
121
terminator.Crash (" List-directed I/O attempted on unformatted file" );
122
122
return nullptr ;
123
123
}
124
+ IoErrorHandler handler{terminator};
125
+ unit.SetDirection (DIR, handler);
124
126
IoStatementState &io{unit.BeginIoStatement <ExternalListIoStatementState<DIR>>(
125
127
unit, sourceFile, sourceLine)};
126
128
if constexpr (DIR == Direction::Input) {
127
- io. AdvanceRecord ( );
129
+ unit. BeginReadingRecord (handler );
128
130
}
129
131
return &io;
130
132
}
@@ -154,11 +156,13 @@ Cookie BeginExternalFormattedIO(const char *format, std::size_t formatLength,
154
156
terminator.Crash (" Formatted I/O attempted on unformatted file" );
155
157
return nullptr ;
156
158
}
159
+ IoErrorHandler handler{terminator};
160
+ unit.SetDirection (DIR, handler);
157
161
IoStatementState &io{
158
162
unit.BeginIoStatement <ExternalFormattedIoStatementState<DIR>>(
159
163
unit, format, formatLength, sourceFile, sourceLine)};
160
164
if constexpr (DIR == Direction::Input) {
161
- io. AdvanceRecord ( );
165
+ unit. BeginReadingRecord (handler );
162
166
}
163
167
return &io;
164
168
}
@@ -181,17 +185,19 @@ template <Direction DIR>
181
185
Cookie BeginUnformattedIO (
182
186
ExternalUnit unitNumber, const char *sourceFile, int sourceLine) {
183
187
Terminator terminator{sourceFile, sourceLine};
184
- ExternalFileUnit &file {
188
+ ExternalFileUnit &unit {
185
189
ExternalFileUnit::LookUpOrCrash (unitNumber, terminator)};
186
- if (!file .isUnformatted ) {
190
+ if (!unit .isUnformatted ) {
187
191
terminator.Crash (" Unformatted output attempted on formatted file" );
188
192
}
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);
191
197
if constexpr (DIR == Direction::Input) {
192
- io. AdvanceRecord ( );
198
+ unit. BeginReadingRecord (handler );
193
199
} else {
194
- if (file .access == Access::Sequential && !file. recordLength . has_value () ) {
200
+ if (unit .access == Access::Sequential && !unit. isFixedRecordLength ) {
195
201
// Create space for (sub)record header to be completed by
196
202
// UnformattedIoStatementState<Direction::Output>::EndIoStatement()
197
203
io.Emit (" \0\0\0\0 " , 4 ); // placeholder for record length header
@@ -225,8 +231,10 @@ Cookie IONAME(BeginOpenUnit)( // OPEN(without NEWUNIT=)
225
231
Cookie IONAME (BeginOpenNewUnit)( // OPEN(NEWUNIT=j)
226
232
const char *sourceFile, int sourceLine) {
227
233
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);
230
238
}
231
239
232
240
Cookie IONAME (BeginClose)(
@@ -243,6 +251,42 @@ Cookie IONAME(BeginClose)(
243
251
}
244
252
}
245
253
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
+
246
290
// Control list items
247
291
248
292
void IONAME (EnableHandlers)(Cookie cookie, bool hasIoStat, bool hasErr,
@@ -388,7 +432,7 @@ bool IONAME(SetRec)(Cookie cookie, std::int64_t rec) {
388
432
" REC= may not appear unless ACCESS='DIRECT'" );
389
433
return false ;
390
434
}
391
- if (!connection.recordLength ) {
435
+ if (!connection.isFixedRecordLength || !connection. recordLength ) {
392
436
io.GetIoErrorHandler ().SignalError (" RECL= was not specified" );
393
437
return false ;
394
438
}
@@ -640,10 +684,11 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
640
684
if (n <= 0 ) {
641
685
io.GetIoErrorHandler ().SignalError (" RECL= must be greater than zero" );
642
686
}
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)) {
645
689
open ->SignalError (" RECL= may not be changed for an open unit" );
646
690
}
691
+ open ->unit ().isFixedRecordLength = true ;
647
692
open ->unit ().recordLength = n;
648
693
return true ;
649
694
}
@@ -754,7 +799,17 @@ bool IONAME(OutputUnformattedBlock)(
754
799
if (auto *unf{io.get_if <UnformattedIoStatementState<Direction::Output>>()}) {
755
800
return unf->Emit (x, length);
756
801
}
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 "
758
813
" statement that is not unformatted output" );
759
814
return false ;
760
815
}
0 commit comments