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

Generated on Fri Feb 28 2020 16:26:58 for gem5 by doxygen 1.8.13