remote_gdb.cc:
[gem5.git] / base / cprintf.cc
1 /*
2 * Copyright (c) 2003 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 <cassert>
30 #include <iomanip>
31 #include <iostream>
32 #include <sstream>
33
34 #include "base/cprintf.hh"
35
36 using namespace std;
37
38 namespace cp {
39
40 void
41 ArgList::dump(const string &format)
42 {
43 const char *p = format.c_str();
44
45 stream->fill(' ');
46 stream->flags((ios::fmtflags)0);
47
48 Format fmt;
49
50 while (*p) {
51 switch (*p) {
52 case '%': {
53 if (p[1] == '%') {
54 *stream << '%';
55 p += 2;
56 continue;
57 }
58
59 if (objects.empty())
60 format_invalid(*stream);
61
62 Base *data = objects.front();
63
64 fmt.clear();
65 bool done = false;
66 bool end_number = false;
67 bool have_precision = false;
68 int number = 0;
69
70 while (!done) {
71 ++p;
72 if (*p >= '0' && *p <= '9') {
73 if (end_number)
74 continue;
75 } else if (number > 0)
76 end_number = true;
77
78 switch (*p) {
79 case 's':
80 fmt.format = Format::string;
81 done = true;
82 break;
83
84 case 'c':
85 fmt.format = Format::character;
86 done = true;
87 break;
88
89 case 'l':
90 continue;
91
92 case 'p':
93 fmt.format = Format::integer;
94 fmt.base = Format::hex;
95 fmt.alternate_form = true;
96 done = true;
97 break;
98
99 case 'X':
100 fmt.uppercase = true;
101 case 'x':
102 fmt.base = Format::hex;
103 fmt.format = Format::integer;
104 done = true;
105 break;
106
107 case 'o':
108 fmt.base = Format::oct;
109 fmt.format = Format::integer;
110 done = true;
111 break;
112
113 case 'd':
114 case 'i':
115 case 'u':
116 fmt.format = Format::integer;
117 done = true;
118 break;
119
120 case 'G':
121 fmt.uppercase = true;
122 case 'g':
123 fmt.format = Format::floating;
124 fmt.float_format = Format::best;
125 done = true;
126 break;
127
128 case 'E':
129 fmt.uppercase = true;
130 case 'e':
131 fmt.format = Format::floating;
132 fmt.float_format = Format::scientific;
133 done = true;
134 break;
135
136 case 'f':
137 fmt.format = Format::floating;
138 fmt.float_format = Format::fixed;
139 done = true;
140 break;
141
142 case 'n':
143 *stream << "we don't do %n!!!\n";
144 done = true;
145 break;
146
147 case '#':
148 fmt.alternate_form = true;
149 break;
150
151 case '-':
152 fmt.flush_left = true;
153 break;
154
155 case '+':
156 fmt.print_sign = true;
157 break;
158
159 case ' ':
160 fmt.blank_space = true;
161 break;
162
163 case '.':
164 fmt.width = number;
165 fmt.precision = 0;
166 have_precision = true;
167 number = 0;
168 end_number = false;
169 break;
170
171 case '0':
172 if (number == 0) {
173 fmt.fill_zero = true;
174 break;
175 }
176 case '1':
177 case '2':
178 case '3':
179 case '4':
180 case '5':
181 case '6':
182 case '7':
183 case '8':
184 case '9':
185 number = number * 10 + (*p - '0');
186 break;
187
188 case '%':
189 assert("we shouldn't get here");
190 break;
191
192 default:
193 done = true;
194 break;
195 }
196
197 if (end_number) {
198 if (have_precision)
199 fmt.precision = number;
200 else
201 fmt.width = number;
202
203 end_number = false;
204 number = 0;
205 }
206 }
207
208 ios::fmtflags saved_flags = stream->flags();
209 char old_fill = stream->fill();
210 int old_precision = stream->precision();
211
212 data->process(*stream, fmt);
213
214 stream->flags(saved_flags);
215 stream->fill(old_fill);
216 stream->precision(old_precision);
217
218 delete data;
219 objects.pop_front();
220 ++p;
221 }
222 break;
223
224 case '\n':
225 *stream << endl;
226 ++p;
227 break;
228 case '\r':
229 ++p;
230 if (*p != '\n')
231 *stream << endl;
232 break;
233
234 default: {
235 size_t len = strcspn(p, "%\n\r\0");
236 stream->write(p, len);
237 p += len;
238 }
239 break;
240 }
241
242 ios::iostate state = stream->rdstate();
243 if (state) {
244 #if 0
245 cout << "stream->rdstate() == " << state << endl;
246 if (state & ios::badbit)
247 cout << "stream is bad!\n";
248 if (state & ios::eofbit)
249 cout << "stream at eof!\n";
250 if (state & ios::failbit)
251 cout << "stream failed!\n";
252 if (state & ios::goodbit)
253 cout << "stream is good!!\n";
254 #endif
255 stream->clear();
256 }
257 }
258
259 while (!objects.empty()) {
260 Base *data = objects.front();
261 data->process(*stream, fmt);
262 delete data;
263 objects.pop_front();
264 }
265 }
266
267 string
268 ArgList::dumpToString(const string &format)
269 {
270 stringstream ss;
271
272 dump(ss, format);
273
274 return ss.str();
275 }
276
277 }