Deleted Added
sdiff udiff text old ( 11793:ef606668d247 ) new ( 12392:e0dbdf30a2a5 )
full compact
1/*
2 * Copyright (c) 2002-2006 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#include "base/cprintf.hh"
32
33#include <cassert>
34#include <iomanip>
35#include <iostream>
36#include <sstream>
37
38using namespace std;
39
40namespace cp {
41
42Print::Print(std::ostream &stream, const std::string &format)
43 : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false)
44{
45 saved_flags = stream.flags();
46 saved_fill = stream.fill();
47 saved_precision = stream.precision();
48}
49
50Print::Print(std::ostream &stream, const char *format)
51 : stream(stream), format(format), ptr(format), cont(false)
52{
53 saved_flags = stream.flags();
54 saved_fill = stream.fill();
55 saved_precision = stream.precision();
56}
57
58Print::~Print()
59{
60}
61
62void
63Print::process()
64{
65 fmt.clear();
66
67 size_t len;
68
69 while (*ptr) {
70 switch (*ptr) {
71 case '%':
72 if (ptr[1] != '%') {
73 process_flag();
74 return;
75 }
76 stream.put('%');
77 ptr += 2;
78 break;
79
80 case '\n':
81 stream << endl;
82 ++ptr;
83 break;
84 case '\r':
85 ++ptr;
86 if (*ptr != '\n')
87 stream << endl;
88 break;
89
90 default:
91 len = strcspn(ptr, "%\n\r\0");
92 stream.write(ptr, len);
93 ptr += len;
94 break;
95 }
96 }
97}
98
99void
100Print::process_flag()
101{
102 bool done = false;
103 bool end_number = false;
104 bool have_precision = false;
105 int number = 0;
106
107 stream.fill(' ');
108 stream.flags((ios::fmtflags)0);
109
110 while (!done) {
111 ++ptr;
112 if (*ptr >= '0' && *ptr <= '9') {
113 if (end_number)
114 continue;
115 } else if (number > 0)
116 end_number = true;
117
118 switch (*ptr) {
119 case 's':
120 fmt.format = Format::string;
121 done = true;
122 break;
123
124 case 'c':
125 fmt.format = Format::character;
126 done = true;
127 break;
128
129 case 'l':
130 continue;
131
132 case 'p':
133 fmt.format = Format::integer;
134 fmt.base = Format::hex;
135 fmt.alternate_form = true;
136 done = true;
137 break;
138
139 case 'X':
140 fmt.uppercase = true;
141 case 'x':
142 fmt.base = Format::hex;
143 fmt.format = Format::integer;
144 done = true;
145 break;
146
147 case 'o':
148 fmt.base = Format::oct;
149 fmt.format = Format::integer;
150 done = true;
151 break;
152
153 case 'd':
154 case 'i':
155 case 'u':
156 fmt.format = Format::integer;
157 done = true;
158 break;
159
160 case 'G':
161 fmt.uppercase = true;
162 case 'g':
163 fmt.format = Format::floating;
164 fmt.float_format = Format::best;
165 done = true;
166 break;
167
168 case 'E':
169 fmt.uppercase = true;
170 case 'e':
171 fmt.format = Format::floating;
172 fmt.float_format = Format::scientific;
173 done = true;
174 break;
175
176 case 'f':
177 fmt.format = Format::floating;
178 fmt.float_format = Format::fixed;
179 done = true;
180 break;
181
182 case 'n':
183 stream << "we don't do %n!!!\n";
184 done = true;
185 break;
186
187 case '#':
188 fmt.alternate_form = true;
189 break;
190
191 case '-':
192 fmt.flush_left = true;
193 break;
194
195 case '+':
196 fmt.print_sign = true;
197 break;
198
199 case ' ':
200 fmt.blank_space = true;
201 break;
202
203 case '.':
204 fmt.width = number;
205 fmt.precision = 0;
206 have_precision = true;
207 number = 0;
208 end_number = false;
209 break;
210
211 case '0':
212 if (number == 0) {
213 fmt.fill_zero = true;
214 break;
215 }
216 case '1':
217 case '2':
218 case '3':
219 case '4':
220 case '5':
221 case '6':
222 case '7':
223 case '8':
224 case '9':
225 number = number * 10 + (*ptr - '0');
226 break;
227
228 case '*':
229 if (have_precision)
230 fmt.get_precision = true;
231 else
232 fmt.get_width = true;
233 break;
234
235 case '%':
236 assert(false && "we shouldn't get here");
237 break;
238
239 default:
240 done = true;
241 break;
242 }
243
244 if (end_number) {
245 if (have_precision)
246 fmt.precision = number;
247 else
248 fmt.width = number;
249
250 end_number = false;
251 number = 0;
252 }
253
254 if (done) {
255 if ((fmt.format == Format::integer) && have_precision) {
256 // specified a . but not a float, set width
257 fmt.width = fmt.precision;
258 // precision requries digits for width, must fill with 0
259 fmt.fill_zero = true;
260 } else if ((fmt.format == Format::floating) && !have_precision &&
261 fmt.fill_zero) {
262 // ambiguous case, matching printf
263 fmt.precision = fmt.width;
264 }
265 }
266 } // end while
267
268 ++ptr;
269}
270
271void
272Print::end_args()
273{
274 size_t len;
275
276 while (*ptr) {
277 switch (*ptr) {
278 case '%':
279 if (ptr[1] != '%')
280 stream << "<extra arg>";
281
282 stream.put('%');
283 ptr += 2;
284 break;
285
286 case '\n':
287 stream << endl;
288 ++ptr;
289 break;
290 case '\r':
291 ++ptr;
292 if (*ptr != '\n')
293 stream << endl;
294 break;
295
296 default:
297 len = strcspn(ptr, "%\n\r\0");
298 stream.write(ptr, len);
299 ptr += len;
300 break;
301 }
302 }
303
304 stream.flags(saved_flags);
305 stream.fill(saved_fill);
306 stream.precision(saved_precision);
307}
308
309} // namespace cp