Commit bbacb998 by Paolo Carlini Committed by Paolo Carlini

re PR libstdc++/9533 (Can't read from tty with ifstream)

2003-03-28  Paolo Carlini  <pcarlini@unitus.it>
	    Nathan Myers  <ncm@cantrip.org>

	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.

Co-Authored-By: Nathan Myers <ncm@cantrip.org>

From-SVN: r64978
parent d18ad191
2003-03-28 Paolo Carlini <pcarlini@unitus.it>
Nathan Myers <ncm@cantrip.org>
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.
2003-03-24 Benjamin Kosnik <bkoz@redhat.com> 2003-03-24 Benjamin Kosnik <bkoz@redhat.com>
* config/linker-map.gnu: Remove string export restrictions. * config/linker-map.gnu: Remove string export restrictions.
......
...@@ -135,6 +135,15 @@ ...@@ -135,6 +135,15 @@
// Define if the compiler/host combination has __builtin_sqrtl // Define if the compiler/host combination has __builtin_sqrtl
#undef HAVE___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>. // Define if LC_MESSAGES is available in <locale.h>.
#undef HAVE_LC_MESSAGES #undef HAVE_LC_MESSAGES
......
...@@ -2106,6 +2106,45 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN]) ...@@ -2106,6 +2106,45 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN])
AC_DEFUN([AC_PROG_LD]) 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>. # Check whether LC_MESSAGES is available in <locale.h>.
# Ulrich Drepper <drepper@cygnus.com>, 1995. # Ulrich Drepper <drepper@cygnus.com>, 1995.
......
...@@ -1932,7 +1932,11 @@ if test x"$glibcpp_toolexecdir" = x"no"; then ...@@ -1932,7 +1932,11 @@ if test x"$glibcpp_toolexecdir" = x"no"; then
glibcpp_toolexecdir='$(libdir)/gcc-lib/$(target_alias)' glibcpp_toolexecdir='$(libdir)/gcc-lib/$(target_alias)'
glibcpp_toolexeclibdir='$(libdir)' glibcpp_toolexeclibdir='$(libdir)'
fi fi
glibcpp_toolexeclibdir=$glibcpp_toolexeclibdir/`$CC -print-multi-os-directory` multi_os_directory=`$CC -print-multi-os-directory`
case $multi_os_directory in
.) ;; # Avoid trailing /.
*) glibcpp_toolexeclibdir=$glibcpp_toolexeclibdir/$multi_os_directory ;;
esac
fi fi
AC_MSG_CHECKING([for install location]) AC_MSG_CHECKING([for install location])
...@@ -2114,6 +2118,45 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN]) ...@@ -2114,6 +2118,45 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN])
AC_DEFUN([AC_PROG_LD]) 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>. # Check whether LC_MESSAGES is available in <locale.h>.
# Ulrich Drepper <drepper@cygnus.com>, 1995. # Ulrich Drepper <drepper@cygnus.com>, 1995.
......
...@@ -113,6 +113,15 @@ ...@@ -113,6 +113,15 @@
// Define if the compiler/host combination has __builtin_sqrtl // Define if the compiler/host combination has __builtin_sqrtl
#undef HAVE___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>. // Define if LC_MESSAGES is available in <locale.h>.
#undef HAVE_LC_MESSAGES #undef HAVE_LC_MESSAGES
...@@ -740,6 +749,12 @@ ...@@ -740,6 +749,12 @@
/* Define if you have the <string.h> header file. */ /* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H #undef HAVE_STRING_H
/* Define if you have the <sys/filio.h> header file. */
#undef HAVE_SYS_FILIO_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/isa_defs.h> header file. */ /* Define if you have the <sys/isa_defs.h> header file. */
#undef HAVE_SYS_ISA_DEFS_H #undef HAVE_SYS_ISA_DEFS_H
......
...@@ -36,6 +36,29 @@ ...@@ -36,6 +36,29 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.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 namespace std
{ {
// Definitions for __basic_file<char>. // Definitions for __basic_file<char>.
...@@ -76,11 +99,7 @@ namespace std ...@@ -76,11 +99,7 @@ namespace std
if (__testi && !__testo && !__testt && !__testa) if (__testi && !__testo && !__testt && !__testa)
{ {
strcpy(__c_mode, "r"); strcpy(__c_mode, "r");
#if defined (O_NONBLOCK)
__p_mode |= O_RDONLY | O_NONBLOCK;
#else
__p_mode |= O_RDONLY; __p_mode |= O_RDONLY;
#endif
} }
if (__testi && __testo && !__testt && !__testa) if (__testi && __testo && !__testt && !__testa)
{ {
...@@ -156,13 +175,6 @@ namespace std ...@@ -156,13 +175,6 @@ namespace std
if ((_M_cfile = fopen(__name, __c_mode))) if ((_M_cfile = fopen(__name, __c_mode)))
{ {
_M_cfile_created = true; _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; __ret = this;
} }
} }
...@@ -261,4 +273,38 @@ namespace std ...@@ -261,4 +273,38 @@ namespace std
int int
__basic_file<char>::sync() __basic_file<char>::sync()
{ return fflush(_M_cfile); } { return fflush(_M_cfile); }
streamsize
__basic_file<char>::showmanyc_helper(bool __stdio)
{
#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))
if (__stdio)
return __buffer.st_size - ftell(_M_cfile);
else
return __buffer.st_size - lseek(this->fd(), 0, ios_base::cur);
#endif
return 0;
}
} // namespace std } // namespace std
...@@ -108,6 +108,9 @@ namespace std ...@@ -108,6 +108,9 @@ namespace std
int int
sync(); sync();
streamsize
showmanyc_helper(bool __stdio);
}; };
} // namespace std } // namespace std
......
...@@ -411,6 +411,12 @@ else ...@@ -411,6 +411,12 @@ else
GLIBCPP_CHECK_COMPLEX_MATH_SUPPORT GLIBCPP_CHECK_COMPLEX_MATH_SUPPORT
GLIBCPP_CHECK_WCHAR_T_SUPPORT GLIBCPP_CHECK_WCHAR_T_SUPPORT
GLIBCPP_CHECK_STDLIB_SUPPORT GLIBCPP_CHECK_STDLIB_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_LC_MESSAGES
AC_TRY_COMPILE([ AC_TRY_COMPILE([
......
...@@ -96,13 +96,6 @@ namespace std ...@@ -96,13 +96,6 @@ namespace std
// Setup initial position of buffer. // Setup initial position of buffer.
_M_set_indeterminate(); _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) if ((__mode & ios_base::ate)
&& this->seekoff(0, ios_base::end, __mode) < 0) && this->seekoff(0, ios_base::end, __mode) < 0)
{ {
...@@ -164,9 +157,21 @@ namespace std ...@@ -164,9 +157,21 @@ namespace std
{ {
streamsize __ret = -1; streamsize __ret = -1;
bool __testin = this->_M_mode & ios_base::in; bool __testin = this->_M_mode & ios_base::in;
const locale __loc = this->getloc();
const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
// Sync with stdio.
bool __sync = this->_M_buf_size == 1;
if (__testin && this->is_open()) if (__testin && this->is_open())
__ret = this->_M_in_end - this->_M_in_cur; {
__ret = this->_M_in_end - this->_M_in_cur;
// For a stateful encoding (-1) the pending sequence might be just
// shift and unshift prefixes with no actual character.
if (__cvt.encoding() >= 0)
__ret += _M_file.showmanyc_helper(__sync) / __cvt.max_length();
}
_M_last_overflowed = false; _M_last_overflowed = false;
return __ret; return __ret;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment