]>
Commit | Line | Data |
---|---|---|
b2dad0e3 BK |
1 | // Iostreams base classes -*- C++ -*- |
2 | ||
6067bea4 | 3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 |
17325050 | 4 | // Free Software Foundation, Inc. |
b2dad0e3 BK |
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 | ||
54c1bf78 BK |
35 | #include <ios> |
36 | #include <ostream> | |
37 | #include <istream> | |
38 | #include <fstream> | |
17325050 | 39 | #include <bits/atomicity.h> |
5cdd50a5 | 40 | #include <ext/stdio_filebuf.h> |
423b950b RO |
41 | #ifdef _GLIBCPP_HAVE_UNISTD_H |
42 | #include <unistd.h> | |
43 | #endif | |
17325050 | 44 | |
a7817e1d | 45 | namespace __gnu_cxx |
d358ecd0 | 46 | { |
5de197f2 | 47 | // Extern declarations for global objects in src/globals.cc. |
a7817e1d BK |
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 | ||
59 | namespace std | |
60 | { | |
61 | using namespace __gnu_cxx; | |
62 | ||
5de197f2 BK |
63 | extern istream cin; |
64 | extern ostream cout; | |
65 | extern ostream cerr; | |
66 | extern ostream clog; | |
5cdd50a5 | 67 | |
5de197f2 BK |
68 | #ifdef _GLIBCPP_USE_WCHAR_T |
69 | extern wistream wcin; | |
70 | extern wostream wcout; | |
71 | extern wostream wcerr; | |
72 | extern wostream wclog; | |
5de197f2 BK |
73 | #endif |
74 | ||
0479a462 BK |
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. | |
b2dad0e3 BK |
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 | ||
663653eb | 142 | const int ios_base::_S_local_word_size; |
0479a462 | 143 | int ios_base::Init::_S_ios_base_init = 0; |
469550eb | 144 | bool ios_base::Init::_S_synced_with_stdio = true; |
0479a462 | 145 | |
d34786e3 | 146 | ios_base::failure::failure(const string& __str) throw() |
b2dad0e3 BK |
147 | { |
148 | strncpy(_M_name, __str.c_str(), _M_bufsize); | |
149 | _M_name[_M_bufsize - 1] = '\0'; | |
150 | } | |
151 | ||
d34786e3 | 152 | ios_base::failure::~failure() throw() |
23a5b444 GDR |
153 | { } |
154 | ||
155 | const char* | |
156 | ios_base::failure::what() const throw() | |
157 | { return _M_name; } | |
158 | ||
12764462 BK |
159 | void |
160 | ios_base::Init::_S_ios_create(bool __sync) | |
161 | { | |
dfc7d899 | 162 | size_t __out_size = __sync ? 0 : static_cast<size_t>(BUFSIZ); |
74af99e5 | 163 | #ifdef _GLIBCPP_HAVE_ISATTY |
dfc7d899 PC |
164 | size_t __in_size = |
165 | (__sync || isatty (0)) ? 1 : static_cast<size_t>(BUFSIZ); | |
74af99e5 | 166 | #else |
dfc7d899 | 167 | size_t __in_size = 1; |
74af99e5 | 168 | #endif |
861d4e70 | 169 | |
5de197f2 | 170 | // NB: The file globals.cc creates the four standard files |
39003c99 | 171 | // with NULL buffers. At this point, we swap out the dummy NULL |
5de197f2 | 172 | // [io]stream objects and buffers with the real deal. |
5cdd50a5 BK |
173 | new (&buf_cout) stdio_filebuf<char>(stdout, ios_base::out, __out_size); |
174 | new (&buf_cin) stdio_filebuf<char>(stdin, ios_base::in, __in_size); | |
175 | new (&buf_cerr) stdio_filebuf<char>(stderr, ios_base::out, __out_size); | |
5de197f2 BK |
176 | new (&cout) ostream(&buf_cout); |
177 | new (&cin) istream(&buf_cin); | |
178 | new (&cerr) ostream(&buf_cerr); | |
179 | new (&clog) ostream(&buf_cerr); | |
12764462 BK |
180 | cin.tie(&cout); |
181 | cerr.flags(ios_base::unitbuf); | |
182 | ||
183 | #ifdef _GLIBCPP_USE_WCHAR_T | |
5cdd50a5 BK |
184 | new (&buf_wcout) stdio_filebuf<wchar_t>(stdout, ios_base::out, __out_size); |
185 | new (&buf_wcin) stdio_filebuf<wchar_t>(stdin, ios_base::in, __in_size); | |
186 | new (&buf_wcerr) stdio_filebuf<wchar_t>(stderr, ios_base::out, __out_size); | |
5de197f2 BK |
187 | new (&wcout) wostream(&buf_wcout); |
188 | new (&wcin) wistream(&buf_wcin); | |
189 | new (&wcerr) wostream(&buf_wcerr); | |
190 | new (&wclog) wostream(&buf_wcerr); | |
12764462 BK |
191 | wcin.tie(&wcout); |
192 | wcerr.flags(ios_base::unitbuf); | |
193 | #endif | |
194 | } | |
195 | ||
12764462 BK |
196 | void |
197 | ios_base::Init::_S_ios_destroy() | |
198 | { | |
5de197f2 BK |
199 | // Explicitly call dtors to free any memory that is dynamically |
200 | // allocated by filebuf ctor or member functions, but don't | |
201 | // deallocate all memory by calling operator delete. | |
5cdd50a5 BK |
202 | buf_cout.~stdio_filebuf(); |
203 | buf_cin.~stdio_filebuf(); | |
204 | buf_cerr.~stdio_filebuf(); | |
205 | ||
b2dad0e3 | 206 | #ifdef _GLIBCPP_USE_WCHAR_T |
5cdd50a5 BK |
207 | buf_wcout.~stdio_filebuf(); |
208 | buf_wcin.~stdio_filebuf(); | |
209 | buf_wcerr.~stdio_filebuf(); | |
b2dad0e3 | 210 | #endif |
b2dad0e3 BK |
211 | } |
212 | ||
5de197f2 BK |
213 | ios_base::Init::Init() |
214 | { | |
1f46fc8e | 215 | if (_S_ios_base_init == 0) |
5de197f2 BK |
216 | { |
217 | // Standard streams default to synced with "C" operations. | |
218 | ios_base::Init::_S_synced_with_stdio = true; | |
219 | _S_ios_create(ios_base::Init::_S_synced_with_stdio); | |
220 | } | |
1f46fc8e | 221 | ++_S_ios_base_init; |
5de197f2 BK |
222 | } |
223 | ||
b2dad0e3 BK |
224 | ios_base::Init::~Init() |
225 | { | |
0479a462 | 226 | if (--_S_ios_base_init == 0) |
12764462 | 227 | _S_ios_destroy(); |
b2dad0e3 BK |
228 | } |
229 | ||
230 | // 27.4.2.5 ios_base storage functions | |
231 | int | |
232 | ios_base::xalloc() throw() | |
233 | { | |
17325050 AP |
234 | // Implementation note: Initialize top to zero to ensure that |
235 | // initialization occurs before main() is started. | |
663653eb BK |
236 | static _Atomic_word _S_top = 0; |
237 | return __exchange_and_add(&_S_top, 1) + 4; | |
b2dad0e3 BK |
238 | } |
239 | ||
240 | // 27.4.2.5 iword/pword storage | |
241 | ios_base::_Words& | |
242 | ios_base::_M_grow_words(int ix) | |
243 | { | |
663653eb BK |
244 | // Precondition: _M_word_size <= ix |
245 | int newsize = _S_local_word_size; | |
246 | _Words* words = _M_local_word; | |
663653eb | 247 | if (ix > _S_local_word_size - 1) |
b2dad0e3 | 248 | { |
d02475fd BK |
249 | if (ix < numeric_limits<int>::max()) |
250 | { | |
251 | newsize = ix + 1; | |
252 | try | |
253 | { words = new _Words[newsize]; } | |
254 | catch (...) | |
255 | { | |
d02475fd BK |
256 | _M_streambuf_state |= badbit; |
257 | if (_M_streambuf_state & _M_exception) | |
258 | __throw_ios_failure("ios_base::_M_grow_words failure"); | |
259 | return _M_word_zero; | |
260 | } | |
261 | for (int i = 0; i < _M_word_size; i++) | |
262 | words[i] = _M_word[i]; | |
263 | if (_M_word && _M_word != _M_local_word) | |
264 | { | |
265 | delete [] _M_word; | |
266 | _M_word = 0; | |
267 | } | |
268 | } | |
663653eb | 269 | else |
b2dad0e3 | 270 | { |
663653eb | 271 | _M_streambuf_state |= badbit; |
c524ed5d JQ |
272 | if (_M_streambuf_state & _M_exception) |
273 | __throw_ios_failure("ios_base::_M_grow_words failure"); | |
663653eb BK |
274 | return _M_word_zero; |
275 | } | |
b2dad0e3 | 276 | } |
663653eb BK |
277 | _M_word = words; |
278 | _M_word_size = newsize; | |
279 | return _M_word[ix]; | |
b2dad0e3 BK |
280 | } |
281 | ||
282 | // Called only by basic_ios<>::init. | |
283 | void | |
284 | ios_base::_M_init() | |
285 | { | |
286 | // NB: May be called more than once | |
b2dad0e3 | 287 | _M_precision = 6; |
d358ecd0 BK |
288 | _M_width = 0; |
289 | _M_flags = skipws | dec; | |
b2dad0e3 | 290 | _M_callbacks = 0; |
456183bb | 291 | _M_ios_locale = locale(); |
b2dad0e3 BK |
292 | } |
293 | ||
294 | // 27.4.2.3 ios_base locale functions | |
295 | locale | |
296 | ios_base::imbue(const locale& __loc) | |
297 | { | |
456183bb BK |
298 | locale __old = _M_ios_locale; |
299 | _M_ios_locale = __loc; | |
b2dad0e3 BK |
300 | _M_call_callbacks(imbue_event); |
301 | return __old; | |
302 | } | |
303 | ||
c562d51b JQ |
304 | ios_base::ios_base() : _M_callbacks(0), _M_word_size(_S_local_word_size), |
305 | _M_word(_M_local_word), _M_locale_cache(0) | |
b2dad0e3 | 306 | { |
1bc59af5 | 307 | // Do nothing: basic_ios::init() does it. |
663653eb | 308 | // NB: _M_callbacks and _M_word must be zero for non-initialized |
1bc59af5 | 309 | // ios_base to go through ~ios_base gracefully. |
b2dad0e3 BK |
310 | } |
311 | ||
312 | // 27.4.2.7 ios_base constructors/destructors | |
313 | ios_base::~ios_base() | |
314 | { | |
315 | _M_call_callbacks(erase_event); | |
316 | _M_dispose_callbacks(); | |
53ec7ec1 | 317 | if (_M_word != _M_local_word) |
663653eb BK |
318 | { |
319 | delete [] _M_word; | |
320 | _M_word = 0; | |
321 | } | |
b2dad0e3 BK |
322 | } |
323 | ||
324 | void | |
325 | ios_base::register_callback(event_callback __fn, int __index) | |
326 | { _M_callbacks = new _Callback_list(__fn, __index, _M_callbacks); } | |
327 | ||
328 | void | |
329 | ios_base::_M_call_callbacks(event __e) throw() | |
330 | { | |
1bc59af5 BK |
331 | _Callback_list* __p = _M_callbacks; |
332 | while (__p) | |
b2dad0e3 | 333 | { |
1bc59af5 BK |
334 | try |
335 | { (*__p->_M_fn) (__e, *this, __p->_M_index); } | |
336 | catch (...) | |
337 | { } | |
338 | __p = __p->_M_next; | |
b2dad0e3 BK |
339 | } |
340 | } | |
341 | ||
342 | void | |
343 | ios_base::_M_dispose_callbacks(void) | |
344 | { | |
345 | _Callback_list* __p = _M_callbacks; | |
346 | while (__p && __p->_M_remove_reference() == 0) | |
347 | { | |
348 | _Callback_list* __next = __p->_M_next; | |
349 | delete __p; | |
350 | __p = __next; | |
351 | } | |
352 | _M_callbacks = 0; | |
353 | } | |
354 | ||
355 | bool | |
356 | ios_base::sync_with_stdio(bool __sync) | |
357 | { | |
358 | #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS | |
359 | // 49. Underspecification of ios_base::sync_with_stdio | |
469550eb | 360 | bool __ret = ios_base::Init::_S_synced_with_stdio; |
d358ecd0 | 361 | #endif |
dd75251f | 362 | |
d358ecd0 BK |
363 | // Turn off sync with C FILE* for cin, cout, cerr, clog iff |
364 | // currently synchronized. | |
5780a46b | 365 | if (!__sync && __ret) |
b2dad0e3 | 366 | { |
469550eb | 367 | ios_base::Init::_S_synced_with_stdio = false; |
12764462 BK |
368 | ios_base::Init::_S_ios_destroy(); |
369 | ios_base::Init::_S_ios_create(ios_base::Init::_S_synced_with_stdio); | |
b2dad0e3 | 370 | } |
5780a46b | 371 | return __ret; |
b2dad0e3 | 372 | } |
b2dad0e3 | 373 | } // namespace std |