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();
5012979Sgabeblack@google.com    saved_width = stream.width();
514039Sbinkertn@umich.edu}
524039Sbinkertn@umich.edu
534039Sbinkertn@umich.eduPrint::Print(std::ostream &stream, const char *format)
545756Snate@binkert.org    : stream(stream), format(format), ptr(format), cont(false)
554039Sbinkertn@umich.edu{
564039Sbinkertn@umich.edu    saved_flags = stream.flags();
574039Sbinkertn@umich.edu    saved_fill = stream.fill();
584039Sbinkertn@umich.edu    saved_precision = stream.precision();
5912979Sgabeblack@google.com    saved_width = stream.width();
604039Sbinkertn@umich.edu}
614039Sbinkertn@umich.edu
624039Sbinkertn@umich.eduPrint::~Print()
634039Sbinkertn@umich.edu{
64492SN/A}
65492SN/A
662SN/Avoid
675756Snate@binkert.orgPrint::process()
682SN/A{
695756Snate@binkert.org    fmt.clear();
705756Snate@binkert.org
714039Sbinkertn@umich.edu    size_t len;
72492SN/A
734039Sbinkertn@umich.edu    while (*ptr) {
744039Sbinkertn@umich.edu        switch (*ptr) {
754039Sbinkertn@umich.edu          case '%':
769331Schander.sudanthi@arm.com            if (ptr[1] != '%') {
779331Schander.sudanthi@arm.com                process_flag();
789331Schander.sudanthi@arm.com                return;
799331Schander.sudanthi@arm.com            }
804039Sbinkertn@umich.edu            stream.put('%');
814039Sbinkertn@umich.edu            ptr += 2;
822SN/A            break;
832SN/A
842SN/A          case '\n':
854039Sbinkertn@umich.edu            stream << endl;
864039Sbinkertn@umich.edu            ++ptr;
872SN/A            break;
882SN/A          case '\r':
894039Sbinkertn@umich.edu            ++ptr;
904039Sbinkertn@umich.edu            if (*ptr != '\n')
914039Sbinkertn@umich.edu                stream << endl;
922SN/A            break;
932SN/A
944039Sbinkertn@umich.edu          default:
954039Sbinkertn@umich.edu            len = strcspn(ptr, "%\n\r\0");
964039Sbinkertn@umich.edu            stream.write(ptr, len);
974039Sbinkertn@umich.edu            ptr += len;
982SN/A            break;
992SN/A        }
1002SN/A    }
1019331Schander.sudanthi@arm.com}
1022SN/A
1039331Schander.sudanthi@arm.comvoid
1049331Schander.sudanthi@arm.comPrint::process_flag()
1059331Schander.sudanthi@arm.com{
1064039Sbinkertn@umich.edu    bool done = false;
1074039Sbinkertn@umich.edu    bool end_number = false;
1084039Sbinkertn@umich.edu    bool have_precision = false;
1094039Sbinkertn@umich.edu    int number = 0;
1104039Sbinkertn@umich.edu
1114039Sbinkertn@umich.edu    stream.fill(' ');
1124039Sbinkertn@umich.edu    stream.flags((ios::fmtflags)0);
1134039Sbinkertn@umich.edu
1144039Sbinkertn@umich.edu    while (!done) {
1154039Sbinkertn@umich.edu        ++ptr;
1164039Sbinkertn@umich.edu        if (*ptr >= '0' && *ptr <= '9') {
1174039Sbinkertn@umich.edu            if (end_number)
1184039Sbinkertn@umich.edu                continue;
1194039Sbinkertn@umich.edu        } else if (number > 0)
1204039Sbinkertn@umich.edu            end_number = true;
1214039Sbinkertn@umich.edu
1224039Sbinkertn@umich.edu        switch (*ptr) {
1234039Sbinkertn@umich.edu          case 's':
1244039Sbinkertn@umich.edu            fmt.format = Format::string;
1254039Sbinkertn@umich.edu            done = true;
1264039Sbinkertn@umich.edu            break;
1274039Sbinkertn@umich.edu
1284039Sbinkertn@umich.edu          case 'c':
1294039Sbinkertn@umich.edu            fmt.format = Format::character;
1304039Sbinkertn@umich.edu            done = true;
1314039Sbinkertn@umich.edu            break;
1324039Sbinkertn@umich.edu
1334039Sbinkertn@umich.edu          case 'l':
1344039Sbinkertn@umich.edu            continue;
1354039Sbinkertn@umich.edu
1364039Sbinkertn@umich.edu          case 'p':
1374039Sbinkertn@umich.edu            fmt.format = Format::integer;
1384039Sbinkertn@umich.edu            fmt.base = Format::hex;
1394039Sbinkertn@umich.edu            fmt.alternate_form = true;
1404039Sbinkertn@umich.edu            done = true;
1414039Sbinkertn@umich.edu            break;
1424039Sbinkertn@umich.edu
1434039Sbinkertn@umich.edu          case 'X':
1444039Sbinkertn@umich.edu            fmt.uppercase = true;
14512392Sjason@lowepower.com            M5_FALLTHROUGH;
1464039Sbinkertn@umich.edu          case 'x':
1474039Sbinkertn@umich.edu            fmt.base = Format::hex;
1484039Sbinkertn@umich.edu            fmt.format = Format::integer;
1494039Sbinkertn@umich.edu            done = true;
1504039Sbinkertn@umich.edu            break;
1514039Sbinkertn@umich.edu
1524039Sbinkertn@umich.edu          case 'o':
1534039Sbinkertn@umich.edu            fmt.base = Format::oct;
1544039Sbinkertn@umich.edu            fmt.format = Format::integer;
1554039Sbinkertn@umich.edu            done = true;
1564039Sbinkertn@umich.edu            break;
1574039Sbinkertn@umich.edu
1584039Sbinkertn@umich.edu          case 'd':
1594039Sbinkertn@umich.edu          case 'i':
1604039Sbinkertn@umich.edu          case 'u':
1614039Sbinkertn@umich.edu            fmt.format = Format::integer;
1624039Sbinkertn@umich.edu            done = true;
1634039Sbinkertn@umich.edu            break;
1644039Sbinkertn@umich.edu
1654039Sbinkertn@umich.edu          case 'G':
1664039Sbinkertn@umich.edu            fmt.uppercase = true;
16712392Sjason@lowepower.com            M5_FALLTHROUGH;
1684039Sbinkertn@umich.edu          case 'g':
1694039Sbinkertn@umich.edu            fmt.format = Format::floating;
1704039Sbinkertn@umich.edu            fmt.float_format = Format::best;
1714039Sbinkertn@umich.edu            done = true;
1724039Sbinkertn@umich.edu            break;
1734039Sbinkertn@umich.edu
1744039Sbinkertn@umich.edu          case 'E':
1754039Sbinkertn@umich.edu            fmt.uppercase = true;
17612392Sjason@lowepower.com            M5_FALLTHROUGH;
1774039Sbinkertn@umich.edu          case 'e':
1784039Sbinkertn@umich.edu            fmt.format = Format::floating;
1794039Sbinkertn@umich.edu            fmt.float_format = Format::scientific;
1804039Sbinkertn@umich.edu            done = true;
1814039Sbinkertn@umich.edu            break;
1824039Sbinkertn@umich.edu
1834039Sbinkertn@umich.edu          case 'f':
1844039Sbinkertn@umich.edu            fmt.format = Format::floating;
1854039Sbinkertn@umich.edu            fmt.float_format = Format::fixed;
1864039Sbinkertn@umich.edu            done = true;
1874039Sbinkertn@umich.edu            break;
1884039Sbinkertn@umich.edu
1894039Sbinkertn@umich.edu          case 'n':
1904039Sbinkertn@umich.edu            stream << "we don't do %n!!!\n";
1914039Sbinkertn@umich.edu            done = true;
1924039Sbinkertn@umich.edu            break;
1934039Sbinkertn@umich.edu
1944039Sbinkertn@umich.edu          case '#':
1954039Sbinkertn@umich.edu            fmt.alternate_form = true;
1964039Sbinkertn@umich.edu            break;
1974039Sbinkertn@umich.edu
1984039Sbinkertn@umich.edu          case '-':
1994039Sbinkertn@umich.edu            fmt.flush_left = true;
2004039Sbinkertn@umich.edu            break;
2014039Sbinkertn@umich.edu
2024039Sbinkertn@umich.edu          case '+':
2034039Sbinkertn@umich.edu            fmt.print_sign = true;
2044039Sbinkertn@umich.edu            break;
2054039Sbinkertn@umich.edu
2064039Sbinkertn@umich.edu          case ' ':
2074039Sbinkertn@umich.edu            fmt.blank_space = true;
2084039Sbinkertn@umich.edu            break;
2094039Sbinkertn@umich.edu
2104039Sbinkertn@umich.edu          case '.':
2114039Sbinkertn@umich.edu            fmt.width = number;
2124039Sbinkertn@umich.edu            fmt.precision = 0;
2134039Sbinkertn@umich.edu            have_precision = true;
2144039Sbinkertn@umich.edu            number = 0;
2154039Sbinkertn@umich.edu            end_number = false;
2164039Sbinkertn@umich.edu            break;
2174039Sbinkertn@umich.edu
2184039Sbinkertn@umich.edu          case '0':
2194039Sbinkertn@umich.edu            if (number == 0) {
2204039Sbinkertn@umich.edu                fmt.fill_zero = true;
2214039Sbinkertn@umich.edu                break;
2224039Sbinkertn@umich.edu            }
22312392Sjason@lowepower.com            M5_FALLTHROUGH;
2244039Sbinkertn@umich.edu          case '1':
2254039Sbinkertn@umich.edu          case '2':
2264039Sbinkertn@umich.edu          case '3':
2274039Sbinkertn@umich.edu          case '4':
2284039Sbinkertn@umich.edu          case '5':
2294039Sbinkertn@umich.edu          case '6':
2304039Sbinkertn@umich.edu          case '7':
2314039Sbinkertn@umich.edu          case '8':
2324039Sbinkertn@umich.edu          case '9':
2334039Sbinkertn@umich.edu            number = number * 10 + (*ptr - '0');
2344039Sbinkertn@umich.edu            break;
2354039Sbinkertn@umich.edu
2365756Snate@binkert.org          case '*':
2375756Snate@binkert.org            if (have_precision)
2385756Snate@binkert.org                fmt.get_precision = true;
2395756Snate@binkert.org            else
2405756Snate@binkert.org                fmt.get_width = true;
2415756Snate@binkert.org            break;
2425756Snate@binkert.org
2434039Sbinkertn@umich.edu          case '%':
2445756Snate@binkert.org            assert(false && "we shouldn't get here");
2454039Sbinkertn@umich.edu            break;
2464039Sbinkertn@umich.edu
2474039Sbinkertn@umich.edu          default:
2484039Sbinkertn@umich.edu            done = true;
2494039Sbinkertn@umich.edu            break;
2504039Sbinkertn@umich.edu        }
2514039Sbinkertn@umich.edu
2524039Sbinkertn@umich.edu        if (end_number) {
2534039Sbinkertn@umich.edu            if (have_precision)
2544039Sbinkertn@umich.edu                fmt.precision = number;
2554039Sbinkertn@umich.edu            else
2564039Sbinkertn@umich.edu                fmt.width = number;
2574039Sbinkertn@umich.edu
2584039Sbinkertn@umich.edu            end_number = false;
2594039Sbinkertn@umich.edu            number = 0;
2604039Sbinkertn@umich.edu        }
2619331Schander.sudanthi@arm.com
2629331Schander.sudanthi@arm.com        if (done) {
2639331Schander.sudanthi@arm.com            if ((fmt.format == Format::integer) && have_precision) {
2649331Schander.sudanthi@arm.com                // specified a . but not a float, set width
2659331Schander.sudanthi@arm.com                fmt.width = fmt.precision;
2669331Schander.sudanthi@arm.com                // precision requries digits for width, must fill with 0
2679331Schander.sudanthi@arm.com                fmt.fill_zero = true;
2689331Schander.sudanthi@arm.com            } else if ((fmt.format == Format::floating) && !have_precision &&
2699331Schander.sudanthi@arm.com                        fmt.fill_zero) {
2709331Schander.sudanthi@arm.com                // ambiguous case, matching printf
2719331Schander.sudanthi@arm.com                fmt.precision = fmt.width;
2729331Schander.sudanthi@arm.com            }
2739331Schander.sudanthi@arm.com        }
2749331Schander.sudanthi@arm.com    } // end while
2754039Sbinkertn@umich.edu
2764039Sbinkertn@umich.edu    ++ptr;
2772SN/A}
2782SN/A
2794039Sbinkertn@umich.eduvoid
2804039Sbinkertn@umich.eduPrint::end_args()
2812SN/A{
2824039Sbinkertn@umich.edu    size_t len;
2832SN/A
2844039Sbinkertn@umich.edu    while (*ptr) {
2854039Sbinkertn@umich.edu        switch (*ptr) {
2864039Sbinkertn@umich.edu          case '%':
2874039Sbinkertn@umich.edu            if (ptr[1] != '%')
2884039Sbinkertn@umich.edu                stream << "<extra arg>";
2892SN/A
2904039Sbinkertn@umich.edu            stream.put('%');
2914039Sbinkertn@umich.edu            ptr += 2;
2924039Sbinkertn@umich.edu            break;
2934039Sbinkertn@umich.edu
2944039Sbinkertn@umich.edu          case '\n':
2954039Sbinkertn@umich.edu            stream << endl;
2964039Sbinkertn@umich.edu            ++ptr;
2974039Sbinkertn@umich.edu            break;
2984039Sbinkertn@umich.edu          case '\r':
2994039Sbinkertn@umich.edu            ++ptr;
3004039Sbinkertn@umich.edu            if (*ptr != '\n')
3014039Sbinkertn@umich.edu                stream << endl;
3024039Sbinkertn@umich.edu            break;
3034039Sbinkertn@umich.edu
3044039Sbinkertn@umich.edu          default:
3054039Sbinkertn@umich.edu            len = strcspn(ptr, "%\n\r\0");
3064039Sbinkertn@umich.edu            stream.write(ptr, len);
3074039Sbinkertn@umich.edu            ptr += len;
3084039Sbinkertn@umich.edu            break;
3094039Sbinkertn@umich.edu        }
3104039Sbinkertn@umich.edu    }
3114039Sbinkertn@umich.edu
3124039Sbinkertn@umich.edu    stream.flags(saved_flags);
3134039Sbinkertn@umich.edu    stream.fill(saved_fill);
3144039Sbinkertn@umich.edu    stream.precision(saved_precision);
31512979Sgabeblack@google.com    stream.width(saved_width);
3162SN/A}
3172SN/A
3187811Ssteve.reinhardt@amd.com} // namespace cp
319