[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