gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 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 }
49 
50 Print::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 
59 {
60 }
61 
62 void
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 
99 void
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':
121  done = true;
122  break;
123 
124  case 'c':
126  done = true;
127  break;
128 
129  case 'l':
130  continue;
131 
132  case 'p':
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;
144  done = true;
145  break;
146 
147  case 'o':
148  fmt.base = Format::oct;
150  done = true;
151  break;
152 
153  case 'd':
154  case 'i':
155  case 'u':
157  done = true;
158  break;
159 
160  case 'G':
161  fmt.uppercase = true;
162  case 'g':
165  done = true;
166  break;
167 
168  case 'E':
169  fmt.uppercase = true;
170  case 'e':
173  done = true;
174  break;
175 
176  case 'f':
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
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
264  }
265  }
266  } // end while
267 
268  ++ptr;
269 }
270 
271 void
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
const char * ptr
Definition: cprintf.hh:51
void process()
Definition: cprintf.cc:63
Print(std::ostream &stream, const std::string &format)
Definition: cprintf.cc:42
int saved_precision
Definition: cprintf.hh:56
enum cp::Format::@28 float_format
void process_flag()
Definition: cprintf.cc:100
enum cp::Format::@26 base
~Print()
Definition: cprintf.cc:58
void end_args()
Definition: cprintf.cc:272
Format fmt
Definition: cprintf.hh:58
std::ostream & stream
Definition: cprintf.hh:49
char saved_fill
Definition: cprintf.hh:55
Bitfield< 31, 29 > format
Definition: miscregs.hh:1819
Bitfield< 18, 16 > len
Definition: miscregs.hh:1626
enum cp::Format::@27 format
std::ios::fmtflags saved_flags
Definition: cprintf.hh:54

Generated on Fri Jun 9 2017 13:03:40 for gem5 by doxygen 1.8.6