@@ -129,26 +129,27 @@ void ExternalFileUnit::OpenUnit(std::optional<OpenStatus> status,
129
129
Open (status.value_or (OpenStatus::Unknown), action, position, handler);
130
130
auto totalBytes{knownSize ()};
131
131
if (access == Access::Direct) {
132
- if (!isFixedRecordLength || !recordLength ) {
132
+ if (!openRecl ) {
133
133
handler.SignalError (IostatOpenBadRecl,
134
134
" OPEN(UNIT=%d,ACCESS='DIRECT'): record length is not known" ,
135
135
unitNumber ());
136
- } else if (*recordLength <= 0 ) {
136
+ } else if (*openRecl <= 0 ) {
137
137
handler.SignalError (IostatOpenBadRecl,
138
138
" OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is invalid" ,
139
- unitNumber (), static_cast <std::intmax_t >(*recordLength ));
140
- } else if (totalBytes && (*totalBytes % *recordLength != 0 )) {
139
+ unitNumber (), static_cast <std::intmax_t >(*openRecl ));
140
+ } else if (totalBytes && (*totalBytes % *openRecl != 0 )) {
141
141
handler.SignalError (IostatOpenBadAppend,
142
142
" OPEN(UNIT=%d,ACCESS='DIRECT',RECL=%jd): record length is not an "
143
143
" even divisor of the file size %jd" ,
144
- unitNumber (), static_cast <std::intmax_t >(*recordLength ),
144
+ unitNumber (), static_cast <std::intmax_t >(*openRecl ),
145
145
static_cast <std::intmax_t >(*totalBytes));
146
146
}
147
+ recordLength = openRecl;
147
148
}
148
149
endfileRecordNumber.reset ();
149
150
currentRecordNumber = 1 ;
150
- if (totalBytes && recordLength && *recordLength ) {
151
- endfileRecordNumber = 1 + (*totalBytes / *recordLength );
151
+ if (totalBytes && access == Access::Direct && openRecl. value_or ( 0 ) > 0 ) {
152
+ endfileRecordNumber = 1 + (*totalBytes / *openRecl );
152
153
}
153
154
if (position == Position::Append) {
154
155
if (!endfileRecordNumber) {
@@ -276,21 +277,27 @@ bool ExternalFileUnit::Emit(const char *data, std::size_t bytes,
276
277
std::size_t elementBytes, IoErrorHandler &handler) {
277
278
auto furthestAfter{std::max (furthestPositionInRecord,
278
279
positionInRecord + static_cast <std::int64_t >(bytes))};
279
- if (recordLength) {
280
- // It is possible for recordLength to have a value now for a
281
- // variable-length output record if the previous operation
282
- // was a BACKSPACE or non advancing input statement.
283
- if (!isFixedRecordLength) {
284
- recordLength.reset ();
285
- beganReadingRecord_ = false ;
286
- } else if (furthestAfter > *recordLength) {
280
+ if (openRecl) {
281
+ // Check for fixed-length record overrun, but allow for
282
+ // the unformatted sequential record header & footer, if any.
283
+ int extra{access == Access::Sequential && isUnformatted && *isUnformatted
284
+ ? static_cast <int >(sizeof (std::uint32_t ))
285
+ : 0 };
286
+ if (furthestAfter > 2 * extra + *openRecl) {
287
287
handler.SignalError (IostatRecordWriteOverrun,
288
288
" Attempt to write %zd bytes to position %jd in a fixed-size record "
289
289
" of %jd bytes" ,
290
- bytes, static_cast <std::intmax_t >(positionInRecord),
291
- static_cast <std::intmax_t >(*recordLength));
290
+ bytes,
291
+ static_cast <std::intmax_t >(positionInRecord - extra /* header*/ ),
292
+ static_cast <std::intmax_t >(*openRecl));
292
293
return false ;
293
294
}
295
+ } else if (recordLength) {
296
+ // It is possible for recordLength to have a value now for a
297
+ // variable-length output record if the previous operation
298
+ // was a BACKSPACE or non advancing input statement.
299
+ recordLength.reset ();
300
+ beganReadingRecord_ = false ;
294
301
}
295
302
WriteFrame (frameOffsetInFile_, recordOffsetInFrame_ + furthestAfter, handler);
296
303
if (positionInRecord > furthestPositionInRecord) {
@@ -340,7 +347,9 @@ std::size_t ExternalFileUnit::GetNextInputBytes(
340
347
const char *&p, IoErrorHandler &handler) {
341
348
RUNTIME_CHECK (handler, direction_ == Direction::Input);
342
349
p = FrameNextInput (handler, 1 );
343
- return p ? recordLength.value_or (positionInRecord + 1 ) - positionInRecord : 0 ;
350
+ return p ? EffectiveRecordLength ().value_or (positionInRecord + 1 ) -
351
+ positionInRecord
352
+ : 0 ;
344
353
}
345
354
346
355
std::optional<char32_t > ExternalFileUnit::GetCurrentChar (
@@ -400,17 +409,20 @@ bool ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
400
409
RUNTIME_CHECK (handler, direction_ == Direction::Input);
401
410
if (!beganReadingRecord_) {
402
411
beganReadingRecord_ = true ;
403
- if (access == Access::Sequential) {
412
+ if (access == Access::Direct) {
413
+ RUNTIME_CHECK (handler, openRecl);
414
+ auto need{static_cast <std::size_t >(recordOffsetInFrame_ + *openRecl)};
415
+ auto got{ReadFrame (frameOffsetInFile_, need, handler)};
416
+ if (got >= need) {
417
+ recordLength = openRecl;
418
+ } else {
419
+ recordLength.reset ();
420
+ handler.SignalEnd ();
421
+ }
422
+ } else if (access == Access::Sequential) {
423
+ recordLength.reset ();
404
424
if (endfileRecordNumber && currentRecordNumber >= *endfileRecordNumber) {
405
425
handler.SignalEnd ();
406
- } else if (isFixedRecordLength && access == Access::Direct) {
407
- RUNTIME_CHECK (handler, recordLength.has_value ());
408
- auto need{
409
- static_cast <std::size_t >(recordOffsetInFrame_ + *recordLength)};
410
- auto got{ReadFrame (frameOffsetInFile_, need, handler)};
411
- if (got < need) {
412
- handler.SignalEnd ();
413
- }
414
426
} else {
415
427
RUNTIME_CHECK (handler, isUnformatted.has_value ());
416
428
if (isUnformatted.value_or (false )) {
@@ -422,8 +434,7 @@ bool ExternalFileUnit::BeginReadingRecord(IoErrorHandler &handler) {
422
434
}
423
435
}
424
436
RUNTIME_CHECK (handler,
425
- access != Access::Sequential || recordLength.has_value () ||
426
- handler.InError ());
437
+ recordLength.has_value () || !IsRecordFile (access) || handler.InError ());
427
438
return !handler.InError ();
428
439
}
429
440
@@ -435,7 +446,7 @@ void ExternalFileUnit::FinishReadingRecord(IoErrorHandler &handler) {
435
446
} else if (access == Access::Sequential) {
436
447
RUNTIME_CHECK (handler, recordLength.has_value ());
437
448
recordOffsetInFrame_ += *recordLength;
438
- if (isFixedRecordLength && access == Access::Direct) {
449
+ if (openRecl && access == Access::Direct) {
439
450
frameOffsetInFile_ += recordOffsetInFrame_;
440
451
recordOffsetInFrame_ = 0 ;
441
452
} else {
@@ -472,17 +483,15 @@ bool ExternalFileUnit::AdvanceRecord(IoErrorHandler &handler) {
472
483
} else { // Direction::Output
473
484
bool ok{true };
474
485
RUNTIME_CHECK (handler, isUnformatted.has_value ());
475
- if (isFixedRecordLength && recordLength &&
476
- furthestPositionInRecord < *recordLength) {
486
+ if (openRecl && furthestPositionInRecord < *openRecl) {
477
487
// Pad remainder of fixed length record
478
- WriteFrame (
479
- frameOffsetInFile_, recordOffsetInFrame_ + *recordLength, handler);
488
+ WriteFrame (frameOffsetInFile_, recordOffsetInFrame_ + *openRecl, handler);
480
489
std::memset (Frame () + recordOffsetInFrame_ + furthestPositionInRecord,
481
490
isUnformatted.value_or (false ) ? 0 : ' ' ,
482
- *recordLength - furthestPositionInRecord);
483
- furthestPositionInRecord = *recordLength ;
491
+ *openRecl - furthestPositionInRecord);
492
+ furthestPositionInRecord = *openRecl ;
484
493
}
485
- if (!(isFixedRecordLength && access == Access::Direct)) {
494
+ if (!(openRecl && access == Access::Direct)) {
486
495
positionInRecord = furthestPositionInRecord;
487
496
if (isUnformatted.value_or (false )) {
488
497
// Append the length of a sequential unformatted variable-length record
@@ -527,7 +536,7 @@ void ExternalFileUnit::BackspaceRecord(IoErrorHandler &handler) {
527
536
DoImpliedEndfile (handler);
528
537
if (frameOffsetInFile_ + recordOffsetInFrame_ > 0 ) {
529
538
--currentRecordNumber;
530
- if (isFixedRecordLength && access == Access::Direct) {
539
+ if (openRecl && access == Access::Direct) {
531
540
BackspaceFixedRecord (handler);
532
541
} else {
533
542
RUNTIME_CHECK (handler, isUnformatted.has_value ());
@@ -670,11 +679,11 @@ void ExternalFileUnit::BeginSequentialVariableFormattedInputRecord(
670
679
}
671
680
672
681
void ExternalFileUnit::BackspaceFixedRecord (IoErrorHandler &handler) {
673
- RUNTIME_CHECK (handler, recordLength .has_value ());
674
- if (frameOffsetInFile_ < *recordLength ) {
682
+ RUNTIME_CHECK (handler, openRecl .has_value ());
683
+ if (frameOffsetInFile_ < *openRecl ) {
675
684
handler.SignalError (IostatBackspaceAtFirstRecord);
676
685
} else {
677
- frameOffsetInFile_ -= *recordLength ;
686
+ frameOffsetInFile_ -= *openRecl ;
678
687
}
679
688
}
680
689
0 commit comments