cprintf.cc revision 9331
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
312SN/A#include <cassert>
322SN/A#include <iomanip>
332SN/A#include <iostream>
342SN/A#include <sstream>
352SN/A
3656SN/A#include "base/cprintf.hh"
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