@@ -646,6 +646,9 @@ bool IONAME(SetAccess)(Cookie cookie, const char *keyword, std::size_t length) {
646
646
if (!open) {
647
647
io.GetIoErrorHandler ().Crash (
648
648
" 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" );
649
652
}
650
653
static const char *keywords[]{
651
654
" SEQUENTIAL" , " DIRECT" , " STREAM" , " APPEND" , nullptr };
@@ -675,6 +678,9 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) {
675
678
if (!open) {
676
679
io.GetIoErrorHandler ().Crash (
677
680
" 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" );
678
684
}
679
685
std::optional<Action> action;
680
686
static const char *keywords[]{" READ" , " WRITE" , " READWRITE" , nullptr };
@@ -711,6 +717,9 @@ bool IONAME(SetAsynchronous)(
711
717
if (!open) {
712
718
io.GetIoErrorHandler ().Crash (
713
719
" 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" );
714
723
}
715
724
static const char *keywords[]{" YES" , " NO" , nullptr };
716
725
switch (IdentifyValue (keyword, length, keywords)) {
@@ -734,6 +743,9 @@ bool IONAME(SetCarriagecontrol)(
734
743
if (!open) {
735
744
io.GetIoErrorHandler ().Crash (
736
745
" 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" );
737
749
}
738
750
static const char *keywords[]{" LIST" , " FORTRAN" , " NONE" , nullptr };
739
751
switch (IdentifyValue (keyword, length, keywords)) {
@@ -759,6 +771,9 @@ bool IONAME(SetConvert)(
759
771
if (!open) {
760
772
io.GetIoErrorHandler ().Crash (
761
773
" 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" );
762
777
}
763
778
if (auto convert{GetConvertFromString (keyword, length)}) {
764
779
open->set_convert (*convert);
@@ -777,6 +792,9 @@ bool IONAME(SetEncoding)(
777
792
if (!open) {
778
793
io.GetIoErrorHandler ().Crash (
779
794
" 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" );
780
798
}
781
799
bool isUTF8{false };
782
800
static const char *keywords[]{" UTF-8" , " DEFAULT" , nullptr };
@@ -806,6 +824,9 @@ bool IONAME(SetForm)(Cookie cookie, const char *keyword, std::size_t length) {
806
824
if (!open) {
807
825
io.GetIoErrorHandler ().Crash (
808
826
" 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" );
809
830
}
810
831
static const char *keywords[]{" FORMATTED" , " UNFORMATTED" , nullptr };
811
832
switch (IdentifyValue (keyword, length, keywords)) {
@@ -829,6 +850,9 @@ bool IONAME(SetPosition)(
829
850
if (!open) {
830
851
io.GetIoErrorHandler ().Crash (
831
852
" 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" );
832
856
}
833
857
static const char *positions[]{" ASIS" , " REWIND" , " APPEND" , nullptr };
834
858
switch (IdentifyValue (keyword, length, positions)) {
@@ -854,6 +878,9 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
854
878
if (!open) {
855
879
io.GetIoErrorHandler ().Crash (
856
880
" 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" );
857
884
}
858
885
if (n <= 0 ) {
859
886
io.GetIoErrorHandler ().SignalError (" RECL= must be greater than zero" );
@@ -871,6 +898,10 @@ bool IONAME(SetRecl)(Cookie cookie, std::size_t n) {
871
898
bool IONAME (SetStatus)(Cookie cookie, const char *keyword, std::size_t length) {
872
899
IoStatementState &io{*cookie};
873
900
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
+ }
874
905
static const char *statuses[]{
875
906
" OLD" , " NEW" , " SCRATCH" , " REPLACE" , " UNKNOWN" , nullptr };
876
907
switch (IdentifyValue (keyword, length, statuses)) {
@@ -920,6 +951,10 @@ bool IONAME(SetStatus)(Cookie cookie, const char *keyword, std::size_t length) {
920
951
bool IONAME (SetFile)(Cookie cookie, const char *path, std::size_t chars) {
921
952
IoStatementState &io{*cookie};
922
953
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
+ }
923
958
open->set_path (path, chars);
924
959
return true ;
925
960
}
@@ -934,6 +969,12 @@ bool IONAME(GetNewUnit)(Cookie cookie, int &unit, int kind) {
934
969
if (!open) {
935
970
io.GetIoErrorHandler ().Crash (
936
971
" 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 ;
937
978
}
938
979
std::int64_t result{open->unit ().unitNumber ()};
939
980
if (!SetInteger (unit, kind, result)) {
@@ -971,16 +1012,17 @@ bool IONAME(OutputUnformattedBlock)(Cookie cookie, const char *x,
971
1012
bool IONAME (InputUnformattedBlock)(
972
1013
Cookie cookie, char *x, std::size_t length, std::size_t elementBytes) {
973
1014
IoStatementState &io{*cookie};
1015
+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
974
1016
io.BeginReadingRecord ();
975
- if (io. GetIoErrorHandler () .InError ()) {
1017
+ if (handler .InError ()) {
976
1018
return false ;
977
1019
}
978
1020
if (auto *unf{
979
1021
io.get_if <ExternalUnformattedIoStatementState<Direction::Input>>()}) {
980
1022
return unf->Receive (x, length, elementBytes);
981
1023
}
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 " );
984
1026
return false ;
985
1027
}
986
1028
@@ -1157,27 +1199,39 @@ bool IONAME(InputLogical)(Cookie cookie, bool &truth) {
1157
1199
1158
1200
std::size_t IONAME (GetSize)(Cookie cookie) {
1159
1201
IoStatementState &io{*cookie};
1202
+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
1203
+ if (!handler.InError ()) {
1204
+ io.CompleteOperation ();
1205
+ }
1160
1206
if (const auto *formatted{
1161
1207
io.get_if <FormattedIoStatementState<Direction::Input>>()}) {
1162
1208
return formatted->GetEditDescriptorChars ();
1163
1209
}
1164
- io. GetIoErrorHandler () .Crash (
1210
+ handler .Crash (
1165
1211
" GetIoSize() called for an I/O statement that is not a formatted READ()" );
1166
1212
return 0 ;
1167
1213
}
1168
1214
1169
1215
std::size_t IONAME (GetIoLength)(Cookie cookie) {
1170
1216
IoStatementState &io{*cookie};
1217
+ IoErrorHandler &handler{io.GetIoErrorHandler ()};
1218
+ if (!handler.InError ()) {
1219
+ io.CompleteOperation ();
1220
+ }
1171
1221
if (const auto *inq{io.get_if <InquireIOLengthState>()}) {
1172
1222
return inq->bytes ();
1173
1223
}
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=)" );
1176
1226
return 0 ;
1177
1227
}
1178
1228
1179
1229
void 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
+ }
1181
1235
if (handler.InError ()) { // leave "msg" alone when no error
1182
1236
handler.GetIoMsg (msg, length);
1183
1237
}
0 commit comments