@@ -94,7 +94,8 @@ static void Compare(Descriptor &result, const Descriptor &x,
94
94
elements *= ub[j];
95
95
xAt[j] = yAt[j] = 1 ;
96
96
}
97
- result.Establish (TypeCategory::Logical, 1 , ub, rank);
97
+ result.Establish (
98
+ TypeCategory::Logical, 1 , nullptr , rank, ub, CFI_attribute_allocatable);
98
99
if (result.Allocate (lb, ub) != CFI_SUCCESS) {
99
100
terminator.Crash (" Compare: could not allocate storage for result" );
100
101
}
@@ -145,7 +146,8 @@ static void AdjustLRHelper(Descriptor &result, const Descriptor &string,
145
146
stringAt[j] = 1 ;
146
147
}
147
148
std::size_t elementBytes{string.ElementBytes ()};
148
- result.Establish (string.type (), elementBytes, ub, rank);
149
+ result.Establish (string.type (), elementBytes, nullptr , rank, ub,
150
+ CFI_attribute_allocatable);
149
151
if (result.Allocate (lb, ub) != CFI_SUCCESS) {
150
152
terminator.Crash (" ADJUSTL/R: could not allocate storage for result" );
151
153
}
@@ -196,7 +198,8 @@ static void LenTrim(Descriptor &result, const Descriptor &string,
196
198
elements *= ub[j];
197
199
stringAt[j] = 1 ;
198
200
}
199
- result.Establish (TypeCategory::Integer, sizeof (INT), ub, rank);
201
+ result.Establish (TypeCategory::Integer, sizeof (INT), nullptr , rank, ub,
202
+ CFI_attribute_allocatable);
200
203
if (result.Allocate (lb, ub) != CFI_SUCCESS) {
201
204
terminator.Crash (" LEN_TRIM: could not allocate storage for result" );
202
205
}
@@ -232,6 +235,133 @@ static void LenTrimKind(Descriptor &result, const Descriptor &string, int kind,
232
235
}
233
236
}
234
237
238
+ // SCAN and VERIFY implementation help. These intrinsic functions
239
+ // do pretty much the same thing, so they're templatized with a
240
+ // distinguishing flag.
241
+
242
+ template <typename CHAR, bool IS_VERIFY = false >
243
+ inline std::size_t ScanVerify (const CHAR *x, std::size_t xLen, const CHAR *set,
244
+ std::size_t setLen, bool back) {
245
+ std::size_t at{back ? xLen : 1 };
246
+ int increment{back ? -1 : 1 };
247
+ for (; xLen-- > 0 ; at += increment) {
248
+ CHAR ch{x[at - 1 ]};
249
+ bool inSet{false };
250
+ // TODO: If set is sorted, could use binary search
251
+ for (std::size_t j{0 }; j < setLen; ++j) {
252
+ if (set[j] == ch) {
253
+ inSet = true ;
254
+ break ;
255
+ }
256
+ }
257
+ if (inSet != IS_VERIFY) {
258
+ return at;
259
+ }
260
+ }
261
+ return 0 ;
262
+ }
263
+
264
+ // Specialization for one-byte characters
265
+ template <bool IS_VERIFY = false >
266
+ inline std::size_t ScanVerify (const char *x, std::size_t xLen, const char *set,
267
+ std::size_t setLen, bool back) {
268
+ std::size_t at{back ? xLen : 1 };
269
+ int increment{back ? -1 : 1 };
270
+ if (xLen > 0 ) {
271
+ std::uint64_t bitSet[256 / 64 ]{0 };
272
+ std::uint64_t one{1 };
273
+ for (std::size_t j{0 }; j < setLen; ++j) {
274
+ unsigned setCh{static_cast <unsigned char >(set[j])};
275
+ bitSet[setCh / 64 ] |= one << (setCh % 64 );
276
+ }
277
+ for (; xLen-- > 0 ; at += increment) {
278
+ unsigned ch{static_cast <unsigned char >(x[at - 1 ])};
279
+ bool inSet{((bitSet[ch / 64 ] >> (ch % 64 )) & 1 ) != 0 };
280
+ if (inSet != IS_VERIFY) {
281
+ return at;
282
+ }
283
+ }
284
+ }
285
+ return 0 ;
286
+ }
287
+
288
+ static bool IsLogicalElementTrue (
289
+ const Descriptor &logical, const SubscriptValue at[]) {
290
+ // A LOGICAL value is false if and only if all of its bytes are zero.
291
+ const char *p{logical.Element <char >(at)};
292
+ for (std::size_t j{logical.ElementBytes ()}; j-- > 0 ; ++p) {
293
+ if (*p) {
294
+ return true ;
295
+ }
296
+ }
297
+ return false ;
298
+ }
299
+
300
+ template <typename INT, typename CHAR, bool IS_VERIFY = false >
301
+ static void ScanVerify (Descriptor &result, const Descriptor &string,
302
+ const Descriptor &set, const Descriptor *back,
303
+ const Terminator &terminator) {
304
+ int rank{string.rank () ? string.rank ()
305
+ : set.rank () ? set.rank () : back ? back->rank () : 0 };
306
+ SubscriptValue lb[maxRank], ub[maxRank], stringAt[maxRank], setAt[maxRank],
307
+ backAt[maxRank];
308
+ SubscriptValue elements{1 };
309
+ for (int j{0 }; j < rank; ++j) {
310
+ lb[j] = 1 ;
311
+ ub[j] = string.rank ()
312
+ ? string.GetDimension (j).Extent ()
313
+ : set.rank () ? set.GetDimension (j).Extent ()
314
+ : back ? back->GetDimension (j).Extent () : 1 ;
315
+ elements *= ub[j];
316
+ stringAt[j] = setAt[j] = backAt[j] = 1 ;
317
+ }
318
+ result.Establish (TypeCategory::Integer, sizeof (INT), nullptr , rank, ub,
319
+ CFI_attribute_allocatable);
320
+ if (result.Allocate (lb, ub) != CFI_SUCCESS) {
321
+ terminator.Crash (" SCAN/VERIFY: could not allocate storage for result" );
322
+ }
323
+ std::size_t stringElementChars{string.ElementBytes () >> shift<CHAR>};
324
+ std::size_t setElementChars{set.ElementBytes () >> shift<CHAR>};
325
+ for (SubscriptValue resultAt{0 }; elements-- > 0 ; resultAt += sizeof (INT),
326
+ string.IncrementSubscripts (stringAt), set.IncrementSubscripts (setAt),
327
+ back && back->IncrementSubscripts (backAt)) {
328
+ *result.OffsetElement <INT>(resultAt) =
329
+ ScanVerify<CHAR, IS_VERIFY>(string.Element <CHAR>(stringAt),
330
+ stringElementChars, set.Element <CHAR>(setAt), setElementChars,
331
+ back && IsLogicalElementTrue (*back, backAt));
332
+ }
333
+ }
334
+
335
+ template <typename CHAR, bool IS_VERIFY = false >
336
+ static void ScanVerifyKind (Descriptor &result, const Descriptor &string,
337
+ const Descriptor &set, const Descriptor *back, int kind,
338
+ const Terminator &terminator) {
339
+ switch (kind) {
340
+ case 1 :
341
+ ScanVerify<std::int8_t , CHAR, IS_VERIFY>(
342
+ result, string, set, back, terminator);
343
+ break ;
344
+ case 2 :
345
+ ScanVerify<std::int16_t , CHAR, IS_VERIFY>(
346
+ result, string, set, back, terminator);
347
+ break ;
348
+ case 4 :
349
+ ScanVerify<std::int32_t , CHAR, IS_VERIFY>(
350
+ result, string, set, back, terminator);
351
+ break ;
352
+ case 8 :
353
+ ScanVerify<std::int64_t , CHAR, IS_VERIFY>(
354
+ result, string, set, back, terminator);
355
+ break ;
356
+ case 16 :
357
+ ScanVerify<common::uint128_t , CHAR, IS_VERIFY>(
358
+ result, string, set, back, terminator);
359
+ break ;
360
+ default :
361
+ terminator.Crash (" SCAN/VERIFY: bad KIND=%d" , kind);
362
+ }
363
+ }
364
+
235
365
template <typename TO, typename FROM>
236
366
static void CopyAndPad (
237
367
TO *to, const FROM *from, std::size_t toChars, std::size_t fromChars) {
@@ -608,7 +738,7 @@ void RTNAME(CharacterPad1)(char *lhs, std::size_t bytes, std::size_t offset) {
608
738
}
609
739
}
610
740
611
- // Intrinsic functions
741
+ // Intrinsic function entry points
612
742
613
743
void RTNAME (AdjustL)(Descriptor &result, const Descriptor &string,
614
744
const char *sourceFile, int sourceLine) {
@@ -649,11 +779,47 @@ void RTNAME(LenTrim)(Descriptor &result, const Descriptor &string, int kind,
649
779
}
650
780
}
651
781
782
+ std::size_t RTNAME (Scan1)(const char *x, std::size_t xLen, const char *set,
783
+ std::size_t setLen, bool back) {
784
+ return ScanVerify<char , false >(x, xLen, set, setLen, back);
785
+ }
786
+ std::size_t RTNAME (Scan2)(const char16_t *x, std::size_t xLen,
787
+ const char16_t *set, std::size_t setLen, bool back) {
788
+ return ScanVerify<char16_t , false >(x, xLen, set, setLen, back);
789
+ }
790
+ std::size_t RTNAME (Scan4)(const char32_t *x, std::size_t xLen,
791
+ const char32_t *set, std::size_t setLen, bool back) {
792
+ return ScanVerify<char32_t , false >(x, xLen, set, setLen, back);
793
+ }
794
+
795
+ void RTNAME (Scan)(Descriptor &result, const Descriptor &string,
796
+ const Descriptor &set, const Descriptor *back, int kind,
797
+ const char *sourceFile, int sourceLine) {
798
+ Terminator terminator{sourceFile, sourceLine};
799
+ switch (string.raw ().type ) {
800
+ case CFI_type_char:
801
+ ScanVerifyKind<char , false >(result, string, set, back, kind, terminator);
802
+ break ;
803
+ case CFI_type_char16_t:
804
+ ScanVerifyKind<char16_t , false >(
805
+ result, string, set, back, kind, terminator);
806
+ break ;
807
+ case CFI_type_char32_t:
808
+ ScanVerifyKind<char32_t , false >(
809
+ result, string, set, back, kind, terminator);
810
+ break ;
811
+ default :
812
+ terminator.Crash (
813
+ " SCAN: bad string type code %d" , static_cast <int >(string.raw ().type ));
814
+ }
815
+ }
816
+
652
817
void RTNAME (Repeat)(Descriptor &result, const Descriptor &string,
653
818
std::size_t ncopies, const char *sourceFile, int sourceLine) {
654
819
Terminator terminator{sourceFile, sourceLine};
655
820
std::size_t origBytes{string.ElementBytes ()};
656
- result.Establish (string.type (), origBytes * ncopies, nullptr , 0 );
821
+ result.Establish (string.type (), origBytes * ncopies, nullptr , 0 , nullptr ,
822
+ CFI_attribute_allocatable);
657
823
if (result.Allocate (nullptr , nullptr ) != CFI_SUCCESS) {
658
824
terminator.Crash (" REPEAT could not allocate storage for result" );
659
825
}
@@ -692,6 +858,39 @@ void RTNAME(Trim)(Descriptor &result, const Descriptor &string,
692
858
std::memcpy (result.OffsetElement (), string.OffsetElement (), resultBytes);
693
859
}
694
860
861
+ std::size_t RTNAME (Verify1)(const char *x, std::size_t xLen, const char *set,
862
+ std::size_t setLen, bool back) {
863
+ return ScanVerify<char , true >(x, xLen, set, setLen, back);
864
+ }
865
+ std::size_t RTNAME (Verify2)(const char16_t *x, std::size_t xLen,
866
+ const char16_t *set, std::size_t setLen, bool back) {
867
+ return ScanVerify<char16_t , true >(x, xLen, set, setLen, back);
868
+ }
869
+ std::size_t RTNAME (Verify4)(const char32_t *x, std::size_t xLen,
870
+ const char32_t *set, std::size_t setLen, bool back) {
871
+ return ScanVerify<char32_t , true >(x, xLen, set, setLen, back);
872
+ }
873
+
874
+ void RTNAME (Verify)(Descriptor &result, const Descriptor &string,
875
+ const Descriptor &set, const Descriptor *back, int kind,
876
+ const char *sourceFile, int sourceLine) {
877
+ Terminator terminator{sourceFile, sourceLine};
878
+ switch (string.raw ().type ) {
879
+ case CFI_type_char:
880
+ ScanVerifyKind<char , true >(result, string, set, back, kind, terminator);
881
+ break ;
882
+ case CFI_type_char16_t:
883
+ ScanVerifyKind<char16_t , true >(result, string, set, back, kind, terminator);
884
+ break ;
885
+ case CFI_type_char32_t:
886
+ ScanVerifyKind<char32_t , true >(result, string, set, back, kind, terminator);
887
+ break ;
888
+ default :
889
+ terminator.Crash (
890
+ " VERIFY: bad string type code %d" , static_cast <int >(string.raw ().type ));
891
+ }
892
+ }
893
+
695
894
void RTNAME (CharacterMax)(Descriptor &accumulator, const Descriptor &x,
696
895
const char *sourceFile, int sourceLine) {
697
896
MaxMin<false >(accumulator, x, sourceFile, sourceLine);
0 commit comments