Skip to content

Commit ebe6161

Browse files
Muiez Ahmedzibi2
authored andcommitted
[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
1 parent e4492b6 commit ebe6161

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ set(files
156156
__support/ibm/gettod_zos.h
157157
__support/ibm/limits.h
158158
__support/ibm/locale_mgmt_aix.h
159+
__support/ibm/locale_mgmt_zos.h
159160
__support/ibm/nanosleep.h
160161
__support/ibm/support.h
161162
__support/ibm/xlocale.h
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H
11+
#define _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H
12+
13+
#if defined(__MVS__)
14+
#include <locale.h>
15+
#include <string>
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif
20+
21+
#define _LC_MAX LC_MESSAGES /* highest real category */
22+
#define _NCAT (_LC_MAX + 1) /* maximum + 1 */
23+
24+
#define _CATMASK(n) (1 << (n))
25+
#define LC_COLLATE_MASK _CATMASK(LC_COLLATE)
26+
#define LC_CTYPE_MASK _CATMASK(LC_CTYPE)
27+
#define LC_MONETARY_MASK _CATMASK(LC_MONETARY)
28+
#define LC_NUMERIC_MASK _CATMASK(LC_NUMERIC)
29+
#define LC_TIME_MASK _CATMASK(LC_TIME)
30+
#define LC_MESSAGES_MASK _CATMASK(LC_MESSAGES)
31+
#define LC_ALL_MASK (_CATMASK(_NCAT) - 1)
32+
33+
typedef struct locale_struct {
34+
int category_mask;
35+
std::string lc_collate;
36+
std::string lc_ctype;
37+
std::string lc_monetary;
38+
std::string lc_numeric;
39+
std::string lc_time;
40+
std::string lc_messages;
41+
} * locale_t;
42+
43+
// z/OS does not have newlocale, freelocale and uselocale.
44+
// The functions below are workarounds in single thread mode.
45+
locale_t newlocale(int category_mask, const char* locale, locale_t base);
46+
void freelocale(locale_t locobj);
47+
locale_t uselocale(locale_t newloc);
48+
49+
#ifdef __cplusplus
50+
}
51+
#endif
52+
#endif // defined(__MVS__)
53+
#endif // _LIBCPP_SUPPORT_IBM_LOCALE_MGMT_ZOS_H

libcxx/include/__support/ibm/xlocale.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define _LIBCPP_SUPPORT_IBM_XLOCALE_H
1212

1313
#include <__support/ibm/locale_mgmt_aix.h>
14+
#include <__support/ibm/locale_mgmt_zos.h>
1415

1516
#include "cstdlib"
1617

libcxx/src/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")
9090
support/solaris/wcsnrtombs.inc
9191
support/solaris/xlocale.cpp
9292
)
93+
elseif(ZOS)
94+
list(APPEND LIBCXX_SOURCES
95+
support/ibm/xlocale_zos.cpp
96+
)
9397
endif()
9498

9599
if (LIBCXX_ENABLE_FILESYSTEM)
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
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+
#include <__support/ibm/xlocale.h>
10+
#include <sstream>
11+
#include <vector>
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif // __cplusplus
16+
17+
locale_t newlocale(int category_mask, const char* locale, locale_t base) {
18+
// Maintain current locale name(s) to restore later.
19+
std::string current_loc_name(setlocale(LC_ALL, 0));
20+
21+
// Check for errors.
22+
if (category_mask == LC_ALL_MASK && setlocale(LC_ALL, locale) == NULL) {
23+
errno = EINVAL;
24+
return (locale_t)0;
25+
} else {
26+
for (int _Cat = 0; _Cat <= _LC_MAX; ++_Cat) {
27+
if ((_CATMASK(_Cat) & category_mask) != 0 && setlocale(_Cat, locale) == NULL) {
28+
setlocale(LC_ALL, current_loc_name.c_str());
29+
errno = EINVAL;
30+
return (locale_t)0;
31+
}
32+
}
33+
}
34+
35+
// Create new locale.
36+
locale_t newloc = new locale_struct();
37+
38+
if (base) {
39+
if (category_mask != LC_ALL_MASK) {
40+
// Copy base when it will not be overwritten.
41+
memcpy(newloc, base, sizeof (locale_struct));
42+
newloc->category_mask = category_mask | base->category_mask;
43+
}
44+
delete base;
45+
} else {
46+
newloc->category_mask = category_mask;
47+
}
48+
49+
if (category_mask & LC_COLLATE_MASK)
50+
newloc->lc_collate = locale;
51+
if (category_mask & LC_CTYPE_MASK)
52+
newloc->lc_ctype = locale;
53+
if (category_mask & LC_MONETARY_MASK)
54+
newloc->lc_monetary = locale;
55+
if (category_mask & LC_NUMERIC_MASK)
56+
newloc->lc_numeric = locale;
57+
if (category_mask & LC_TIME_MASK)
58+
newloc->lc_time = locale;
59+
if (category_mask & LC_MESSAGES_MASK)
60+
newloc->lc_messages = locale;
61+
62+
// Restore current locale.
63+
setlocale(LC_ALL, current_loc_name.c_str());
64+
return (locale_t)newloc;
65+
}
66+
67+
void freelocale(locale_t locobj) {
68+
delete locobj;
69+
}
70+
71+
locale_t uselocale(locale_t newloc) {
72+
// Maintain current locale name(s).
73+
std::string current_loc_name(setlocale(LC_ALL, 0));
74+
75+
if (newloc) {
76+
// Set locales and check for errors.
77+
bool is_error =
78+
(newloc->category_mask & LC_COLLATE_MASK &&
79+
setlocale(LC_COLLATE, newloc->lc_collate.c_str()) == NULL) ||
80+
(newloc->category_mask & LC_CTYPE_MASK &&
81+
setlocale(LC_CTYPE, newloc->lc_ctype.c_str()) == NULL) ||
82+
(newloc->category_mask & LC_MONETARY_MASK &&
83+
setlocale(LC_MONETARY, newloc->lc_monetary.c_str()) == NULL) ||
84+
(newloc->category_mask & LC_NUMERIC_MASK &&
85+
setlocale(LC_NUMERIC, newloc->lc_numeric.c_str()) == NULL) ||
86+
(newloc->category_mask & LC_TIME_MASK &&
87+
setlocale(LC_TIME, newloc->lc_time.c_str()) == NULL) ||
88+
(newloc->category_mask & LC_MESSAGES_MASK &&
89+
setlocale(LC_MESSAGES, newloc->lc_messages.c_str()) == NULL);
90+
91+
if (is_error) {
92+
setlocale(LC_ALL, current_loc_name.c_str());
93+
errno = EINVAL;
94+
return (locale_t)0;
95+
}
96+
}
97+
98+
// Construct and return previous locale.
99+
locale_t previous_loc = new locale_struct();
100+
101+
// current_loc_name might be a comma-separated locale name list.
102+
if (current_loc_name.find(',') != std::string::npos) {
103+
// Tokenize locale name list.
104+
const char delimiter = ',';
105+
std::vector<std::string> tokenized;
106+
std::stringstream ss(current_loc_name);
107+
std::string s;
108+
109+
while (std::getline(ss, s, delimiter)) {
110+
tokenized.push_back(s);
111+
}
112+
113+
_LIBCPP_ASSERT(tokenized.size() >= _NCAT, "locale-name list is too short");
114+
115+
previous_loc->lc_collate = tokenized[LC_COLLATE];
116+
previous_loc->lc_ctype = tokenized[LC_CTYPE];
117+
previous_loc->lc_monetary = tokenized[LC_MONETARY];
118+
previous_loc->lc_numeric = tokenized[LC_NUMERIC];
119+
previous_loc->lc_time = tokenized[LC_TIME];
120+
// Skip LC_TOD.
121+
previous_loc->lc_messages = tokenized[LC_MESSAGES];
122+
} else {
123+
previous_loc->lc_collate = current_loc_name;
124+
previous_loc->lc_ctype = current_loc_name;
125+
previous_loc->lc_monetary = current_loc_name;
126+
previous_loc->lc_numeric = current_loc_name;
127+
previous_loc->lc_time = current_loc_name;
128+
previous_loc->lc_messages = current_loc_name;
129+
}
130+
131+
previous_loc->category_mask = LC_ALL_MASK;
132+
return previous_loc;
133+
}
134+
135+
#ifdef __cplusplus
136+
}
137+
#endif // __cplusplus

0 commit comments

Comments
 (0)