@@ -511,7 +511,7 @@ void ExternalFileUnit::EndIoStatement() {
511511void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord (
512512 IoErrorHandler &handler) {
513513 RUNTIME_CHECK (handler, access == Access::Sequential);
514- std::int32_t header{0 }, footer{0 };
514+ std::uint32_t header{0 }, footer{0 };
515515 std::size_t need{recordOffsetInFrame_ + sizeof header};
516516 std::size_t got{ReadFrame (frameOffsetInFile_, need, handler)};
517517 // Try to emit informative errors to help debug corrupted files.
@@ -528,17 +528,41 @@ void ExternalFileUnit::BeginSequentialVariableUnformattedInputRecord(
528528 recordLength = sizeof header + header; // does not include footer
529529 need = recordOffsetInFrame_ + *recordLength + sizeof footer;
530530 got = ReadFrame (frameOffsetInFile_, need, handler);
531- if (got < need) {
531+ if (got >= need) {
532+ footer = ReadHeaderOrFooter (recordOffsetInFrame_ + *recordLength);
533+ }
534+ if (frameOffsetInFile_ == 0 && recordOffsetInFrame_ == 0 &&
535+ (got < need || footer != header)) {
536+ // Maybe an omitted or incorrect byte swap flag setting?
537+ // Try it the other way, since this is the first record.
538+ // (N.B. Won't work on files starting with empty records, but there's
539+ // no good way to know later if all preceding records were empty.)
540+ swapEndianness_ = !swapEndianness_;
541+ std::uint32_t header2{ReadHeaderOrFooter (0 )};
542+ std::size_t recordLength2{sizeof header2 + header2};
543+ std::size_t need2{recordLength2 + sizeof footer};
544+ std::size_t got2{ReadFrame (0 , need2, handler)};
545+ if (got2 >= need2) {
546+ std::uint32_t footer2{ReadHeaderOrFooter (recordLength2)};
547+ if (footer2 == header2) {
548+ error = " Unformatted variable-length sequential file input "
549+ " failed on the first record, probably due to a need "
550+ " for byte order data conversion; consider adding "
551+ " CONVERT='SWAP' to the OPEN statement or adding "
552+ " FORT_CONVERT=SWAP to the execution environment" ;
553+ }
554+ }
555+ swapEndianness_ = !swapEndianness_;
556+ }
557+ if (error) {
558+ } else if (got < need) {
532559 error = " Unformatted variable-length sequential file input failed at "
533560 " record #%jd (file offset %jd): hit EOF reading record with "
534561 " length %jd bytes" ;
535- } else {
536- footer = ReadHeaderOrFooter (recordOffsetInFrame_ + *recordLength);
537- if (footer != header) {
538- error = " Unformatted variable-length sequential file input failed at "
539- " record #%jd (file offset %jd): record header has length %jd "
540- " that does not match record footer (%jd)" ;
541- }
562+ } else if (footer != header) {
563+ error = " Unformatted variable-length sequential file input failed at "
564+ " record #%jd (file offset %jd): record header has length %jd "
565+ " that does not match record footer (%jd)" ;
542566 }
543567 }
544568 if (error) {
@@ -590,7 +614,7 @@ void ExternalFileUnit::BackspaceFixedRecord(IoErrorHandler &handler) {
590614
591615void ExternalFileUnit::BackspaceVariableUnformattedRecord (
592616 IoErrorHandler &handler) {
593- std::int32_t header{0 };
617+ std::uint32_t header{0 };
594618 auto headerBytes{static_cast <std::int64_t >(sizeof header)};
595619 frameOffsetInFile_ += recordOffsetInFrame_;
596620 recordOffsetInFrame_ = 0 ;
@@ -775,8 +799,8 @@ void ExternalFileUnit::PopChildIo(ChildIo &child) {
775799 child_.reset (child.AcquirePrevious ().release ()); // deletes top child
776800}
777801
778- std::int32_t ExternalFileUnit::ReadHeaderOrFooter (std::int64_t frameOffset) {
779- std::int32_t word;
802+ std::uint32_t ExternalFileUnit::ReadHeaderOrFooter (std::int64_t frameOffset) {
803+ std::uint32_t word;
780804 char *wordPtr{reinterpret_cast <char *>(&word)};
781805 std::memcpy (wordPtr, Frame () + frameOffset, sizeof word);
782806 if (swapEndianness_) {
0 commit comments