Get rid of the gross operator,()/variadic macro hack

that made ccprintf and friends work, turn it into a
normal function (though it still has a slightly strange
implementation.)  All instances of variadic macros
are not yet removed, but I know how, and it will happen.

One side effect of this new implementation is that a
cprintf statement can now only have 16 parameters, though
it's easy enough to raise this number if needed.

--HG--
extra : convert_revision : 85cb3c17f8e2ecf9cd2f31ea80a760a28ea127a7
This commit is contained in:
Nathan Binkert
2007-02-07 22:11:30 -08:00
parent af698e8b05
commit 1f834b569c
8 changed files with 750 additions and 432 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002-2005 The Regents of The University of Michigan
* Copyright (c) 2002-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,142 +29,135 @@
* Steve Reinhardt
*/
#ifndef __CPRINTF_HH__
#define __CPRINTF_HH__
#ifndef __BASE_CPRINTF_HH__
#define __BASE_CPRINTF_HH__
#include <ios>
#include <iostream>
#include <list>
#include <string>
#include "base/varargs.hh"
#include "base/cprintf_formats.hh"
namespace cp {
class ArgList
#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print)
#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print)
struct Print
{
private:
class Base
{
public:
virtual ~Base() {}
virtual void process(std::ostream &out, Format &fmt) = 0;
};
template <typename T>
class Node : public Base
{
public:
const T &data;
public:
Node(const T &d) : data(d) {}
virtual void process(std::ostream &out, Format &fmt) {
switch (fmt.format) {
case Format::character:
format_char(out, data, fmt);
break;
case Format::integer:
format_integer(out, data, fmt);
break;
case Format::floating:
format_float(out, data, fmt);
break;
case Format::string:
format_string(out, data, fmt);
break;
default:
out << "<bad format>";
break;
}
}
};
typedef std::list<Base *> list_t;
protected:
list_t objects;
std::ostream *stream;
std::ostream &stream;
const char *format;
const char *ptr;
std::ios::fmtflags saved_flags;
char saved_fill;
int saved_precision;
void process(Format &fmt);
public:
ArgList() : stream(&std::cout) {}
~ArgList();
Print(std::ostream &stream, const std::string &format);
Print(std::ostream &stream, const char *format);
~Print();
template<class T>
void append(const T &data) {
Base *obj = new ArgList::Node<T>(data);
objects.push_back(obj);
template <typename T>
void
add_arg(const T &data)
{
Format fmt;
process(fmt);
switch (fmt.format) {
case Format::character:
format_char(stream, data, fmt);
break;
case Format::integer:
format_integer(stream, data, fmt);
break;
case Format::floating:
format_float(stream, data, fmt);
break;
case Format::string:
format_string(stream, data, fmt);
break;
default:
stream << "<bad format>";
break;
}
}
template<class T>
void prepend(const T &data) {
Base *obj = new ArgList::Node<T>(data);
objects.push_front(obj);
}
void dump(const std::string &format);
void dump(std::ostream &strm, const std::string &fmt)
{ stream = &strm; dump(fmt); }
std::string dumpToString(const std::string &format);
friend ArgList &operator<<(std::ostream &str, ArgList &list);
void end_args();
};
template<class T>
inline ArgList &
operator,(ArgList &alist, const T &data)
/* end namespace cp */ }
typedef VarArgs::List<cp::Print> CPrintfArgsList;
inline void
ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args)
{
alist.append(data);
return alist;
cp::Print print(stream, format);
args.add_args(print);
}
class ArgListNull {
};
inline ArgList &
operator,(ArgList &alist, ArgListNull)
{ return alist; }
//
// cprintf(format, args, ...) prints to cout
// (analogous to printf())
//
inline void
__cprintf(const std::string &format, ArgList &args)
{ args.dump(format); delete &args; }
#define __cprintf__(format, ...) \
cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__))
#define cprintf(...) \
__cprintf__(__VA_ARGS__, cp::ArgListNull())
ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION)
{
cp::Print print(stream, format);
VARARGS_ADDARGS(print);
}
//
// ccprintf(stream, format, args, ...) prints to the specified stream
// (analogous to fprintf())
//
inline void
__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
{ args.dump(stream, format); delete &args; }
#define __ccprintf__(stream, format, ...) \
cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__))
#define ccprintf(stream, ...) \
__ccprintf__(stream, __VA_ARGS__, cp::ArgListNull())
cprintf(const char *format, CPRINTF_DECLARATION)
{
ccprintf(std::cout, format, VARARGS_ALLARGS);
}
//
// csprintf(format, args, ...) returns a string
// (roughly analogous to sprintf())
//
inline std::string
__csprintf(const std::string &format, ArgList &args)
{ std::string s = args.dumpToString(format); delete &args; return s; }
#define __csprintf__(format, ...) \
cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__))
#define csprintf(...) \
__csprintf__(__VA_ARGS__, cp::ArgListNull())
csprintf(const char *format, CPRINTF_DECLARATION)
{
std::stringstream stream;
ccprintf(stream, format, VARARGS_ALLARGS);
return stream.str();
}
/*
* functions again with std::string. We have both so we don't waste
* time converting const char * to std::string since we don't take
* advantage of it.
*/
inline void
ccprintf(std::ostream &stream, const std::string &format,
const CPrintfArgsList &args)
{
ccprintf(stream, format.c_str(), args);
}
inline void
ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION)
{
ccprintf(stream, format, VARARGS_ALLARGS);
}
inline void
cprintf(const std::string &format, CPRINTF_DECLARATION)
{
ccprintf(std::cout, format, VARARGS_ALLARGS);
}
inline std::string
csprintf(const std::string &format, CPRINTF_DECLARATION)
{
std::stringstream stream;
ccprintf(stream, format, VARARGS_ALLARGS);
return stream.str();
}
#endif // __CPRINTF_HH__