clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name raw_ostream.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVMSupport/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVMSupport/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVMSupport/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVMSupport/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVMSupport/../include -I /usr/src/gnu/usr.bin/clang/libLLVMSupport/obj -I /usr/src/gnu/usr.bin/clang/libLLVMSupport/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVMSupport/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVMSupport/../../../llvm/llvm/lib/Support/raw_ostream.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "llvm/Support/raw_ostream.h" |
14 | #include "llvm/ADT/STLExtras.h" |
15 | #include "llvm/ADT/StringExtras.h" |
16 | #include "llvm/Config/config.h" |
17 | #include "llvm/Support/Compiler.h" |
18 | #include "llvm/Support/ErrorHandling.h" |
19 | #include "llvm/Support/FileSystem.h" |
20 | #include "llvm/Support/Format.h" |
21 | #include "llvm/Support/FormatVariadic.h" |
22 | #include "llvm/Support/MathExtras.h" |
23 | #include "llvm/Support/NativeFormatting.h" |
24 | #include "llvm/Support/Process.h" |
25 | #include "llvm/Support/Program.h" |
26 | #include <algorithm> |
27 | #include <cctype> |
28 | #include <cerrno> |
29 | #include <cstdio> |
30 | #include <iterator> |
31 | #include <sys/stat.h> |
32 | |
33 | |
34 | #if defined(HAVE_FCNTL_H) |
35 | # include <fcntl.h> |
36 | #endif |
37 | |
38 | #if defined(HAVE_UNISTD_H) |
39 | # include <unistd.h> |
40 | #endif |
41 | |
42 | #if defined(__CYGWIN__) |
43 | #include <io.h> |
44 | #endif |
45 | |
46 | #if defined(_MSC_VER) |
47 | #include <io.h> |
48 | #ifndef STDIN_FILENO |
49 | # define STDIN_FILENO 0 |
50 | #endif |
51 | #ifndef STDOUT_FILENO |
52 | # define STDOUT_FILENO 1 |
53 | #endif |
54 | #ifndef STDERR_FILENO |
55 | # define STDERR_FILENO 2 |
56 | #endif |
57 | #endif |
58 | |
59 | #ifdef _WIN32 |
60 | #include "llvm/Support/ConvertUTF.h" |
61 | #include "llvm/Support/Windows/WindowsSupport.h" |
62 | #endif |
63 | |
64 | using namespace llvm; |
65 | |
66 | constexpr raw_ostream::Colors raw_ostream::BLACK; |
67 | constexpr raw_ostream::Colors raw_ostream::RED; |
68 | constexpr raw_ostream::Colors raw_ostream::GREEN; |
69 | constexpr raw_ostream::Colors raw_ostream::YELLOW; |
70 | constexpr raw_ostream::Colors raw_ostream::BLUE; |
71 | constexpr raw_ostream::Colors raw_ostream::MAGENTA; |
72 | constexpr raw_ostream::Colors raw_ostream::CYAN; |
73 | constexpr raw_ostream::Colors raw_ostream::WHITE; |
74 | constexpr raw_ostream::Colors raw_ostream::SAVEDCOLOR; |
75 | constexpr raw_ostream::Colors raw_ostream::RESET; |
76 | |
77 | raw_ostream::~raw_ostream() { |
78 | |
79 | |
80 | assert(OutBufCur == OutBufStart && |
81 | "raw_ostream destructor called with non-empty buffer!"); |
82 | |
83 | if (BufferMode == BufferKind::InternalBuffer) |
84 | delete [] OutBufStart; |
85 | } |
86 | |
87 | size_t raw_ostream::preferred_buffer_size() const { |
88 | |
89 | return BUFSIZ; |
90 | } |
91 | |
92 | void raw_ostream::SetBuffered() { |
93 | |
94 | if (size_t Size = preferred_buffer_size()) |
| |
| |
95 | SetBufferSize(Size); |
96 | else |
97 | |
98 | SetUnbuffered(); |
| 28 | | Calling 'raw_ostream::SetUnbuffered' | |
|
| 36 | | Returning from 'raw_ostream::SetUnbuffered' | |
|
99 | } |
100 | |
101 | void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size, |
102 | BufferKind Mode) { |
103 | assert(((Mode == BufferKind::Unbuffered && !BufferStart && Size == 0) || |
104 | (Mode != BufferKind::Unbuffered && BufferStart && Size != 0)) && |
105 | "stream must be unbuffered or have at least one byte"); |
106 | |
107 | |
108 | assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!"); |
109 | |
110 | if (BufferMode == BufferKind::InternalBuffer) |
| 31 | | Assuming field 'BufferMode' is not equal to InternalBuffer | |
|
| |
111 | delete [] OutBufStart; |
112 | OutBufStart = BufferStart; |
| 33 | | Null pointer value stored to field 'OutBufStart' | |
|
113 | OutBufEnd = OutBufStart+Size; |
114 | OutBufCur = OutBufStart; |
| 34 | | Null pointer value stored to field 'OutBufCur' | |
|
115 | BufferMode = Mode; |
116 | |
117 | assert(OutBufStart <= OutBufEnd && "Invalid size!"); |
118 | } |
119 | |
120 | raw_ostream &raw_ostream::operator<<(unsigned long N) { |
121 | write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer); |
122 | return *this; |
123 | } |
124 | |
125 | raw_ostream &raw_ostream::operator<<(long N) { |
126 | write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer); |
127 | return *this; |
128 | } |
129 | |
130 | raw_ostream &raw_ostream::operator<<(unsigned long long N) { |
131 | write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer); |
132 | return *this; |
133 | } |
134 | |
135 | raw_ostream &raw_ostream::operator<<(long long N) { |
136 | write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer); |
137 | return *this; |
138 | } |
139 | |
140 | raw_ostream &raw_ostream::write_hex(unsigned long long N) { |
141 | llvm::write_hex(*this, N, HexPrintStyle::Lower); |
142 | return *this; |
143 | } |
144 | |
145 | raw_ostream &raw_ostream::operator<<(Colors C) { |
146 | if (C == Colors::RESET) |
147 | resetColor(); |
148 | else |
149 | changeColor(C); |
150 | return *this; |
151 | } |
152 | |
153 | raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) { |
154 | for (int Idx = 0; Idx < 16; ++Idx) { |
| 1 | Loop condition is true. Entering loop body | |
|
155 | *this << format("%02" PRIX32, UUID[Idx]); |
| 2 | | Calling 'raw_ostream::operator<<' | |
|
156 | if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9) |
157 | *this << "-"; |
158 | } |
159 | return *this; |
160 | } |
161 | |
162 | |
163 | raw_ostream &raw_ostream::write_escaped(StringRef Str, |
164 | bool UseHexEscapes) { |
165 | for (unsigned char c : Str) { |
166 | switch (c) { |
167 | case '\\': |
168 | *this << '\\' << '\\'; |
169 | break; |
170 | case '\t': |
171 | *this << '\\' << 't'; |
172 | break; |
173 | case '\n': |
174 | *this << '\\' << 'n'; |
175 | break; |
176 | case '"': |
177 | *this << '\\' << '"'; |
178 | break; |
179 | default: |
180 | if (isPrint(c)) { |
181 | *this << c; |
182 | break; |
183 | } |
184 | |
185 | |
186 | if (UseHexEscapes) { |
187 | *this << '\\' << 'x'; |
188 | *this << hexdigit((c >> 4 & 0xF)); |
189 | *this << hexdigit((c >> 0) & 0xF); |
190 | } else { |
191 | |
192 | *this << '\\'; |
193 | *this << char('0' + ((c >> 6) & 7)); |
194 | *this << char('0' + ((c >> 3) & 7)); |
195 | *this << char('0' + ((c >> 0) & 7)); |
196 | } |
197 | } |
198 | } |
199 | |
200 | return *this; |
201 | } |
202 | |
203 | raw_ostream &raw_ostream::operator<<(const void *P) { |
204 | llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower); |
205 | return *this; |
206 | } |
207 | |
208 | raw_ostream &raw_ostream::operator<<(double N) { |
209 | llvm::write_double(*this, N, FloatStyle::Exponent); |
210 | return *this; |
211 | } |
212 | |
213 | void raw_ostream::flush_nonempty() { |
214 | assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); |
215 | size_t Length = OutBufCur - OutBufStart; |
216 | OutBufCur = OutBufStart; |
217 | flush_tied_then_write(OutBufStart, Length); |
218 | } |
219 | |
220 | raw_ostream &raw_ostream::write(unsigned char C) { |
221 | |
222 | if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) { |
223 | if (LLVM_UNLIKELY(!OutBufStart)) { |
224 | if (BufferMode == BufferKind::Unbuffered) { |
225 | flush_tied_then_write(reinterpret_cast<char *>(&C), 1); |
226 | return *this; |
227 | } |
228 | |
229 | SetBuffered(); |
230 | return write(C); |
231 | } |
232 | |
233 | flush_nonempty(); |
234 | } |
235 | |
236 | *OutBufCur++ = C; |
237 | return *this; |
238 | } |
239 | |
240 | raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) { |
241 | |
242 | if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) { |
| 19 | | Assuming the condition is true | |
|
| |
| 39 | | Assuming the condition is false | |
|
| |
243 | if (LLVM_UNLIKELY(!OutBufStart)) { |
| 21 | | Assuming field 'OutBufStart' is null | |
|
| |
244 | if (BufferMode == BufferKind::Unbuffered) { |
| 23 | | Assuming field 'BufferMode' is not equal to Unbuffered | |
|
| |
245 | flush_tied_then_write(Ptr, Size); |
246 | return *this; |
247 | } |
248 | |
249 | SetBuffered(); |
| 25 | | Calling 'raw_ostream::SetBuffered' | |
|
| 37 | | Returning from 'raw_ostream::SetBuffered' | |
|
250 | return write(Ptr, Size); |
| 38 | | Calling 'raw_ostream::write' | |
|
251 | } |
252 | |
253 | size_t NumBytes = OutBufEnd - OutBufCur; |
254 | |
255 | |
256 | |
257 | |
258 | if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) { |
259 | assert(NumBytes != 0 && "undefined behavior"); |
260 | size_t BytesToWrite = Size - (Size % NumBytes); |
261 | flush_tied_then_write(Ptr, BytesToWrite); |
262 | size_t BytesRemaining = Size - BytesToWrite; |
263 | if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) { |
264 | |
265 | return write(Ptr + BytesToWrite, BytesRemaining); |
266 | } |
267 | copy_to_buffer(Ptr + BytesToWrite, BytesRemaining); |
268 | return *this; |
269 | } |
270 | |
271 | |
272 | |
273 | copy_to_buffer(Ptr, NumBytes); |
274 | flush_nonempty(); |
275 | return write(Ptr + NumBytes, Size - NumBytes); |
276 | } |
277 | |
278 | copy_to_buffer(Ptr, Size); |
| 41 | | Calling 'raw_ostream::copy_to_buffer' | |
|
279 | |
280 | return *this; |
281 | } |
282 | |
283 | void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) { |
284 | assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!"); |
285 | |
286 | |
287 | |
288 | switch (Size) { |
| 42 | | Control jumps to the 'default' case at line 294 | |
|
289 | case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH; |
290 | case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH; |
291 | case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH; |
292 | case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH; |
293 | case 0: break; |
294 | default: |
295 | memcpy(OutBufCur, Ptr, Size); |
| 43 | | Null pointer passed as 1st argument to memory copy function |
|
296 | break; |
297 | } |
298 | |
299 | OutBufCur += Size; |
300 | } |
301 | |
302 | void raw_ostream::flush_tied_then_write(const char *Ptr, size_t Size) { |
303 | if (TiedStream) |
304 | TiedStream->flush(); |
305 | write_impl(Ptr, Size); |
306 | } |
307 | |
308 | |
309 | raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { |
310 | |
311 | |
312 | size_t NextBufferSize = 127; |
313 | size_t BufferBytesLeft = OutBufEnd - OutBufCur; |
314 | if (BufferBytesLeft > 3) { |
| 3 | | Assuming 'BufferBytesLeft' is <= 3 | |
|
| |
315 | size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); |
316 | |
317 | |
318 | if (BytesUsed <= BufferBytesLeft) { |
319 | OutBufCur += BytesUsed; |
320 | return *this; |
321 | } |
322 | |
323 | |
324 | |
325 | NextBufferSize = BytesUsed; |
326 | } |
327 | |
328 | |
329 | |
330 | |
331 | SmallVector<char, 128> V; |
332 | |
333 | while (true) { |
| 5 | | Loop condition is true. Entering loop body | |
|
| 8 | | Loop condition is true. Entering loop body | |
|
334 | V.resize(NextBufferSize); |
335 | |
336 | |
337 | size_t BytesUsed = Fmt.print(V.data(), NextBufferSize); |
| 9 | | Calling 'format_object_base::print' | |
|
| 15 | | Returning from 'format_object_base::print' | |
|
338 | |
339 | |
340 | if (BytesUsed <= NextBufferSize) |
| 6 | | Assuming 'BytesUsed' is > 'NextBufferSize' | |
|
| |
| 16 | | Assuming 'BytesUsed' is <= 'NextBufferSize' | |
|
| |
341 | return write(V.data(), BytesUsed); |
| 18 | | Calling 'raw_ostream::write' | |
|
342 | |
343 | |
344 | assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); |
345 | NextBufferSize = BytesUsed; |
346 | } |
347 | } |
348 | |
349 | raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) { |
350 | Obj.format(*this); |
351 | return *this; |
352 | } |
353 | |
354 | raw_ostream &raw_ostream::operator<<(const FormattedString &FS) { |
355 | unsigned LeftIndent = 0; |
356 | unsigned RightIndent = 0; |
357 | const ssize_t Difference = FS.Width - FS.Str.size(); |
358 | if (Difference > 0) { |
359 | switch (FS.Justify) { |
360 | case FormattedString::JustifyNone: |
361 | break; |
362 | case FormattedString::JustifyLeft: |
363 | RightIndent = Difference; |
364 | break; |
365 | case FormattedString::JustifyRight: |
366 | LeftIndent = Difference; |
367 | break; |
368 | case FormattedString::JustifyCenter: |
369 | LeftIndent = Difference / 2; |
370 | RightIndent = Difference - LeftIndent; |
371 | break; |
372 | } |
373 | } |
374 | indent(LeftIndent); |
375 | (*this) << FS.Str; |
376 | indent(RightIndent); |
377 | return *this; |
378 | } |
379 | |
380 | raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) { |
381 | if (FN.Hex) { |
382 | HexPrintStyle Style; |
383 | if (FN.Upper && FN.HexPrefix) |
384 | Style = HexPrintStyle::PrefixUpper; |
385 | else if (FN.Upper && !FN.HexPrefix) |
386 | Style = HexPrintStyle::Upper; |
387 | else if (!FN.Upper && FN.HexPrefix) |
388 | Style = HexPrintStyle::PrefixLower; |
389 | else |
390 | Style = HexPrintStyle::Lower; |
391 | llvm::write_hex(*this, FN.HexValue, Style, FN.Width); |
392 | } else { |
393 | llvm::SmallString<16> Buffer; |
394 | llvm::raw_svector_ostream Stream(Buffer); |
395 | llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer); |
396 | if (Buffer.size() < FN.Width) |
397 | indent(FN.Width - Buffer.size()); |
398 | (*this) << Buffer; |
399 | } |
400 | return *this; |
401 | } |
402 | |
403 | raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) { |
404 | if (FB.Bytes.empty()) |
405 | return *this; |
406 | |
407 | size_t LineIndex = 0; |
408 | auto Bytes = FB.Bytes; |
409 | const size_t Size = Bytes.size(); |
410 | HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower; |
411 | uint64_t OffsetWidth = 0; |
412 | if (FB.FirstByteOffset.hasValue()) { |
413 | |
414 | |
415 | |
416 | size_t Lines = Size / FB.NumPerLine; |
417 | uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine; |
418 | unsigned Power = 0; |
419 | if (MaxOffset > 0) |
420 | Power = llvm::Log2_64_Ceil(MaxOffset); |
421 | OffsetWidth = std::max<uint64_t>(4, llvm::alignTo(Power, 4) / 4); |
422 | } |
423 | |
424 | |
425 | unsigned NumByteGroups = |
426 | alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize; |
427 | unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1; |
428 | |
429 | while (!Bytes.empty()) { |
430 | indent(FB.IndentLevel); |
431 | |
432 | if (FB.FirstByteOffset.hasValue()) { |
433 | uint64_t Offset = FB.FirstByteOffset.getValue(); |
434 | llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth); |
435 | *this << ": "; |
436 | } |
437 | |
438 | auto Line = Bytes.take_front(FB.NumPerLine); |
439 | |
440 | size_t CharsPrinted = 0; |
441 | |
442 | for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) { |
443 | if (I && (I % FB.ByteGroupSize) == 0) { |
444 | ++CharsPrinted; |
445 | *this << " "; |
446 | } |
447 | llvm::write_hex(*this, Line[I], HPS, 2); |
448 | } |
449 | |
450 | if (FB.ASCII) { |
451 | |
452 | |
453 | assert(BlockCharWidth >= CharsPrinted); |
454 | indent(BlockCharWidth - CharsPrinted + 2); |
455 | *this << "|"; |
456 | |
457 | |
458 | for (uint8_t Byte : Line) { |
459 | if (isPrint(Byte)) |
460 | *this << static_cast<char>(Byte); |
461 | else |
462 | *this << '.'; |
463 | } |
464 | *this << '|'; |
465 | } |
466 | |
467 | Bytes = Bytes.drop_front(Line.size()); |
468 | LineIndex += Line.size(); |
469 | if (LineIndex < Size) |
470 | *this << '\n'; |
471 | } |
472 | return *this; |
473 | } |
474 | |
475 | template <char C> |
476 | static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) { |
477 | static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, |
478 | C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, |
479 | C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, |
480 | C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, |
481 | C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C}; |
482 | |
483 | |
484 | if (NumChars < array_lengthof(Chars)) |
485 | return OS.write(Chars, NumChars); |
486 | |
487 | while (NumChars) { |
488 | unsigned NumToWrite = std::min(NumChars, |
489 | (unsigned)array_lengthof(Chars)-1); |
490 | OS.write(Chars, NumToWrite); |
491 | NumChars -= NumToWrite; |
492 | } |
493 | return OS; |
494 | } |
495 | |
496 | |
497 | raw_ostream &raw_ostream::indent(unsigned NumSpaces) { |
498 | return write_padding<' '>(*this, NumSpaces); |
499 | } |
500 | |
501 | |
502 | raw_ostream &raw_ostream::write_zeros(unsigned NumZeros) { |
503 | return write_padding<'\0'>(*this, NumZeros); |
504 | } |
505 | |
506 | bool raw_ostream::prepare_colors() { |
507 | |
508 | if (!ColorEnabled) |
509 | return false; |
510 | |
511 | |
512 | |
513 | if (sys::Process::ColorNeedsFlush() && !is_displayed()) |
514 | return false; |
515 | |
516 | if (sys::Process::ColorNeedsFlush()) |
517 | flush(); |
518 | |
519 | return true; |
520 | } |
521 | |
522 | raw_ostream &raw_ostream::changeColor(enum Colors colors, bool bold, bool bg) { |
523 | if (!prepare_colors()) |
524 | return *this; |
525 | |
526 | const char *colorcode = |
527 | (colors == SAVEDCOLOR) |
528 | ? sys::Process::OutputBold(bg) |
529 | : sys::Process::OutputColor(static_cast<char>(colors), bold, bg); |
530 | if (colorcode) |
531 | write(colorcode, strlen(colorcode)); |
532 | return *this; |
533 | } |
534 | |
535 | raw_ostream &raw_ostream::resetColor() { |
536 | if (!prepare_colors()) |
537 | return *this; |
538 | |
539 | if (const char *colorcode = sys::Process::ResetColor()) |
540 | write(colorcode, strlen(colorcode)); |
541 | return *this; |
542 | } |
543 | |
544 | raw_ostream &raw_ostream::reverseColor() { |
545 | if (!prepare_colors()) |
546 | return *this; |
547 | |
548 | if (const char *colorcode = sys::Process::OutputReverse()) |
549 | write(colorcode, strlen(colorcode)); |
550 | return *this; |
551 | } |
552 | |
553 | void raw_ostream::anchor() {} |
554 | |
555 | |
556 | |
557 | |
558 | |
559 | |
560 | void format_object_base::home() { |
561 | } |
562 | |
563 | |
564 | |
565 | |
566 | |
567 | static int getFD(StringRef Filename, std::error_code &EC, |
568 | sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access, |
569 | sys::fs::OpenFlags Flags) { |
570 | assert((Access & sys::fs::FA_Write) && |
571 | "Cannot make a raw_ostream from a read-only descriptor!"); |
572 | |
573 | |
574 | |
575 | if (Filename == "-") { |
576 | EC = std::error_code(); |
577 | |
578 | sys::ChangeStdoutMode(Flags); |
579 | return STDOUT_FILENO; |
580 | } |
581 | |
582 | int FD; |
583 | if (Access & sys::fs::FA_Read) |
584 | EC = sys::fs::openFileForReadWrite(Filename, FD, Disp, Flags); |
585 | else |
586 | EC = sys::fs::openFileForWrite(Filename, FD, Disp, Flags); |
587 | if (EC) |
588 | return -1; |
589 | |
590 | return FD; |
591 | } |
592 | |
593 | raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC) |
594 | : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write, |
595 | sys::fs::OF_None) {} |
596 | |
597 | raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, |
598 | sys::fs::CreationDisposition Disp) |
599 | : raw_fd_ostream(Filename, EC, Disp, sys::fs::FA_Write, sys::fs::OF_None) {} |
600 | |
601 | raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, |
602 | sys::fs::FileAccess Access) |
603 | : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, Access, |
604 | sys::fs::OF_None) {} |
605 | |
606 | raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, |
607 | sys::fs::OpenFlags Flags) |
608 | : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write, |
609 | Flags) {} |
610 | |
611 | raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC, |
612 | sys::fs::CreationDisposition Disp, |
613 | sys::fs::FileAccess Access, |
614 | sys::fs::OpenFlags Flags) |
615 | : raw_fd_ostream(getFD(Filename, EC, Disp, Access, Flags), true) {} |
616 | |
617 | |
618 | |
619 | raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered, |
620 | OStreamKind K) |
621 | : raw_pwrite_stream(unbuffered, K), FD(fd), ShouldClose(shouldClose) { |
622 | if (FD < 0 ) { |
623 | ShouldClose = false; |
624 | return; |
625 | } |
626 | |
627 | enable_colors(true); |
628 | |
629 | |
630 | |
631 | |
632 | |
633 | |
634 | |
635 | if (FD <= STDERR_FILENO) |
636 | ShouldClose = false; |
637 | |
638 | #ifdef _WIN32 |
639 | |
640 | IsWindowsConsole = |
641 | ::GetFileType((HANDLE)::_get_osfhandle(fd)) == FILE_TYPE_CHAR; |
642 | #endif |
643 | |
644 | |
645 | off_t loc = ::lseek(FD, 0, SEEK_CUR); |
646 | #ifdef _WIN32 |
647 | |
648 | sys::fs::file_status Status; |
649 | std::error_code EC = status(FD, Status); |
650 | SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file; |
651 | #else |
652 | SupportsSeeking = loc != (off_t)-1; |
653 | #endif |
654 | if (!SupportsSeeking) |
655 | pos = 0; |
656 | else |
657 | pos = static_cast<uint64_t>(loc); |
658 | } |
659 | |
660 | raw_fd_ostream::~raw_fd_ostream() { |
661 | if (FD >= 0) { |
662 | flush(); |
663 | if (ShouldClose) { |
664 | if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD)) |
665 | error_detected(EC); |
666 | } |
667 | } |
668 | |
669 | #ifdef __MINGW32__ |
670 | |
671 | |
672 | |
673 | |
674 | if (FD == 2) return; |
675 | #endif |
676 | |
677 | |
678 | |
679 | |
680 | |
681 | if (has_error()) |
682 | report_fatal_error("IO failure on output stream: " + error().message(), |
683 | false); |
684 | } |
685 | |
686 | #if defined(_WIN32) |
687 | |
688 | |
689 | |
690 | |
691 | |
692 | |
693 | |
694 | |
695 | |
696 | |
697 | |
698 | |
699 | |
700 | |
701 | static bool write_console_impl(int FD, StringRef Data) { |
702 | SmallVector<wchar_t, 256> WideText; |
703 | |
704 | |
705 | if (auto EC = sys::windows::UTF8ToUTF16(Data, WideText)) |
706 | return false; |
707 | |
708 | |
709 | |
710 | size_t MaxWriteSize = WideText.size(); |
711 | if (!RunningWindows8OrGreater()) |
712 | MaxWriteSize = 32767; |
713 | |
714 | size_t WCharsWritten = 0; |
715 | do { |
716 | size_t WCharsToWrite = |
717 | std::min(MaxWriteSize, WideText.size() - WCharsWritten); |
718 | DWORD ActuallyWritten; |
719 | bool Success = |
720 | ::WriteConsoleW((HANDLE)::_get_osfhandle(FD), &WideText[WCharsWritten], |
721 | WCharsToWrite, &ActuallyWritten, |
722 | nullptr); |
723 | |
724 | |
725 | |
726 | |
727 | if (!Success) |
728 | return false; |
729 | |
730 | WCharsWritten += ActuallyWritten; |
731 | } while (WCharsWritten != WideText.size()); |
732 | return true; |
733 | } |
734 | #endif |
735 | |
736 | void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) { |
737 | assert(FD >= 0 && "File already closed."); |
738 | pos += Size; |
739 | |
740 | #if defined(_WIN32) |
741 | |
742 | |
743 | if (IsWindowsConsole) |
744 | if (write_console_impl(FD, StringRef(Ptr, Size))) |
745 | return; |
746 | #endif |
747 | |
748 | |
749 | |
750 | |
751 | size_t MaxWriteSize = INT32_MAX; |
752 | |
753 | #if defined(__linux__) |
754 | |
755 | |
756 | MaxWriteSize = 1024 * 1024 * 1024; |
757 | #endif |
758 | |
759 | do { |
760 | size_t ChunkSize = std::min(Size, MaxWriteSize); |
761 | ssize_t ret = ::write(FD, Ptr, ChunkSize); |
762 | |
763 | if (ret < 0) { |
764 | |
765 | |
766 | |
767 | |
768 | |
769 | |
770 | |
771 | |
772 | if (errno == EINTR || errno == EAGAIN |
773 | #ifdef EWOULDBLOCK |
774 | || errno == EWOULDBLOCK |
775 | #endif |
776 | ) |
777 | continue; |
778 | |
779 | |
780 | error_detected(std::error_code(errno, std::generic_category())); |
781 | break; |
782 | } |
783 | |
784 | |
785 | |
786 | |
787 | Ptr += ret; |
788 | Size -= ret; |
789 | } while (Size > 0); |
790 | } |
791 | |
792 | void raw_fd_ostream::close() { |
793 | assert(ShouldClose); |
794 | ShouldClose = false; |
795 | flush(); |
796 | if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD)) |
797 | error_detected(EC); |
798 | FD = -1; |
799 | } |
800 | |
801 | uint64_t raw_fd_ostream::seek(uint64_t off) { |
802 | assert(SupportsSeeking && "Stream does not support seeking!"); |
803 | flush(); |
804 | #ifdef _WIN32 |
805 | pos = ::_lseeki64(FD, off, SEEK_SET); |
806 | #elif defined(HAVE_LSEEK64) |
807 | pos = ::lseek64(FD, off, SEEK_SET); |
808 | #else |
809 | pos = ::lseek(FD, off, SEEK_SET); |
810 | #endif |
811 | if (pos == (uint64_t)-1) |
812 | error_detected(std::error_code(errno, std::generic_category())); |
813 | return pos; |
814 | } |
815 | |
816 | void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size, |
817 | uint64_t Offset) { |
818 | uint64_t Pos = tell(); |
819 | seek(Offset); |
820 | write(Ptr, Size); |
821 | seek(Pos); |
822 | } |
823 | |
824 | size_t raw_fd_ostream::preferred_buffer_size() const { |
825 | #if defined(_WIN32) |
826 | |
827 | |
828 | |
829 | |
830 | |
831 | if (IsWindowsConsole) |
832 | return 0; |
833 | return raw_ostream::preferred_buffer_size(); |
834 | #elif !defined(__minix) |
835 | |
836 | assert(FD >= 0 && "File not yet open!"); |
837 | struct stat statbuf; |
838 | if (fstat(FD, &statbuf) != 0) |
839 | return 0; |
840 | |
841 | |
842 | |
843 | |
844 | if (S_ISCHR(statbuf.st_mode) && is_displayed()) |
845 | return 0; |
846 | |
847 | return statbuf.st_blksize; |
848 | #else |
849 | return raw_ostream::preferred_buffer_size(); |
850 | #endif |
851 | } |
852 | |
853 | bool raw_fd_ostream::is_displayed() const { |
854 | return sys::Process::FileDescriptorIsDisplayed(FD); |
855 | } |
856 | |
857 | bool raw_fd_ostream::has_colors() const { |
858 | if (!HasColors) |
859 | HasColors = sys::Process::FileDescriptorHasColors(FD); |
860 | return *HasColors; |
861 | } |
862 | |
863 | Expected<sys::fs::FileLocker> raw_fd_ostream::lock() { |
864 | std::error_code EC = sys::fs::lockFile(FD); |
865 | if (!EC) |
866 | return sys::fs::FileLocker(FD); |
867 | return errorCodeToError(EC); |
868 | } |
869 | |
870 | Expected<sys::fs::FileLocker> |
871 | raw_fd_ostream::tryLockFor(std::chrono::milliseconds Timeout) { |
872 | std::error_code EC = sys::fs::tryLockFile(FD, Timeout); |
873 | if (!EC) |
874 | return sys::fs::FileLocker(FD); |
875 | return errorCodeToError(EC); |
876 | } |
877 | |
878 | void raw_fd_ostream::anchor() {} |
879 | |
880 | |
881 | |
882 | |
883 | |
884 | raw_fd_ostream &llvm::outs() { |
885 | |
886 | std::error_code EC; |
887 | static raw_fd_ostream S("-", EC, sys::fs::OF_None); |
888 | assert(!EC); |
889 | return S; |
890 | } |
891 | |
892 | raw_fd_ostream &llvm::errs() { |
893 | |
894 | static raw_fd_ostream S(STDERR_FILENO, false, true); |
895 | return S; |
896 | } |
897 | |
898 | |
899 | raw_ostream &llvm::nulls() { |
900 | static raw_null_ostream S; |
901 | return S; |
902 | } |
903 | |
904 | |
905 | |
906 | |
907 | |
908 | raw_fd_stream::raw_fd_stream(StringRef Filename, std::error_code &EC) |
909 | : raw_fd_ostream(getFD(Filename, EC, sys::fs::CD_CreateAlways, |
910 | sys::fs::FA_Write | sys::fs::FA_Read, |
911 | sys::fs::OF_None), |
912 | true, false, OStreamKind::OK_FDStream) { |
913 | if (EC) |
914 | return; |
915 | |
916 | |
917 | if (!supportsSeeking()) |
918 | EC = std::make_error_code(std::errc::invalid_argument); |
919 | } |
920 | |
921 | ssize_t raw_fd_stream::read(char *Ptr, size_t Size) { |
922 | assert(get_fd() >= 0 && "File already closed."); |
923 | ssize_t Ret = ::read(get_fd(), (void *)Ptr, Size); |
924 | if (Ret >= 0) |
925 | inc_pos(Ret); |
926 | else |
927 | error_detected(std::error_code(errno, std::generic_category())); |
928 | return Ret; |
929 | } |
930 | |
931 | bool raw_fd_stream::classof(const raw_ostream *OS) { |
932 | return OS->get_kind() == OStreamKind::OK_FDStream; |
933 | } |
934 | |
935 | |
936 | |
937 | |
938 | |
939 | raw_string_ostream::~raw_string_ostream() { |
940 | flush(); |
941 | } |
942 | |
943 | void raw_string_ostream::write_impl(const char *Ptr, size_t Size) { |
944 | OS.append(Ptr, Size); |
945 | } |
946 | |
947 | |
948 | |
949 | |
950 | |
951 | uint64_t raw_svector_ostream::current_pos() const { return OS.size(); } |
952 | |
953 | void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { |
954 | OS.append(Ptr, Ptr + Size); |
955 | } |
956 | |
957 | void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size, |
958 | uint64_t Offset) { |
959 | memcpy(OS.data() + Offset, Ptr, Size); |
960 | } |
961 | |
962 | |
963 | |
964 | |
965 | |
966 | raw_null_ostream::~raw_null_ostream() { |
967 | #ifndef NDEBUG |
968 | |
969 | |
970 | |
971 | flush(); |
972 | #endif |
973 | } |
974 | |
975 | void raw_null_ostream::write_impl(const char *Ptr, size_t Size) { |
976 | } |
977 | |
978 | uint64_t raw_null_ostream::current_pos() const { |
979 | return 0; |
980 | } |
981 | |
982 | void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size, |
983 | uint64_t Offset) {} |
984 | |
985 | void raw_pwrite_stream::anchor() {} |
986 | |
987 | void buffer_ostream::anchor() {} |
988 | |
989 | void buffer_unique_ostream::anchor() {} |
990 | |
991 | Error llvm::writeToOutput(StringRef OutputFileName, |
992 | std::function<Error(raw_ostream &)> Write) { |
993 | if (OutputFileName == "-") |
994 | return Write(outs()); |
995 | |
996 | if (OutputFileName == "/dev/null") { |
997 | raw_null_ostream Out; |
998 | return Write(Out); |
999 | } |
1000 | |
1001 | unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe; |
1002 | Expected<sys::fs::TempFile> Temp = |
1003 | sys::fs::TempFile::create(OutputFileName + ".temp-stream-%%%%%%", Mode); |
1004 | if (!Temp) |
1005 | return createFileError(OutputFileName, Temp.takeError()); |
1006 | |
1007 | raw_fd_ostream Out(Temp->FD, false); |
1008 | |
1009 | if (Error E = Write(Out)) { |
1010 | if (Error DiscardError = Temp->discard()) |
1011 | return joinErrors(std::move(E), std::move(DiscardError)); |
1012 | return E; |
1013 | } |
1014 | Out.flush(); |
1015 | |
1016 | return Temp->keep(OutputFileName); |
1017 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | #ifndef LLVM_SUPPORT_FORMAT_H |
23 | #define LLVM_SUPPORT_FORMAT_H |
24 | |
25 | #include "llvm/ADT/ArrayRef.h" |
26 | #include "llvm/ADT/STLExtras.h" |
27 | #include "llvm/ADT/StringRef.h" |
28 | #include "llvm/Support/DataTypes.h" |
29 | #include <cassert> |
30 | #include <cstdio> |
31 | #include <tuple> |
32 | #include <utility> |
33 | |
34 | namespace llvm { |
35 | |
36 | |
37 | |
38 | class format_object_base { |
39 | protected: |
40 | const char *Fmt; |
41 | ~format_object_base() = default; |
42 | format_object_base(const format_object_base &) = default; |
43 | virtual void home(); |
44 | |
45 | |
46 | virtual int snprint(char *Buffer, unsigned BufferSize) const = 0; |
47 | |
48 | public: |
49 | format_object_base(const char *fmt) : Fmt(fmt) {} |
50 | |
51 | |
52 | |
53 | |
54 | unsigned print(char *Buffer, unsigned BufferSize) const { |
55 | assert(BufferSize && "Invalid buffer size!"); |
56 | |
57 | |
58 | int N = snprint(Buffer, BufferSize); |
59 | |
60 | |
61 | if (N < 0) |
| |
| |
62 | return BufferSize * 2; |
63 | |
64 | |
65 | |
66 | if (unsigned(N) >= BufferSize) |
| 12 | | Assuming 'N' is >= 'BufferSize' | |
|
| |
67 | return N + 1; |
| 14 | | Returning value, which participates in a condition later | |
|
68 | |
69 | |
70 | return N; |
71 | } |
72 | }; |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | template <typename... Args> struct validate_format_parameters; |
81 | template <typename Arg, typename... Args> |
82 | struct validate_format_parameters<Arg, Args...> { |
83 | static_assert(std::is_scalar<Arg>::value, |
84 | "format can't be used with non fundamental / non pointer type"); |
85 | validate_format_parameters() { validate_format_parameters<Args...>(); } |
86 | }; |
87 | template <> struct validate_format_parameters<> {}; |
88 | |
89 | template <typename... Ts> |
90 | class format_object final : public format_object_base { |
91 | std::tuple<Ts...> Vals; |
92 | |
93 | template <std::size_t... Is> |
94 | int snprint_tuple(char *Buffer, unsigned BufferSize, |
95 | std::index_sequence<Is...>) const { |
96 | #ifdef _MSC_VER |
97 | return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); |
98 | #else |
99 | return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); |
100 | #endif |
101 | } |
102 | |
103 | public: |
104 | format_object(const char *fmt, const Ts &... vals) |
105 | : format_object_base(fmt), Vals(vals...) { |
106 | validate_format_parameters<Ts...>(); |
107 | } |
108 | |
109 | int snprint(char *Buffer, unsigned BufferSize) const override { |
110 | return snprint_tuple(Buffer, BufferSize, std::index_sequence_for<Ts...>()); |
111 | } |
112 | }; |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | template <typename... Ts> |
124 | inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) { |
125 | return format_object<Ts...>(Fmt, Vals...); |
126 | } |
127 | |
128 | |
129 | class FormattedString { |
130 | public: |
131 | enum Justification { JustifyNone, JustifyLeft, JustifyRight, JustifyCenter }; |
132 | FormattedString(StringRef S, unsigned W, Justification J) |
133 | : Str(S), Width(W), Justify(J) {} |
134 | |
135 | private: |
136 | StringRef Str; |
137 | unsigned Width; |
138 | Justification Justify; |
139 | friend class raw_ostream; |
140 | }; |
141 | |
142 | |
143 | |
144 | |
145 | inline FormattedString left_justify(StringRef Str, unsigned Width) { |
146 | return FormattedString(Str, Width, FormattedString::JustifyLeft); |
147 | } |
148 | |
149 | |
150 | |
151 | |
152 | inline FormattedString right_justify(StringRef Str, unsigned Width) { |
153 | return FormattedString(Str, Width, FormattedString::JustifyRight); |
154 | } |
155 | |
156 | |
157 | |
158 | |
159 | inline FormattedString center_justify(StringRef Str, unsigned Width) { |
160 | return FormattedString(Str, Width, FormattedString::JustifyCenter); |
161 | } |
162 | |
163 | |
164 | class FormattedNumber { |
165 | uint64_t HexValue; |
166 | int64_t DecValue; |
167 | unsigned Width; |
168 | bool Hex; |
169 | bool Upper; |
170 | bool HexPrefix; |
171 | friend class raw_ostream; |
172 | |
173 | public: |
174 | FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U, |
175 | bool Prefix) |
176 | : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U), |
177 | HexPrefix(Prefix) {} |
178 | }; |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | inline FormattedNumber format_hex(uint64_t N, unsigned Width, |
187 | bool Upper = false) { |
188 | assert(Width <= 18 && "hex width must be <= 18"); |
189 | return FormattedNumber(N, 0, Width, true, Upper, true); |
190 | } |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, |
200 | bool Upper = false) { |
201 | assert(Width <= 16 && "hex width must be <= 16"); |
202 | return FormattedNumber(N, 0, Width, true, Upper, false); |
203 | } |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | inline FormattedNumber format_decimal(int64_t N, unsigned Width) { |
212 | return FormattedNumber(0, N, Width, false, false, false); |
213 | } |
214 | |
215 | class FormattedBytes { |
216 | ArrayRef<uint8_t> Bytes; |
217 | |
218 | |
219 | Optional<uint64_t> FirstByteOffset; |
220 | uint32_t IndentLevel; |
221 | uint32_t NumPerLine; |
222 | uint8_t ByteGroupSize; |
223 | bool Upper; |
224 | bool ASCII; |
225 | friend class raw_ostream; |
226 | |
227 | public: |
228 | FormattedBytes(ArrayRef<uint8_t> B, uint32_t IL, Optional<uint64_t> O, |
229 | uint32_t NPL, uint8_t BGS, bool U, bool A) |
230 | : Bytes(B), FirstByteOffset(O), IndentLevel(IL), NumPerLine(NPL), |
231 | ByteGroupSize(BGS), Upper(U), ASCII(A) { |
232 | |
233 | if (ByteGroupSize > NumPerLine) |
234 | ByteGroupSize = NumPerLine; |
235 | } |
236 | }; |
237 | |
238 | inline FormattedBytes |
239 | format_bytes(ArrayRef<uint8_t> Bytes, Optional<uint64_t> FirstByteOffset = None, |
240 | uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4, |
241 | uint32_t IndentLevel = 0, bool Upper = false) { |
242 | return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine, |
243 | ByteGroupSize, Upper, false); |
244 | } |
245 | |
246 | inline FormattedBytes |
247 | format_bytes_with_ascii(ArrayRef<uint8_t> Bytes, |
248 | Optional<uint64_t> FirstByteOffset = None, |
249 | uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4, |
250 | uint32_t IndentLevel = 0, bool Upper = false) { |
251 | return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine, |
252 | ByteGroupSize, Upper, true); |
253 | } |
254 | |
255 | } |
256 | |
257 | #endif |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_SUPPORT_RAW_OSTREAM_H |
14 | #define LLVM_SUPPORT_RAW_OSTREAM_H |
15 | |
16 | #include "llvm/ADT/SmallVector.h" |
17 | #include "llvm/ADT/StringRef.h" |
18 | #include "llvm/Support/DataTypes.h" |
19 | #include <cassert> |
20 | #include <chrono> |
21 | #include <cstddef> |
22 | #include <cstdint> |
23 | #include <cstring> |
24 | #include <string> |
25 | #if __cplusplus > 201402L |
26 | #include <string_view> |
27 | #endif |
28 | #include <system_error> |
29 | #include <type_traits> |
30 | |
31 | namespace llvm { |
32 | |
33 | class formatv_object_base; |
34 | class format_object_base; |
35 | class FormattedString; |
36 | class FormattedNumber; |
37 | class FormattedBytes; |
38 | template <class T> class LLVM_NODISCARD Expected; |
39 | |
40 | namespace sys { |
41 | namespace fs { |
42 | enum FileAccess : unsigned; |
43 | enum OpenFlags : unsigned; |
44 | enum CreationDisposition : unsigned; |
45 | class FileLocker; |
46 | } |
47 | } |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | class raw_ostream { |
54 | public: |
55 | |
56 | enum class OStreamKind { |
57 | OK_OStream, |
58 | OK_FDStream, |
59 | }; |
60 | |
61 | private: |
62 | OStreamKind Kind; |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | char *OutBufStart, *OutBufEnd, *OutBufCur; |
83 | bool ColorEnabled = false; |
84 | |
85 | |
86 | |
87 | raw_ostream *TiedStream = nullptr; |
88 | |
89 | enum class BufferKind { |
90 | Unbuffered = 0, |
91 | InternalBuffer, |
92 | ExternalBuffer |
93 | } BufferMode; |
94 | |
95 | public: |
96 | |
97 | enum class Colors { |
98 | BLACK = 0, |
99 | RED, |
100 | GREEN, |
101 | YELLOW, |
102 | BLUE, |
103 | MAGENTA, |
104 | CYAN, |
105 | WHITE, |
106 | SAVEDCOLOR, |
107 | RESET, |
108 | }; |
109 | |
110 | static constexpr Colors BLACK = Colors::BLACK; |
111 | static constexpr Colors RED = Colors::RED; |
112 | static constexpr Colors GREEN = Colors::GREEN; |
113 | static constexpr Colors YELLOW = Colors::YELLOW; |
114 | static constexpr Colors BLUE = Colors::BLUE; |
115 | static constexpr Colors MAGENTA = Colors::MAGENTA; |
116 | static constexpr Colors CYAN = Colors::CYAN; |
117 | static constexpr Colors WHITE = Colors::WHITE; |
118 | static constexpr Colors SAVEDCOLOR = Colors::SAVEDCOLOR; |
119 | static constexpr Colors RESET = Colors::RESET; |
120 | |
121 | explicit raw_ostream(bool unbuffered = false, |
122 | OStreamKind K = OStreamKind::OK_OStream) |
123 | : Kind(K), BufferMode(unbuffered ? BufferKind::Unbuffered |
124 | : BufferKind::InternalBuffer) { |
125 | |
126 | OutBufStart = OutBufEnd = OutBufCur = nullptr; |
127 | } |
128 | |
129 | raw_ostream(const raw_ostream &) = delete; |
130 | void operator=(const raw_ostream &) = delete; |
131 | |
132 | virtual ~raw_ostream(); |
133 | |
134 | |
135 | uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } |
136 | |
137 | OStreamKind get_kind() const { return Kind; } |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | virtual void reserveExtraSpace(uint64_t ExtraSize) {} |
149 | |
150 | |
151 | |
152 | void SetBuffered(); |
153 | |
154 | |
155 | void SetBufferSize(size_t Size) { |
156 | flush(); |
157 | SetBufferAndMode(new char[Size], Size, BufferKind::InternalBuffer); |
158 | } |
159 | |
160 | size_t GetBufferSize() const { |
161 | |
162 | |
163 | if (BufferMode != BufferKind::Unbuffered && OutBufStart == nullptr) |
164 | return preferred_buffer_size(); |
165 | |
166 | |
167 | return OutBufEnd - OutBufStart; |
168 | } |
169 | |
170 | |
171 | |
172 | |
173 | void SetUnbuffered() { |
174 | flush(); |
175 | SetBufferAndMode(nullptr, 0, BufferKind::Unbuffered); |
| 29 | | Passing null pointer value via 1st parameter 'BufferStart' | |
|
| 30 | | Calling 'raw_ostream::SetBufferAndMode' | |
|
| 35 | | Returning from 'raw_ostream::SetBufferAndMode' | |
|
176 | } |
177 | |
178 | size_t GetNumBytesInBuffer() const { |
179 | return OutBufCur - OutBufStart; |
180 | } |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | void flush() { |
187 | if (OutBufCur != OutBufStart) |
188 | flush_nonempty(); |
189 | } |
190 | |
191 | raw_ostream &operator<<(char C) { |
192 | if (OutBufCur >= OutBufEnd) |
193 | return write(C); |
194 | *OutBufCur++ = C; |
195 | return *this; |
196 | } |
197 | |
198 | raw_ostream &operator<<(unsigned char C) { |
199 | if (OutBufCur >= OutBufEnd) |
200 | return write(C); |
201 | *OutBufCur++ = C; |
202 | return *this; |
203 | } |
204 | |
205 | raw_ostream &operator<<(signed char C) { |
206 | if (OutBufCur >= OutBufEnd) |
207 | return write(C); |
208 | *OutBufCur++ = C; |
209 | return *this; |
210 | } |
211 | |
212 | raw_ostream &operator<<(StringRef Str) { |
213 | |
214 | size_t Size = Str.size(); |
215 | |
216 | |
217 | if (Size > (size_t)(OutBufEnd - OutBufCur)) |
218 | return write(Str.data(), Size); |
219 | |
220 | if (Size) { |
221 | memcpy(OutBufCur, Str.data(), Size); |
222 | OutBufCur += Size; |
223 | } |
224 | return *this; |
225 | } |
226 | |
227 | raw_ostream &operator<<(const char *Str) { |
228 | |
229 | |
230 | |
231 | return this->operator<<(StringRef(Str)); |
232 | } |
233 | |
234 | raw_ostream &operator<<(const std::string &Str) { |
235 | |
236 | return write(Str.data(), Str.length()); |
237 | } |
238 | |
239 | #if __cplusplus > 201402L |
240 | raw_ostream &operator<<(const std::string_view &Str) { |
241 | return write(Str.data(), Str.length()); |
242 | } |
243 | #endif |
244 | |
245 | raw_ostream &operator<<(const SmallVectorImpl<char> &Str) { |
246 | return write(Str.data(), Str.size()); |
247 | } |
248 | |
249 | raw_ostream &operator<<(unsigned long N); |
250 | raw_ostream &operator<<(long N); |
251 | raw_ostream &operator<<(unsigned long long N); |
252 | raw_ostream &operator<<(long long N); |
253 | raw_ostream &operator<<(const void *P); |
254 | |
255 | raw_ostream &operator<<(unsigned int N) { |
256 | return this->operator<<(static_cast<unsigned long>(N)); |
257 | } |
258 | |
259 | raw_ostream &operator<<(int N) { |
260 | return this->operator<<(static_cast<long>(N)); |
261 | } |
262 | |
263 | raw_ostream &operator<<(double N); |
264 | |
265 | |
266 | raw_ostream &write_hex(unsigned long long N); |
267 | |
268 | |
269 | raw_ostream &operator<<(Colors C); |
270 | |
271 | |
272 | using uuid_t = uint8_t[16]; |
273 | raw_ostream &write_uuid(const uuid_t UUID); |
274 | |
275 | |
276 | |
277 | raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); |
278 | |
279 | raw_ostream &write(unsigned char C); |
280 | raw_ostream &write(const char *Ptr, size_t Size); |
281 | |
282 | |
283 | raw_ostream &operator<<(const format_object_base &Fmt); |
284 | |
285 | |
286 | raw_ostream &operator<<(const FormattedString &); |
287 | |
288 | |
289 | raw_ostream &operator<<(const FormattedNumber &); |
290 | |
291 | |
292 | raw_ostream &operator<<(const formatv_object_base &); |
293 | |
294 | |
295 | raw_ostream &operator<<(const FormattedBytes &); |
296 | |
297 | |
298 | raw_ostream &indent(unsigned NumSpaces); |
299 | |
300 | |
301 | raw_ostream &write_zeros(unsigned NumZeros); |
302 | |
303 | |
304 | |
305 | |
306 | |
307 | |
308 | |
309 | |
310 | virtual raw_ostream &changeColor(enum Colors Color, bool Bold = false, |
311 | bool BG = false); |
312 | |
313 | |
314 | |
315 | virtual raw_ostream &resetColor(); |
316 | |
317 | |
318 | virtual raw_ostream &reverseColor(); |
319 | |
320 | |
321 | |
322 | |
323 | virtual bool is_displayed() const { return false; } |
324 | |
325 | |
326 | |
327 | virtual bool has_colors() const { return is_displayed(); } |
328 | |
329 | |
330 | |
331 | virtual void enable_colors(bool enable) { ColorEnabled = enable; } |
332 | |
333 | |
334 | |
335 | void tie(raw_ostream *TieTo) { TiedStream = TieTo; } |
336 | |
337 | |
338 | |
339 | |
340 | |
341 | private: |
342 | |
343 | |
344 | |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | |
351 | |
352 | |
353 | |
354 | |
355 | virtual void write_impl(const char *Ptr, size_t Size) = 0; |
356 | |
357 | |
358 | |
359 | virtual uint64_t current_pos() const = 0; |
360 | |
361 | protected: |
362 | |
363 | |
364 | |
365 | void SetBuffer(char *BufferStart, size_t Size) { |
366 | SetBufferAndMode(BufferStart, Size, BufferKind::ExternalBuffer); |
367 | } |
368 | |
369 | |
370 | virtual size_t preferred_buffer_size() const; |
371 | |
372 | |
373 | |
374 | const char *getBufferStart() const { return OutBufStart; } |
375 | |
376 | |
377 | |
378 | |
379 | private: |
380 | |
381 | void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); |
382 | |
383 | |
384 | |
385 | void flush_nonempty(); |
386 | |
387 | |
388 | |
389 | void copy_to_buffer(const char *Ptr, size_t Size); |
390 | |
391 | |
392 | |
393 | bool prepare_colors(); |
394 | |
395 | |
396 | void flush_tied_then_write(const char *Ptr, size_t Size); |
397 | |
398 | virtual void anchor(); |
399 | }; |
400 | |
401 | |
402 | |
403 | template <typename OStream, typename T> |
404 | std::enable_if_t<!std::is_reference<OStream>::value && |
405 | std::is_base_of<raw_ostream, OStream>::value, |
406 | OStream &&> |
407 | operator<<(OStream &&OS, const T &Value) { |
408 | OS << Value; |
409 | return std::move(OS); |
410 | } |
411 | |
412 | |
413 | |
414 | |
415 | class raw_pwrite_stream : public raw_ostream { |
416 | virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0; |
417 | void anchor() override; |
418 | |
419 | public: |
420 | explicit raw_pwrite_stream(bool Unbuffered = false, |
421 | OStreamKind K = OStreamKind::OK_OStream) |
422 | : raw_ostream(Unbuffered, K) {} |
423 | void pwrite(const char *Ptr, size_t Size, uint64_t Offset) { |
424 | #ifndef NDEBUG |
425 | uint64_t Pos = tell(); |
426 | |
427 | |
428 | if (Pos) |
429 | assert(Size + Offset <= Pos && "We don't support extending the stream"); |
430 | #endif |
431 | pwrite_impl(Ptr, Size, Offset); |
432 | } |
433 | }; |
434 | |
435 | |
436 | |
437 | |
438 | |
439 | |
440 | |
441 | class raw_fd_ostream : public raw_pwrite_stream { |
442 | int FD; |
443 | bool ShouldClose; |
444 | bool SupportsSeeking = false; |
445 | mutable Optional<bool> HasColors; |
446 | |
447 | #ifdef _WIN32 |
448 | |
449 | |
450 | bool IsWindowsConsole = false; |
451 | #endif |
452 | |
453 | std::error_code EC; |
454 | |
455 | uint64_t pos = 0; |
456 | |
457 | |
458 | void write_impl(const char *Ptr, size_t Size) override; |
459 | |
460 | void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; |
461 | |
462 | |
463 | |
464 | uint64_t current_pos() const override { return pos; } |
465 | |
466 | |
467 | size_t preferred_buffer_size() const override; |
468 | |
469 | void anchor() override; |
470 | |
471 | protected: |
472 | |
473 | void error_detected(std::error_code EC) { this->EC = EC; } |
474 | |
475 | |
476 | int get_fd() const { return FD; } |
477 | |
478 | |
479 | void inc_pos(uint64_t Delta) { pos += Delta; } |
480 | |
481 | public: |
482 | |
483 | |
484 | |
485 | |
486 | |
487 | |
488 | |
489 | |
490 | raw_fd_ostream(StringRef Filename, std::error_code &EC); |
491 | raw_fd_ostream(StringRef Filename, std::error_code &EC, |
492 | sys::fs::CreationDisposition Disp); |
493 | raw_fd_ostream(StringRef Filename, std::error_code &EC, |
494 | sys::fs::FileAccess Access); |
495 | raw_fd_ostream(StringRef Filename, std::error_code &EC, |
496 | sys::fs::OpenFlags Flags); |
497 | raw_fd_ostream(StringRef Filename, std::error_code &EC, |
498 | sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access, |
499 | sys::fs::OpenFlags Flags); |
500 | |
501 | |
502 | |
503 | |
504 | raw_fd_ostream(int fd, bool shouldClose, bool unbuffered = false, |
505 | OStreamKind K = OStreamKind::OK_OStream); |
506 | |
507 | ~raw_fd_ostream() override; |
508 | |
509 | |
510 | |
511 | void close(); |
512 | |
513 | bool supportsSeeking() const { return SupportsSeeking; } |
514 | |
515 | |
516 | |
517 | uint64_t seek(uint64_t off); |
518 | |
519 | bool is_displayed() const override; |
520 | |
521 | bool has_colors() const override; |
522 | |
523 | std::error_code error() const { return EC; } |
524 | |
525 | |
526 | |
527 | |
528 | |
529 | bool has_error() const { return bool(EC); } |
530 | |
531 | |
532 | |
533 | |
534 | |
535 | |
536 | |
537 | |
538 | |
539 | |
540 | void clear_error() { EC = std::error_code(); } |
541 | |
542 | |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | |
554 | |
555 | |
556 | |
557 | |
558 | |
559 | |
560 | |
561 | |
562 | LLVM_NODISCARD Expected<sys::fs::FileLocker> lock(); |
563 | |
564 | |
565 | |
566 | |
567 | |
568 | |
569 | |
570 | |
571 | LLVM_NODISCARD |
572 | Expected<sys::fs::FileLocker> tryLockFor(std::chrono::milliseconds Timeout); |
573 | }; |
574 | |
575 | |
576 | |
577 | raw_fd_ostream &outs(); |
578 | |
579 | |
580 | |
581 | |
582 | |
583 | |
584 | raw_fd_ostream &errs(); |
585 | |
586 | |
587 | raw_ostream &nulls(); |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | |
594 | |
595 | class raw_fd_stream : public raw_fd_ostream { |
596 | public: |
597 | |
598 | |
599 | |
600 | raw_fd_stream(StringRef Filename, std::error_code &EC); |
601 | |
602 | |
603 | |
604 | |
605 | |
606 | |
607 | |
608 | |
609 | |
610 | |
611 | ssize_t read(char *Ptr, size_t Size); |
612 | |
613 | |
614 | static bool classof(const raw_ostream *OS); |
615 | }; |
616 | |
617 | |
618 | |
619 | |
620 | |
621 | |
622 | |
623 | class raw_string_ostream : public raw_ostream { |
624 | std::string &OS; |
625 | |
626 | |
627 | void write_impl(const char *Ptr, size_t Size) override; |
628 | |
629 | |
630 | |
631 | uint64_t current_pos() const override { return OS.size(); } |
632 | |
633 | public: |
634 | explicit raw_string_ostream(std::string &O) : OS(O) { |
635 | SetUnbuffered(); |
636 | } |
637 | ~raw_string_ostream() override; |
638 | |
639 | |
640 | |
641 | std::string& str() { |
642 | flush(); |
643 | return OS; |
644 | } |
645 | |
646 | void reserveExtraSpace(uint64_t ExtraSize) override { |
647 | OS.reserve(tell() + ExtraSize); |
648 | } |
649 | }; |
650 | |
651 | |
652 | |
653 | |
654 | |
655 | |
656 | class raw_svector_ostream : public raw_pwrite_stream { |
657 | SmallVectorImpl<char> &OS; |
658 | |
659 | |
660 | void write_impl(const char *Ptr, size_t Size) override; |
661 | |
662 | void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; |
663 | |
664 | |
665 | uint64_t current_pos() const override; |
666 | |
667 | public: |
668 | |
669 | |
670 | |
671 | |
672 | explicit raw_svector_ostream(SmallVectorImpl<char> &O) : OS(O) { |
673 | SetUnbuffered(); |
674 | } |
675 | |
676 | ~raw_svector_ostream() override = default; |
677 | |
678 | void flush() = delete; |
679 | |
680 | |
681 | StringRef str() const { return StringRef(OS.data(), OS.size()); } |
682 | |
683 | void reserveExtraSpace(uint64_t ExtraSize) override { |
684 | OS.reserve(tell() + ExtraSize); |
685 | } |
686 | }; |
687 | |
688 | |
689 | class raw_null_ostream : public raw_pwrite_stream { |
690 | |
691 | void write_impl(const char *Ptr, size_t size) override; |
692 | void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; |
693 | |
694 | |
695 | |
696 | uint64_t current_pos() const override; |
697 | |
698 | public: |
699 | explicit raw_null_ostream() = default; |
700 | ~raw_null_ostream() override; |
701 | }; |
702 | |
703 | class buffer_ostream : public raw_svector_ostream { |
704 | raw_ostream &OS; |
705 | SmallVector<char, 0> Buffer; |
706 | |
707 | virtual void anchor() override; |
708 | |
709 | public: |
710 | buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer), OS(OS) {} |
711 | ~buffer_ostream() override { OS << str(); } |
712 | }; |
713 | |
714 | class buffer_unique_ostream : public raw_svector_ostream { |
715 | std::unique_ptr<raw_ostream> OS; |
716 | SmallVector<char, 0> Buffer; |
717 | |
718 | virtual void anchor() override; |
719 | |
720 | public: |
721 | buffer_unique_ostream(std::unique_ptr<raw_ostream> OS) |
722 | : raw_svector_ostream(Buffer), OS(std::move(OS)) {} |
723 | ~buffer_unique_ostream() override { *OS << str(); } |
724 | }; |
725 | |
726 | class Error; |
727 | |
728 | |
729 | |
730 | |
731 | |
732 | |
733 | |
734 | Error writeToOutput(StringRef OutputFileName, |
735 | std::function<Error(raw_ostream &)> Write); |
736 | |
737 | } |
738 | |
739 | #endif // LLVM_SUPPORT_RAW_OSTREAM_H |