1 //===----------------------------------------------------------------------===// 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 #include <__locale_dir/support/windows.h> 10 #include <clocale> // std::localeconv() & friends 11 #include <cstdarg> // va_start & friends 12 #include <cstddef> 13 #include <cstdio> // std::vsnprintf & friends 14 #include <cstdlib> // std::strtof & friends 15 #include <ctime> // std::strftime 16 #include <cwchar> // wide char manipulation 17 18 _LIBCPP_BEGIN_NAMESPACE_STD 19 namespace __locale { 20 21 // 22 // Locale management 23 // 24 // FIXME: base and mask currently unused. Needs manual work to construct the new locale 25 __locale_t __newlocale(int /*mask*/, const char* locale, __locale_t /*base*/) { 26 return {::_create_locale(LC_ALL, locale), locale}; 27 } 28 29 __lconv_t* __localeconv(__locale_t& loc) { 30 __locale_guard __current(loc); 31 lconv* lc = std::localeconv(); 32 if (!lc) 33 return lc; 34 return loc.__store_lconv(lc); 35 } 36 37 // 38 // Strtonum functions 39 // 40 #if !defined(_LIBCPP_MSVCRT) 41 float __strtof(const char* nptr, char** endptr, __locale_t loc) { 42 __locale_guard __current(loc); 43 return std::strtof(nptr, endptr); 44 } 45 46 long double __strtold(const char* nptr, char** endptr, __locale_t loc) { 47 __locale_guard __current(loc); 48 return std::strtold(nptr, endptr); 49 } 50 #endif 51 52 // 53 // Character manipulation functions 54 // 55 #if defined(__MINGW32__) && __MSVCRT_VERSION__ < 0x0800 56 size_t __strftime(char* ret, size_t n, const char* format, const struct tm* tm, __locale_t loc) { 57 __locale_guard __current(loc); 58 return std::strftime(ret, n, format, tm); 59 } 60 #endif 61 62 // 63 // Other functions 64 // 65 decltype(MB_CUR_MAX) __mb_len_max(__locale_t __l) { 66 #if defined(_LIBCPP_MSVCRT) 67 return ::___mb_cur_max_l_func(__l); 68 #else 69 __locale_guard __current(__l); 70 return MB_CUR_MAX; 71 #endif 72 } 73 74 wint_t __btowc(int c, __locale_t loc) { 75 __locale_guard __current(loc); 76 return std::btowc(c); 77 } 78 79 int __wctob(wint_t c, __locale_t loc) { 80 __locale_guard __current(loc); 81 return std::wctob(c); 82 } 83 84 size_t __wcsnrtombs(char* __restrict dst, 85 const wchar_t** __restrict src, 86 size_t nwc, 87 size_t len, 88 mbstate_t* __restrict ps, 89 __locale_t loc) { 90 __locale_guard __current(loc); 91 return ::wcsnrtombs(dst, src, nwc, len, ps); 92 } 93 94 size_t __wcrtomb(char* __restrict s, wchar_t wc, mbstate_t* __restrict ps, __locale_t loc) { 95 __locale_guard __current(loc); 96 return std::wcrtomb(s, wc, ps); 97 } 98 99 size_t __mbsnrtowcs(wchar_t* __restrict dst, 100 const char** __restrict src, 101 size_t nms, 102 size_t len, 103 mbstate_t* __restrict ps, 104 __locale_t loc) { 105 __locale_guard __current(loc); 106 return ::mbsnrtowcs(dst, src, nms, len, ps); 107 } 108 109 size_t 110 __mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps, __locale_t loc) { 111 __locale_guard __current(loc); 112 return std::mbrtowc(pwc, s, n, ps); 113 } 114 115 size_t __mbrlen(const char* __restrict s, size_t n, mbstate_t* __restrict ps, __locale_t loc) { 116 __locale_guard __current(loc); 117 return std::mbrlen(s, n, ps); 118 } 119 120 size_t __mbsrtowcs( 121 wchar_t* __restrict dst, const char** __restrict src, size_t len, mbstate_t* __restrict ps, __locale_t loc) { 122 __locale_guard __current(loc); 123 return std::mbsrtowcs(dst, src, len, ps); 124 } 125 126 int __snprintf(char* ret, size_t n, __locale_t loc, const char* format, ...) { 127 va_list ap; 128 va_start(ap, format); 129 #if defined(_LIBCPP_MSVCRT) 130 // FIXME: Remove usage of internal CRT function and globals. 131 int result = ::__stdio_common_vsprintf( 132 _CRT_INTERNAL_LOCAL_PRINTF_OPTIONS | _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR, ret, n, format, loc, ap); 133 #else 134 __locale_guard __current(loc); 135 _LIBCPP_DIAGNOSTIC_PUSH 136 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") 137 int result = std::vsnprintf(ret, n, format, ap); 138 _LIBCPP_DIAGNOSTIC_POP 139 #endif 140 va_end(ap); 141 return result; 142 } 143 144 // Like sprintf, but when return value >= 0 it returns 145 // a pointer to a malloc'd string in *sptr. 146 // If return >= 0, use free to delete *sptr. 147 int __libcpp_vasprintf(char** sptr, const char* __restrict format, va_list ap) { 148 *sptr = nullptr; 149 // Query the count required. 150 va_list ap_copy; 151 va_copy(ap_copy, ap); 152 _LIBCPP_DIAGNOSTIC_PUSH 153 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") 154 int count = vsnprintf(nullptr, 0, format, ap_copy); 155 _LIBCPP_DIAGNOSTIC_POP 156 va_end(ap_copy); 157 if (count < 0) 158 return count; 159 size_t buffer_size = static_cast<size_t>(count) + 1; 160 char* p = static_cast<char*>(malloc(buffer_size)); 161 if (!p) 162 return -1; 163 // If we haven't used exactly what was required, something is wrong. 164 // Maybe bug in vsnprintf. Report the error and return. 165 _LIBCPP_DIAGNOSTIC_PUSH 166 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") 167 if (vsnprintf(p, buffer_size, format, ap) != count) { 168 _LIBCPP_DIAGNOSTIC_POP 169 free(p); 170 return -1; 171 } 172 // All good. This is returning memory to the caller not freeing it. 173 *sptr = p; 174 return count; 175 } 176 177 int __asprintf(char** ret, __locale_t loc, const char* format, ...) { 178 va_list ap; 179 va_start(ap, format); 180 __locale_guard __current(loc); 181 return __libcpp_vasprintf(ret, format, ap); 182 } 183 184 } // namespace __locale 185 _LIBCPP_END_NAMESPACE_STD 186