ios.cc revision 110614
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#ifdef _GLIBCPP_HAVE_UNISTD_H
42#include <unistd.h>
43#endif
44
45namespace __gnu_cxx
46{
47  // Extern declarations for global objects in src/globals.cc.
48  extern stdio_filebuf<char> buf_cout;
49  extern stdio_filebuf<char> buf_cin;
50  extern stdio_filebuf<char> buf_cerr;
51
52#ifdef _GLIBCPP_USE_WCHAR_T
53  extern stdio_filebuf<wchar_t> buf_wcout;
54  extern stdio_filebuf<wchar_t> buf_wcin;
55  extern stdio_filebuf<wchar_t> buf_wcerr;
56#endif
57} // namespace __gnu_cxx
58
59namespace std
60{
61  using namespace __gnu_cxx;
62
63  extern istream cin;
64  extern ostream cout;
65  extern ostream cerr;
66  extern ostream clog;
67
68#ifdef _GLIBCPP_USE_WCHAR_T
69  extern wistream wcin;
70  extern wostream wcout;
71  extern wostream wcerr;
72  extern wostream wclog;
73#endif
74
75  // Definitions for static const data members of __ios_flags.
76  const __ios_flags::__int_type __ios_flags::_S_boolalpha;
77  const __ios_flags::__int_type __ios_flags::_S_dec;
78  const __ios_flags::__int_type __ios_flags::_S_fixed;
79  const __ios_flags::__int_type __ios_flags::_S_hex;
80  const __ios_flags::__int_type __ios_flags::_S_internal;
81  const __ios_flags::__int_type __ios_flags::_S_left;
82  const __ios_flags::__int_type __ios_flags::_S_oct;
83  const __ios_flags::__int_type __ios_flags::_S_right;
84  const __ios_flags::__int_type __ios_flags::_S_scientific;
85  const __ios_flags::__int_type __ios_flags::_S_showbase;
86  const __ios_flags::__int_type __ios_flags::_S_showpoint;
87  const __ios_flags::__int_type __ios_flags::_S_showpos;
88  const __ios_flags::__int_type __ios_flags::_S_skipws;
89  const __ios_flags::__int_type __ios_flags::_S_unitbuf;
90  const __ios_flags::__int_type __ios_flags::_S_uppercase;
91  const __ios_flags::__int_type __ios_flags::_S_adjustfield;
92  const __ios_flags::__int_type __ios_flags::_S_basefield;
93  const __ios_flags::__int_type __ios_flags::_S_floatfield;
94
95  const __ios_flags::__int_type __ios_flags::_S_badbit;
96  const __ios_flags::__int_type __ios_flags::_S_eofbit;
97  const __ios_flags::__int_type __ios_flags::_S_failbit;
98
99  const __ios_flags::__int_type __ios_flags::_S_app;
100  const __ios_flags::__int_type __ios_flags::_S_ate;
101  const __ios_flags::__int_type __ios_flags::_S_bin;
102  const __ios_flags::__int_type __ios_flags::_S_in;
103  const __ios_flags::__int_type __ios_flags::_S_out;
104  const __ios_flags::__int_type __ios_flags::_S_trunc;
105
106  // Definitions for static const members of ios_base.
107  const ios_base::fmtflags ios_base::boolalpha;
108  const ios_base::fmtflags ios_base::dec;
109  const ios_base::fmtflags ios_base::fixed;
110  const ios_base::fmtflags ios_base::hex;
111  const ios_base::fmtflags ios_base::internal;
112  const ios_base::fmtflags ios_base::left;
113  const ios_base::fmtflags ios_base::oct;
114  const ios_base::fmtflags ios_base::right;
115  const ios_base::fmtflags ios_base::scientific;
116  const ios_base::fmtflags ios_base::showbase;
117  const ios_base::fmtflags ios_base::showpoint;
118  const ios_base::fmtflags ios_base::showpos;
119  const ios_base::fmtflags ios_base::skipws;
120  const ios_base::fmtflags ios_base::unitbuf;
121  const ios_base::fmtflags ios_base::uppercase;
122  const ios_base::fmtflags ios_base::adjustfield;
123  const ios_base::fmtflags ios_base::basefield;
124  const ios_base::fmtflags ios_base::floatfield;
125
126  const ios_base::iostate ios_base::badbit;
127  const ios_base::iostate ios_base::eofbit;
128  const ios_base::iostate ios_base::failbit;
129  const ios_base::iostate ios_base::goodbit;
130
131  const ios_base::openmode ios_base::app;
132  const ios_base::openmode ios_base::ate;
133  const ios_base::openmode ios_base::binary;
134  const ios_base::openmode ios_base::in;
135  const ios_base::openmode ios_base::out;
136  const ios_base::openmode ios_base::trunc;
137
138  const ios_base::seekdir ios_base::beg;
139  const ios_base::seekdir ios_base::cur;
140  const ios_base::seekdir ios_base::end;
141
142  const int ios_base::_S_local_word_size;
143  int ios_base::Init::_S_ios_base_init = 0;
144  bool ios_base::Init::_S_synced_with_stdio = true;
145
146  ios_base::failure::failure(const string& __str) throw()
147  {
148    strncpy(_M_name, __str.c_str(), _M_bufsize);
149    _M_name[_M_bufsize - 1] = '\0';
150  }
151
152  ios_base::failure::~failure() throw()
153  { }
154
155  const char*
156  ios_base::failure::what() const throw()
157  { return _M_name; }
158
159  void
160  ios_base::Init::_S_ios_create(bool __sync)
161  {
162    int __out_size = __sync ? 0 : static_cast<int>(BUFSIZ);
163#ifdef _GLIBCPP_HAVE_ISATTY
164    int __in_size = (__sync || isatty (0)) ? 1 : static_cast<int>(BUFSIZ);
165#else
166    int __in_size = 1;
167#endif
168
169    // NB: The file globals.cc creates the four standard files
170    // with NULL buffers. At this point, we swap out the dummy NULL
171    // [io]stream objects and buffers with the real deal.
172    new (&buf_cout) stdio_filebuf<char>(stdout, ios_base::out, __out_size);
173    new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size);
174    new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size);
175    new (&cout) ostream(&buf_cout);
176    new (&cin) istream(&buf_cin);
177    new (&cerr) ostream(&buf_cerr);
178    new (&clog) ostream(&buf_cerr);
179    cin.tie(&cout);
180    cerr.flags(ios_base::unitbuf);
181
182#ifdef _GLIBCPP_USE_WCHAR_T
183    new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size);
184    new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size);
185    new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size);
186    new (&wcout) wostream(&buf_wcout);
187    new (&wcin) wistream(&buf_wcin);
188    new (&wcerr) wostream(&buf_wcerr);
189    new (&wclog) wostream(&buf_wcerr);
190    wcin.tie(&wcout);
191    wcerr.flags(ios_base::unitbuf);
192#endif
193  }
194
195  void
196  ios_base::Init::_S_ios_destroy()
197  {
198    // Explicitly call dtors to free any memory that is dynamically
199    // allocated by filebuf ctor or member functions, but don't
200    // deallocate all memory by calling operator delete.
201    buf_cout.~stdio_filebuf();
202    buf_cin.~stdio_filebuf();
203    buf_cerr.~stdio_filebuf();
204
205#ifdef _GLIBCPP_USE_WCHAR_T
206    buf_wcout.~stdio_filebuf();
207    buf_wcin.~stdio_filebuf();
208    buf_wcerr.~stdio_filebuf();
209#endif
210  }
211
212  ios_base::Init::Init()
213  {
214    if (_S_ios_base_init == 0)
215      {
216	// Standard streams default to synced with "C" operations.
217	ios_base::Init::_S_synced_with_stdio = true;
218	_S_ios_create(ios_base::Init::_S_synced_with_stdio);
219      }
220    ++_S_ios_base_init;
221  }
222
223  ios_base::Init::~Init()
224  {
225    if (--_S_ios_base_init == 0)
226      _S_ios_destroy();
227  }
228
229  // 27.4.2.5  ios_base storage functions
230  int
231  ios_base::xalloc() throw()
232  {
233    // Implementation note: Initialize top to zero to ensure that
234    // initialization occurs before main() is started.
235    static _Atomic_word _S_top = 0;
236    return __exchange_and_add(&_S_top, 1) + 4;
237  }
238
239  // 27.4.2.5  iword/pword storage
240  ios_base::_Words&
241  ios_base::_M_grow_words(int ix)
242  {
243    // Precondition: _M_word_size <= ix
244    int newsize = _S_local_word_size;
245    _Words* words = _M_local_word;
246    if (ix > _S_local_word_size - 1)
247      {
248	if (ix < numeric_limits<int>::max())
249	  {
250	    newsize = ix + 1;
251	    try
252	      { words = new _Words[newsize]; }
253	    catch (...)
254	      {
255		delete [] _M_word;
256		_M_word = 0;
257		_M_streambuf_state |= badbit;
258		if (_M_streambuf_state & _M_exception)
259		  __throw_ios_failure("ios_base::_M_grow_words failure");
260		return _M_word_zero;
261	      }
262	    for (int i = 0; i < _M_word_size; i++)
263	      words[i] = _M_word[i];
264	    if (_M_word && _M_word != _M_local_word)
265	      {
266		delete [] _M_word;
267		_M_word = 0;
268	      }
269	  }
270	else
271	  {
272	    _M_streambuf_state |= badbit;
273	    return _M_word_zero;
274	  }
275      }
276    _M_word = words;
277    _M_word_size = newsize;
278    return _M_word[ix];
279  }
280
281  // Called only by basic_ios<>::init.
282  void
283  ios_base::_M_init()
284  {
285    // NB: May be called more than once
286    _M_precision = 6;
287    _M_width = 0;
288    _M_flags = skipws | dec;
289    _M_callbacks = 0;
290    _M_word_size = 0;
291    _M_ios_locale = locale();
292  }
293
294  // 27.4.2.3  ios_base locale functions
295  locale
296  ios_base::imbue(const locale& __loc)
297  {
298    locale __old = _M_ios_locale;
299    _M_ios_locale = __loc;
300    _M_call_callbacks(imbue_event);
301    return __old;
302  }
303
304  ios_base::ios_base() : _M_callbacks(0), _M_word(0)
305  {
306    // Do nothing: basic_ios::init() does it.
307    // NB: _M_callbacks and _M_word must be zero for non-initialized
308    // ios_base to go through ~ios_base gracefully.
309  }
310
311  // 27.4.2.7  ios_base constructors/destructors
312  ios_base::~ios_base()
313  {
314    _M_call_callbacks(erase_event);
315    _M_dispose_callbacks();
316    if (_M_word && _M_word != _M_local_word)
317      {
318	delete [] _M_word;
319	_M_word = 0;
320      }
321  }
322
323  void
324  ios_base::register_callback(event_callback __fn, int __index)
325  { _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); }
326
327  void
328  ios_base::_M_call_callbacks(event __e) throw()
329  {
330    _Callback_list* __p = _M_callbacks;
331    while (__p)
332      {
333	try
334	  { (*__p->_M_fn) (__e, *this, __p->_M_index); }
335	catch (...)
336	  { }
337	__p = __p->_M_next;
338      }
339  }
340
341  void
342  ios_base::_M_dispose_callbacks(void)
343  {
344    _Callback_list* __p = _M_callbacks;
345    while (__p && __p->_M_remove_reference() == 0)
346      {
347	_Callback_list* __next = __p->_M_next;
348	delete __p;
349	__p = __next;
350      }
351    _M_callbacks = 0;
352  }
353
354  bool
355  ios_base::sync_with_stdio(bool __sync)
356  {
357#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
358    // 49.  Underspecification of ios_base::sync_with_stdio
359    bool __ret = ios_base::Init::_S_synced_with_stdio;
360#endif
361
362    // Turn off sync with C FILE* for cin, cout, cerr, clog iff
363    // currently synchronized.
364    if (!__sync && __ret)
365      {
366	ios_base::Init::_S_synced_with_stdio = false;
367	ios_base::Init::_S_ios_destroy();
368	ios_base::Init::_S_ios_create(ios_base::Init::_S_synced_with_stdio);
369      }
370    return __ret;
371  }
372}  // namespace std
373