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