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