cprintf.cc revision 11793
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 382SN/Ausing namespace std; 392SN/A 402SN/Anamespace cp { 412SN/A 424039Sbinkertn@umich.eduPrint::Print(std::ostream &stream, const std::string &format) 435756Snate@binkert.org : stream(stream), format(format.c_str()), ptr(format.c_str()), cont(false) 44492SN/A{ 454039Sbinkertn@umich.edu saved_flags = stream.flags(); 464039Sbinkertn@umich.edu saved_fill = stream.fill(); 474039Sbinkertn@umich.edu saved_precision = stream.precision(); 484039Sbinkertn@umich.edu} 494039Sbinkertn@umich.edu 504039Sbinkertn@umich.eduPrint::Print(std::ostream &stream, const char *format) 515756Snate@binkert.org : stream(stream), format(format), ptr(format), cont(false) 524039Sbinkertn@umich.edu{ 534039Sbinkertn@umich.edu saved_flags = stream.flags(); 544039Sbinkertn@umich.edu saved_fill = stream.fill(); 554039Sbinkertn@umich.edu saved_precision = stream.precision(); 564039Sbinkertn@umich.edu} 574039Sbinkertn@umich.edu 584039Sbinkertn@umich.eduPrint::~Print() 594039Sbinkertn@umich.edu{ 60492SN/A} 61492SN/A 622SN/Avoid 635756Snate@binkert.orgPrint::process() 642SN/A{ 655756Snate@binkert.org fmt.clear(); 665756Snate@binkert.org 674039Sbinkertn@umich.edu size_t len; 68492SN/A 694039Sbinkertn@umich.edu while (*ptr) { 704039Sbinkertn@umich.edu switch (*ptr) { 714039Sbinkertn@umich.edu case '%': 729331Schander.sudanthi@arm.com if (ptr[1] != '%') { 739331Schander.sudanthi@arm.com process_flag(); 749331Schander.sudanthi@arm.com return; 759331Schander.sudanthi@arm.com } 764039Sbinkertn@umich.edu stream.put('%'); 774039Sbinkertn@umich.edu ptr += 2; 782SN/A break; 792SN/A 802SN/A case '\n': 814039Sbinkertn@umich.edu stream << endl; 824039Sbinkertn@umich.edu ++ptr; 832SN/A break; 842SN/A case '\r': 854039Sbinkertn@umich.edu ++ptr; 864039Sbinkertn@umich.edu if (*ptr != '\n') 874039Sbinkertn@umich.edu stream << endl; 882SN/A break; 892SN/A 904039Sbinkertn@umich.edu default: 914039Sbinkertn@umich.edu len = strcspn(ptr, "%\n\r\0"); 924039Sbinkertn@umich.edu stream.write(ptr, len); 934039Sbinkertn@umich.edu ptr += len; 942SN/A break; 952SN/A } 962SN/A } 979331Schander.sudanthi@arm.com} 982SN/A 999331Schander.sudanthi@arm.comvoid 1009331Schander.sudanthi@arm.comPrint::process_flag() 1019331Schander.sudanthi@arm.com{ 1024039Sbinkertn@umich.edu bool done = false; 1034039Sbinkertn@umich.edu bool end_number = false; 1044039Sbinkertn@umich.edu bool have_precision = false; 1054039Sbinkertn@umich.edu int number = 0; 1064039Sbinkertn@umich.edu 1074039Sbinkertn@umich.edu stream.fill(' '); 1084039Sbinkertn@umich.edu stream.flags((ios::fmtflags)0); 1094039Sbinkertn@umich.edu 1104039Sbinkertn@umich.edu while (!done) { 1114039Sbinkertn@umich.edu ++ptr; 1124039Sbinkertn@umich.edu if (*ptr >= '0' && *ptr <= '9') { 1134039Sbinkertn@umich.edu if (end_number) 1144039Sbinkertn@umich.edu continue; 1154039Sbinkertn@umich.edu } else if (number > 0) 1164039Sbinkertn@umich.edu end_number = true; 1174039Sbinkertn@umich.edu 1184039Sbinkertn@umich.edu switch (*ptr) { 1194039Sbinkertn@umich.edu case 's': 1204039Sbinkertn@umich.edu fmt.format = Format::string; 1214039Sbinkertn@umich.edu done = true; 1224039Sbinkertn@umich.edu break; 1234039Sbinkertn@umich.edu 1244039Sbinkertn@umich.edu case 'c': 1254039Sbinkertn@umich.edu fmt.format = Format::character; 1264039Sbinkertn@umich.edu done = true; 1274039Sbinkertn@umich.edu break; 1284039Sbinkertn@umich.edu 1294039Sbinkertn@umich.edu case 'l': 1304039Sbinkertn@umich.edu continue; 1314039Sbinkertn@umich.edu 1324039Sbinkertn@umich.edu case 'p': 1334039Sbinkertn@umich.edu fmt.format = Format::integer; 1344039Sbinkertn@umich.edu fmt.base = Format::hex; 1354039Sbinkertn@umich.edu fmt.alternate_form = true; 1364039Sbinkertn@umich.edu done = true; 1374039Sbinkertn@umich.edu break; 1384039Sbinkertn@umich.edu 1394039Sbinkertn@umich.edu case 'X': 1404039Sbinkertn@umich.edu fmt.uppercase = true; 1414039Sbinkertn@umich.edu case 'x': 1424039Sbinkertn@umich.edu fmt.base = Format::hex; 1434039Sbinkertn@umich.edu fmt.format = Format::integer; 1444039Sbinkertn@umich.edu done = true; 1454039Sbinkertn@umich.edu break; 1464039Sbinkertn@umich.edu 1474039Sbinkertn@umich.edu case 'o': 1484039Sbinkertn@umich.edu fmt.base = Format::oct; 1494039Sbinkertn@umich.edu fmt.format = Format::integer; 1504039Sbinkertn@umich.edu done = true; 1514039Sbinkertn@umich.edu break; 1524039Sbinkertn@umich.edu 1534039Sbinkertn@umich.edu case 'd': 1544039Sbinkertn@umich.edu case 'i': 1554039Sbinkertn@umich.edu case 'u': 1564039Sbinkertn@umich.edu fmt.format = Format::integer; 1574039Sbinkertn@umich.edu done = true; 1584039Sbinkertn@umich.edu break; 1594039Sbinkertn@umich.edu 1604039Sbinkertn@umich.edu case 'G': 1614039Sbinkertn@umich.edu fmt.uppercase = true; 1624039Sbinkertn@umich.edu case 'g': 1634039Sbinkertn@umich.edu fmt.format = Format::floating; 1644039Sbinkertn@umich.edu fmt.float_format = Format::best; 1654039Sbinkertn@umich.edu done = true; 1664039Sbinkertn@umich.edu break; 1674039Sbinkertn@umich.edu 1684039Sbinkertn@umich.edu case 'E': 1694039Sbinkertn@umich.edu fmt.uppercase = true; 1704039Sbinkertn@umich.edu case 'e': 1714039Sbinkertn@umich.edu fmt.format = Format::floating; 1724039Sbinkertn@umich.edu fmt.float_format = Format::scientific; 1734039Sbinkertn@umich.edu done = true; 1744039Sbinkertn@umich.edu break; 1754039Sbinkertn@umich.edu 1764039Sbinkertn@umich.edu case 'f': 1774039Sbinkertn@umich.edu fmt.format = Format::floating; 1784039Sbinkertn@umich.edu fmt.float_format = Format::fixed; 1794039Sbinkertn@umich.edu done = true; 1804039Sbinkertn@umich.edu break; 1814039Sbinkertn@umich.edu 1824039Sbinkertn@umich.edu case 'n': 1834039Sbinkertn@umich.edu stream << "we don't do %n!!!\n"; 1844039Sbinkertn@umich.edu done = true; 1854039Sbinkertn@umich.edu break; 1864039Sbinkertn@umich.edu 1874039Sbinkertn@umich.edu case '#': 1884039Sbinkertn@umich.edu fmt.alternate_form = true; 1894039Sbinkertn@umich.edu break; 1904039Sbinkertn@umich.edu 1914039Sbinkertn@umich.edu case '-': 1924039Sbinkertn@umich.edu fmt.flush_left = true; 1934039Sbinkertn@umich.edu break; 1944039Sbinkertn@umich.edu 1954039Sbinkertn@umich.edu case '+': 1964039Sbinkertn@umich.edu fmt.print_sign = true; 1974039Sbinkertn@umich.edu break; 1984039Sbinkertn@umich.edu 1994039Sbinkertn@umich.edu case ' ': 2004039Sbinkertn@umich.edu fmt.blank_space = true; 2014039Sbinkertn@umich.edu break; 2024039Sbinkertn@umich.edu 2034039Sbinkertn@umich.edu case '.': 2044039Sbinkertn@umich.edu fmt.width = number; 2054039Sbinkertn@umich.edu fmt.precision = 0; 2064039Sbinkertn@umich.edu have_precision = true; 2074039Sbinkertn@umich.edu number = 0; 2084039Sbinkertn@umich.edu end_number = false; 2094039Sbinkertn@umich.edu break; 2104039Sbinkertn@umich.edu 2114039Sbinkertn@umich.edu case '0': 2124039Sbinkertn@umich.edu if (number == 0) { 2134039Sbinkertn@umich.edu fmt.fill_zero = true; 2144039Sbinkertn@umich.edu break; 2154039Sbinkertn@umich.edu } 2164039Sbinkertn@umich.edu case '1': 2174039Sbinkertn@umich.edu case '2': 2184039Sbinkertn@umich.edu case '3': 2194039Sbinkertn@umich.edu case '4': 2204039Sbinkertn@umich.edu case '5': 2214039Sbinkertn@umich.edu case '6': 2224039Sbinkertn@umich.edu case '7': 2234039Sbinkertn@umich.edu case '8': 2244039Sbinkertn@umich.edu case '9': 2254039Sbinkertn@umich.edu number = number * 10 + (*ptr - '0'); 2264039Sbinkertn@umich.edu break; 2274039Sbinkertn@umich.edu 2285756Snate@binkert.org case '*': 2295756Snate@binkert.org if (have_precision) 2305756Snate@binkert.org fmt.get_precision = true; 2315756Snate@binkert.org else 2325756Snate@binkert.org fmt.get_width = true; 2335756Snate@binkert.org break; 2345756Snate@binkert.org 2354039Sbinkertn@umich.edu case '%': 2365756Snate@binkert.org assert(false && "we shouldn't get here"); 2374039Sbinkertn@umich.edu break; 2384039Sbinkertn@umich.edu 2394039Sbinkertn@umich.edu default: 2404039Sbinkertn@umich.edu done = true; 2414039Sbinkertn@umich.edu break; 2424039Sbinkertn@umich.edu } 2434039Sbinkertn@umich.edu 2444039Sbinkertn@umich.edu if (end_number) { 2454039Sbinkertn@umich.edu if (have_precision) 2464039Sbinkertn@umich.edu fmt.precision = number; 2474039Sbinkertn@umich.edu else 2484039Sbinkertn@umich.edu fmt.width = number; 2494039Sbinkertn@umich.edu 2504039Sbinkertn@umich.edu end_number = false; 2514039Sbinkertn@umich.edu number = 0; 2524039Sbinkertn@umich.edu } 2539331Schander.sudanthi@arm.com 2549331Schander.sudanthi@arm.com if (done) { 2559331Schander.sudanthi@arm.com if ((fmt.format == Format::integer) && have_precision) { 2569331Schander.sudanthi@arm.com // specified a . but not a float, set width 2579331Schander.sudanthi@arm.com fmt.width = fmt.precision; 2589331Schander.sudanthi@arm.com // precision requries digits for width, must fill with 0 2599331Schander.sudanthi@arm.com fmt.fill_zero = true; 2609331Schander.sudanthi@arm.com } else if ((fmt.format == Format::floating) && !have_precision && 2619331Schander.sudanthi@arm.com fmt.fill_zero) { 2629331Schander.sudanthi@arm.com // ambiguous case, matching printf 2639331Schander.sudanthi@arm.com fmt.precision = fmt.width; 2649331Schander.sudanthi@arm.com } 2659331Schander.sudanthi@arm.com } 2669331Schander.sudanthi@arm.com } // end while 2674039Sbinkertn@umich.edu 2684039Sbinkertn@umich.edu ++ptr; 2692SN/A} 2702SN/A 2714039Sbinkertn@umich.eduvoid 2724039Sbinkertn@umich.eduPrint::end_args() 2732SN/A{ 2744039Sbinkertn@umich.edu size_t len; 2752SN/A 2764039Sbinkertn@umich.edu while (*ptr) { 2774039Sbinkertn@umich.edu switch (*ptr) { 2784039Sbinkertn@umich.edu case '%': 2794039Sbinkertn@umich.edu if (ptr[1] != '%') 2804039Sbinkertn@umich.edu stream << "<extra arg>"; 2812SN/A 2824039Sbinkertn@umich.edu stream.put('%'); 2834039Sbinkertn@umich.edu ptr += 2; 2844039Sbinkertn@umich.edu break; 2854039Sbinkertn@umich.edu 2864039Sbinkertn@umich.edu case '\n': 2874039Sbinkertn@umich.edu stream << endl; 2884039Sbinkertn@umich.edu ++ptr; 2894039Sbinkertn@umich.edu break; 2904039Sbinkertn@umich.edu case '\r': 2914039Sbinkertn@umich.edu ++ptr; 2924039Sbinkertn@umich.edu if (*ptr != '\n') 2934039Sbinkertn@umich.edu stream << endl; 2944039Sbinkertn@umich.edu break; 2954039Sbinkertn@umich.edu 2964039Sbinkertn@umich.edu default: 2974039Sbinkertn@umich.edu len = strcspn(ptr, "%\n\r\0"); 2984039Sbinkertn@umich.edu stream.write(ptr, len); 2994039Sbinkertn@umich.edu ptr += len; 3004039Sbinkertn@umich.edu break; 3014039Sbinkertn@umich.edu } 3024039Sbinkertn@umich.edu } 3034039Sbinkertn@umich.edu 3044039Sbinkertn@umich.edu stream.flags(saved_flags); 3054039Sbinkertn@umich.edu stream.fill(saved_fill); 3064039Sbinkertn@umich.edu stream.precision(saved_precision); 3072SN/A} 3082SN/A 3097811Ssteve.reinhardt@amd.com} // namespace cp 310