From: Benjamin Kosnik Date: Tue, 30 Apr 2002 08:27:20 +0000 (+0000) Subject: re PR libstdc++/5820 (EOF not handled correctly on input) X-Git-Tag: releases/gcc-3.1.0~108 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2fc045a030b656201b53dce88da45b985342eed0;p=thirdparty%2Fgcc.git re PR libstdc++/5820 (EOF not handled correctly on input) 2002-04-29 Benjamin Kosnik 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7f099362763e..95c5b24c6196 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,26 @@ +2002-04-29 Benjamin Kosnik + + 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 + + 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 * testsuite/lib/libstdc++-v3-dg.exp (libstdc++-v3-init): Set all @@ -48,6 +71,11 @@ * config/cpu/mmix/bits/cpu_limits.h: New file. * configure.target (CPULIMITSH): Use it. +2002-04-22 Benjamin Kosnik + + * include/bits/istream.tcc (istream::read): Fix. + * testsuite/27_io/istream_unformatted.cc (main): Add. + 2002-04-20 Jason Merrill PR libstdc++/4150 diff --git a/libstdc++-v3/config/io/basic_file_stdio.cc b/libstdc++-v3/config/io/basic_file_stdio.cc index eaebdf25ad9e..25c93e322dc8 100644 --- a/libstdc++-v3/config/io/basic_file_stdio.cc +++ b/libstdc++-v3/config/io/basic_file_stdio.cc @@ -81,11 +81,13 @@ namespace std return __ret; } - char - __basic_file::sys_getc() { return getc (_M_cfile); } + int + __basic_file::sys_getc() + { return getc(_M_cfile); } - char - __basic_file::sys_ungetc(char __s) { return ungetc (__s, _M_cfile); } + int + __basic_file::sys_ungetc(int __c) + { return ungetc(__c, _M_cfile); } __basic_file* __basic_file::open(const char* __name, ios_base::openmode __mode, diff --git a/libstdc++-v3/config/io/basic_file_stdio.h b/libstdc++-v3/config/io/basic_file_stdio.h index ca81d6d168f8..137dfec94991 100644 --- a/libstdc++-v3/config/io/basic_file_stdio.h +++ b/libstdc++-v3/config/io/basic_file_stdio.h @@ -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(); diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc index 740d5e2c4334..910209a1bf10 100644 --- a/libstdc++-v3/include/bits/fstream.tcc +++ b/libstdc++-v3/include/bits/fstream.tcc @@ -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(); - } } } } diff --git a/libstdc++-v3/include/bits/streambuf_iterator.h b/libstdc++-v3/include/bits/streambuf_iterator.h index 88ae25eab186..f7317b2e4813 100644 --- a/libstdc++-v3/include/bits/streambuf_iterator.h +++ b/libstdc++-v3/include/bits/streambuf_iterator.h @@ -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 @@ -41,60 +42,6 @@ namespace std { - template - class ostreambuf_iterator - : public iterator - { - 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 - 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 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(-2)) - __ret = _M_c; - else if (_M_sbuf) - __ret = traits_type::to_char_type(_M_sbuf->sgetc()); - else - __ret = static_cast(traits_type::eof()); - return __ret; + int_type __ret = traits_type::eof(); + if (_M_sbuf) + { + if (_M_c != static_cast(-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 + class ostreambuf_iterator + : public iterator + { + 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 + 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 diff --git a/libstdc++-v3/src/ios.cc b/libstdc++-v3/src/ios.cc index 1d97bf9e7a8c..8e834fd65b01 100644 --- a/libstdc++-v3/src/ios.cc +++ b/libstdc++-v3/src/ios.cc @@ -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::max(); - if (ix < max) - newsize = ix + 1; + if (ix < numeric_limits::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 - diff --git a/libstdc++-v3/testsuite/27_io/ios_base_storage.cc b/libstdc++-v3/testsuite/27_io/ios_base_storage.cc index 560e69695128..c39d0302716d 100644 --- a/libstdc++-v3/testsuite/27_io/ios_base_storage.cc +++ b/libstdc++-v3/testsuite/27_io/ios_base_storage.cc @@ -45,7 +45,7 @@ void test01() void test02() { bool test = true; - int max = std::numeric_limits::max(); + int max = std::numeric_limits::max() - 1; std::stringbuf strbuf; std::ios ios(&strbuf); diff --git a/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc b/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc index 3abcb07b47ee..27291be00fc2 100644 --- a/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc +++ b/libstdc++-v3/testsuite/27_io/narrow_stream_objects.cc @@ -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; }