Support newlib as libc++'s C library [locale part]
http://reviews.llvm.org/D5385 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@218144 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -193,6 +193,11 @@ template <class charT> class messages_byname;
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
|
#if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
|
||||||
#include <support/win32/locale_win32.h>
|
#include <support/win32/locale_win32.h>
|
||||||
|
#elif defined(_NEWLIB_VERSION)
|
||||||
|
// FIXME: replace all the uses of _NEWLIB_VERSION with __NEWLIB__ preceded by an
|
||||||
|
// include of <sys/cdefs.h> once https://sourceware.org/ml/newlib-cvs/2014-q3/msg00038.html
|
||||||
|
// has had a chance to bake for a bit
|
||||||
|
#include <support/newlib/xlocale.h>
|
||||||
#elif !defined(__ANDROID__)
|
#elif !defined(__ANDROID__)
|
||||||
#include <nl_types.h>
|
#include <nl_types.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -229,7 +234,8 @@ typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
|
|||||||
// OSX has nice foo_l() functions that let you turn off use of the global
|
// OSX has nice foo_l() functions that let you turn off use of the global
|
||||||
// locale. Linux, not so much. The following functions avoid the locale when
|
// locale. Linux, not so much. The following functions avoid the locale when
|
||||||
// that's possible and otherwise do the wrong thing. FIXME.
|
// that's possible and otherwise do the wrong thing. FIXME.
|
||||||
#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(_AIX)
|
#if defined(__linux__) || defined(__EMSCRIPTEN__) || defined(_AIX) || \
|
||||||
|
defined(_NEWLIB_VERSION)
|
||||||
|
|
||||||
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
|
#ifdef _LIBCPP_LOCALE__L_EXTENSIONS
|
||||||
decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
|
decltype(MB_CUR_MAX_L(_VSTD::declval<locale_t>()))
|
||||||
@@ -3673,7 +3679,7 @@ template <class _CharT>
|
|||||||
typename messages<_CharT>::catalog
|
typename messages<_CharT>::catalog
|
||||||
messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
|
messages<_CharT>::do_open(const basic_string<char>& __nm, const locale&) const
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(__ANDROID__)
|
#if defined(_WIN32) || defined(__ANDROID__) || defined(_NEWLIB_VERSION)
|
||||||
return -1;
|
return -1;
|
||||||
#else // _WIN32 || __ANDROID__
|
#else // _WIN32 || __ANDROID__
|
||||||
catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
|
catalog __cat = (catalog)catopen(__nm.c_str(), NL_CAT_LOCALE);
|
||||||
@@ -3688,7 +3694,7 @@ typename messages<_CharT>::string_type
|
|||||||
messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
|
messages<_CharT>::do_get(catalog __c, int __set, int __msgid,
|
||||||
const string_type& __dflt) const
|
const string_type& __dflt) const
|
||||||
{
|
{
|
||||||
#if defined(_WIN32) || defined(__ANDROID__)
|
#if defined(_WIN32) || defined(__ANDROID__) || defined(_NEWLIB_VERSION)
|
||||||
return __dflt;
|
return __dflt;
|
||||||
#else // _WIN32
|
#else // _WIN32
|
||||||
string __ndflt;
|
string __ndflt;
|
||||||
@@ -3710,7 +3716,7 @@ template <class _CharT>
|
|||||||
void
|
void
|
||||||
messages<_CharT>::do_close(catalog __c) const
|
messages<_CharT>::do_close(catalog __c) const
|
||||||
{
|
{
|
||||||
#if !defined(_WIN32) && !defined(__ANDROID__)
|
#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(_NEWLIB_VERSION)
|
||||||
if (__c != -1)
|
if (__c != -1)
|
||||||
__c <<= 1;
|
__c <<= 1;
|
||||||
nl_catd __cat = (nl_catd)__c;
|
nl_catd __cat = (nl_catd)__c;
|
||||||
|
@@ -20,173 +20,12 @@ extern "C" {
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <xlocale.h>
|
#include <xlocale.h>
|
||||||
|
|
||||||
static inline int isalnum_l(int c, locale_t) {
|
|
||||||
return isalnum(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isalpha_l(int c, locale_t) {
|
|
||||||
return isalpha(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isblank_l(int c, locale_t) {
|
|
||||||
return isblank(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iscntrl_l(int c, locale_t) {
|
|
||||||
return iscntrl(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isdigit_l(int c, locale_t) {
|
|
||||||
return isdigit(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isgraph_l(int c, locale_t) {
|
|
||||||
return isgraph(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int islower_l(int c, locale_t) {
|
|
||||||
return islower(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isprint_l(int c, locale_t) {
|
|
||||||
return isprint(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int ispunct_l(int c, locale_t) {
|
|
||||||
return ispunct(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isspace_l(int c, locale_t) {
|
|
||||||
return isspace(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isupper_l(int c, locale_t) {
|
|
||||||
return isupper(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int isxdigit_l(int c, locale_t) {
|
|
||||||
return isxdigit(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswalnum_l(wint_t c, locale_t) {
|
|
||||||
return iswalnum(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswalpha_l(wint_t c, locale_t) {
|
|
||||||
return iswalpha(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswblank_l(wint_t c, locale_t) {
|
|
||||||
return iswblank(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswcntrl_l(wint_t c, locale_t) {
|
|
||||||
return iswcntrl(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswdigit_l(wint_t c, locale_t) {
|
|
||||||
return iswdigit(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswgraph_l(wint_t c, locale_t) {
|
|
||||||
return iswgraph(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswlower_l(wint_t c, locale_t) {
|
|
||||||
return iswlower(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswprint_l(wint_t c, locale_t) {
|
|
||||||
return iswprint(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswpunct_l(wint_t c, locale_t) {
|
|
||||||
return iswpunct(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswspace_l(wint_t c, locale_t) {
|
|
||||||
return iswspace(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswupper_l(wint_t c, locale_t) {
|
|
||||||
return iswupper(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int iswxdigit_l(wint_t c, locale_t) {
|
|
||||||
return iswxdigit(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int toupper_l(int c, locale_t) {
|
|
||||||
return toupper(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int tolower_l(int c, locale_t) {
|
|
||||||
return tolower(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int towupper_l(int c, locale_t) {
|
|
||||||
return towupper(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int towlower_l(int c, locale_t) {
|
|
||||||
return towlower(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int strcoll_l(const char *s1, const char *s2, locale_t) {
|
|
||||||
return strcoll(s1, s2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t strxfrm_l(char *dest, const char *src, size_t n,
|
|
||||||
locale_t) {
|
|
||||||
return strxfrm(dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t strftime_l(char *s, size_t max, const char *format,
|
|
||||||
const struct tm *tm, locale_t) {
|
|
||||||
return strftime(s, max, format, tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
|
|
||||||
return wcscoll(ws1, ws2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n,
|
|
||||||
locale_t) {
|
|
||||||
return wcsxfrm(dest, src, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long double strtold_l(const char *nptr, char **endptr, locale_t) {
|
|
||||||
return strtold(nptr, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long long strtoll_l(const char *nptr, char **endptr, size_t base,
|
|
||||||
locale_t) {
|
|
||||||
return strtoll(nptr, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned long long strtoull_l(const char *nptr, char **endptr,
|
|
||||||
size_t base, locale_t) {
|
|
||||||
return strtoull(nptr, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr,
|
|
||||||
size_t base, locale_t) {
|
|
||||||
return wcstoll(nptr, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned long long wcstoull_l(const wchar_t *nptr,
|
|
||||||
wchar_t **endptr, size_t base,
|
|
||||||
locale_t) {
|
|
||||||
return wcstoull(nptr, endptr, base);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline long double wcstold_l(const wchar_t *nptr, wchar_t **endptr,
|
|
||||||
locale_t) {
|
|
||||||
return wcstold(nptr, endptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Share implementation with Newlib
|
||||||
|
#include <support/xlocale/xlocale.h>
|
||||||
|
|
||||||
#endif // defined(__ANDROID__)
|
#endif // defined(__ANDROID__)
|
||||||
#endif // _LIBCPP_SUPPORT_ANDROID_LOCALE_BIONIC_H
|
#endif // _LIBCPP_SUPPORT_ANDROID_LOCALE_BIONIC_H
|
||||||
|
63
include/support/newlib/xlocale.h
Normal file
63
include/support/newlib/xlocale.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_SUPPORT_NEWLIB_XLOCALE_H
|
||||||
|
#define _LIBCPP_SUPPORT_NEWLIB_XLOCALE_H
|
||||||
|
|
||||||
|
#if defined(_NEWLIB_VERSION)
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <clocale>
|
||||||
|
#include <cwctype>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Patch over newlib's lack of extended locale support
|
||||||
|
typedef void *locale_t;
|
||||||
|
static inline locale_t duplocale(locale_t) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void freelocale(locale_t) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline locale_t newlocale(int, const char *, locale_t) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline locale_t uselocale(locale_t) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LC_COLLATE_MASK (1 << LC_COLLATE)
|
||||||
|
#define LC_CTYPE_MASK (1 << LC_CTYPE)
|
||||||
|
#define LC_MESSAGES_MASK (1 << LC_MESSAGES)
|
||||||
|
#define LC_MONETARY_MASK (1 << LC_MONETARY)
|
||||||
|
#define LC_NUMERIC_MASK (1 << LC_NUMERIC)
|
||||||
|
#define LC_TIME_MASK (1 << LC_TIME)
|
||||||
|
#define LC_ALL_MASK (LC_COLLATE_MASK|\
|
||||||
|
LC_CTYPE_MASK|\
|
||||||
|
LC_MONETARY_MASK|\
|
||||||
|
LC_NUMERIC_MASK|\
|
||||||
|
LC_TIME_MASK|\
|
||||||
|
LC_MESSAGES_MASK)
|
||||||
|
|
||||||
|
// Share implementation with Android's Bionic
|
||||||
|
#include <support/xlocale/xlocale.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _NEWLIB_VERSION
|
||||||
|
|
||||||
|
#endif
|
194
include/support/xlocale/xlocale.h
Normal file
194
include/support/xlocale/xlocale.h
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===------------------- support/xlocale/xlocale.h ------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// This is a shared implementation of a shim to provide extended locale support
|
||||||
|
// on top of libc's that don't support it (like Android's bionic, and Newlib).
|
||||||
|
//
|
||||||
|
// The 'illusion' only works when the specified locale is "C" or "POSIX", but
|
||||||
|
// that's about as good as we can do without implementing full xlocale support
|
||||||
|
// in the underlying libc.
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_SUPPORT_XLOCALE_XLOCALE_H
|
||||||
|
#define _LIBCPP_SUPPORT_XLOCALE_XLOCALE_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline int isalnum_l(int c, locale_t) {
|
||||||
|
return isalnum(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isalpha_l(int c, locale_t) {
|
||||||
|
return isalpha(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isblank_l(int c, locale_t) {
|
||||||
|
return isblank(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iscntrl_l(int c, locale_t) {
|
||||||
|
return iscntrl(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isdigit_l(int c, locale_t) {
|
||||||
|
return isdigit(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isgraph_l(int c, locale_t) {
|
||||||
|
return isgraph(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int islower_l(int c, locale_t) {
|
||||||
|
return islower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isprint_l(int c, locale_t) {
|
||||||
|
return isprint(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ispunct_l(int c, locale_t) {
|
||||||
|
return ispunct(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isspace_l(int c, locale_t) {
|
||||||
|
return isspace(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isupper_l(int c, locale_t) {
|
||||||
|
return isupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int isxdigit_l(int c, locale_t) {
|
||||||
|
return isxdigit(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswalnum_l(wint_t c, locale_t) {
|
||||||
|
return iswalnum(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswalpha_l(wint_t c, locale_t) {
|
||||||
|
return iswalpha(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswblank_l(wint_t c, locale_t) {
|
||||||
|
return iswblank(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswcntrl_l(wint_t c, locale_t) {
|
||||||
|
return iswcntrl(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswdigit_l(wint_t c, locale_t) {
|
||||||
|
return iswdigit(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswgraph_l(wint_t c, locale_t) {
|
||||||
|
return iswgraph(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswlower_l(wint_t c, locale_t) {
|
||||||
|
return iswlower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswprint_l(wint_t c, locale_t) {
|
||||||
|
return iswprint(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswpunct_l(wint_t c, locale_t) {
|
||||||
|
return iswpunct(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswspace_l(wint_t c, locale_t) {
|
||||||
|
return iswspace(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswupper_l(wint_t c, locale_t) {
|
||||||
|
return iswupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int iswxdigit_l(wint_t c, locale_t) {
|
||||||
|
return iswxdigit(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int toupper_l(int c, locale_t) {
|
||||||
|
return toupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int tolower_l(int c, locale_t) {
|
||||||
|
return tolower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int towupper_l(int c, locale_t) {
|
||||||
|
return towupper(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int towlower_l(int c, locale_t) {
|
||||||
|
return towlower(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int strcoll_l(const char *s1, const char *s2, locale_t) {
|
||||||
|
return strcoll(s1, s2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t strxfrm_l(char *dest, const char *src, size_t n,
|
||||||
|
locale_t) {
|
||||||
|
return strxfrm(dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t strftime_l(char *s, size_t max, const char *format,
|
||||||
|
const struct tm *tm, locale_t) {
|
||||||
|
return strftime(s, max, format, tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t) {
|
||||||
|
return wcscoll(ws1, ws2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t wcsxfrm_l(wchar_t *dest, const wchar_t *src, size_t n,
|
||||||
|
locale_t) {
|
||||||
|
return wcsxfrm(dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long double strtold_l(const char *nptr, char **endptr, locale_t) {
|
||||||
|
return strtold(nptr, endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long long strtoll_l(const char *nptr, char **endptr, int base,
|
||||||
|
locale_t) {
|
||||||
|
return strtoll(nptr, endptr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long long strtoull_l(const char *nptr, char **endptr,
|
||||||
|
int base, locale_t) {
|
||||||
|
return strtoull(nptr, endptr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long long wcstoll_l(const wchar_t *nptr, wchar_t **endptr,
|
||||||
|
int base, locale_t) {
|
||||||
|
return wcstoll(nptr, endptr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned long long wcstoull_l(const wchar_t *nptr,
|
||||||
|
wchar_t **endptr, int base,
|
||||||
|
locale_t) {
|
||||||
|
return wcstoull(nptr, endptr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline long double wcstold_l(const wchar_t *nptr, wchar_t **endptr,
|
||||||
|
locale_t) {
|
||||||
|
return wcstold(nptr, endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _LIBCPP_SUPPORT_XLOCALE_XLOCALE_H
|
Reference in New Issue
Block a user