// Input streams -*- C++ -*-

// Copyright (C) 1997-1999 Cygnus Solutions
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING.  If not, write to the Free
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.

// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

//
// ISO C++ 14882: 27.6.1  Input streams
//

#ifndef _CPP_ISTREAM
#define _CPP_ISTREAM	1

#include <bits/std_ios.h>
#include <bits/sbuf_iter.h>
#include <bits/std_limits.h> // For numeric_limits

namespace std {

  // 27.6.1.1 Template class basic_istream
  template<typename _CharT, typename _Traits>
    class basic_istream : virtual public basic_ios<_CharT, _Traits>
    {
      // Types (inherited from basic_ios (27.4.4)):
      typedef _CharT                     		char_type;
      typedef typename _Traits::int_type 		int_type;
      typedef typename _Traits::pos_type 		pos_type;
      typedef typename _Traits::off_type 		off_type;
      typedef _Traits                    		traits_type;
      
      // Non-standard Types:
      typedef basic_streambuf<_CharT, _Traits> 		__streambuf_type;
      typedef basic_ios<_CharT, _Traits>		__ios_type;
      typedef basic_istream<_CharT, _Traits>		__istream_type;
      typedef istreambuf_iterator<_CharT>		__istreambuf_iter;
      typedef num_get<_CharT, __istreambuf_iter>        __numget_type;

    protected:
      // Data Members:
      streamsize 		_M_gcount;
      const __numget_type* 	_M_fnumget;

    public:
      // 27.6.1.1.1 Constructor/destructor:
      explicit 
      basic_istream(__streambuf_type* __sb) : __ios_type(__sb)  
      { 
	// XXX Need to fix for imbue events, as currently _M_fnumput
	// is not updated on pubimbue calls. Need a callback? Needs to
	// be moved down do basic_ios??
	_M_gcount = streamsize(0);
	_M_fnumget =  &use_facet<__numget_type>(this->getloc());
      }

      // Needed for [io]stringstream/[io]fstream classes. This assumes
      // that basic_ios has already been initialized _M_streambuf with
      // some relevant buffer.
      explicit 
      basic_istream() 
      { 
	// XXX Need to fix for imbue events, as currently _M_fnumput
	// is not updated on pubimbue calls. Need a callback? Needs to
	// be moved down do basic_ios??
	_M_gcount = streamsize(0);
	_M_fnumget =  &use_facet<__numget_type>(this->getloc());
      }

      virtual 
      ~basic_istream() 
      {
	_M_gcount = streamsize(0);
	_M_fnumget = NULL; 
      }

      // 27.6.1.1.2 Prefix/suffix:
      class sentry;
      friend class sentry;

      // 27.6.1.2 Formatted input:
      // 27.6.1.2.3 basic_istream::operator>>
      __istream_type&
      operator>>(__istream_type& (*__pf)(__istream_type&))
      {
	sentry __cerb(*this);
	if (__cerb) 
	  {
	    try {
	      __pf(*this);
	    }
	    catch(exception& __fail){
	      // 27.6.1.2.1 Common requirements.
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      __istream_type&
      operator>>(__ios_type& (*__pf)(__ios_type&))
      {
	sentry __cerb(*this);
	if (__cerb) 
	  {
	    try {
	      __pf(*this);
	    }
	    catch(exception& __fail){
	      // 27.6.1.2.1 Common requirements.
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      __istream_type&
      operator>>(ios_base& (*__pf)(ios_base&))
      {
	sentry __cerb(*this);
	if (__cerb) 
	  {
	    try {
	      __pf(*this);
	    }
	    catch(exception& __fail){
	      // 27.6.1.2.1 Common requirements.
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }
      
      // 27.6.1.2.2 Arithmetic Extractors
      __istream_type& 
      operator>>(bool& __n);
      
      __istream_type& 
      operator>>(short& __n);
      
      __istream_type& 
      operator>>(unsigned short& __n);

      __istream_type& 
      operator>>(int& __n);
      
      __istream_type& 
      operator>>(unsigned int& __n);

      __istream_type& 
      operator>>(long& __n);
      
      __istream_type& 
      operator>>(unsigned long& __n);

#ifdef _GLIBCPP_USE_LONG_LONG
      __istream_type& 
      operator>>(long long& __n);

      __istream_type& 
      operator>>(unsigned long long& __n);
#endif

      __istream_type& 
      operator>>(float& __f);

      __istream_type& 
      operator>>(double& __f);

      __istream_type& 
      operator>>(long double& __f);

      __istream_type& 
      operator>>(void*& __p);

      __istream_type& 
      operator>>(__streambuf_type* __sb);
      
      // 27.6.1.3 Unformatted input:
      streamsize 
      gcount() const 
      { return _M_gcount; }
      
      int_type 
      get()
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	int_type __retval;
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      __retval = this->rdbuf()->sbumpc();
	      // 27.6.1.1 paragraph 3
	      if (__retval != __eof)
		_M_gcount = 1;
	      else
		this->setstate(ios_base::eofbit | ios_base::failbit);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	else
	  __retval = __eof;
	return __retval;
      }

      __istream_type& 
      get(char_type& __c)
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	int_type __bufval;
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      __bufval = this->rdbuf()->sbumpc();
	      // 27.6.1.1 paragraph 3
	      if (__bufval != __eof)
		{
		  _M_gcount = 1;
		  __c = traits_type::to_char_type(__bufval);
		}
	      else
		this->setstate(ios_base::eofbit | ios_base::failbit);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      __istream_type& 
      get(char_type* __s, streamsize __n, char_type __delim)
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	int_type __idelim = traits_type::to_int_type(__delim);
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      for (; _M_gcount < __n; ++_M_gcount)
		{
		  int_type __bufval = this->rdbuf()->sbumpc();
		  if (__bufval == __eof)
		    {
		      this->setstate(ios_base::eofbit | ios_base::failbit);
		      break;
		    }
		  if (__idelim == __bufval)
		    {
		      this->rdbuf()->sputbackc(__bufval);		      
		      break;
		    }
		  *__s = traits_type::to_char_type(__bufval);
		  ++__s;
		}
	      if (!_M_gcount)
		this->setstate(ios_base::failbit);
	      *__s = char_type(NULL);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      __istream_type& 
      get(char_type* __s, streamsize __n)
      { return get(__s, __n, widen('\n')); }

      __istream_type&
      get(__streambuf_type& __sb, char_type __delim)
      {
	sentry __cerb(*this);
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      int_type __eof = traits_type::eof();	      
	      __streambuf_type* __this_sb = this->rdbuf();
	      streamsize __n = __this_sb->in_avail();
	      for (; _M_gcount < __n; ++_M_gcount)
		{
		  int_type __bufval = __this_sb->sbumpc();
		  if (__bufval == __eof)
		    {
		      this->setstate(ios_base::eofbit);
		      break;
		    }
		  __bufval = traits_type::to_char_type(__bufval);
		  if (__this_sb->_M_fctype->is(__delim, __bufval))
		    {
		      __this_sb->sputbackc(__bufval);
		      break;
		    }
		  int_type __g = __sb.sputc(__bufval);
		  if (__g == __eof)
		    {
		      __this_sb->sputbackc(__bufval);		      
		      break;
		    }
		}
	    }
	    catch(exception& __fail){
	      // "...the exception is caught but not rethrown."
	    }
	    if (!_M_gcount)
	      this->setstate(ios_base::failbit);
	  }
	return *this;
      }

      __istream_type&
      get(__streambuf_type& __sb)
      { return get(__sb, widen('\n')); }

      __istream_type& 
      getline(char_type* __s, streamsize __n, char_type __delim)
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      for (; _M_gcount < __n; ++_M_gcount)
		{
		  int_type __bufval = this->rdbuf()->sbumpc();
		  if (__bufval == __eof)
		    {
		      this->setstate(ios_base::eofbit);
		      break;
		    }
		  if (this->rdbuf()->_M_fctype->is(__delim, __bufval))
		    {
		      this->rdbuf()->sputbackc(__bufval);		      
		      break;
		    }
		  *__s = traits_type::to_char_type(__bufval);
		  ++__s;
		}
	      if (!_M_gcount || _M_gcount == __n - 1)
		this->setstate(ios_base::failbit);
	      *__s = char_type(NULL);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }
      __istream_type& 
      getline(char_type* __s, streamsize __n)
      { return getline(__s, __n, widen('\n')); }

      __istream_type& 
      ignore(streamsize __n = 1, int_type __delim = traits_type::eof())
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	_M_gcount = 0;
	if (__cerb && __n != numeric_limits<int>::max()) 
	  {
	    try {
	      for (; _M_gcount < __n; ++_M_gcount)
		{
		  int_type __bufval = this->rdbuf()->sbumpc();
		  if (__bufval == __eof)
		    {
		      this->setstate(ios_base::eofbit);
		      break;
		    }
		  if (this->rdbuf()->_M_fctype->is(__delim, __bufval))
		      break;
		}
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }
      
      int_type 
      peek()
      {
	sentry __cerb(*this);
	int_type __retval = traits_type::eof();
	_M_gcount = 0;
	if (__cerb && this->good())
	  {
	    try {
	      __retval = this->rdbuf()->sgetc();
	      _M_gcount = 1;
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  } 
	return __retval;
      }
      
      __istream_type& 
      read(char_type* __s, streamsize __n)
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      if (this->good())
		{
		  for (; _M_gcount <= __n; ++_M_gcount)
		    {
		      int_type __bufval = this->rdbuf()->sbumpc();
		      if (__bufval == __eof)
			{
			  this->setstate(ios_base::eofbit | ios_base::failbit);
			  break;
			}
		      *__s = traits_type::to_char_type(__bufval);
		      ++__s;
		    }
		}
	      else
		this->setstate(ios_base::failbit);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      streamsize 
      readsome(char_type* __s, streamsize __n)
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      if (this->good())
		{
		  streamsize __num = this->rdbuf()->in_avail();
		  if (__num != __eof)
		    {
		      __num = min(__num, __n);
		      _M_gcount = this->rdbuf()->sgetn(__s, __num);
		    }
		  else
		    this->setstate(ios_base::eofbit);		    
		}
	      else
		this->setstate(ios_base::failbit);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return _M_gcount;
      }
      
      __istream_type& 
      putback(char_type __c)
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      if (this->good())
		{
		  __streambuf_type* __sb = this->rdbuf();
		  if (!__sb || __eof == __sb->sputbackc(__c)) 
		    this->setstate(ios_base::badbit);		    
		}
	      else
		this->setstate(ios_base::failbit);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      __istream_type& 
      unget()
      {
	sentry __cerb(*this);
	int_type __eof = traits_type::eof();
	_M_gcount = 0;
	if (__cerb) 
	  {
	    try {
	      if (this->good())
		{
		  __streambuf_type* __sb = this->rdbuf();
		  if (!__sb || __eof == __sb->sungetc())
		    this->setstate(ios_base::badbit);		    
		}
	      else
		this->setstate(ios_base::failbit);
	    }
	    catch(exception& __fail){
	      // 27.6.1.3 paragraph 1
	      // Turn this on without causing an ios::failure to be thrown.
	      this->setstate(ios_base::badbit);
	      if ((this->exceptions() & ios_base::badbit) != 0)
		throw;
	    }
	  }
	return *this;
      }

      int 
      sync();

      pos_type 
      tellg();

      __istream_type& 
      seekg(pos_type);

      __istream_type& 
      seekg(off_type, ios_base::seekdir);
      
    };

  template<typename _CharT, typename _Traits>
    class basic_istream<_CharT, _Traits>::sentry
    {
      typedef basic_streambuf<_CharT, _Traits> 		__streambuf_type;
      typedef basic_istream<_CharT, _Traits> 		__istream_type;
      typedef _Traits 					traits_type;
      typedef typename _Traits::int_type		__int_type;
      bool _M_ok;
    public:
      explicit 
      sentry (basic_istream<_CharT, _Traits>& __is, bool __noskipws = false);

      operator bool() { return _M_ok; }
    };


  // 27.6.1.2.3 Character extraction templates:
  template<typename _CharT, typename _Traits>
    basic_istream<_CharT, _Traits>&
    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT& __c)
    {
      typedef basic_istream<char, _Traits> __istream_type;
      __istream_type::sentry __cerb(__in);
      if (__cerb)
	{
	  try {
	    __in.get(__c);
	  }
	  catch(exception& __fail){
	    // 27.6.1.2.1 Common requirements.
	    // Turn this on without causing an ios::failure to be thrown.
	    __in.setstate(ios_base::badbit);
	    if ((__in.exceptions() & ios_base::badbit) != 0)
	      throw;
	  }
	}
      return __in;
    }

  template<class _Traits>
    basic_istream<char, _Traits>&
    operator>>(basic_istream<char, _Traits>& __in, unsigned char& __c)
    {
      typedef basic_istream<char, _Traits> __istream_type;
      typedef unsigned char char_type;
      __istream_type::sentry __cerb(__in);
      if (__cerb)
	{
	  try {
	    char_type __tmp;
	    __in.get(__tmp);
	    __c = _Traits::narrow(__tmp, 0);
	  }
	  catch(exception& __fail){
	    // 27.6.1.2.1 Common requirements.
	    // Turn this on without causing an ios::failure to be thrown.
	    __in.setstate(ios_base::badbit);
	    if ((__in.exceptions() & ios_base::badbit) != 0)
	      throw;
	  }
	}
      return __in;
    }

  template<class _Traits>
    basic_istream<char, _Traits>&
    operator>>(basic_istream<char, _Traits>& __in, signed char& __c)
    {
      typedef basic_istream<char, _Traits> __istream_type;
      typedef signed char char_type;
      __istream_type::sentry __cerb(__in);
      if (__cerb)
	{
	  try {
	    char_type __tmp;
	    __in.get(__tmp);
	    __c = _Traits::narrow(__tmp,0);
	  }
	  catch(exception& __fail){
	    // 27.6.1.2.1 Common requirements.
	    // Turn this on without causing an ios::failure to be thrown.
	    __in.setstate(ios_base::badbit);
	    if ((__in.exceptions() & ios_base::badbit) != 0)
	      throw;
	  }
	}
      return __in;
    }

  template<typename _CharT, typename _Traits>
    basic_istream<_CharT, _Traits>&
    operator>>(basic_istream<_CharT, _Traits>& __in, _CharT* __s)
    {
      typedef basic_istream<char, _Traits> 		__istream_type;
      typedef typename _Traits::int_type 		int_type;
      typedef _CharT                     		char_type;
      
      __istream_type::sentry __cerb(__out);
      if (__cerb)
	{
	  try {
	    streamsize __num = __in.width();
	    if (__num > 0)
	      __in.read(__c, __num);
	    else
	      {
		// Figure out how many characters to extract.
		bool __testeof;
		bool __testspace;
		bool __testnull;
		char_type __tmp;
		char_type __default;
		int_type __eof = _Traits::eof();

		// XXX Works, but kind of kludgey. . . 
		do 
		  {
		    __in.get(__tmp);
		    __testeof = __tmp == __eof;
		    __testspace = __in->rdbuf()->_M_fctype->
		      				 is(ctype_base::space, __tmp); 
		    __testnull = __tmp == __default;	    
		    if (!__testeof && !__testspace && !__testnull)
		      {
			*__s = __tmp;
			++__s;
		      }
		  }
		while (!__testeof && !__testspace && !__testnull);
	      }

	    if (__num > 0)
	      __in.width(0);
	    else
	      __in.setstate(ios_base::failbit);
	  }
	  catch(exception& __fail){
	    // 27.6.1.2.1 Common requirements.
	    // Turn this on without causing an ios::failure to be thrown.
	    __in.setstate(ios_base::badbit);
	    if ((__in.exceptions() & ios_base::badbit) != 0)
	      throw;
	  }
	}
      return __in;
    }
  
  template<class _Traits>
    basic_istream<char,_Traits>&
    operator>>(basic_istream<char,_Traits>& __in, unsigned char* __s)
    {
      typedef basic_istream<char, _Traits> 		__istream_type;
      typedef typename _Traits::int_type 		int_type;
      typedef unsigned char                     	char_type;
      
      __istream_type::sentry __cerb(__out);
      if (__cerb)
	{
	  try {
	    streamsize __num = __in.width();
	    if (__num > 0)
	      __in.read(__c, __num);
	    else
	      {
		// Figure out how many characters to extract.
		bool __testeof;
		bool __testspace;
		bool __testnull;
		char_type __tmp;
		char_type __default;
		int_type __eof = _Traits::eof();

		// XXX Works, but kind of kludgey. . . 
		do 
		  {
		    __in.get(__tmp);
		    __testeof = __tmp == __eof;
		    __testspace = __in->_M_streambuf->_M_fctype->is(space, 
								    __tmp); 
		    __testnull = __tmp == __default;	    
		    if (!__testeof && !__testspace && !__testnull)
		      {
			*__s = __tmp;
			++__s;
		      }
		  }
		while (!__testeof && !__testspace && !__testnull);
	      }

	    if (__num > 0)
	      __in.width(0);
	    else
	      __in.setstate(ios_base::failbit);
	  }
	  catch(exception& __fail){
	    // 27.6.1.2.1 Common requirements.
	    // Turn this on without causing an ios::failure to be thrown.
	    __in.setstate(ios_base::badbit);
	    if ((__in.exceptions() & ios_base::badbit) != 0)
	      throw;
	  }
	}
      return __in;
    }

  template<class _Traits>
    basic_istream<char,_Traits>&
    operator>>(basic_istream<char,_Traits>& __in, signed char* __s)
    {
      typedef basic_istream<char, _Traits> 		__istream_type;
      typedef typename _Traits::int_type 		int_type;
      typedef signed char                     		char_type;
      
      __istream_type::sentry __cerb(__out);
      if (__cerb)
	{
	  try {
	    streamsize __num = __in.width();
	    if (__num > 0)
	      __in.read(__c, __num);
	    else
	      {
		// Figure out how many characters to extract.
		bool __testeof;
		bool __testspace;
		bool __testnull;
		char_type __tmp;
		char_type __default;
		int_type __eof = _Traits::eof();

		// XXX Works, but kind of kludgey. . . 
		do 
		  {
		    __in.get(__tmp);
		    __testeof = __tmp == __eof;
		    __testspace = __in->_M_streambuf->_M_fctype->is(space, 
								    __tmp); 
		    __testnull = __tmp == __default;	    
		    if (!__testeof && !__testspace && !__testnull)
		      {
			*__s = __tmp;
			++__s;
		      }
		  }
		while (!__testeof && !__testspace && !__testnull);
	      }

	    if (__num > 0)
	      __in.width(0);
	    else
	      __in.setstate(ios_base::failbit);
	  }
	  catch(exception& __fail){
	    // 27.6.1.2.1 Common requirements.
	    // Turn this on without causing an ios::failure to be thrown.
	    __in.setstate(ios_base::badbit);
	    if ((__in.exceptions() & ios_base::badbit) != 0)
	      throw;
	  }
	}
      return __in;
    }

  // 27.6.1.5 Template class basic_iostream
  template<typename _CharT, typename _Traits>
    class basic_iostream
    : public basic_istream<_CharT, _Traits>,
      public basic_ostream<_CharT, _Traits>
    {
      // Non-standard Types:
      typedef basic_istream<_CharT, _Traits>		__istream_type;
      typedef basic_ostream<_CharT, _Traits>		__ostream_type;

    public:
      explicit 
      basic_iostream(basic_streambuf<_CharT, _Traits>* __sb)
      : __istream_type(__sb), __ostream_type(__sb)
      { }

      virtual 
      ~basic_iostream() { }
    };

  // 27.6.1.4 Standard basic_istream manipulators
  template<typename _CharT, typename _Traits>
    basic_istream<_CharT, _Traits>& 
    ws(basic_istream<_CharT, _Traits>& __is);

} // namespace std

#ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
# define export
# include <bits/istream.tcc>
#endif

#endif	/* _CPP_ISTREAM */




