1 // -*- C++ -*-
2 //===-----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef _LIBCPP___LOCALE_LOCALE_BASE_API_IBM_H
11 #define _LIBCPP___LOCALE_LOCALE_BASE_API_IBM_H
12
13 #if defined(__MVS__)
14 # include <__support/ibm/locale_mgmt_zos.h>
15 #endif // defined(__MVS__)
16
17 #include <locale.h>
18 #include <stdarg.h>
19 #include <stdio.h>
20
21 #include "cstdlib"
22
23 #if defined(__MVS__)
24 # include <wctype.h>
25 // POSIX routines
26 # include <__support/xlocale/__posix_l_fallback.h>
27 #endif // defined(__MVS__)
28
29 namespace {
30
31 struct __setAndRestore {
__setAndRestore__setAndRestore32 explicit __setAndRestore(locale_t locale) {
33 if (locale == (locale_t)0) {
34 __cloc = newlocale(LC_ALL_MASK, "C", /* base */ (locale_t)0);
35 __stored = uselocale(__cloc);
36 } else {
37 __stored = uselocale(locale);
38 }
39 }
40
~__setAndRestore__setAndRestore41 ~__setAndRestore() {
42 uselocale(__stored);
43 if (__cloc)
44 freelocale(__cloc);
45 }
46
47 private:
48 locale_t __stored = (locale_t)0;
49 locale_t __cloc = (locale_t)0;
50 };
51
52 } // namespace
53
54 // The following are not POSIX routines. These are quick-and-dirty hacks
55 // to make things pretend to work
strtoll_l(const char * __nptr,char ** __endptr,int __base,locale_t locale)56 inline _LIBCPP_HIDE_FROM_ABI long long strtoll_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
57 __setAndRestore __newloc(locale);
58 return ::strtoll(__nptr, __endptr, __base);
59 }
60
strtod_l(const char * __nptr,char ** __endptr,locale_t locale)61 inline _LIBCPP_HIDE_FROM_ABI double strtod_l(const char* __nptr, char** __endptr, locale_t locale) {
62 __setAndRestore __newloc(locale);
63 return ::strtod(__nptr, __endptr);
64 }
65
strtof_l(const char * __nptr,char ** __endptr,locale_t locale)66 inline _LIBCPP_HIDE_FROM_ABI float strtof_l(const char* __nptr, char** __endptr, locale_t locale) {
67 __setAndRestore __newloc(locale);
68 return ::strtof(__nptr, __endptr);
69 }
70
strtold_l(const char * __nptr,char ** __endptr,locale_t locale)71 inline _LIBCPP_HIDE_FROM_ABI long double strtold_l(const char* __nptr, char** __endptr, locale_t locale) {
72 __setAndRestore __newloc(locale);
73 return ::strtold(__nptr, __endptr);
74 }
75
76 inline _LIBCPP_HIDE_FROM_ABI unsigned long long
strtoull_l(const char * __nptr,char ** __endptr,int __base,locale_t locale)77 strtoull_l(const char* __nptr, char** __endptr, int __base, locale_t locale) {
78 __setAndRestore __newloc(locale);
79 return ::strtoull(__nptr, __endptr, __base);
80 }
81
82 inline _LIBCPP_HIDE_FROM_ABI
vasprintf(char ** strp,const char * fmt,va_list ap)83 _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 2, 0) int vasprintf(char** strp, const char* fmt, va_list ap) {
84 const size_t buff_size = 256;
85 if ((*strp = (char*)malloc(buff_size)) == NULL) {
86 return -1;
87 }
88
89 va_list ap_copy;
90 // va_copy may not be provided by the C library in C++03 mode.
91 #if defined(_LIBCPP_CXX03_LANG) && __has_builtin(__builtin_va_copy)
92 __builtin_va_copy(ap_copy, ap);
93 #else
94 va_copy(ap_copy, ap);
95 #endif
96 int str_size = vsnprintf(*strp, buff_size, fmt, ap_copy);
97 va_end(ap_copy);
98
99 if ((size_t)str_size >= buff_size) {
100 if ((*strp = (char*)realloc(*strp, str_size + 1)) == NULL) {
101 return -1;
102 }
103 str_size = vsnprintf(*strp, str_size + 1, fmt, ap);
104 }
105 return str_size;
106 }
107
108 #endif // _LIBCPP___LOCALE_LOCALE_BASE_API_IBM_H
109