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