This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[v3] c/c++ io



Removes any fileno-based interface to IO, and goes up the food chain,
settling on FILE* objects. Works way better.

x86/linux using shared linking now has no expected
failures. Yay. There are two static fails that have to do with
-ffunction-sections. And there are bugs with no testsuite
regressions. However, this is still forward progress.

sync_with_stdio is not done, but now seems like much nicer thing to
implement correctly. Patch following shortly.

Loren had posted a patch along these lines months ago. It wasn't
checked in but I did look at it, and appreciate the arguments advanced.

I anticipate people who were using the fileno based interface will
freak out. This patch will smoke out people using these ctors. As this
is not a standards-conforming bit of the C++ interface (and clearly
marked as such), something may have to be done.

-benjamin

tested x86/linux


2001-03-26  Benjamin Kosnik  <bkoz@redhat.com>

	* include/bits/basic_file.h (get_fileno): Remove.
	(_M_fileno): Remove.
	(_M_cfile_created): Add.
	(basic_file::basic_file(__c_file_type*, openmode): Add.
	(basic_file::basic_file(int, const char*, openmode): Remove.
	* include/bits/fstream.tcc (basic_fstream::basic_filebuf(int __fd,
	const char*, ios_base::openmode): Don't allocate
	internal buffers. Turn off internal buffers.
	(basic_filebuf::overflow): Remove test for null buffer.
	(basic_filebuf::_M_really_overflow): Same. Allow unbuffered use.
	* include/bits/streambuf.cc: Tweak.
	* include/bits/std_ostream.h: Tweak.
	* config/basic_file_libio.h: Same.
	* config/basic_file_stdio.h: Same.
	* src/ios.cc (ios_base::Init::Init()): Unbuffer stdout by default.
	* testsuite/27_io/filebuf_members.cc: Tweaks.
	* testsuite/27_io/ios_base_members_static.cc: Tweaks.	

Index: config/basic_file_libio.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/basic_file_libio.h,v
retrieving revision 1.2
diff -c -p -r1.2 basic_file_libio.h
*** basic_file_libio.h	2001/03/01 00:37:17	1.2
--- basic_file_libio.h	2001/03/27 03:37:51
*************** namespace std 
*** 127,139 ****
      __basic_file<wchar_t>::doallocate();
  #endif
  
-   // Generic definitions for __basic_file
    template<typename _CharT>
-     int 
-     __basic_file<_CharT>::get_fileno(void)
-     { return _fileno; }
-  
-   template<typename _CharT>
      __basic_file<_CharT>::~__basic_file()
      { _IO_file_finish(this, 0); }
        
--- 127,133 ----
*************** namespace std 
*** 189,197 ****
    
    template<typename _CharT>
      __basic_file<_CharT>*
!     __basic_file<_CharT>::sys_open(int __fd, ios_base::openmode __mode) 
      {
        __basic_file* __ret = NULL;
        int __p_mode = 0;
        int __rw_mode = _IO_NO_READS + _IO_NO_WRITES; 
        char __c_mode[4];
--- 183,193 ----
    
    template<typename _CharT>
      __basic_file<_CharT>*
!     __basic_file<_CharT>::sys_open(__c_file_type* __f, 
! 				   ios_base::openmode __mode) 
      {
        __basic_file* __ret = NULL;
+       int __fd = fileno(__f);
        int __p_mode = 0;
        int __rw_mode = _IO_NO_READS + _IO_NO_WRITES; 
        char __c_mode[4];
*************** namespace std 
*** 201,207 ****
        if (!_IO_file_is_open(this))
  	{
  	  _fileno = __fd;
! 	  _flags &= ~(_IO_NO_READS+_IO_NO_WRITES);
  	  _flags |= _IO_DELETE_DONT_CLOSE;
  	  _offset = _IO_pos_BAD;
  	  int __mask = _IO_NO_READS + _IO_NO_WRITES + _IO_IS_APPENDING;
--- 197,203 ----
        if (!_IO_file_is_open(this))
  	{
  	  _fileno = __fd;
! 	  _flags &= ~(_IO_NO_READS + _IO_NO_WRITES);
  	  _flags |= _IO_DELETE_DONT_CLOSE;
  	  _offset = _IO_pos_BAD;
  	  int __mask = _IO_NO_READS + _IO_NO_WRITES + _IO_IS_APPENDING;
Index: config/basic_file_stdio.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/config/basic_file_stdio.h,v
retrieving revision 1.1
diff -c -p -r1.1 basic_file_stdio.h
*** basic_file_stdio.h	2001/02/28 03:20:35	1.1
--- basic_file_stdio.h	2001/03/27 03:37:51
*************** namespace std 
*** 38,51 ****
    // Generic definitions for __basic_file
    template<typename _CharT>
      __basic_file<_CharT>::__basic_file(__c_lock* /*__lock*/) 
!     : _M_fileno(-1), _M_cfile(NULL) { }
  
    template<typename _CharT>
-     int 
-     __basic_file<_CharT>::get_fileno(void)
-     { return _M_fileno; }
-  
-   template<typename _CharT>
      __basic_file<_CharT>::~__basic_file()
      {
        if (this->is_open())
--- 38,46 ----
    // Generic definitions for __basic_file
    template<typename _CharT>
      __basic_file<_CharT>::__basic_file(__c_lock* /*__lock*/) 
!     : _M_cfile(NULL), _M_cfile_created(false) { }
  
    template<typename _CharT>
      __basic_file<_CharT>::~__basic_file()
      {
        if (this->is_open())
*************** namespace std 
*** 85,108 ****
    
    template<typename _CharT>
      __basic_file<_CharT>*
!     __basic_file<_CharT>::sys_open(int __fd, ios_base::openmode __mode) 
      {
        __basic_file* __ret = NULL;
-       int __p_mode = 0;
-       int __rw_mode = 0;
-       char __c_mode[4];
- 
-       _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode);
  
!       int __dupfd = dup(__fd);
! 
!       if (__dupfd != -1 && !this->is_open())
  	{
! 	  if ((_M_cfile = fdopen(__dupfd, __c_mode)))
! 	    {
! 	      _M_fileno = __dupfd;
! 	      __ret = this;
! 	    }
  	}
  
        return __ret;
--- 80,94 ----
    
    template<typename _CharT>
      __basic_file<_CharT>*
!     __basic_file<_CharT>::sys_open(__c_file_type* __file, ios_base::openmode) 
      {
        __basic_file* __ret = NULL;
  
!       if (!this->is_open() && __file)
  	{
! 	  _M_cfile = __file;
! 	  _M_cfile_created = false;
! 	  __ret = this;
  	}
  
        return __ret;
*************** namespace std 
*** 124,130 ****
  	{
  	  if ((_M_cfile = fopen(__name, __c_mode)))
  	    {
! 	      _M_fileno = fileno(_M_cfile);
  	      __ret = this;
  	    }
  	}
--- 110,116 ----
  	{
  	  if ((_M_cfile = fopen(__name, __c_mode)))
  	    {
! 	      _M_cfile_created = true;
  	      __ret = this;
  	    }
  	}
*************** namespace std 
*** 133,151 ****
    
    template<typename _CharT>
      bool 
!     __basic_file<_CharT>::is_open() { return _M_fileno >= 0; }
    
    template<typename _CharT>
      __basic_file<_CharT>* 
      __basic_file<_CharT>::close()
      { 
        __basic_file* __retval = static_cast<__basic_file*>(NULL);
!       bool __testopen = fclose(_M_cfile);
!       if (!__testopen)
! 	{
! 	  __retval = this;
! 	  _M_fileno = -1;
! 	}  
        return __retval;
      }
   
--- 119,133 ----
    
    template<typename _CharT>
      bool 
!     __basic_file<_CharT>::is_open() { return _M_cfile != 0; }
    
    template<typename _CharT>
      __basic_file<_CharT>* 
      __basic_file<_CharT>::close()
      { 
        __basic_file* __retval = static_cast<__basic_file*>(NULL);
!       if (_M_cfile_created && fclose(_M_cfile))
! 	__retval = this;
        return __retval;
      }
   
Index: include/bits/basic_file.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/basic_file.h,v
retrieving revision 1.7
diff -c -p -r1.7 basic_file.h
*** basic_file.h	2001/03/21 19:26:49	1.7
--- basic_file.h	2001/03/27 03:37:52
*************** namespace std 
*** 121,128 ****
  #endif
      {
  #if _GLIBCPP_BASIC_FILE_ENCAPSULATION
-       int 		_M_fileno;
        __c_file_type* 	_M_cfile;
  #else
  # ifdef _GLIBCPP_USE_WCHAR_T
        __c_wfile_type	_M_wfile;
--- 121,128 ----
  #endif
      {
  #if _GLIBCPP_BASIC_FILE_ENCAPSULATION
        __c_file_type* 	_M_cfile;
+       bool 		_M_cfile_created;
  #else
  # ifdef _GLIBCPP_USE_WCHAR_T
        __c_wfile_type	_M_wfile;
*************** namespace std 
*** 145,151 ****
        // just sets __c_file_type->_fileno and the respective _flags bits, and
        // returns.
        __basic_file*
!       sys_open(int __fd, ios_base::openmode __mode);
  
        __basic_file* 
        close(); 
--- 145,151 ----
        // just sets __c_file_type->_fileno and the respective _flags bits, and
        // returns.
        __basic_file*
!       sys_open(__c_file_type* __file, ios_base::openmode __mode);
  
        __basic_file* 
        close(); 
*************** namespace std 
*** 153,161 ****
        bool 
        is_open();
  
-       // Needed by ios_base::sync_with_stdio.
-       int get_fileno(void);
- 
        // NB: Must match FILE specific jump table starting here--this
        // means all virtual functions starting with the dtor must match,
        // slot by slot. For glibc-based dystems, this means the _IO_FILE
--- 153,158 ----
*************** namespace std 
*** 247,250 ****
  #include <bits/basic_file_model.h>
  
  #endif	// _CPP_BASIC_FILE
- 
--- 244,246 ----
Index: include/bits/fstream.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/fstream.tcc,v
retrieving revision 1.10
diff -c -p -r1.10 fstream.tcc
*** fstream.tcc	2001/03/14 20:46:33	1.10
--- fstream.tcc	2001/03/27 03:37:54
*************** namespace std
*** 90,113 ****
  
    template<typename _CharT, typename _Traits>
      basic_filebuf<_CharT, _Traits>::
!     basic_filebuf(int __fd, const char* /*__name*/, ios_base::openmode __mode)
      : __streambuf_type(),  _M_file(NULL), _M_state_cur(__state_type()), 
      _M_state_beg(__state_type()), _M_last_overflowed(false)
      {
        _M_filebuf_init();
!       _M_file->sys_open(__fd, __mode);
        if (this->is_open())
! 	{
! 	  _M_allocate_buffers();
! 	  _M_mode = __mode;
! 
! 	  // XXX So that istream::getc() will only need to get 1 char,
! 	  // as opposed to BUF_SIZE.
! 	  if (__fd == 0)
! 	    _M_buf_size = 1;
! 
! 	  this->_M_set_indeterminate();
! 	}
     }
  
    template<typename _CharT, typename _Traits>
--- 90,103 ----
  
    template<typename _CharT, typename _Traits>
      basic_filebuf<_CharT, _Traits>::
!     basic_filebuf(__c_file_type* __f, ios_base::openmode __mode)
      : __streambuf_type(),  _M_file(NULL), _M_state_cur(__state_type()), 
      _M_state_beg(__state_type()), _M_last_overflowed(false)
      {
        _M_filebuf_init();
!       _M_file->sys_open(__f, __mode);
        if (this->is_open())
! 	_M_mode = __mode;
     }
  
    template<typename _CharT, typename _Traits>
*************** namespace std
*** 382,393 ****
      overflow(int_type __c)
      {
        int_type __ret = traits_type::eof();
!       bool __testpos = _M_out_cur && _M_out_cur >= _M_buf + _M_buf_size;
        bool __testout = _M_mode & ios_base::out;
        
        if (__testout)
  	{
! 	  if (!__testpos)
  	    {
  	      *_M_out_cur = traits_type::to_char_type(__c);
  	      _M_out_cur_move(1);
--- 372,383 ----
      overflow(int_type __c)
      {
        int_type __ret = traits_type::eof();
!       bool __testput = _M_out_cur && _M_out_cur < _M_buf + _M_buf_size;
        bool __testout = _M_mode & ios_base::out;
        
        if (__testout)
  	{
! 	  if (__testput)
  	    {
  	      *_M_out_cur = traits_type::to_char_type(__c);
  	      _M_out_cur_move(1);
*************** namespace std
*** 408,427 ****
      {
        int_type __ret = traits_type::eof();
        bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
!       
!       if (__testput)
  	{
- 	  bool __testeof = traits_type::eq_int_type(__c, traits_type::eof());
  #if 1
  	  int __plen = _M_out_end - _M_out_beg;
! 	  streamsize __len = _M_file->xsputn(_M_out_beg, __plen);
! 	  if (!__testeof)
  	    {
! 	      char_type __pending = traits_type::to_char_type(__c);
! 	      __len += _M_file->xsputn(&__pending, 1);
! 	      ++__plen;
  	    }
! 	  traits_type::to_char_type(__c);
  	  // NB: Need this so that external byte sequence reflects
  	  // internal buffer.
  	  _M_file->sync();
--- 398,421 ----
      {
        int_type __ret = traits_type::eof();
        bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
!       bool __testunbuffered = _M_file && !_M_buf_size;
! 
!       if (__testput || __testunbuffered)
  	{
  #if 1
  	  int __plen = _M_out_end - _M_out_beg;
! 	  streamsize __len = 0;
! 
! 	  if (__plen)
! 	    __len = _M_file->xsputn(_M_out_beg, __plen);
! 
! 	  if (__c !=traits_type::eof())
  	    {
!  	      char_type __pending = traits_type::to_char_type(__c);
!  	      __len += _M_file->xsputn(&__pending, 1);
!   	      ++__plen;
  	    }
! 
  	  // NB: Need this so that external byte sequence reflects
  	  // internal buffer.
  	  _M_file->sync();
Index: include/bits/std_fstream.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/std_fstream.h,v
retrieving revision 1.5
diff -c -p -r1.5 std_fstream.h
*** std_fstream.h	2001/03/14 20:46:34	1.5
--- std_fstream.h	2001/03/27 03:37:55
***************
*** 42,49 ****
  #include <bits/std_locale.h>	// For codecvt
  #include <bits/c++threads.h>	// For __mutext_type
  
! namespace std {
! 
    template<typename _CharT, typename _Traits>
      class basic_filebuf : public basic_streambuf<_CharT, _Traits>
      {
--- 42,49 ----
  #include <bits/std_locale.h>	// For codecvt
  #include <bits/c++threads.h>	// For __mutext_type
  
! namespace std 
! {
    template<typename _CharT, typename _Traits>
      class basic_filebuf : public basic_streambuf<_CharT, _Traits>
      {
*************** namespace std {
*** 86,93 ****
        basic_filebuf();
  
        // Non-standard ctor:
!       basic_filebuf(int __fd, const char* __name, ios_base::openmode __mode);
! 
        virtual 
        ~basic_filebuf() 
        { 
--- 86,93 ----
        basic_filebuf();
  
        // Non-standard ctor:
!       basic_filebuf(__c_file_type* __f, ios_base::openmode __mode);
!  
        virtual 
        ~basic_filebuf() 
        { 
*************** namespace std {
*** 399,405 ****
  	  setstate (ios_base::failbit); 
        }
      };
- 
  } // namespace std
  
  
--- 399,404 ----
*************** namespace std {
*** 410,414 ****
  #endif
  #endif
  
! #endif	/* _CPP_FSTREAM */
  
--- 409,413 ----
  #endif
  #endif
  
! #endif	
  
Index: include/bits/std_ostream.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/std_ostream.h,v
retrieving revision 1.5
diff -c -p -r1.5 std_ostream.h
*** std_ostream.h	2001/03/04 21:34:00	1.5
--- std_ostream.h	2001/03/27 03:37:56
*************** namespace std
*** 281,283 ****
--- 281,284 ----
  #endif
  
  #endif	/* _CPP_OSTREAM */
+ 
Index: include/bits/streambuf.tcc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/bits/streambuf.tcc,v
retrieving revision 1.5
diff -c -p -r1.5 streambuf.tcc
*** streambuf.tcc	2001/03/04 21:34:01	1.5
--- streambuf.tcc	2001/03/27 03:37:56
*************** namespace std {
*** 131,140 ****
  	  if (__ret < __n)
  	    {
  	      int_type __c = this->uflow();  
! 	      if (traits_type::eq_int_type(__c, traits_type::eof()))
  		break;
- 	      traits_type::assign(*__s++, traits_type::to_char_type(__c));
- 	      ++__ret;
  	    }
  	}
        return __ret;
--- 131,143 ----
  	  if (__ret < __n)
  	    {
  	      int_type __c = this->uflow();  
! 	      if (__c != traits_type::eof())
! 		{
! 		  traits_type::assign(*__s++, traits_type::to_char_type(__c));
! 		  ++__ret;
! 		}
! 	      else
  		break;
  	    }
  	}
        return __ret;
*************** namespace std {
*** 166,177 ****
  
  	  if (__ret < __n)
  	    {
! 	      int_type __c = traits_type::to_int_type(*__s);
! 	      int_type __overfc = this->overflow(__c);
! 	      if (traits_type::eq_int_type(__overfc, traits_type::eof()))
  		break;
- 	      ++__ret;
- 	      ++__s;
  	    }
  	}
        return __ret;
--- 169,182 ----
  
  	  if (__ret < __n)
  	    {
! 	      int_type __c = this->overflow(traits_type::to_int_type(*__s));
! 	      if (__c != traits_type::eof())
! 		{
! 		  ++__ret;
! 		  ++__s;
! 		}
! 	      else
  		break;
  	    }
  	}
        return __ret;
Index: src/ios.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/src/ios.cc,v
retrieving revision 1.15
diff -c -p -r1.15 ios.cc
*** ios.cc	2001/03/04 21:34:02	1.15
--- ios.cc	2001/03/27 03:37:58
*************** namespace std 
*** 140,148 ****
  	// NB: std_iostream.h creates the four standard files with
  	// NULL buffers. At this point, we swap out these placeholder
  	// objects for the properly-constructed ones
!        	_M_cout = new filebuf(1, "stdout", ios_base::out);
! 	_M_cin = new filebuf(0, "stdin", ios_base::in);
! 	_M_cerr = new filebuf(2, "stderr", ios_base::out);
  	new (&cout) ostream(_M_cout);
  	new (&cin) istream(_M_cin);
  	new (&cerr) ostream(_M_cerr);
--- 140,148 ----
  	// NB: std_iostream.h creates the four standard files with
  	// NULL buffers. At this point, we swap out these placeholder
  	// objects for the properly-constructed ones
!        	_M_cout = new filebuf(stdout, ios_base::out);
! 	_M_cin = new filebuf(stdin, ios_base::in);
! 	_M_cerr = new filebuf(stderr, ios_base::out);
  	new (&cout) ostream(_M_cout);
  	new (&cin) istream(_M_cin);
  	new (&cerr) ostream(_M_cerr);
*************** namespace std 
*** 151,159 ****
  	cerr.flags(ios_base::unitbuf);
  
  #ifdef _GLIBCPP_USE_WCHAR_T
! 	_M_wcout = new wfilebuf(1, "stdout", ios_base::out);
! 	_M_wcin = new wfilebuf(0, "stdin", ios_base::in);
! 	_M_wcerr = new wfilebuf(2, "stderr", ios_base::out);
  	new (&wcout) wostream(_M_wcout);
  	new (&wcin) wistream(_M_wcin);
  	new (&wcerr) wostream(_M_wcerr);
--- 151,159 ----
  	cerr.flags(ios_base::unitbuf);
  
  #ifdef _GLIBCPP_USE_WCHAR_T
! 	_M_wcout = new wfilebuf(stdout, ios_base::out);
! 	_M_wcin = new wfilebuf(stdin, ios_base::in);
! 	_M_wcerr = new wfilebuf(stderr, ios_base::out);
  	new (&wcout) wostream(_M_wcout);
  	new (&wcin) wistream(_M_wcin);
  	new (&wcerr) wostream(_M_wcerr);
Index: testsuite/27_io/filebuf_members.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/filebuf_members.cc,v
retrieving revision 1.5
diff -c -p -r1.5 filebuf_members.cc
*** filebuf_members.cc	2001/01/25 04:09:21	1.5
--- filebuf_members.cc	2001/03/27 03:37:58
*************** test_01()
*** 49,76 ****
    int close_num;
  
    // read (ext)
!   int fd = open(name_01, O_RDONLY);
!   VERIFY( fd >= 0 );
! 
    {
!     std::filebuf fb(fd, "double_read", std::ios_base::in);
    }
!   
!   close_num = close(fd);
    VERIFY( close_num == 0 );
  
  
    // read (standard)
    FILE* f = fopen(name_01, "r");
    VERIFY( f != NULL );
- 
    {
      std::ifstream ifstream1(name_01);
      VERIFY( ifstream1.is_open() );
      std::ios_base::iostate st01 = ifstream1.rdstate();
      VERIFY( st01 == std::ios_base::goodbit );
    }
-   
    close_num = fclose(f);
    VERIFY( close_num == 0 );
  
--- 49,72 ----
    int close_num;
  
    // read (ext)
!   FILE* f2 = fopen(name_01, "r");
!   VERIFY( f2 != NULL );
    {
!     std::filebuf fb(f2, std::ios_base::in);
    }
!   close_num = fclose(f2);
    VERIFY( close_num == 0 );
  
  
    // read (standard)
    FILE* f = fopen(name_01, "r");
    VERIFY( f != NULL );
    {
      std::ifstream ifstream1(name_01);
      VERIFY( ifstream1.is_open() );
      std::ios_base::iostate st01 = ifstream1.rdstate();
      VERIFY( st01 == std::ios_base::goodbit );
    }
    close_num = fclose(f);
    VERIFY( close_num == 0 );
  
Index: testsuite/27_io/ios_base_members_static.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/testsuite/27_io/ios_base_members_static.cc,v
retrieving revision 1.5
diff -c -p -r1.5 ios_base_members_static.cc
*** ios_base_members_static.cc	2001/02/05 22:08:47	1.5
--- ios_base_members_static.cc	2001/03/27 03:37:59
*************** void
*** 36,58 ****
  test01()
  {
    std::ios_base::sync_with_stdio();
-  
    std::freopen("ios_base_members_static-1.txt", "w", stdout);
   
    for (int i = 0; i < 2; i++)
      {
        std::printf("1");
        std::cout << "2";
!       std::putc('3', stdout); // std::stdout doesn't work here
        std::cout << '4';
        std::fputs("5", stdout);
        std::cout << 6;
        std::putchar('7');
        std::cout << 8 << '9';
!       if (i)
! 	std::printf ("0\n");
!       else
! 	std::cout << "0" << std::endl;
      }
  }
  
--- 36,54 ----
  test01()
  {
    std::ios_base::sync_with_stdio();
    std::freopen("ios_base_members_static-1.txt", "w", stdout);
   
    for (int i = 0; i < 2; i++)
      {
        std::printf("1");
        std::cout << "2";
!       std::putc('3', stdout); 
        std::cout << '4';
        std::fputs("5", stdout);
        std::cout << 6;
        std::putchar('7');
        std::cout << 8 << '9';
!       std::printf("0\n");
      }
  }
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]