ios.cc revision 110614
1180740Sdes// Iostreams base classes -*- C++ -*-
2180740Sdes
3180740Sdes// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
4180740Sdes// Free Software Foundation, Inc.
5180740Sdes//
6180740Sdes// This file is part of the GNU ISO C++ Library.  This library is free
7180740Sdes// software; you can redistribute it and/or modify it under the
8180740Sdes// terms of the GNU General Public License as published by the
9180740Sdes// Free Software Foundation; either version 2, or (at your option)
10180740Sdes// any later version.
11180740Sdes
12180740Sdes// This library is distributed in the hope that it will be useful,
13180740Sdes// but WITHOUT ANY WARRANTY; without even the implied warranty of
14180740Sdes// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15180740Sdes// GNU General Public License for more details.
16180740Sdes
17180740Sdes// You should have received a copy of the GNU General Public License along
18180740Sdes// with this library; see the file COPYING.  If not, write to the Free
19180740Sdes// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20180740Sdes// USA.
21180740Sdes
22180740Sdes// As a special exception, you may use this file as part of a free software
23180740Sdes// library without restriction.  Specifically, if other files instantiate
24180740Sdes// templates or use macros or inline functions from this file, or you compile
25180740Sdes// this file and link it with other files to produce an executable, this
26180740Sdes// file does not by itself cause the resulting executable to be covered by
27180740Sdes// the GNU General Public License.  This exception does not however
28180740Sdes// invalidate any other reasons why the executable file might be covered by
29180740Sdes// the GNU General Public License.
30180740Sdes
31180740Sdes//
32180740Sdes// ISO C++ 14882: 27.4  Iostreams base classes
33180740Sdes//
34180740Sdes
35180740Sdes#include <ios>
36180740Sdes#include <ostream>
37180740Sdes#include <istream>
38180740Sdes#include <fstream>
39180740Sdes#include <bits/atomicity.h>
40180740Sdes#include <ext/stdio_filebuf.h>
41180740Sdes#ifdef _GLIBCPP_HAVE_UNISTD_H
42180740Sdes#include <unistd.h>
43180740Sdes#endif
44180740Sdes
45180740Sdesnamespace __gnu_cxx
46180740Sdes{
47180740Sdes  // Extern declarations for global objects in src/globals.cc.
48180740Sdes  extern stdio_filebuf<char> buf_cout;
49180740Sdes  extern stdio_filebuf<char> buf_cin;
50180740Sdes  extern stdio_filebuf<char> buf_cerr;
51180740Sdes
52180740Sdes#ifdef _GLIBCPP_USE_WCHAR_T
53180740Sdes  extern stdio_filebuf<wchar_t> buf_wcout;
54180740Sdes  extern stdio_filebuf<wchar_t> buf_wcin;
55180740Sdes  extern stdio_filebuf<wchar_t> buf_wcerr;
56180740Sdes#endif
57180740Sdes} // namespace __gnu_cxx
58180740Sdes
59180740Sdesnamespace std
60180740Sdes{
61180740Sdes  using namespace __gnu_cxx;
62180740Sdes
63180740Sdes  extern istream cin;
64180740Sdes  extern ostream cout;
65180740Sdes  extern ostream cerr;
66180740Sdes  extern ostream clog;
67180740Sdes
68180740Sdes#ifdef _GLIBCPP_USE_WCHAR_T
69180740Sdes  extern wistream wcin;
70180740Sdes  extern wostream wcout;
71180740Sdes  extern wostream wcerr;
72180740Sdes  extern wostream wclog;
73180740Sdes#endif
74180740Sdes
75180740Sdes  // Definitions for static const data members of __ios_flags.
76180740Sdes  const __ios_flags::__int_type __ios_flags::_S_boolalpha;
77180740Sdes  const __ios_flags::__int_type __ios_flags::_S_dec;
78180740Sdes  const __ios_flags::__int_type __ios_flags::_S_fixed;
79180740Sdes  const __ios_flags::__int_type __ios_flags::_S_hex;
80180740Sdes  const __ios_flags::__int_type __ios_flags::_S_internal;
81180740Sdes  const __ios_flags::__int_type __ios_flags::_S_left;
82180740Sdes  const __ios_flags::__int_type __ios_flags::_S_oct;
83180740Sdes  const __ios_flags::__int_type __ios_flags::_S_right;
84180740Sdes  const __ios_flags::__int_type __ios_flags::_S_scientific;
85180740Sdes  const __ios_flags::__int_type __ios_flags::_S_showbase;
86180740Sdes  const __ios_flags::__int_type __ios_flags::_S_showpoint;
87180740Sdes  const __ios_flags::__int_type __ios_flags::_S_showpos;
88180740Sdes  const __ios_flags::__int_type __ios_flags::_S_skipws;
89180740Sdes  const __ios_flags::__int_type __ios_flags::_S_unitbuf;
90180740Sdes  const __ios_flags::__int_type __ios_flags::_S_uppercase;
91180740Sdes  const __ios_flags::__int_type __ios_flags::_S_adjustfield;
92180740Sdes  const __ios_flags::__int_type __ios_flags::_S_basefield;
93180740Sdes  const __ios_flags::__int_type __ios_flags::_S_floatfield;
94180740Sdes
95180740Sdes  const __ios_flags::__int_type __ios_flags::_S_badbit;
96180740Sdes  const __ios_flags::__int_type __ios_flags::_S_eofbit;
97180740Sdes  const __ios_flags::__int_type __ios_flags::_S_failbit;
98180740Sdes
99180740Sdes  const __ios_flags::__int_type __ios_flags::_S_app;
100180740Sdes  const __ios_flags::__int_type __ios_flags::_S_ate;
101180740Sdes  const __ios_flags::__int_type __ios_flags::_S_bin;
102180740Sdes  const __ios_flags::__int_type __ios_flags::_S_in;
103180740Sdes  const __ios_flags::__int_type __ios_flags::_S_out;
104180740Sdes  const __ios_flags::__int_type __ios_flags::_S_trunc;
105180740Sdes
106180740Sdes  // Definitions for static const members of ios_base.
107180740Sdes  const ios_base::fmtflags ios_base::boolalpha;
108180740Sdes  const ios_base::fmtflags ios_base::dec;
109180740Sdes  const ios_base::fmtflags ios_base::fixed;
110180740Sdes  const ios_base::fmtflags ios_base::hex;
111180740Sdes  const ios_base::fmtflags ios_base::internal;
112180740Sdes  const ios_base::fmtflags ios_base::left;
113180740Sdes  const ios_base::fmtflags ios_base::oct;
114180740Sdes  const ios_base::fmtflags ios_base::right;
115180740Sdes  const ios_base::fmtflags ios_base::scientific;
116180740Sdes  const ios_base::fmtflags ios_base::showbase;
117180740Sdes  const ios_base::fmtflags ios_base::showpoint;
118180740Sdes  const ios_base::fmtflags ios_base::showpos;
119180740Sdes  const ios_base::fmtflags ios_base::skipws;
120180740Sdes  const ios_base::fmtflags ios_base::unitbuf;
121180740Sdes  const ios_base::fmtflags ios_base::uppercase;
122180740Sdes  const ios_base::fmtflags ios_base::adjustfield;
123180740Sdes  const ios_base::fmtflags ios_base::basefield;
124180740Sdes  const ios_base::fmtflags ios_base::floatfield;
125180740Sdes
126180740Sdes  const ios_base::iostate ios_base::badbit;
127180740Sdes  const ios_base::iostate ios_base::eofbit;
128180740Sdes  const ios_base::iostate ios_base::failbit;
129180740Sdes  const ios_base::iostate ios_base::goodbit;
130180740Sdes
131180740Sdes  const ios_base::openmode ios_base::app;
132180740Sdes  const ios_base::openmode ios_base::ate;
133180740Sdes  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