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