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_SUPPORT_IBM_XLOCALE_H
11 #define _LIBCPP_SUPPORT_IBM_XLOCALE_H
12
13 #include <__support/ibm/locale_mgmt_zos.h>
14 #include <stdarg.h>
15
16 #include "cstdlib"
17
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21
22 #if defined(__MVS__)
23 #include <wctype.h>
24 // POSIX routines
25 #include <__support/xlocale/__posix_l_fallback.h>
26 #endif // defined(__MVS__)
27
28 namespace {
29
30 struct __setAndRestore {
__setAndRestore__setAndRestore31 explicit __setAndRestore(locale_t locale) {
32 if (locale == (locale_t)0) {
33 __cloc = newlocale(LC_ALL_MASK, "C", /* base */ (locale_t)0);
34 __stored = uselocale(__cloc);
35 } else {
36 __stored = uselocale(locale);
37 }
38 }
39
~__setAndRestore__setAndRestore40 ~__setAndRestore() {
41 uselocale(__stored);
42 if (__cloc)
43 freelocale(__cloc);
44 }
45
46 private:
47 locale_t __stored = (locale_t)0;
48 locale_t __cloc = (locale_t)0;
49 };
50
51 } // namespace
52
53 // The following are not POSIX routines. These are quick-and-dirty hacks
54 // to make things pretend to work
55 static inline
strtoll_l(const char * __nptr,char ** __endptr,int __base,locale_t locale)56 long long strtoll_l(const char *__nptr, char **__endptr,
57 int __base, locale_t locale) {
58 __setAndRestore __newloc(locale);
59 return strtoll(__nptr, __endptr, __base);
60 }
61
62 static inline
strtol_l(const char * __nptr,char ** __endptr,int __base,locale_t locale)63 long strtol_l(const char *__nptr, char **__endptr,
64 int __base, locale_t locale) {
65 __setAndRestore __newloc(locale);
66 return strtol(__nptr, __endptr, __base);
67 }
68
69 static inline
strtod_l(const char * __nptr,char ** __endptr,locale_t locale)70 double strtod_l(const char *__nptr, char **__endptr,
71 locale_t locale) {
72 __setAndRestore __newloc(locale);
73 return strtod(__nptr, __endptr);
74 }
75
76 static inline
strtof_l(const char * __nptr,char ** __endptr,locale_t locale)77 float strtof_l(const char *__nptr, char **__endptr,
78 locale_t locale) {
79 __setAndRestore __newloc(locale);
80 return strtof(__nptr, __endptr);
81 }
82
83 static inline
strtold_l(const char * __nptr,char ** __endptr,locale_t locale)84 long double strtold_l(const char *__nptr, char **__endptr,
85 locale_t locale) {
86 __setAndRestore __newloc(locale);
87 return strtold(__nptr, __endptr);
88 }
89
90 static inline
strtoull_l(const char * __nptr,char ** __endptr,int __base,locale_t locale)91 unsigned long long strtoull_l(const char *__nptr, char **__endptr,
92 int __base, locale_t locale) {
93 __setAndRestore __newloc(locale);
94 return strtoull(__nptr, __endptr, __base);
95 }
96
97 static inline
strtoul_l(const char * __nptr,char ** __endptr,int __base,locale_t locale)98 unsigned long strtoul_l(const char *__nptr, char **__endptr,
99 int __base, locale_t locale) {
100 __setAndRestore __newloc(locale);
101 return strtoul(__nptr, __endptr, __base);
102 }
103
104 static inline
vasprintf(char ** strp,const char * fmt,va_list ap)105 int vasprintf(char **strp, const char *fmt, va_list ap) {
106 const size_t buff_size = 256;
107 if ((*strp = (char *)malloc(buff_size)) == NULL) {
108 return -1;
109 }
110
111 va_list ap_copy;
112 // va_copy may not be provided by the C library in C++ 03 mode.
113 #if defined(_LIBCPP_CXX03_LANG) && __has_builtin(__builtin_va_copy)
114 __builtin_va_copy(ap_copy, ap);
115 #else
116 va_copy(ap_copy, ap);
117 #endif
118 int str_size = vsnprintf(*strp, buff_size, fmt, ap_copy);
119 va_end(ap_copy);
120
121 if ((size_t) str_size >= buff_size) {
122 if ((*strp = (char *)realloc(*strp, str_size + 1)) == NULL) {
123 return -1;
124 }
125 str_size = vsnprintf(*strp, str_size + 1, fmt, ap);
126 }
127 return str_size;
128 }
129
130 #ifdef __cplusplus
131 }
132 #endif
133 #endif // _LIBCPP_SUPPORT_IBM_XLOCALE_H
134