]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libstdc++/5820 (EOF not handled correctly on input)
authorBenjamin Kosnik <bkoz@redhat.com>
Tue, 30 Apr 2002 08:27:20 +0000 (08:27 +0000)
committerBenjamin Kosnik <bkoz@gcc.gnu.org>
Tue, 30 Apr 2002 08:27:20 +0000 (08:27 +0000)
2002-04-29  Benjamin Kosnik  <bkoz@redhat.com>

        PR libstdc++/5820
        * include/bits/fstream.tcc (basic_filebuf::_M_underflow_common):
        Check for eof.
        * include/bits/streambuf_iterator.h: Match stream_iterator.h.
        (istreambuf_iterator::operator++): Invalidate on eof.
        (istreambuf_iterator::operator++(int)): Same.
        (istreambuf_iterator::operator*): Same.

From-SVN: r52935

libstdc++-v3/ChangeLog
libstdc++-v3/config/io/basic_file_stdio.cc
libstdc++-v3/config/io/basic_file_stdio.h
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/bits/streambuf_iterator.h
libstdc++-v3/src/ios.cc
libstdc++-v3/testsuite/27_io/ios_base_storage.cc
libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc

index 7f099362763ed8d46bb277eb278248330b5be012..95c5b24c61966911b59028d9af1ed11c5379112c 100644 (file)
@@ -1,3 +1,26 @@
+2002-04-29  Benjamin Kosnik  <bkoz@redhat.com>
+
+        PR libstdc++/5820
+        * include/bits/fstream.tcc (basic_filebuf::_M_underflow_common):
+        Check for eof.
+        * include/bits/streambuf_iterator.h: Match stream_iterator.h.
+        (istreambuf_iterator::operator++): Invalidate on eof.
+        (istreambuf_iterator::operator++(int)): Same.
+        (istreambuf_iterator::operator*): Same.
+2002-04-29  Benjamin Kosnik  <bkoz@redhat.com>
+
+        PR libstdc++/5820
+       * config/io/basic_file_stdio.h (__basic_file::sys_getc): Return int.
+        (__basic_file::sys_ungetc): Take int.
+        * config/io/basic_file_stdio.cc (__basic_file::sys_ungetc): Same.
+        * include/bits/fstream.tcc (basic_filebuf::_M_underflow_common):
+        Use sys_getc for unbuffered input.
+        * testsuite/27_io/narrow_stream_objects.cc (test06): New.
+        
+        * src/ios.cc (_M_grow_words): Adjust error checking.
+        * testsuite/27_io/ios_base_storage.cc: Same.
+
 2002-04-29  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
        * testsuite/lib/libstdc++-v3-dg.exp (libstdc++-v3-init): Set all
        * config/cpu/mmix/bits/cpu_limits.h: New file.
        * configure.target (CPULIMITSH): Use it.
 
+2002-04-22  Benjamin Kosnik  <bkoz@redhat.com>
+
+       * include/bits/istream.tcc (istream::read): Fix.
+       * testsuite/27_io/istream_unformatted.cc (main): Add.
+
 2002-04-20  Jason Merrill  <jason@redhat.com>
 
        PR libstdc++/4150
index eaebdf25ad9eb6c7c9a82a225e33835188b1496c..25c93e322dc8f50dee10dafef7685214899cb43c 100644 (file)
@@ -81,11 +81,13 @@ namespace std
     return __ret;
   }
 
-  char
-  __basic_file<char>::sys_getc() { return getc (_M_cfile); }
+  int
+  __basic_file<char>::sys_getc() 
+  { return getc(_M_cfile); }
   
-  char
-  __basic_file<char>::sys_ungetc(char __s) { return ungetc (__s, _M_cfile); }
+  int
+  __basic_file<char>::sys_ungetc(int __c) 
+  { return ungetc(__c, _M_cfile); }
   
   __basic_file<char>* 
   __basic_file<char>::open(const char* __name, ios_base::openmode __mode, 
index ca81d6d168f879399772c7666579388f9d6a0287..137dfec94991637d199ccea9c1ecb160123be0ec 100644 (file)
@@ -72,11 +72,11 @@ namespace std
       __basic_file*
       sys_open(__c_file* __file, ios_base::openmode __mode);
 
-      char
+      int
       sys_getc();
 
-      char
-      sys_ungetc(char);
+      int
+      sys_ungetc(int);
 
       __basic_file* 
       close(); 
index 740d5e2c4334b0313002b2c6435f8b7af1993261..910209a1bf1093077155c421629e69d9d11ddb58 100644 (file)
@@ -224,6 +224,21 @@ namespace std
                return traits_type::to_int_type(*_M_in_cur);
            }
 
+         // Check for unbuffered stream.
+         if (_M_buf_size == 1)
+           {
+             int_type __c = _M_file.sys_getc();
+             if (__c != __ret)
+               {
+                 __ret = __c;
+                 *_M_in_cur = traits_type::to_char_type(__c);
+                 _M_set_determinate(1);
+                 if (__testout)
+                   _M_out_cur = _M_in_cur;
+               }
+             return __ret;
+           }
+
          // Sync internal and external buffers.
          // NB: __testget -> __testput as _M_buf_unified here.
          bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
@@ -278,14 +293,6 @@ namespace std
                  __ret = traits_type::to_int_type(*_M_in_cur);
                  if (__bump)
                    _M_in_cur_move(1);
-                 else if (_M_buf_size == 1)
-                   {
-                     // If we are synced with stdio, we have to unget the
-                     // character we just read so that the file pointer
-                     // doesn't move.
-                     _M_file.sys_ungetc(*_M_in_cur);
-                     _M_set_indeterminate();
-                   }
                }          
            }
        }
index 88ae25eab1861e84f6757099b3b2e3dfe067852c..f7317b2e48139eac06232718cbe4690dc3870511 100644 (file)
@@ -1,6 +1,7 @@
 // Streambuf iterators
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+// 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
 
 namespace std
 {
-  template<typename _CharT, typename _Traits>
-    class ostreambuf_iterator
-    : public iterator<output_iterator_tag, void, void, void, void>
-    {
-    public:
-      // Types:
-      typedef _CharT                           char_type;
-      typedef _Traits                          traits_type;
-      typedef basic_streambuf<_CharT, _Traits> streambuf_type;
-      typedef basic_ostream<_CharT, _Traits>   ostream_type;
-
-    private:
-      streambuf_type*  _M_sbuf;
-      bool             _M_failed;
-
-    public:
-      inline 
-      ostreambuf_iterator(ostream_type& __s) throw ()
-      : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
-      
-      ostreambuf_iterator(streambuf_type* __s) throw ()
-      : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
-
-      ostreambuf_iterator& 
-      operator=(_CharT __c);
-
-      ostreambuf_iterator& 
-      operator*() throw()
-      { return *this; }
-
-      ostreambuf_iterator& 
-      operator++(int) throw()
-      { return *this; }
-
-      ostreambuf_iterator& 
-      operator++() throw()
-      { return *this; }
-
-      bool 
-      failed() const throw()
-      { return _M_failed; }
-    };
-
-  template<typename _CharT, typename _Traits>
-    inline ostreambuf_iterator<_CharT, _Traits>&
-    ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c)
-    {
-      if (!_M_failed && 
-          _Traits::eq_int_type(_M_sbuf->sputc(__c),_Traits::eof()))
-      _M_failed = true;
-      return *this;
-    }
-
-
   // 24.5.3 Template class istreambuf_iterator
   template<typename _CharT, typename _Traits>
     class istreambuf_iterator
@@ -117,12 +64,12 @@ namespace std
       // the "end of stream" iterator value.
       // NB: This implementation assumes the "end of stream" value
       // is EOF, or -1.
-      streambuf_type*          _M_sbuf;  
+      mutable streambuf_type*  _M_sbuf;  
       int_type                         _M_c;
 
     public:
       istreambuf_iterator() throw() 
-      : _M_sbuf(NULL), _M_c(-2) { }
+      : _M_sbuf(0), _M_c(-2) { }
       
       istreambuf_iterator(istream_type& __s) throw()
       : _M_sbuf(__s.rdbuf()), _M_c(-2) { }
@@ -137,22 +84,25 @@ namespace std
       operator*() const
       { 
        // The result of operator*() on an end of stream is undefined.
-       char_type __ret;
-       if (_M_sbuf && _M_c != static_cast<int_type>(-2))
-         __ret = _M_c;
-       else if (_M_sbuf)
-         __ret = traits_type::to_char_type(_M_sbuf->sgetc()); 
-       else
-         __ret = static_cast<char_type>(traits_type::eof());
-       return __ret;
+       int_type __ret = traits_type::eof();
+       if (_M_sbuf)
+         { 
+           if (_M_c != static_cast<int_type>(-2))
+             __ret = _M_c;
+           else 
+             if ((__ret = _M_sbuf->sgetc()) == traits_type::eof())
+               _M_sbuf = 0;
+         }
+       return traits_type::to_char_type(__ret);
       }
        
       istreambuf_iterator& 
       operator++()
       { 
-       if (_M_sbuf)
-         _M_sbuf->sbumpc();
-       _M_c = -2;
+       if (_M_sbuf && _M_sbuf->sbumpc() == traits_type::eof())
+         _M_sbuf = 0;
+       else
+         _M_c = -2;
        return *this; 
       }
 
@@ -160,30 +110,22 @@ namespace std
       operator++(int)
       {
        istreambuf_iterator __old = *this;
-       if (_M_sbuf)
-         __old._M_c = _M_sbuf->sbumpc();
-       _M_c = -2;
+       if (_M_sbuf && (__old._M_c = _M_sbuf->sbumpc()) == traits_type::eof())
+         _M_sbuf = 0;
+       else
+         _M_c = -2;
        return __old; 
       }
 
-      bool 
-      equal(const istreambuf_iterator& __b)
-      { 
-       int_type __eof = traits_type::eof();
-       bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
-       bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof;
-       return (__thiseof && __beof || (!__thiseof && !__beof));
-      }
-
 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
       // 110 istreambuf_iterator::equal not const
       // NB: there is also number 111 (NAD, Future) pending on this function.
       bool 
       equal(const istreambuf_iterator& __b) const
       {
-       int_type __eof = traits_type::eof();
-       bool __thiseof = !_M_sbuf || _M_sbuf->sgetc() == __eof;
-       bool __beof = !__b._M_sbuf || __b._M_sbuf->sgetc() == __eof;
+       const int_type __eof = traits_type::eof();
+       bool __thiseof = traits_type::eq_int_type(this->operator*(), __eof);
+       bool __beof = traits_type::eq_int_type(__b.operator*(), __eof);
        return (__thiseof && __beof || (!__thiseof && !__beof));
       }
 #endif
@@ -200,5 +142,58 @@ namespace std
     operator!=(const istreambuf_iterator<_CharT, _Traits>& __a,
               const istreambuf_iterator<_CharT, _Traits>& __b)
     { return !__a.equal(__b); }
+
+  template<typename _CharT, typename _Traits>
+    class ostreambuf_iterator
+    : public iterator<output_iterator_tag, void, void, void, void>
+    {
+    public:
+      // Types:
+      typedef _CharT                           char_type;
+      typedef _Traits                          traits_type;
+      typedef basic_streambuf<_CharT, _Traits> streambuf_type;
+      typedef basic_ostream<_CharT, _Traits>   ostream_type;
+
+    private:
+      streambuf_type*  _M_sbuf;
+      bool             _M_failed;
+
+    public:
+      inline 
+      ostreambuf_iterator(ostream_type& __s) throw ()
+      : _M_sbuf(__s.rdbuf()), _M_failed(!_M_sbuf) { }
+      
+      ostreambuf_iterator(streambuf_type* __s) throw ()
+      : _M_sbuf(__s), _M_failed(!_M_sbuf) { }
+
+      ostreambuf_iterator& 
+      operator=(_CharT __c);
+
+      ostreambuf_iterator& 
+      operator*() throw()
+      { return *this; }
+
+      ostreambuf_iterator& 
+      operator++(int) throw()
+      { return *this; }
+
+      ostreambuf_iterator& 
+      operator++() throw()
+      { return *this; }
+
+      bool 
+      failed() const throw()
+      { return _M_failed; }
+    };
+
+  template<typename _CharT, typename _Traits>
+    inline ostreambuf_iterator<_CharT, _Traits>&
+    ostreambuf_iterator<_CharT, _Traits>::operator=(_CharT __c)
+    {
+      if (!_M_failed && 
+          _Traits::eq_int_type(_M_sbuf->sputc(__c), _Traits::eof()))
+       _M_failed = true;
+      return *this;
+    }
 } // namespace std
 #endif
index 1d97bf9e7a8c1ed94c365366926b3f252bbcd57a..8e834fd65b01dfaaf7e595cf5ff517cb071248fa 100644 (file)
@@ -226,33 +226,35 @@ namespace std
     // Precondition: _M_word_size <= ix
     int newsize = _S_local_word_size;
     _Words* words = _M_local_word;
-    int i = 0;
     if (ix > _S_local_word_size - 1)
       {
-       const int max = numeric_limits<int>::max();
-       if (ix < max)
-         newsize = ix + 1;
+       if (ix < numeric_limits<int>::max())
+         {
+           newsize = ix + 1;
+           try
+             { words = new _Words[newsize]; }
+           catch (...)
+             {
+               delete [] _M_word;
+               _M_word = 0;
+               _M_streambuf_state |= badbit;
+               if (_M_streambuf_state & _M_exception)
+                 __throw_ios_failure("ios_base::_M_grow_words failure");
+               return _M_word_zero;
+             }
+           for (int i = 0; i < _M_word_size; i++) 
+             words[i] = _M_word[i];
+           if (_M_word && _M_word != _M_local_word) 
+             {
+               delete [] _M_word;
+               _M_word = 0;
+             }
+         }
        else
-         newsize = max;
-
-       try
-         { words = new _Words[newsize]; }
-       catch (...)
          {
-           delete [] _M_word;
-           _M_word = 0;
            _M_streambuf_state |= badbit;
-           if (_M_streambuf_state & _M_exception)
-             __throw_ios_failure("ios_base::_M_grow_words caused exception");
            return _M_word_zero;
          }
-       for (; i < _M_word_size; i++) 
-         words[i] = _M_word[i];
-       if (_M_word && _M_word != _M_local_word) 
-         {
-           delete [] _M_word;
-           _M_word = 0;
-         }
       }
     _M_word = words;
     _M_word_size = newsize;
@@ -351,4 +353,3 @@ namespace std
     return __ret; 
   }
 }  // namespace std
-
index 560e69695128eec4c418c85ab7f194f1bae0d7ba..c39d0302716dcecf6cc7323a87a7897b046f22d2 100644 (file)
@@ -45,7 +45,7 @@ void test01()
 void test02()
 {
   bool test = true;
-  int max = std::numeric_limits<int>::max();
+  int max = std::numeric_limits<int>::max() - 1;
   std::stringbuf        strbuf;
   std::ios              ios(&strbuf);
 
index 3abcb07b47eef4f17f035f12ea4bf4661cda9c77..27291be00fc25dad13c419a5ae78ba2e1a244634 100644 (file)
@@ -1,6 +1,6 @@
 // 2000-08-02 bkoz
 
-// Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+// Copyright (C) 2000, 2001, 2002 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
@@ -145,6 +145,26 @@ void test05()
   std::cout << "hello " << s << std::endl;
 }
 
+// libstdc++/5280
+// Interactive test: input "1234^D^D" for i should terminate for EOF.
+void test06()
+{
+  using namespace std;
+  int i;
+  cin >> i;
+  if (!cin.good()) 
+    {
+      cerr << endl;
+      cerr << "i == " << i << endl;
+      cerr << "cin.rdstate() == " << cin.rdstate() << endl;
+      cerr << "cin.bad() == " << cin.bad() << endl;      
+      cerr << "cin.fail() == " << cin.fail() << endl;      
+      cerr << "cin.eof() == " << cin.eof() << endl;
+    }   
+  else
+    cerr << "i == " << i << endl;
+}
+
 int 
 main()
 {
@@ -154,5 +174,6 @@ main()
   // test03();
   // test04();
   // test05();
+  // test06();
   return 0;
 }