]>
Commit | Line | Data |
---|---|---|
33590f13 | 1 | // std::messages implementation details, GNU version -*- C++ -*- |
0214010c | 2 | |
99dee823 | 3 | // Copyright (C) 2001-2021 Free Software Foundation, Inc. |
0214010c BK |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
0214010c BK |
9 | // any later version. |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
0214010c BK |
24 | |
25 | // | |
33590f13 | 26 | // ISO C++ 14882: 22.2.7.1.2 messages virtual functions |
0214010c BK |
27 | // |
28 | ||
29 | // Written by Benjamin Kosnik <bkoz@redhat.com> | |
30 | ||
33590f13 | 31 | #include <locale> |
6aa43d99 | 32 | #include <bits/c++locale_internal.h> |
7a6f7290 | 33 | |
2a9611d0 JW |
34 | #include <cstdlib> // std::free |
35 | #include <string.h> // ::strdup | |
d31008d7 | 36 | |
d31008d7 | 37 | namespace |
12ffa228 | 38 | { |
d31008d7 | 39 | using namespace std; |
3cbc7af0 | 40 | |
d31008d7 | 41 | const char* |
2a9611d0 JW |
42 | get_glibc_msg(__c_locale __locale_messages __attribute__((unused)), |
43 | const char* __name_messages __attribute__((unused)), | |
d31008d7 FD |
44 | const char* __domainname, |
45 | const char* __dfault) | |
46 | { | |
99ffa1e3 | 47 | #if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 2) |
d31008d7 | 48 | std::__c_locale __old = __uselocale(__locale_messages); |
d31008d7 | 49 | const char* __msg = dgettext(__domainname, __dfault); |
2a9611d0 | 50 | __uselocale(__old); |
d31008d7 | 51 | return __msg; |
2a9611d0 JW |
52 | #else |
53 | if (char* __sav = strdup(setlocale(LC_ALL, 0))) | |
54 | { | |
55 | setlocale(LC_ALL, __name_messages); | |
56 | const char* __msg = dgettext(__domainname, __dfault); | |
57 | setlocale(LC_ALL, __sav); | |
58 | free(__sav); | |
59 | return __msg; | |
60 | } | |
61 | return __dfault; | |
62 | #endif | |
63 | } | |
d31008d7 FD |
64 | } |
65 | ||
66 | namespace std _GLIBCXX_VISIBILITY(default) | |
67 | { | |
68 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
69 | ||
70 | // Specializations. | |
71 | template<> | |
72 | typename messages<char>::catalog | |
73 | messages<char>::do_open(const basic_string<char>& __s, | |
74 | const locale& __l) const | |
2a9611d0 JW |
75 | { |
76 | typedef codecvt<char, char, mbstate_t> __codecvt_t; | |
77 | const __codecvt_t& __codecvt = use_facet<__codecvt_t>(__l); | |
d31008d7 | 78 | |
2a9611d0 JW |
79 | bind_textdomain_codeset(__s.c_str(), |
80 | __nl_langinfo_l(CODESET, __codecvt._M_c_locale_codecvt)); | |
9702ee6a | 81 | return get_catalogs()._M_add(__s.c_str(), __l); |
2a9611d0 | 82 | } |
d31008d7 FD |
83 | |
84 | template<> | |
85 | void | |
86 | messages<char>::do_close(catalog __c) const | |
87 | { get_catalogs()._M_erase(__c); } | |
88 | ||
89 | template<> | |
90 | string | |
91 | messages<char>::do_get(catalog __c, int, int, | |
92 | const string& __dfault) const | |
93 | { | |
94 | if (__c < 0 || __dfault.empty()) | |
95 | return __dfault; | |
96 | ||
97 | const Catalog_info* __cat_info = get_catalogs()._M_get(__c); | |
98 | ||
99 | if (!__cat_info) | |
100 | return __dfault; | |
101 | ||
2a9611d0 | 102 | return get_glibc_msg(_M_c_locale_messages, _M_name_messages, |
9702ee6a | 103 | __cat_info->_M_domain, |
d31008d7 | 104 | __dfault.c_str()); |
33590f13 | 105 | } |
89671b70 | 106 | |
3d7c150e | 107 | #ifdef _GLIBCXX_USE_WCHAR_T |
d31008d7 FD |
108 | template<> |
109 | typename messages<wchar_t>::catalog | |
110 | messages<wchar_t>::do_open(const basic_string<char>& __s, | |
111 | const locale& __l) const | |
2a9611d0 JW |
112 | { |
113 | typedef codecvt<wchar_t, char, mbstate_t> __codecvt_t; | |
114 | const __codecvt_t& __codecvt = use_facet<__codecvt_t>(__l); | |
d31008d7 | 115 | |
2a9611d0 JW |
116 | bind_textdomain_codeset(__s.c_str(), |
117 | __nl_langinfo_l(CODESET, __codecvt._M_c_locale_codecvt)); | |
d31008d7 | 118 | |
9702ee6a | 119 | return get_catalogs()._M_add(__s.c_str(), __l); |
2a9611d0 | 120 | } |
d31008d7 FD |
121 | |
122 | template<> | |
123 | void | |
124 | messages<wchar_t>::do_close(catalog __c) const | |
125 | { get_catalogs()._M_erase(__c); } | |
126 | ||
89671b70 JJ |
127 | template<> |
128 | wstring | |
d31008d7 FD |
129 | messages<wchar_t>::do_get(catalog __c, int, int, |
130 | const wstring& __wdfault) const | |
89671b70 | 131 | { |
d31008d7 FD |
132 | if (__c < 0 || __wdfault.empty()) |
133 | return __wdfault; | |
134 | ||
135 | const Catalog_info* __cat_info = get_catalogs()._M_get(__c); | |
136 | ||
137 | if (!__cat_info) | |
138 | return __wdfault; | |
139 | ||
140 | typedef codecvt<wchar_t, char, mbstate_t> __codecvt_t; | |
141 | const __codecvt_t& __conv = | |
142 | use_facet<__codecvt_t>(__cat_info->_M_locale); | |
143 | ||
144 | const char* __translation; | |
145 | mbstate_t __state; | |
146 | __builtin_memset(&__state, 0, sizeof(mbstate_t)); | |
147 | { | |
148 | const wchar_t* __wdfault_next; | |
9702ee6a | 149 | size_t __mb_size = __wdfault.size() * __conv.max_length(); |
d31008d7 FD |
150 | char* __dfault = |
151 | static_cast<char*>(__builtin_alloca(sizeof(char) * (__mb_size + 1))); | |
152 | char* __dfault_next; | |
153 | __conv.out(__state, | |
154 | __wdfault.data(), __wdfault.data() + __wdfault.size(), | |
155 | __wdfault_next, | |
156 | __dfault, __dfault + __mb_size, __dfault_next); | |
157 | ||
158 | // Make sure string passed to dgettext is \0 terminated. | |
159 | *__dfault_next = '\0'; | |
2a9611d0 | 160 | __translation = get_glibc_msg(_M_c_locale_messages, _M_name_messages, |
9702ee6a | 161 | __cat_info->_M_domain, __dfault); |
d31008d7 FD |
162 | |
163 | // If we end up getting default value back we can simply return original | |
164 | // default value. | |
165 | if (__translation == __dfault) | |
166 | return __wdfault; | |
2a9611d0 | 167 | } |
d31008d7 FD |
168 | |
169 | __builtin_memset(&__state, 0, sizeof(mbstate_t)); | |
170 | size_t __size = __builtin_strlen(__translation); | |
171 | const char* __translation_next; | |
172 | wchar_t* __wtranslation = | |
173 | static_cast<wchar_t*>(__builtin_alloca(sizeof(wchar_t) * (__size + 1))); | |
174 | wchar_t* __wtranslation_next; | |
175 | __conv.in(__state, __translation, __translation + __size, | |
176 | __translation_next, | |
177 | __wtranslation, __wtranslation + __size, | |
178 | __wtranslation_next); | |
179 | return wstring(__wtranslation, __wtranslation_next); | |
89671b70 JJ |
180 | } |
181 | #endif | |
3cbc7af0 | 182 | |
12ffa228 BK |
183 | _GLIBCXX_END_NAMESPACE_VERSION |
184 | } // namespace |