cprintf.cc revision 5756
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 '%':
724039Sbinkertn@umich.edu            if (ptr[1] != '%')
734039Sbinkertn@umich.edu                goto processing;
742SN/A
754039Sbinkertn@umich.edu            stream.put('%');
764039Sbinkertn@umich.edu            ptr += 2;
772SN/A            break;
782SN/A
792SN/A          case '\n':
804039Sbinkertn@umich.edu            stream << endl;
814039Sbinkertn@umich.edu            ++ptr;
822SN/A            break;
832SN/A          case '\r':
844039Sbinkertn@umich.edu            ++ptr;
854039Sbinkertn@umich.edu            if (*ptr != '\n')
864039Sbinkertn@umich.edu                stream << endl;
872SN/A            break;
882SN/A
894039Sbinkertn@umich.edu          default:
904039Sbinkertn@umich.edu            len = strcspn(ptr, "%\n\r\0");
914039Sbinkertn@umich.edu            stream.write(ptr, len);
924039Sbinkertn@umich.edu            ptr += len;
932SN/A            break;
942SN/A        }
952SN/A    }
962SN/A
974039Sbinkertn@umich.edu    return;
984039Sbinkertn@umich.edu
994039Sbinkertn@umich.edu  processing:
1004039Sbinkertn@umich.edu    bool done = false;
1014039Sbinkertn@umich.edu    bool end_number = false;
1024039Sbinkertn@umich.edu    bool have_precision = false;
1034039Sbinkertn@umich.edu    int number = 0;
1044039Sbinkertn@umich.edu
1054039Sbinkertn@umich.edu    stream.fill(' ');
1064039Sbinkertn@umich.edu    stream.flags((ios::fmtflags)0);
1074039Sbinkertn@umich.edu
1084039Sbinkertn@umich.edu    while (!done) {
1094039Sbinkertn@umich.edu        ++ptr;
1104039Sbinkertn@umich.edu        if (*ptr >= '0' && *ptr <= '9') {
1114039Sbinkertn@umich.edu            if (end_number)
1124039Sbinkertn@umich.edu                continue;
1134039Sbinkertn@umich.edu        } else if (number > 0)
1144039Sbinkertn@umich.edu            end_number = true;
1154039Sbinkertn@umich.edu
1164039Sbinkertn@umich.edu        switch (*ptr) {
1174039Sbinkertn@umich.edu          case 's':
1184039Sbinkertn@umich.edu            fmt.format = Format::string;
1194039Sbinkertn@umich.edu            done = true;
1204039Sbinkertn@umich.edu            break;
1214039Sbinkertn@umich.edu
1224039Sbinkertn@umich.edu          case 'c':
1234039Sbinkertn@umich.edu            fmt.format = Format::character;
1244039Sbinkertn@umich.edu            done = true;
1254039Sbinkertn@umich.edu            break;
1264039Sbinkertn@umich.edu
1274039Sbinkertn@umich.edu          case 'l':
1284039Sbinkertn@umich.edu            continue;
1294039Sbinkertn@umich.edu
1304039Sbinkertn@umich.edu          case 'p':
1314039Sbinkertn@umich.edu            fmt.format = Format::integer;
1324039Sbinkertn@umich.edu            fmt.base = Format::hex;
1334039Sbinkertn@umich.edu            fmt.alternate_form = true;
1344039Sbinkertn@umich.edu            done = true;
1354039Sbinkertn@umich.edu            break;
1364039Sbinkertn@umich.edu
1374039Sbinkertn@umich.edu          case 'X':
1384039Sbinkertn@umich.edu            fmt.uppercase = true;
1394039Sbinkertn@umich.edu          case 'x':
1404039Sbinkertn@umich.edu            fmt.base = Format::hex;
1414039Sbinkertn@umich.edu            fmt.format = Format::integer;
1424039Sbinkertn@umich.edu            done = true;
1434039Sbinkertn@umich.edu            break;
1444039Sbinkertn@umich.edu
1454039Sbinkertn@umich.edu          case 'o':
1464039Sbinkertn@umich.edu            fmt.base = Format::oct;
1474039Sbinkertn@umich.edu            fmt.format = Format::integer;
1484039Sbinkertn@umich.edu            done = true;
1494039Sbinkertn@umich.edu            break;
1504039Sbinkertn@umich.edu
1514039Sbinkertn@umich.edu          case 'd':
1524039Sbinkertn@umich.edu          case 'i':
1534039Sbinkertn@umich.edu          case 'u':
1544039Sbinkertn@umich.edu            fmt.format = Format::integer;
1554039Sbinkertn@umich.edu            done = true;
1564039Sbinkertn@umich.edu            break;
1574039Sbinkertn@umich.edu
1584039Sbinkertn@umich.edu          case 'G':
1594039Sbinkertn@umich.edu            fmt.uppercase = true;
1604039Sbinkertn@umich.edu          case 'g':
1614039Sbinkertn@umich.edu            fmt.format = Format::floating;
1624039Sbinkertn@umich.edu            fmt.float_format = Format::best;
1634039Sbinkertn@umich.edu            done = true;
1644039Sbinkertn@umich.edu            break;
1654039Sbinkertn@umich.edu
1664039Sbinkertn@umich.edu          case 'E':
1674039Sbinkertn@umich.edu            fmt.uppercase = true;
1684039Sbinkertn@umich.edu          case 'e':
1694039Sbinkertn@umich.edu            fmt.format = Format::floating;
1704039Sbinkertn@umich.edu            fmt.float_format = Format::scientific;
1714039Sbinkertn@umich.edu            done = true;
1724039Sbinkertn@umich.edu            break;
1734039Sbinkertn@umich.edu
1744039Sbinkertn@umich.edu          case 'f':
1754039Sbinkertn@umich.edu            fmt.format = Format::floating;
1764039Sbinkertn@umich.edu            fmt.float_format = Format::fixed;
1774039Sbinkertn@umich.edu            done = true;
1784039Sbinkertn@umich.edu            break;
1794039Sbinkertn@umich.edu
1804039Sbinkertn@umich.edu          case 'n':
1814039Sbinkertn@umich.edu            stream << "we don't do %n!!!\n";
1824039Sbinkertn@umich.edu            done = true;
1834039Sbinkertn@umich.edu            break;
1844039Sbinkertn@umich.edu
1854039Sbinkertn@umich.edu          case '#':
1864039Sbinkertn@umich.edu            fmt.alternate_form = true;
1874039Sbinkertn@umich.edu            break;
1884039Sbinkertn@umich.edu
1894039Sbinkertn@umich.edu          case '-':
1904039Sbinkertn@umich.edu            fmt.flush_left = true;
1914039Sbinkertn@umich.edu            break;
1924039Sbinkertn@umich.edu
1934039Sbinkertn@umich.edu          case '+':
1944039Sbinkertn@umich.edu            fmt.print_sign = true;
1954039Sbinkertn@umich.edu            break;
1964039Sbinkertn@umich.edu
1974039Sbinkertn@umich.edu          case ' ':
1984039Sbinkertn@umich.edu            fmt.blank_space = true;
1994039Sbinkertn@umich.edu            break;
2004039Sbinkertn@umich.edu
2014039Sbinkertn@umich.edu          case '.':
2024039Sbinkertn@umich.edu            fmt.width = number;
2034039Sbinkertn@umich.edu            fmt.precision = 0;
2044039Sbinkertn@umich.edu            have_precision = true;
2054039Sbinkertn@umich.edu            number = 0;
2064039Sbinkertn@umich.edu            end_number = false;
2074039Sbinkertn@umich.edu            break;
2084039Sbinkertn@umich.edu
2094039Sbinkertn@umich.edu          case '0':
2104039Sbinkertn@umich.edu            if (number == 0) {
2114039Sbinkertn@umich.edu                fmt.fill_zero = true;
2124039Sbinkertn@umich.edu                break;
2134039Sbinkertn@umich.edu            }
2144039Sbinkertn@umich.edu          case '1':
2154039Sbinkertn@umich.edu          case '2':
2164039Sbinkertn@umich.edu          case '3':
2174039Sbinkertn@umich.edu          case '4':
2184039Sbinkertn@umich.edu          case '5':
2194039Sbinkertn@umich.edu          case '6':
2204039Sbinkertn@umich.edu          case '7':
2214039Sbinkertn@umich.edu          case '8':
2224039Sbinkertn@umich.edu          case '9':
2234039Sbinkertn@umich.edu            number = number * 10 + (*ptr - '0');
2244039Sbinkertn@umich.edu            break;
2254039Sbinkertn@umich.edu
2265756Snate@binkert.org          case '*':
2275756Snate@binkert.org            if (have_precision)
2285756Snate@binkert.org                fmt.get_precision = true;
2295756Snate@binkert.org            else
2305756Snate@binkert.org                fmt.get_width = true;
2315756Snate@binkert.org            break;
2325756Snate@binkert.org
2334039Sbinkertn@umich.edu          case '%':
2345756Snate@binkert.org            assert(false && "we shouldn't get here");
2354039Sbinkertn@umich.edu            break;
2364039Sbinkertn@umich.edu
2374039Sbinkertn@umich.edu          default:
2384039Sbinkertn@umich.edu            done = true;
2394039Sbinkertn@umich.edu            break;
2404039Sbinkertn@umich.edu        }
2414039Sbinkertn@umich.edu
2424039Sbinkertn@umich.edu        if (end_number) {
2434039Sbinkertn@umich.edu            if (have_precision)
2444039Sbinkertn@umich.edu                fmt.precision = number;
2454039Sbinkertn@umich.edu            else
2464039Sbinkertn@umich.edu                fmt.width = number;
2474039Sbinkertn@umich.edu
2484039Sbinkertn@umich.edu            end_number = false;
2494039Sbinkertn@umich.edu            number = 0;
2504039Sbinkertn@umich.edu        }
2512SN/A    }
2524039Sbinkertn@umich.edu
2534039Sbinkertn@umich.edu    ++ptr;
2542SN/A}
2552SN/A
2564039Sbinkertn@umich.eduvoid
2574039Sbinkertn@umich.eduPrint::end_args()
2582SN/A{
2594039Sbinkertn@umich.edu    size_t len;
2602SN/A
2614039Sbinkertn@umich.edu    while (*ptr) {
2624039Sbinkertn@umich.edu        switch (*ptr) {
2634039Sbinkertn@umich.edu          case '%':
2644039Sbinkertn@umich.edu            if (ptr[1] != '%')
2654039Sbinkertn@umich.edu                stream << "<extra arg>";
2662SN/A
2674039Sbinkertn@umich.edu            stream.put('%');
2684039Sbinkertn@umich.edu            ptr += 2;
2694039Sbinkertn@umich.edu            break;
2704039Sbinkertn@umich.edu
2714039Sbinkertn@umich.edu          case '\n':
2724039Sbinkertn@umich.edu            stream << endl;
2734039Sbinkertn@umich.edu            ++ptr;
2744039Sbinkertn@umich.edu            break;
2754039Sbinkertn@umich.edu          case '\r':
2764039Sbinkertn@umich.edu            ++ptr;
2774039Sbinkertn@umich.edu            if (*ptr != '\n')
2784039Sbinkertn@umich.edu                stream << endl;
2794039Sbinkertn@umich.edu            break;
2804039Sbinkertn@umich.edu
2814039Sbinkertn@umich.edu          default:
2824039Sbinkertn@umich.edu            len = strcspn(ptr, "%\n\r\0");
2834039Sbinkertn@umich.edu            stream.write(ptr, len);
2844039Sbinkertn@umich.edu            ptr += len;
2854039Sbinkertn@umich.edu            break;
2864039Sbinkertn@umich.edu        }
2874039Sbinkertn@umich.edu    }
2884039Sbinkertn@umich.edu
2894039Sbinkertn@umich.edu    stream.flags(saved_flags);
2904039Sbinkertn@umich.edu    stream.fill(saved_fill);
2914039Sbinkertn@umich.edu    stream.precision(saved_precision);
2922SN/A}
2932SN/A
2944039Sbinkertn@umich.edu/* end namespace cp */ }
295