1191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene//===-- llvm/Support/FormattedStream.cpp - Formatted streams ----*- C++ -*-===//
262fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//
362fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//                     The LLVM Compiler Infrastructure
462fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//
5191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene// This file is distributed under the University of Illinois Open Source
6191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene// License. See LICENSE.TXT for details.
762fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//
862fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//===----------------------------------------------------------------------===//
962fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//
101f318e00bad8b7499ef14d5732bcbda89243ec89Chris Lattner// This file contains the implementation of formatted_raw_ostream.
1162fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//
1262fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene//===----------------------------------------------------------------------===//
1362fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene
148f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene#include "llvm/Support/Debug.h"
1562fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene#include "llvm/Support/FormattedStream.h"
16476b242fe7a61e5f9ac6214b0bc5c680d24f152eNick Lewycky#include <algorithm>
17ed0e2adc7076365596ee3d26d5ba5240ce13f23dDavid Greene
18191cf2851b40fea6b7d927d5de8f22c35dd33828David Greeneusing namespace llvm;
19191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
20f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea/// UpdatePosition - Examine the given char sequence and figure out which
21f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea/// column we end up in after output, and how many line breaks are contained.
22191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene///
23f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Maleastatic void UpdatePosition(std::pair<unsigned, unsigned> &Position, const char *Ptr, size_t Size) {
24f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  unsigned &Column = Position.first;
25f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  unsigned &Line = Position.second;
26191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
27f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  // Keep track of the current column and line by scanning the string for
28f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  // special characters
29fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  for (const char *End = Ptr + Size; Ptr != End; ++Ptr) {
30fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman    ++Column;
31f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    switch (*Ptr) {
32f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    case '\n':
33f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea      Line += 1;
34f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    case '\r':
35fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman      Column = 0;
36f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea      break;
37f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    case '\t':
38eb85728970c6152842577658ac2c5d2ff3a98b13David Greene      // Assumes tab stop = 8 characters.
39fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman      Column += (8 - (Column & 0x7)) & 0x7;
40f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea      break;
41f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    }
4262fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene  }
43fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman}
44fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
45f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea/// ComputePosition - Examine the current output and update line and column
46f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea/// counts.
47f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Maleavoid formatted_raw_ostream::ComputePosition(const char *Ptr, size_t Size) {
48ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // If our previous scan pointer is inside the buffer, assume we already
49ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // scanned those bytes. This depends on raw_ostream to not change our buffer
50ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // in unexpected ways.
51f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  if (Ptr <= Scanned && Scanned <= Ptr + Size)
52ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar    // Scan all characters added since our last scan to determine the new
53ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar    // column.
54f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    UpdatePosition(Position, Scanned, Size - (Scanned - Ptr));
55f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  else
56f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea    UpdatePosition(Position, Ptr, Size);
57ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar
58ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // Update the scanning pointer.
59ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  Scanned = Ptr + Size;
60191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene}
6162fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene
62191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene/// PadToColumn - Align the output to some column number.
63191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene///
64191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene/// \param NewCol - The column to move to.
65191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene///
66efbdaa6463c8febe9cbfdd6d39f3a9ba18773427Chris Lattnerformatted_raw_ostream &formatted_raw_ostream::PadToColumn(unsigned NewCol) {
67eb85728970c6152842577658ac2c5d2ff3a98b13David Greene  // Figure out what's in the buffer and add it to the column count.
68f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  ComputePosition(getBufferStart(), GetNumBytesInBuffer());
69191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
70191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene  // Output spaces until we reach the desired column.
71f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  indent(std::max(int(NewCol - getColumn()), 1));
72efbdaa6463c8febe9cbfdd6d39f3a9ba18773427Chris Lattner  return *this;
7362fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene}
74191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
75a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohmanvoid formatted_raw_ostream::write_impl(const char *Ptr, size_t Size) {
76fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  // Figure out what's in the buffer and add it to the column count.
77f28e3c501e033f103405c03a4bbf848cb6e67a2aDaniel Malea  ComputePosition(Ptr, Size);
78fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
79fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  // Write the data to the underlying stream (which is unbuffered, so
80fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  // the data will be immediately written out).
81a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohman  TheStream->write(Ptr, Size);
82fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
83ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // Reset the scanning pointer.
84dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Scanned = nullptr;
85a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohman}
86a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohman
8771847813bc419f7a0667468136a07429c6d9f164David Greene/// fouts() - This returns a reference to a formatted_raw_ostream for
8871847813bc419f7a0667468136a07429c6d9f164David Greene/// standard output.  Use it like: fouts() << "foo" << "bar";
8971847813bc419f7a0667468136a07429c6d9f164David Greeneformatted_raw_ostream &llvm::fouts() {
9071847813bc419f7a0667468136a07429c6d9f164David Greene  static formatted_raw_ostream S(outs());
9171847813bc419f7a0667468136a07429c6d9f164David Greene  return S;
9271847813bc419f7a0667468136a07429c6d9f164David Greene}
9371847813bc419f7a0667468136a07429c6d9f164David Greene
9471847813bc419f7a0667468136a07429c6d9f164David Greene/// ferrs() - This returns a reference to a formatted_raw_ostream for
9571847813bc419f7a0667468136a07429c6d9f164David Greene/// standard error.  Use it like: ferrs() << "foo" << "bar";
9671847813bc419f7a0667468136a07429c6d9f164David Greeneformatted_raw_ostream &llvm::ferrs() {
9771847813bc419f7a0667468136a07429c6d9f164David Greene  static formatted_raw_ostream S(errs());
9871847813bc419f7a0667468136a07429c6d9f164David Greene  return S;
9971847813bc419f7a0667468136a07429c6d9f164David Greene}
1008f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene
1018f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene/// fdbgs() - This returns a reference to a formatted_raw_ostream for
1028f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene/// the debug stream.  Use it like: fdbgs() << "foo" << "bar";
1038f1929b9eae512aedc0f3fedae3c0f24583171e1David Greeneformatted_raw_ostream &llvm::fdbgs() {
1048f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene  static formatted_raw_ostream S(dbgs());
1058f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene  return S;
1068f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene}
107