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