ios.cc revision 97403
1// Iostreams base classes -*- C++ -*-
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31//
32// ISO C++ 14882: 27.4  Iostreams base classes
33//
34
35#include <ios>
36#include <ostream>
37#include <istream>
38#include <fstream>
39#include <bits/atomicity.h>
40#include <ext/stdio_filebuf.h>
41
42namespace std
43{
44  // Extern declarations for global objects in src/globals.cc.
45  extern istream cin;
46  extern ostream cout;
47  extern ostream cerr;
48  extern ostream clog;
49
50  using __gnu_cxx::stdio_filebuf;
51  extern stdio_filebuf<char> buf_cout;
52  extern stdio_filebuf<char> buf_cin;
53  extern stdio_filebuf<char> buf_cerr;
54
55#ifdef _GLIBCPP_USE_WCHAR_T
56  extern wistream wcin;
57  extern wostream wcout;
58  extern wostream wcerr;
59  extern wostream wclog;
60
61  extern stdio_filebuf<wchar_t> buf_wcout;
62  extern stdio_filebuf<wchar_t> buf_wcin;
63  extern stdio_filebuf<wchar_t> buf_wcerr;
64#endif
65
66  // Definitions for static const data members of __ios_flags.
67  const __ios_flags::__int_type __ios_flags::_S_boolalpha;
68  const __ios_flags::__int_type __ios_flags::_S_dec;
69  const __ios_flags::__int_type __ios_flags::_S_fixed;
70  const __ios_flags::__int_type __ios_flags::_S_hex;
71  const __ios_flags::__int_type __ios_flags::_S_internal;
72  const __ios_flags::__int_type __ios_flags::_S_left;
73  const __ios_flags::__int_type __ios_flags::_S_oct;
74  const __ios_flags::__int_type __ios_flags::_S_right;
75  const __ios_flags::__int_type __ios_flags::_S_scientific;
76  const __ios_flags::__int_type __ios_flags::_S_showbase;
77  const __ios_flags::__int_type __ios_flags::_S_showpoint;
78  const __ios_flags::__int_type __ios_flags::_S_showpos;
79  const __ios_flags::__int_type __ios_flags::_S_skipws;
80  const __ios_flags::__int_type __ios_flags::_S_unitbuf;
81  const __ios_flags::__int_type __ios_flags::_S_uppercase;
82  const __ios_flags::__int_type __ios_flags::_S_adjustfield;
83  const __ios_flags::__int_type __ios_flags::_S_basefield;
84  const __ios_flags::__int_type __ios_flags::_S_floatfield;
85
86  const __ios_flags::__int_type __ios_flags::_S_badbit;
87  const __ios_flags::__int_type __ios_flags::_S_eofbit;
88  const __ios_flags::__int_type __ios_flags::_S_failbit;
89
90  const __ios_flags::__int_type __ios_flags::_S_app;
91  const __ios_flags::__int_type __ios_flags::_S_ate;
92  const __ios_flags::__int_type __ios_flags::_S_bin;
93  const __ios_flags::__int_type __ios_flags::_S_in;
94  const __ios_flags::__int_type __ios_flags::_S_out;
95  const __ios_flags::__int_type __ios_flags::_S_trunc;
96
97  // Definitions for static const members of ios_base.
98  const ios_base::fmtflags ios_base::boolalpha;
99  const ios_base::fmtflags ios_base::dec;
100  const ios_base::fmtflags ios_base::fixed;
101  const ios_base::fmtflags ios_base::hex;
102  const ios_base::fmtflags ios_base::internal;
103  const ios_base::fmtflags ios_base::left;
104  const ios_base::fmtflags ios_base::oct;
105  const ios_base::fmtflags ios_base::right;
106  const ios_base::fmtflags ios_base::scientific;
107  const ios_base::fmtflags ios_base::showbase;
108  const ios_base::fmtflags ios_base::showpoint;
109  const ios_base::fmtflags ios_base::showpos;
110  const ios_base::fmtflags ios_base::skipws;
111  const ios_base::fmtflags ios_base::unitbuf;
112  const ios_base::fmtflags ios_base::uppercase;
113  const ios_base::fmtflags ios_base::adjustfield;
114  const ios_base::fmtflags ios_base::basefield;
115  const ios_base::fmtflags ios_base::floatfield;
116
117  const ios_base::iostate ios_base::badbit;
118  const ios_base::iostate ios_base::eofbit;
119  const ios_base::iostate ios_base::failbit;
120  const ios_base::iostate ios_base::goodbit;
121
122  const ios_base::openmode ios_base::app;
123  const ios_base::openmode ios_base::ate;
124  const ios_base::openmode ios_base::binary;
125  const ios_base::openmode ios_base::in;
126  const ios_base::openmode ios_base::out;
127  const ios_base::openmode ios_base::trunc;
128
129  const ios_base::seekdir ios_base::beg;
130  const ios_base::seekdir ios_base::cur;
131  const ios_base::seekdir ios_base::end;
132
133  const int ios_base::_S_local_word_size;
134  int ios_base::Init::_S_ios_base_init = 0;
135  bool ios_base::Init::_S_synced_with_stdio = true;
136
137  ios_base::failure::failure(const string& __str) throw()
138  {
139    strncpy(_M_name, __str.c_str(), _M_bufsize);
140    _M_name[_M_bufsize - 1] = '\0';
141  }
142
143  ios_base::failure::~failure() throw()
144  { }
145
146  const char*
147  ios_base::failure::what() const throw()
148  { return _M_name; }
149
150  void
151  ios_base::Init::_S_ios_create(bool __sync)
152  {
153    int __out_size = __sync ? 0 : static_cast<int>(BUFSIZ);
154    int __in_size = __sync ? 1 : static_cast<int>(BUFSIZ);
155
156    // NB: The file globals.cc creates the four standard files
157    // with NULL buffers. At this point, we swap out the dummy NULL
158    // [io]stream objects and buffers with the real deal.
159    new (&buf_cout) stdio_filebuf<char>(stdout, ios_base::out, __out_size);
160    new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size);
161    new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size);
162    new (&cout) ostream(&buf_cout);
163    new (&cin) istream(&buf_cin);
164    new (&cerr) ostream(&buf_cerr);
165    new (&clog) ostream(&buf_cerr);
166    cin.tie(&cout);
167    cerr.flags(ios_base::unitbuf);
168
169#ifdef _GLIBCPP_USE_WCHAR_T
170    new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
171    new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
172    new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
173    new (&wcout) wostream(&buf_wcout);
174    new (&wcin) wistream(&buf_wcin);
175    new (&wcerr) wostream(&buf_wcerr);
176    new (&wclog) wostream(&buf_wcerr);
177    wcin.tie(&wcout);
178    wcerr.flags(ios_base::unitbuf);
179#endif
180  }
181
182  void
183  ios_base::Init::_S_ios_destroy()
184  {
185    // Explicitly call dtors to free any memory that is dynamically
186    // allocated by filebuf ctor or member functions, but don't
187    // deallocate all memory by calling operator delete.
188    buf_cout.~stdio_filebuf();
189    buf_cin.~stdio_filebuf();
190    buf_cerr.~stdio_filebuf();
191
192#ifdef _GLIBCPP_USE_WCHAR_T
193    buf_wcout.~stdio_filebuf();
194    buf_wcin.~stdio_filebuf();
195    buf_wcerr.~stdio_filebuf();
196#endif
197  }
198
199  ios_base::Init::Init()
200  {
201    if (_S_ios_base_init == 0)
202      {
203	// Standard streams default to synced with "C" operations.
204	ios_base::Init::_S_synced_with_stdio = true;
205	_S_ios_create(ios_base::Init::_S_synced_with_stdio);
206      }
207    ++_S_ios_base_init;
208  }
209
210  ios_base::Init::~Init()
211  {
212    if (--_S_ios_base_init == 0)
213      _S_ios_destroy();
214  }
215
216  // 27.4.2.5  ios_base storage functions
217  int
218  ios_base::xalloc() throw()
219  {
220    // Implementation note: Initialize top to zero to ensure that
221    // initialization occurs before main() is started.
222    static _Atomic_word _S_top = 0;
223    return __exchange_and_add(&_S_top, 1) + 4;
224  }
225
226  // 27.4.2.5  iword/pword storage
227  ios_base::_Words&
228  ios_base::_M_grow_words(int ix)
229  {
230    // Precondition: _M_word_size <= ix
231    int newsize = _S_local_word_size;
232    _Words* words = _M_local_word;
233    if (ix > _S_local_word_size - 1)
234      {
235	if (ix < numeric_limits<int>::max())
236	  {
237	    newsize = ix + 1;
238	    try
239	      { words = new _Words[newsize]; }
240	    catch (...)
241	      {
242		delete [] _M_word;
243		_M_word = 0;
244		_M_streambuf_state |= badbit;
245		if (_M_streambuf_state & _M_exception)
246		  __throw_ios_failure("ios_base::_M_grow_words failure");
247		return _M_word_zero;
248	      }
249	    for (int i = 0; i < _M_word_size; i++)
250	      words[i] = _M_word[i];
251	    if (_M_word && _M_word != _M_local_word)
252	      {
253		delete [] _M_word;
254		_M_word = 0;
255	      }
256	  }
257	else
258	  {
259	    _M_streambuf_state |= badbit;
260	    return _M_word_zero;
261	  }
262      }
263    _M_word = words;
264    _M_word_size = newsize;
265    return _M_word[ix];
266  }
267
268  // Called only by basic_ios<>::init.
269  void
270  ios_base::_M_init()
271  {
272    // NB: May be called more than once
273    _M_precision = 6;
274    _M_width = 0;
275    _M_flags = skipws | dec;
276    _M_callbacks = 0;
277    _M_word_size = 0;
278    _M_ios_locale = locale();
279  }
280
281  // 27.4.2.3  ios_base locale functions
282  locale
283  ios_base::imbue(const locale& __loc)
284  {
285    locale __old = _M_ios_locale;
286    _M_ios_locale = __loc;
287    _M_call_callbacks(imbue_event);
288    return __old;
289  }
290
291  ios_base::ios_base() : _M_callbacks(0), _M_word(0)
292  {
293    // Do nothing: basic_ios::init() does it.
294    // NB: _M_callbacks and _M_word must be zero for non-initialized
295    // ios_base to go through ~ios_base gracefully.
296  }
297
298  // 27.4.2.7  ios_base constructors/destructors
299  ios_base::~ios_base()
300  {
301    _M_call_callbacks(erase_event);
302    _M_dispose_callbacks();
303    if (_M_word && _M_word != _M_local_word)
304      {
305	delete [] _M_word;
306	_M_word = 0;
307      }
308  }
309
310  void
311  ios_base::register_callback(event_callback __fn, int __index)
312  { _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); }
313
314  void
315  ios_base::_M_call_callbacks(event __e) throw()
316  {
317    _Callback_list* __p = _M_callbacks;
318    while (__p)
319      {
320	try
321	  { (*__p->_M_fn) (__e, *this, __p->_M_index); }
322	catch (...)
323	  { }
324	__p = __p->_M_next;
325      }
326  }
327
328  void
329  ios_base::_M_dispose_callbacks(void)
330  {
331    _Callback_list* __p = _M_callbacks;
332    while (__p && __p->_M_remove_reference() == 0)
333      {
334	_Callback_list* __next = __p->_M_next;
335	delete __p;
336	__p = __next;
337      }
338    _M_callbacks = 0;
339  }
340
341  bool
342  ios_base::sync_with_stdio(bool __sync)
343  {
344#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
345    // 49.  Underspecification of ios_base::sync_with_stdio
346    bool __ret = ios_base::Init::_S_synced_with_stdio;
347#endif
348
349    // Turn off sync with C FILE* for cin, cout, cerr, clog iff
350    // currently synchronized.
351    if (!__sync && __ret)
352      {
353	ios_base::Init::_S_synced_with_stdio = false;
354	ios_base::Init::_S_ios_destroy();
355	ios_base::Init::_S_ios_create(ios_base::Init::_S_synced_with_stdio);
356      }
357    return __ret;
358  }
359}  // namespace std
360