@@ -646,6 +646,9 @@ bool IONAME(SetAccess)(Cookie cookie, const char *keyword, std::size_t length) {
646646 if (!open) {
647647 io.GetIoErrorHandler ().Crash (
648648 " SetAccess() called when not in an OPEN statement" );
649+ } else if (open->completedOperation ()) {
650+ io.GetIoErrorHandler ().Crash (
651+ " SetAccess() called after GetNewUnit() for an OPEN statement" );
649652 }
650653 static const char *keywords[]{
651654 " SEQUENTIAL" , " DIRECT" , " STREAM" , " APPEND" , nullptr };
@@ -675,6 +678,9 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) {
675678 if (!open) {
676679 io.GetIoErrorHandler ().Crash (
677680 " SetAction() called when not in an OPEN statement" );
681+ } else if (open->completedOperation ()) {
682+ io.GetIoErrorHandler ().Crash (
683+ " SetAction() called after GetNewUnit() for an OPEN statement" );
678684 }
679685 std::optional<Action> action;
680686 static const char *keywords[]{" READ" , " WRITE" , " READWRITE" , nullptr };
@@ -711,6 +717,9 @@ bool IONAME(SetAsynchronous)(
711717 if (!open) {
712718 io.GetIoErrorHandler ().Crash (
713719 " SetAsynchronous() called when not in an OPEN statement" );
720+ } else if (open->completedOperation ()) {
721+ io.GetIoErrorHandler ().Crash (
722+ " SetAsynchronous() called after GetNewUnit() for an OPEN statement" );
714723 }
715724 static const char *keywords[]{" YES" , " NO" , nullptr };
716725 switch (IdentifyValue (keyword, length, keywords)) {
@@ -734,6 +743,9 @@ bool IONAME(SetCarriagecontrol)(
734743 if (!open) {
735744 io.GetIoErrorHandler ().Crash (
736745 " SetCarriageControl() called when not in an OPEN statement" );
746+ } else if (open->completedOperation ()) {
747+ io.GetIoErrorHandler ().Crash (
748+ " SetCarriageControl() called after GetNewUnit() for an OPEN statement" );
737749 }
738750 static const char *keywords[]{" LIST" , " FORTRAN" , " NONE" , nullptr };
739751 switch (IdentifyValue (keyword, length, keywords)) {
@@ -759,6 +771,9 @@ bool IONAME(SetConvert)(
759771 if (!open) {
760772 io.GetIoErrorHandler ().Crash (
761773 " SetConvert() called when not in an OPEN statement" );
774+ } else if (open->completedOperation ()) {
775+ io.GetIoErrorHandler ().Crash (
776+ " SetConvert() called after GetNewUnit() for an OPEN statement" );
762777 }
763778 if (auto convert{GetConvertFromString (keyword, length)}) {
764779 open->set_convert (*convert);
@@ -777,6 +792,9 @@ bool IONAME(SetEncoding)(
777792 if (!open) {
778793 io.GetIoErrorHandler ().Crash (
779794 " SetEncoding() called when not in an OPEN statement" );
795+ } else if (open->completedOperation ()) {
796+ io.GetIoErrorHandler ().Crash (
797+ " SetEncoding() called after GetNewUnit() for an OPEN statement" );
780798 }
781799 bool isUTF8{false };
782800 static const char *keywords[]{" UTF-8" , " DEFAULT" , nullptr };
@@ -806,6 +824,9 @@ bool IONAME(SetForm)(Cookie cookie, const char *keyword, std::size_t length) {
806824 if (!open) {
807825 io.GetIoErrorHandler ().Crash (
808826 " SetForm() called when not in an OPEN statement" );
827+ } else if (open->completedOperation ()) {
828+ io.GetIoErrorHandler ().Crash (
829+ " SetForm() called after GetNewUnit() for an OPEN statement" );
809830 }
810831 static const char *keywords[]{" FORMATTED" , " UNFORMATTED" , nullptr };
811832 switch (IdentifyValue (keyword, length, keywords)) {
@@ -829,6 +850,9 @@ bool IONAME(SetPosition)(
829850 if (!open) {
830851 io.GetIoErrorHandler ().Crash (
831852 " SetPosition() called when not in an OPEN statement" );
853+ } else if (open->completedOperation ()) {
854+ io.GetIoErrorHandler ().Crash (
855+ " SetPosition() called after GetNewUnit() for an OPEN statement" );
832856 }
833857 static const char *positions[]{" ASIS" , " REWIND" , " APPEND" , nullptr };
834858 switch (IdentifyValue (keyword, length, positions)) {
@@ -854,6 +878,9 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
854878 if (!open) {
855879 io.GetIoErrorHandler ().Crash (
856880 " SetRecl() called when not in an OPEN statement" );
881+ } else if (open->completedOperation ()) {
882+ io.GetIoErrorHandler ().Crash (
883+ " SetRecl() called after GetNewUnit() for an OPEN statement" );
857884 }
858885 if (n <= 0 ) {
859886 io.GetIoErrorHandler ().SignalError (" RECL= must be greater than zero" );
@@ -871,6 +898,10 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
871898bool IONAME (SetStatus)(Cookie cookie, const char *keyword, std::size_t length) {
872899 IoStatementState &io{*cookie};
873900 if (auto *open{io.get_if <OpenStatementState>()}) {
901+ if (open->completedOperation ()) {
902+ io.GetIoErrorHandler ().Crash (
903+ " SetStatus() called after GetNewUnit() for an OPEN statement" );
904+ }
874905 static const char *statuses[]{
875906 " OLD" , " NEW" , " SCRATCH" , " REPLACE" , " UNKNOWN" , nullptr };
876907 switch (IdentifyValue (keyword, length, statuses)) {
@@ -920,6 +951,10 @@ bool IONAME(SetStatus)(Cookie cookie, const char *keyword, std::size_t length) {
920951bool IONAME (SetFile)(Cookie cookie, const char *path, std::size_t chars) {
921952 IoStatementState &io{*cookie};
922953 if (auto *open{io.get_if <OpenStatementState>()}) {
954+ if (open->completedOperation ()) {
955+ io.GetIoErrorHandler ().Crash (
956+ " SetFile() called after GetNewUnit() for an OPEN statement" );
957+ }
923958 open->set_path (path, chars);
924959 return true ;
925960 }
@@ -934,6 +969,12 @@ bool IONAME(GetNewUnit)(Cookie cookie, int &unit, int kind) {
934969 if (!open) {
935970 io.GetIoErrorHandler ().Crash (
936971 " GetNewUnit() called when not in an OPEN statement" );
972+ } else if (!open->InError ()) {
973+ open->CompleteOperation ();
974+ }
975+ if (open->InError ()) {
976+ // A failed OPEN(NEWUNIT=n) does not modify 'n'
977+ return false ;
937978 }
938979 std::int64_t result{open->unit ().unitNumber ()};
939980 if (!SetInteger (unit, kind, result)) {
@@ -971,16 +1012,17 @@ bool IONAME(OutputUnformattedBlock)(Cookie cookie, const char *x,
9711012bool IONAME (InputUnformattedBlock)(
9721013 Cookie cookie, char *x, std::size_t length, std::size_t elementBytes) {
9731014 IoStatementState &io{*cookie};
1015+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
9741016 io.BeginReadingRecord ();
975- if (io. GetIoErrorHandler () .InError ()) {
1017+ if (handler .InError ()) {
9761018 return false ;
9771019 }
9781020 if (auto *unf{
9791021 io.get_if <ExternalUnformattedIoStatementState<Direction::Input>>()}) {
9801022 return unf->Receive (x, length, elementBytes);
9811023 }
982- io. GetIoErrorHandler (). Crash (" InputUnformattedBlock() called for an I/O "
983- " statement that is not unformatted output " );
1024+ handler. Crash (" InputUnformattedBlock() called for an I/O statement that is "
1025+ " not unformatted input " );
9841026 return false ;
9851027}
9861028
@@ -1157,27 +1199,39 @@ bool IONAME(InputLogical)(Cookie cookie, bool &truth) {
11571199
11581200std::size_t IONAME (GetSize)(Cookie cookie) {
11591201 IoStatementState &io{*cookie};
1202+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
1203+ if (!handler.InError ()) {
1204+ io.CompleteOperation ();
1205+ }
11601206 if (const auto *formatted{
11611207 io.get_if <FormattedIoStatementState<Direction::Input>>()}) {
11621208 return formatted->GetEditDescriptorChars ();
11631209 }
1164- io. GetIoErrorHandler () .Crash (
1210+ handler .Crash (
11651211 " GetIoSize() called for an I/O statement that is not a formatted READ()" );
11661212 return 0 ;
11671213}
11681214
11691215std::size_t IONAME (GetIoLength)(Cookie cookie) {
11701216 IoStatementState &io{*cookie};
1217+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
1218+ if (!handler.InError ()) {
1219+ io.CompleteOperation ();
1220+ }
11711221 if (const auto *inq{io.get_if <InquireIOLengthState>()}) {
11721222 return inq->bytes ();
11731223 }
1174- io. GetIoErrorHandler (). Crash (" GetIoLength() called for an I/O statement that "
1175- " is not INQUIRE(IOLENGTH=)" );
1224+ handler. Crash (" GetIoLength() called for an I/O statement that is not "
1225+ " INQUIRE(IOLENGTH=)" );
11761226 return 0 ;
11771227}
11781228
11791229void IONAME (GetIoMsg)(Cookie cookie, char *msg, std::size_t length) {
1180- IoErrorHandler &handler{cookie->GetIoErrorHandler ()};
1230+ IoStatementState &io{*cookie};
1231+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
1232+ if (!handler.InError ()) {
1233+ io.CompleteOperation ();
1234+ }
11811235 if (handler.InError ()) { // leave "msg" alone when no error
11821236 handler.GetIoMsg (msg, length);
11831237 }
0 commit comments