This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[v3, 3.3 high] Fix libstdc++/9533
- From: Paolo Carlini <pcarlini at unitus dot it>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>, bkoz <bkoz at redhat dot com>
- Date: Thu, 01 May 2003 19:59:45 +0200
- Subject: [v3, 3.3 high] Fix libstdc++/9533
Hi everyone, hi Mark,
Benjamin kindly asked to have this high priority 3.3/3.4
regression fixed for 3.3.0 too.
Tested x86-linux (+ both our trunk 9533 testcases)
Ok for 3.3.0?
Thanks,
Paolo.
////////
2003-05-01 Paolo Carlini <pcarlini@unitus.it>
Nathan Myers <ncm@cantrip.org>
Backport from mainline fix of 2003-03-28.
PR libstdc++/9533
* include/bits/fstream.tcc (basic_filebuf<>::open): Don't
call underflow().
(basic_filebuf<>::showmanyc): Use the information provided
by codecvt and __basic_file<>::showmanyc_helper to implement
a non-trivial showmanyc.
* config/io/basic_file_stdio.h
(__basic_file<>::showmanyc_helper): New, declare.
* config/io/basic_file_stdio.cc
(__basic_file<>::showmanyc_helper): Define.
(__basic_file<>::_M_open_mode): Don't set O_NONBLOCK.
(__basic_file<char>::open): Don't call fcntl().
* acinclude.m4 (GLIBCPP_CHECK_S_ISREG_OR_S_IFREG,
GLIBCPP_CHECK_POLL): New macros.
* configure.in: Call here.
* acconfig.h: Add #undefs for the corresponding symbols.
* aclocal.m4: Regenerate.
* configure: Regenerate.
* config.h.in: Regenerate.
diff -urN libstdc++-v3-orig/acconfig.h libstdc++-v3/acconfig.h
--- libstdc++-v3-orig/acconfig.h 2002-11-13 23:49:20.000000000 +0100
+++ libstdc++-v3/acconfig.h 2003-05-01 19:12:02.000000000 +0200
@@ -135,6 +135,15 @@
// Define if the compiler/host combination has __builtin_sqrtl
#undef HAVE___BUILTIN_SQRTL
+// Define if poll is available in <poll.h>.
+#undef HAVE_POLL
+
+// Define if S_ISREG (Posix) is available in <sys/stat.h>.
+#undef HAVE_S_ISREG
+
+// Define if S_IFREG is available in <sys/stat.h>.
+#undef HAVE_S_IFREG
+
// Define if LC_MESSAGES is available in <locale.h>.
#undef HAVE_LC_MESSAGES
diff -urN libstdc++-v3-orig/acinclude.m4 libstdc++-v3/acinclude.m4
--- libstdc++-v3-orig/acinclude.m4 2003-02-28 09:18:04.000000000 +0100
+++ libstdc++-v3/acinclude.m4 2003-05-01 19:09:57.000000000 +0200
@@ -2144,6 +2144,45 @@
AC_DEFUN([AC_PROG_LD])
])
+dnl
+dnl Check whether S_ISREG (Posix) or S_IFREG is available in <sys/stat.h>.
+dnl
+
+AC_DEFUN(GLIBCPP_CHECK_S_ISREG_OR_S_IFREG, [
+ AC_CACHE_VAL(glibcpp_cv_S_ISREG, [
+ AC_TRY_LINK([#include <sys/stat.h>],
+ [struct stat buffer; fstat(0, &buffer); S_ISREG(buffer.st_mode); ],
+ [glibcpp_cv_S_ISREG=yes],
+ [glibcpp_cv_S_ISREG=no])
+ ])
+ AC_CACHE_VAL(glibcpp_cv_S_IFREG, [
+ AC_TRY_LINK([#include <sys/stat.h>],
+ [struct stat buffer; fstat(0, &buffer); S_IFREG & buffer.st_mode; ],
+ [glibcpp_cv_S_IFREG=yes],
+ [glibcpp_cv_S_IFREG=no])
+ ])
+ if test x$glibcpp_cv_S_ISREG = xyes; then
+ AC_DEFINE(HAVE_S_ISREG)
+ elif test x$glibcpp_cv_S_IFREG = xyes; then
+ AC_DEFINE(HAVE_S_IFREG)
+ fi
+])
+
+dnl
+dnl Check whether poll is available in <poll.h>.
+dnl
+
+AC_DEFUN(GLIBCPP_CHECK_POLL, [
+ AC_CACHE_VAL(glibcpp_cv_POLL, [
+ AC_TRY_COMPILE([#include <poll.h>],
+ [struct pollfd pfd[1]; pfd[0].events = POLLIN; poll(pfd, 1, 0); ],
+ [glibcpp_cv_POLL=yes],
+ [glibcpp_cv_POLL=no])
+ ])
+ if test x$glibcpp_cv_POLL = xyes; then
+ AC_DEFINE(HAVE_POLL)
+ fi
+])
# Check whether LC_MESSAGES is available in <locale.h>.
# Ulrich Drepper <drepper@cygnus.com>, 1995.
diff -urN libstdc++-v3-orig/config/io/basic_file_stdio.cc libstdc++-v3/config/io/basic_file_stdio.cc
--- libstdc++-v3-orig/config/io/basic_file_stdio.cc 2003-04-11 04:12:37.000000000 +0200
+++ libstdc++-v3/config/io/basic_file_stdio.cc 2003-05-01 19:21:17.000000000 +0200
@@ -34,6 +34,29 @@
#include <bits/basic_file.h>
#include <fcntl.h>
+#ifdef _GLIBCPP_HAVE_SYS_IOCTL_H
+#define BSD_COMP /* Get FIONREAD on Solaris2. */
+#include <sys/ioctl.h>
+#endif
+
+// Pick up FIONREAD on Solaris 2.5.
+#ifdef _GLIBCPP_HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#ifdef _GLIBCPP_HAVE_POLL
+#include <poll.h>
+#endif
+
+#if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG)
+# include <sys/stat.h>
+# ifdef _GLIBCPP_HAVE_S_ISREG
+# define _GLIBCPP_ISREG(x) S_ISREG(x)
+# else
+# define _GLIBCPP_ISREG(x) (((x) & S_IFMT) == S_IFREG)
+# endif
+#endif
+
namespace std
{
// Definitions for __basic_file<char>.
@@ -74,11 +97,7 @@
if (__testi && !__testo && !__testt && !__testa)
{
strcpy(__c_mode, "r");
-#if defined (O_NONBLOCK)
- __p_mode |= O_RDONLY | O_NONBLOCK;
-#else
__p_mode |= O_RDONLY;
-#endif
}
if (__testi && __testo && !__testt && !__testa)
{
@@ -154,13 +173,6 @@
if ((_M_cfile = fopen(__name, __c_mode)))
{
_M_cfile_created = true;
-
-#if defined (F_SETFL) && defined (O_NONBLOCK)
- // Set input to nonblocking for fifos.
- if (__mode & ios_base::in)
- fcntl(this->fd(), F_SETFL, O_NONBLOCK);
-#endif
-
__ret = this;
}
}
@@ -223,4 +235,34 @@
int
__basic_file<char>::sync()
{ return fflush(_M_cfile); }
+
+ streamsize
+ __basic_file<char>::showmanyc_helper()
+ {
+#ifdef FIONREAD
+ // Pipes and sockets.
+ int __num = 0;
+ int __r = ioctl(this->fd(), FIONREAD, &__num);
+ if (!__r && __num >= 0)
+ return __num;
+#endif
+
+#ifdef _GLIBCPP_HAVE_POLL
+ // Cheap test.
+ struct pollfd __pfd[1];
+ __pfd[0].fd = this->fd();
+ __pfd[0].events = POLLIN;
+ if (poll(__pfd, 1, 0) <= 0)
+ return 0;
+#endif
+
+#if defined(_GLIBCPP_HAVE_S_ISREG) || defined(_GLIBCPP_HAVE_S_IFREG)
+ // Regular files.
+ struct stat __buffer;
+ int __ret = fstat(this->fd(), &__buffer);
+ if (!__ret && _GLIBCPP_ISREG(__buffer.st_mode))
+ return __buffer.st_size - ftell(_M_cfile);
+#endif
+ return 0;
+ }
} // namespace std
diff -urN libstdc++-v3-orig/config/io/basic_file_stdio.h libstdc++-v3/config/io/basic_file_stdio.h
--- libstdc++-v3-orig/config/io/basic_file_stdio.h 2002-04-30 21:04:35.000000000 +0200
+++ libstdc++-v3/config/io/basic_file_stdio.h 2003-05-01 19:17:43.000000000 +0200
@@ -108,6 +108,9 @@
int
sync();
+
+ streamsize
+ showmanyc_helper();
};
} // namespace std
diff -urN libstdc++-v3-orig/configure.in libstdc++-v3/configure.in
--- libstdc++-v3-orig/configure.in 2003-02-28 09:18:15.000000000 +0100
+++ libstdc++-v3/configure.in 2003-05-01 19:10:54.000000000 +0200
@@ -412,6 +412,12 @@
GLIBCPP_CHECK_WCHAR_T_SUPPORT
GLIBCPP_CHECK_STDLIB_SUPPORT
GLIBCPP_CHECK_UNISTD_SUPPORT
+
+ # For showmanyc_helper().
+ AC_CHECK_HEADERS(sys/ioctl.h sys/filio.h)
+ GLIBCPP_CHECK_POLL
+ GLIBCPP_CHECK_S_ISREG_OR_S_IFREG
+
AC_LC_MESSAGES
AC_TRY_COMPILE([
diff -urN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
--- libstdc++-v3-orig/include/bits/fstream.tcc 2003-04-28 17:40:45.000000000 +0200
+++ libstdc++-v3/include/bits/fstream.tcc 2003-05-01 19:45:32.000000000 +0200
@@ -94,13 +94,6 @@
// Setup initial position of buffer.
_M_set_indeterminate();
- // Set input buffer to something real.
- // NB: Must open in non-blocking way to do this, or must
- // set the initial position in a different manner than
- // using underflow.
- if (__mode & ios_base::in && _M_buf_allocated)
- this->underflow();
-
if ((__mode & ios_base::ate)
&& this->seekoff(0, ios_base::end, __mode) < 0)
{
@@ -169,9 +162,16 @@
{
streamsize __ret = -1;
bool __testin = _M_mode & ios_base::in;
+ const locale __loc = this->getloc();
+ const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
if (__testin && this->is_open())
- __ret = _M_in_end - _M_in_cur;
+ {
+ __ret = _M_in_end - _M_in_cur;
+ if (__cvt.always_noconv())
+ __ret += _M_file.showmanyc_helper();
+ }
+
_M_last_overflowed = false;
return __ret;
}