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]

PATCH provide new non-standard interface; prefer to use it


Hi Benjamin,

I think you asked for this. ;-)

>> (2) since the __basic_file<_CharT>::sys_open([...]) entry point is
>>     completely non-standard w.r.t. ISO C++ could it be changed to:

>> __basic_file<_CharT>::sys_open(FILE* __fp, ios_base::openmode __mode)

>> That would remove the whole issue of dup() [which only had to be
>> introduced to work around semantics of fdopen()]; my hack (which you
>> wisely didn't take yet ;-) to map fd={0,1,2} to std{out,in,err}.

> Hmm. You know, half the people want FILE* ctors, half want fileno ctors. 
> Perhaps. Can you send a patch for this?

Patch summary: Provide a new non-standard interface for hooking
c{in,out,err} to std{in,out,err} that shares FILE*; prefer to use it
over the old non-standard interface while retaining the old interface
for existing users.  Without a rather large hack, the old non-standard
interface point appears to force one to construct a new FILE* even
when trying to relate c{in,out,err} to std{in,out,err}.  This
disconnect between the FILE* that is std{in,out,err} and that which is
used under the hood by c{in,out,err} causes synchronization problems
since there is no buffering relationship between distinct FILE*'s.

This patch includes no bits directly related to actually fixing
testsuite/27_io/mixed_io.cc; but is a prerequisite for that work since
any C++ IO scheme layered on C stdio that does not share the same FILE*
between c{in,out,err} and std{in,out,err} can never be synchronized.

Checked in already bootstrapped tree on i386-unknown-freebsd4.2 by
first rebuilding all of libstdc++-v3.

[Reminder: I have no CVS write access.  In any event, this should be
 checked elsewhere before commit.]

Regards,
Loren

2001-01-17  Loren J. Rittle  <ljrittle@acm.org>

	* testsuite/27_io/filebuf_members.cc (test_01): Add test for
	new non-standard constructor.  Note how the non-standard
	constructors are different.

	* config/c_io_stdio.cc (__basic_file<_CharT>::__basic_file):
	Initialize new field _M_tied.
	(__basic_file<_CharT>::~__basic_file): Handle files tied to
	preexisting FILE* streams.  In particular: do not close them.
	(__basic_file<_CharT>::close): Same.  Reset _M_tied.
	(__basic_file<_CharT>::sys_open): Only dup() once it is known
	that fd will actually be saved.
	(__basic_file<_CharT>::sys_tie): New function.

	* include/bits/basic_file.h (class __basic_file<_CharT>): Add new
        field _M_tied and method sys_tie.  Mark sys_open as obsolete.

	* include/bits/fstream.tcc (basic_filebuf<_CharT, _Traits>::
	basic_filebuf(__c_file_type* __f, ios_base::openmode __mode)):
	New constructor.

	* include/bits/std_fstream.h (class basic_filebuf<_CharT, _Traits>):
	Add new constructor.

	* src/ios.cc (ios_base::Init::Init): Switch to new non-standard
	filebuf constructor.

Index: testsuite/27_io/filebuf_members.cc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/testsuite/27_io/filebuf_members.cc,v
retrieving revision 1.4
diff -c -r1.4 filebuf_members.cc
*** filebuf_members.cc	2000/08/14 19:59:25	1.4
--- filebuf_members.cc	2001/01/17 11:48:07
***************
*** 46,52 ****
    bool test = true;
    int close_num;
  
!   // read (ext)
    int fd = open(name_01, O_RDONLY);
    VERIFY( fd >= 0 );
  
--- 46,52 ----
    bool test = true;
    int close_num;
  
!   // read (ext - dup()/fdopen() an already open fd)
    int fd = open(name_01, O_RDONLY);
    VERIFY( fd >= 0 );
  
***************
*** 55,60 ****
--- 55,72 ----
    }
    
    close_num = close(fd);
+   VERIFY( close_num == 0 );
+ 
+ 
+   // read (ext - reuse an already open FILE*)
+   FILE* xf = fopen(name_01, "r");
+   VERIFY( xf != 0 );
+ 
+   {
+     std::filebuf fb(xf, std::ios_base::in);
+   }
+   
+   close_num = fclose(xf);
    VERIFY( close_num == 0 );
  
  
Index: config/c_io_stdio.cc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/config/c_io_stdio.cc,v
retrieving revision 1.3
diff -c -r1.3 c_io_stdio.cc
*** c_io_stdio.cc	2001/01/06 02:44:10	1.3
--- c_io_stdio.cc	2001/01/17 11:48:07
***************
*** 39,45 ****
    // 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 
--- 39,45 ----
    // Generic definitions for __basic_file
    template<typename _CharT>
      __basic_file<_CharT>::__basic_file(__c_lock* /*__lock*/) 
!     : _M_fileno(-1), _M_cfile(NULL), _M_tied(false) { }
  
    template<typename _CharT>
      int 
***************
*** 52,58 ****
        if (this->is_open())
  	{
  	  fflush(_M_cfile);
! 	  this->close();
  	}
      }
        
--- 52,59 ----
        if (this->is_open())
  	{
  	  fflush(_M_cfile);
! 	  if (!_M_tied)
! 	    this->close();
  	}
      }
        
***************
*** 95,105 ****
  
        _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;
--- 96,106 ----
  
        _M_open_mode(__mode, __p_mode, __rw_mode, __c_mode);
  
!       if (!this->is_open())
  	{
! 	  int __dupfd = dup(__fd);
! 
! 	  if (__dupfd != -1 && (_M_cfile = fdopen(__dupfd, __c_mode)))
  	    {
  	      _M_fileno = __dupfd;
  	      __ret = this;
***************
*** 110,115 ****
--- 111,133 ----
      }
    
    template<typename _CharT>
+     __basic_file<_CharT>*
+     __basic_file<_CharT>::sys_tie(__c_file_type* __f)
+     {
+       __basic_file* __ret = NULL;
+ 
+       if (!this->is_open())
+ 	{
+ 	  _M_cfile = __f;
+ 	  _M_fileno = fileno(__f);
+ 	  _M_tied = true;
+ 	  __ret = this;
+ 	}
+ 
+       return __ret;
+     }
+   
+   template<typename _CharT>
      __basic_file<_CharT>* 
      __basic_file<_CharT>::open(const char* __name, ios_base::openmode __mode, 
  			       int /*__prot*/)
***************
*** 141,151 ****
      __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;
      }
--- 159,173 ----
      __basic_file<_CharT>::close()
      { 
        __basic_file* __retval = static_cast<__basic_file*>(NULL);
!       bool __testopen = true;
! 
!       if (!_M_tied)
!         __testopen = fclose(_M_cfile);
        if (!__testopen)
  	{
  	  __retval = this;
  	  _M_fileno = -1;
+ 	  _M_tied = false;
  	}  
        return __retval;
      }
Index: include/bits/basic_file.h
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/basic_file.h,v
retrieving revision 1.3
diff -c -r1.3 basic_file.h
*** basic_file.h	2000/11/12 03:27:10	1.3
--- basic_file.h	2001/01/17 11:48:07
***************
*** 121,126 ****
--- 121,127 ----
  #if _GLIBCPP_BASIC_FILE_ENCAPSULATION
        int 		_M_fileno;
        __c_file_type* 	_M_cfile;
+       bool		_M_tied;
  #endif
  #ifdef _GLIBCPP_USE_WCHAR_T
        __c_wfile_type	_M_wfile;
***************
*** 141,146 ****
--- 142,151 ----
        // and their wide-stream equivalents. Instead of calling open, it
        // just sets __c_file_type->_fileno and the respective _flags bits, and
        // returns.
+       __basic_file*
+       sys_tie(__c_file_type* __f);
+ 
+       // Obsolete.
        __basic_file*
        sys_open(int __fd, ios_base::openmode __mode);
  
Index: include/bits/fstream.tcc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/fstream.tcc,v
retrieving revision 1.4
diff -c -r1.4 fstream.tcc
*** fstream.tcc	2001/01/16 07:55:25	1.4
--- fstream.tcc	2001/01/17 11:48:07
***************
*** 112,117 ****
--- 112,140 ----
     }
  
    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_fcvt = &use_facet<__codecvt_type>(this->getloc());
+       _M_filebuf_init();
+       _M_file->sys_tie(__f);
+       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 (__f == stdin)
+ 	    _M_buf_size = 1;
+ 
+ 	  this->_M_set_indeterminate();
+ 	}
+    }
+ 
+   template<typename _CharT, typename _Traits>
      basic_filebuf<_CharT, _Traits>::__filebuf_type* 
      basic_filebuf<_CharT, _Traits>::
      open(const char* __s, ios_base::openmode __mode)
Index: include/bits/std_fstream.h
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/include/bits/std_fstream.h,v
retrieving revision 1.1
diff -c -r1.1 std_fstream.h
*** std_fstream.h	2000/10/05 11:27:01	1.1
--- std_fstream.h	2001/01/17 11:48:07
***************
*** 87,92 ****
--- 87,93 ----
  
        // Non-standard ctor:
        basic_filebuf(int __fd, const char* __name, ios_base::openmode __mode);
+       basic_filebuf(__c_file_type* __f, ios_base::openmode __mode);
  
        virtual 
        ~basic_filebuf() 
Index: src/ios.cc
===================================================================
RCS file: /cvs/gcc/egcs/libstdc++-v3/src/ios.cc,v
retrieving revision 1.12
diff -c -r1.12 ios.cc
*** ios.cc	2001/01/17 07:44:57	1.12
--- ios.cc	2001/01/17 11:48:08
***************
*** 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);
***************
*** 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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]