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 (__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
#  pragma init_seg("STLPORT_NO_INIT")
65
66
_STLP_DECLSPEC istream cin(0);
67
_STLP_DECLSPEC ostream cout(0);
68
_STLP_DECLSPEC ostream cerr(0);
69
_STLP_DECLSPEC ostream clog(0);
70
71
#  ifndef _STLP_NO_WCHAR_T
72
_STLP_DECLSPEC wistream wcin(0);
73
_STLP_DECLSPEC wostream wcout(0);
74
_STLP_DECLSPEC wostream wcerr(0);
75
_STLP_DECLSPEC wostream wclog(0);
76
#  endif
77
78
#else
79
80
// Definitions of the eight global I/O objects that are declared in
81
// <iostream>.  Disgusting hack: we deliberately define them with the
82
// wrong types so that the constructors don't get run automatically.
83
// We need special tricks to make sure that these objects are struct-
84
// aligned rather than byte-aligned.
85
86
// This is not portable.  Declaring a variable with different types in
87
// two translations units is "undefined", according to the C++ standard.
88
// Most compilers, however, silently accept this instead of diagnosing
89
// it as an error.
90
91
#  ifndef __DMC__
92
_STLP_DECLSPEC _Stl_aligned_buffer<istream> cin;
93
_STLP_DECLSPEC _Stl_aligned_buffer<ostream> cout;
94
_STLP_DECLSPEC _Stl_aligned_buffer<ostream> cerr;
95
_STLP_DECLSPEC _Stl_aligned_buffer<ostream> clog;
96
#  else
97
_Stl_aligned_buffer<istream> cin;
98
_Stl_aligned_buffer<ostream> cout;
99
_Stl_aligned_buffer<ostream> cerr;
100
_Stl_aligned_buffer<ostream> clog;
101
102
#    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")
103
#    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")
104
#    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")
105
#    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")
106
#  endif
107
108
#  ifndef _STLP_NO_WCHAR_T
109
110
#    ifndef __DMC__
111
_STLP_DECLSPEC _Stl_aligned_buffer<wistream> wcin;
112
_STLP_DECLSPEC _Stl_aligned_buffer<wostream> wcout;
113
_STLP_DECLSPEC _Stl_aligned_buffer<wostream> wcerr;
114
_STLP_DECLSPEC _Stl_aligned_buffer<wostream> wclog;
115
#    else
116
_Stl_aligned_buffer<wistream> wcin;
117
_Stl_aligned_buffer<wostream> wcout;
118
_Stl_aligned_buffer<wostream> wcerr;
119
_Stl_aligned_buffer<wostream> wclog;
120
121
#      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")
122
#      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")
123
#      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")
124
#      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")
125
#    endif
126
#  endif
127
#endif /* STL_MSVC */
128
129
// Member functions from class ios_base and ios_base::Init
130
131
long ios_base::Init::_S_count = 0;
132
// by default, those are synced
133
bool ios_base::_S_is_synced = true;
134
135
ios_base::Init::Init() {
136
  if (_S_count++ == 0) {
137
    _Locale_init();
138
    ios_base::_S_initialize();
139
    _Filebuf_base::_S_initialize();
140
  }
141
}
142
143
ios_base::Init::~Init() {
144
  if (--_S_count == 0) {
145
    ios_base::_S_uninitialize();
146
    _Locale_final();
147
  }
148
}
149
150
namespace {
151
int _Stl_extract_open_param(FILE* f)
152
{ return _FILE_fd(f); }
153
154
#ifdef _STLP_REDIRECT_STDSTREAMS
155
const char* _Stl_extract_open_param(const char* name)
156
{ return name; }
157
#endif
158
} // end anonymous namespace
159
160
template <class _Tp>
161
static filebuf*
162
_Stl_create_filebuf(_Tp x, ios_base::openmode mode ) {
163
  auto_ptr<filebuf> result(new basic_filebuf<char, char_traits<char> >());
164
  result->open(_Stl_extract_open_param(x), mode);
165
166
  if (result->is_open())
167
    return result.release();
168
169
  return 0;
170
}
171
172
#if !defined (_STLP_NO_WCHAR_T)
173
static wfilebuf*
174
_Stl_create_wfilebuf(FILE* f, ios_base::openmode mode) {
175
  auto_ptr<wfilebuf> result(new basic_filebuf<wchar_t, char_traits<wchar_t> >());
176
  result->_M_open(_FILE_fd(f), mode);
177
178
  if (result->is_open())
179
    return result.release();
180
181
  return 0;
182
}
183
#endif
184
185
void  _STLP_CALL ios_base::_S_initialize() {
186
#if !defined (_STLP_HAS_NO_NAMESPACES) && !defined (_STLP_DONT_USE_PRIV_NAMESPACE)
187
  using _STLP_PRIV stdio_istreambuf;
188
  using _STLP_PRIV stdio_ostreambuf;
189
#endif
190
191
  auto_ptr<streambuf> cin_buf;
192
  auto_ptr<streambuf> cout_buf;
193
  auto_ptr<streambuf> cerr_buf;
194
  auto_ptr<streambuf> clog_buf;
195
196
  if (_S_is_synced)
197
    cin_buf.reset(new stdio_istreambuf(stdin));
198
  else
199
    cin_buf.reset(_Stl_create_filebuf(stdin, ios_base::in));
200
201
  if (_S_is_synced) {
202
#ifdef _STLP_REDIRECT_STDSTREAMS
203
    cout_buf.reset(_Stl_create_filebuf("/stdout.txt", ios::out));
204
    cerr_buf.reset(_Stl_create_filebuf("/stderr.txt", ios::out));
205
    clog_buf.reset(_Stl_create_filebuf("/stdlog.txt", ios::out));
206
#else
207
    cout_buf.reset(new stdio_ostreambuf(stdout));
208
    cerr_buf.reset(new stdio_ostreambuf(stderr));
209
    clog_buf.reset(new stdio_ostreambuf(stderr));
210
#endif
211
  }
212
  else {
213
    cout_buf.reset(_Stl_create_filebuf(stdout, ios_base::out));
214
    cerr_buf.reset(_Stl_create_filebuf(stderr, ios_base::out));
215
    clog_buf.reset(_Stl_create_filebuf(stderr, ios_base::out));
216
  }
217
218
  istream* ptr_cin  = new(&cin)  istream(cin_buf.get()); cin_buf.release();
219
  ostream* ptr_cout = new(&cout) ostream(cout_buf.get()); cout_buf.release();
220
  ostream* ptr_cerr = new(&cerr) ostream(cerr_buf.get()); cerr_buf.release();
221
  /*ostream* ptr_clog = */ new(&clog) ostream(clog_buf.get()); clog_buf.release();
222
  ptr_cin->tie(ptr_cout);
223
  ptr_cerr->setf(ios_base::unitbuf);
224
225
#ifndef _STLP_NO_WCHAR_T
226
  auto_ptr<wfilebuf> win(_Stl_create_wfilebuf(stdin, ios_base::in));
227
  auto_ptr<wfilebuf> wout(_Stl_create_wfilebuf(stdout, ios_base::out));
228
  auto_ptr<wfilebuf> werr(_Stl_create_wfilebuf(stderr, ios_base::out));
229
  auto_ptr<wfilebuf> wlog(_Stl_create_wfilebuf(stderr, ios_base::out));
230
231
  // Run constructors for the four wide stream objects.
232
  wistream* ptr_wcin  = new(&wcin)  wistream(win.get()); win.release();
233
  wostream* ptr_wcout = new(&wcout) wostream(wout.get()); wout.release();
234
  wostream* ptr_wcerr = new(&wcerr) wostream(werr.get()); werr.release();
235
  /*wostream* ptr_wclog = */ new(&wclog) wostream(wlog.get()); wlog.release();
236
237
  ptr_wcin->tie(ptr_wcout);
238
  ptr_wcerr->setf(ios_base::unitbuf);
239
#endif
240
}
241
242
void _STLP_CALL ios_base::_S_uninitialize() {
243
  // Note that destroying output streambufs flushes the buffers.
244
  istream* ptr_cin  = &cin;
245
  ostream* ptr_cout = &cout;
246
  ostream* ptr_cerr = &cerr;
247
  ostream* ptr_clog = &clog;
248
249
  // We don't want any exceptions being thrown here
250
  ptr_cin->exceptions(0);
251
  ptr_cout->exceptions(0);
252
  ptr_cerr->exceptions(0);
253
  ptr_clog->exceptions(0);
254
255
  delete ptr_cin->rdbuf(0);
256
  delete ptr_cout->rdbuf(0);
257
  delete ptr_cerr->rdbuf(0);
258
  delete ptr_clog->rdbuf(0);
259
260
  ptr_cin->~istream();
261
  ptr_cout->~ostream();
262
  ptr_cerr->~ostream();
263
  ptr_clog->~ostream();
264
265
#ifndef _STLP_NO_WCHAR_T
266
  wistream* ptr_wcin  = &wcin;
267
  wostream* ptr_wcout = &wcout;
268
  wostream* ptr_wcerr = &wcerr;
269
  wostream* ptr_wclog = &wclog;
270
271
  // We don't want any exceptions being thrown here
272
  ptr_wcin->exceptions(0);
273
  ptr_wcout->exceptions(0);
274
  ptr_wcerr->exceptions(0);
275
  ptr_wclog->exceptions(0);
276
277
  delete ptr_wcin->rdbuf(0);
278
  delete ptr_wcout->rdbuf(0);
279
  delete ptr_wcerr->rdbuf(0);
280
  delete ptr_wclog->rdbuf(0);
281
282
  ptr_wcin->~wistream();
283
  ptr_wcout->~wostream();
284
  ptr_wcerr->~wostream();
285
  ptr_wclog->~wostream();
286
#endif
287
}
288
289
290
bool _STLP_CALL ios_base::sync_with_stdio(bool sync) {
291
#  if !defined (_STLP_HAS_NO_NAMESPACES) && !defined (_STLP_DONT_USE_PRIV_NAMESPACE)
292
  using _STLP_PRIV stdio_istreambuf;
293
  using _STLP_PRIV stdio_ostreambuf;
294
#  endif
295
296
  if (sync == _S_is_synced) return sync;
297
298
  // if by any chance we got there before std streams initialization,
299
  // just set the sync flag and exit
300
  if (Init::_S_count == 0) {
301
    _S_is_synced = sync;
302
    return sync;
303
  }
304
305
  auto_ptr<streambuf> cin_buf;
306
  auto_ptr<streambuf> cout_buf;
307
  auto_ptr<streambuf> cerr_buf;
308
  auto_ptr<streambuf> clog_buf;
309
310
  if (sync)
311
    cin_buf.reset(new stdio_istreambuf(stdin));
312
  else
313
    cin_buf.reset(_Stl_create_filebuf(stdin, ios_base::in));
314
315
  if (sync) {
316
#ifdef _STLP_REDIRECT_STDSTREAMS
317
    cout_buf.reset(_Stl_create_filebuf("/stdout.txt", ios::out));
318
    cerr_buf.reset(_Stl_create_filebuf("/stderr.txt", ios::out));
319
    clog_buf.reset(_Stl_create_filebuf("/stdlog.txt", ios::out));
320
#else
321
    cout_buf.reset(new stdio_ostreambuf(stdout));
322
    cerr_buf.reset(new stdio_ostreambuf(stderr));
323
    clog_buf.reset(new stdio_ostreambuf(stderr));
324
#endif
325
  }
326
  else {
327
    cout_buf.reset(_Stl_create_filebuf(stdout, ios_base::out));
328
    cerr_buf.reset(_Stl_create_filebuf(stderr, ios_base::out));
329
    clog_buf.reset(_Stl_create_filebuf(stderr, ios_base::out));
330
  }
331
332
  if (cin_buf.get() != 0 && cout_buf.get() != 0 && cerr_buf.get() != 0 && clog_buf.get() != 0) {
333
    // When streambuf passed to rdbuf is not null, rdbuf is exception safe:
334
    delete (&cin)->rdbuf(cin_buf.release());
335
    delete (&cout)->rdbuf(cout_buf.release());
336
    delete (&cerr)->rdbuf(cerr_buf.release());
337
    delete (&clog)->rdbuf(clog_buf.release());
338
    _S_is_synced = sync;
339
  }
340
341
  return _S_is_synced;
342
}
343
344
_STLP_END_NAMESPACE
345
346
// Local Variables:
347
// mode:C++
348
// End: