cprintf.cc revision 4039
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)
434039Sbinkertn@umich.edu    : stream(stream), format(format.c_str()), ptr(format.c_str())
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)
514039Sbinkertn@umich.edu    : stream(stream), format(format), ptr(format)
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
634039Sbinkertn@umich.eduPrint::process(Format &fmt)
642SN/A{
654039Sbinkertn@umich.edu    size_t len;
66492SN/A
674039Sbinkertn@umich.edu    while (*ptr) {
684039Sbinkertn@umich.edu        switch (*ptr) {
694039Sbinkertn@umich.edu          case '%':
704039Sbinkertn@umich.edu            if (ptr[1] != '%')
714039Sbinkertn@umich.edu                goto processing;
722SN/A
734039Sbinkertn@umich.edu            stream.put('%');
744039Sbinkertn@umich.edu            ptr += 2;
752SN/A            break;
762SN/A
772SN/A          case '\n':
784039Sbinkertn@umich.edu            stream << endl;
794039Sbinkertn@umich.edu            ++ptr;
802SN/A            break;
812SN/A          case '\r':
824039Sbinkertn@umich.edu            ++ptr;
834039Sbinkertn@umich.edu            if (*ptr != '\n')
844039Sbinkertn@umich.edu                stream << endl;
852SN/A            break;
862SN/A
874039Sbinkertn@umich.edu          default:
884039Sbinkertn@umich.edu            len = strcspn(ptr, "%\n\r\0");
894039Sbinkertn@umich.edu            stream.write(ptr, len);
904039Sbinkertn@umich.edu            ptr += len;
912SN/A            break;
922SN/A        }
932SN/A    }
942SN/A
954039Sbinkertn@umich.edu    return;
964039Sbinkertn@umich.edu
974039Sbinkertn@umich.edu  processing:
984039Sbinkertn@umich.edu    bool done = false;
994039Sbinkertn@umich.edu    bool end_number = false;
1004039Sbinkertn@umich.edu    bool have_precision = false;
1014039Sbinkertn@umich.edu    int number = 0;
1024039Sbinkertn@umich.edu
1034039Sbinkertn@umich.edu    stream.fill(' ');
1044039Sbinkertn@umich.edu    stream.flags((ios::fmtflags)0);
1054039Sbinkertn@umich.edu
1064039Sbinkertn@umich.edu    while (!done) {
1074039Sbinkertn@umich.edu        ++ptr;
1084039Sbinkertn@umich.edu        if (*ptr >= '0' && *ptr <= '9') {
1094039Sbinkertn@umich.edu            if (end_number)
1104039Sbinkertn@umich.edu                continue;
1114039Sbinkertn@umich.edu        } else if (number > 0)
1124039Sbinkertn@umich.edu            end_number = true;
1134039Sbinkertn@umich.edu
1144039Sbinkertn@umich.edu        switch (*ptr) {
1154039Sbinkertn@umich.edu          case 's':
1164039Sbinkertn@umich.edu            fmt.format = Format::string;
1174039Sbinkertn@umich.edu            done = true;
1184039Sbinkertn@umich.edu            break;
1194039Sbinkertn@umich.edu
1204039Sbinkertn@umich.edu          case 'c':
1214039Sbinkertn@umich.edu            fmt.format = Format::character;
1224039Sbinkertn@umich.edu            done = true;
1234039Sbinkertn@umich.edu            break;
1244039Sbinkertn@umich.edu
1254039Sbinkertn@umich.edu          case 'l':
1264039Sbinkertn@umich.edu            continue;
1274039Sbinkertn@umich.edu
1284039Sbinkertn@umich.edu          case 'p':
1294039Sbinkertn@umich.edu            fmt.format = Format::integer;
1304039Sbinkertn@umich.edu            fmt.base = Format::hex;
1314039Sbinkertn@umich.edu            fmt.alternate_form = true;
1324039Sbinkertn@umich.edu            done = true;
1334039Sbinkertn@umich.edu            break;
1344039Sbinkertn@umich.edu
1354039Sbinkertn@umich.edu          case 'X':
1364039Sbinkertn@umich.edu            fmt.uppercase = true;
1374039Sbinkertn@umich.edu          case 'x':
1384039Sbinkertn@umich.edu            fmt.base = Format::hex;
1394039Sbinkertn@umich.edu            fmt.format = Format::integer;
1404039Sbinkertn@umich.edu            done = true;
1414039Sbinkertn@umich.edu            break;
1424039Sbinkertn@umich.edu
1434039Sbinkertn@umich.edu          case 'o':
1444039Sbinkertn@umich.edu            fmt.base = Format::oct;
1454039Sbinkertn@umich.edu            fmt.format = Format::integer;
1464039Sbinkertn@umich.edu            done = true;
1474039Sbinkertn@umich.edu            break;
1484039Sbinkertn@umich.edu
1494039Sbinkertn@umich.edu          case 'd':
1504039Sbinkertn@umich.edu          case 'i':
1514039Sbinkertn@umich.edu          case 'u':
1524039Sbinkertn@umich.edu            fmt.format = Format::integer;
1534039Sbinkertn@umich.edu            done = true;
1544039Sbinkertn@umich.edu            break;
1554039Sbinkertn@umich.edu
1564039Sbinkertn@umich.edu          case 'G':
1574039Sbinkertn@umich.edu            fmt.uppercase = true;
1584039Sbinkertn@umich.edu          case 'g':
1594039Sbinkertn@umich.edu            fmt.format = Format::floating;
1604039Sbinkertn@umich.edu            fmt.float_format = Format::best;
1614039Sbinkertn@umich.edu            done = true;
1624039Sbinkertn@umich.edu            break;
1634039Sbinkertn@umich.edu
1644039Sbinkertn@umich.edu          case 'E':
1654039Sbinkertn@umich.edu            fmt.uppercase = true;
1664039Sbinkertn@umich.edu          case 'e':
1674039Sbinkertn@umich.edu            fmt.format = Format::floating;
1684039Sbinkertn@umich.edu            fmt.float_format = Format::scientific;
1694039Sbinkertn@umich.edu            done = true;
1704039Sbinkertn@umich.edu            break;
1714039Sbinkertn@umich.edu
1724039Sbinkertn@umich.edu          case 'f':
1734039Sbinkertn@umich.edu            fmt.format = Format::floating;
1744039Sbinkertn@umich.edu            fmt.float_format = Format::fixed;
1754039Sbinkertn@umich.edu            done = true;
1764039Sbinkertn@umich.edu            break;
1774039Sbinkertn@umich.edu
1784039Sbinkertn@umich.edu          case 'n':
1794039Sbinkertn@umich.edu            stream << "we don't do %n!!!\n";
1804039Sbinkertn@umich.edu            done = true;
1814039Sbinkertn@umich.edu            break;
1824039Sbinkertn@umich.edu
1834039Sbinkertn@umich.edu          case '#':
1844039Sbinkertn@umich.edu            fmt.alternate_form = true;
1854039Sbinkertn@umich.edu            break;
1864039Sbinkertn@umich.edu
1874039Sbinkertn@umich.edu          case '-':
1884039Sbinkertn@umich.edu            fmt.flush_left = true;
1894039Sbinkertn@umich.edu            break;
1904039Sbinkertn@umich.edu
1914039Sbinkertn@umich.edu          case '+':
1924039Sbinkertn@umich.edu            fmt.print_sign = true;
1934039Sbinkertn@umich.edu            break;
1944039Sbinkertn@umich.edu
1954039Sbinkertn@umich.edu          case ' ':
1964039Sbinkertn@umich.edu            fmt.blank_space = true;
1974039Sbinkertn@umich.edu            break;
1984039Sbinkertn@umich.edu
1994039Sbinkertn@umich.edu          case '.':
2004039Sbinkertn@umich.edu            fmt.width = number;
2014039Sbinkertn@umich.edu            fmt.precision = 0;
2024039Sbinkertn@umich.edu            have_precision = true;
2034039Sbinkertn@umich.edu            number = 0;
2044039Sbinkertn@umich.edu            end_number = false;
2054039Sbinkertn@umich.edu            break;
2064039Sbinkertn@umich.edu
2074039Sbinkertn@umich.edu          case '0':
2084039Sbinkertn@umich.edu            if (number == 0) {
2094039Sbinkertn@umich.edu                fmt.fill_zero = true;
2104039Sbinkertn@umich.edu                break;
2114039Sbinkertn@umich.edu            }
2124039Sbinkertn@umich.edu          case '1':
2134039Sbinkertn@umich.edu          case '2':
2144039Sbinkertn@umich.edu          case '3':
2154039Sbinkertn@umich.edu          case '4':
2164039Sbinkertn@umich.edu          case '5':
2174039Sbinkertn@umich.edu          case '6':
2184039Sbinkertn@umich.edu          case '7':
2194039Sbinkertn@umich.edu          case '8':
2204039Sbinkertn@umich.edu          case '9':
2214039Sbinkertn@umich.edu            number = number * 10 + (*ptr - '0');
2224039Sbinkertn@umich.edu            break;
2234039Sbinkertn@umich.edu
2244039Sbinkertn@umich.edu          case '%':
2254039Sbinkertn@umich.edu            assert("we shouldn't get here");
2264039Sbinkertn@umich.edu            break;
2274039Sbinkertn@umich.edu
2284039Sbinkertn@umich.edu          default:
2294039Sbinkertn@umich.edu            done = true;
2304039Sbinkertn@umich.edu            break;
2314039Sbinkertn@umich.edu        }
2324039Sbinkertn@umich.edu
2334039Sbinkertn@umich.edu        if (end_number) {
2344039Sbinkertn@umich.edu            if (have_precision)
2354039Sbinkertn@umich.edu                fmt.precision = number;
2364039Sbinkertn@umich.edu            else
2374039Sbinkertn@umich.edu                fmt.width = number;
2384039Sbinkertn@umich.edu
2394039Sbinkertn@umich.edu            end_number = false;
2404039Sbinkertn@umich.edu            number = 0;
2414039Sbinkertn@umich.edu        }
2422SN/A    }
2434039Sbinkertn@umich.edu
2444039Sbinkertn@umich.edu    ++ptr;
2452SN/A}
2462SN/A
2474039Sbinkertn@umich.eduvoid
2484039Sbinkertn@umich.eduPrint::end_args()
2492SN/A{
2504039Sbinkertn@umich.edu    size_t len;
2512SN/A
2524039Sbinkertn@umich.edu    while (*ptr) {
2534039Sbinkertn@umich.edu        switch (*ptr) {
2544039Sbinkertn@umich.edu          case '%':
2554039Sbinkertn@umich.edu            if (ptr[1] != '%')
2564039Sbinkertn@umich.edu                stream << "<extra arg>";
2572SN/A
2584039Sbinkertn@umich.edu            stream.put('%');
2594039Sbinkertn@umich.edu            ptr += 2;
2604039Sbinkertn@umich.edu            break;
2614039Sbinkertn@umich.edu
2624039Sbinkertn@umich.edu          case '\n':
2634039Sbinkertn@umich.edu            stream << endl;
2644039Sbinkertn@umich.edu            ++ptr;
2654039Sbinkertn@umich.edu            break;
2664039Sbinkertn@umich.edu          case '\r':
2674039Sbinkertn@umich.edu            ++ptr;
2684039Sbinkertn@umich.edu            if (*ptr != '\n')
2694039Sbinkertn@umich.edu                stream << endl;
2704039Sbinkertn@umich.edu            break;
2714039Sbinkertn@umich.edu
2724039Sbinkertn@umich.edu          default:
2734039Sbinkertn@umich.edu            len = strcspn(ptr, "%\n\r\0");
2744039Sbinkertn@umich.edu            stream.write(ptr, len);
2754039Sbinkertn@umich.edu            ptr += len;
2764039Sbinkertn@umich.edu            break;
2774039Sbinkertn@umich.edu        }
2784039Sbinkertn@umich.edu    }
2794039Sbinkertn@umich.edu
2804039Sbinkertn@umich.edu    stream.flags(saved_flags);
2814039Sbinkertn@umich.edu    stream.fill(saved_fill);
2824039Sbinkertn@umich.edu    stream.precision(saved_precision);
2832SN/A}
2842SN/A
2854039Sbinkertn@umich.edu/* end namespace cp */ }
286