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
|