| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //================================================================================================== | ||
| 2 | /* | ||
| 3 | SPY - C++ Informations Broker | ||
| 4 | Copyright : SPY Project Contributors | ||
| 5 | SPDX-License-Identifier: BSL-1.0 | ||
| 6 | */ | ||
| 7 | //================================================================================================== | ||
| 8 | #pragma once | ||
| 9 | |||
| 10 | // Make sure the proper header is included to detect GNU libc | ||
| 11 | #include <spy/detail.hpp> | ||
| 12 | |||
| 13 | #include <compare> | ||
| 14 | #include <cstddef> | ||
| 15 | |||
| 16 | namespace spy::_ | ||
| 17 | { | ||
| 18 | enum class libC | ||
| 19 | { | ||
| 20 | undefined_ = -1, | ||
| 21 | cloudabi_, | ||
| 22 | uc_, | ||
| 23 | vms_, | ||
| 24 | zos_, | ||
| 25 | gnu_ | ||
| 26 | }; | ||
| 27 | |||
| 28 | template<libC Lib, int M, int N, int P> struct libc_info | ||
| 29 | { | ||
| 30 | static constexpr libC vendor = Lib; | ||
| 31 | static constexpr version_id<M, N, P> version = {}; | ||
| 32 | |||
| 33 | inline constexpr explicit operator bool() const noexcept; | ||
| 34 | |||
| 35 | template<libC C2> constexpr bool operator==(libc_info<C2, -1, 0, 0> const&) const noexcept | ||
| 36 | { | ||
| 37 | return C2 == vendor; | ||
| 38 | } | ||
| 39 | |||
| 40 | template<libC C2, int M2, int N2, int P2> | ||
| 41 | constexpr bool operator==(libc_info<C2, M2, N2, P2> const& c2) const noexcept | ||
| 42 | { | ||
| 43 | return C2 == vendor && version == c2.version; | ||
| 44 | } | ||
| 45 | |||
| 46 | template<libC C2, int M2, int N2, int P2> | ||
| 47 | constexpr auto operator<=>(libc_info<C2, M2, N2, P2> const& c2) const noexcept | ||
| 48 | { | ||
| 49 | if constexpr(vendor == C2) return version <=> c2.version; | ||
| 50 | else return vendor <=> C2; | ||
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 54 | template<_::stream OS, libC C, int M, int N, int P> | ||
| 55 | 1 | auto& operator<<(OS& os, libc_info<C, M, N, P> const& c) | |
| 56 | { | ||
| 57 | if(c.vendor == libC::cloudabi_) return os << "CloudABI Standard C Library " << c.version; | ||
| 58 | if(c.vendor == libC::uc_) return os << "uClibc Standard C Library " << c.version; | ||
| 59 | if(c.vendor == libC::vms_) return os << "VMS Standard C Library " << c.version; | ||
| 60 | if(c.vendor == libC::zos_) return os << "z/OS Standard C Library " << c.version; | ||
| 61 | 1 | if(c.vendor == libC::gnu_) return os << "GNU Standard C Library " << c.version; | |
| 62 | |||
| 63 | return os << "Undefined Standard C Library"; | ||
| 64 | } | ||
| 65 | |||
| 66 | template<int M, int N, int P> using cloudabi_t = libc_info<libC::cloudabi_, M, N, P>; | ||
| 67 | template<int M, int N, int P> using uc_t = libc_info<libC::uc_, M, N, P>; | ||
| 68 | template<int M, int N, int P> using vms_t = libc_info<libC::vms_, M, N, P>; | ||
| 69 | template<int M, int N, int P> using zos_t = libc_info<libC::zos_, M, N, P>; | ||
| 70 | template<int M, int N, int P> using gnu_t = libc_info<libC::gnu_, M, N, P>; | ||
| 71 | } | ||
| 72 | |||
| 73 | namespace spy | ||
| 74 | { | ||
| 75 | //================================================================================================ | ||
| 76 | // LIBC detection object type | ||
| 77 | //================================================================================================ | ||
| 78 | #if defined(__cloudlibc__) | ||
| 79 | #define SPY_LIBC_IS_CLOUDABI | ||
| 80 | using libc_type = _::cloudabi_t<__cloudlibc_major__, __cloudlibc_minor__, 0>; | ||
| 81 | #elif defined(__GLIBC__) | ||
| 82 | #define SPY_LIBC_IS_GNU | ||
| 83 | using libc_type = _::gnu_t<__GLIBC__, __GLIBC_MINOR__, 0>; | ||
| 84 | #elif defined(__GNU_LIBRARY__) | ||
| 85 | #define SPY_LIBC_IS_GNU | ||
| 86 | using libc_type = _::gnu_t<__GNU_LIBRARY__, __GNU_LIBRARY_MINOR__, 0>; | ||
| 87 | #elif defined(__UCLIBC__) | ||
| 88 | #define SPY_LIBC_IS_UCLIBC | ||
| 89 | using libc_type = _::uc_t<__UCLIBC_MAJOR__, __UCLIBC_MINOR__, __UCLIBC_SUBLEVEL__>; | ||
| 90 | #elif defined(__CRTL_VER) | ||
| 91 | #define SPY_LIBC_IS_VMS | ||
| 92 | #define SPY0 (__CRTL_VER / 100) | ||
| 93 | using libc_type = _::vms_t<(SPY0 / 100000) % 100, (SPY0 / 1000) % 100, (SPY0) % 100>; | ||
| 94 | #undef SPY0 | ||
| 95 | #elif defined(__LIBREL__) | ||
| 96 | #define SPY_LIBC_IS_ZOS | ||
| 97 | using libc_type = _::zos_t < (__LIBREL__ & 0xF000000) >> 24, (__LIBREL__ & 0xFF0000) >> 16, | ||
| 98 | (__LIBREL__ & 0xFFFF) > ; | ||
| 99 | #else | ||
| 100 | #define SPY_LIBC_IS_UNKNOWN | ||
| 101 | using libc_type = _::libc_info<_::libC::undefined_, -1, 0, 0>; | ||
| 102 | #endif | ||
| 103 | |||
| 104 | //================================================================================================ | ||
| 105 | //! @ingroup spy_standards | ||
| 106 | //! @brief LIBC version reporting value | ||
| 107 | //! | ||
| 108 | //! The `spy::libc` object can be compared to any other libc related value to verify | ||
| 109 | //! if the code being compiled with a specific version of the libc. | ||
| 110 | //! | ||
| 111 | //! Any libc related value can be checked for equality or ordering for a given version. The | ||
| 112 | //! targeted version is then specified using a libc-dependent literal. | ||
| 113 | //! | ||
| 114 | //! Additionally, any of the libc related value are convertible to `bool`. They evaluates to | ||
| 115 | //! `true` if they matches the correct libc currently used. | ||
| 116 | //! | ||
| 117 | //! @groupheader{Supported Value} | ||
| 118 | //! | ||
| 119 | //! Name | Vendor | ||
| 120 | //! ----------------- | ------------- | ||
| 121 | //! `spy::cloudabi_` | CloudABI | ||
| 122 | //! `spy::uc_` | uClibc | ||
| 123 | //! `spy::vms_` | VMS | ||
| 124 | //! `spy::zos_` | zOS | ||
| 125 | //! `spy::gnu_` | GNU | ||
| 126 | //! | ||
| 127 | //! @groupheader{Example} | ||
| 128 | //! @godbolt{samples/libc.cpp} | ||
| 129 | //================================================================================================ | ||
| 130 | constexpr inline auto libc = libc_type {}; | ||
| 131 | } | ||
| 132 | |||
| 133 | namespace spy::_ | ||
| 134 | { | ||
| 135 | template<libC C, int M, int N, int P> | ||
| 136 | inline constexpr libc_info<C, M, N, P>::operator bool() const noexcept | ||
| 137 | { | ||
| 138 | return spy::libc == *this; | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | namespace spy | ||
| 143 | { | ||
| 144 | //================================================================================================ | ||
| 145 | // LIBCs detector stand-alone instances | ||
| 146 | //================================================================================================ | ||
| 147 | constexpr inline auto cloudabi_ = _::cloudabi_t<-1, 0, 0> {}; | ||
| 148 | constexpr inline auto uc_ = _::uc_t<-1, 0, 0> {}; | ||
| 149 | constexpr inline auto vms_ = _::vms_t<-1, 0, 0> {}; | ||
| 150 | constexpr inline auto zos_ = _::zos_t<-1, 0, 0> {}; | ||
| 151 | constexpr inline auto gnu_ = _::gnu_t<-1, 0, 0> {}; | ||
| 152 | } | ||
| 153 | |||
| 154 | namespace spy::literal | ||
| 155 | { | ||
| 156 | //! @ingroup spy_standards | ||
| 157 | //! @brief User-defined suffix for the CloudABI libc version definition | ||
| 158 | template<char... c> constexpr auto operator""_cloud() | ||
| 159 | { | ||
| 160 | return _::literal_wrap<_::cloudabi_t, c...>(); | ||
| 161 | } | ||
| 162 | |||
| 163 | //! @ingroup spy_standards | ||
| 164 | //! @brief User-defined suffix for the uClibc version definition | ||
| 165 | template<char... c> constexpr auto operator""_uc() { return _::literal_wrap<_::uc_t, c...>(); } | ||
| 166 | |||
| 167 | //! @ingroup spy_standards | ||
| 168 | //! @brief User-defined suffix for the VMS libc version definition | ||
| 169 | template<char... c> constexpr auto operator""_vms() { return _::literal_wrap<_::vms_t, c...>(); } | ||
| 170 | |||
| 171 | //! @ingroup spy_standards | ||
| 172 | //! @brief User-defined suffix for the zOS libc version definition | ||
| 173 | template<char... c> constexpr auto operator""_zos() { return _::literal_wrap<_::zos_t, c...>(); } | ||
| 174 | |||
| 175 | //! @ingroup spy_standards | ||
| 176 | //! @brief User-defined suffix for the GNU libc version definition | ||
| 177 | template<char... c> constexpr auto operator""_gnu() { return _::literal_wrap<_::gnu_t, c...>(); } | ||
| 178 | } | ||
| 179 |