xref: /openbsd/gnu/lib/libstdc++/libstdc++/src/ios.cc (revision c2fb3212)
103a78d15Sespie // Iostreams base classes -*- C++ -*-
203a78d15Sespie 
303a78d15Sespie // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
403a78d15Sespie // Free Software Foundation, Inc.
503a78d15Sespie //
603a78d15Sespie // This file is part of the GNU ISO C++ Library.  This library is free
703a78d15Sespie // software; you can redistribute it and/or modify it under the
803a78d15Sespie // terms of the GNU General Public License as published by the
903a78d15Sespie // Free Software Foundation; either version 2, or (at your option)
1003a78d15Sespie // any later version.
1103a78d15Sespie 
1203a78d15Sespie // This library is distributed in the hope that it will be useful,
1303a78d15Sespie // but WITHOUT ANY WARRANTY; without even the implied warranty of
1403a78d15Sespie // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1503a78d15Sespie // GNU General Public License for more details.
1603a78d15Sespie 
1703a78d15Sespie // You should have received a copy of the GNU General Public License along
1803a78d15Sespie // with this library; see the file COPYING.  If not, write to the Free
1903a78d15Sespie // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2003a78d15Sespie // USA.
2103a78d15Sespie 
2203a78d15Sespie // As a special exception, you may use this file as part of a free software
2303a78d15Sespie // library without restriction.  Specifically, if other files instantiate
2403a78d15Sespie // templates or use macros or inline functions from this file, or you compile
2503a78d15Sespie // this file and link it with other files to produce an executable, this
2603a78d15Sespie // file does not by itself cause the resulting executable to be covered by
2703a78d15Sespie // the GNU General Public License.  This exception does not however
2803a78d15Sespie // invalidate any other reasons why the executable file might be covered by
2903a78d15Sespie // the GNU General Public License.
3003a78d15Sespie 
3103a78d15Sespie //
3203a78d15Sespie // ISO C++ 14882: 27.4  Iostreams base classes
3303a78d15Sespie //
3403a78d15Sespie 
3503a78d15Sespie #include <ios>
3603a78d15Sespie #include <ostream>
3703a78d15Sespie #include <istream>
3803a78d15Sespie #include <fstream>
3903a78d15Sespie #include <bits/atomicity.h>
4003a78d15Sespie #include <ext/stdio_filebuf.h>
4103a78d15Sespie #ifdef _GLIBCPP_HAVE_UNISTD_H
4203a78d15Sespie #include <unistd.h>
4303a78d15Sespie #endif
4403a78d15Sespie 
4503a78d15Sespie namespace __gnu_cxx
4603a78d15Sespie {
4703a78d15Sespie   // Extern declarations for global objects in src/globals.cc.
4803a78d15Sespie   extern stdio_filebuf<char> buf_cout;
4903a78d15Sespie   extern stdio_filebuf<char> buf_cin;
5003a78d15Sespie   extern stdio_filebuf<char> buf_cerr;
5103a78d15Sespie 
52*c2fb3212Sespie #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T)
5303a78d15Sespie   extern stdio_filebuf<wchar_t> buf_wcout;
5403a78d15Sespie   extern stdio_filebuf<wchar_t> buf_wcin;
5503a78d15Sespie   extern stdio_filebuf<wchar_t> buf_wcerr;
5603a78d15Sespie #endif
5703a78d15Sespie } // namespace __gnu_cxx
5803a78d15Sespie 
5903a78d15Sespie namespace std
6003a78d15Sespie {
6103a78d15Sespie   using namespace __gnu_cxx;
6203a78d15Sespie 
6303a78d15Sespie   extern istream cin;
6403a78d15Sespie   extern ostream cout;
6503a78d15Sespie   extern ostream cerr;
6603a78d15Sespie   extern ostream clog;
6703a78d15Sespie 
68*c2fb3212Sespie #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T)
6903a78d15Sespie   extern wistream wcin;
7003a78d15Sespie   extern wostream wcout;
7103a78d15Sespie   extern wostream wcerr;
7203a78d15Sespie   extern wostream wclog;
7303a78d15Sespie #endif
7403a78d15Sespie 
7503a78d15Sespie   // Definitions for static const data members of __ios_flags.
7603a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_boolalpha;
7703a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_dec;
7803a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_fixed;
7903a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_hex;
8003a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_internal;
8103a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_left;
8203a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_oct;
8303a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_right;
8403a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_scientific;
8503a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_showbase;
8603a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_showpoint;
8703a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_showpos;
8803a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_skipws;
8903a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_unitbuf;
9003a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_uppercase;
9103a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_adjustfield;
9203a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_basefield;
9303a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_floatfield;
9403a78d15Sespie 
9503a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_badbit;
9603a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_eofbit;
9703a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_failbit;
9803a78d15Sespie 
9903a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_app;
10003a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_ate;
10103a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_bin;
10203a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_in;
10303a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_out;
10403a78d15Sespie   const __ios_flags::__int_type __ios_flags::_S_trunc;
10503a78d15Sespie 
10603a78d15Sespie   // Definitions for static const members of ios_base.
10703a78d15Sespie   const ios_base::fmtflags ios_base::boolalpha;
10803a78d15Sespie   const ios_base::fmtflags ios_base::dec;
10903a78d15Sespie   const ios_base::fmtflags ios_base::fixed;
11003a78d15Sespie   const ios_base::fmtflags ios_base::hex;
11103a78d15Sespie   const ios_base::fmtflags ios_base::internal;
11203a78d15Sespie   const ios_base::fmtflags ios_base::left;
11303a78d15Sespie   const ios_base::fmtflags ios_base::oct;
11403a78d15Sespie   const ios_base::fmtflags ios_base::right;
11503a78d15Sespie   const ios_base::fmtflags ios_base::scientific;
11603a78d15Sespie   const ios_base::fmtflags ios_base::showbase;
11703a78d15Sespie   const ios_base::fmtflags ios_base::showpoint;
11803a78d15Sespie   const ios_base::fmtflags ios_base::showpos;
11903a78d15Sespie   const ios_base::fmtflags ios_base::skipws;
12003a78d15Sespie   const ios_base::fmtflags ios_base::unitbuf;
12103a78d15Sespie   const ios_base::fmtflags ios_base::uppercase;
12203a78d15Sespie   const ios_base::fmtflags ios_base::adjustfield;
12303a78d15Sespie   const ios_base::fmtflags ios_base::basefield;
12403a78d15Sespie   const ios_base::fmtflags ios_base::floatfield;
12503a78d15Sespie 
12603a78d15Sespie   const ios_base::iostate ios_base::badbit;
12703a78d15Sespie   const ios_base::iostate ios_base::eofbit;
12803a78d15Sespie   const ios_base::iostate ios_base::failbit;
12903a78d15Sespie   const ios_base::iostate ios_base::goodbit;
13003a78d15Sespie 
13103a78d15Sespie   const ios_base::openmode ios_base::app;
13203a78d15Sespie   const ios_base::openmode ios_base::ate;
13303a78d15Sespie   const ios_base::openmode ios_base::binary;
13403a78d15Sespie   const ios_base::openmode ios_base::in;
13503a78d15Sespie   const ios_base::openmode ios_base::out;
13603a78d15Sespie   const ios_base::openmode ios_base::trunc;
13703a78d15Sespie 
13803a78d15Sespie   const ios_base::seekdir ios_base::beg;
13903a78d15Sespie   const ios_base::seekdir ios_base::cur;
14003a78d15Sespie   const ios_base::seekdir ios_base::end;
14103a78d15Sespie 
14203a78d15Sespie   const int ios_base::_S_local_word_size;
14303a78d15Sespie   int ios_base::Init::_S_ios_base_init = 0;
14403a78d15Sespie   bool ios_base::Init::_S_synced_with_stdio = true;
14503a78d15Sespie 
failure(const string & __str)14603a78d15Sespie   ios_base::failure::failure(const string& __str) throw()
14703a78d15Sespie   {
14803a78d15Sespie     strncpy(_M_name, __str.c_str(), _M_bufsize);
14903a78d15Sespie     _M_name[_M_bufsize - 1] = '\0';
15003a78d15Sespie   }
15103a78d15Sespie 
~failure()15203a78d15Sespie   ios_base::failure::~failure() throw()
15303a78d15Sespie   { }
15403a78d15Sespie 
15503a78d15Sespie   const char*
what() const15603a78d15Sespie   ios_base::failure::what() const throw()
15703a78d15Sespie   { return _M_name; }
15803a78d15Sespie 
15903a78d15Sespie   void
_S_ios_create(bool __sync)16003a78d15Sespie   ios_base::Init::_S_ios_create(bool __sync)
16103a78d15Sespie   {
16203a78d15Sespie     size_t __out_size = __sync ? 0 : static_cast<size_t>(BUFSIZ);
16303a78d15Sespie #ifdef _GLIBCPP_HAVE_ISATTY
16403a78d15Sespie     size_t __in_size =
16503a78d15Sespie       (__sync || isatty (0)) ? 1 : static_cast<size_t>(BUFSIZ);
16603a78d15Sespie #else
16703a78d15Sespie     size_t __in_size = 1;
16803a78d15Sespie #endif
16903a78d15Sespie 
17003a78d15Sespie     // NB: The file globals.cc creates the four standard files
17103a78d15Sespie     // with NULL buffers. At this point, we swap out the dummy NULL
17203a78d15Sespie     // [io]stream objects and buffers with the real deal.
17303a78d15Sespie     new (&buf_cout) stdio_filebuf<char>(stdout, ios_base::out, __out_size);
17403a78d15Sespie     new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size);
17503a78d15Sespie     new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size);
17603a78d15Sespie 
17703a78d15Sespie     new (&cout) ostream(&buf_cout);
17803a78d15Sespie     new (&cin) istream(&buf_cin);
17903a78d15Sespie     new (&cerr) ostream(&buf_cerr);
18003a78d15Sespie     new (&clog) ostream(&buf_cerr);
18103a78d15Sespie     cout.init(&buf_cout);
18203a78d15Sespie     cin.init(&buf_cin);
18303a78d15Sespie     cerr.init(&buf_cerr);
18403a78d15Sespie     clog.init(&buf_cerr);
18503a78d15Sespie     cin.tie(&cout);
18603a78d15Sespie     cerr.flags(ios_base::unitbuf);
18703a78d15Sespie 
188*c2fb3212Sespie #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T)
18903a78d15Sespie     new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
19003a78d15Sespie     new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
19103a78d15Sespie     new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
19203a78d15Sespie     new (&wcout) wostream(&buf_wcout);
19303a78d15Sespie     new (&wcin) wistream(&buf_wcin);
19403a78d15Sespie     new (&wcerr) wostream(&buf_wcerr);
19503a78d15Sespie     new (&wclog) wostream(&buf_wcerr);
19603a78d15Sespie     wcout.init(&buf_wcout);
19703a78d15Sespie     wcin.init(&buf_wcin);
19803a78d15Sespie     wcerr.init(&buf_wcerr);
19903a78d15Sespie     wclog.init(&buf_wcerr);
20003a78d15Sespie     wcin.tie(&wcout);
20103a78d15Sespie     wcerr.flags(ios_base::unitbuf);
20203a78d15Sespie #endif
20303a78d15Sespie   }
20403a78d15Sespie 
20503a78d15Sespie   void
_S_ios_destroy()20603a78d15Sespie   ios_base::Init::_S_ios_destroy()
20703a78d15Sespie   {
20803a78d15Sespie     // Explicitly call dtors to free any memory that is dynamically
20903a78d15Sespie     // allocated by filebuf ctor or member functions, but don't
21003a78d15Sespie     // deallocate all memory by calling operator delete.
21103a78d15Sespie     buf_cout.~stdio_filebuf();
21203a78d15Sespie     buf_cin.~stdio_filebuf();
21303a78d15Sespie     buf_cerr.~stdio_filebuf();
21403a78d15Sespie 
215*c2fb3212Sespie #if defined(_GLIBCPP_USE_WCHAR_T) || defined(_GLIBCPP_USE_TYPE_WCHAR_T)
21603a78d15Sespie     buf_wcout.~stdio_filebuf();
21703a78d15Sespie     buf_wcin.~stdio_filebuf();
21803a78d15Sespie     buf_wcerr.~stdio_filebuf();
21903a78d15Sespie #endif
22003a78d15Sespie   }
22103a78d15Sespie 
Init()22203a78d15Sespie   ios_base::Init::Init()
22303a78d15Sespie   {
22403a78d15Sespie     if (_S_ios_base_init == 0)
22503a78d15Sespie       {
22603a78d15Sespie 	// Standard streams default to synced with "C" operations.
22703a78d15Sespie 	ios_base::Init::_S_synced_with_stdio = true;
22803a78d15Sespie 	_S_ios_create(ios_base::Init::_S_synced_with_stdio);
22903a78d15Sespie       }
23003a78d15Sespie     ++_S_ios_base_init;
23103a78d15Sespie   }
23203a78d15Sespie 
~Init()23303a78d15Sespie   ios_base::Init::~Init()
23403a78d15Sespie   {
23503a78d15Sespie     if (--_S_ios_base_init == 0)
23603a78d15Sespie       _S_ios_destroy();
23703a78d15Sespie   }
23803a78d15Sespie 
23903a78d15Sespie   // 27.4.2.5  ios_base storage functions
24003a78d15Sespie   int
xalloc()24103a78d15Sespie   ios_base::xalloc() throw()
24203a78d15Sespie   {
24303a78d15Sespie     // Implementation note: Initialize top to zero to ensure that
24403a78d15Sespie     // initialization occurs before main() is started.
24503a78d15Sespie     static _Atomic_word _S_top = 0;
24603a78d15Sespie     return __exchange_and_add(&_S_top, 1) + 4;
24703a78d15Sespie   }
24803a78d15Sespie 
24903a78d15Sespie   // 27.4.2.5  iword/pword storage
25003a78d15Sespie   ios_base::_Words&
_M_grow_words(int ix)25103a78d15Sespie   ios_base::_M_grow_words(int ix)
25203a78d15Sespie   {
25303a78d15Sespie     // Precondition: _M_word_size <= ix
25403a78d15Sespie     int newsize = _S_local_word_size;
25503a78d15Sespie     _Words* words = _M_local_word;
25603a78d15Sespie     if (ix > _S_local_word_size - 1)
25703a78d15Sespie       {
25803a78d15Sespie 	if (ix < numeric_limits<int>::max())
25903a78d15Sespie 	  {
26003a78d15Sespie 	    newsize = ix + 1;
26103a78d15Sespie 	    try
26203a78d15Sespie 	      { words = new _Words[newsize]; }
26303a78d15Sespie 	    catch (...)
26403a78d15Sespie 	      {
26503a78d15Sespie 		_M_streambuf_state |= badbit;
26603a78d15Sespie 		if (_M_streambuf_state & _M_exception)
26703a78d15Sespie 		  __throw_ios_failure("ios_base::_M_grow_words failure");
26803a78d15Sespie 		return _M_word_zero;
26903a78d15Sespie 	      }
27003a78d15Sespie 	    for (int i = 0; i < _M_word_size; i++)
27103a78d15Sespie 	      words[i] = _M_word[i];
27203a78d15Sespie 	    if (_M_word && _M_word != _M_local_word)
27303a78d15Sespie 	      {
27403a78d15Sespie 		delete [] _M_word;
27503a78d15Sespie 		_M_word = 0;
27603a78d15Sespie 	      }
27703a78d15Sespie 	  }
27803a78d15Sespie 	else
27903a78d15Sespie 	  {
28003a78d15Sespie 	    _M_streambuf_state |= badbit;
28103a78d15Sespie 	    if (_M_streambuf_state & _M_exception)
28203a78d15Sespie 	      __throw_ios_failure("ios_base::_M_grow_words failure");
28303a78d15Sespie 	    return _M_word_zero;
28403a78d15Sespie 	  }
28503a78d15Sespie       }
28603a78d15Sespie     _M_word = words;
28703a78d15Sespie     _M_word_size = newsize;
28803a78d15Sespie     return _M_word[ix];
28903a78d15Sespie   }
29003a78d15Sespie 
29103a78d15Sespie   // Called only by basic_ios<>::init.
29203a78d15Sespie   void
_M_init()29303a78d15Sespie   ios_base::_M_init()
29403a78d15Sespie   {
29503a78d15Sespie     // NB: May be called more than once
29603a78d15Sespie     _M_precision = 6;
29703a78d15Sespie     _M_width = 0;
29803a78d15Sespie     _M_flags = skipws | dec;
29903a78d15Sespie     _M_ios_locale = locale();
30003a78d15Sespie   }
30103a78d15Sespie 
30203a78d15Sespie   // 27.4.2.3  ios_base locale functions
30303a78d15Sespie   locale
imbue(const locale & __loc)30403a78d15Sespie   ios_base::imbue(const locale& __loc)
30503a78d15Sespie   {
30603a78d15Sespie     locale __old = _M_ios_locale;
30703a78d15Sespie     _M_ios_locale = __loc;
30803a78d15Sespie     _M_call_callbacks(imbue_event);
30903a78d15Sespie     return __old;
31003a78d15Sespie   }
31103a78d15Sespie 
ios_base()31203a78d15Sespie   ios_base::ios_base() : _M_callbacks(0), _M_word_size(_S_local_word_size),
31303a78d15Sespie 			 _M_word(_M_local_word)
31403a78d15Sespie   {
31503a78d15Sespie     // Do nothing: basic_ios::init() does it.
31603a78d15Sespie     // NB: _M_callbacks and _M_word must be zero for non-initialized
31703a78d15Sespie     // ios_base to go through ~ios_base gracefully.
31803a78d15Sespie   }
31903a78d15Sespie 
32003a78d15Sespie   // 27.4.2.7  ios_base constructors/destructors
~ios_base()32103a78d15Sespie   ios_base::~ios_base()
32203a78d15Sespie   {
32303a78d15Sespie     _M_call_callbacks(erase_event);
32403a78d15Sespie     _M_dispose_callbacks();
32503a78d15Sespie     if (_M_word != _M_local_word)
32603a78d15Sespie       {
32703a78d15Sespie 	delete [] _M_word;
32803a78d15Sespie 	_M_word = 0;
32903a78d15Sespie       }
33003a78d15Sespie   }
33103a78d15Sespie 
33203a78d15Sespie   void
register_callback(event_callback __fn,int __index)33303a78d15Sespie   ios_base::register_callback(event_callback __fn, int __index)
33403a78d15Sespie   { _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); }
33503a78d15Sespie 
33603a78d15Sespie   void
_M_call_callbacks(event __e)33703a78d15Sespie   ios_base::_M_call_callbacks(event __e) throw()
33803a78d15Sespie   {
33903a78d15Sespie     _Callback_list* __p = _M_callbacks;
34003a78d15Sespie     while (__p)
34103a78d15Sespie       {
34203a78d15Sespie 	try
34303a78d15Sespie 	  { (*__p->_M_fn) (__e, *this, __p->_M_index); }
34403a78d15Sespie 	catch (...)
34503a78d15Sespie 	  { }
34603a78d15Sespie 	__p = __p->_M_next;
34703a78d15Sespie       }
34803a78d15Sespie   }
34903a78d15Sespie 
35003a78d15Sespie   void
_M_dispose_callbacks(void)35103a78d15Sespie   ios_base::_M_dispose_callbacks(void)
35203a78d15Sespie   {
35303a78d15Sespie     _Callback_list* __p = _M_callbacks;
35403a78d15Sespie     while (__p && __p->_M_remove_reference() == 0)
35503a78d15Sespie       {
35603a78d15Sespie 	_Callback_list* __next = __p->_M_next;
35703a78d15Sespie 	delete __p;
35803a78d15Sespie 	__p = __next;
35903a78d15Sespie       }
36003a78d15Sespie     _M_callbacks = 0;
36103a78d15Sespie   }
36203a78d15Sespie 
36303a78d15Sespie   bool
sync_with_stdio(bool __sync)36403a78d15Sespie   ios_base::sync_with_stdio(bool __sync)
36503a78d15Sespie   {
36603a78d15Sespie #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
36703a78d15Sespie     // 49.  Underspecification of ios_base::sync_with_stdio
36803a78d15Sespie     bool __ret = ios_base::Init::_S_synced_with_stdio;
36903a78d15Sespie #endif
37003a78d15Sespie 
37103a78d15Sespie     // Turn off sync with C FILE* for cin, cout, cerr, clog iff
37203a78d15Sespie     // currently synchronized.
37303a78d15Sespie     if (!__sync && __ret)
37403a78d15Sespie       {
37503a78d15Sespie 	ios_base::Init::_S_synced_with_stdio = false;
37603a78d15Sespie 	ios_base::Init::_S_ios_destroy();
37703a78d15Sespie 	ios_base::Init::_S_ios_create(ios_base::Init::_S_synced_with_stdio);
37803a78d15Sespie       }
37903a78d15Sespie     return __ret;
38003a78d15Sespie   }
38103a78d15Sespie }  // namespace std
382