[libcxx-commits] [libcxx] [zOS] Avoid ambiguous declarations when z/OS libc or wrpper lib adds functionality (PR #133104)
Sean Perry via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Mar 26 10:25:41 PDT 2025
https://github.com/perry-ca updated https://github.com/llvm/llvm-project/pull/133104
>From 5b42f60aedba50a3118344054c390c6b618ca336 Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Wed, 26 Mar 2025 11:05:45 -0400
Subject: [PATCH 1/4] upstream fixes for z/OS
---
.../__locale_dir/locale_base_api/ibm.h | 40 ++++++++++++++-----
libcxx/include/__thread/support/pthread.h | 8 +++-
2 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/__locale_dir/locale_base_api/ibm.h b/libcxx/include/__locale_dir/locale_base_api/ibm.h
index 1d1d15df9f799..9d51043b7ffdb 100644
--- a/libcxx/include/__locale_dir/locale_base_api/ibm.h
+++ b/libcxx/include/__locale_dir/locale_base_api/ibm.h
@@ -22,31 +22,41 @@
#if defined(__MVS__)
# include <wctype.h>
-// POSIX routines
-# include <__support/xlocale/__posix_l_fallback.h>
#endif // defined(__MVS__)
+_LIBCPP_BEGIN_NAMESPACE_STD
+#ifdef __MVS__
+#define _LIBCPP_CLOC std::__c_locale()
+#ifndef _LIBCPP_LC_GLOBAL_LOCALE
+#define _LIBCPP_LC_GLOBAL_LOCALE ((locale_t) -1)
+#endif
+#else
+extern locale_t __cloc();
+#define _LIBCPP_CLOC std::__cloc()
+#endif
+_LIBCPP_END_NAMESPACE_STD
+
+#ifdef __MVS__
+_LIBCPP_BEGIN_NAMESPACE_STD
+#endif
+
namespace {
struct __setAndRestore {
- explicit __setAndRestore(locale_t locale) {
- if (locale == (locale_t)0) {
- __cloc = newlocale(LC_ALL_MASK, "C", /* base */ (locale_t)0);
- __stored = uselocale(__cloc);
+ explicit __setAndRestore(locale_t __l) {
+ if (__l == (locale_t)0) {
+ __stored = std::uselocale(_LIBCPP_CLOC);
} else {
- __stored = uselocale(locale);
+ __stored = std::uselocale(__l);
}
}
~__setAndRestore() {
- uselocale(__stored);
- if (__cloc)
- freelocale(__cloc);
+ std::uselocale(__stored);
}
private:
locale_t __stored = (locale_t)0;
- locale_t __cloc = (locale_t)0;
};
} // namespace
@@ -89,7 +99,11 @@ _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 2, 0) int vasprintf(char** strp, const char
va_list ap_copy;
// va_copy may not be provided by the C library in C++03 mode.
#if defined(_LIBCPP_CXX03_LANG) && __has_builtin(__builtin_va_copy)
+#if defined(__MVS__) && !defined(_VARARG_EXT_)
+ __builtin_zos_va_copy(ap_copy, ap);
+#else
__builtin_va_copy(ap_copy, ap);
+#endif
#else
va_copy(ap_copy, ap);
#endif
@@ -105,4 +119,8 @@ _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 2, 0) int vasprintf(char** strp, const char
return str_size;
}
+#ifdef __MVS__
+_LIBCPP_END_NAMESPACE_STD
+#endif
+
#endif // _LIBCPP___LOCALE_DIR_LOCALE_BASE_API_IBM_H
diff --git a/libcxx/include/__thread/support/pthread.h b/libcxx/include/__thread/support/pthread.h
index 14e92079dadfe..f32dbd7f09253 100644
--- a/libcxx/include/__thread/support/pthread.h
+++ b/libcxx/include/__thread/support/pthread.h
@@ -194,9 +194,15 @@ inline _LIBCPP_HIDE_FROM_ABI int __libcpp_thread_detach(__libcpp_thread_t* __t)
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_yield() { sched_yield(); }
inline _LIBCPP_HIDE_FROM_ABI void __libcpp_thread_sleep_for(const chrono::nanoseconds& __ns) {
+#ifdef __MVS__
+ #define __LIBCPP_NS __ibm::
+#else
+ #define __LIBCPP_NS
+#endif
__libcpp_timespec_t __ts = std::__convert_to_timespec<__libcpp_timespec_t>(__ns);
- while (nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
+ while (__LIBCPP_NS nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
;
+#undef __LIBCPP_NS
}
//
>From 7832978ffeb3ef56ea2227480bdd205192deb558 Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Wed, 26 Mar 2025 11:13:50 -0400
Subject: [PATCH 2/4] make functionlity conform to specs & fix memory leak
---
libcxx/src/support/ibm/xlocale_zos.cpp | 402 +++++++++++++++++++------
1 file changed, 302 insertions(+), 100 deletions(-)
diff --git a/libcxx/src/support/ibm/xlocale_zos.cpp b/libcxx/src/support/ibm/xlocale_zos.cpp
index 136999ec0b02f..fa5fb745df88e 100644
--- a/libcxx/src/support/ibm/xlocale_zos.cpp
+++ b/libcxx/src/support/ibm/xlocale_zos.cpp
@@ -6,125 +6,327 @@
//
//===----------------------------------------------------------------------===//
+#include "include/ibm_xlocale.h"
+
#include <__assert>
-#include <__support/ibm/xlocale.h>
-#include <sstream>
-#include <vector>
+#include <__locale_dir/locale_base_api/ibm.h>
+#include <errno.h>
-#ifdef __cplusplus
-extern "C" {
-#endif // __cplusplus
+_LIBCPP_BEGIN_NAMESPACE_STD
-locale_t newlocale(int category_mask, const char* locale, locale_t base) {
- // Maintain current locale name(s) to restore later.
- std::string current_loc_name(setlocale(LC_ALL, 0));
+#define CategoryList(pair, sep) \
+ pair(LC_COLLATE, lc_collate) sep \
+ pair(LC_CTYPE, lc_ctype) sep \
+ pair(LC_MONETARY, lc_monetary) sep \
+ pair(LC_NUMERIC, lc_numeric) sep \
+ pair(LC_TIME, lc_time) sep \
+ pair(LC_MESSAGES, lc_messages)
+
+// check ids and masks agree
+#define check_ids_and_masks_agree(id, _) \
+ static_assert((1 << id) == id##_MASK, "id and mask do not agree for " #id); \
+ static_assert((1 << id) == _CATMASK(id), "mask does not have expected value for " #id);
+CategoryList(check_ids_and_masks_agree,)
+#undef check_ids_and_masks_agree
+
+// check that LC_ALL_MASK is defined as expected
+#define get_mask(id, _) id##_MASK
+static_assert(LC_ALL_MASK == (CategoryList(get_mask, |)), "LC_ALL_MASK does not have the expected value. Check that its definition includes all supported categories");
+#undef get_mask
+
+
+// initialize c_locale
+#define init_clocale(id, locale_member) "C",
+static locale_struct c_locale = { LC_ALL_MASK, CategoryList(init_clocale, ) };
+#undef init_clocale
- // Check for errors.
- if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == nullptr) {
+static locale_t current_locale = _LIBCPP_LC_GLOBAL_LOCALE;
+
+
+locale_t __c_locale() {
+ return &c_locale;
+}
+
+// locale
+locale_t newlocale(int category_mask, const char* locale, locale_t base) {
+ // start with some basic checks
+ if (! locale) {
errno = EINVAL;
- return (locale_t)0;
- } else {
- for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) {
- if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == nullptr) {
- setlocale(LC_ALL, current_loc_name.c_str());
- errno = EINVAL;
- return (locale_t)0;
- }
- }
+ return (locale_t) 0;
+ }
+ if (category_mask & ~LC_ALL_MASK) {
+ // then there are bits in category_mask that does not correspond
+ // to a valid category
+ errno = EINVAL;
+ return (locale_t) 0;
}
- // Create new locale.
- locale_t newloc = new locale_struct();
+ locale_t new_loc = new locale_struct;
+ int num_locales_not_found = 0;
+
+ if (base && base != _LIBCPP_LC_GLOBAL_LOCALE)
+ *new_loc = *base;
+
+ auto set_for_category = [&](int id, int mask, std::string &setting) {
+ const char *setting_to_apply = nullptr;
+
+ if (category_mask & mask)
+ setting_to_apply = locale;
+ else if (!base)
+ setting_to_apply = "C";
- if (base) {
- if (category_mask != LC_ALL_MASK) {
- // Copy base when it will not be overwritten.
- memcpy(newloc, base, sizeof(locale_struct));
- newloc->category_mask = category_mask | base->category_mask;
+ if (setting_to_apply) {
+ // setlocale takes the id, not the mask
+ const char *saved_setting = setlocale(id, nullptr);
+ if (setlocale(id, setting_to_apply)) {
+ // then setting_to_apply is valid for this category
+ // restore the saved setting
+ setlocale(id, saved_setting);
+
+ new_loc->category_mask |= mask;
+ setting = setting_to_apply;
+ } else {
+ // unknown locale for this category
+ num_locales_not_found++;
+ }
}
- delete base;
- } else {
- newloc->category_mask = category_mask;
+ };
+
+ // now overlay values
+#define Set(id, locale_member) set_for_category(id, id##_MASK, new_loc->locale_member)
+ CategoryList(Set, ;);
+#undef Set
+
+ if (num_locales_not_found != 0) {
+ delete new_loc;
+ errno = ENOENT;
+ new_loc = (locale_t) 0;
}
- if (category_mask & LC_COLLATE_MASK)
- newloc->lc_collate = locale;
- if (category_mask & LC_CTYPE_MASK)
- newloc->lc_ctype = locale;
- if (category_mask & LC_MONETARY_MASK)
- newloc->lc_monetary = locale;
- if (category_mask & LC_NUMERIC_MASK)
- newloc->lc_numeric = locale;
- if (category_mask & LC_TIME_MASK)
- newloc->lc_time = locale;
- if (category_mask & LC_MESSAGES_MASK)
- newloc->lc_messages = locale;
-
- // Restore current locale.
- setlocale(LC_ALL, current_loc_name.c_str());
- return (locale_t)newloc;
-}
-
-void freelocale(locale_t locobj) { delete locobj; }
-
-locale_t uselocale(locale_t newloc) {
- // Maintain current locale name(s).
- std::string current_loc_name(setlocale(LC_ALL, 0));
-
- if (newloc) {
- // Set locales and check for errors.
- bool is_error =
- (newloc->category_mask & LC_COLLATE_MASK && setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == nullptr) ||
- (newloc->category_mask & LC_CTYPE_MASK && setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == nullptr) ||
- (newloc->category_mask & LC_MONETARY_MASK && setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == nullptr) ||
- (newloc->category_mask & LC_NUMERIC_MASK && setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == nullptr) ||
- (newloc->category_mask & LC_TIME_MASK && setlocale(LC_TIME, newloc->lc_time.c_str()) == nullptr) ||
- (newloc->category_mask & LC_MESSAGES_MASK && setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == nullptr);
-
- if (is_error) {
- setlocale(LC_ALL, current_loc_name.c_str());
+ return new_loc;
+}
+
+void freelocale(locale_t locobj) {
+ if (locobj != nullptr && locobj != &c_locale && locobj != _LIBCPP_LC_GLOBAL_LOCALE)
+ delete locobj;
+}
+
+locale_t uselocale(locale_t new_loc) {
+ locale_t prev_loc = current_locale;
+
+ if (new_loc == _LIBCPP_LC_GLOBAL_LOCALE) {
+ current_locale = _LIBCPP_LC_GLOBAL_LOCALE;
+ } else if (new_loc != nullptr) {
+ locale_struct saved_locale;
+ saved_locale.category_mask = 0;
+
+ auto apply_category = [&](int id, int mask, std::string &setting, std::string &save_setting)-> bool {
+ if (new_loc->category_mask & mask) {
+ const char *old_setting = setlocale(id, setting.c_str());
+ if (old_setting) {
+ // we were able to set for this category. Save the old setting
+ // in case a subsequent category fails, and we need to restore
+ // all earlier settings.
+ saved_locale.category_mask |= mask;
+ save_setting = old_setting;
+ return true;
+ }
+ return false;
+ }
+ return true;
+ };
+
+#define Apply(id, locale_member) apply_category(id, id##_MASK, new_loc->locale_member, saved_locale. locale_member)
+ bool is_ok = CategoryList(Apply, &&);
+#undef Apply
+
+ if (!is_ok) {
+ auto restore = [&](int id, int mask, std::string &setting) {
+ if (saved_locale.category_mask & mask)
+ setlocale(id, setting.c_str());
+ };
+#define Restore(id, locale_member) restore(id, id##_MASK, saved_locale. locale_member);
+ CategoryList(Restore,);
+#undef Restore
errno = EINVAL;
- return (locale_t)0;
+ return nullptr;
}
+ current_locale = new_loc;
}
- // Construct and return previous locale.
- locale_t previous_loc = new locale_struct();
+ return prev_loc;
+}
- // current_loc_name might be a comma-separated locale name list.
- if (current_loc_name.find(',') != std::string::npos) {
- // Tokenize locale name list.
- const char delimiter = ',';
- std::vector<std::string> tokenized;
- std::stringstream ss(current_loc_name);
- std::string s;
+int isdigit_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isdigit(__c);
+}
- while (std::getline(ss, s, delimiter)) {
- tokenized.push_back(s);
- }
+int isxdigit_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isxdigit(__c);
+}
- _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(tokenized.size() >= _NCAT, "locale-name list is too short");
-
- previous_loc->lc_collate = tokenized[LC_COLLATE];
- previous_loc->lc_ctype = tokenized[LC_CTYPE];
- previous_loc->lc_monetary = tokenized[LC_MONETARY];
- previous_loc->lc_numeric = tokenized[LC_NUMERIC];
- previous_loc->lc_time = tokenized[LC_TIME];
- // Skip LC_TOD.
- previous_loc->lc_messages = tokenized[LC_MESSAGES];
- } else {
- previous_loc->lc_collate = current_loc_name;
- previous_loc->lc_ctype = current_loc_name;
- previous_loc->lc_monetary = current_loc_name;
- previous_loc->lc_numeric = current_loc_name;
- previous_loc->lc_time = current_loc_name;
- previous_loc->lc_messages = current_loc_name;
- }
+namespace __ibm {
+int isalnum_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isalnum(__c);
+}
+
+int isalpha_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isalpha(__c);
+}
+
+int isblank_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isblank(__c);
+}
+
+int iscntrl_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iscntrl(__c);
+}
+
+int isgraph_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isgraph(__c);
+}
+
+int islower_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::islower(__c);
+}
+
+int isprint_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isprint(__c);
+}
+
+int ispunct_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::ispunct(__c);
+}
+
+int isspace_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isspace(__c);
+}
+
+int isupper_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::isupper(__c);
+}
+
+int iswalnum_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswalnum(__c);
+}
+
+int iswalpha_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswalpha(__c);
+}
+
+int iswblank_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswblank(__c);
+}
+
+int iswcntrl_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswcntrl(__c);
+}
+
+int iswdigit_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswdigit(__c);
+}
+
+int iswgraph_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswgraph(__c);
+}
+
+int iswlower_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswlower(__c);
+}
+
+int iswprint_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswprint(__c);
+}
+
+int iswpunct_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswpunct(__c);
+}
+
+int iswspace_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswspace(__c);
+}
+
+int iswupper_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswupper(__c);
+}
+
+int iswxdigit_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswxdigit(__c);
+}
+
+int toupper_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::toupper(__c);
+}
+
+int tolower_l(int __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::tolower(__c);
+}
+
+wint_t towupper_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::towupper(__c);
+}
+
+wint_t towlower_l(wint_t __c, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::towlower(__c);
+}
+
+int strcoll_l(const char *__s1, const char *__s2, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::strcoll(__s1, __s2);
+}
+
+size_t strxfrm_l(char *__dest, const char *__src, size_t __n, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::strxfrm(__dest, __src, __n);
+}
+
+size_t strftime_l(char *__s, size_t __max, const char *__format, const struct tm *__tm,
+ locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::strftime(__s, __max, __format, __tm);
+}
+
+int wcscoll_l(const wchar_t *__ws1, const wchar_t *__ws2, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::wcscoll(__ws1, __ws2);
+}
- previous_loc->category_mask = LC_ALL_MASK;
- return previous_loc;
+size_t wcsxfrm_l(wchar_t *__dest, const wchar_t *__src, size_t __n, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::wcsxfrm(__dest, __src, __n);
}
-#ifdef __cplusplus
+int iswctype_l(wint_t __c, wctype_t __type, locale_t __l) {
+ __setAndRestore __newloc(__l);
+ return ::iswctype(__c, __type);
}
-#endif // __cplusplus
+} // namespace __ibm
+_LIBCPP_END_NAMESPACE_STD
>From 54ef2e1f20376443ca755bf18200141f27f233eb Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Wed, 26 Mar 2025 13:23:34 -0400
Subject: [PATCH 3/4] formatting
---
libcxx/src/support/ibm/xlocale_zos.cpp | 132 ++++++++++++-------------
1 file changed, 64 insertions(+), 68 deletions(-)
diff --git a/libcxx/src/support/ibm/xlocale_zos.cpp b/libcxx/src/support/ibm/xlocale_zos.cpp
index fa5fb745df88e..c264bff9f45fc 100644
--- a/libcxx/src/support/ibm/xlocale_zos.cpp
+++ b/libcxx/src/support/ibm/xlocale_zos.cpp
@@ -14,61 +14,58 @@
_LIBCPP_BEGIN_NAMESPACE_STD
-#define CategoryList(pair, sep) \
- pair(LC_COLLATE, lc_collate) sep \
- pair(LC_CTYPE, lc_ctype) sep \
- pair(LC_MONETARY, lc_monetary) sep \
- pair(LC_NUMERIC, lc_numeric) sep \
- pair(LC_TIME, lc_time) sep \
- pair(LC_MESSAGES, lc_messages)
+#define CategoryList(pair, sep) \
+ pair(LC_COLLATE, lc_collate) sep pair(LC_CTYPE, lc_ctype) \
+ sep pair(LC_MONETARY, lc_monetary) \
+ sep pair(LC_NUMERIC, lc_numeric) \
+ sep pair(LC_TIME, lc_time) \
+ sep pair(LC_MESSAGES, lc_messages)
// check ids and masks agree
-#define check_ids_and_masks_agree(id, _) \
- static_assert((1 << id) == id##_MASK, "id and mask do not agree for " #id); \
+#define check_ids_and_masks_agree(id, _) \
+ static_assert((1 << id) == id##_MASK, "id and mask do not agree for " #id); \
static_assert((1 << id) == _CATMASK(id), "mask does not have expected value for " #id);
-CategoryList(check_ids_and_masks_agree,)
+CategoryList(check_ids_and_masks_agree, )
#undef check_ids_and_masks_agree
// check that LC_ALL_MASK is defined as expected
#define get_mask(id, _) id##_MASK
-static_assert(LC_ALL_MASK == (CategoryList(get_mask, |)), "LC_ALL_MASK does not have the expected value. Check that its definition includes all supported categories");
+ static_assert(
+ LC_ALL_MASK == (CategoryList(get_mask, |)),
+ "LC_ALL_MASK does not have the expected value. Check that its definition includes all supported categories");
#undef get_mask
-
// initialize c_locale
#define init_clocale(id, locale_member) "C",
-static locale_struct c_locale = { LC_ALL_MASK, CategoryList(init_clocale, ) };
+static locale_struct c_locale = {LC_ALL_MASK, CategoryList(init_clocale, )};
#undef init_clocale
static locale_t current_locale = _LIBCPP_LC_GLOBAL_LOCALE;
-
-locale_t __c_locale() {
- return &c_locale;
-}
+locale_t __c_locale() { return &c_locale; }
// locale
locale_t newlocale(int category_mask, const char* locale, locale_t base) {
// start with some basic checks
- if (! locale) {
+ if (!locale) {
errno = EINVAL;
- return (locale_t) 0;
+ return (locale_t)0;
}
if (category_mask & ~LC_ALL_MASK) {
// then there are bits in category_mask that does not correspond
// to a valid category
errno = EINVAL;
- return (locale_t) 0;
+ return (locale_t)0;
}
- locale_t new_loc = new locale_struct;
+ locale_t new_loc = new locale_struct;
int num_locales_not_found = 0;
if (base && base != _LIBCPP_LC_GLOBAL_LOCALE)
*new_loc = *base;
- auto set_for_category = [&](int id, int mask, std::string &setting) {
- const char *setting_to_apply = nullptr;
+ auto set_for_category = [&](int id, int mask, std::string& setting) {
+ const char* setting_to_apply = nullptr;
if (category_mask & mask)
setting_to_apply = locale;
@@ -77,7 +74,7 @@ locale_t newlocale(int category_mask, const char* locale, locale_t base) {
if (setting_to_apply) {
// setlocale takes the id, not the mask
- const char *saved_setting = setlocale(id, nullptr);
+ const char* saved_setting = setlocale(id, nullptr);
if (setlocale(id, setting_to_apply)) {
// then setting_to_apply is valid for this category
// restore the saved setting
@@ -99,8 +96,8 @@ locale_t newlocale(int category_mask, const char* locale, locale_t base) {
if (num_locales_not_found != 0) {
delete new_loc;
- errno = ENOENT;
- new_loc = (locale_t) 0;
+ errno = ENOENT;
+ new_loc = (locale_t)0;
}
return new_loc;
@@ -117,12 +114,12 @@ locale_t uselocale(locale_t new_loc) {
if (new_loc == _LIBCPP_LC_GLOBAL_LOCALE) {
current_locale = _LIBCPP_LC_GLOBAL_LOCALE;
} else if (new_loc != nullptr) {
- locale_struct saved_locale;
+ locale_struct saved_locale;
saved_locale.category_mask = 0;
- auto apply_category = [&](int id, int mask, std::string &setting, std::string &save_setting)-> bool {
+ auto apply_category = [&](int id, int mask, std::string& setting, std::string& save_setting) -> bool {
if (new_loc->category_mask & mask) {
- const char *old_setting = setlocale(id, setting.c_str());
+ const char* old_setting = setlocale(id, setting.c_str());
if (old_setting) {
// we were able to set for this category. Save the old setting
// in case a subsequent category fails, and we need to restore
@@ -136,17 +133,17 @@ locale_t uselocale(locale_t new_loc) {
return true;
};
-#define Apply(id, locale_member) apply_category(id, id##_MASK, new_loc->locale_member, saved_locale. locale_member)
+#define Apply(id, locale_member) apply_category(id, id##_MASK, new_loc->locale_member, saved_locale.locale_member)
bool is_ok = CategoryList(Apply, &&);
#undef Apply
if (!is_ok) {
- auto restore = [&](int id, int mask, std::string &setting) {
+ auto restore = [&](int id, int mask, std::string& setting) {
if (saved_locale.category_mask & mask)
setlocale(id, setting.c_str());
};
-#define Restore(id, locale_member) restore(id, id##_MASK, saved_locale. locale_member);
- CategoryList(Restore,);
+#define Restore(id, locale_member) restore(id, id##_MASK, saved_locale.locale_member);
+ CategoryList(Restore, );
#undef Restore
errno = EINVAL;
return nullptr;
@@ -157,174 +154,173 @@ locale_t uselocale(locale_t new_loc) {
return prev_loc;
}
-int isdigit_l(int __c, locale_t __l) {
+int isdigit_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isdigit(__c);
}
-int isxdigit_l(int __c, locale_t __l) {
+int isxdigit_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isxdigit(__c);
}
namespace __ibm {
-int isalnum_l(int __c, locale_t __l) {
+int isalnum_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isalnum(__c);
}
-int isalpha_l(int __c, locale_t __l) {
+int isalpha_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isalpha(__c);
}
-int isblank_l(int __c, locale_t __l) {
+int isblank_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isblank(__c);
}
-int iscntrl_l(int __c, locale_t __l) {
+int iscntrl_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iscntrl(__c);
}
-int isgraph_l(int __c, locale_t __l) {
+int isgraph_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isgraph(__c);
}
-int islower_l(int __c, locale_t __l) {
+int islower_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::islower(__c);
}
-int isprint_l(int __c, locale_t __l) {
+int isprint_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isprint(__c);
}
-int ispunct_l(int __c, locale_t __l) {
+int ispunct_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::ispunct(__c);
}
-int isspace_l(int __c, locale_t __l) {
+int isspace_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isspace(__c);
}
-int isupper_l(int __c, locale_t __l) {
+int isupper_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::isupper(__c);
}
-int iswalnum_l(wint_t __c, locale_t __l) {
+int iswalnum_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswalnum(__c);
}
-int iswalpha_l(wint_t __c, locale_t __l) {
+int iswalpha_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswalpha(__c);
}
-int iswblank_l(wint_t __c, locale_t __l) {
+int iswblank_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswblank(__c);
}
-int iswcntrl_l(wint_t __c, locale_t __l) {
+int iswcntrl_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswcntrl(__c);
}
-int iswdigit_l(wint_t __c, locale_t __l) {
+int iswdigit_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswdigit(__c);
}
-int iswgraph_l(wint_t __c, locale_t __l) {
+int iswgraph_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswgraph(__c);
}
-int iswlower_l(wint_t __c, locale_t __l) {
+int iswlower_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswlower(__c);
}
-int iswprint_l(wint_t __c, locale_t __l) {
+int iswprint_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswprint(__c);
}
-int iswpunct_l(wint_t __c, locale_t __l) {
+int iswpunct_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswpunct(__c);
}
-int iswspace_l(wint_t __c, locale_t __l) {
+int iswspace_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswspace(__c);
}
-int iswupper_l(wint_t __c, locale_t __l) {
+int iswupper_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswupper(__c);
}
-int iswxdigit_l(wint_t __c, locale_t __l) {
+int iswxdigit_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswxdigit(__c);
}
-int toupper_l(int __c, locale_t __l) {
+int toupper_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::toupper(__c);
}
-int tolower_l(int __c, locale_t __l) {
+int tolower_l(int __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::tolower(__c);
}
-wint_t towupper_l(wint_t __c, locale_t __l) {
+wint_t towupper_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::towupper(__c);
}
-wint_t towlower_l(wint_t __c, locale_t __l) {
+wint_t towlower_l(wint_t __c, locale_t __l) {
__setAndRestore __newloc(__l);
return ::towlower(__c);
}
-int strcoll_l(const char *__s1, const char *__s2, locale_t __l) {
+int strcoll_l(const char* __s1, const char* __s2, locale_t __l) {
__setAndRestore __newloc(__l);
return ::strcoll(__s1, __s2);
}
-size_t strxfrm_l(char *__dest, const char *__src, size_t __n, locale_t __l) {
+size_t strxfrm_l(char* __dest, const char* __src, size_t __n, locale_t __l) {
__setAndRestore __newloc(__l);
return ::strxfrm(__dest, __src, __n);
}
-size_t strftime_l(char *__s, size_t __max, const char *__format, const struct tm *__tm,
- locale_t __l) {
+size_t strftime_l(char* __s, size_t __max, const char* __format, const struct tm* __tm, locale_t __l) {
__setAndRestore __newloc(__l);
return ::strftime(__s, __max, __format, __tm);
}
-int wcscoll_l(const wchar_t *__ws1, const wchar_t *__ws2, locale_t __l) {
+int wcscoll_l(const wchar_t* __ws1, const wchar_t* __ws2, locale_t __l) {
__setAndRestore __newloc(__l);
return ::wcscoll(__ws1, __ws2);
}
-size_t wcsxfrm_l(wchar_t *__dest, const wchar_t *__src, size_t __n, locale_t __l) {
+size_t wcsxfrm_l(wchar_t* __dest, const wchar_t* __src, size_t __n, locale_t __l) {
__setAndRestore __newloc(__l);
return ::wcsxfrm(__dest, __src, __n);
}
-int iswctype_l(wint_t __c, wctype_t __type, locale_t __l) {
+int iswctype_l(wint_t __c, wctype_t __type, locale_t __l) {
__setAndRestore __newloc(__l);
return ::iswctype(__c, __type);
}
>From e191be630a0a258ec2da486693479c6bf20c07f8 Mon Sep 17 00:00:00 2001
From: Sean Perry <perry at ca.ibm.com>
Date: Wed, 26 Mar 2025 13:25:19 -0400
Subject: [PATCH 4/4] add back in include
---
libcxx/include/__locale_dir/locale_base_api/ibm.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/include/__locale_dir/locale_base_api/ibm.h b/libcxx/include/__locale_dir/locale_base_api/ibm.h
index 9d51043b7ffdb..b4cbd134c78ee 100644
--- a/libcxx/include/__locale_dir/locale_base_api/ibm.h
+++ b/libcxx/include/__locale_dir/locale_base_api/ibm.h
@@ -22,6 +22,8 @@
#if defined(__MVS__)
# include <wctype.h>
+// POSIX routines
+# include <__support/xlocale/__posix_l_fallback.h>
#endif // defined(__MVS__)
_LIBCPP_BEGIN_NAMESPACE_STD
More information about the libcxx-commits
mailing list