ctype support for libstdc++ on VxWorks
authorCorentin Gay <gay@adacore.com>
Wed, 5 May 2021 00:49:43 +0000 (21:49 -0300)
committerAlexandre Oliva <oliva@gnu.org>
Wed, 5 May 2021 00:49:43 +0000 (21:49 -0300)
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
libstdc++-v3/config/locale/vxworks/ctype_members.cc [new file with mode: 0644]
libstdc++-v3/config/os/vxworks/ctype_base.h
libstdc++-v3/config/os/vxworks/ctype_configure_char.cc
libstdc++-v3/config/os/vxworks/ctype_inline.h
libstdc++-v3/configure
libstdc++-v3/testsuite/28_regex/traits/char/isctype.cc
libstdc++-v3/testsuite/28_regex/traits/wchar_t/isctype.cc

index 94897a6..90ecc4a 100644 (file)
@@ -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 (file)
index 0000000..f9dd64c
--- /dev/null
@@ -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
index be60d79..951cb80 100644 (file)
@@ -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,12 +53,34 @@ _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
   };
 
 _GLIBCXX_END_NAMESPACE_VERSION
index cd2eca1..34f12db 100644 (file)
@@ -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)
index cf8b389..885886f 100644 (file)
 // 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
index 067b5d1..6f08b65 100755 (executable)
@@ -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; }
index a4dd73c..5dc5074 100644 (file)
@@ -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>
index d153c58..e3de5ea 100644 (file)
@@ -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.
 //