[libcxx-commits] [libcxx] ebe6161 - [SystemZ][z/OS] Missing locale functions libc++
Zbigniew Sarbinowski via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Mar 8 11:32:49 PST 2021
Author: Muiez Ahmed
Date: 2021-03-08T19:32:33Z
New Revision: ebe6161c54b92199d897d086834e0c873e3de01c
URL: https://github.com/llvm/llvm-project/commit/ebe6161c54b92199d897d086834e0c873e3de01c
DIFF: https://github.com/llvm/llvm-project/commit/ebe6161c54b92199d897d086834e0c873e3de01c.diff
LOG: [SystemZ][z/OS] Missing locale functions libc++
The aim is to add the missing z/OS specific locale functions for libc++ (newlocale, freelocale and uselocale).
Reviewed By: ldionne, #libc, curdeius
Differential Revision: https://reviews.llvm.org/D98044
Added:
libcxx/include/__support/ibm/locale_mgmt_zos.h
libcxx/src/support/ibm/xlocale_zos.cpp
Modified:
libcxx/include/CMakeLists.txt
libcxx/include/__support/ibm/xlocale.h
libcxx/src/CMakeLists.txt
Removed:
################################################################################
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index ae19e26ca4f5..dd68e5f9e3ca 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -156,6 +156,7 @@ set(files
__support/ibm/gettod_zos.h
__support/ibm/limits.h
__support/ibm/locale_mgmt_aix.h
+ __support/ibm/locale_mgmt_zos.h
__support/ibm/nanosleep.h
__support/ibm/support.h
__support/ibm/xlocale.h
diff --git a/libcxx/include/__support/ibm/locale_mgmt_zos.h b/libcxx/include/__support/ibm/locale_mgmt_zos.h
new file mode 100644
index 000000000000..90ad2c2c8612
--- /dev/null
+++ b/libcxx/include/__support/ibm/locale_mgmt_zos.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H
+#define _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H
+
+#if defined(__MVS__)
+#include <locale.h>
+#include <string>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _LC_MAX LC_MESSAGES /* highest real category */
+#define _NCAT (_LC_MAX + 1) /* maximum + 1 */
+
+#define _CATMASK(n) (1 << (n))
+#define LC_COLLATE_MASK _CATMASK(LC_COLLATE)
+#define LC_CTYPE_MASK _CATMASK(LC_CTYPE)
+#define LC_MONETARY_MASK _CATMASK(LC_MONETARY)
+#define LC_NUMERIC_MASK _CATMASK(LC_NUMERIC)
+#define LC_TIME_MASK _CATMASK(LC_TIME)
+#define LC_MESSAGES_MASK _CATMASK(LC_MESSAGES)
+#define LC_ALL_MASK (_CATMASK(_NCAT) - 1)
+
+typedef struct locale_struct {
+ int category_mask;
+ std::string lc_collate;
+ std::string lc_ctype;
+ std::string lc_monetary;
+ std::string lc_numeric;
+ std::string lc_time;
+ std::string lc_messages;
+} * locale_t;
+
+// z/OS does not have newlocale, freelocale and uselocale.
+// The functions below are workarounds in single thread mode.
+locale_t newlocale(int category_mask, const char* locale, locale_t base);
+void freelocale(locale_t locobj);
+locale_t uselocale(locale_t newloc);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // defined(__MVS__)
+#endif // _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H
diff --git a/libcxx/include/__support/ibm/xlocale.h b/libcxx/include/__support/ibm/xlocale.h
index 5722eb96a2a1..b4d21172bcfa 100644
--- a/libcxx/include/__support/ibm/xlocale.h
+++ b/libcxx/include/__support/ibm/xlocale.h
@@ -11,6 +11,7 @@
#define _LIBCPP_SUPPORT_IBM_XLOCALE_H
#include <__support/ibm/locale_mgmt_aix.h>
+#include <__support/ibm/locale_mgmt_zos.h>
#include "cstdlib"
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index 5dcf92a012ff..aa59698db733 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -90,6 +90,10 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
support/solaris/wcsnrtombs.inc
support/solaris/xlocale.cpp
)
+elseif(ZOS)
+ list(APPEND LIBCXX_SOURCES
+ support/ibm/xlocale_zos.cpp
+ )
endif()
if (LIBCXX_ENABLE_FILESYSTEM)
diff --git a/libcxx/src/support/ibm/xlocale_zos.cpp b/libcxx/src/support/ibm/xlocale_zos.cpp
new file mode 100644
index 000000000000..cb3a9507eb51
--- /dev/null
+++ b/libcxx/src/support/ibm/xlocale_zos.cpp
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include <__support/ibm/xlocale.h>
+#include <sstream>
+#include <vector>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+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));
+
+ // Check for errors.
+ if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) {
+ errno = EINVAL;
+ return (locale_t)0;
+ } else {
+ for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) {
+ if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) {
+ setlocale(LC_ALL, current_loc_name.c_str());
+ errno = EINVAL;
+ return (locale_t)0;
+ }
+ }
+ }
+
+ // Create new locale.
+ locale_t newloc = new locale_struct();
+
+ 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;
+ }
+ delete base;
+ } else {
+ newloc->category_mask = category_mask;
+ }
+
+ 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()) == NULL) ||
+ (newloc->category_mask & LC_CTYPE_MASK &&
+ setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) ||
+ (newloc->category_mask & LC_MONETARY_MASK &&
+ setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) ||
+ (newloc->category_mask & LC_NUMERIC_MASK &&
+ setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) ||
+ (newloc->category_mask & LC_TIME_MASK &&
+ setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) ||
+ (newloc->category_mask & LC_MESSAGES_MASK &&
+ setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL);
+
+ if (is_error) {
+ setlocale(LC_ALL, current_loc_name.c_str());
+ errno = EINVAL;
+ return (locale_t)0;
+ }
+ }
+
+ // Construct and return previous locale.
+ locale_t previous_loc = new locale_struct();
+
+ // 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;
+
+ while (std::getline(ss, s, delimiter)) {
+ tokenized.push_back(s);
+ }
+
+ _LIBCPP_ASSERT(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;
+ }
+
+ previous_loc->category_mask = LC_ALL_MASK;
+ return previous_loc;
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
More information about the libcxx-commits
mailing list