@@ -44,8 +44,7 @@ bool IODEF(OutputNamelist)(Cookie cookie, const NamelistGroup &group) {
44
44
if ((connection.NeedAdvance (prefixLen) &&
45
45
!(io.AdvanceRecord () && EmitAscii (io, " " , 1 ))) ||
46
46
!EmitAscii (io, prefix, prefixLen) ||
47
- (connection.NeedAdvance (
48
- Fortran::runtime::strlen (str) + (suffix != ' ' )) &&
47
+ (connection.NeedAdvance (runtime::strlen (str) + (suffix != ' ' )) &&
49
48
!(io.AdvanceRecord () && EmitAscii (io, " " , 1 )))) {
50
49
return false ;
51
50
}
@@ -102,8 +101,8 @@ static constexpr RT_API_ATTRS char NormalizeIdChar(char32_t ch) {
102
101
return static_cast <char >(ch >= ' A' && ch <= ' Z' ? ch - ' A' + ' a' : ch);
103
102
}
104
103
105
- static RT_API_ATTRS bool GetLowerCaseName (
106
- IoStatementState &io, char buffer[], std::size_t maxLength) {
104
+ static RT_API_ATTRS bool GetLowerCaseName (IoStatementState &io, char buffer[],
105
+ std::size_t maxLength, bool crashIfTooLong = true ) {
107
106
std::size_t byteLength{0 };
108
107
if (auto ch{io.GetNextNonBlank (byteLength)}) {
109
108
if (IsLegalIdStart (*ch)) {
@@ -117,8 +116,10 @@ static RT_API_ATTRS bool GetLowerCaseName(
117
116
if (j <= maxLength) {
118
117
return true ;
119
118
}
120
- io.GetIoErrorHandler ().SignalError (
121
- " Identifier '%s...' in NAMELIST input group is too long" , buffer);
119
+ if (crashIfTooLong) {
120
+ io.GetIoErrorHandler ().SignalError (
121
+ " Identifier '%s...' in NAMELIST input group is too long" , buffer);
122
+ }
122
123
}
123
124
}
124
125
return false ;
@@ -383,9 +384,8 @@ static RT_API_ATTRS bool HandleComponent(IoStatementState &io, Descriptor &desc,
383
384
const DescriptorAddendum *addendum{source.Addendum ()};
384
385
if (const typeInfo::DerivedType *
385
386
type{addendum ? addendum->derivedType () : nullptr }) {
386
- if (const typeInfo::Component *
387
- comp{type->FindDataComponent (
388
- compName, Fortran::runtime::strlen (compName))}) {
387
+ if (const typeInfo::Component *comp{
388
+ type->FindDataComponent (compName, runtime::strlen (compName))}) {
389
389
bool createdDesc{false };
390
390
if (comp->rank () > 0 && source.rank () > 0 ) {
391
391
// If base and component are both arrays, the component name
@@ -510,7 +510,7 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
510
510
handler.SignalError (" NAMELIST input group has no name" );
511
511
return false ;
512
512
}
513
- if (Fortran:: runtime::strcmp (group.groupName , name) == 0 ) {
513
+ if (runtime::strcmp (group.groupName , name) == 0 ) {
514
514
break ; // found it
515
515
}
516
516
SkipNamelistGroup (io);
@@ -529,7 +529,7 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
529
529
}
530
530
std::size_t itemIndex{0 };
531
531
for (; itemIndex < group.items ; ++itemIndex) {
532
- if (Fortran:: runtime::strcmp (name, group.item [itemIndex].name ) == 0 ) {
532
+ if (runtime::strcmp (name, group.item [itemIndex].name ) == 0 ) {
533
533
break ;
534
534
}
535
535
}
@@ -604,13 +604,14 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
604
604
if (const auto *addendum{useDescriptor->Addendum ()};
605
605
addendum && addendum->derivedType ()) {
606
606
const NonTbpDefinedIoTable *table{group.nonTbpDefinedIo };
607
- listInput->ResetForNextNamelistItem (/* inNamelistSequence= */ true );
607
+ listInput->ResetForNextNamelistItem (&group );
608
608
if (!IONAME (InputDerivedType)(cookie, *useDescriptor, table) &&
609
609
handler.InError ()) {
610
610
return false ;
611
611
}
612
612
} else {
613
- listInput->ResetForNextNamelistItem (useDescriptor->rank () > 0 );
613
+ listInput->ResetForNextNamelistItem (
614
+ useDescriptor->rank () > 0 ? &group : nullptr );
614
615
if (!descr::DescriptorIO<Direction::Input>(io, *useDescriptor) &&
615
616
handler.InError ()) {
616
617
return false ;
@@ -640,27 +641,51 @@ bool IODEF(InputNamelist)(Cookie cookie, const NamelistGroup &group) {
640
641
}
641
642
642
643
RT_API_ATTRS bool IsNamelistNameOrSlash (IoStatementState &io) {
643
- if (auto *listInput{
644
- io.get_if <ListDirectedStatementState<Direction::Input>>()}) {
645
- if (listInput->inNamelistSequence ()) {
646
- SavedPosition savedPosition{io};
647
- std::size_t byteCount{0 };
648
- if (auto ch{io.GetNextNonBlank (byteCount)}) {
649
- if (IsLegalIdStart (*ch)) {
650
- do {
651
- io.HandleRelativePosition (byteCount);
652
- ch = io.GetCurrentChar (byteCount);
653
- } while (ch && IsLegalIdChar (*ch));
654
- ch = io.GetNextNonBlank (byteCount);
655
- // TODO: how to deal with NaN(...) ambiguity?
656
- return ch && (*ch == ' =' || *ch == ' (' || *ch == ' %' );
657
- } else {
658
- return *ch == ' /' || *ch == ' &' || *ch == ' $' ;
659
- }
660
- }
644
+ auto *listInput{io.get_if <ListDirectedStatementState<Direction::Input>>()};
645
+ if (!listInput || !listInput->namelistGroup ()) {
646
+ return false ; // not namelist
647
+ }
648
+ SavedPosition savedPosition{io};
649
+ std::size_t byteCount{0 };
650
+ auto ch{io.GetNextNonBlank (byteCount)};
651
+ if (!ch) {
652
+ return false ;
653
+ } else if (!IsLegalIdStart (*ch)) {
654
+ return *ch == ' /' || *ch == ' &' || *ch == ' $' ;
655
+ }
656
+ char id[nameBufferSize];
657
+ if (!GetLowerCaseName (io, id, sizeof id, /* crashIfTooLong=*/ false )) {
658
+ return true ; // long name
659
+ }
660
+ // It looks like a name, but might be "inf" or "nan". Check what
661
+ // follows.
662
+ ch = io.GetNextNonBlank (byteCount);
663
+ if (!ch) {
664
+ return false ;
665
+ } else if (*ch == ' =' || *ch == ' %' ) {
666
+ return true ;
667
+ } else if (*ch != ' (' ) {
668
+ return false ;
669
+ } else if (runtime::strcmp (id, " nan" ) != 0 ) {
670
+ return true ;
671
+ }
672
+ // "nan(" ambiguity
673
+ int depth{1 };
674
+ while (true ) {
675
+ io.HandleRelativePosition (byteCount);
676
+ ch = io.GetNextNonBlank (byteCount);
677
+ if (depth == 0 ) {
678
+ // nan(...) followed by '=', '%', or '('?
679
+ break ;
680
+ } else if (!ch) {
681
+ return true ; // not a valid NaN(...)
682
+ } else if (*ch == ' (' ) {
683
+ ++depth;
684
+ } else if (*ch == ' )' ) {
685
+ --depth;
661
686
}
662
687
}
663
- return false ;
688
+ return ch && (*ch == ' = ' || *ch == ' % ' || *ch == ' ( ' ) ;
664
689
}
665
690
666
691
RT_OFFLOAD_API_GROUP_END
0 commit comments