text: //===--- raw_ostream.cpp - Implement the raw_ostream classes --------------===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  //
  // This implements support for bulk buffered stream output.
  //
  //===----------------------------------------------------------------------===//
  
  #include "llvm/Support/raw_ostream.h"
  #include "llvm/ADT/STLExtras.h"
  #include "llvm/ADT/SmallVector.h"
  #include "llvm/ADT/StringExtras.h"
  #include "llvm/Config/config.h"
  #include "llvm/Support/Compiler.h"
  #include "llvm/Support/ErrorHandling.h"
  #include "llvm/Support/FileSystem.h"
  #include "llvm/Support/Format.h"
  #include "llvm/Support/FormatVariadic.h"
  #include "llvm/Support/MathExtras.h"
  #include "llvm/Support/NativeFormatting.h"
  #include "llvm/Support/Process.h"
  #include "llvm/Support/Program.h"
  #include <algorithm>
  #include <cctype>
  #include <cerrno>
  #include <cstdio>
  #include <iterator>
  #include <sys/stat.h>
  #include <system_error>
  
  // <fcntl.h> may provide O_BINARY.
  #if defined(HAVE_FCNTL_H)
  # include <fcntl.h>
  #endif
  
  #if defined(HAVE_UNISTD_H)
  # include <unistd.h>
  #endif
  
  #if defined(__CYGWIN__)
  #include <io.h>
  #endif
  
  #if defined(_MSC_VER)
  #include <io.h>
  #ifndef STDIN_FILENO
  # define STDIN_FILENO 0
  #endif
  #ifndef STDOUT_FILENO
  # define STDOUT_FILENO 1
  #endif
  #ifndef STDERR_FILENO
  # define STDERR_FILENO 2
  #endif
  #endif
  
  #ifdef _WIN32
  #include "Windows/WindowsSupport.h"
  #endif
  
  using namespace llvm;
  
  raw_ostream::~raw_ostream() {
    // raw_ostream's subclasses should take care to flush the buffer
    // in their destructors.
    assert(OutBufCur == OutBufStart &&
           "raw_ostream destructor called with non-empty buffer!");
  
    if (BufferMode == InternalBuffer)
      delete [] OutBufStart;
  }
  
  size_t raw_ostream::preferred_buffer_size() const {
    // BUFSIZ is intended to be a reasonable default.
    return BUFSIZ;
  }
  
  void raw_ostream::SetBuffered() {
    // Ask the subclass to determine an appropriate buffer size.
    if (size_t Size = preferred_buffer_size())
      SetBufferSize(Size);
    else
      // It may return 0, meaning this stream should be unbuffered.
      SetUnbuffered();
  }
  
  void raw_ostream::SetBufferAndMode(char *BufferStart, size_t Size,
                                     BufferKind Mode) {
    assert(((Mode == Unbuffered && !BufferStart && Size == 0) ||
            (Mode != Unbuffered && BufferStart && Size != 0)) &&
           "stream must be unbuffered or have at least one byte");
    // Make sure the current buffer is free of content (we can't flush here; the
    // child buffer management logic will be in write_impl).
    assert(GetNumBytesInBuffer() == 0 && "Current buffer is non-empty!");
  
    if (BufferMode == InternalBuffer)
      delete [] OutBufStart;
    OutBufStart = BufferStart;
    OutBufEnd = OutBufStart+Size;
    OutBufCur = OutBufStart;
    BufferMode = Mode;
  
    assert(OutBufStart <= OutBufEnd && "Invalid size!");
  }
  
  raw_ostream &raw_ostream::operator<<(unsigned long N) {
    write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(long N) {
    write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(unsigned long long N) {
    write_integer(*this, static_cast<uint64_t>(N), 0, IntegerStyle::Integer);
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(long long N) {
    write_integer(*this, static_cast<int64_t>(N), 0, IntegerStyle::Integer);
    return *this;
  }
  
  raw_ostream &raw_ostream::write_hex(unsigned long long N) {
    llvm::write_hex(*this, N, HexPrintStyle::Lower);
    return *this;
  }
  
  raw_ostream &raw_ostream::write_uuid(const uuid_t UUID) {
    for (int Idx = 0; Idx < 16; ++Idx) {
      *this << format("%02" PRIX32, UUID[Idx]);
      if (Idx == 3 || Idx == 5 || Idx == 7 || Idx == 9)
        *this << "-";
    }
    return *this;
  }
  
  
  raw_ostream &raw_ostream::write_escaped(StringRef Str,
                                          bool UseHexEscapes) {
    for (unsigned char c : Str) {
      switch (c) {
      case '\\':
        *this << '\\' << '\\';
        break;
      case '\t':
        *this << '\\' << 't';
        break;
      case '\n':
        *this << '\\' << 'n';
        break;
      case '"':
        *this << '\\' << '"';
        break;
      default:
        if (isPrint(c)) {
          *this << c;
          break;
        }
  
        // Write out the escaped representation.
        if (UseHexEscapes) {
          *this << '\\' << 'x';
          *this << hexdigit((c >> 4 & 0xF));
          *this << hexdigit((c >> 0) & 0xF);
        } else {
          // Always use a full 3-character octal escape.
          *this << '\\';
          *this << char('0' + ((c >> 6) & 7));
          *this << char('0' + ((c >> 3) & 7));
          *this << char('0' + ((c >> 0) & 7));
        }
      }
    }
  
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(const void *P) {
    llvm::write_hex(*this, (uintptr_t)P, HexPrintStyle::PrefixLower);
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(double N) {
    llvm::write_double(*this, N, FloatStyle::Exponent);
    return *this;
  }
  
  void raw_ostream::flush_nonempty() {
    assert(OutBufCur > OutBufStart && "Invalid call to flush_nonempty.");
    size_t Length = OutBufCur - OutBufStart;
    OutBufCur = OutBufStart;
    write_impl(OutBufStart, Length);
  }
  
  raw_ostream &raw_ostream::write(unsigned char C) {
    // Group exceptional cases into a single branch.
    if (LLVM_UNLIKELY(OutBufCur >= OutBufEnd)) {
      if (LLVM_UNLIKELY(!OutBufStart)) {
        if (BufferMode == Unbuffered) {
          write_impl(reinterpret_cast<char*>(&C), 1);
          return *this;
        }
        // Set up a buffer and start over.
        SetBuffered();
        return write(C);
      }
  
      flush_nonempty();
    }
  
    *OutBufCur++ = C;
    return *this;
  }
  
  raw_ostream &raw_ostream::write(const char *Ptr, size_t Size) {
    // Group exceptional cases into a single branch.
    if (LLVM_UNLIKELY(size_t(OutBufEnd - OutBufCur) < Size)) {
      if (LLVM_UNLIKELY(!OutBufStart)) {
        if (BufferMode == Unbuffered) {
          write_impl(Ptr, Size);
          return *this;
        }
        // Set up a buffer and start over.
        SetBuffered();
        return write(Ptr, Size);
      }
  
      size_t NumBytes = OutBufEnd - OutBufCur;
  
      // If the buffer is empty at this point we have a string that is larger
      // than the buffer. Directly write the chunk that is a multiple of the
      // preferred buffer size and put the remainder in the buffer.
      if (LLVM_UNLIKELY(OutBufCur == OutBufStart)) {
        assert(NumBytes != 0 && "undefined behavior");
        size_t BytesToWrite = Size - (Size % NumBytes);
        write_impl(Ptr, BytesToWrite);
        size_t BytesRemaining = Size - BytesToWrite;
        if (BytesRemaining > size_t(OutBufEnd - OutBufCur)) {
          // Too much left over to copy into our buffer.
          return write(Ptr + BytesToWrite, BytesRemaining);
        }
        copy_to_buffer(Ptr + BytesToWrite, BytesRemaining);
        return *this;
      }
  
      // We don't have enough space in the buffer to fit the string in. Insert as
      // much as possible, flush and start over with the remainder.
      copy_to_buffer(Ptr, NumBytes);
      flush_nonempty();
      return write(Ptr + NumBytes, Size - NumBytes);
    }
  
    copy_to_buffer(Ptr, Size);
  
    return *this;
  }
  
  void raw_ostream::copy_to_buffer(const char *Ptr, size_t Size) {
    assert(Size <= size_t(OutBufEnd - OutBufCur) && "Buffer overrun!");
  
    // Handle short strings specially, memcpy isn't very good at very short
    // strings.
    switch (Size) {
    case 4: OutBufCur[3] = Ptr[3]; LLVM_FALLTHROUGH;
    case 3: OutBufCur[2] = Ptr[2]; LLVM_FALLTHROUGH;
    case 2: OutBufCur[1] = Ptr[1]; LLVM_FALLTHROUGH;
    case 1: OutBufCur[0] = Ptr[0]; LLVM_FALLTHROUGH;
    case 0: break;
    default:
      memcpy(OutBufCur, Ptr, Size);
      break;
    }
  
    OutBufCur += Size;
  }
  
  // Formatted output.
  raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
    // If we have more than a few bytes left in our output buffer, try
    // formatting directly onto its end.
    size_t NextBufferSize = 127;
    size_t BufferBytesLeft = OutBufEnd - OutBufCur;
    if (BufferBytesLeft > 3) {
      size_t BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
  
      // Common case is that we have plenty of space.
      if (BytesUsed <= BufferBytesLeft) {
        OutBufCur += BytesUsed;
        return *this;
      }
  
      // Otherwise, we overflowed and the return value tells us the size to try
      // again with.
      NextBufferSize = BytesUsed;
    }
  
    // If we got here, we didn't have enough space in the output buffer for the
    // string.  Try printing into a SmallVector that is resized to have enough
    // space.  Iterate until we win.
    SmallVector<char, 128> V;
  
    while (true) {
      V.resize(NextBufferSize);
  
      // Try formatting into the SmallVector.
      size_t BytesUsed = Fmt.print(V.data(), NextBufferSize);
  
      // If BytesUsed fit into the vector, we win.
      if (BytesUsed <= NextBufferSize)
        return write(V.data(), BytesUsed);
  
      // Otherwise, try again with a new size.
      assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
      NextBufferSize = BytesUsed;
    }
  }
  
  raw_ostream &raw_ostream::operator<<(const formatv_object_base &Obj) {
    SmallString<128> S;
    Obj.format(*this);
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(const FormattedString &FS) {
    if (FS.Str.size() >= FS.Width || FS.Justify == FormattedString::JustifyNone) {
      this->operator<<(FS.Str);
      return *this;
    }
    const size_t Difference = FS.Width - FS.Str.size();
    switch (FS.Justify) {
    case FormattedString::JustifyLeft:
      this->operator<<(FS.Str);
      this->indent(Difference);
      break;
    case FormattedString::JustifyRight:
      this->indent(Difference);
      this->operator<<(FS.Str);
      break;
    case FormattedString::JustifyCenter: {
      int PadAmount = Difference / 2;
      this->indent(PadAmount);
      this->operator<<(FS.Str);
      this->indent(Difference - PadAmount);
      break;
    }
    default:
      llvm_unreachable("Bad Justification");
    }
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(const FormattedNumber &FN) {
    if (FN.Hex) {
      HexPrintStyle Style;
      if (FN.Upper && FN.HexPrefix)
        Style = HexPrintStyle::PrefixUpper;
      else if (FN.Upper && !FN.HexPrefix)
        Style = HexPrintStyle::Upper;
      else if (!FN.Upper && FN.HexPrefix)
        Style = HexPrintStyle::PrefixLower;
      else
        Style = HexPrintStyle::Lower;
      llvm::write_hex(*this, FN.HexValue, Style, FN.Width);
    } else {
      llvm::SmallString<16> Buffer;
      llvm::raw_svector_ostream Stream(Buffer);
      llvm::write_integer(Stream, FN.DecValue, 0, IntegerStyle::Integer);
      if (Buffer.size() < FN.Width)
        indent(FN.Width - Buffer.size());
      (*this) << Buffer;
    }
    return *this;
  }
  
  raw_ostream &raw_ostream::operator<<(const FormattedBytes &FB) {
    if (FB.Bytes.empty())
      return *this;
  
    size_t LineIndex = 0;
    auto Bytes = FB.Bytes;
    const size_t Size = Bytes.size();
    HexPrintStyle HPS = FB.Upper ? HexPrintStyle::Upper : HexPrintStyle::Lower;
    uint64_t OffsetWidth = 0;
    if (FB.FirstByteOffset.hasValue()) {
      // Figure out how many nibbles are needed to print the largest offset
      // represented by this data set, so that we can align the offset field
      // to the right width.
      size_t Lines = Size / FB.NumPerLine;
      uint64_t MaxOffset = *FB.FirstByteOffset + Lines * FB.NumPerLine;
      unsigned Power = 0;
      if (MaxOffset > 0)
        Power = llvm::Log2_64_Ceil(MaxOffset);
      OffsetWidth = std::max<uint64_t>(4, llvm::alignTo(Power, 4) / 4);
    }
  
    // The width of a block of data including all spaces for group separators.
    unsigned NumByteGroups =
        alignTo(FB.NumPerLine, FB.ByteGroupSize) / FB.ByteGroupSize;
    unsigned BlockCharWidth = FB.NumPerLine * 2 + NumByteGroups - 1;
  
    while (!Bytes.empty()) {
      indent(FB.IndentLevel);
  
      if (FB.FirstByteOffset.hasValue()) {
        uint64_t Offset = FB.FirstByteOffset.getValue();
        llvm::write_hex(*this, Offset + LineIndex, HPS, OffsetWidth);
        *this << ": ";
      }
  
      auto Line = Bytes.take_front(FB.NumPerLine);
  
      size_t CharsPrinted = 0;
      // Print the hex bytes for this line in groups
      for (size_t I = 0; I < Line.size(); ++I, CharsPrinted += 2) {
        if (I && (I % FB.ByteGroupSize) == 0) {
          ++CharsPrinted;
          *this << " ";
        }
        llvm::write_hex(*this, Line[I], HPS, 2);
      }
  
      if (FB.ASCII) {
        // Print any spaces needed for any bytes that we didn't print on this
        // line so that the ASCII bytes are correctly aligned.
        assert(BlockCharWidth >= CharsPrinted);
        indent(BlockCharWidth - CharsPrinted + 2);
        *this << "|";
  
        // Print the ASCII char values for each byte on this line
        for (uint8_t Byte : Line) {
          if (isPrint(Byte))
            *this << static_cast<char>(Byte);
          else
            *this << '.';
        }
        *this << '|';
      }
  
      Bytes = Bytes.drop_front(Line.size());
      LineIndex += Line.size();
      if (LineIndex < Size)
        *this << '\n';
    }
    return *this;
  }
  
  template <char C>
  static raw_ostream &write_padding(raw_ostream &OS, unsigned NumChars) {
    static const char Chars[] = {C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
                                 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
                                 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
                                 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C,
                                 C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C};
  
    // Usually the indentation is small, handle it with a fastpath.
    if (NumChars < array_lengthof(Chars))
      return OS.write(Chars, NumChars);
  
    while (NumChars) {
      unsigned NumToWrite = std::min(NumChars,
                                     (unsigned)array_lengthof(Chars)-1);
      OS.write(Chars, NumToWrite);
      NumChars -= NumToWrite;
    }
    return OS;
  }
  
  /// indent - Insert 'NumSpaces' spaces.
  raw_ostream &raw_ostream::indent(unsigned NumSpaces) {
    return write_padding<' '>(*this, NumSpaces);
  }
  
  /// write_zeros - Insert 'NumZeros' nulls.
  raw_ostream &raw_ostream::write_zeros(unsigned NumZeros) {
    return write_padding<'\0'>(*this, NumZeros);
  }
  
  void raw_ostream::anchor() {}
  
  //===----------------------------------------------------------------------===//
  //  Formatted Output
  //===----------------------------------------------------------------------===//
  
  // Out of line virtual method.
  void format_object_base::home() {
  }
  
  //===----------------------------------------------------------------------===//
  //  raw_fd_ostream
  //===----------------------------------------------------------------------===//
  
  static int getFD(StringRef Filename, std::error_code &EC,
                   sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
                   sys::fs::OpenFlags Flags) {
    assert((Access & sys::fs::FA_Write) &&
           "Cannot make a raw_ostream from a read-only descriptor!");
  
    // Handle "-" as stdout. Note that when we do this, we consider ourself
    // the owner of stdout and may set the "binary" flag globally based on Flags.
    if (Filename == "-") {
      EC = std::error_code();
      // If user requested binary then put stdout into binary mode if
      // possible.
      if (!(Flags & sys::fs::OF_Text))
        sys::ChangeStdoutToBinary();
      return STDOUT_FILENO;
    }
  
    int FD;
    if (Access & sys::fs::FA_Read)
      EC = sys::fs::openFileForReadWrite(Filename, FD, Disp, Flags);
    else
      EC = sys::fs::openFileForWrite(Filename, FD, Disp, Flags);
    if (EC)
      return -1;
  
    return FD;
  }
  
  raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC)
      : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,
                       sys::fs::OF_None) {}
  
  raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
                                 sys::fs::CreationDisposition Disp)
      : raw_fd_ostream(Filename, EC, Disp, sys::fs::FA_Write, sys::fs::OF_None) {}
  
  raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
                                 sys::fs::FileAccess Access)
      : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, Access,
                       sys::fs::OF_None) {}
  
  raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
                                 sys::fs::OpenFlags Flags)
      : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,
                       Flags) {}
  
  raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
                                 sys::fs::CreationDisposition Disp,
                                 sys::fs::FileAccess Access,
                                 sys::fs::OpenFlags Flags)
      : raw_fd_ostream(getFD(Filename, EC, Disp, Access, Flags), true) {}
  
  /// FD is the file descriptor that this writes to.  If ShouldClose is true, this
  /// closes the file when the stream is destroyed.
  raw_fd_ostream::raw_fd_ostream(int fd, bool shouldClose, bool unbuffered)
      : raw_pwrite_stream(unbuffered), FD(fd), ShouldClose(shouldClose) {
    if (FD < 0 ) {
      ShouldClose = false;
      return;
    }
  
    // Do not attempt to close stdout or stderr. We used to try to maintain the
    // property that tools that support writing file to stdout should not also
    // write informational output to stdout, but in practice we were never able to
    // maintain this invariant. Many features have been added to LLVM and clang
    // (-fdump-record-layouts, optimization remarks, etc) that print to stdout, so
    // users must simply be aware that mixed output and remarks is a possibility.
    if (FD <= STDERR_FILENO)
      ShouldClose = false;
  
    // Get the starting position.
    off_t loc = ::lseek(FD, 0, SEEK_CUR);
  #ifdef _WIN32
    // MSVCRT's _lseek(SEEK_CUR) doesn't return -1 for pipes.
    sys::fs::file_status Status;
    std::error_code EC = status(FD, Status);
    SupportsSeeking = !EC && Status.type() == sys::fs::file_type::regular_file;
  #else
    SupportsSeeking = loc != (off_t)-1;
  #endif
    if (!SupportsSeeking)
      pos = 0;
    else
      pos = static_cast<uint64_t>(loc);
  }
  
  raw_fd_ostream::~raw_fd_ostream() {
    if (FD >= 0) {
      flush();
      if (ShouldClose) {
        if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
          error_detected(EC);
      }
    }
  
  #ifdef __MINGW32__
    // On mingw, global dtors should not call exit().
    // report_fatal_error() invokes exit(). We know report_fatal_error()
    // might not write messages to stderr when any errors were detected
    // on FD == 2.
    if (FD == 2) return;
  #endif
  
    // If there are any pending errors, report them now. Clients wishing
    // to avoid report_fatal_error calls should check for errors with
    // has_error() and clear the error flag with clear_error() before
    // destructing raw_ostream objects which may have errors.
    if (has_error())
      report_fatal_error("IO failure on output stream: " + error().message(),
                         /*GenCrashDiag=*/false);
  }
  
  void raw_fd_ostream::write_impl(const char *Ptr, size_t Size) {
    assert(FD >= 0 && "File already closed.");
    pos += Size;
  
    // The maximum write size is limited to INT32_MAX. A write
    // greater than SSIZE_MAX is implementation-defined in POSIX,
    // and Windows _write requires 32 bit input.
    size_t MaxWriteSize = INT32_MAX;
  
  #if defined(__linux__)
    // It is observed that Linux returns EINVAL for a very large write (>2G).
    // Make it a reasonably small value.
    MaxWriteSize = 1024 * 1024 * 1024;
  #elif defined(_WIN32)
    // Writing a large size of output to Windows console returns ENOMEM. It seems
    // that, prior to Windows 8, WriteFile() is redirecting to WriteConsole(), and
    // the latter has a size limit (66000 bytes or less, depending on heap usage).
    if (::_isatty(FD) && !RunningWindows8OrGreater())
      MaxWriteSize = 32767;
  #endif
  
    do {
      size_t ChunkSize = std::min(Size, MaxWriteSize);
      ssize_t ret = ::write(FD, Ptr, ChunkSize);
  
      if (ret < 0) {
        // If it's a recoverable error, swallow it and retry the write.
        //
        // Ideally we wouldn't ever see EAGAIN or EWOULDBLOCK here, since
        // raw_ostream isn't designed to do non-blocking I/O. However, some
        // programs, such as old versions of bjam, have mistakenly used
        // O_NONBLOCK. For compatibility, emulate blocking semantics by
        // spinning until the write succeeds. If you don't want spinning,
        // don't use O_NONBLOCK file descriptors with raw_ostream.
        if (errno == EINTR || errno == EAGAIN
  #ifdef EWOULDBLOCK
            || errno == EWOULDBLOCK
  #endif
            )
          continue;
  
        // Otherwise it's a non-recoverable error. Note it and quit.
        error_detected(std::error_code(errno, std::generic_category()));
        break;
      }
  
      // The write may have written some or all of the data. Update the
      // size and buffer pointer to reflect the remainder that needs
      // to be written. If there are no bytes left, we're done.
      Ptr += ret;
      Size -= ret;
    } while (Size > 0);
  }
  
  void raw_fd_ostream::close() {
    assert(ShouldClose);
    ShouldClose = false;
    flush();
    if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
      error_detected(EC);
    FD = -1;
  }
  
  uint64_t raw_fd_ostream::seek(uint64_t off) {
    assert(SupportsSeeking && "Stream does not support seeking!");
    flush();
  #ifdef _WIN32
    pos = ::_lseeki64(FD, off, SEEK_SET);
  #elif defined(HAVE_LSEEK64)
    pos = ::lseek64(FD, off, SEEK_SET);
  #else
    pos = ::lseek(FD, off, SEEK_SET);
  #endif
    if (pos == (uint64_t)-1)
      error_detected(std::error_code(errno, std::generic_category()));
    return pos;
  }
  
  void raw_fd_ostream::pwrite_impl(const char *Ptr, size_t Size,
                                   uint64_t Offset) {
    uint64_t Pos = tell();
    seek(Offset);
    write(Ptr, Size);
    seek(Pos);
  }
  
  size_t raw_fd_ostream::preferred_buffer_size() const {
  #if !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__minix)
    // Windows and Minix have no st_blksize.
    assert(FD >= 0 && "File not yet open!");
    struct stat statbuf;
    if (fstat(FD, &statbuf) != 0)
      return 0;
  
    // If this is a terminal, don't use buffering. Line buffering
    // would be a more traditional thing to do, but it's not worth
    // the complexity.
    if (S_ISCHR(statbuf.st_mode) && isatty(FD))
      return 0;
    // Return the preferred block size.
    return statbuf.st_blksize;
  #else
    return raw_ostream::preferred_buffer_size();
  #endif
  }
  
  raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
                                           bool bg) {
    if (sys::Process::ColorNeedsFlush())
      flush();
    const char *colorcode =
      (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
      : sys::Process::OutputColor(colors, bold, bg);
    if (colorcode) {
      size_t len = strlen(colorcode);
      write(colorcode, len);
      // don't account colors towards output characters
      pos -= len;
    }
    return *this;
  }
  
  raw_ostream &raw_fd_ostream::resetColor() {
    if (sys::Process::ColorNeedsFlush())
      flush();
    const char *colorcode = sys::Process::ResetColor();
    if (colorcode) {
      size_t len = strlen(colorcode);
      write(colorcode, len);
      // don't account colors towards output characters
      pos -= len;
    }
    return *this;
  }
  
  raw_ostream &raw_fd_ostream::reverseColor() {
    if (sys::Process::ColorNeedsFlush())
      flush();
    const char *colorcode = sys::Process::OutputReverse();
    if (colorcode) {
      size_t len = strlen(colorcode);
      write(colorcode, len);
      // don't account colors towards output characters
      pos -= len;
    }
    return *this;
  }
  
  bool raw_fd_ostream::is_displayed() const {
    return sys::Process::FileDescriptorIsDisplayed(FD);
  }
  
  bool raw_fd_ostream::has_colors() const {
    return sys::Process::FileDescriptorHasColors(FD);
  }
  
  void raw_fd_ostream::anchor() {}
  
  //===----------------------------------------------------------------------===//
  //  outs(), errs(), nulls()
  //===----------------------------------------------------------------------===//
  
  /// outs() - This returns a reference to a raw_ostream for standard output.
  /// Use it like: outs() << "foo" << "bar";
  raw_ostream &llvm::outs() {
    // Set buffer settings to model stdout behavior.
    std::error_code EC;
    static raw_fd_ostream S("-", EC, sys::fs::F_None);
    assert(!EC);
    return S;
  }
  
  /// errs() - This returns a reference to a raw_ostream for standard error.
  /// Use it like: errs() << "foo" << "bar";
  raw_ostream &llvm::errs() {
    // Set standard error to be unbuffered by default.
    static raw_fd_ostream S(STDERR_FILENO, false, true);
    return S;
  }
  
  /// nulls() - This returns a reference to a raw_ostream which discards output.
  raw_ostream &llvm::nulls() {
    static raw_null_ostream S;
    return S;
  }
  
  //===----------------------------------------------------------------------===//
  //  raw_string_ostream
  //===----------------------------------------------------------------------===//
  
  raw_string_ostream::~raw_string_ostream() {
    flush();
  }
  
  void raw_string_ostream::write_impl(const char *Ptr, size_t Size) {
    OS.append(Ptr, Size);
  }
  
  //===----------------------------------------------------------------------===//
  //  raw_svector_ostream
  //===----------------------------------------------------------------------===//
  
  uint64_t raw_svector_ostream::current_pos() const { return OS.size(); }
  
  void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) {
    OS.append(Ptr, Ptr + Size);
  }
  
  void raw_svector_ostream::pwrite_impl(const char *Ptr, size_t Size,
                                        uint64_t Offset) {
    memcpy(OS.data() + Offset, Ptr, Size);
  }
  
  //===----------------------------------------------------------------------===//
  //  raw_null_ostream
  //===----------------------------------------------------------------------===//
  
  raw_null_ostream::~raw_null_ostream() {
  #ifndef NDEBUG
    // ~raw_ostream asserts that the buffer is empty. This isn't necessary
    // with raw_null_ostream, but it's better to have raw_null_ostream follow
    // the rules than to change the rules just for raw_null_ostream.
    flush();
  #endif
  }
  
  void raw_null_ostream::write_impl(const char *Ptr, size_t Size) {
  }
  
  uint64_t raw_null_ostream::current_pos() const {
    return 0;
  }
  
  void raw_null_ostream::pwrite_impl(const char *Ptr, size_t Size,
                                     uint64_t Offset) {}
  
  void raw_pwrite_stream::anchor() {}
  