blob: d776fa583f1ab803279044ae6b28d4015b35b547 [file] [log] [blame]
Chris Lattner60d39622008-08-17 01:35:29 +00001//===--- 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"
Chris Lattner969a46a2008-08-22 15:45:00 +000015#include "llvm/Config/config.h"
Chris Lattner07f51f72008-08-17 04:13:37 +000016#include <ostream>
Chris Lattner60d39622008-08-17 01:35:29 +000017
Chris Lattner969a46a2008-08-22 15:45:00 +000018#if defined(HAVE_UNISTD_H)
19# include <unistd.h>
20#endif
21#if defined(HAVE_FCNTL_H)
22# include <fcntl.h>
23#endif
Argyrios Kyrtzidisb68dc362008-08-17 09:25:21 +000024
25#if defined(_MSC_VER)
Chris Lattner60d39622008-08-17 01:35:29 +000026#include <io.h>
Owen Andersoncb371882008-08-21 00:14:44 +000027#ifndef STDIN_FILENO
28# define STDIN_FILENO 0
29#endif
30#ifndef STDOUT_FILENO
31# define STDOUT_FILENO 1
32#endif
33#ifndef STDERR_FILENO
34# define STDERR_FILENO 2
35#endif
Chris Lattner60d39622008-08-17 01:35:29 +000036#endif
37
Chris Lattner969a46a2008-08-22 15:45:00 +000038using namespace llvm;
39
40
Chris Lattner60d39622008-08-17 01:35:29 +000041// An out of line virtual method to provide a home for the class vtable.
42void raw_ostream::handle() {}
43
Owen Anderson66b17ba2008-08-21 20:58:52 +000044raw_ostream &raw_ostream::operator<<(unsigned long N) {
45 // Zero is a special case.
46 if (N == 0)
47 return *this << '0';
48
49 char NumberBuffer[20];
50 char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
51 char *CurPtr = EndPtr;
52
53 while (N) {
54 *--CurPtr = '0' + char(N % 10);
55 N /= 10;
56 }
57 return write(CurPtr, EndPtr-CurPtr);
58}
59
60raw_ostream &raw_ostream::operator<<(long N) {
61 if (N < 0) {
62 if (OutBufCur >= OutBufEnd)
63 flush_impl();
64 *OutBufCur++ = '-';
65
66 N = -N;
67 }
68
69 return this->operator<<(static_cast<unsigned long>(N));
70}
71
72raw_ostream &raw_ostream::operator<<(unsigned long long N) {
73 // Zero is a special case.
74 if (N == 0)
75 return *this << '0';
76
77 char NumberBuffer[20];
78 char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
79 char *CurPtr = EndPtr;
80
81 while (N) {
82 *--CurPtr = '0' + char(N % 10);
83 N /= 10;
84 }
85 return write(CurPtr, EndPtr-CurPtr);
86}
87
88raw_ostream &raw_ostream::operator<<(long long N) {
89 if (N < 0) {
90 if (OutBufCur >= OutBufEnd)
91 flush_impl();
92 *OutBufCur++ = '-';
93
94 N = -N;
95 }
96
97 return this->operator<<(static_cast<unsigned long long>(N));
98}
99
100raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
101 if (OutBufCur+Size > OutBufEnd)
102 flush_impl();
103
104 // Handle short strings specially, memcpy isn't very good at very short
105 // strings.
106 switch (Size) {
107 case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
108 case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
109 case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
110 case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
111 case 0: break;
112 default:
113 // Normally the string to emit is shorter than the buffer.
114 if (Size <= unsigned(OutBufEnd-OutBufStart)) {
115 memcpy(OutBufCur, Ptr, Size);
116 break;
117 }
118
119 // If emitting a string larger than our buffer, emit in chunks. In this
120 // case we know that we just flushed the buffer.
121 while (Size) {
122 unsigned NumToEmit = OutBufEnd-OutBufStart;
123 if (Size < NumToEmit) NumToEmit = Size;
124 assert(OutBufCur == OutBufStart);
125 memcpy(OutBufStart, Ptr, NumToEmit);
126 Ptr += NumToEmit;
Owen Andersonfd2a0532008-08-21 22:39:33 +0000127 Size -= NumToEmit;
Owen Anderson66b17ba2008-08-21 20:58:52 +0000128 OutBufCur = OutBufStart + NumToEmit;
129 flush_impl();
130 }
131 break;
132 }
133 OutBufCur += Size;
134 return *this;
135}
136
Chris Lattner60d39622008-08-17 01:35:29 +0000137//===----------------------------------------------------------------------===//
138// raw_fd_ostream
139//===----------------------------------------------------------------------===//
140
141/// raw_fd_ostream - Open the specified file for writing. If an error occurs,
142/// information about the error is put into ErrorInfo, and the stream should
143/// be immediately destroyed.
144raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo) {
Chris Lattnerc52b1282008-08-17 03:53:23 +0000145 // Handle "-" as stdout.
146 if (Filename[0] == '-' && Filename[1] == 0) {
147 FD = STDOUT_FILENO;
148 ShouldClose = false;
149 return;
150 }
151
Chris Lattner60d39622008-08-17 01:35:29 +0000152 FD = open(Filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
153 if (FD < 0) {
154 ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
155 ShouldClose = false;
156 } else {
157 ShouldClose = true;
158 }
159}
160
161raw_fd_ostream::~raw_fd_ostream() {
162 flush();
163 if (ShouldClose)
164 close(FD);
165}
166
167void raw_fd_ostream::flush_impl() {
168 if (OutBufCur-OutBufStart)
Chris Lattnerd497df52008-08-17 01:46:05 +0000169 ::write(FD, OutBufStart, OutBufCur-OutBufStart);
Chris Lattner60d39622008-08-17 01:35:29 +0000170 HandleFlush();
171}
172
Chris Lattner07f51f72008-08-17 04:13:37 +0000173//===----------------------------------------------------------------------===//
174// raw_stdout/err_ostream
175//===----------------------------------------------------------------------===//
Chris Lattner60d39622008-08-17 01:35:29 +0000176
177raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
178raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
179
180// An out of line virtual method to provide a home for the class vtable.
181void raw_stdout_ostream::handle() {}
182void raw_stderr_ostream::handle() {}
Chris Lattner07f51f72008-08-17 04:13:37 +0000183
184/// outs() - This returns a reference to a raw_ostream for standard output.
185/// Use it like: outs() << "foo" << "bar";
Owen Andersoncb371882008-08-21 00:14:44 +0000186raw_ostream &llvm::outs() {
Chris Lattner07f51f72008-08-17 04:13:37 +0000187 static raw_stdout_ostream S;
188 return S;
189}
190
191/// errs() - This returns a reference to a raw_ostream for standard error.
192/// Use it like: errs() << "foo" << "bar";
Owen Andersoncb371882008-08-21 00:14:44 +0000193raw_ostream &llvm::errs() {
Chris Lattner07f51f72008-08-17 04:13:37 +0000194 static raw_stderr_ostream S;
195 return S;
196}
197
198//===----------------------------------------------------------------------===//
199// raw_os_ostream
200//===----------------------------------------------------------------------===//
201
202/// flush_impl - The is the piece of the class that is implemented by
203/// subclasses. This outputs the currently buffered data and resets the
204/// buffer to empty.
205void raw_os_ostream::flush_impl() {
206 if (OutBufCur-OutBufStart)
207 OS.write(OutBufStart, OutBufCur-OutBufStart);
208 HandleFlush();
209}