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 139long ios_base::Init::_S_count = 0; 140// by default, those are synced 141bool ios_base::_S_is_synced = true; 142 143ios_base::Init::Init() { 144 if (_S_count++ == 0) { 145 _Locale_init(); 146 ios_base::_S_initialize(); 147 _Filebuf_base::_S_initialize(); 148 } 149} 150 151ios_base::Init::~Init() { 152 if (--_S_count == 0) { 153 ios_base::_S_uninitialize(); 154 _Locale_final(); 155 } 156} 157 158static int _Stl_extract_open_param(FILE* f) 159{ return _FILE_fd(f); } 160 161#ifdef _STLP_REDIRECT_STDSTREAMS 162static const char* _Stl_extract_open_param(const char* name) 163{ return name; } 164#endif 165 166template <class _Tp> 167static 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) 179static 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 191void _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 248void _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 296bool _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