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
20fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman/// CountColumns - Examine the given char sequence and figure out which
21191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene/// column we end up in after output.
22191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene///
23fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohmanstatic unsigned CountColumns(unsigned Column, const char *Ptr, size_t Size) {
24191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene  // Keep track of the current column by scanning the string for
25191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene  // special characters
26191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
27fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  for (const char *End = Ptr + Size; Ptr != End; ++Ptr) {
28fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman    ++Column;
29fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman    if (*Ptr == '\n' || *Ptr == '\r')
30fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman      Column = 0;
31fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman    else if (*Ptr == '\t')
32eb85728970c6152842577658ac2c5d2ff3a98b13David Greene      // Assumes tab stop = 8 characters.
33fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman      Column += (8 - (Column & 0x7)) & 0x7;
3462fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene  }
35fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
36fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  return Column;
37fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman}
38fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
39fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman/// ComputeColumn - Examine the current output and figure out which
40fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman/// column we end up in after output.
41ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbarvoid formatted_raw_ostream::ComputeColumn(const char *Ptr, size_t Size) {
42ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // If our previous scan pointer is inside the buffer, assume we already
43ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // scanned those bytes. This depends on raw_ostream to not change our buffer
44ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // in unexpected ways.
45ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  if (Ptr <= Scanned && Scanned <= Ptr + Size) {
46ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar    // Scan all characters added since our last scan to determine the new
47ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar    // column.
48ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar    ColumnScanned = CountColumns(ColumnScanned, Scanned,
49ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar                                 Size - (Scanned - Ptr));
50ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  } else
51ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar    ColumnScanned = CountColumns(ColumnScanned, Ptr, Size);
52ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar
53ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // Update the scanning pointer.
54ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  Scanned = Ptr + Size;
55191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene}
5662fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene
57191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene/// PadToColumn - Align the output to some column number.
58191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene///
59191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene/// \param NewCol - The column to move to.
60191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene///
61efbdaa6463c8febe9cbfdd6d39f3a9ba18773427Chris Lattnerformatted_raw_ostream &formatted_raw_ostream::PadToColumn(unsigned NewCol) {
62eb85728970c6152842577658ac2c5d2ff3a98b13David Greene  // Figure out what's in the buffer and add it to the column count.
63ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  ComputeColumn(getBufferStart(), GetNumBytesInBuffer());
64191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
65191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene  // Output spaces until we reach the desired column.
66de51ded2fa3d8d92e821e72294a89c1310a70cc6Chris Lattner  indent(std::max(int(NewCol - ColumnScanned), 1));
67efbdaa6463c8febe9cbfdd6d39f3a9ba18773427Chris Lattner  return *this;
6862fe47a33755719ab9c6e8c239e0dd01fc87e6f9David Greene}
69191cf2851b40fea6b7d927d5de8f22c35dd33828David Greene
70a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohmanvoid formatted_raw_ostream::write_impl(const char *Ptr, size_t Size) {
71fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  // Figure out what's in the buffer and add it to the column count.
72ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  ComputeColumn(Ptr, Size);
73fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
74fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  // Write the data to the underlying stream (which is unbuffered, so
75fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman  // the data will be immediately written out).
76a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohman  TheStream->write(Ptr, Size);
77fbcb5b678f0fc0432072212a26a0507954c805d8Dan Gohman
78ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  // Reset the scanning pointer.
79ab810275448c34c072c47be1f16ae1d679bfd20cDaniel Dunbar  Scanned = 0;
80a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohman}
81a4a68c1b439af1bacf8b9c3c06cdb97f56be4d94Dan Gohman
8271847813bc419f7a0667468136a07429c6d9f164David Greene/// fouts() - This returns a reference to a formatted_raw_ostream for
8371847813bc419f7a0667468136a07429c6d9f164David Greene/// standard output.  Use it like: fouts() << "foo" << "bar";
8471847813bc419f7a0667468136a07429c6d9f164David Greeneformatted_raw_ostream &llvm::fouts() {
8571847813bc419f7a0667468136a07429c6d9f164David Greene  static formatted_raw_ostream S(outs());
8671847813bc419f7a0667468136a07429c6d9f164David Greene  return S;
8771847813bc419f7a0667468136a07429c6d9f164David Greene}
8871847813bc419f7a0667468136a07429c6d9f164David Greene
8971847813bc419f7a0667468136a07429c6d9f164David Greene/// ferrs() - This returns a reference to a formatted_raw_ostream for
9071847813bc419f7a0667468136a07429c6d9f164David Greene/// standard error.  Use it like: ferrs() << "foo" << "bar";
9171847813bc419f7a0667468136a07429c6d9f164David Greeneformatted_raw_ostream &llvm::ferrs() {
9271847813bc419f7a0667468136a07429c6d9f164David Greene  static formatted_raw_ostream S(errs());
9371847813bc419f7a0667468136a07429c6d9f164David Greene  return S;
9471847813bc419f7a0667468136a07429c6d9f164David Greene}
958f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene
968f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene/// fdbgs() - This returns a reference to a formatted_raw_ostream for
978f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene/// the debug stream.  Use it like: fdbgs() << "foo" << "bar";
988f1929b9eae512aedc0f3fedae3c0f24583171e1David Greeneformatted_raw_ostream &llvm::fdbgs() {
998f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene  static formatted_raw_ostream S(dbgs());
1008f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene  return S;
1018f1929b9eae512aedc0f3fedae3c0f24583171e1David Greene}
102