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 | #include <__locale> |
11 | #include <new> |
12 | #include <string> |
13 | |
14 | #ifdef _LIBCPP_MSVCRT_LIKE |
15 | # include <__locale_dir/locale_base_api/locale_guard.h> |
16 | #endif |
17 | |
18 | #define _str(s) #s |
19 | #define str(s) _str(s) |
20 | #define _LIBCPP_ABI_NAMESPACE_STR str(_LIBCPP_ABI_NAMESPACE) |
21 | |
22 | _LIBCPP_BEGIN_NAMESPACE_STD |
23 | |
24 | alignas(istream) _LIBCPP_EXPORTED_FROM_ABI char cin[sizeof(istream)] |
25 | #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
26 | __asm__("?cin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR |
27 | "@std@@@12@A" ) |
28 | #endif |
29 | ; |
30 | alignas(__stdinbuf<char>) static char __cin[sizeof(__stdinbuf<char>)]; |
31 | static mbstate_t mb_cin; |
32 | |
33 | #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
34 | alignas(wistream) _LIBCPP_EXPORTED_FROM_ABI char wcin[sizeof(wistream)] |
35 | # if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
36 | __asm__("?wcin@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_istream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR |
37 | "@std@@@12@A" ) |
38 | # endif |
39 | ; |
40 | alignas(__stdinbuf<wchar_t>) static char __wcin[sizeof(__stdinbuf<wchar_t>)]; |
41 | static mbstate_t mb_wcin; |
42 | #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS |
43 | |
44 | alignas(ostream) _LIBCPP_EXPORTED_FROM_ABI char cout[sizeof(ostream)] |
45 | #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
46 | __asm__("?cout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR |
47 | "@std@@@12@A" ) |
48 | #endif |
49 | ; |
50 | alignas(__stdoutbuf<char>) static char __cout[sizeof(__stdoutbuf<char>)]; |
51 | static mbstate_t mb_cout; |
52 | |
53 | #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
54 | alignas(wostream) _LIBCPP_EXPORTED_FROM_ABI char wcout[sizeof(wostream)] |
55 | # if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
56 | __asm__("?wcout@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR |
57 | "@std@@@12@A" ) |
58 | # endif |
59 | ; |
60 | alignas(__stdoutbuf<wchar_t>) static char __wcout[sizeof(__stdoutbuf<wchar_t>)]; |
61 | static mbstate_t mb_wcout; |
62 | #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS |
63 | |
64 | alignas(ostream) _LIBCPP_EXPORTED_FROM_ABI char cerr[sizeof(ostream)] |
65 | #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
66 | __asm__("?cerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR |
67 | "@std@@@12@A" ) |
68 | #endif |
69 | ; |
70 | alignas(__stdoutbuf<char>) static char __cerr[sizeof(__stdoutbuf<char>)]; |
71 | static mbstate_t mb_cerr; |
72 | |
73 | #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
74 | alignas(wostream) _LIBCPP_EXPORTED_FROM_ABI char wcerr[sizeof(wostream)] |
75 | # if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
76 | __asm__("?wcerr@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR |
77 | "@std@@@12@A" ) |
78 | # endif |
79 | ; |
80 | alignas(__stdoutbuf<wchar_t>) static char __wcerr[sizeof(__stdoutbuf<wchar_t>)]; |
81 | static mbstate_t mb_wcerr; |
82 | #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS |
83 | |
84 | alignas(ostream) _LIBCPP_EXPORTED_FROM_ABI char clog[sizeof(ostream)] |
85 | #if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
86 | __asm__("?clog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@DU?$char_traits@D@" _LIBCPP_ABI_NAMESPACE_STR |
87 | "@std@@@12@A" ) |
88 | #endif |
89 | ; |
90 | |
91 | #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
92 | alignas(wostream) _LIBCPP_EXPORTED_FROM_ABI char wclog[sizeof(wostream)] |
93 | # if defined(_LIBCPP_ABI_MICROSOFT) && defined(__clang__) |
94 | __asm__("?wclog@" _LIBCPP_ABI_NAMESPACE_STR "@std@@3V?$basic_ostream@_WU?$char_traits@_W@" _LIBCPP_ABI_NAMESPACE_STR |
95 | "@std@@@12@A" ) |
96 | # endif |
97 | ; |
98 | #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS |
99 | |
100 | // Pretend we're inside a system header so the compiler doesn't flag the use of the init_priority |
101 | // attribute with a value that's reserved for the implementation (we're the implementation). |
102 | #include "iostream_init.h" |
103 | |
104 | // On Windows the TLS storage for locales needs to be initialized before we create |
105 | // the standard streams, otherwise it may not be alive during program termination |
106 | // when we flush the streams. |
107 | static void force_locale_initialization() { |
108 | #if defined(_LIBCPP_MSVCRT_LIKE) |
109 | static bool once = []() { |
110 | auto loc = newlocale(LC_ALL_MASK, "C" , 0); |
111 | { |
112 | __libcpp_locale_guard g(loc); // forces initialization of locale TLS |
113 | ((void)g); |
114 | } |
115 | freelocale(loc); |
116 | return true; |
117 | }(); |
118 | ((void)once); |
119 | #endif |
120 | } |
121 | |
122 | class DoIOSInit { |
123 | public: |
124 | DoIOSInit(); |
125 | ~DoIOSInit(); |
126 | }; |
127 | |
128 | DoIOSInit::DoIOSInit() { |
129 | force_locale_initialization(); |
130 | |
131 | istream* cin_ptr = ::new (cin) istream(::new (__cin) __stdinbuf<char>(stdin, &mb_cin)); |
132 | ostream* cout_ptr = ::new (cout) ostream(::new (__cout) __stdoutbuf<char>(stdout, &mb_cout)); |
133 | ostream* cerr_ptr = ::new (cerr) ostream(::new (__cerr) __stdoutbuf<char>(stderr, &mb_cerr)); |
134 | ::new (clog) ostream(cerr_ptr->rdbuf()); |
135 | cin_ptr->tie(tiestr: cout_ptr); |
136 | std::unitbuf(base&: *cerr_ptr); |
137 | cerr_ptr->tie(tiestr: cout_ptr); |
138 | |
139 | #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
140 | wistream* wcin_ptr = ::new (wcin) wistream(::new (__wcin) __stdinbuf<wchar_t>(stdin, &mb_wcin)); |
141 | wostream* wcout_ptr = ::new (wcout) wostream(::new (__wcout) __stdoutbuf<wchar_t>(stdout, &mb_wcout)); |
142 | wostream* wcerr_ptr = ::new (wcerr) wostream(::new (__wcerr) __stdoutbuf<wchar_t>(stderr, &mb_wcerr)); |
143 | ::new (wclog) wostream(wcerr_ptr->rdbuf()); |
144 | |
145 | wcin_ptr->tie(tiestr: wcout_ptr); |
146 | std::unitbuf(base&: *wcerr_ptr); |
147 | wcerr_ptr->tie(tiestr: wcout_ptr); |
148 | #endif |
149 | } |
150 | |
151 | DoIOSInit::~DoIOSInit() { |
152 | ostream* cout_ptr = reinterpret_cast<ostream*>(cout); |
153 | cout_ptr->flush(); |
154 | ostream* clog_ptr = reinterpret_cast<ostream*>(clog); |
155 | clog_ptr->flush(); |
156 | |
157 | #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
158 | wostream* wcout_ptr = reinterpret_cast<wostream*>(wcout); |
159 | wcout_ptr->flush(); |
160 | wostream* wclog_ptr = reinterpret_cast<wostream*>(wclog); |
161 | wclog_ptr->flush(); |
162 | #endif |
163 | } |
164 | |
165 | ios_base::Init::Init() { |
166 | static DoIOSInit init_the_streams; // gets initialized once |
167 | } |
168 | |
169 | ios_base::Init::~Init() {} |
170 | |
171 | _LIBCPP_END_NAMESPACE_STD |
172 | |