cprintf.cc (11793:ef606668d247) cprintf.cc (12392:e0dbdf30a2a5)
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
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
38#include "base/compiler.hh"
39
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;
40using namespace std;
41
42namespace cp {
43
44Print::Print(std::ostream &stream, const std::string &format)
45 : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false)
46{
47 saved_flags = stream.flags();
48 saved_fill = stream.fill();
49 saved_precision = stream.precision();
50}
51
52Print::Print(std::ostream &stream, const char *format)
53 : stream(stream), format(format), ptr(format), cont(false)
54{
55 saved_flags = stream.flags();
56 saved_fill = stream.fill();
57 saved_precision = stream.precision();
58}
59
60Print::~Print()
61{
62}
63
64void
65Print::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
101void
102Print::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;
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;
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;
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;
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;
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 }
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;
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
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
277void
278Print::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}
314
315} // namespace cp