This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH provide new non-standard interface; prefer to use it
- To: libstdc++ at gcc dot gnu dot org
- Subject: PATCH provide new non-standard interface; prefer to use it
- From: Loren James Rittle <rittle at latour dot rsch dot comm dot mot dot com>
- Date: Wed, 17 Jan 2001 06:40:36 -0600 (CST)
- CC: gcc-patches at gcc dot gnu dot org
- Reply-to: rittle at rsch dot comm dot mot dot com
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);