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