1 //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This implements support for bulk buffered stream output. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/Support/raw_ostream.h" 15 #include "llvm/Support/Format.h" 16 #include "llvm/System/Program.h" 17 #include "llvm/System/Process.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/Config/config.h" 20 #include "llvm/Support/Compiler.h" 21 #include <ostream> 22 23 #if defined(HAVE_UNISTD_H) 24 # include <unistd.h> 25 #endif 26 #if defined(HAVE_FCNTL_H) 27 # include <fcntl.h> 28 #endif 29 30 #if defined(_MSC_VER) 31 #include <io.h> 32 #include <fcntl.h> 33 #ifndef STDIN_FILENO 34 # define STDIN_FILENO 0 35 #endif 36 #ifndef STDOUT_FILENO 37 # define STDOUT_FILENO 1 38 #endif 39 #ifndef STDERR_FILENO 40 # define STDERR_FILENO 2 41 #endif 42 #endif 43 44 using namespace llvm; 45 46 47 // An out of line virtual method to provide a home for the class vtable. 48 void raw_ostream::handle() {} 49 50 raw_ostream &raw_ostream::operator<<(unsigned long N) { 51 // Zero is a special case. 52 if (N == 0) 53 return *this << '0'; 54 55 char NumberBuffer[20]; 56 char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 57 char *CurPtr = EndPtr; 58 59 while (N) { 60 *--CurPtr = '0' + char(N % 10); 61 N /= 10; 62 } 63 return write(CurPtr, EndPtr-CurPtr); 64 } 65 66 raw_ostream &raw_ostream::operator<<(long N) { 67 if (N < 0) { 68 *this << '-'; 69 N = -N; 70 } 71 72 return this->operator<<(static_cast<unsigned long>(N)); 73 } 74 75 raw_ostream &raw_ostream::operator<<(unsigned long long N) { 76 // Zero is a special case. 77 if (N == 0) 78 return *this << '0'; 79 80 char NumberBuffer[20]; 81 char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 82 char *CurPtr = EndPtr; 83 84 while (N) { 85 *--CurPtr = '0' + char(N % 10); 86 N /= 10; 87 } 88 return write(CurPtr, EndPtr-CurPtr); 89 } 90 91 raw_ostream &raw_ostream::operator<<(long long N) { 92 if (N < 0) { 93 *this << '-'; 94 N = -N; 95 } 96 97 return this->operator<<(static_cast<unsigned long long>(N)); 98 } 99 100 raw_ostream &raw_ostream::operator<<(const void *P) { 101 uintptr_t N = (uintptr_t) P; 102 *this << '0' << 'x'; 103 104 // Zero is a special case. 105 if (N == 0) 106 return *this << '0'; 107 108 char NumberBuffer[20]; 109 char *EndPtr = NumberBuffer+sizeof(NumberBuffer); 110 char *CurPtr = EndPtr; 111 112 while (N) { 113 unsigned x = N % 16; 114 *--CurPtr = (x < 10 ? '0' + x : 'a' + x - 10); 115 N /= 16; 116 } 117 118 return write(CurPtr, EndPtr-CurPtr); 119 } 120 121 void raw_ostream::flush_nonempty() { 122 assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty."); 123 write_impl(OutBufStart, OutBufCur - OutBufStart); 124 OutBufCur = OutBufStart; 125 } 126 127 raw_ostream &raw_ostream::write(unsigned char C) { 128 // Group exceptional cases into a single branch. 129 if (OutBufCur >= OutBufEnd) { 130 if (Unbuffered) { 131 write_impl(reinterpret_cast<char*>(&C), 1); 132 return *this; 133 } 134 135 if (!OutBufStart) 136 SetBufferSize(); 137 else 138 flush_nonempty(); 139 } 140 141 *OutBufCur++ = C; 142 return *this; 143 } 144 145 raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) { 146 // Group exceptional cases into a single branch. 147 if (BUILTIN_EXPECT(OutBufCur+Size > OutBufEnd, false)) { 148 if (Unbuffered) { 149 write_impl(Ptr, Size); 150 return *this; 151 } 152 153 if (!OutBufStart) 154 SetBufferSize(); 155 else 156 flush_nonempty(); 157 } 158 159 // Handle short strings specially, memcpy isn't very good at very short 160 // strings. 161 switch (Size) { 162 case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH 163 case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH 164 case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH 165 case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH 166 case 0: break; 167 default: 168 // Normally the string to emit is shorter than the buffer. 169 if (Size <= unsigned(OutBufEnd-OutBufStart)) { 170 memcpy(OutBufCur, Ptr, Size); 171 break; 172 } 173 174 // Otherwise we are emitting a string larger than our buffer. We 175 // know we already flushed, so just write it out directly. 176 write_impl(Ptr, Size); 177 Size = 0; 178 break; 179 } 180 OutBufCur += Size; 181 182 return *this; 183 } 184 185 // Formatted output. 186 raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) { 187 // If we have more than a few bytes left in our output buffer, try 188 // formatting directly onto its end. 189 // 190 // FIXME: This test is a bit silly, since if we don't have enough 191 // space in the buffer we will have to flush the formatted output 192 // anyway. We should just flush upfront in such cases, and use the 193 // whole buffer as our scratch pad. Note, however, that this case is 194 // also necessary for correctness on unbuffered streams. 195 unsigned NextBufferSize = 127; 196 if (OutBufEnd-OutBufCur > 3) { 197 unsigned BufferBytesLeft = OutBufEnd-OutBufCur; 198 unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft); 199 200 // Common case is that we have plenty of space. 201 if (BytesUsed < BufferBytesLeft) { 202 OutBufCur += BytesUsed; 203 return *this; 204 } 205 206 // Otherwise, we overflowed and the return value tells us the size to try 207 // again with. 208 NextBufferSize = BytesUsed; 209 } 210 211 // If we got here, we didn't have enough space in the output buffer for the 212 // string. Try printing into a SmallVector that is resized to have enough 213 // space. Iterate until we win. 214 SmallVector<char, 128> V; 215 216 while (1) { 217 V.resize(NextBufferSize); 218 219 // Try formatting into the SmallVector. 220 unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize); 221 222 // If BytesUsed fit into the vector, we win. 223 if (BytesUsed <= NextBufferSize) 224 return write(&V[0], BytesUsed); 225 226 // Otherwise, try again with a new size. 227 assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?"); 228 NextBufferSize = BytesUsed; 229 } 230 } 231 232 //===----------------------------------------------------------------------===// 233 // Formatted Output 234 //===----------------------------------------------------------------------===// 235 236 // Out of line virtual method. 237 void format_object_base::home() { 238 } 239 240 //===----------------------------------------------------------------------===// 241 // raw_fd_ostream 242 //===----------------------------------------------------------------------===// 243 244 /// raw_fd_ostream - Open the specified file for writing. If an error 245 /// occurs, information about the error is put into ErrorInfo, and the 246 /// stream should be immediately destroyed; the string will be empty 247 /// if no error occurred. 248 raw_fd_ostream::raw_fd_ostream(const char *Filename, bool Binary, 249 std::string &ErrorInfo) : pos(0) { 250 ErrorInfo.clear(); 251 252 // Handle "-" as stdout. 253 if (Filename[0] == '-' && Filename[1] == 0) { 254 FD = STDOUT_FILENO; 255 // If user requested binary then put stdout into binary mode if 256 // possible. 257 if (Binary) 258 sys::Program::ChangeStdoutToBinary(); 259 ShouldClose = false; 260 return; 261 } 262 263 int Flags = O_WRONLY|O_CREAT|O_TRUNC; 264 #ifdef O_BINARY 265 if (Binary) 266 Flags |= O_BINARY; 267 #endif 268 FD = open(Filename, Flags, 0644); 269 if (FD < 0) { 270 ErrorInfo = "Error opening output file '" + std::string(Filename) + "'"; 271 ShouldClose = false; 272 } else { 273 ShouldClose = true; 274 } 275 } 276 277 raw_fd_ostream::~raw_fd_ostream() { 278 if (FD >= 0) { 279 flush(); 280 if (ShouldClose) 281 ::close(FD); 282 } 283 } 284 285 void raw_fd_ostream::write_impl(const char *Ptr, unsigned Size) { 286 assert (FD >= 0 && "File already closed."); 287 pos += Size; 288 ::write(FD, Ptr, Size); 289 } 290 291 void raw_fd_ostream::close() { 292 assert (ShouldClose); 293 ShouldClose = false; 294 flush(); 295 ::close(FD); 296 FD = -1; 297 } 298 299 uint64_t raw_fd_ostream::seek(uint64_t off) { 300 flush(); 301 pos = lseek(FD, off, SEEK_SET); 302 return pos; 303 } 304 305 raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, 306 bool bg) { 307 if (sys::Process::ColorNeedsFlush()) 308 flush(); 309 const char *colorcode = 310 (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg) 311 : sys::Process::OutputColor(colors, bold, bg); 312 if (colorcode) { 313 unsigned len = strlen(colorcode); 314 write(colorcode, len); 315 // don't account colors towards output characters 316 pos -= len; 317 } 318 return *this; 319 } 320 321 raw_ostream &raw_fd_ostream::resetColor() { 322 if (sys::Process::ColorNeedsFlush()) 323 flush(); 324 const char *colorcode = sys::Process::ResetColor(); 325 if (colorcode) { 326 unsigned len = strlen(colorcode); 327 write(colorcode, len); 328 // don't account colors towards output characters 329 pos -= len; 330 } 331 return *this; 332 } 333 334 //===----------------------------------------------------------------------===// 335 // raw_stdout/err_ostream 336 //===----------------------------------------------------------------------===// 337 338 raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {} 339 raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false, 340 true) {} 341 342 // An out of line virtual method to provide a home for the class vtable. 343 void raw_stdout_ostream::handle() {} 344 void raw_stderr_ostream::handle() {} 345 346 /// outs() - This returns a reference to a raw_ostream for standard output. 347 /// Use it like: outs() << "foo" << "bar"; 348 raw_ostream &llvm::outs() { 349 static raw_stdout_ostream S; 350 return S; 351 } 352 353 /// errs() - This returns a reference to a raw_ostream for standard error. 354 /// Use it like: errs() << "foo" << "bar"; 355 raw_ostream &llvm::errs() { 356 static raw_stderr_ostream S; 357 return S; 358 } 359 360 //===----------------------------------------------------------------------===// 361 // raw_os_ostream 362 //===----------------------------------------------------------------------===// 363 364 raw_os_ostream::~raw_os_ostream() { 365 flush(); 366 } 367 368 void raw_os_ostream::write_impl(const char *Ptr, unsigned Size) { 369 OS.write(Ptr, Size); 370 } 371 372 uint64_t raw_os_ostream::current_pos() { return OS.tellp(); } 373 374 uint64_t raw_os_ostream::tell() { 375 return (uint64_t)OS.tellp() + GetNumBytesInBuffer(); 376 } 377 378 //===----------------------------------------------------------------------===// 379 // raw_string_ostream 380 //===----------------------------------------------------------------------===// 381 382 raw_string_ostream::~raw_string_ostream() { 383 flush(); 384 } 385 386 void raw_string_ostream::write_impl(const char *Ptr, unsigned Size) { 387 OS.append(Ptr, Size); 388 } 389 390 //===----------------------------------------------------------------------===// 391 // raw_svector_ostream 392 //===----------------------------------------------------------------------===// 393 394 raw_svector_ostream::~raw_svector_ostream() { 395 flush(); 396 } 397 398 void raw_svector_ostream::write_impl(const char *Ptr, unsigned Size) { 399 OS.append(Ptr, Ptr + Size); 400 } 401 402 uint64_t raw_svector_ostream::current_pos() { return OS.size(); } 403 404 uint64_t raw_svector_ostream::tell() { 405 return OS.size() + GetNumBytesInBuffer(); 406 } 407