1651f58bfSDiana Picus //===-- runtime/tools.cpp -------------------------------------------------===//
2352d347aSAlexis Perry //
3352d347aSAlexis Perry // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4352d347aSAlexis Perry // See https://llvm.org/LICENSE.txt for license information.
5352d347aSAlexis Perry // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6352d347aSAlexis Perry //
7352d347aSAlexis Perry //===----------------------------------------------------------------------===//
8352d347aSAlexis Perry
9352d347aSAlexis Perry #include "tools.h"
10e372e0f9Speter klausler #include "terminator.h"
11231fae90SIsuru Fernando #include <algorithm>
12e372e0f9Speter klausler #include <cstdint>
13824bf908SDiana Picus #include <cstdlib>
14352d347aSAlexis Perry #include <cstring>
15352d347aSAlexis Perry
16352d347aSAlexis Perry namespace Fortran::runtime {
17352d347aSAlexis Perry
TrimTrailingSpaces(const char * s,std::size_t n)18675ad1bcSpeter klausler std::size_t TrimTrailingSpaces(const char *s, std::size_t n) {
19675ad1bcSpeter klausler while (n > 0 && s[n - 1] == ' ') {
20675ad1bcSpeter klausler --n;
21675ad1bcSpeter klausler }
22675ad1bcSpeter klausler return n;
23675ad1bcSpeter klausler }
24675ad1bcSpeter klausler
SaveDefaultCharacter(const char * s,std::size_t length,const Terminator & terminator)25352d347aSAlexis Perry OwningPtr<char> SaveDefaultCharacter(
2695696d56Speter klausler const char *s, std::size_t length, const Terminator &terminator) {
27352d347aSAlexis Perry if (s) {
28352d347aSAlexis Perry auto *p{static_cast<char *>(AllocateMemoryOrCrash(terminator, length + 1))};
29352d347aSAlexis Perry std::memcpy(p, s, length);
30352d347aSAlexis Perry p[length] = '\0';
31352d347aSAlexis Perry return OwningPtr<char>{p};
32352d347aSAlexis Perry } else {
33352d347aSAlexis Perry return OwningPtr<char>{};
34352d347aSAlexis Perry }
35352d347aSAlexis Perry }
36352d347aSAlexis Perry
CaseInsensitiveMatch(const char * value,std::size_t length,const char * possibility)37352d347aSAlexis Perry static bool CaseInsensitiveMatch(
38352d347aSAlexis Perry const char *value, std::size_t length, const char *possibility) {
393b635714Speter klausler for (; length-- > 0; ++possibility) {
403b635714Speter klausler char ch{*value++};
41352d347aSAlexis Perry if (ch >= 'a' && ch <= 'z') {
42352d347aSAlexis Perry ch += 'A' - 'a';
43352d347aSAlexis Perry }
443b635714Speter klausler if (*possibility != ch) {
453b635714Speter klausler if (*possibility != '\0' || ch != ' ') {
46352d347aSAlexis Perry return false;
47352d347aSAlexis Perry }
483b635714Speter klausler // Ignore trailing blanks (12.5.6.2 p1)
493b635714Speter klausler while (length-- > 0) {
503b635714Speter klausler if (*value++ != ' ') {
513b635714Speter klausler return false;
523b635714Speter klausler }
533b635714Speter klausler }
543b635714Speter klausler return true;
553b635714Speter klausler }
56352d347aSAlexis Perry }
57352d347aSAlexis Perry return *possibility == '\0';
58352d347aSAlexis Perry }
59352d347aSAlexis Perry
IdentifyValue(const char * value,std::size_t length,const char * possibilities[])60352d347aSAlexis Perry int IdentifyValue(
61352d347aSAlexis Perry const char *value, std::size_t length, const char *possibilities[]) {
62352d347aSAlexis Perry if (value) {
63352d347aSAlexis Perry for (int j{0}; possibilities[j]; ++j) {
64352d347aSAlexis Perry if (CaseInsensitiveMatch(value, length, possibilities[j])) {
65352d347aSAlexis Perry return j;
66352d347aSAlexis Perry }
67352d347aSAlexis Perry }
68352d347aSAlexis Perry }
69352d347aSAlexis Perry return -1;
70352d347aSAlexis Perry }
713b635714Speter klausler
ToFortranDefaultCharacter(char * to,std::size_t toLength,const char * from)723b635714Speter klausler void ToFortranDefaultCharacter(
733b635714Speter klausler char *to, std::size_t toLength, const char *from) {
743b635714Speter klausler std::size_t len{std::strlen(from)};
753b635714Speter klausler if (len < toLength) {
7643fadefbSpeter klausler std::memcpy(to, from, len);
773b635714Speter klausler std::memset(to + len, ' ', toLength - len);
7843fadefbSpeter klausler } else {
7943fadefbSpeter klausler std::memcpy(to, from, toLength);
803b635714Speter klausler }
813b635714Speter klausler }
823b635714Speter klausler
CheckConformability(const Descriptor & to,const Descriptor & x,Terminator & terminator,const char * funcName,const char * toName,const char * xName)83e372e0f9Speter klausler void CheckConformability(const Descriptor &to, const Descriptor &x,
84e372e0f9Speter klausler Terminator &terminator, const char *funcName, const char *toName,
85e372e0f9Speter klausler const char *xName) {
86e372e0f9Speter klausler if (x.rank() == 0) {
87e372e0f9Speter klausler return; // scalar conforms with anything
88e372e0f9Speter klausler }
89e372e0f9Speter klausler int rank{to.rank()};
90e372e0f9Speter klausler if (x.rank() != rank) {
91e372e0f9Speter klausler terminator.Crash(
92e372e0f9Speter klausler "Incompatible array arguments to %s: %s has rank %d but %s has rank %d",
93e372e0f9Speter klausler funcName, toName, rank, xName, x.rank());
94e372e0f9Speter klausler } else {
95e372e0f9Speter klausler for (int j{0}; j < rank; ++j) {
96e372e0f9Speter klausler auto toExtent{static_cast<std::int64_t>(to.GetDimension(j).Extent())};
97e372e0f9Speter klausler auto xExtent{static_cast<std::int64_t>(x.GetDimension(j).Extent())};
98e372e0f9Speter klausler if (xExtent != toExtent) {
99e372e0f9Speter klausler terminator.Crash("Incompatible array arguments to %s: dimension %d of "
100e372e0f9Speter klausler "%s has extent %" PRId64 " but %s has extent %" PRId64,
101b910cf98SJean Perier funcName, j + 1, toName, toExtent, xName, xExtent);
102e372e0f9Speter klausler }
103e372e0f9Speter klausler }
104e372e0f9Speter klausler }
105e372e0f9Speter klausler }
106e372e0f9Speter klausler
CheckIntegerKind(Terminator & terminator,int kind,const char * intrinsic)107e372e0f9Speter klausler void CheckIntegerKind(Terminator &terminator, int kind, const char *intrinsic) {
108e372e0f9Speter klausler if (kind < 1 || kind > 16 || (kind & (kind - 1)) != 0) {
109*d4609ae4SPeter Steinfeld terminator.Crash(
110*d4609ae4SPeter Steinfeld "not yet implemented: %s: KIND=%d argument", intrinsic, kind);
111e372e0f9Speter klausler }
112e372e0f9Speter klausler }
1131f879005STim Keith } // namespace Fortran::runtime
114