fastmodel: Use a shared pointer to track PC events.
[gem5.git] / src / base / cprintf.cc
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
29 #include "base/cprintf.hh"
30
31 #include <cassert>
32 #include <iomanip>
33 #include <iostream>
34 #include <sstream>
35
36 #include "base/compiler.hh"
37
38 using namespace std;
39
40 namespace cp {
41
42 Print::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 saved_width = stream.width();
49 }
50
51 Print::Print(std::ostream &stream, const char *format)
52 : stream(stream), format(format), ptr(format), cont(false)
53 {
54 saved_flags = stream.flags();
55 saved_fill = stream.fill();
56 saved_precision = stream.precision();
57 saved_width = stream.width();
58 }
59
60 Print::~Print()
61 {
62 }
63
64 void
65 Print::process()
66 {
67 fmt.clear();
68
69 size_t len;
70
71 while (*ptr) {
72 switch (*ptr) {
73 case '%':
74 if (ptr[1] != '%') {
75 process_flag();
76 return;
77 }
78 stream.put('%');
79 ptr += 2;
80 break;
81
82 case '\n':
83 stream << endl;
84 ++ptr;
85 break;
86 case '\r':
87 ++ptr;
88 if (*ptr != '\n')
89 stream << endl;
90 break;
91
92 default:
93 len = strcspn(ptr, "%\n\r\0");
94 stream.write(ptr, len);
95 ptr += len;
96 break;
97 }
98 }
99 }
100
101 void
102 Print::process_flag()
103 {
104 bool done = false;
105 bool end_number = false;
106 bool have_precision = false;
107 int number = 0;
108
109 stream.fill(' ');
110 stream.flags((ios::fmtflags)0);
111
112 while (!done) {
113 ++ptr;
114 if (*ptr >= '0' && *ptr <= '9') {
115 if (end_number)
116 continue;
117 } else if (number > 0)
118 end_number = true;
119
120 switch (*ptr) {
121 case 's':
122 fmt.format = Format::string;
123 done = true;
124 break;
125
126 case 'c':
127 fmt.format = Format::character;
128 done = true;
129 break;
130
131 case 'l':
132 continue;
133
134 case 'p':
135 fmt.format = Format::integer;
136 fmt.base = Format::hex;
137 fmt.alternate_form = true;
138 done = true;
139 break;
140
141 case 'X':
142 fmt.uppercase = true;
143 M5_FALLTHROUGH;
144 case 'x':
145 fmt.base = Format::hex;
146 fmt.format = Format::integer;
147 done = true;
148 break;
149
150 case 'o':
151 fmt.base = Format::oct;
152 fmt.format = Format::integer;
153 done = true;
154 break;
155
156 case 'd':
157 case 'i':
158 case 'u':
159 fmt.format = Format::integer;
160 done = true;
161 break;
162
163 case 'G':
164 fmt.uppercase = true;
165 M5_FALLTHROUGH;
166 case 'g':
167 fmt.format = Format::floating;
168 fmt.float_format = Format::best;
169 done = true;
170 break;
171
172 case 'E':
173 fmt.uppercase = true;
174 M5_FALLTHROUGH;
175 case 'e':
176 fmt.format = Format::floating;
177 fmt.float_format = Format::scientific;
178 done = true;
179 break;
180
181 case 'f':
182 fmt.format = Format::floating;
183 fmt.float_format = Format::fixed;
184 done = true;
185 break;
186
187 case 'n':
188 stream << "we don't do %n!!!\n";
189 done = true;
190 break;
191
192 case '#':
193 fmt.alternate_form = true;
194 break;
195
196 case '-':
197 fmt.flush_left = true;
198 break;
199
200 case '+':
201 fmt.print_sign = true;
202 break;
203
204 case ' ':
205 fmt.blank_space = true;
206 break;
207
208 case '.':
209 fmt.width = number;
210 fmt.precision = 0;
211 have_precision = true;
212 number = 0;
213 end_number = false;
214 break;
215
216 case '0':
217 if (number == 0) {
218 fmt.fill_zero = true;
219 break;
220 }
221 M5_FALLTHROUGH;
222 case '1':
223 case '2':
224 case '3':
225 case '4':
226 case '5':
227 case '6':
228 case '7':
229 case '8':
230 case '9':
231 number = number * 10 + (*ptr - '0');
232 break;
233
234 case '*':
235 if (have_precision)
236 fmt.get_precision = true;
237 else
238 fmt.get_width = true;
239 break;
240
241 case '%':
242 assert(false && "we shouldn't get here");
243 break;
244
245 default:
246 done = true;
247 break;
248 }
249
250 if (end_number) {
251 if (have_precision)
252 fmt.precision = number;
253 else
254 fmt.width = number;
255
256 end_number = false;
257 number = 0;
258 }
259
260 if (done) {
261 if ((fmt.format == Format::integer) && have_precision) {
262 // specified a . but not a float, set width
263 fmt.width = fmt.precision;
264 // precision requries digits for width, must fill with 0
265 fmt.fill_zero = true;
266 } else if ((fmt.format == Format::floating) && !have_precision &&
267 fmt.fill_zero) {
268 // ambiguous case, matching printf
269 fmt.precision = fmt.width;
270 }
271 }
272 } // end while
273
274 ++ptr;
275 }
276
277 void
278 Print::end_args()
279 {
280 size_t len;
281
282 while (*ptr) {
283 switch (*ptr) {
284 case '%':
285 if (ptr[1] != '%')
286 stream << "<extra arg>";
287
288 stream.put('%');
289 ptr += 2;
290 break;
291
292 case '\n':
293 stream << endl;
294 ++ptr;
295 break;
296 case '\r':
297 ++ptr;
298 if (*ptr != '\n')
299 stream << endl;
300 break;
301
302 default:
303 len = strcspn(ptr, "%\n\r\0");
304 stream.write(ptr, len);
305 ptr += len;
306 break;
307 }
308 }
309
310 stream.flags(saved_flags);
311 stream.fill(saved_fill);
312 stream.precision(saved_precision);
313 stream.width(saved_width);
314 }
315
316 } // namespace cp