ctype support for libstdc++ on VxWorks

Message ID or5yzzgqhx.fsf@lxoliva.fsfla.org
State New
Headers show
Series
  • ctype support for libstdc++ on VxWorks
Related show

Commit Message

Alexandre Oliva May 4, 2021, 2:52 a.m.
This patch adds ctype and locale support to libstdc++ on vxworks7.
We've been using this for a while internally.  It was tested with
various vx7r2 targets.  Ok to install?


From: Corentin Gay <gay@adacore.com>


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.
---
 libstdc++-v3/acinclude.m4                          |   18 +
 .../config/locale/vxworks/ctype_members.cc         |  291 ++++++++++++++++++++
 libstdc++-v3/config/os/vxworks/ctype_base.h        |   27 ++
 .../config/os/vxworks/ctype_configure_char.cc      |   10 +
 libstdc++-v3/config/os/vxworks/ctype_inline.h      |   39 +++
 libstdc++-v3/configure                             |   19 +
 .../testsuite/28_regex/traits/char/isctype.cc      |    1 
 .../testsuite/28_regex/traits/wchar_t/isctype.cc   |    1 
 8 files changed, 405 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/config/locale/vxworks/ctype_members.cc



-- 
Alexandre Oliva, happy hacker                https://FSFLA.org/blogs/lxo/
   Free Software Activist                       GNU Toolchain Engineer
Disinformation flourishes because many people care deeply about injustice
but very few check the facts.  Ask me about <https://stallmansupport.org>

Comments

Ian Lance Taylor via Gcc-patches May 4, 2021, 10:02 a.m. | #1
On 03/05/21 23:52 -0300, Alexandre Oliva wrote:
>

>This patch adds ctype and locale support to libstdc++ on vxworks7.

>We've been using this for a while internally.  It was tested with

>various vx7r2 targets.  Ok to install?




>+    // VxWorks does not consider spaces to be blank, however, the testsuite

>+    // and more generally the libstdc++ rely on it, we explicitely handle


s/explicitely/explicitly/


OK with that tweak.
Ian Lance Taylor via Gcc-patches May 4, 2021, 7:53 p.m. | #2
On 04/05/21 4:52 am, Alexandre Oliva wrote:
> This patch adds ctype and locale support to libstdc++ on vxworks7.

> We've been using this for a while internally.  It was tested with

> various vx7r2 targets.  Ok to install?

>

>

> From: Corentin Gay <gay@adacore.com>

>

> +

> +// Copyright (C) 2001-2021 Free Software Foundation, Inc.

> +//


Just a detail but for a new file this Copyright specification looks wrong
Ian Lance Taylor via Gcc-patches May 4, 2021, 10:16 p.m. | #3
On 04/05/21 21:53 +0200, Fran├žois Dumont via Libstdc++ wrote:
>On 04/05/21 4:52 am, Alexandre Oliva wrote:

>>This patch adds ctype and locale support to libstdc++ on vxworks7.

>>We've been using this for a while internally.  It was tested with

>>various vx7r2 targets.  Ok to install?

>>

>>

>>From: Corentin Gay <gay@adacore.com>

>>

>>+

>>+// Copyright (C) 2001-2021 Free Software Foundation, Inc.

>>+//

>

>Just a detail but for a new file this Copyright specification looks wrong


It's derived from an existing file, with a few modifications relevant
to vxworks. As a derived work, I think it should retain the copyright
of the original file.
Alexandre Oliva May 5, 2021, 1:05 a.m. | #4
On May  4, 2021, Jonathan Wakely <jwakely@redhat.com> wrote:

> s/explicitely/explicitly/


Thanks.  I also adjusted the attribution in that file.  Here's what I'm
checking in.


ctype support for libstdc++ on VxWorks

From: Corentin Gay <gay@adacore.com>


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.
---
 libstdc++-v3/acinclude.m4                          |   18 +
 .../config/locale/vxworks/ctype_members.cc         |  292 ++++++++++++++++++++
 libstdc++-v3/config/os/vxworks/ctype_base.h        |   27 ++
 .../config/os/vxworks/ctype_configure_char.cc      |   10 +
 libstdc++-v3/config/os/vxworks/ctype_inline.h      |   39 +++
 libstdc++-v3/configure                             |   19 +
 .../testsuite/28_regex/traits/char/isctype.cc      |    1 
 .../testsuite/28_regex/traits/wchar_t/isctype.cc   |    1 
 8 files changed, 406 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/config/locale/vxworks/ctype_members.cc

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 94897a654c950..90ecc4a87a253 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2391,6 +2391,9 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       darwin*)
 	enable_clocale_flag=darwin
 	;;
+      vxworks*)
+	enable_clocale_flag=vxworks
+	;;
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
@@ -2485,7 +2488,22 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       CTIME_CC=config/locale/generic/time_members.cc
       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)
       AC_MSG_RESULT(dragonfly or freebsd)
 
diff --git a/libstdc++-v3/config/locale/vxworks/ctype_members.cc b/libstdc++-v3/config/locale/vxworks/ctype_members.cc
new file mode 100644
index 0000000000000..f9dd64c73ff78
--- /dev/null
+++ b/libstdc++-v3/config/locale/vxworks/ctype_members.cc
@@ -0,0 +1,292 @@
+// 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
diff --git a/libstdc++-v3/config/os/vxworks/ctype_base.h b/libstdc++-v3/config/os/vxworks/ctype_base.h
index be60d791e27bf..951cb80d456ef 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_base.h
+++ b/libstdc++-v3/config/os/vxworks/ctype_base.h
@@ -28,6 +28,8 @@
 
 // Information extracted from target/h/ctype.h.
 
+#include <_vxworks-versions.h>
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -35,6 +37,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// @brief  Base class for ctype.
   struct ctype_base
   {
+#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
     // Non-standard typedefs.
     typedef const unsigned char* 	__to_type;
 
@@ -50,11 +53,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask print 	= (_C_UPPER | _C_LOWER | _C_NUMBER
 				   | _C_WHITE_SPACE | _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 alnum 	= _C_UPPER | _C_LOWER | _C_NUMBER;
 #if __cplusplus >= 201103L
     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
   };
 
diff --git a/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc b/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
index cd2eca1ae5157..34f12dbb1f78b 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
@@ -28,6 +28,8 @@
 // ISO C++ 14882: 22.1  Locales
 //
 
+#include <_vxworks-versions.h>
+
 #include <locale>
 #include <cstdlib>
 #include <cstring>
@@ -38,9 +40,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 // Information as gleaned from target/h/ctype.h
 
+#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
   const ctype_base::mask*
   ctype<char>::classic_table() throw()
   { 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,
 		     size_t __refs)
diff --git a/libstdc++-v3/config/os/vxworks/ctype_inline.h b/libstdc++-v3/config/os/vxworks/ctype_inline.h
index cf8b389efddaf..885886fa92b75 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_inline.h
+++ b/libstdc++-v3/config/os/vxworks/ctype_inline.h
@@ -36,10 +36,13 @@
 // ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
 // functions go in ctype.cc
 
+#include <_vxworks-versions.h>
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
   bool
   ctype<char>::
   is(mask __m, char __c) const
@@ -74,5 +77,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     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
 } // namespace
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 067b5d1ae8ebf..6f08b65c8ba76 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -16403,6 +16403,9 @@ fi
       darwin*)
 	enable_clocale_flag=darwin
 	;;
+      vxworks*)
+	enable_clocale_flag=vxworks
+	;;
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
@@ -16550,7 +16553,23 @@ $as_echo "darwin" >&6; }
       CTIME_CC=config/locale/generic/time_members.cc
       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)
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly or freebsd" >&5
 $as_echo "dragonfly or freebsd" >&6; }
diff --git a/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc b/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
index a4dd73cf6eb4e..5dc5074c3da0b 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
@@ -1,6 +1,7 @@
 // { dg-do run { target c++11 } }
 // { dg-timeout-factor 2 }
 // { 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>
diff --git a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc
index d153c58483ae2..e3de5ea9ee911 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc
@@ -1,6 +1,7 @@
 // { dg-do run { target c++11 } }
 // { dg-timeout-factor 2 }
 // { 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.
 //


-- 
Alexandre Oliva, happy hacker                https://FSFLA.org/blogs/lxo/
   Free Software Activist                       GNU Toolchain Engineer
Disinformation flourishes because many people care deeply about injustice
but very few check the facts.  Ask me about <https://stallmansupport.org>

Patch

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 7b78e148fbd38..e5d88daac0aa9 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2391,6 +2391,9 @@  AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       darwin*)
 	enable_clocale_flag=darwin
 	;;
+      vxworks*)
+	enable_clocale_flag=vxworks
+	;;
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
@@ -2485,7 +2488,22 @@  AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
       CTIME_CC=config/locale/generic/time_members.cc
       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)
       AC_MSG_RESULT(dragonfly or freebsd)
 
diff --git a/libstdc++-v3/config/locale/vxworks/ctype_members.cc b/libstdc++-v3/config/locale/vxworks/ctype_members.cc
new file mode 100644
index 0000000000000..c5f327969b3f5
--- /dev/null
+++ b/libstdc++-v3/config/locale/vxworks/ctype_members.cc
@@ -0,0 +1,291 @@ 
+// 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.
+//
+
+// Written by Benjamin Kosnik <bkoz@redhat.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 explicitely 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
diff --git a/libstdc++-v3/config/os/vxworks/ctype_base.h b/libstdc++-v3/config/os/vxworks/ctype_base.h
index be60d791e27bf..951cb80d456ef 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_base.h
+++ b/libstdc++-v3/config/os/vxworks/ctype_base.h
@@ -28,6 +28,8 @@ 
 
 // Information extracted from target/h/ctype.h.
 
+#include <_vxworks-versions.h>
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -35,6 +37,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// @brief  Base class for ctype.
   struct ctype_base
   {
+#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
     // Non-standard typedefs.
     typedef const unsigned char* 	__to_type;
 
@@ -50,11 +53,33 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     static const mask print 	= (_C_UPPER | _C_LOWER | _C_NUMBER
 				   | _C_WHITE_SPACE | _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 alnum 	= _C_UPPER | _C_LOWER | _C_NUMBER;
 #if __cplusplus >= 201103L
     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
   };
 
diff --git a/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc b/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
index cd2eca1ae5157..34f12dbb1f78b 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
+++ b/libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
@@ -28,6 +28,8 @@ 
 // ISO C++ 14882: 22.1  Locales
 //
 
+#include <_vxworks-versions.h>
+
 #include <locale>
 #include <cstdlib>
 #include <cstring>
@@ -38,9 +40,17 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 // Information as gleaned from target/h/ctype.h
 
+#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
   const ctype_base::mask*
   ctype<char>::classic_table() throw()
   { 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,
 		     size_t __refs)
diff --git a/libstdc++-v3/config/os/vxworks/ctype_inline.h b/libstdc++-v3/config/os/vxworks/ctype_inline.h
index cf8b389efddaf..885886fa92b75 100644
--- a/libstdc++-v3/config/os/vxworks/ctype_inline.h
+++ b/libstdc++-v3/config/os/vxworks/ctype_inline.h
@@ -36,10 +36,13 @@ 
 // ctype bits to be inlined go here. Non-inlinable (ie virtual do_*)
 // functions go in ctype.cc
 
+#include <_vxworks-versions.h>
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if _VXWORKS_MAJOR_LT(7) && !defined(__RTP__)
   bool
   ctype<char>::
   is(mask __m, char __c) const
@@ -74,5 +77,41 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     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
 } // namespace
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 272bd993a9caf..14b6cad5b1244 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -16437,6 +16437,9 @@  fi
       darwin*)
 	enable_clocale_flag=darwin
 	;;
+      vxworks*)
+	enable_clocale_flag=vxworks
+	;;
       dragonfly* | freebsd*)
 	enable_clocale_flag=dragonfly
 	;;
@@ -16584,7 +16587,23 @@  $as_echo "darwin" >&6; }
       CTIME_CC=config/locale/generic/time_members.cc
       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)
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: dragonfly or freebsd" >&5
 $as_echo "dragonfly or freebsd" >&6; }
diff --git a/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc b/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
index a4dd73cf6eb4e..5dc5074c3da0b 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
@@ -1,6 +1,7 @@ 
 // { dg-do run { target c++11 } }
 // { dg-timeout-factor 2 }
 // { 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>
diff --git a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc
index d153c58483ae2..e3de5ea9ee911 100644
--- a/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc
+++ b/libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc
@@ -1,6 +1,7 @@ 
 // { dg-do run { target c++11 } }
 // { dg-timeout-factor 2 }
 // { 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.
 //