On May  4, 2021, Jonathan Wakely <jwak...@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 <g...@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 <b...@redhat.com>.
+// Ported to vxworks by Corentin Gay <g...@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.w...@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>

Reply via email to