Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
iostream.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30
31#if 3 == __GNUG__ && 3 > __GNUC_MINOR__ \
32 || 3 == __GNUC_MINOR__ && 1 >__GNUC_PATCHLEVEL__
33
34 // working around a gcc bug (PR #29570)
35# include <rw/_config.h>
36# ifndef _RWSTD_NO_EXTERN_TEMPLATE
37# define _RWSTD_NO_EXTERN_TEMPLATE
38# endif
39#endif // gcc >= 3.0 && gcc < 3.3.1
40
41#include <rw/_defs.h>
42
43#ifdef _WIN32
44# include <io.h>
45# ifndef STDIN_FILENO
46# define STDIN_FILENO 0
47# define STDOUT_FILENO 1
48# define STDERR_FILENO 2
49# endif // STDIN_FILENO
50#else
51 // unistd.h must preceed other headers to avoid a namespace issue
52 // ("time_t" vrs "std::time_t") on SunPro 5.3/SunOS 5.8
53# include <unistd.h>
54#endif
55
56#include <iosfwd>
57#include <istream>
58#include <ostream>
59#include <fstream>
60#include <memory>
61#include <new>
62
63#include <rw/_error.h>
64
65#include "iosdata.h"
66#include "podarray.h" // for __rw_aligned_buffer
67
68#include <stdio.h> // fprintf(), stderr
69#include <stdlib.h> // abort()
70
71
72#ifdef _MSC_VER
73 // force early intitalization of Standard Iostream Objects
74 // gives warning C4073: initializers put in library initialization
75 // area; disable it
76# ifdef _RWSTD_MSVC
77# pragma warning (disable: 4073)
78# endif
79# pragma init_seg (lib)
80#endif // _MSC_VER
81
82
83// #defined below
84#undef _INIT
85
86// stream objects are initialized with static basic_filebuf objects
87// based on static data buffers to avoid dynamic memory allocation
88// at library initialization time
89
90#ifndef _RWSTD_NO_STATIC_IOSTREAM_INIT
91
92// iostream objects and buffers are (re)constructed in ios_base::Init()
93// via calls to placement new after being zero-initialized (not constructed)
94// at definition time (by the means of the __rw_aligned_buffer trick)
95
96# ifndef _RWSTD_NO_IOSTREAM_OBJECT_REFS
97
98// cin, cout, and the other Standard iostream objects are references to
99// these objects which of caurse violates 27.3 but avoids the potential
100// for destruction prior to any other objects with static storage duration
101// and is undetectable
102
103#define _RWSTD_DEFINE_STREAM_OBJECT(buftype, stream, name, ign1, ign2) \
104 _RWSTD_NAMESPACE (__rw) { \
105 /* static character buffer to prevent dynamic allocation */ \
106 static _STD::stream::char_type __rw_##name##_databuf [512]; \
107 /* static indestructible `basic_filebuf<>' object */ \
108 static __rw_aligned_buffer<_STD::buftype> __rw_##name##_buffer; \
109 /* static indestructible `basic_[i|o]stream<>' object */ \
110 static __rw_aligned_buffer<_STD::stream> __rw_indestructible_##name; \
111 } /* namespace __rw */ \
112 _RWSTD_NAMESPACE (std) { \
113 /* reference (not object) to a basic_[i|o]stream<> object */ \
114 _RWSTD_EXPORT stream &name \
115 = _RWSTD_REINTERPRET_CAST (stream&, _RW::__rw_indestructible_##name); \
116 } /* namespace std */ \
117 typedef void __rw_unused_typedef
118
119#define _OBJECT(ignore, name) name
120
121# else // if defined (_RWSTD_NO_IOSTREAM_OBJECT_REFS)
122
123// cin, cout, and the other Standard iostream objects are defined to be
124// specializations of the POD type __rw::__rw_aligned_buffer<[i|o]stream>
125// but declared in <iostream> to be extern [i|o]stream
126// since the type information isn't encoded (mangled) in data names this
127// lie is transparent to the compiler/linker as neither ever sees both
128// declarations
129
130#define _RWSTD_DEFINE_STREAM_OBJECT(buftype, stream, name, ign1, ign2) \
131 _RWSTD_NAMESPACE (__rw) { \
132 /* static character buffer to prevent dynamic allocation */ \
133 static _STD::stream::char_type __rw_##name##_databuf [512]; \
134 /* static indestructible `basic_filebuf<>' object */ \
135 static __rw_aligned_buffer<_STD::buftype> __rw_##name##_buffer; \
136 } /* namespace __rw */ \
137 _RWSTD_NAMESPACE (std) { \
138 /* extern indestructible `basic_[i|o]stream<>' object */ \
139 _RWSTD_EXPORT _RW::__rw_aligned_buffer<stream> name; \
140 } /* namespace std */ \
141 _RWSTD_NAMESPACE (__rw) { \
142 /* reference to the actual object for convenience */ \
143 static __rw_aligned_buffer<_STD::stream>& \
144 __rw_indestructible_##name = _STD::name; \
145 } /* namespace __rw */ \
146 typedef void __rw_unused_typedef
147
148#define _OBJECT(type, name) _RWSTD_REINTERPRET_CAST (type&, name)
149
150# endif // _RWSTD_NO_IOSTREAM_OBJECT_REFS
151
152// expression returning the address of the initialized object
153#define _INIT(buftype, stream, name, buf, f) \
154 /* construct basic_[i|o]stream object backed by a filebuf object */ \
155 /* backed by a static characater array */ \
156 new (&_RW::__rw_indestructible_##name) stream \
157 (new (&_RW::__rw_##name##_buffer) buftype \
158 (f, _RW::__rw_##name##_databuf, \
159 sizeof _RW::__rw_##name##_databuf / sizeof *_RW::__rw_##name##_databuf)) \
160
161
162#else // if defined (_RWSTD_NO_STATIC_IOSTREAM_INIT)
163
164// iostream objects and buffers are constructed at definition time
165
166#define _RWSTD_DEFINE_STREAM_OBJECT(buftype, stream, name, buf, f) \
167 _RWSTD_NAMESPACE (__rw) { \
168 /* static character buffer to prevent dynamic allocation */ \
169 static _STD::stream::char_type __rw_##name##_databuf [512]; \
170 /* static `basic_filebuf<>' object, destroyed at program termination */ \
171 static _STD::buftype __rw_##name##_buffer (f, \
172 __rw_##name##_databuf, \
173 sizeof __rw_##name##_databuf / sizeof *__rw_##name##_databuf); \
174 } /* namespace __rw */ \
175 _RWSTD_NAMESPACE (std) { \
176 /* extern `basic_[i|o]stream<>' object, destroyed at termination */ \
177 _RWSTD_EXPORT stream name (&_RW::__rw_##buf##_buffer); \
178 } /* namespace std */ \
179 typedef void __rw_unused_typedef
180
181#define _INIT(ign1, stream, ign3, ign4, ign5) ((stream*)0)
182
183#endif // _RWSTD_NO_STATIC_IOSTREAM_INIT
184
185
186// define iostream objects and their corresponding "buffers"
187_RWSTD_DEFINE_STREAM_OBJECT (filebuf, istream, cin, cin, STDIN_FILENO);
188_RWSTD_DEFINE_STREAM_OBJECT (filebuf, ostream, cout, cout, STDOUT_FILENO);
189_RWSTD_DEFINE_STREAM_OBJECT (filebuf, ostream, cerr, cerr, STDERR_FILENO);
190_RWSTD_DEFINE_STREAM_OBJECT (filebuf, ostream, clog, cerr, STDERR_FILENO);
191
192#ifndef _RWSTD_NO_WCHAR_T
193
194_RWSTD_DEFINE_STREAM_OBJECT (wfilebuf, wistream, wcin, wcin, STDIN_FILENO);
195_RWSTD_DEFINE_STREAM_OBJECT (wfilebuf, wostream, wcout, wcout, STDOUT_FILENO);
196_RWSTD_DEFINE_STREAM_OBJECT (wfilebuf, wostream, wcerr, wcerr, STDERR_FILENO);
197_RWSTD_DEFINE_STREAM_OBJECT (wfilebuf, wostream, wclog, wcerr, STDERR_FILENO);
198
199#endif // _RWSTD_NO_WCHAR_T
200
201
202// allow basic_ostream<> inline member functions to refer to the standard
203// iostream objects without making those objects visible to user code (so
204// that they can safely be dereferenced only after #including <iostream>
205// which is the only header where they are declared and by the means of
206// which they are initialized - through the static initialization object)
207
209
210#ifdef _RWSTD_NO_STATIC_IOSTREAM_INIT
211
212// a single (library-wide) iostream initializer object - must be defined
213// after the definition of the iostream objects (above) so that when
214// its dtor manipulates the objects they have not been destroyed
215ios_base::Init __rw_stream_initializer;
216
217#endif // _RWSTD_NO_STATIC_IOSTREAM_INIT
218
219
220// array of pointers to the 8 standard iostream objects
221extern const void* __rw_std_streams [];
222
223
224// iostream initialization counter
225static int __rw_ios_initcnt /* = 0 */;
226
227} // namespace __rw
228
229
231
232ios_base::Init::Init ()
233{
234 // only the first thread initializes
235 if (1 != _RWSTD_ATOMIC_PREINCREMENT (_RW::__rw_ios_initcnt, false))
236 return;
237
238 // since references need not be initialzied statically, cin, et al
239 // may not be initialized at this time (i.e., &cin == 0 may hold,
240 // and does with MSVC 6.0), obtain and use pointers to the objects
241 istream *pcin = _INIT (filebuf, istream, cin, cin, STDIN_FILENO);
242 ostream *pcout = _INIT (filebuf, ostream, cout, cout, STDOUT_FILENO);
243 ostream *pcerr = _INIT (filebuf, ostream, cerr, cerr, STDERR_FILENO);
244 ostream *pclog = _INIT (filebuf, ostream, clog, cerr, STDERR_FILENO);
245
246 // stream objects expected to be arranged in this order
247 // must be initialized dynamically (as opposed to statically)
248 _RW::__rw_std_streams[0] = _RWSTD_STATIC_CAST (ios_base*, pcin);
249 _RW::__rw_std_streams[1] = _RWSTD_STATIC_CAST (ios_base*, pcout);
250 _RW::__rw_std_streams[2] = _RWSTD_STATIC_CAST (ios_base*, pcerr);
251 _RW::__rw_std_streams[3] = _RWSTD_STATIC_CAST (ios_base*, pclog);
252
253 // 27.3.1, p2
254 pcin->_C_usr = &_C_usr_data::_C_std_usr_data [0];
255 pcin->_C_usr->_C_tie = pcout;
256
257 // 27.3.1, p5
258 pcerr->_C_fmtfl |= _RW::__rw_unitbuf;
259
260 pcin->_C_fmtfl |= _RW::__rw_sync_stdio;
261 pcout->_C_fmtfl |= _RW::__rw_sync_stdio;
262 pcerr->_C_fmtfl |= _RW::__rw_sync_stdio;
263 pclog->_C_fmtfl |= _RW::__rw_sync_stdio;
264
265#if defined (_RWSTD_REENTRANT) \
266 && !defined (_RWSTD_NO_EXT_REENTRANT_IO) \
267 && !defined (_RWSTD_NO_REENTRANT_IO_DEFAULT)
268
269 // override MT-safety setting done in basic_ios<>::init()
270 pcin->_C_fmtfl &= ~(nolock | nolockbuf);
271 pcout->_C_fmtfl &= ~(nolock | nolockbuf);
272 pcerr->_C_fmtfl &= ~(nolock | nolockbuf);
273 pclog->_C_fmtfl &= ~(nolock | nolockbuf);
274
275#endif // _RWSTD_REENTRANT && !_RWSTD_NO_EXT_REENTRANT_IO && ...
276
277
278#ifndef _RWSTD_NO_WCHAR_T
279
280 wistream *pwcin = _INIT (wfilebuf, wistream, wcin, wcin, STDIN_FILENO);
281 wostream *pwcout = _INIT (wfilebuf, wostream, wcout, wcout, STDOUT_FILENO);
282 wostream *pwcerr = _INIT (wfilebuf, wostream, wcerr, wcerr, STDERR_FILENO);
283 wostream *pwclog = _INIT (wfilebuf, wostream, wclog, wcerr, STDERR_FILENO);
284
285 // stream objects expected to be arranged in this order
286 // must be initialized dynamically (as opposed to statically)
287 _RW::__rw_std_streams[4] = _RWSTD_STATIC_CAST (ios_base*, pwcin);
288 _RW::__rw_std_streams[5] = _RWSTD_STATIC_CAST (ios_base*, pwcout);
289 _RW::__rw_std_streams[6] = _RWSTD_STATIC_CAST (ios_base*, pwcerr);
290 _RW::__rw_std_streams[7] = _RWSTD_STATIC_CAST (ios_base*, pwclog);
291
292 // 27.3.2, p2
293 pwcin->_C_usr = &_C_usr_data::_C_std_usr_data [1];
294 pwcin->_C_usr->_C_tie = pwcout;
295
296 // 27.3.2, p5
297 pwcerr->_C_fmtfl |= _RW::__rw_unitbuf;
298
299 pwcin->_C_fmtfl |= _RW::__rw_sync_stdio;
300 pwcout->_C_fmtfl |= _RW::__rw_sync_stdio;
301 pwcerr->_C_fmtfl |= _RW::__rw_sync_stdio;
302 pwclog->_C_fmtfl |= _RW::__rw_sync_stdio;
303
304# if defined (_RWSTD_REENTRANT) \
305 && !defined (_RWSTD_NO_EXT_REENTRANT_IO) \
306 && !defined (_RWSTD_NO_REENTRANT_IO_DEFAULT)
307
308 // override MT-safety setting done in basic_ios<>::init()
309 pwcin->_C_fmtfl &= ~(nolock | nolockbuf);
310 pwcout->_C_fmtfl &= ~(nolock | nolockbuf);
311 pwcerr->_C_fmtfl &= ~(nolock | nolockbuf);
312 pwclog->_C_fmtfl &= ~(nolock | nolockbuf);
313
314# endif // _RWSTD_REENTRANT && !_RWSTD_NO_EXT_REENTRANT_IO && ...
315
316#endif // _RWSTD_NO_WCHAR_T
317}
318
319
320ios_base::Init::~Init ()
321{
322 if (_RWSTD_ATOMIC_PREDECREMENT (_RW::__rw_ios_initcnt, false))
323 return;
324
325 // put all standard iostream objects in unbuffered mode so that
326 // output made from dtors of user objects with static storage
327 // duration destroyed from this point on (i.e., after the destruction
328 // of *this, the last initializer object) is not lost
329
330 // references must not be destroyed
331 _RWSTD_ASSERT (&cout && &cerr && &clog);
332
333 const char fmt[] = "exception during std::%s cleanup\n";
334
335 int caught = 0;
336
337 _TRY {
338 _OBJECT (ostream, cout).rdbuf ()->pubsetbuf (0, 0);
339 }
340 _CATCH (...) {
341 fprintf (stderr, fmt, "cout");
342 ++caught;
343 }
344 _TRY {
345 _OBJECT (ostream, cerr).rdbuf ()->pubsetbuf (0, 0);
346 }
347 _CATCH (...) {
348 fprintf (stderr, fmt, "cerr");
349 ++caught;
350 }
351 _TRY {
352 _OBJECT (ostream, clog).rdbuf ()->pubsetbuf (0, 0);
353 }
354 _CATCH (...) {
355 fprintf (stderr, fmt, "clog");
356 ++caught;
357 }
358
359#ifndef _RWSTD_NO_WCHAR_T
360
361 _RWSTD_ASSERT (&wcout && &wcerr && &wclog);
362
363 _TRY {
364 _OBJECT (wostream, wcout).rdbuf ()->pubsetbuf (0, 0);
365 }
366 _CATCH (...) {
367 fprintf (stderr, fmt, "wcout");
368 ++caught;
369 }
370 _TRY {
371 _OBJECT (wostream, wcerr).rdbuf ()->pubsetbuf (0, 0);
372 }
373 _CATCH (...) {
374 fprintf (stderr, fmt, "wcerr");
375 ++caught;
376 }
377 _TRY {
378 _OBJECT (wostream, wclog).rdbuf ()->pubsetbuf (0, 0);
379 }
380 _CATCH (...) {
381 fprintf (stderr, fmt, "wclog");
382 ++caught;
383 }
384
385#endif // _RWSTD_NO_WCHAR_T
386
387 if (caught)
388 abort ();
389}
390
391
392} // namespace std
#define nolock
#define nolockbuf
int caught
#define STDOUT_FILENO
#define STDERR_FILENO
#define STDIN_FILENO
#define stderr
#define _RWSTD_ATOMIC_PREINCREMENT(x, ignore)
Definition _defs.h:699
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
#define _TRY
Definition _defs.h:850
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ATOMIC_PREDECREMENT(x, ignore)
Definition _defs.h:700
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _CATCH(ex)
Definition _defs.h:851
#define _RWSTD_DEFINE_STREAM_OBJECT(buftype, stream, name, ign1, ign2)
Definition iostream.cpp:103
#define _INIT(buftype, stream, name, buf, f)
Definition iostream.cpp:153
#define _OBJECT(ignore, name)
Definition iostream.cpp:119
Definition json.h:5363