Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/system/lib/libcxx/src/iostream.cpp
6175 views
1
//===----------------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "std_stream.h"
10
11
#include <__memory/construct_at.h>
12
#include <__ostream/basic_ostream.h>
13
#include <istream>
14
15
#define ABI_NAMESPACE_STR _LIBCPP_TOSTRING(_LIBCPP_ABI_NAMESPACE)
16
17
_LIBCPP_BEGIN_NAMESPACE_STD
18
19
template <class StreamT, class BufferT>
20
union stream_data {
21
constexpr stream_data() {}
22
constexpr ~stream_data() {}
23
struct {
24
// The stream has to be the first element, since that's referenced by the stream declarations in <iostream>
25
StreamT stream;
26
BufferT buffer;
27
mbstate_t mb;
28
};
29
30
void init(FILE* stdstream) {
31
mb = {};
32
std::construct_at(&buffer, stdstream, &mb);
33
std::construct_at(&stream, &buffer);
34
}
35
};
36
37
#define CHAR_MANGLING_char "D"
38
#define CHAR_MANGLING_wchar_t "_W"
39
#define CHAR_MANGLING(CharT) CHAR_MANGLING_##CharT
40
41
#ifdef _LIBCPP_COMPILER_CLANG_BASED
42
# define STRING_DATA_CONSTINIT constinit
43
#else
44
# define STRING_DATA_CONSTINIT
45
#endif
46
47
#ifdef _LIBCPP_ABI_MICROSOFT
48
# define STREAM(StreamT, BufferT, CharT, var) \
49
STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var __asm__( \
50
"?" #var "@" ABI_NAMESPACE_STR "@std@@3V?$" #StreamT \
51
"@" CHAR_MANGLING(CharT) "U?$char_traits@" CHAR_MANGLING(CharT) "@" ABI_NAMESPACE_STR "@std@@@12@A")
52
#else
53
# define STREAM(StreamT, BufferT, CharT, var) STRING_DATA_CONSTINIT stream_data<StreamT<CharT>, BufferT<CharT>> var
54
#endif
55
56
// These definitions and the declarations in <iostream> technically cause ODR violations, since they have different
57
// types (stream_data and {i,o}stream respectively). This means that <iostream> should never be included in this TU.
58
59
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_istream, __stdinbuf, char, cin);
60
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, cout);
61
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, cerr);
62
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, char, clog);
63
#if _LIBCPP_HAS_WIDE_CHARACTERS
64
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_istream, __stdinbuf, wchar_t, wcin);
65
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wcout);
66
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wcerr);
67
_LIBCPP_EXPORTED_FROM_ABI STREAM(basic_ostream, __stdoutbuf, wchar_t, wclog);
68
#endif // _LIBCPP_HAS_WIDE_CHARACTERS
69
70
// Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority
71
// attribute with a value that's reserved for the implementation (we're the implementation).
72
#include "iostream_init.h"
73
74
// On Windows the TLS storage for locales needs to be initialized before we create
75
// the standard streams, otherwise it may not be alive during program termination
76
// when we flush the streams.
77
static void force_locale_initialization() {
78
#if defined(_LIBCPP_MSVCRT_LIKE)
79
static bool once = []() {
80
auto loc = __locale::__newlocale(_LIBCPP_ALL_MASK, "C", 0);
81
{
82
__locale::__locale_guard g(loc); // forces initialization of locale TLS
83
((void)g);
84
}
85
__locale::__freelocale(loc);
86
return true;
87
}();
88
((void)once);
89
#endif
90
}
91
92
class DoIOSInit {
93
public:
94
DoIOSInit();
95
~DoIOSInit();
96
};
97
98
DoIOSInit::DoIOSInit() {
99
force_locale_initialization();
100
101
cin.init(stdin);
102
cout.init(stdout);
103
cerr.init(stderr);
104
clog.init(stderr);
105
106
cin.stream.tie(&cout.stream);
107
std::unitbuf(cerr.stream);
108
cerr.stream.tie(&cout.stream);
109
110
#if _LIBCPP_HAS_WIDE_CHARACTERS
111
wcin.init(stdin);
112
wcout.init(stdout);
113
wcerr.init(stderr);
114
wclog.init(stderr);
115
116
wcin.stream.tie(&wcout.stream);
117
std::unitbuf(wcerr.stream);
118
wcerr.stream.tie(&wcout.stream);
119
#endif
120
}
121
122
DoIOSInit::~DoIOSInit() {
123
cout.stream.flush();
124
clog.stream.flush();
125
126
#if _LIBCPP_HAS_WIDE_CHARACTERS
127
wcout.stream.flush();
128
wclog.stream.flush();
129
#endif
130
}
131
132
ios_base::Init::Init() {
133
static DoIOSInit init_the_streams; // gets initialized once
134
}
135
136
ios_base::Init::~Init() {}
137
138
_LIBCPP_END_NAMESPACE_STD
139
140