cprintf.cc revision 12392
12SN/A/* 24039Sbinkertn@umich.edu * Copyright (c) 2002-2006 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 292SN/A */ 302SN/A 3111793Sbrandon.potter@amd.com#include "base/cprintf.hh" 3211793Sbrandon.potter@amd.com 332SN/A#include <cassert> 342SN/A#include <iomanip> 352SN/A#include <iostream> 362SN/A#include <sstream> 372SN/A 3812392Sjason@lowepower.com#include "base/compiler.hh" 3912392Sjason@lowepower.com 402SN/Ausing namespace std; 412SN/A 422SN/Anamespace cp { 432SN/A 444039Sbinkertn@umich.eduPrint::Print(std::ostream &stream, const std::string &format) 455756Snate@binkert.org : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false) 46492SN/A{ 474039Sbinkertn@umich.edu saved_flags = stream.flags(); 484039Sbinkertn@umich.edu saved_fill = stream.fill(); 494039Sbinkertn@umich.edu saved_precision = stream.precision(); 504039Sbinkertn@umich.edu} 514039Sbinkertn@umich.edu 524039Sbinkertn@umich.eduPrint::Print(std::ostream &stream, const char *format) 535756Snate@binkert.org : stream(stream), format(format), ptr(format), cont(false) 544039Sbinkertn@umich.edu{ 554039Sbinkertn@umich.edu saved_flags = stream.flags(); 564039Sbinkertn@umich.edu saved_fill = stream.fill(); 574039Sbinkertn@umich.edu saved_precision = stream.precision(); 584039Sbinkertn@umich.edu} 594039Sbinkertn@umich.edu 604039Sbinkertn@umich.eduPrint::~Print() 614039Sbinkertn@umich.edu{ 62492SN/A} 63492SN/A 642SN/Avoid 655756Snate@binkert.orgPrint::process() 662SN/A{ 675756Snate@binkert.org fmt.clear(); 685756Snate@binkert.org 694039Sbinkertn@umich.edu size_t len; 70492SN/A 714039Sbinkertn@umich.edu while (*ptr) { 724039Sbinkertn@umich.edu switch (*ptr) { 734039Sbinkertn@umich.edu case '%': 749331Schander.sudanthi@arm.com if (ptr[1] != '%') { 759331Schander.sudanthi@arm.com process_flag(); 769331Schander.sudanthi@arm.com return; 779331Schander.sudanthi@arm.com } 784039Sbinkertn@umich.edu stream.put('%'); 794039Sbinkertn@umich.edu ptr += 2; 802SN/A break; 812SN/A 822SN/A case '\n': 834039Sbinkertn@umich.edu stream << endl; 844039Sbinkertn@umich.edu ++ptr; 852SN/A break; 862SN/A case '\r': 874039Sbinkertn@umich.edu ++ptr; 884039Sbinkertn@umich.edu if (*ptr != '\n') 894039Sbinkertn@umich.edu stream << endl; 902SN/A break; 912SN/A 924039Sbinkertn@umich.edu default: 934039Sbinkertn@umich.edu len = strcspn(ptr, "%\n\r\0"); 944039Sbinkertn@umich.edu stream.write(ptr, len); 954039Sbinkertn@umich.edu ptr += len; 962SN/A break; 972SN/A } 982SN/A } 999331Schander.sudanthi@arm.com} 1002SN/A 1019331Schander.sudanthi@arm.comvoid 1029331Schander.sudanthi@arm.comPrint::process_flag() 1039331Schander.sudanthi@arm.com{ 1044039Sbinkertn@umich.edu bool done = false; 1054039Sbinkertn@umich.edu bool end_number = false; 1064039Sbinkertn@umich.edu bool have_precision = false; 1074039Sbinkertn@umich.edu int number = 0; 1084039Sbinkertn@umich.edu 1094039Sbinkertn@umich.edu stream.fill(' '); 1104039Sbinkertn@umich.edu stream.flags((ios::fmtflags)0); 1114039Sbinkertn@umich.edu 1124039Sbinkertn@umich.edu while (!done) { 1134039Sbinkertn@umich.edu ++ptr; 1144039Sbinkertn@umich.edu if (*ptr >= '0' && *ptr <= '9') { 1154039Sbinkertn@umich.edu if (end_number) 1164039Sbinkertn@umich.edu continue; 1174039Sbinkertn@umich.edu } else if (number > 0) 1184039Sbinkertn@umich.edu end_number = true; 1194039Sbinkertn@umich.edu 1204039Sbinkertn@umich.edu switch (*ptr) { 1214039Sbinkertn@umich.edu case 's': 1224039Sbinkertn@umich.edu fmt.format = Format::string; 1234039Sbinkertn@umich.edu done = true; 1244039Sbinkertn@umich.edu break; 1254039Sbinkertn@umich.edu 1264039Sbinkertn@umich.edu case 'c': 1274039Sbinkertn@umich.edu fmt.format = Format::character; 1284039Sbinkertn@umich.edu done = true; 1294039Sbinkertn@umich.edu break; 1304039Sbinkertn@umich.edu 1314039Sbinkertn@umich.edu case 'l': 1324039Sbinkertn@umich.edu continue; 1334039Sbinkertn@umich.edu 1344039Sbinkertn@umich.edu case 'p': 1354039Sbinkertn@umich.edu fmt.format = Format::integer; 1364039Sbinkertn@umich.edu fmt.base = Format::hex; 1374039Sbinkertn@umich.edu fmt.alternate_form = true; 1384039Sbinkertn@umich.edu done = true; 1394039Sbinkertn@umich.edu break; 1404039Sbinkertn@umich.edu 1414039Sbinkertn@umich.edu case 'X': 1424039Sbinkertn@umich.edu fmt.uppercase = true; 14312392Sjason@lowepower.com M5_FALLTHROUGH; 1444039Sbinkertn@umich.edu case 'x': 1454039Sbinkertn@umich.edu fmt.base = Format::hex; 1464039Sbinkertn@umich.edu fmt.format = Format::integer; 1474039Sbinkertn@umich.edu done = true; 1484039Sbinkertn@umich.edu break; 1494039Sbinkertn@umich.edu 1504039Sbinkertn@umich.edu case 'o': 1514039Sbinkertn@umich.edu fmt.base = Format::oct; 1524039Sbinkertn@umich.edu fmt.format = Format::integer; 1534039Sbinkertn@umich.edu done = true; 1544039Sbinkertn@umich.edu break; 1554039Sbinkertn@umich.edu 1564039Sbinkertn@umich.edu case 'd': 1574039Sbinkertn@umich.edu case 'i': 1584039Sbinkertn@umich.edu case 'u': 1594039Sbinkertn@umich.edu fmt.format = Format::integer; 1604039Sbinkertn@umich.edu done = true; 1614039Sbinkertn@umich.edu break; 1624039Sbinkertn@umich.edu 1634039Sbinkertn@umich.edu case 'G': 1644039Sbinkertn@umich.edu fmt.uppercase = true; 16512392Sjason@lowepower.com M5_FALLTHROUGH; 1664039Sbinkertn@umich.edu case 'g': 1674039Sbinkertn@umich.edu fmt.format = Format::floating; 1684039Sbinkertn@umich.edu fmt.float_format = Format::best; 1694039Sbinkertn@umich.edu done = true; 1704039Sbinkertn@umich.edu break; 1714039Sbinkertn@umich.edu 1724039Sbinkertn@umich.edu case 'E': 1734039Sbinkertn@umich.edu fmt.uppercase = true; 17412392Sjason@lowepower.com M5_FALLTHROUGH; 1754039Sbinkertn@umich.edu case 'e': 1764039Sbinkertn@umich.edu fmt.format = Format::floating; 1774039Sbinkertn@umich.edu fmt.float_format = Format::scientific; 1784039Sbinkertn@umich.edu done = true; 1794039Sbinkertn@umich.edu break; 1804039Sbinkertn@umich.edu 1814039Sbinkertn@umich.edu case 'f': 1824039Sbinkertn@umich.edu fmt.format = Format::floating; 1834039Sbinkertn@umich.edu fmt.float_format = Format::fixed; 1844039Sbinkertn@umich.edu done = true; 1854039Sbinkertn@umich.edu break; 1864039Sbinkertn@umich.edu 1874039Sbinkertn@umich.edu case 'n': 1884039Sbinkertn@umich.edu stream << "we don't do %n!!!\n"; 1894039Sbinkertn@umich.edu done = true; 1904039Sbinkertn@umich.edu break; 1914039Sbinkertn@umich.edu 1924039Sbinkertn@umich.edu case '#': 1934039Sbinkertn@umich.edu fmt.alternate_form = true; 1944039Sbinkertn@umich.edu break; 1954039Sbinkertn@umich.edu 1964039Sbinkertn@umich.edu case '-': 1974039Sbinkertn@umich.edu fmt.flush_left = true; 1984039Sbinkertn@umich.edu break; 1994039Sbinkertn@umich.edu 2004039Sbinkertn@umich.edu case '+': 2014039Sbinkertn@umich.edu fmt.print_sign = true; 2024039Sbinkertn@umich.edu break; 2034039Sbinkertn@umich.edu 2044039Sbinkertn@umich.edu case ' ': 2054039Sbinkertn@umich.edu fmt.blank_space = true; 2064039Sbinkertn@umich.edu break; 2074039Sbinkertn@umich.edu 2084039Sbinkertn@umich.edu case '.': 2094039Sbinkertn@umich.edu fmt.width = number; 2104039Sbinkertn@umich.edu fmt.precision = 0; 2114039Sbinkertn@umich.edu have_precision = true; 2124039Sbinkertn@umich.edu number = 0; 2134039Sbinkertn@umich.edu end_number = false; 2144039Sbinkertn@umich.edu break; 2154039Sbinkertn@umich.edu 2164039Sbinkertn@umich.edu case '0': 2174039Sbinkertn@umich.edu if (number == 0) { 2184039Sbinkertn@umich.edu fmt.fill_zero = true; 2194039Sbinkertn@umich.edu break; 2204039Sbinkertn@umich.edu } 22112392Sjason@lowepower.com M5_FALLTHROUGH; 2224039Sbinkertn@umich.edu case '1': 2234039Sbinkertn@umich.edu case '2': 2244039Sbinkertn@umich.edu case '3': 2254039Sbinkertn@umich.edu case '4': 2264039Sbinkertn@umich.edu case '5': 2274039Sbinkertn@umich.edu case '6': 2284039Sbinkertn@umich.edu case '7': 2294039Sbinkertn@umich.edu case '8': 2304039Sbinkertn@umich.edu case '9': 2314039Sbinkertn@umich.edu number = number * 10 + (*ptr - '0'); 2324039Sbinkertn@umich.edu break; 2334039Sbinkertn@umich.edu 2345756Snate@binkert.org case '*': 2355756Snate@binkert.org if (have_precision) 2365756Snate@binkert.org fmt.get_precision = true; 2375756Snate@binkert.org else 2385756Snate@binkert.org fmt.get_width = true; 2395756Snate@binkert.org break; 2405756Snate@binkert.org 2414039Sbinkertn@umich.edu case '%': 2425756Snate@binkert.org assert(false && "we shouldn't get here"); 2434039Sbinkertn@umich.edu break; 2444039Sbinkertn@umich.edu 2454039Sbinkertn@umich.edu default: 2464039Sbinkertn@umich.edu done = true; 2474039Sbinkertn@umich.edu break; 2484039Sbinkertn@umich.edu } 2494039Sbinkertn@umich.edu 2504039Sbinkertn@umich.edu if (end_number) { 2514039Sbinkertn@umich.edu if (have_precision) 2524039Sbinkertn@umich.edu fmt.precision = number; 2534039Sbinkertn@umich.edu else 2544039Sbinkertn@umich.edu fmt.width = number; 2554039Sbinkertn@umich.edu 2564039Sbinkertn@umich.edu end_number = false; 2574039Sbinkertn@umich.edu number = 0; 2584039Sbinkertn@umich.edu } 2599331Schander.sudanthi@arm.com 2609331Schander.sudanthi@arm.com if (done) { 2619331Schander.sudanthi@arm.com if ((fmt.format == Format::integer) && have_precision) { 2629331Schander.sudanthi@arm.com // specified a . but not a float, set width 2639331Schander.sudanthi@arm.com fmt.width = fmt.precision; 2649331Schander.sudanthi@arm.com // precision requries digits for width, must fill with 0 2659331Schander.sudanthi@arm.com fmt.fill_zero = true; 2669331Schander.sudanthi@arm.com } else if ((fmt.format == Format::floating) && !have_precision && 2679331Schander.sudanthi@arm.com fmt.fill_zero) { 2689331Schander.sudanthi@arm.com // ambiguous case, matching printf 2699331Schander.sudanthi@arm.com fmt.precision = fmt.width; 2709331Schander.sudanthi@arm.com } 2719331Schander.sudanthi@arm.com } 2729331Schander.sudanthi@arm.com } // end while 2734039Sbinkertn@umich.edu 2744039Sbinkertn@umich.edu ++ptr; 2752SN/A} 2762SN/A 2774039Sbinkertn@umich.eduvoid 2784039Sbinkertn@umich.eduPrint::end_args() 2792SN/A{ 2804039Sbinkertn@umich.edu size_t len; 2812SN/A 2824039Sbinkertn@umich.edu while (*ptr) { 2834039Sbinkertn@umich.edu switch (*ptr) { 2844039Sbinkertn@umich.edu case '%': 2854039Sbinkertn@umich.edu if (ptr[1] != '%') 2864039Sbinkertn@umich.edu stream << "<extra arg>"; 2872SN/A 2884039Sbinkertn@umich.edu stream.put('%'); 2894039Sbinkertn@umich.edu ptr += 2; 2904039Sbinkertn@umich.edu break; 2914039Sbinkertn@umich.edu 2924039Sbinkertn@umich.edu case '\n': 2934039Sbinkertn@umich.edu stream << endl; 2944039Sbinkertn@umich.edu ++ptr; 2954039Sbinkertn@umich.edu break; 2964039Sbinkertn@umich.edu case '\r': 2974039Sbinkertn@umich.edu ++ptr; 2984039Sbinkertn@umich.edu if (*ptr != '\n') 2994039Sbinkertn@umich.edu stream << endl; 3004039Sbinkertn@umich.edu break; 3014039Sbinkertn@umich.edu 3024039Sbinkertn@umich.edu default: 3034039Sbinkertn@umich.edu len = strcspn(ptr, "%\n\r\0"); 3044039Sbinkertn@umich.edu stream.write(ptr, len); 3054039Sbinkertn@umich.edu ptr += len; 3064039Sbinkertn@umich.edu break; 3074039Sbinkertn@umich.edu } 3084039Sbinkertn@umich.edu } 3094039Sbinkertn@umich.edu 3104039Sbinkertn@umich.edu stream.flags(saved_flags); 3114039Sbinkertn@umich.edu stream.fill(saved_fill); 3124039Sbinkertn@umich.edu stream.precision(saved_precision); 3132SN/A} 3142SN/A 3157811Ssteve.reinhardt@amd.com} // namespace cp 316