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_aix.h>
14#include <__support/ibm/locale_mgmt_zos.h>
15#include <stdarg.h>
16
17#include "cstdlib"
18
19#ifdef __cplusplus
20extern "C" {
21#endif
22
23#if defined(_AIX)
24#if !defined(_AIX71)
25// AIX 7.1 and higher has these definitions.  Definitions and stubs
26// are provied here as a temporary workaround on AIX 6.1.
27static inline
28int isalnum_l(int c, locale_t locale)
29{
30  return __xisalnum(locale, c);
31}
32static inline
33int isalpha_l(int c, locale_t locale)
34{
35  return __xisalpha(locale, c);
36}
37static inline
38int isblank_l(int c, locale_t locale)
39{
40  return __xisblank(locale, c);
41}
42static inline
43int iscntrl_l(int c, locale_t locale)
44{
45  return __xiscntrl(locale, c);
46}
47static inline
48int isdigit_l(int c, locale_t locale)
49{
50  return __xisdigit(locale, c);
51}
52static inline
53int isgraph_l(int c, locale_t locale)
54{
55  return __xisgraph(locale, c);
56}
57static inline
58int islower_l(int c, locale_t locale)
59{
60  return __xislower(locale, c);
61}
62static inline
63int isprint_l(int c, locale_t locale)
64{
65  return __xisprint(locale, c);
66}
67
68static inline
69int ispunct_l(int c, locale_t locale)
70{
71  return __xispunct(locale, c);
72}
73static inline
74int isspace_l(int c, locale_t locale)
75{
76  return __xisspace(locale, c);
77}
78static inline
79int isupper_l(int c, locale_t locale)
80{
81  return __xisupper(locale, c);
82}
83
84static inline
85int isxdigit_l(int c, locale_t locale)
86{
87  return __xisxdigit(locale, c);
88}
89
90static inline
91int iswalnum_l(wchar_t wc, locale_t locale)
92{
93  return __xiswalnum(locale, wc);
94}
95
96static inline
97int iswalpha_l(wchar_t wc, locale_t locale)
98{
99  return __xiswalpha(locale, wc);
100}
101
102static inline
103int iswblank_l(wchar_t wc, locale_t locale)
104{
105  return __xiswblank(locale, wc);
106}
107
108static inline
109int iswcntrl_l(wchar_t wc, locale_t locale)
110{
111  return __xiswcntrl(locale, wc);
112}
113
114static inline
115int iswdigit_l(wchar_t wc, locale_t locale)
116{
117  return __xiswdigit(locale, wc);
118}
119
120static inline
121int iswgraph_l(wchar_t wc, locale_t locale)
122{
123  return __xiswgraph(locale, wc);
124}
125
126static inline
127int iswlower_l(wchar_t wc, locale_t locale)
128{
129  return __xiswlower(locale, wc);
130}
131
132static inline
133int iswprint_l(wchar_t wc, locale_t locale)
134{
135  return __xiswprint(locale, wc);
136}
137
138static inline
139int iswpunct_l(wchar_t wc, locale_t locale)
140{
141  return __xiswpunct(locale, wc);
142}
143
144static inline
145int iswspace_l(wchar_t wc, locale_t locale)
146{
147  return __xiswspace(locale, wc);
148}
149
150static inline
151int iswupper_l(wchar_t wc, locale_t locale)
152{
153  return __xiswupper(locale, wc);
154}
155
156static inline
157int iswxdigit_l(wchar_t wc, locale_t locale)
158{
159  return __xiswxdigit(locale, wc);
160}
161
162static inline
163int iswctype_l(wint_t wc, wctype_t desc, locale_t locale)
164{
165  return __xiswctype(locale, wc, desc);
166}
167
168static inline
169int toupper_l(int c, locale_t locale)
170{
171  return __xtoupper(locale, c);
172}
173static inline
174int tolower_l(int c, locale_t locale)
175{
176  return __xtolower(locale, c);
177}
178static inline
179wint_t towupper_l(wint_t wc, locale_t locale)
180{
181  return __xtowupper(locale, wc);
182}
183static inline
184wint_t towlower_l(wint_t wc, locale_t locale)
185{
186  return __xtowlower(locale, wc);
187}
188
189static inline
190int strcoll_l(const char *__s1, const char *__s2, locale_t locale)
191{
192  return __xstrcoll(locale, __s1, __s2);
193}
194static inline
195int wcscoll_l(const wchar_t *__s1, const wchar_t *__s2, locale_t locale)
196{
197  return __xwcscoll(locale, __s1, __s2);
198}
199static inline
200size_t strxfrm_l(char *__s1, const char *__s2, size_t __n, locale_t locale)
201{
202  return __xstrxfrm(locale, __s1, __s2, __n);
203}
204
205static inline
206size_t wcsxfrm_l(wchar_t *__ws1, const wchar_t *__ws2, size_t __n,
207    locale_t locale)
208{
209  return __xwcsxfrm(locale, __ws1, __ws2, __n);
210}
211#endif // !defined(_AIX71)
212
213// strftime_l() is defined by POSIX. However, AIX 7.1 and z/OS do not have it
214// implemented yet. z/OS retrieves it from the POSIX fallbacks.
215#if !defined(_AIX72)
216static inline
217size_t strftime_l(char *__s, size_t __size, const char *__fmt,
218                  const struct tm *__tm, locale_t locale) {
219  return __xstrftime(locale, __s, __size, __fmt, __tm);
220}
221#endif
222
223#elif defined(__MVS__)
224#include <wctype.h>
225// POSIX routines
226#include <__support/xlocale/__posix_l_fallback.h>
227#endif // defined(__MVS__)
228
229namespace {
230
231struct __setAndRestore {
232  explicit __setAndRestore(locale_t locale) {
233    if (locale == (locale_t)0) {
234      __cloc = newlocale(LC_ALL_MASK, "C", /* base */ (locale_t)0);
235      __stored = uselocale(__cloc);
236    } else {
237      __stored = uselocale(locale);
238    }
239  }
240
241  ~__setAndRestore() {
242    uselocale(__stored);
243    if (__cloc)
244      freelocale(__cloc);
245  }
246
247private:
248  locale_t __stored = (locale_t)0;
249  locale_t __cloc = (locale_t)0;
250};
251
252} // namespace
253
254// The following are not POSIX routines.  These are quick-and-dirty hacks
255// to make things pretend to work
256static inline
257long long strtoll_l(const char *__nptr, char **__endptr,
258    int __base, locale_t locale) {
259  __setAndRestore __newloc(locale);
260  return strtoll(__nptr, __endptr, __base);
261}
262
263static inline
264long strtol_l(const char *__nptr, char **__endptr,
265    int __base, locale_t locale) {
266  __setAndRestore __newloc(locale);
267  return strtol(__nptr, __endptr, __base);
268}
269
270static inline
271double strtod_l(const char *__nptr, char **__endptr,
272    locale_t locale) {
273  __setAndRestore __newloc(locale);
274  return strtod(__nptr, __endptr);
275}
276
277static inline
278float strtof_l(const char *__nptr, char **__endptr,
279    locale_t locale) {
280  __setAndRestore __newloc(locale);
281  return strtof(__nptr, __endptr);
282}
283
284static inline
285long double strtold_l(const char *__nptr, char **__endptr,
286    locale_t locale) {
287  __setAndRestore __newloc(locale);
288  return strtold(__nptr, __endptr);
289}
290
291static inline
292unsigned long long strtoull_l(const char *__nptr, char **__endptr,
293    int __base, locale_t locale) {
294  __setAndRestore __newloc(locale);
295  return strtoull(__nptr, __endptr, __base);
296}
297
298static inline
299unsigned long strtoul_l(const char *__nptr, char **__endptr,
300    int __base, locale_t locale) {
301  __setAndRestore __newloc(locale);
302  return strtoul(__nptr, __endptr, __base);
303}
304
305static inline
306int vasprintf(char **strp, const char *fmt, va_list ap) {
307  const size_t buff_size = 256;
308  if ((*strp = (char *)malloc(buff_size)) == NULL) {
309    return -1;
310  }
311
312  va_list ap_copy;
313  va_copy(ap_copy, ap);
314  int str_size = vsnprintf(*strp, buff_size, fmt,  ap_copy);
315  va_end(ap_copy);
316
317  if ((size_t) str_size >= buff_size) {
318    if ((*strp = (char *)realloc(*strp, str_size + 1)) == NULL) {
319      return -1;
320    }
321    str_size = vsnprintf(*strp, str_size + 1, fmt,  ap);
322  }
323  return str_size;
324}
325
326#ifdef __cplusplus
327}
328#endif
329#endif // _LIBCPP_SUPPORT_IBM_XLOCALE_H
330