blob: 432e6031948d4ee0c1da5d6e3aa3c406a52ffb1f [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 Lattner42f77ab2008-08-23 20:34:06 +000015#include "llvm/Support/Format.h"
Chris Lattner097af7f2008-08-23 19:23:10 +000016#include "llvm/ADT/SmallVector.h"
Chris Lattner969a46a2008-08-22 15:45:00 +000017#include "llvm/Config/config.h"
Chris Lattner07f51f72008-08-17 04:13:37 +000018#include <ostream>
Chris Lattner60d39622008-08-17 01:35:29 +000019
Chris Lattner969a46a2008-08-22 15:45:00 +000020#if defined(HAVE_UNISTD_H)
21# include <unistd.h>
22#endif
23#if defined(HAVE_FCNTL_H)
24# include <fcntl.h>
25#endif
Argyrios Kyrtzidisb68dc362008-08-17 09:25:21 +000026
27#if defined(_MSC_VER)
Chris Lattner60d39622008-08-17 01:35:29 +000028#include <io.h>
Owen Andersoncb371882008-08-21 00:14:44 +000029#ifndef STDIN_FILENO
30# define STDIN_FILENO 0
31#endif
32#ifndef STDOUT_FILENO
33# define STDOUT_FILENO 1
34#endif
35#ifndef STDERR_FILENO
36# define STDERR_FILENO 2
37#endif
Chris Lattner60d39622008-08-17 01:35:29 +000038#endif
39
Chris Lattner969a46a2008-08-22 15:45:00 +000040using namespace llvm;
41
42
Chris Lattner60d39622008-08-17 01:35:29 +000043// An out of line virtual method to provide a home for the class vtable.
44void raw_ostream::handle() {}
45
Owen Anderson66b17ba2008-08-21 20:58:52 +000046raw_ostream &raw_ostream::operator<<(unsigned long N) {
47 // Zero is a special case.
48 if (N == 0)
49 return *this << '0';
50
51 char NumberBuffer[20];
52 char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
53 char *CurPtr = EndPtr;
54
55 while (N) {
56 *--CurPtr = '0' + char(N % 10);
57 N /= 10;
58 }
59 return write(CurPtr, EndPtr-CurPtr);
60}
61
62raw_ostream &raw_ostream::operator<<(long N) {
63 if (N < 0) {
64 if (OutBufCur >= OutBufEnd)
65 flush_impl();
66 *OutBufCur++ = '-';
67
68 N = -N;
69 }
70
71 return this->operator<<(static_cast<unsigned long>(N));
72}
73
74raw_ostream &raw_ostream::operator<<(unsigned long long N) {
75 // Zero is a special case.
76 if (N == 0)
77 return *this << '0';
78
79 char NumberBuffer[20];
80 char *EndPtr = NumberBuffer+sizeof(NumberBuffer);
81 char *CurPtr = EndPtr;
82
83 while (N) {
84 *--CurPtr = '0' + char(N % 10);
85 N /= 10;
86 }
87 return write(CurPtr, EndPtr-CurPtr);
88}
89
90raw_ostream &raw_ostream::operator<<(long long N) {
91 if (N < 0) {
92 if (OutBufCur >= OutBufEnd)
93 flush_impl();
94 *OutBufCur++ = '-';
95
96 N = -N;
97 }
98
99 return this->operator<<(static_cast<unsigned long long>(N));
100}
101
102raw_ostream &raw_ostream::write(const char *Ptr, unsigned Size) {
103 if (OutBufCur+Size > OutBufEnd)
104 flush_impl();
105
106 // Handle short strings specially, memcpy isn't very good at very short
107 // strings.
108 switch (Size) {
109 case 4: OutBufCur[3] = Ptr[3]; // FALL THROUGH
110 case 3: OutBufCur[2] = Ptr[2]; // FALL THROUGH
111 case 2: OutBufCur[1] = Ptr[1]; // FALL THROUGH
112 case 1: OutBufCur[0] = Ptr[0]; // FALL THROUGH
113 case 0: break;
114 default:
115 // Normally the string to emit is shorter than the buffer.
116 if (Size <= unsigned(OutBufEnd-OutBufStart)) {
117 memcpy(OutBufCur, Ptr, Size);
118 break;
119 }
120
121 // If emitting a string larger than our buffer, emit in chunks. In this
122 // case we know that we just flushed the buffer.
123 while (Size) {
124 unsigned NumToEmit = OutBufEnd-OutBufStart;
125 if (Size < NumToEmit) NumToEmit = Size;
126 assert(OutBufCur == OutBufStart);
127 memcpy(OutBufStart, Ptr, NumToEmit);
128 Ptr += NumToEmit;
Owen Andersonfd2a0532008-08-21 22:39:33 +0000129 Size -= NumToEmit;
Owen Anderson66b17ba2008-08-21 20:58:52 +0000130 OutBufCur = OutBufStart + NumToEmit;
131 flush_impl();
132 }
133 break;
134 }
135 OutBufCur += Size;
136 return *this;
137}
138
Chris Lattner097af7f2008-08-23 19:23:10 +0000139// Formatted output.
140raw_ostream &raw_ostream::operator<<(const format_object_base &Fmt) {
141 // If we have more than a few bytes left in our output buffer, try formatting
142 // directly onto its end.
143 unsigned NextBufferSize = 127;
144 if (OutBufEnd-OutBufCur > 3) {
145 unsigned BufferBytesLeft = OutBufEnd-OutBufCur;
146 unsigned BytesUsed = Fmt.print(OutBufCur, BufferBytesLeft);
147
148 // Common case is that we have plenty of space.
149 if (BytesUsed < BufferBytesLeft) {
150 OutBufCur += BytesUsed;
151 return *this;
152 }
153
154 // Otherwise, we overflowed and the return value tells us the size to try
155 // again with.
156 NextBufferSize = BytesUsed;
157 }
158
159 // If we got here, we didn't have enough space in the output buffer for the
160 // string. Try printing into a SmallVector that is resized to have enough
161 // space. Iterate until we win.
162 SmallVector<char, 128> V;
163
164 while (1) {
165 V.resize(NextBufferSize);
166
167 // Try formatting into the SmallVector.
168 unsigned BytesUsed = Fmt.print(&V[0], NextBufferSize);
169
170 // If BytesUsed fit into the vector, we win.
171 if (BytesUsed < NextBufferSize)
172 return write(&V[0], BytesUsed);
173
174 // Otherwise, try again with a new size.
175 assert(BytesUsed > NextBufferSize && "Didn't grow buffer!?");
176 NextBufferSize = BytesUsed;
177 }
178}
179
180//===----------------------------------------------------------------------===//
181// Formatted Output
182//===----------------------------------------------------------------------===//
183
184// Out of line virtual method.
185void format_object_base::home() {
186}
187
Chris Lattner60d39622008-08-17 01:35:29 +0000188//===----------------------------------------------------------------------===//
189// raw_fd_ostream
190//===----------------------------------------------------------------------===//
191
192/// raw_fd_ostream - Open the specified file for writing. If an error occurs,
193/// information about the error is put into ErrorInfo, and the stream should
194/// be immediately destroyed.
195raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo) {
Chris Lattnerc52b1282008-08-17 03:53:23 +0000196 // Handle "-" as stdout.
197 if (Filename[0] == '-' && Filename[1] == 0) {
198 FD = STDOUT_FILENO;
199 ShouldClose = false;
200 return;
201 }
202
Chris Lattner60d39622008-08-17 01:35:29 +0000203 FD = open(Filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
204 if (FD < 0) {
205 ErrorInfo = "Error opening output file '" + std::string(Filename) + "'";
206 ShouldClose = false;
207 } else {
208 ShouldClose = true;
209 }
210}
211
212raw_fd_ostream::~raw_fd_ostream() {
213 flush();
214 if (ShouldClose)
215 close(FD);
216}
217
218void raw_fd_ostream::flush_impl() {
219 if (OutBufCur-OutBufStart)
Chris Lattnerd497df52008-08-17 01:46:05 +0000220 ::write(FD, OutBufStart, OutBufCur-OutBufStart);
Chris Lattner60d39622008-08-17 01:35:29 +0000221 HandleFlush();
222}
223
Chris Lattner07f51f72008-08-17 04:13:37 +0000224//===----------------------------------------------------------------------===//
225// raw_stdout/err_ostream
226//===----------------------------------------------------------------------===//
Chris Lattner60d39622008-08-17 01:35:29 +0000227
228raw_stdout_ostream::raw_stdout_ostream():raw_fd_ostream(STDOUT_FILENO, false) {}
229raw_stderr_ostream::raw_stderr_ostream():raw_fd_ostream(STDERR_FILENO, false) {}
230
231// An out of line virtual method to provide a home for the class vtable.
232void raw_stdout_ostream::handle() {}
233void raw_stderr_ostream::handle() {}
Chris Lattner07f51f72008-08-17 04:13:37 +0000234
235/// outs() - This returns a reference to a raw_ostream for standard output.
236/// Use it like: outs() << "foo" << "bar";
Owen Andersoncb371882008-08-21 00:14:44 +0000237raw_ostream &llvm::outs() {
Chris Lattner07f51f72008-08-17 04:13:37 +0000238 static raw_stdout_ostream S;
239 return S;
240}
241
242/// errs() - This returns a reference to a raw_ostream for standard error.
243/// Use it like: errs() << "foo" << "bar";
Owen Andersoncb371882008-08-21 00:14:44 +0000244raw_ostream &llvm::errs() {
Chris Lattner07f51f72008-08-17 04:13:37 +0000245 static raw_stderr_ostream S;
246 return S;
247}
248
249//===----------------------------------------------------------------------===//
250// raw_os_ostream
251//===----------------------------------------------------------------------===//
252
253/// flush_impl - The is the piece of the class that is implemented by
254/// subclasses. This outputs the currently buffered data and resets the
255/// buffer to empty.
256void raw_os_ostream::flush_impl() {
257 if (OutBufCur-OutBufStart)
258 OS.write(OutBufStart, OutBufCur-OutBufStart);
259 HandleFlush();
260}