Skip to content
Snippets Groups Projects
Commit 523ca640 authored by Corentin Gay's avatar Corentin Gay Committed by Alexandre Oliva
Browse files

ctype support for libstdc++ on VxWorks

for  libstdc++-v3/ChangeLog

	* acinclude.m4: Add VxWorks-specific case for the
	configuration of ctypes.
	* configure: Regenerate.
	* config/locale/vxworks/ctype_members.cc: Add VxWorks-specific
	version.
	* config/os/vxworks/ctype_base.h: Adjust for VxWorks7+.
	* config/os/vxworks/ctype_configure_char.cc: Likewise.
	* config/os/vxworks/ctype_inline.h: Likewise.
	* testsuite/28_regex/traits/char/isctype.cc: Defines
	NEWLINE_IN_CLASS_BLANK if the target is VxWorks.
	* testsuite/28_regex/traits/wchar_t/isctype.cc: Likewise.
parent 9aed32cc
No related branches found
No related tags found
No related merge requests found
...@@ -2391,6 +2391,9 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ ...@@ -2391,6 +2391,9 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
darwin*) darwin*)
enable_clocale_flag=darwin enable_clocale_flag=darwin
;; ;;
vxworks*)
enable_clocale_flag=vxworks
;;
dragonfly* | freebsd*) dragonfly* | freebsd*)
enable_clocale_flag=dragonfly enable_clocale_flag=dragonfly
;; ;;
...@@ -2485,7 +2488,22 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [ ...@@ -2485,7 +2488,22 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
CTIME_CC=config/locale/generic/time_members.cc CTIME_CC=config/locale/generic/time_members.cc
CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
;; ;;
vxworks)
AC_MSG_RESULT(vxworks)
CLOCALE_H=config/locale/generic/c_locale.h
CLOCALE_CC=config/locale/generic/c_locale.cc
CCODECVT_CC=config/locale/generic/codecvt_members.cc
CCOLLATE_CC=config/locale/generic/collate_members.cc
CCTYPE_CC=config/locale/vxworks/ctype_members.cc
CMESSAGES_H=config/locale/generic/messages_members.h
CMESSAGES_CC=config/locale/generic/messages_members.cc
CMONEY_CC=config/locale/generic/monetary_members.cc
CNUMERIC_CC=config/locale/generic/numeric_members.cc
CTIME_H=config/locale/generic/time_members.h
CTIME_CC=config/locale/generic/time_members.cc
CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
;;
dragonfly) dragonfly)
AC_MSG_RESULT(dragonfly or freebsd) AC_MSG_RESULT(dragonfly or freebsd)
......
// std::ctype implementation details, vxworks specific version -*- C++ -*-
// Copyright (C) 2001-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.
// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
// <http://www.gnu.org/licenses/>.
//
// ISO C++ 14882: 22.2.1.1.2 ctype virtual functions.
//
// Originally written by Benjamin Kosnik <bkoz@redhat.com>.
// Ported to vxworks by Corentin Gay <gay@adacore.com>.
#include <locale>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <iostream>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// NB: The other ctype<char> specializations are in src/locale.cc and
// various /config/os/* files.
ctype_byname<char>::ctype_byname(const char* __s, size_t __refs)
: ctype<char>(0, false, __refs)
{
if (std::strcmp(__s, "C") != 0 && std::strcmp(__s, "POSIX") != 0)
{
this->_S_destroy_c_locale(this->_M_c_locale_ctype);
this->_S_create_c_locale(this->_M_c_locale_ctype, __s);
}
}
ctype_byname<char>::~ctype_byname()
{ }
#ifdef _GLIBCXX_USE_WCHAR_T
ctype<wchar_t>::__wmask_type
ctype<wchar_t>::_M_convert_to_wmask(const mask __m) const throw()
{
__wmask_type __ret;
switch (__m)
{
case space:
__ret = wctype("space");
break;
case print:
__ret = wctype("print");
break;
case cntrl:
__ret = wctype("cntrl");
break;
case upper:
__ret = wctype("upper");
break;
case lower:
__ret = wctype("lower");
break;
case alpha:
__ret = wctype("alpha");
break;
case digit:
__ret = wctype("digit");
break;
case punct:
__ret = wctype("punct");
break;
case xdigit:
__ret = wctype("xdigit");
break;
case alnum:
__ret = wctype("alnum");
break;
case graph:
__ret = wctype("graph");
break;
default:
__ret = __wmask_type();
break;
}
return __ret;
};
wchar_t
ctype<wchar_t>::do_toupper(wchar_t __c) const
{ return towupper(__c); }
const wchar_t*
ctype<wchar_t>::do_toupper(wchar_t* __lo, const wchar_t* __hi) const
{
while (__lo < __hi)
{
*__lo = towupper(*__lo);
++__lo;
}
return __hi;
}
wchar_t
ctype<wchar_t>::do_tolower(wchar_t __c) const
{ return towlower(__c); }
const wchar_t*
ctype<wchar_t>::do_tolower(wchar_t* __lo, const wchar_t* __hi) const
{
while (__lo < __hi)
{
*__lo = towlower(*__lo);
++__lo;
}
return __hi;
}
bool
ctype<wchar_t>::
do_is(mask __m, char_type __c) const
{
bool __ret = false;
// In VxWorks, a ctype is a short int, thus if we go up to the 15th index,
// we will overflow.
const size_t __bitmasksize = 14;
// VxWorks does not consider spaces to be blank, however, the testsuite
// and more generally the libstdc++ rely on it, we explicitly handle
// that case here.
if ((__m & blank) && isspace(__c))
{
__ret = true;
}
else
{
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur) {
if (__m & _M_bit[__bitcur]
&& iswctype(__c, _M_wmask[__bitcur]))
{
__ret = true;
break;
}
}
}
return __ret;
}
const wchar_t*
ctype<wchar_t>::
do_is(const wchar_t* __lo, const wchar_t* __hi, mask* __vec) const
{
for (;__lo < __hi; ++__vec, ++__lo)
{
const size_t __bitmasksize = 14;
// In VxWorks, a ctype is a short int, thus if we go up to the 15th index,
// we will overflow.
mask __m = 0;
// VxWorks does not consider space as blank, so let's add an explicit
// check.
if (isspace(*__lo))
__m |= blank;
for (size_t __bitcur = 0; __bitcur <= __bitmasksize; ++__bitcur)
if (iswctype(*__lo, _M_wmask[__bitcur]))
__m |= _M_bit[__bitcur];
*__vec = __m;
}
return __hi;
}
const wchar_t*
ctype<wchar_t>::
do_scan_is(mask __m, const wchar_t* __lo, const wchar_t* __hi) const
{
while (__lo < __hi && !this->do_is(__m, *__lo))
++__lo;
return __lo;
}
const wchar_t*
ctype<wchar_t>::
do_scan_not(mask __m, const char_type* __lo, const char_type* __hi) const
{
while (__lo < __hi && this->do_is(__m, *__lo) != 0)
++__lo;
return __lo;
}
wchar_t
ctype<wchar_t>::
do_widen(char __c) const
{ return _M_widen[static_cast<unsigned char>(__c)]; }
const char*
ctype<wchar_t>::
do_widen(const char* __lo, const char* __hi, wchar_t* __dest) const
{
while (__lo < __hi)
{
*__dest = _M_widen[static_cast<unsigned char>(*__lo)];
++__lo;
++__dest;
}
return __hi;
}
char
ctype<wchar_t>::
do_narrow(wchar_t __wc, char __dfault) const
{
if (__wc >= 0 && __wc < 128 && _M_narrow_ok)
return _M_narrow[__wc];
const int __c = wctob(__wc);
return (__c == EOF ? __dfault : static_cast<char>(__c));
}
const wchar_t*
ctype<wchar_t>::
do_narrow(const wchar_t* __lo, const wchar_t* __hi, char __dfault,
char* __dest) const
{
if (_M_narrow_ok)
while (__lo < __hi)
{
if (*__lo >= 0 && *__lo < 128)
*__dest = _M_narrow[*__lo];
else
{
const int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
}
++__lo;
++__dest;
}
else
while (__lo < __hi)
{
const int __c = wctob(*__lo);
*__dest = (__c == EOF ? __dfault : static_cast<char>(__c));
++__lo;
++__dest;
}
return __hi;
}
void
ctype<wchar_t>::_M_initialize_ctype() throw()
{
wint_t __i;
for (__i = 0; __i < 128; ++__i)
{
const int __c = wctob(__i);
if (__c == EOF)
break;
else
_M_narrow[__i] = static_cast<char>(__c);
}
if (__i == 128)
_M_narrow_ok = true;
else
_M_narrow_ok = false;
for (size_t __i = 0;
__i < sizeof(_M_widen) / sizeof(wint_t); ++__i)
_M_widen[__i] = btowc(__i);
// In VxWorks, a ctype is a short int, thus if we go up to the 15th index,
// we will overflow.
for (size_t __i = 0; __i <= 14; ++__i)
{
_M_bit[__i] = static_cast<mask>(1 << __i);
_M_wmask[__i] = _M_convert_to_wmask(_M_bit[__i]);
}
}
#endif // _GLIBCXX_USE_WCHAR_T
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
// Information extracted from target/h/ctype.h. // Information extracted from target/h/ctype.h.
#include <_vxworks-versions.h>
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
...@@ -35,6 +37,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -35,6 +37,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
/// @brief Base class for ctype. /// @brief Base class for ctype.
struct ctype_base struct ctype_base
{ {
#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
// Non-standard typedefs. // Non-standard typedefs.
typedef const unsigned char* __to_type; typedef const unsigned char* __to_type;
...@@ -50,11 +53,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -50,11 +53,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static const mask print = (_C_UPPER | _C_LOWER | _C_NUMBER static const mask print = (_C_UPPER | _C_LOWER | _C_NUMBER
| _C_WHITE_SPACE | _C_PUNCT); | _C_WHITE_SPACE | _C_PUNCT);
static const mask graph = _C_UPPER | _C_LOWER | _C_NUMBER | _C_PUNCT; static const mask graph = _C_UPPER | _C_LOWER | _C_NUMBER | _C_PUNCT;
static const mask cntrl = _C_CONTROL; static const mask cntrl = _C_CONTROL | _C_B;
static const mask punct = _C_PUNCT; static const mask punct = _C_PUNCT;
static const mask alnum = _C_UPPER | _C_LOWER | _C_NUMBER; static const mask alnum = _C_UPPER | _C_LOWER | _C_NUMBER;
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
static const mask blank = _C_WHITE_SPACE; static const mask blank = _C_WHITE_SPACE;
#endif
#else
// Non-standard typedefs.
typedef const short* __to_type;
// NB: Offsets into ctype<char>::_M_table force a particular size
// on the mask type. Because of this, we don't use an enum.
typedef short mask;
static const mask upper = _UP;
static const mask lower = _LO;
static const mask alpha = _UP|_LO|_XA;
static const mask digit = _DI;
static const mask xdigit = _XD;
static const mask space = _CN|_SP|_XS;
static const mask print = _DI|_LO|_PU|_SP|_UP|_XA;
static const mask graph = _DI|_LO|_PU|_UP|_XA;
static const mask cntrl = _BB;
static const mask punct = _PU;
static const mask alnum = _DI|_LO|_UP|_XA;
#if __cplusplus >= 201103L
static const mask blank = _SP|_XB;
#endif
#endif #endif
}; };
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
// ISO C++ 14882: 22.1 Locales // ISO C++ 14882: 22.1 Locales
// //
#include <_vxworks-versions.h>
#include <locale> #include <locale>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
...@@ -38,9 +40,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -38,9 +40,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Information as gleaned from target/h/ctype.h // Information as gleaned from target/h/ctype.h
#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
const ctype_base::mask* const ctype_base::mask*
ctype<char>::classic_table() throw() ctype<char>::classic_table() throw()
{ return __ctype; } { return __ctype; }
#else
const ctype_base::mask*
ctype<char>::classic_table() throw()
{ return _Getpctype(); }
# define __toupper _CToupper
# define __tolower _CTolower
#endif
ctype<char>::ctype(__c_locale, const mask* __table, bool __del, ctype<char>::ctype(__c_locale, const mask* __table, bool __del,
size_t __refs) size_t __refs)
......
...@@ -36,10 +36,13 @@ ...@@ -36,10 +36,13 @@
// ctype bits to be inlined go here. Non-inlinable (ie virtual do_*) // ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
// functions go in ctype.cc // functions go in ctype.cc
#include <_vxworks-versions.h>
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
bool bool
ctype<char>:: ctype<char>::
is(mask __m, char __c) const is(mask __m, char __c) const
...@@ -74,5 +77,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -74,5 +77,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __low; return __low;
} }
#else
bool
ctype<char>::
is(mask __m, char __c) const
{ return _Getpctype()[static_cast<int>(__c)] & __m; }
const char*
ctype<char>::
is(const char* __low, const char* __high, mask* __vec) const
{
while (__low < __high)
*__vec++ = _Getpctype()[static_cast<int>(*__low++)];
return __high;
}
const char*
ctype<char>::
scan_is(mask __m, const char* __low, const char* __high) const
{
while (__low < __high
&& !(_Getpctype()[static_cast<int>(*__low)] & __m))
++__low;
return __low;
}
const char*
ctype<char>::
scan_not(mask __m, const char* __low, const char* __high) const
{
while (__low < __high
&& (_Getpctype()[static_cast<int>(*__low)] & __m))
++__low;
return __low;
}
#endif
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
...@@ -16403,6 +16403,9 @@ fi ...@@ -16403,6 +16403,9 @@ fi
darwin*) darwin*)
enable_clocale_flag=darwin enable_clocale_flag=darwin
;; ;;
vxworks*)
enable_clocale_flag=vxworks
;;
dragonfly* | freebsd*) dragonfly* | freebsd*)
enable_clocale_flag=dragonfly enable_clocale_flag=dragonfly
;; ;;
...@@ -16550,7 +16553,23 @@ $as_echo "darwin" >&6; } ...@@ -16550,7 +16553,23 @@ $as_echo "darwin" >&6; }
CTIME_CC=config/locale/generic/time_members.cc CTIME_CC=config/locale/generic/time_members.cc
CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
;; ;;
vxworks)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: vxworks" >&5
$as_echo "vxworks" >&6; }
   
CLOCALE_H=config/locale/generic/c_locale.h
CLOCALE_CC=config/locale/generic/c_locale.cc
CCODECVT_CC=config/locale/generic/codecvt_members.cc
CCOLLATE_CC=config/locale/generic/collate_members.cc
CCTYPE_CC=config/locale/vxworks/ctype_members.cc
CMESSAGES_H=config/locale/generic/messages_members.h
CMESSAGES_CC=config/locale/generic/messages_members.cc
CMONEY_CC=config/locale/generic/monetary_members.cc
CNUMERIC_CC=config/locale/generic/numeric_members.cc
CTIME_H=config/locale/generic/time_members.h
CTIME_CC=config/locale/generic/time_members.cc
CLOCALE_INTERNAL_H=config/locale/generic/c++locale_internal.h
;;
dragonfly) dragonfly)
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly or freebsd" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly or freebsd" >&5
$as_echo "dragonfly or freebsd" >&6; } $as_echo "dragonfly or freebsd" >&6; }
// { dg-do run { target c++11 } } // { dg-do run { target c++11 } }
// { dg-timeout-factor 2 } // { dg-timeout-factor 2 }
// { dg-additional-options "-DNEWLINE_IN_CLASS_BLANK" { target newlib } } // { dg-additional-options "-DNEWLINE_IN_CLASS_BLANK" { target newlib } }
// { dg-additional-options "-DNEWLINE_IN_CLASS_BLANK" { target *-vxworks*-* } }
// //
// 2010-06-23 Stephen M. Webb <stephen.webb@bregmasoft.ca> // 2010-06-23 Stephen M. Webb <stephen.webb@bregmasoft.ca>
......
// { dg-do run { target c++11 } } // { dg-do run { target c++11 } }
// { dg-timeout-factor 2 } // { dg-timeout-factor 2 }
// { dg-additional-options "-DNEWLINE_IN_CLASS_BLANK" { target newlib } } // { dg-additional-options "-DNEWLINE_IN_CLASS_BLANK" { target newlib } }
// { dg-additional-options "-DNEWLINE_IN_CLASS_BLANK" { target *-vxworks*-* } }
// Copyright (C) 2010-2021 Free Software Foundation, Inc. // Copyright (C) 2010-2021 Free Software Foundation, Inc.
// //
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment