1 /* 2 * Copyright (c) 1999 3 * Silicon Graphics Computer Systems, Inc. 4 * 5 * Copyright (c) 1999 6 * Boris Fomitchev 7 * 8 * This material is provided "as is", with absolutely no warranty expressed 9 * or implied. Any use is at your own risk. 10 * 11 * Permission to use or copy this software for any purpose is hereby granted 12 * without fee, provided the above notices are retained on all copies. 13 * Permission to modify the code and to distribute modified code is granted, 14 * provided the above notices are retained, and a notice that the code was 15 * modified is included with the above copyright notice. 16 * 17 */ 18 #include "stlport_prefix.h" 19 20 #include <memory> 21 #include <istream> 22 #include <fstream> 23 #if defined (_STLP_MSVC) || defined (__MWERKS__) || defined (__ICL) || defined (__ISCPP__) 24 # define _STLP_USE_NOT_INIT_SEGMENT 25 # include <iostream> 26 #endif 27 28 #include "stdio_streambuf.h" 29 #include "aligned_buffer.h" 30 #include "_stdio_file.h" 31 #include "c_locale.h" 32 33 // boris : note this is repeated in <iostream> 34 #ifndef _STLP_USE_NAMESPACES 35 // in case of SGI iostreams, we have to rename our streams not to clash with those 36 // provided in native lib 37 # define cin _STLP_cin 38 # define cout _STLP_cout 39 # define cerr _STLP_cerr 40 # define clog _STLP_clog 41 #endif 42 43 _STLP_BEGIN_NAMESPACE 44 45 // This file handles iostream initialization. It is inherently 46 // nonportable, since the C++ language definition provides no mechanism 47 // for controlling order of initialization of nonlocal objects. 48 // Initialization has three parts, which must be performed in the following 49 // order: 50 // (1) Initialize the locale system 51 // (2) Call the constructors for the eight global stream objects. 52 // (3) Create streambufs for the global stream objects, and initialize 53 // the stream objects by calling the init() member function. 54 55 56 #if defined (_STLP_USE_NOT_INIT_SEGMENT) 57 58 // Definitions of the eight global I/O objects that are declared in 59 // <iostream>. For some compilers we use pragmas to put the global I/O 60 // objects into an initialization segment that will not 61 // be executed. We then explicitly invoke the constructors 62 // with placement new in ios_base::_S_initialize() 63 64 # if defined (__MWERKS__) 65 # pragma suppress_init_code on 66 # else 67 # pragma init_seg("STLPORT_NO_INIT") 68 # endif 69 70 _STLP_DECLSPEC istream cin(0); 71 _STLP_DECLSPEC ostream cout(0); 72 _STLP_DECLSPEC ostream cerr(0); 73 _STLP_DECLSPEC ostream clog(0); 74 75 # ifndef _STLP_NO_WCHAR_T 76 _STLP_DECLSPEC wistream wcin(0); 77 _STLP_DECLSPEC wostream wcout(0); 78 _STLP_DECLSPEC wostream wcerr(0); 79 _STLP_DECLSPEC wostream wclog(0); 80 # endif 81 82 # if defined (__MWERKS__) 83 # pragma suppress_init_code off 84 # endif 85 86 #else 87 88 // Definitions of the eight global I/O objects that are declared in 89 // <iostream>. Disgusting hack: we deliberately define them with the 90 // wrong types so that the constructors don't get run automatically. 91 // We need special tricks to make sure that these objects are struct- 92 // aligned rather than byte-aligned. 93 94 // This is not portable. Declaring a variable with different types in 95 // two translations units is "undefined", according to the C++ standard. 96 // Most compilers, however, silently accept this instead of diagnosing 97 // it as an error. 98 99 # ifndef __DMC__ 100 _STLP_DECLSPEC _Stl_aligned_buffer<istream> cin; 101 _STLP_DECLSPEC _Stl_aligned_buffer<ostream> cout; 102 _STLP_DECLSPEC _Stl_aligned_buffer<ostream> cerr; 103 _STLP_DECLSPEC _Stl_aligned_buffer<ostream> clog; 104 # else 105 _Stl_aligned_buffer<istream> cin; 106 _Stl_aligned_buffer<ostream> cout; 107 _Stl_aligned_buffer<ostream> cerr; 108 _Stl_aligned_buffer<ostream> clog; 109 110 # pragma alias("?cin@std@@3V?$basic_istream@std@DV?$char_traits@std@D@1@@1@A", "?cin@std@@3T?$_Stl_aligned_buffer@std@V?$basic_istream@std@DV?$char_traits@std@D@1@@1@@1@A") 111 # pragma alias("?cout@std@@3V?$basic_ostream@std@DV?$char_traits@std@D@1@@1@A", "?cout@std@@3T?$_Stl_aligned_buffer@std@V?$basic_ostream@std@DV?$char_traits@std@D@1@@1@@1@A") 112 # pragma alias("?cerr@std@@3V?$basic_ostream@std@DV?$char_traits@std@D@1@@1@A", "?cerr@std@@3T?$_Stl_aligned_buffer@std@V?$basic_ostream@std@DV?$char_traits@std@D@1@@1@@1@A") 113 # pragma alias("?clog@std@@3V?$basic_ostream@std@DV?$char_traits@std@D@1@@1@A", "?clog@std@@3T?$_Stl_aligned_buffer@std@V?$basic_ostream@std@DV?$char_traits@std@D@1@@1@@1@A") 114 # endif 115 116 # ifndef _STLP_NO_WCHAR_T 117 118 # ifndef __DMC__ 119 _STLP_DECLSPEC _Stl_aligned_buffer<wistream> wcin; 120 _STLP_DECLSPEC _Stl_aligned_buffer<wostream> wcout; 121 _STLP_DECLSPEC _Stl_aligned_buffer<wostream> wcerr; 122 _STLP_DECLSPEC _Stl_aligned_buffer<wostream> wclog; 123 # else 124 _Stl_aligned_buffer<wistream> wcin; 125 _Stl_aligned_buffer<wostream> wcout; 126 _Stl_aligned_buffer<wostream> wcerr; 127 _Stl_aligned_buffer<wostream> wclog; 128 129 # pragma alias("?wcin@std@@3V?$basic_istream@std@_YV?$char_traits@std@_Y@1@@1@A", "?wcin@std@@3T?$_Stl_aligned_buffer@std@V?$basic_istream@std@_YV?$char_traits@std@_Y@1@@1@@1@A") 130 # pragma alias("?wcout@std@@3V?$basic_ostream@std@_YV?$char_traits@std@_Y@1@@1@A", "?wcout@std@@3T?$_Stl_aligned_buffer@std@V?$basic_ostream@std@_YV?$char_traits@std@_Y@1@@1@@1@A") 131 # pragma alias("?wcerr@std@@3V?$basic_ostream@std@_YV?$char_traits@std@_Y@1@@1@A", "?wcerr@std@@3T?$_Stl_aligned_buffer@std@V?$basic_ostream@std@_YV?$char_traits@std@_Y@1@@1@@1@A") 132 # pragma alias("?wclog@std@@3V?$basic_ostream@std@_YV?$char_traits@std@_Y@1@@1@A", "?wclog@std@@3T?$_Stl_aligned_buffer@std@V?$basic_ostream@std@_YV?$char_traits@std@_Y@1@@1@@1@A") 133 # endif 134 # endif 135 #endif /* STL_MSVC || __MWERKS__ */ 136 137 // Member functions from class ios_base and ios_base::Init 138 139 long ios_base::Init::_S_count = 0; 140 // by default, those are synced 141 bool ios_base::_S_is_synced = true; 142 143 ios_base::Init::Init() { 144 if (_S_count++ == 0) { 145 _Locale_init(); 146 ios_base::_S_initialize(); 147 _Filebuf_base::_S_initialize(); 148 } 149 } 150 151 ios_base::Init::~Init() { 152 if (--_S_count == 0) { 153 ios_base::_S_uninitialize(); 154 _Locale_final(); 155 } 156 } 157 158 static int _Stl_extract_open_param(FILE* f) 159 { return _FILE_fd(f); } 160 161 #ifdef _STLP_REDIRECT_STDSTREAMS 162 static const char* _Stl_extract_open_param(const char* name) 163 { return name; } 164 #endif 165 166 template <class _Tp> 167 static filebuf* 168 _Stl_create_filebuf(_Tp x, ios_base::openmode mode ) { 169 auto_ptr<filebuf> result(new basic_filebuf<char, char_traits<char> >()); 170 result->open(_Stl_extract_open_param(x), mode); 171 172 if (result->is_open()) 173 return result.release(); 174 175 return 0; 176 } 177 178 #if !defined (_STLP_NO_WCHAR_T) 179 static wfilebuf* 180 _Stl_create_wfilebuf(FILE* f, ios_base::openmode mode) { 181 auto_ptr<wfilebuf> result(new basic_filebuf<wchar_t, char_traits<wchar_t> >()); 182 result->_M_open(_FILE_fd(f), mode); 183 184 if (result->is_open()) 185 return result.release(); 186 187 return 0; 188 } 189 #endif 190 191 void _STLP_CALL ios_base::_S_initialize() { 192 #if !defined (_STLP_HAS_NO_NAMESPACES) && !defined (_STLP_DONT_USE_PRIV_NAMESPACE) 193 using _STLP_PRIV stdio_istreambuf; 194 using _STLP_PRIV stdio_ostreambuf; 195 #endif 196 197 auto_ptr<streambuf> cin_buf; 198 auto_ptr<streambuf> cout_buf; 199 auto_ptr<streambuf> cerr_buf; 200 auto_ptr<streambuf> clog_buf; 201 202 if (_S_is_synced) 203 cin_buf.reset(new stdio_istreambuf(stdin)); 204 else 205 cin_buf.reset(_Stl_create_filebuf(stdin, ios_base::in)); 206 207 if (_S_is_synced) { 208 #ifdef _STLP_REDIRECT_STDSTREAMS 209 cout_buf.reset(_Stl_create_filebuf("/stdout.txt", ios::out)); 210 cerr_buf.reset(_Stl_create_filebuf("/stderr.txt", ios::out)); 211 clog_buf.reset(_Stl_create_filebuf("/stdlog.txt", ios::out)); 212 #else 213 cout_buf.reset(new stdio_ostreambuf(stdout)); 214 cerr_buf.reset(new stdio_ostreambuf(stderr)); 215 clog_buf.reset(new stdio_ostreambuf(stderr)); 216 #endif 217 } 218 else { 219 cout_buf.reset(_Stl_create_filebuf(stdout, ios_base::out)); 220 cerr_buf.reset(_Stl_create_filebuf(stderr, ios_base::out)); 221 clog_buf.reset(_Stl_create_filebuf(stderr, ios_base::out)); 222 } 223 224 istream* ptr_cin = new(&cin) istream(cin_buf.get()); cin_buf.release(); 225 ostream* ptr_cout = new(&cout) ostream(cout_buf.get()); cout_buf.release(); 226 ostream* ptr_cerr = new(&cerr) ostream(cerr_buf.get()); cerr_buf.release(); 227 /*ostream* ptr_clog = */ new(&clog) ostream(clog_buf.get()); clog_buf.release(); 228 ptr_cin->tie(ptr_cout); 229 ptr_cerr->setf(ios_base::unitbuf); 230 231 #ifndef _STLP_NO_WCHAR_T 232 auto_ptr<wfilebuf> win(_Stl_create_wfilebuf(stdin, ios_base::in)); 233 auto_ptr<wfilebuf> wout(_Stl_create_wfilebuf(stdout, ios_base::out)); 234 auto_ptr<wfilebuf> werr(_Stl_create_wfilebuf(stderr, ios_base::out)); 235 auto_ptr<wfilebuf> wlog(_Stl_create_wfilebuf(stderr, ios_base::out)); 236 237 // Run constructors for the four wide stream objects. 238 wistream* ptr_wcin = new(&wcin) wistream(win.get()); win.release(); 239 wostream* ptr_wcout = new(&wcout) wostream(wout.get()); wout.release(); 240 wostream* ptr_wcerr = new(&wcerr) wostream(werr.get()); werr.release(); 241 /*wostream* ptr_wclog = */ new(&wclog) wostream(wlog.get()); wlog.release(); 242 243 ptr_wcin->tie(ptr_wcout); 244 ptr_wcerr->setf(ios_base::unitbuf); 245 #endif 246 } 247 248 void _STLP_CALL ios_base::_S_uninitialize() { 249 // Note that destroying output streambufs flushes the buffers. 250 istream* ptr_cin = &cin; 251 ostream* ptr_cout = &cout; 252 ostream* ptr_cerr = &cerr; 253 ostream* ptr_clog = &clog; 254 255 // We don't want any exceptions being thrown here 256 ptr_cin->exceptions(0); 257 ptr_cout->exceptions(0); 258 ptr_cerr->exceptions(0); 259 ptr_clog->exceptions(0); 260 261 delete ptr_cin->rdbuf(0); 262 delete ptr_cout->rdbuf(0); 263 delete ptr_cerr->rdbuf(0); 264 delete ptr_clog->rdbuf(0); 265 266 _Destroy(ptr_cin); 267 _Destroy(ptr_cout); 268 _Destroy(ptr_cerr); 269 _Destroy(ptr_clog); 270 271 #ifndef _STLP_NO_WCHAR_T 272 wistream* ptr_wcin = &wcin; 273 wostream* ptr_wcout = &wcout; 274 wostream* ptr_wcerr = &wcerr; 275 wostream* ptr_wclog = &wclog; 276 277 // We don't want any exceptions being thrown here 278 ptr_wcin->exceptions(0); 279 ptr_wcout->exceptions(0); 280 ptr_wcerr->exceptions(0); 281 ptr_wclog->exceptions(0); 282 283 delete ptr_wcin->rdbuf(0); 284 delete ptr_wcout->rdbuf(0); 285 delete ptr_wcerr->rdbuf(0); 286 delete ptr_wclog->rdbuf(0); 287 288 _Destroy(ptr_wcin); 289 _Destroy(ptr_wcout); 290 _Destroy(ptr_wcerr); 291 _Destroy(ptr_wclog); 292 #endif 293 } 294 295 296 bool _STLP_CALL ios_base::sync_with_stdio(bool sync) { 297 # if !defined (_STLP_HAS_NO_NAMESPACES) && !defined (_STLP_DONT_USE_PRIV_NAMESPACE) 298 using _STLP_PRIV stdio_istreambuf; 299 using _STLP_PRIV stdio_ostreambuf; 300 # endif 301 302 if (sync == _S_is_synced) return sync; 303 304 // if by any chance we got there before std streams initialization, 305 // just set the sync flag and exit 306 if (Init::_S_count == 0) { 307 _S_is_synced = sync; 308 return sync; 309 } 310 311 auto_ptr<streambuf> cin_buf; 312 auto_ptr<streambuf> cout_buf; 313 auto_ptr<streambuf> cerr_buf; 314 auto_ptr<streambuf> clog_buf; 315 316 if (sync) 317 cin_buf.reset(new stdio_istreambuf(stdin)); 318 else 319 cin_buf.reset(_Stl_create_filebuf(stdin, ios_base::in)); 320 321 if (sync) { 322 #ifdef _STLP_REDIRECT_STDSTREAMS 323 cout_buf.reset(_Stl_create_filebuf("/stdout.txt", ios::out)); 324 cerr_buf.reset(_Stl_create_filebuf("/stderr.txt", ios::out)); 325 clog_buf.reset(_Stl_create_filebuf("/stdlog.txt", ios::out)); 326 #else 327 cout_buf.reset(new stdio_ostreambuf(stdout)); 328 cerr_buf.reset(new stdio_ostreambuf(stderr)); 329 clog_buf.reset(new stdio_ostreambuf(stderr)); 330 #endif 331 } 332 else { 333 cout_buf.reset(_Stl_create_filebuf(stdout, ios_base::out)); 334 cerr_buf.reset(_Stl_create_filebuf(stderr, ios_base::out)); 335 clog_buf.reset(_Stl_create_filebuf(stderr, ios_base::out)); 336 } 337 338 if (cin_buf.get() != 0 && cout_buf.get() != 0 && cerr_buf.get() != 0 && clog_buf.get() != 0) { 339 // When streambuf passed to rdbuf is not null, rdbuf is exception safe: 340 delete (&cin)->rdbuf(cin_buf.release()); 341 delete (&cout)->rdbuf(cout_buf.release()); 342 delete (&cerr)->rdbuf(cerr_buf.release()); 343 delete (&clog)->rdbuf(clog_buf.release()); 344 _S_is_synced = sync; 345 } 346 347 return _S_is_synced; 348 } 349 350 _STLP_END_NAMESPACE 351 352 // Local Variables: 353 // mode:C++ 354 // End: 355