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