OSDN Git Service

PR libstdc++/4150
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Apr 2002 20:28:05 +0000 (20:28 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Apr 2002 20:28:05 +0000 (20:28 +0000)
        * include/std/std_streambuf.h (basic_streambuf::_M_set_indeterminate):
        Move to filebuf.
        (basic_streambuf::_M_set_determinate): Likewise.
        (basic_streambuf::_M_is_indeterminate): Likewise.
        * include/bits/std_fstream.h (basic_filebuf::_M_filepos): New
        non-static data member.
        (basic_filebuf::_M_underflow_common): New non-static member function.
        (basic_filebuf::_M_underflow, _M_uflow): Call it.
        (basic_filebuf::sync): Avoid useless seeking.
        (basic_filebuf::_M_set_indeterminate): Move here from streambuf.
        Set _M_filepos.
        (basic_filebuf::_M_set_determinate): Likewise.
        (basic_filebuf::_M_is_indeterminate): Likewise.
        * include/bits/fstream.tcc (basic_filebuf::_M_really_overflow): Seek
        back to _M_out_beg if necessary.
        (basic_filebuf::seekoff): Likewise.
        (basic_filebuf::_M_underflow_common): Generalization of old
        underflow().  Don't seek back to _M_in_beg.
        * src/ios.cc: Lose _GLIBCPP_AVOID_FSEEK stuff.
        * config/os/solaris/solaris2.?/bits/os_defines.h: Likewise.
        * config/os/bsd/freebsd/bits/os_defines.h: Likewise.
        * config/os/mingw32/bits/os_defines.h: Likewise.
        * testsuite/27_io/filebuf_virtuals.cc (test05): Don't overspecify
        ungetc test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52634 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/config/os/bsd/freebsd/bits/os_defines.h
libstdc++-v3/config/os/mingw32/bits/os_defines.h
libstdc++-v3/config/os/solaris/solaris2.5/bits/os_defines.h
libstdc++-v3/config/os/solaris/solaris2.6/bits/os_defines.h
libstdc++-v3/config/os/solaris/solaris2.7/bits/os_defines.h
libstdc++-v3/include/bits/fstream.tcc
libstdc++-v3/include/std/std_fstream.h
libstdc++-v3/include/std/std_streambuf.h
libstdc++-v3/src/ios.cc
libstdc++-v3/testsuite/27_io/filebuf_virtuals.cc

index 3ac23e5..61788e0 100644 (file)
@@ -1,3 +1,31 @@
+2002-04-20  Jason Merrill  <jason@redhat.com>
+
+       PR libstdc++/4150
+       * include/std/std_streambuf.h (basic_streambuf::_M_set_indeterminate): 
+       Move to filebuf.
+       (basic_streambuf::_M_set_determinate): Likewise.
+       (basic_streambuf::_M_is_indeterminate): Likewise.
+       * include/bits/std_fstream.h (basic_filebuf::_M_filepos): New 
+       non-static data member.
+       (basic_filebuf::_M_underflow_common): New non-static member function.
+       (basic_filebuf::_M_underflow, _M_uflow): Call it.
+       (basic_filebuf::sync): Avoid useless seeking.
+       (basic_filebuf::_M_set_indeterminate): Move here from streambuf.
+       Set _M_filepos.
+       (basic_filebuf::_M_set_determinate): Likewise.
+       (basic_filebuf::_M_is_indeterminate): Likewise.
+       * include/bits/fstream.tcc (basic_filebuf::_M_really_overflow): Seek
+       back to _M_out_beg if necessary.
+       (basic_filebuf::seekoff): Likewise.
+       (basic_filebuf::_M_underflow_common): Generalization of old 
+       underflow().  Don't seek back to _M_in_beg.
+       * src/ios.cc: Lose _GLIBCPP_AVOID_FSEEK stuff.
+       * config/os/solaris/solaris2.?/bits/os_defines.h: Likewise.
+       * config/os/bsd/freebsd/bits/os_defines.h: Likewise.
+       * config/os/mingw32/bits/os_defines.h: Likewise.
+       * testsuite/27_io/filebuf_virtuals.cc (test05): Don't overspecify 
+       ungetc test.
+
 2002-04-22  Benjamin Kosnik  <bkoz@redhat.com>
 
        * include/bits/istream.tcc (istream::read): Fix.
index 9e6bbaf..cfc917f 100644 (file)
@@ -36,6 +36,4 @@
 
 #define __glibcpp_long_double_bits __glibcpp_double_bits
 
-#define _GLIBCPP_AVOID_FSEEK 1
-
 #endif
index eb4bb1c..5c99e09 100644 (file)
@@ -34,7 +34,4 @@
 // System-specific #define, typedefs, corrections, etc, go here.  This
 // file will come before all others.
 
-#define _GLIBCPP_AVOID_FSEEK 1
-
-
 #endif
index 0edc784..145ae66 100644 (file)
@@ -33,8 +33,6 @@
 // System-specific #define, typedefs, corrections, etc, go here.  This
 // file will come before all others.
 
-#define _GLIBCPP_AVOID_FSEEK 1
-
 // These are typedefs which libio assumes are already in place (because
 // they really are, under Linux).
 #define __off_t     off_t
index 3acdf5c..7aa9a7e 100644 (file)
@@ -33,8 +33,6 @@
 // System-specific #define, typedefs, corrections, etc, go here.  This
 // file will come before all others.
 
-#define _GLIBCPP_AVOID_FSEEK 1
-
 // These are typedefs which libio assumes are already in place (because
 // they really are, under Linux).
 #define __off_t     off_t
index a0fd243..356c55c 100644 (file)
@@ -33,8 +33,6 @@
 // System-specific #define, typedefs, corrections, etc, go here.  This
 // file will come before all others.
 
-#define _GLIBCPP_AVOID_FSEEK 1
-
 // These are typedefs which libio assumes are already in place (because
 // they really are, under Linux).
 #define __off_t     off_t
index fb2f876..235b4a8 100644 (file)
@@ -206,7 +206,7 @@ namespace std
   template<typename _CharT, typename _Traits>
     typename basic_filebuf<_CharT, _Traits>::int_type 
     basic_filebuf<_CharT, _Traits>::
-    underflow()
+    _M_underflow_common(bool __bump)
     {
       int_type __ret = traits_type::eof();
       bool __testin = _M_mode & ios_base::in;
@@ -232,12 +232,8 @@ namespace std
            {
              if (__testout)
                _M_really_overflow();
-#if _GLIBCPP_AVOID_FSEEK
-             else if ((_M_in_cur - _M_in_beg) == 1)
-               _M_file.sys_getc();
-#endif
-             else 
-               _M_file.seekoff(_M_in_cur - _M_in_beg, 
+             else if (_M_in_cur != _M_filepos)
+               _M_file.seekoff(_M_in_cur - _M_filepos,
                                ios_base::cur, ios_base::in);
            }
 
@@ -280,16 +276,16 @@ namespace std
                  if (__testout)
                    _M_out_cur = _M_in_cur;
                  __ret = traits_type::to_int_type(*_M_in_cur);
-#if _GLIBCPP_AVOID_FSEEK
-                 if (__elen == 1)
-                   _M_file.sys_ungetc(*_M_in_cur);
-                 else
+                 if (__bump)
+                   _M_in_cur_move(1);
+                 else if (_M_buf_size == 1)
                    {
-#endif
-                     _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
-#if _GLIBCPP_AVOID_FSEEK
+                     // 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();
                    }
-#endif
                }          
            }
        }
@@ -464,6 +460,15 @@ namespace std
          streamsize __elen = 0;
          streamsize __plen = 0;
 
+         // Need to restore current position. The position of the external
+         // byte sequence (_M_file) corresponds to _M_filepos, and we need
+         // to move it to _M_out_beg for the write.
+         if (_M_filepos && _M_filepos != _M_out_beg)
+           {
+             off_type __off = _M_out_beg - _M_filepos;
+             _M_file.seekoff(__off, ios_base::cur);
+           }
+
          // Convert internal buffer to external representation, output.
          // NB: In the unbuffered case, no internal buffer exists. 
          if (!__testunbuffered)
@@ -551,9 +556,8 @@ namespace std
                  _M_output_unshift();
                }
              //in
-             // NB: underflow() rewinds the external buffer.
              else if (__testget && __way == ios_base::cur)
-               __computed_off += _M_in_cur - _M_in_beg;
+               __computed_off += _M_in_cur - _M_filepos;
          
              __ret = _M_file.seekoff(__computed_off, __way, __mode);
              _M_set_indeterminate();
index 4db2594..c0d80da 100644 (file)
@@ -93,6 +93,10 @@ namespace std
       // XXX Needed?
       bool                     _M_last_overflowed;
 
+      // The position in the buffer corresponding to the external file
+      // pointer.
+      char_type*               _M_filepos;
+
     public:
       // Constructors/destructor:
       basic_filebuf();
@@ -137,8 +141,21 @@ namespace std
       // underflow() and uflow() functions are called to get the next
       // charater from the real input source when the buffer is empty.
       // Buffered input uses underflow()
+
+      // The only difference between underflow() and uflow() is that the
+      // latter bumps _M_in_cur after the read.  In the sync_with_stdio
+      // case, this is important, as we need to unget the read character in
+      // the underflow() case in order to maintain synchronization.  So
+      // instead of calling underflow() from uflow(), we create a common
+      // subroutine to do the real work.
+      int_type
+      _M_underflow_common(bool __bump);
+
+      virtual int_type
+      underflow() { return _M_underflow_common(false); }
+
       virtual int_type
-      underflow();
+      uflow() { return _M_underflow_common(true); }
 
       virtual int_type
       pbackfail(int_type __c = _Traits::eof());
@@ -189,14 +206,11 @@ namespace std
        // the file position with the external file.
        if (__testput && !_M_file.sync())
          {
-           // Need to restore current position. This interpreted as
-           // the position of the external byte sequence (_M_file)
-           // plus the offset in the current internal buffer
-           // (_M_out_beg - _M_out_cur)
-           streamoff __cur = _M_file.seekoff(0, ios_base::cur);
-           off_type __off = _M_out_cur - _M_out_beg;
+           // Need to restore current position after the write.
+           off_type __off = _M_out_cur - _M_out_end;
            _M_really_overflow();
-           _M_file.seekpos(__cur + __off);
+           if (__off)
+             _M_file.seekoff(__off, ios_base::cur);
          }
        _M_last_overflowed = false;
        return 0;
@@ -235,6 +249,50 @@ namespace std
 
       void
       _M_output_unshift();
+
+      // These three functions are used to clarify internal buffer
+      // maintenance. After an overflow, or after a seekoff call that
+      // started at beg or end, or possibly when the stream becomes
+      // unbuffered, and a myrid other obscure corner cases, the
+      // internal buffer does not truly reflect the contents of the
+      // external buffer. At this point, for whatever reason, it is in
+      // an indeterminate state.
+      void
+      _M_set_indeterminate(void)
+      {
+       if (_M_mode & ios_base::in)
+         this->setg(_M_buf, _M_buf, _M_buf);
+       if (_M_mode & ios_base::out)
+         this->setp(_M_buf, _M_buf);
+       _M_filepos = _M_in_end;
+      }
+
+      void
+      _M_set_determinate(off_type __off)
+      {
+       bool __testin = _M_mode & ios_base::in;
+       bool __testout = _M_mode & ios_base::out;
+       if (__testin)
+         this->setg(_M_buf, _M_buf, _M_buf + __off);
+       if (__testout)
+         this->setp(_M_buf, _M_buf + __off);
+       _M_filepos = _M_in_end;
+      }
+
+      bool
+      _M_is_indeterminate(void)
+      { 
+       bool __ret = false;
+       // Don't return true if unbuffered.
+       if (_M_buf)
+         {
+           if (_M_mode & ios_base::in)
+             __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
+           if (_M_mode & ios_base::out)
+             __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
+         }
+       return __ret;
+      }
     };
 
 
index 53e1e08..012bf4e 100644 (file)
@@ -231,48 +231,6 @@ namespace std
        return __ret;
       }
 
-      // These three functions are used to clarify internal buffer
-      // maintenance. After an overflow, or after a seekoff call that
-      // started at beg or end, or possibly when the stream becomes
-      // unbuffered, and a myrid other obscure corner cases, the
-      // internal buffer does not truly reflect the contents of the
-      // external buffer. At this point, for whatever reason, it is in
-      // an indeterminate state.
-      void
-      _M_set_indeterminate(void)
-      {
-       if (_M_mode & ios_base::in)
-         this->setg(_M_buf, _M_buf, _M_buf);
-       if (_M_mode & ios_base::out)
-         this->setp(_M_buf, _M_buf);
-      }
-
-      void
-      _M_set_determinate(off_type __off)
-      {
-       bool __testin = _M_mode & ios_base::in;
-       bool __testout = _M_mode & ios_base::out;
-       if (__testin)
-         this->setg(_M_buf, _M_buf, _M_buf + __off);
-       if (__testout)
-         this->setp(_M_buf, _M_buf + __off);
-      }
-
-      bool
-      _M_is_indeterminate(void)
-      { 
-       bool __ret = false;
-       // Don't return true if unbuffered.
-       if (_M_buf)
-         {
-           if (_M_mode & ios_base::in)
-             __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
-           if (_M_mode & ios_base::out)
-             __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
-         }
-       return __ret;
-      }
-
   public:
       virtual 
       ~basic_streambuf() 
index 0aab0a2..1d97bf9 100644 (file)
@@ -150,14 +150,6 @@ namespace std
     int __out_bufsize = __sync ? 0 : static_cast<int>(BUFSIZ);
     int __in_bufsize = __sync ? 1 : static_cast<int>(BUFSIZ);
 
-#if _GLIBCPP_AVOID_FSEEK
-    // Platforms that prefer to avoid fseek() calls on streams only
-    // get their desire when the C++-layer input buffer size is 1.
-    // This hack hurts performance but keeps correctness across
-    // all types of streams that might be attached to (e.g.) cin.
-    __in_bufsize = 1;
-#endif
-
     // NB: The file globals.cc creates the four standard files
     // with NULL buffers. At this point, we swap out the dummy NULL
     // [io]stream objects and buffers with the real deal.
index 2609d26..fb370c3 100644 (file)
@@ -444,6 +444,9 @@ void test05()
   strmsz_1 = fb_03.sputn("because because because. . .", 28);  
   VERIFY( strmsz_1 == 28 );
   c1 = fb_03.sungetc();
+  // Defect?  retval of sungetc is not necessarily the character ungotten.
+  // So re-get it.
+  c1 = fb_03.sgetc();
   fb_03.pubsync(); 
   c3 = fb_03.sgetc();
   VERIFY( c1 == c3 );