Skip to content

Commit d8bc87a

Browse files
committed
[libc++] Cleanly implement the base locale API for BSD-like platforms
Instead of going through the old locale entry points, define the base localization API for BSD-like platforms (Apple and FreeBSD) from scratch, using <xlocale.h> as a basis. This doesn't actually change how that functionality is implemented, it only avoids going through a maze to do so. This patch also introduces generic headers that can be mixed-and-matched to implement platform support for localization, which is going to be useful because e.g. Windows does provide a few BSD-like functions that it can reuse. This clean new support is implemented in a separate __locale_dir/support directory, which mirrors what we do for the threading support API. Eventually, everything under __locale_dir/locale_base_api will go away. rdar://131476632
1 parent fb90733 commit d8bc87a

File tree

12 files changed

+398
-93
lines changed

12 files changed

+398
-93
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -494,16 +494,20 @@ set(files
494494
__locale
495495
__locale_dir/locale_base_api.h
496496
__locale_dir/locale_base_api/android.h
497-
__locale_dir/locale_base_api/apple.h
498497
__locale_dir/locale_base_api/bsd_locale_defaults.h
499498
__locale_dir/locale_base_api/bsd_locale_fallbacks.h
500-
__locale_dir/locale_base_api/freebsd.h
501499
__locale_dir/locale_base_api/fuchsia.h
502500
__locale_dir/locale_base_api/ibm.h
503501
__locale_dir/locale_base_api/musl.h
504502
__locale_dir/locale_base_api/openbsd.h
505503
__locale_dir/locale_base_api/win32.h
506504
__locale_dir/locale_guard.h
505+
__locale_dir/support/apple.h
506+
__locale_dir/support/characters/bsd_like.h
507+
__locale_dir/support/freebsd.h
508+
__locale_dir/support/management/bsd_like.h
509+
__locale_dir/support/other/bsd_like.h
510+
__locale_dir/support/strtonum/bsd_like.h
507511
__math/abs.h
508512
__math/copysign.h
509513
__math/error_functions.h

libcxx/include/__locale_dir/locale_base_api.h

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -94,52 +94,54 @@
9494
// int __sscanf(const char*, __locale_t, const char*, ...);
9595
// }
9696

97+
#if defined(__APPLE__)
98+
# include <__locale_dir/support/apple.h>
99+
#elif defined(__FreeBSD__)
100+
# include <__locale_dir/support/freebsd.h>
101+
#else
102+
97103
// TODO: This is a temporary definition to bridge between the old way we defined the locale base API
98104
// (by providing global non-reserved names) and the new API. As we move individual platforms
99105
// towards the new way of defining the locale base API, this should disappear since each platform
100106
// will define those directly.
101-
#if defined(_LIBCPP_MSVCRT_LIKE)
102-
# include <__locale_dir/locale_base_api/win32.h>
103-
#elif defined(_AIX) || defined(__MVS__)
104-
# include <__locale_dir/locale_base_api/ibm.h>
105-
#elif defined(__ANDROID__)
106-
# include <__locale_dir/locale_base_api/android.h>
107-
#elif defined(__OpenBSD__)
108-
# include <__locale_dir/locale_base_api/openbsd.h>
109-
#elif defined(__Fuchsia__)
110-
# include <__locale_dir/locale_base_api/fuchsia.h>
111-
#elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC
112-
# include <__locale_dir/locale_base_api/musl.h>
113-
#elif defined(__APPLE__)
114-
# include <__locale_dir/locale_base_api/apple.h>
115-
#elif defined(__FreeBSD__)
116-
# include <__locale_dir/locale_base_api/freebsd.h>
117-
#endif
107+
# if defined(_LIBCPP_MSVCRT_LIKE)
108+
# include <__locale_dir/locale_base_api/win32.h>
109+
# elif defined(_AIX) || defined(__MVS__)
110+
# include <__locale_dir/locale_base_api/ibm.h>
111+
# elif defined(__ANDROID__)
112+
# include <__locale_dir/locale_base_api/android.h>
113+
# elif defined(__OpenBSD__)
114+
# include <__locale_dir/locale_base_api/openbsd.h>
115+
# elif defined(__Fuchsia__)
116+
# include <__locale_dir/locale_base_api/fuchsia.h>
117+
# elif defined(__wasi__) || _LIBCPP_HAS_MUSL_LIBC
118+
# include <__locale_dir/locale_base_api/musl.h>
119+
# endif
118120

119-
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
120-
# include <__locale_dir/locale_base_api/bsd_locale_defaults.h>
121-
#else
122-
# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
123-
#endif
121+
# ifdef _LIBCPP_LOCALE__L_EXTENSIONS
122+
# include <__locale_dir/locale_base_api/bsd_locale_defaults.h>
123+
# else
124+
# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
125+
# endif
124126

125-
#include <__cstddef/size_t.h>
126-
#include <__utility/forward.h>
127-
#include <ctype.h>
128-
#include <string.h>
129-
#include <time.h>
130-
#if _LIBCPP_HAS_WIDE_CHARACTERS
131-
# include <wctype.h>
132-
#endif
127+
# include <__cstddef/size_t.h>
128+
# include <__utility/forward.h>
129+
# include <ctype.h>
130+
# include <string.h>
131+
# include <time.h>
132+
# if _LIBCPP_HAS_WIDE_CHARACTERS
133+
# include <wctype.h>
134+
# endif
133135
_LIBCPP_BEGIN_NAMESPACE_STD
134136
namespace __locale {
135137
//
136138
// Locale management
137139
//
138140
using __locale_t = locale_t;
139141

140-
#ifndef _LIBCPP_MSVCRT_LIKE
142+
# ifndef _LIBCPP_MSVCRT_LIKE
141143
inline _LIBCPP_HIDE_FROM_ABI __locale_t __uselocale(__locale_t __loc) { return uselocale(__loc); }
142-
#endif
144+
# endif
143145

144146
inline _LIBCPP_HIDE_FROM_ABI __locale_t __newlocale(int __category_mask, const char* __name, __locale_t __loc) {
145147
return newlocale(__category_mask, __name, __loc);
@@ -189,7 +191,7 @@ inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, s
189191
inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __ch, __locale_t __loc) { return toupper_l(__ch, __loc); }
190192
inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __ch, __locale_t __loc) { return tolower_l(__ch, __loc); }
191193

192-
#if _LIBCPP_HAS_WIDE_CHARACTERS
194+
# if _LIBCPP_HAS_WIDE_CHARACTERS
193195
inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __s1, const wchar_t* __s2, __locale_t __loc) {
194196
return wcscoll_l(__s1, __s2, __loc);
195197
}
@@ -208,7 +210,7 @@ inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __ch, __locale_t __loc) { ret
208210
inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __ch, __locale_t __loc) { return iswxdigit_l(__ch, __loc); }
209211
inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __ch, __locale_t __loc) { return towupper_l(__ch, __loc); }
210212
inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __ch, __locale_t __loc) { return towlower_l(__ch, __loc); }
211-
#endif
213+
# endif
212214

213215
inline _LIBCPP_HIDE_FROM_ABI size_t
214216
__strftime(char* __s, size_t __max, const char* __format, const tm* __tm, __locale_t __loc) {
@@ -221,7 +223,7 @@ __strftime(char* __s, size_t __max, const char* __format, const tm* __tm, __loca
221223
inline _LIBCPP_HIDE_FROM_ABI decltype(__libcpp_mb_cur_max_l(__locale_t())) __mb_len_max(__locale_t __loc) {
222224
return __libcpp_mb_cur_max_l(__loc);
223225
}
224-
#if _LIBCPP_HAS_WIDE_CHARACTERS
226+
# if _LIBCPP_HAS_WIDE_CHARACTERS
225227
inline _LIBCPP_HIDE_FROM_ABI wint_t __btowc(int __ch, __locale_t __loc) { return __libcpp_btowc_l(__ch, __loc); }
226228
inline _LIBCPP_HIDE_FROM_ABI int __wctob(wint_t __ch, __locale_t __loc) { return __libcpp_wctob_l(__ch, __loc); }
227229
inline _LIBCPP_HIDE_FROM_ABI size_t
@@ -249,16 +251,16 @@ inline _LIBCPP_HIDE_FROM_ABI size_t
249251
__mbsrtowcs(wchar_t* __dest, const char** __src, size_t __len, mbstate_t* __ps, __locale_t __loc) {
250252
return __libcpp_mbsrtowcs_l(__dest, __src, __len, __ps, __loc);
251253
}
252-
#endif
254+
# endif
253255

254256
_LIBCPP_DIAGNOSTIC_PUSH
255257
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgcc-compat")
256258
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wformat-nonliteral") // GCC doesn't support [[gnu::format]] on variadic templates
257-
#ifdef _LIBCPP_COMPILER_CLANG_BASED
258-
# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__)
259-
#else
260-
# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) /* nothing */
261-
#endif
259+
# ifdef _LIBCPP_COMPILER_CLANG_BASED
260+
# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) _LIBCPP_ATTRIBUTE_FORMAT(__VA_ARGS__)
261+
# else
262+
# define _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(...) /* nothing */
263+
# endif
262264

263265
template <class... _Args>
264266
_LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__printf__, 4, 5) int __snprintf(
@@ -276,9 +278,11 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT(__scanf__, 3, 4) int __s
276278
return __libcpp_sscanf_l(__s, __loc, __format, std::forward<_Args>(__args)...);
277279
}
278280
_LIBCPP_DIAGNOSTIC_POP
279-
#undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
281+
# undef _LIBCPP_VARIADIC_ATTRIBUTE_FORMAT
280282

281283
} // namespace __locale
282284
_LIBCPP_END_NAMESPACE_STD
283285

286+
#endif // Compatibility definition of locale base APIs
287+
284288
#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_H

libcxx/include/__locale_dir/locale_base_api/apple.h

Lines changed: 0 additions & 23 deletions
This file was deleted.

libcxx/include/__locale_dir/locale_base_api/freebsd.h

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___LOCALE_DIR_SUPPORT_APPLE_H
10+
#define _LIBCPP___LOCALE_DIR_SUPPORT_APPLE_H
11+
12+
#include <__config>
13+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
#include <__locale_dir/support/management/bsd_like.h> // must come first since it defines __locale_t
19+
20+
#include <__locale_dir/support/characters/bsd_like.h>
21+
#include <__locale_dir/support/other/bsd_like.h>
22+
#include <__locale_dir/support/strtonum/bsd_like.h>
23+
24+
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_APPLE_H
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//===-----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___LOCALE_DIR_SUPPORT_CHARACTERS_BSD_LIKE_H
10+
#define _LIBCPP___LOCALE_DIR_SUPPORT_CHARACTERS_BSD_LIKE_H
11+
12+
#include <__config>
13+
#include <ctype.h>
14+
#include <stdlib.h>
15+
#include <string.h>
16+
#include <time.h>
17+
#if _LIBCPP_HAS_WIDE_CHARACTERS
18+
# include <wchar.h>
19+
# include <wctype.h>
20+
#endif
21+
22+
#include <xlocale.h>
23+
24+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25+
# pragma GCC system_header
26+
#endif
27+
28+
_LIBCPP_BEGIN_NAMESPACE_STD
29+
namespace __locale {
30+
31+
inline _LIBCPP_HIDE_FROM_ABI int __islower(int __c, __locale_t __loc) { return ::islower_l(__c, __loc); }
32+
33+
inline _LIBCPP_HIDE_FROM_ABI int __isupper(int __c, __locale_t __loc) { return ::isupper_l(__c, __loc); }
34+
35+
inline _LIBCPP_HIDE_FROM_ABI int __isdigit(int __c, __locale_t __loc) { return ::isdigit_l(__c, __loc); }
36+
37+
inline _LIBCPP_HIDE_FROM_ABI int __isxdigit(int __c, __locale_t __loc) { return ::isxdigit_l(__c, __loc); }
38+
39+
inline _LIBCPP_HIDE_FROM_ABI int __toupper(int __c, __locale_t __loc) { return ::toupper_l(__c, __loc); }
40+
41+
inline _LIBCPP_HIDE_FROM_ABI int __tolower(int __c, __locale_t __loc) { return ::tolower_l(__c, __loc); }
42+
43+
inline _LIBCPP_HIDE_FROM_ABI int __strcoll(const char* __s1, const char* __s2, __locale_t __loc) {
44+
return ::strcoll_l(__s1, __s2, __loc);
45+
}
46+
47+
inline _LIBCPP_HIDE_FROM_ABI size_t __strxfrm(char* __dest, const char* __src, size_t __n, __locale_t __loc) {
48+
return ::strxfrm_l(__dest, __src, __n, __loc);
49+
}
50+
51+
#if _LIBCPP_HAS_WIDE_CHARACTERS
52+
inline _LIBCPP_HIDE_FROM_ABI int __iswspace(wint_t __c, __locale_t __loc) { return ::iswspace_l(__c, __loc); }
53+
54+
inline _LIBCPP_HIDE_FROM_ABI int __iswprint(wint_t __c, __locale_t __loc) { return ::iswprint_l(__c, __loc); }
55+
56+
inline _LIBCPP_HIDE_FROM_ABI int __iswcntrl(wint_t __c, __locale_t __loc) { return ::iswcntrl_l(__c, __loc); }
57+
58+
inline _LIBCPP_HIDE_FROM_ABI int __iswupper(wint_t __c, __locale_t __loc) { return ::iswupper_l(__c, __loc); }
59+
60+
inline _LIBCPP_HIDE_FROM_ABI int __iswlower(wint_t __c, __locale_t __loc) { return ::iswlower_l(__c, __loc); }
61+
62+
inline _LIBCPP_HIDE_FROM_ABI int __iswalpha(wint_t __c, __locale_t __loc) { return ::iswalpha_l(__c, __loc); }
63+
64+
inline _LIBCPP_HIDE_FROM_ABI int __iswblank(wint_t __c, __locale_t __loc) { return ::iswblank_l(__c, __loc); }
65+
66+
inline _LIBCPP_HIDE_FROM_ABI int __iswdigit(wint_t __c, __locale_t __loc) { return ::iswdigit_l(__c, __loc); }
67+
68+
inline _LIBCPP_HIDE_FROM_ABI int __iswpunct(wint_t __c, __locale_t __loc) { return ::iswpunct_l(__c, __loc); }
69+
70+
inline _LIBCPP_HIDE_FROM_ABI int __iswxdigit(wint_t __c, __locale_t __loc) { return ::iswxdigit_l(__c, __loc); }
71+
72+
inline _LIBCPP_HIDE_FROM_ABI wint_t __towupper(wint_t __c, __locale_t __loc) { return ::towupper_l(__c, __loc); }
73+
74+
inline _LIBCPP_HIDE_FROM_ABI wint_t __towlower(wint_t __c, __locale_t __loc) { return ::towlower_l(__c, __loc); }
75+
76+
inline _LIBCPP_HIDE_FROM_ABI int __wcscoll(const wchar_t* __ws1, const wchar_t* __ws2, __locale_t __loc) {
77+
return ::wcscoll_l(__ws1, __ws2, __loc);
78+
}
79+
80+
inline _LIBCPP_HIDE_FROM_ABI size_t __wcsxfrm(wchar_t* __dest, const wchar_t* __src, size_t __n, __locale_t __loc) {
81+
return ::wcsxfrm_l(__dest, __src, __n, __loc);
82+
}
83+
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
84+
85+
inline _LIBCPP_HIDE_FROM_ABI size_t
86+
__strftime(char* __s, size_t __max, const char* __format, const struct tm* __tm, __locale_t __loc) {
87+
return ::strftime_l(__s, __max, __format, __tm, __loc);
88+
}
89+
90+
} // namespace __locale
91+
_LIBCPP_END_NAMESPACE_STD
92+
93+
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_CHARACTERS_BSD_LIKE_H
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//===-----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___LOCALE_DIR_SUPPORT_FREEBSD_H
10+
#define _LIBCPP___LOCALE_DIR_SUPPORT_FREEBSD_H
11+
12+
#include <__config>
13+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
#include <__locale_dir/support/management/bsd_like.h> // must come first since it defines __locale_t
19+
20+
#include <__locale_dir/support/characters/bsd_like.h>
21+
#include <__locale_dir/support/other/bsd_like.h>
22+
#include <__locale_dir/support/strtonum/bsd_like.h>
23+
24+
#endif // _LIBCPP___LOCALE_DIR_SUPPORT_FREEBSD_H

0 commit comments

Comments
 (0)