OSDN Git Service

* parser.c (cp_parser_class_specifier): Set class location to that
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / src / istream.cc
index 462824d..e410277 100644 (file)
@@ -1,11 +1,12 @@
 // Input streams -*- C++ -*-
 
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+// 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 2, or (at your option)
+// 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,
 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 // GNU General Public License for more details.
 
-// You should have received a copy of the GNU General Public License along
-// with this library; see the file COPYING.  If not, write to the Free
-// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
-// USA.
+// 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.
 
-// As a special exception, you may use this file as part of a free software
-// library without restriction.  Specifically, if other files instantiate
-// templates or use macros or inline functions from this file, or you compile
-// this file and link it with other files to produce an executable, this
-// file does not by itself cause the resulting executable to be covered by
-// the GNU General Public License.  This exception does not however
-// invalidate any other reasons why the executable file might be covered by
-// the GNU General Public License.
+// 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: 27.6.1  Input streams
 
 #include <istream>
 
-namespace std
-{
+_GLIBCXX_BEGIN_NAMESPACE(std)
+
   template<>
     basic_istream<char>&
     basic_istream<char>::
     getline(char_type* __s, streamsize __n, char_type __delim)
     {
       _M_gcount = 0;
-      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+      ios_base::iostate __err = ios_base::goodbit;
       sentry __cerb(*this, true);
       if (__cerb)
        {
-          try
+          __try
            {
              const int_type __idelim = traits_type::to_int_type(__delim);
              const int_type __eof = traits_type::eof();
@@ -91,10 +87,18 @@ namespace std
              else
                __err |= ios_base::failbit;
            }
-         catch(...)
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             this->_M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
            { this->_M_setstate(ios_base::badbit); }
        }
-      *__s = char_type();
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 243. get and getline when sentry reports failure.
+      if (__n > 0)
+       *__s = char_type();
       if (!_M_gcount)
        __err |= ios_base::failbit;
       if (__err)
@@ -105,48 +109,81 @@ namespace std
   template<>
     basic_istream<char>&
     basic_istream<char>::
-    ignore(streamsize __n)
+    ignore(streamsize __n, int_type __delim)
     {
-      if (__n == 1)
-       return ignore();
-      
+      if (traits_type::eq_int_type(__delim, traits_type::eof()))
+       return ignore(__n);
+
       _M_gcount = 0;
       sentry __cerb(*this, true);
-      if (__cerb && __n > 0)
+      if (__n > 0 && __cerb)
        {
-         ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
-         try
+         ios_base::iostate __err = ios_base::goodbit;
+         __try
            {
+             const char_type __cdelim = traits_type::to_char_type(__delim);
              const int_type __eof = traits_type::eof();
              __streambuf_type* __sb = this->rdbuf();
              int_type __c = __sb->sgetc();
-             
-             const bool __bound = __n != numeric_limits<streamsize>::max();
-             if (__bound)
-               --__n;
-             while (_M_gcount <= __n
-                    && !traits_type::eq_int_type(__c, __eof))
-               {
-                 streamsize __size = __sb->egptr() - __sb->gptr();
-                 if (__bound)
-                   __size = std::min(__size, streamsize(__n - _M_gcount + 1));
 
-                 if (__size > 1)
+             bool __large_ignore = false;
+             while (true)
+               {
+                 while (_M_gcount < __n
+                        && !traits_type::eq_int_type(__c, __eof)
+                        && !traits_type::eq_int_type(__c, __delim))
                    {
-                     __sb->gbump(__size);
-                     _M_gcount += __size;
-                     __c = __sb->sgetc();
+                     streamsize __size = std::min(streamsize(__sb->egptr()
+                                                             - __sb->gptr()),
+                                                  streamsize(__n - _M_gcount));
+                     if (__size > 1)
+                       {
+                         const char_type* __p = traits_type::find(__sb->gptr(),
+                                                                  __size,
+                                                                  __cdelim);
+                         if (__p)
+                           __size = __p - __sb->gptr();
+                         __sb->gbump(__size);
+                         _M_gcount += __size;
+                         __c = __sb->sgetc();
+                       }
+                     else
+                       {
+                         ++_M_gcount;
+                         __c = __sb->snextc();
+                       }
                    }
-                 else
+                 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max
+                     && !traits_type::eq_int_type(__c, __eof)
+                     && !traits_type::eq_int_type(__c, __delim))
                    {
-                     ++_M_gcount;
-                     __c = __sb->snextc();
-                   }             
+                     _M_gcount =
+                       __gnu_cxx::__numeric_traits<streamsize>::__min;
+                     __large_ignore = true;
+                   }
+                 else
+                   break;
                }
+
+             if (__large_ignore)
+               _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max;
+
              if (traits_type::eq_int_type(__c, __eof))
                __err |= ios_base::eofbit;
+             else if (traits_type::eq_int_type(__c, __delim))
+               {
+                 if (_M_gcount
+                     < __gnu_cxx::__numeric_traits<streamsize>::__max)
+                   ++_M_gcount;
+                 __sb->sbumpc();
+               }
            }
-         catch(...)
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             this->_M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
            { this->_M_setstate(ios_base::badbit); }
          if (__err)
            this->setstate(__err);
@@ -156,66 +193,163 @@ namespace std
 
   template<>
     basic_istream<char>&
-    basic_istream<char>::
-    ignore(streamsize __n, int_type __delim)
+    operator>>(basic_istream<char>& __in, char* __s)
     {
-      if (traits_type::eq_int_type(__delim, traits_type::eof()))
-       return ignore(__n);
+      typedef basic_istream<char>              __istream_type;
+      typedef __istream_type::int_type         __int_type;
+      typedef __istream_type::char_type                __char_type;
+      typedef __istream_type::traits_type      __traits_type;
+      typedef __istream_type::__streambuf_type  __streambuf_type;
+      typedef __istream_type::__ctype_type     __ctype_type;
 
-      _M_gcount = 0;
-      sentry __cerb(*this, true);
-      if (__cerb && __n > 0)
+      streamsize __extracted = 0;
+      ios_base::iostate __err = ios_base::goodbit;
+      __istream_type::sentry __cerb(__in, false);
+      if (__cerb)
        {
-         ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
-         try
+         __try
            {
-             const char_type __cdelim = traits_type::to_char_type(__delim);          
-             const int_type __eof = traits_type::eof();
-             __streambuf_type* __sb = this->rdbuf();
-             int_type __c = __sb->sgetc();
+             // Figure out how many characters to extract.
+             streamsize __num = __in.width();
+             if (__num <= 0)
+               __num = __gnu_cxx::__numeric_traits<streamsize>::__max;
 
-             const bool __bound = __n != numeric_limits<streamsize>::max();
-             if (__bound)
-               --__n;
-             while (_M_gcount <= __n
-                    && !traits_type::eq_int_type(__c, __eof)
-                    && !traits_type::eq_int_type(__c, __delim))
-               {
-                 streamsize __size = __sb->egptr() - __sb->gptr();
-                 if (__bound)
-                   __size = std::min(__size, streamsize(__n - _M_gcount + 1));
+             const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
 
+             const __int_type __eof = __traits_type::eof();
+             __streambuf_type* __sb = __in.rdbuf();
+             __int_type __c = __sb->sgetc();
+
+             while (__extracted < __num - 1
+                    && !__traits_type::eq_int_type(__c, __eof)
+                    && !__ct.is(ctype_base::space,
+                                __traits_type::to_char_type(__c)))
+               {
+                 streamsize __size = std::min(streamsize(__sb->egptr()
+                                                         - __sb->gptr()),
+                                              streamsize(__num - __extracted
+                                                         - 1));
                  if (__size > 1)
                    {
-                     const char_type* __p = traits_type::find(__sb->gptr(),
-                                                              __size,
-                                                              __cdelim);
-                     if (__p)
-                       __size = __p - __sb->gptr();
+                     __size = (__ct.scan_is(ctype_base::space,
+                                            __sb->gptr() + 1,
+                                            __sb->gptr() + __size)
+                               - __sb->gptr());
+                     __traits_type::copy(__s, __sb->gptr(), __size);
+                     __s += __size;
                      __sb->gbump(__size);
-                     _M_gcount += __size;
+                     __extracted += __size;
                      __c = __sb->sgetc();
                    }
                  else
                    {
-                     ++_M_gcount;
+                     *__s++ = __traits_type::to_char_type(__c);
+                     ++__extracted;
                      __c = __sb->snextc();
-                   }             
+                   }
                }
-             if (traits_type::eq_int_type(__c, __eof))
+
+             if (__traits_type::eq_int_type(__c, __eof))
                __err |= ios_base::eofbit;
-             else if (traits_type::eq_int_type(__c, __delim))
+
+             // _GLIBCXX_RESOLVE_LIB_DEFECTS
+             // 68.  Extractors for char* should store null at end
+             *__s = __char_type();
+             __in.width(0);
+           }
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             __in._M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
+           { __in._M_setstate(ios_base::badbit); }
+       }
+      if (!__extracted)
+       __err |= ios_base::failbit;
+      if (__err)
+       __in.setstate(__err);
+      return __in;
+    }
+
+  template<>
+    basic_istream<char>&
+    operator>>(basic_istream<char>& __in, basic_string<char>& __str)
+    {
+      typedef basic_istream<char>              __istream_type;
+      typedef __istream_type::int_type         __int_type;
+      typedef __istream_type::char_type                __char_type;
+      typedef __istream_type::traits_type      __traits_type;
+      typedef __istream_type::__streambuf_type  __streambuf_type;
+      typedef __istream_type::__ctype_type     __ctype_type;
+      typedef basic_string<char>               __string_type;
+      typedef __string_type::size_type         __size_type;
+
+      __size_type __extracted = 0;
+      ios_base::iostate __err = ios_base::goodbit;
+      __istream_type::sentry __cerb(__in, false);
+      if (__cerb)
+       {
+         __try
+           {
+             __str.erase();
+             const streamsize __w = __in.width();
+             const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
+                                             : __str.max_size();
+             const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
+             const __int_type __eof = __traits_type::eof();
+             __streambuf_type* __sb = __in.rdbuf();
+             __int_type __c = __sb->sgetc();
+
+             while (__extracted < __n
+                    && !__traits_type::eq_int_type(__c, __eof)
+                    && !__ct.is(ctype_base::space,
+                                __traits_type::to_char_type(__c)))
                {
-                 ++_M_gcount;
-                 __sb->sbumpc();
+                 streamsize __size = std::min(streamsize(__sb->egptr()
+                                                         - __sb->gptr()),
+                                              streamsize(__n - __extracted));
+                 if (__size > 1)
+                   {
+                     __size = (__ct.scan_is(ctype_base::space,
+                                            __sb->gptr() + 1,
+                                            __sb->gptr() + __size)
+                               - __sb->gptr());
+                     __str.append(__sb->gptr(), __size);
+                     __sb->gbump(__size);
+                     __extracted += __size;
+                     __c = __sb->sgetc();
+                   }
+                 else
+                   {
+                     __str += __traits_type::to_char_type(__c);
+                     ++__extracted;
+                     __c = __sb->snextc();
+                   }             
                }
+
+             if (__traits_type::eq_int_type(__c, __eof))
+               __err |= ios_base::eofbit;
+             __in.width(0);
+           }
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             __in._M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
+           {
+             // _GLIBCXX_RESOLVE_LIB_DEFECTS
+             // 91. Description of operator>> and getline() for string<>
+             // might cause endless loop
+             __in._M_setstate(ios_base::badbit);
            }
-         catch(...)
-           { this->_M_setstate(ios_base::badbit); }
-         if (__err)
-           this->setstate(__err);
        }
-      return *this;
+      if (!__extracted)
+       __err |= ios_base::failbit;
+      if (__err)
+       __in.setstate(__err);
+      return __in;
     }
 
   template<>
@@ -234,11 +368,11 @@ namespace std
 
       __size_type __extracted = 0;
       const __size_type __n = __str.max_size();
-      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+      ios_base::iostate __err = ios_base::goodbit;
       __istream_type::sentry __cerb(__in, true);
       if (__cerb)
        {
-         try
+         __try
            {
              __str.erase();
              const __int_type __idelim = __traits_type::to_int_type(__delim);
@@ -283,7 +417,12 @@ namespace std
              else
                __err |= ios_base::failbit;
            }
-         catch(...)
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             __in._M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
            {
              // _GLIBCXX_RESOLVE_LIB_DEFECTS
              // 91. Description of operator>> and getline() for string<>
@@ -305,11 +444,11 @@ namespace std
     getline(char_type* __s, streamsize __n, char_type __delim)
     {
       _M_gcount = 0;
-      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+      ios_base::iostate __err = ios_base::goodbit;
       sentry __cerb(*this, true);
       if (__cerb)
        {
-          try
+          __try
            {
              const int_type __idelim = traits_type::to_int_type(__delim);
              const int_type __eof = traits_type::eof();
@@ -355,10 +494,18 @@ namespace std
              else
                __err |= ios_base::failbit;
            }
-         catch(...)
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             this->_M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
            { this->_M_setstate(ios_base::badbit); }
        }
-      *__s = char_type();
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 243. get and getline when sentry reports failure.
+      if (__n > 0)
+       *__s = char_type();
       if (!_M_gcount)
        __err |= ios_base::failbit;
       if (__err)
@@ -369,58 +516,6 @@ namespace std
   template<>
     basic_istream<wchar_t>&
     basic_istream<wchar_t>::
-    ignore(streamsize __n)
-    {
-      if (__n == 1)
-       return ignore();
-      
-      _M_gcount = 0;
-      sentry __cerb(*this, true);
-      if (__cerb && __n > 0)
-       {
-         ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
-         try
-           {
-             const int_type __eof = traits_type::eof();
-             __streambuf_type* __sb = this->rdbuf();
-             int_type __c = __sb->sgetc();
-             
-             const bool __bound = __n != numeric_limits<streamsize>::max();
-             if (__bound)
-               --__n;
-             while (_M_gcount <= __n
-                    && !traits_type::eq_int_type(__c, __eof))
-               {
-                 streamsize __size = __sb->egptr() - __sb->gptr();
-                 if (__bound)
-                   __size = std::min(__size, streamsize(__n - _M_gcount + 1));
-
-                 if (__size > 1)
-                   {
-                     __sb->gbump(__size);
-                     _M_gcount += __size;
-                     __c = __sb->sgetc();
-                   }
-                 else
-                   {
-                     ++_M_gcount;
-                     __c = __sb->snextc();
-                   }             
-               }
-             if (traits_type::eq_int_type(__c, __eof))
-               __err |= ios_base::eofbit;
-           }
-         catch(...)
-           { this->_M_setstate(ios_base::badbit); }
-         if (__err)
-           this->setstate(__err);
-       }
-      return *this;
-    }
-
-  template<>
-    basic_istream<wchar_t>&
-    basic_istream<wchar_t>::
     ignore(streamsize __n, int_type __delim)
     {
       if (traits_type::eq_int_type(__delim, traits_type::eof()))
@@ -428,53 +523,74 @@ namespace std
 
       _M_gcount = 0;
       sentry __cerb(*this, true);
-      if (__cerb && __n > 0)
+      if (__n > 0 && __cerb)
        {
-         ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
-         try
+         ios_base::iostate __err = ios_base::goodbit;
+         __try
            {
-             const char_type __cdelim = traits_type::to_char_type(__delim);          
+             const char_type __cdelim = traits_type::to_char_type(__delim);
              const int_type __eof = traits_type::eof();
              __streambuf_type* __sb = this->rdbuf();
              int_type __c = __sb->sgetc();
 
-             const bool __bound = __n != numeric_limits<streamsize>::max();
-             if (__bound)
-               --__n;
-             while (_M_gcount <= __n
-                    && !traits_type::eq_int_type(__c, __eof)
-                    && !traits_type::eq_int_type(__c, __delim))
+             bool __large_ignore = false;
+             while (true)
                {
-                 streamsize __size = __sb->egptr() - __sb->gptr();
-                 if (__bound)
-                   __size = std::min(__size, streamsize(__n - _M_gcount + 1));
-
-                 if (__size > 1)
+                 while (_M_gcount < __n
+                        && !traits_type::eq_int_type(__c, __eof)
+                        && !traits_type::eq_int_type(__c, __delim))
                    {
-                     const char_type* __p = traits_type::find(__sb->gptr(),
-                                                              __size,
-                                                              __cdelim);
-                     if (__p)
-                       __size = __p - __sb->gptr();
-                     __sb->gbump(__size);
-                     _M_gcount += __size;
-                     __c = __sb->sgetc();
+                     streamsize __size = std::min(streamsize(__sb->egptr()
+                                                             - __sb->gptr()),
+                                                  streamsize(__n - _M_gcount));
+                     if (__size > 1)
+                       {
+                         const char_type* __p = traits_type::find(__sb->gptr(),
+                                                                  __size,
+                                                                  __cdelim);
+                         if (__p)
+                           __size = __p - __sb->gptr();
+                         __sb->gbump(__size);
+                         _M_gcount += __size;
+                         __c = __sb->sgetc();
+                       }
+                     else
+                       {
+                         ++_M_gcount;
+                         __c = __sb->snextc();
+                       }
                    }
-                 else
+                 if (__n == __gnu_cxx::__numeric_traits<streamsize>::__max
+                     && !traits_type::eq_int_type(__c, __eof)
+                     && !traits_type::eq_int_type(__c, __delim))
                    {
-                     ++_M_gcount;
-                     __c = __sb->snextc();
-                   }             
+                     _M_gcount =
+                       __gnu_cxx::__numeric_traits<streamsize>::__min;
+                     __large_ignore = true;
+                   }
+                 else
+                   break;
                }
+
+             if (__large_ignore)
+               _M_gcount = __gnu_cxx::__numeric_traits<streamsize>::__max;
+
              if (traits_type::eq_int_type(__c, __eof))
                __err |= ios_base::eofbit;
              else if (traits_type::eq_int_type(__c, __delim))
                {
-                 ++_M_gcount;
+                 if (_M_gcount
+                     < __gnu_cxx::__numeric_traits<streamsize>::__max)
+                   ++_M_gcount;
                  __sb->sbumpc();
                }
            }
-         catch(...)
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             this->_M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
            { this->_M_setstate(ios_base::badbit); }
          if (__err)
            this->setstate(__err);
@@ -498,11 +614,11 @@ namespace std
 
       __size_type __extracted = 0;
       const __size_type __n = __str.max_size();
-      ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
+      ios_base::iostate __err = ios_base::goodbit;
       __istream_type::sentry __cerb(__in, true);
       if (__cerb)
        {
-         try
+         __try
            {
              __str.erase();
              const __int_type __idelim = __traits_type::to_int_type(__delim);
@@ -547,7 +663,12 @@ namespace std
              else
                __err |= ios_base::failbit;
            }
-         catch(...)
+         __catch(__cxxabiv1::__forced_unwind&)
+           {
+             __in._M_setstate(ios_base::badbit);
+             __throw_exception_again;
+           }
+         __catch(...)
            {
              // _GLIBCXX_RESOLVE_LIB_DEFECTS
              // 91. Description of operator>> and getline() for string<>
@@ -562,4 +683,5 @@ namespace std
       return __in;
     }
 #endif
-} // namespace std
+
+_GLIBCXX_END_NAMESPACE