Home | History | Annotate | Download | only in src
      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