xref: /freebsd/contrib/llvm-project/libcxx/include/__locale_dir/locale_base_api/ibm.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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