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