peter klausler | fae12a0 | 2020-01-24 00:10:00 | [diff] [blame] | 1 | //===-- runtime/tools.h -----------------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef FORTRAN_RUNTIME_TOOLS_H_ |
| 10 | #define FORTRAN_RUNTIME_TOOLS_H_ |
peter klausler | f7be251 | 2020-01-24 00:59:27 | [diff] [blame] | 11 | |
peter klausler | e372e0f | 2021-03-31 16:14:08 | [diff] [blame^] | 12 | #include "cpp-type.h" |
| 13 | #include "descriptor.h" |
peter klausler | fae12a0 | 2020-01-24 00:10:00 | [diff] [blame] | 14 | #include "memory.h" |
peter klausler | e372e0f | 2021-03-31 16:14:08 | [diff] [blame^] | 15 | #include "terminator.h" |
peter klausler | f7be251 | 2020-01-24 00:59:27 | [diff] [blame] | 16 | #include <functional> |
| 17 | #include <map> |
| 18 | #include <type_traits> |
| 19 | |
peter klausler | fae12a0 | 2020-01-24 00:10:00 | [diff] [blame] | 20 | namespace Fortran::runtime { |
| 21 | |
| 22 | class Terminator; |
| 23 | |
peter klausler | 675ad1b | 2020-08-03 18:35:29 | [diff] [blame] | 24 | std::size_t TrimTrailingSpaces(const char *, std::size_t); |
| 25 | |
peter klausler | 95696d5 | 2020-02-05 00:55:45 | [diff] [blame] | 26 | OwningPtr<char> SaveDefaultCharacter( |
| 27 | const char *, std::size_t, const Terminator &); |
peter klausler | fae12a0 | 2020-01-24 00:10:00 | [diff] [blame] | 28 | |
| 29 | // For validating and recognizing default CHARACTER values in a |
| 30 | // case-insensitive manner. Returns the zero-based index into the |
| 31 | // null-terminated array of upper-case possibilities when the value is valid, |
| 32 | // or -1 when it has no match. |
| 33 | int IdentifyValue( |
| 34 | const char *value, std::size_t length, const char *possibilities[]); |
peter klausler | f7be251 | 2020-01-24 00:59:27 | [diff] [blame] | 35 | |
peter klausler | 3b63571 | 2020-02-13 22:41:56 | [diff] [blame] | 36 | // Truncates or pads as necessary |
| 37 | void ToFortranDefaultCharacter( |
| 38 | char *to, std::size_t toLength, const char *from); |
peter klausler | e372e0f | 2021-03-31 16:14:08 | [diff] [blame^] | 39 | |
| 40 | // Utility for dealing with elemental LOGICAL arguments |
| 41 | inline bool IsLogicalElementTrue( |
| 42 | const Descriptor &logical, const SubscriptValue at[]) { |
| 43 | // A LOGICAL value is false if and only if all of its bytes are zero. |
| 44 | const char *p{logical.Element<char>(at)}; |
| 45 | for (std::size_t j{logical.ElementBytes()}; j-- > 0; ++p) { |
| 46 | if (*p) { |
| 47 | return true; |
| 48 | } |
| 49 | } |
| 50 | return false; |
| 51 | } |
| 52 | |
| 53 | // Check array conformability; a scalar 'x' conforms. Crashes on error. |
| 54 | void CheckConformability(const Descriptor &to, const Descriptor &x, |
| 55 | Terminator &, const char *funcName, const char *toName, |
| 56 | const char *fromName); |
| 57 | |
| 58 | // Validate a KIND= argument |
| 59 | void CheckIntegerKind(Terminator &, int kind, const char *intrinsic); |
| 60 | |
| 61 | template <typename TO, typename FROM> |
| 62 | inline void PutContiguousConverted(TO *to, FROM *from, std::size_t count) { |
| 63 | while (count-- > 0) { |
| 64 | *to++ = *from++; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | static inline std::int64_t GetInt64(const char *p, std::size_t bytes) { |
| 69 | switch (bytes) { |
| 70 | case 1: |
| 71 | return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 1> *>(p); |
| 72 | case 2: |
| 73 | return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 2> *>(p); |
| 74 | case 4: |
| 75 | return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 4> *>(p); |
| 76 | case 8: |
| 77 | return *reinterpret_cast<const CppTypeFor<TypeCategory::Integer, 8> *>(p); |
| 78 | default: |
| 79 | Terminator{__FILE__, __LINE__}.Crash( |
| 80 | "GetInt64: no case for %zd bytes", bytes); |
| 81 | } |
| 82 | } |
| 83 | |
| 84 | template <typename INT> |
| 85 | inline bool SetInteger(INT &x, int kind, std::int64_t value) { |
| 86 | switch (kind) { |
| 87 | case 1: |
| 88 | reinterpret_cast<CppTypeFor<TypeCategory::Integer, 1> &>(x) = value; |
| 89 | return true; |
| 90 | case 2: |
| 91 | reinterpret_cast<CppTypeFor<TypeCategory::Integer, 2> &>(x) = value; |
| 92 | return true; |
| 93 | case 4: |
| 94 | reinterpret_cast<CppTypeFor<TypeCategory::Integer, 4> &>(x) = value; |
| 95 | return true; |
| 96 | case 8: |
| 97 | reinterpret_cast<CppTypeFor<TypeCategory::Integer, 8> &>(x) = value; |
| 98 | return true; |
| 99 | default: |
| 100 | return false; |
| 101 | } |
| 102 | } |
| 103 | |
Tim Keith | 1f87900 | 2020-03-29 04:00:16 | [diff] [blame] | 104 | } // namespace Fortran::runtime |
| 105 | #endif // FORTRAN_RUNTIME_TOOLS_H_ |