1// std::ctype implementation details, vxworks specific version -*- C++ -*- 2 3// Copyright (C) 2001-2022 Free Software Foundation, Inc. 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 8// Free Software Foundation; either version 3, or (at your option) 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 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/>. 24 25// 26// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions. 27// 28 29// Originally written by Benjamin Kosnik <bkoz@redhat.com>. 30// Ported to vxworks by Corentin Gay <gay@adacore.com>. 31 32#include <locale> 33#include <cstdlib> 34#include <cstring> 35#include <cstdio> 36 37namespace std _GLIBCXX_VISIBILITY(default) 38{ 39_GLIBCXX_BEGIN_NAMESPACE_VERSION 40 41 // NB: The other ctype<char> specializations are in src/locale.cc and 42 // various /config/os/* files. 43 ctype_byname<char>::ctype_byname(const char* __s, size_t __refs) 44 : ctype<char>(0, false, __refs) 45 { 46 if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0) 47 { 48 this->_S_destroy_c_locale(this->_M_c_locale_ctype); 49 this->_S_create_c_locale(this->_M_c_locale_ctype, __s); 50 } 51 } 52 53 ctype_byname<char>::~ctype_byname() 54 { } 55 56#ifdef _GLIBCXX_USE_WCHAR_T 57 ctype<wchar_t>::__wmask_type 58 ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const throw() 59 { 60 __wmask_type __ret; 61 62 switch (__m) 63 { 64 case space: 65 __ret = wctype("space"); 66 break; 67 case print: 68 __ret = wctype("print"); 69 break; 70 case cntrl: 71 __ret = wctype("cntrl"); 72 break; 73 case upper: 74 __ret = wctype("upper"); 75 break; 76 case lower: 77 __ret = wctype("lower"); 78 break; 79 case alpha: 80 __ret = wctype("alpha"); 81 break; 82 case digit: 83 __ret = wctype("digit"); 84 break; 85 case punct: 86 __ret = wctype("punct"); 87 break; 88 case xdigit: 89 __ret = wctype("xdigit"); 90 break; 91 case alnum: 92 __ret = wctype("alnum"); 93 break; 94 case graph: 95 __ret = wctype("graph"); 96 break; 97 default: 98 __ret = __wmask_type(); 99 break; 100 } 101 return __ret; 102 }; 103 104 wchar_t 105 ctype<wchar_t>::do_toupper(wchar_t __c) const 106 { return towupper(__c); } 107 108 const wchar_t* 109 ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const 110 { 111 while (__lo < __hi) 112 { 113 *__lo = towupper(*__lo); 114 ++__lo; 115 } 116 return __hi; 117 } 118 119 wchar_t 120 ctype<wchar_t>::do_tolower(wchar_t __c) const 121 { return towlower(__c); } 122 123 const wchar_t* 124 ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const 125 { 126 while (__lo < __hi) 127 { 128 *__lo = towlower(*__lo); 129 ++__lo; 130 } 131 return __hi; 132 } 133 134 bool 135 ctype<wchar_t>:: 136 do_is(mask __m, char_type __c) const 137 { 138 bool __ret = false; 139 // In VxWorks, a ctype is a short int, thus if we go up to the 15th index, 140 // we will overflow. 141 const size_t __bitmasksize = 14; 142 143 // VxWorks does not consider spaces to be blank, however, the testsuite 144 // and more generally the libstdc++ rely on it, we explicitly handle 145 // that case here. 146 if ((__m & blank) && isspace(__c)) 147 { 148 __ret = true; 149 } 150 else 151 { 152 for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) { 153 if (__m & _M_bit[__bitcur] 154 && iswctype(__c, _M_wmask[__bitcur])) 155 { 156 __ret = true; 157 break; 158 } 159 } 160 } 161 return __ret; 162 } 163 164 const wchar_t* 165 ctype<wchar_t>:: 166 do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const 167 { 168 for (;__lo < __hi; ++__vec, ++__lo) 169 { 170 const size_t __bitmasksize = 14; 171 // In VxWorks, a ctype is a short int, thus if we go up to the 15th index, 172 // we will overflow. 173 mask __m = 0; 174 // VxWorks does not consider space as blank, so let's add an explicit 175 // check. 176 if (isspace(*__lo)) 177 __m |= blank; 178 for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) 179 if (iswctype(*__lo, _M_wmask[__bitcur])) 180 __m |= _M_bit[__bitcur]; 181 *__vec = __m; 182 } 183 return __hi; 184 } 185 186 const wchar_t* 187 ctype<wchar_t>:: 188 do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const 189 { 190 while (__lo < __hi && !this->do_is(__m, *__lo)) 191 ++__lo; 192 return __lo; 193 } 194 195 const wchar_t* 196 ctype<wchar_t>:: 197 do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const 198 { 199 while (__lo < __hi && this->do_is(__m, *__lo) != 0) 200 ++__lo; 201 return __lo; 202 } 203 204 wchar_t 205 ctype<wchar_t>:: 206 do_widen(char __c) const 207 { return _M_widen[static_cast<unsigned char>(__c)]; } 208 209 const char* 210 ctype<wchar_t>:: 211 do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const 212 { 213 while (__lo < __hi) 214 { 215 *__dest = _M_widen[static_cast<unsigned char>(*__lo)]; 216 ++__lo; 217 ++__dest; 218 } 219 return __hi; 220 } 221 222 char 223 ctype<wchar_t>:: 224 do_narrow(wchar_t __wc, char __dfault) const 225 { 226 if (__wc >= 0 && __wc < 128 && _M_narrow_ok) 227 return _M_narrow[__wc]; 228 const int __c = wctob(__wc); 229 return (__c == EOF ? __dfault : static_cast<char>(__c)); 230 } 231 232 const wchar_t* 233 ctype<wchar_t>:: 234 do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault, 235 char* __dest) const 236 { 237 if (_M_narrow_ok) 238 while (__lo < __hi) 239 { 240 if (*__lo >= 0 && *__lo < 128) 241 *__dest = _M_narrow[*__lo]; 242 else 243 { 244 const int __c = wctob(*__lo); 245 *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); 246 } 247 ++__lo; 248 ++__dest; 249 } 250 else 251 while (__lo < __hi) 252 { 253 const int __c = wctob(*__lo); 254 *__dest = (__c == EOF ? __dfault : static_cast<char>(__c)); 255 ++__lo; 256 ++__dest; 257 } 258 return __hi; 259 } 260 261 void 262 ctype<wchar_t>::_M_initialize_ctype() throw() 263 { 264 wint_t __i; 265 for (__i = 0; __i < 128; ++__i) 266 { 267 const int __c = wctob(__i); 268 if (__c == EOF) 269 break; 270 else 271 _M_narrow[__i] = static_cast<char>(__c); 272 } 273 if (__i == 128) 274 _M_narrow_ok = true; 275 else 276 _M_narrow_ok = false; 277 for (size_t __i = 0; 278 __i < sizeof(_M_widen) / sizeof(wint_t); ++__i) 279 _M_widen[__i] = btowc(__i); 280 281 // In VxWorks, a ctype is a short int, thus if we go up to the 15th index, 282 // we will overflow. 283 for (size_t __i = 0; __i <= 14; ++__i) 284 { 285 _M_bit[__i] = static_cast<mask>(1 << __i); 286 _M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]); 287 } 288 } 289#endif // _GLIBCXX_USE_WCHAR_T 290_GLIBCXX_END_NAMESPACE_VERSION 291} // namespace 292