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
@ -39,232 +39,247 @@ using namespace std;
namespace cp {
ArgList::~ArgList()
Print::Print(std::ostream &stream, const std::string &format)
: stream(stream), format(format.c_str()), ptr(format.c_str())
{
saved_flags = stream.flags();
saved_fill = stream.fill();
saved_precision = stream.precision();
}
Print::Print(std::ostream &stream, const char *format)
: stream(stream), format(format), ptr(format)
{
saved_flags = stream.flags();
saved_fill = stream.fill();
saved_precision = stream.precision();
}
Print::~Print()
{
while (!objects.empty()) {
delete objects.front();
objects.pop_front();
}
}
void
ArgList::dump(const string &format)
Print::process(Format &fmt)
{
list_t::iterator iter = objects.begin();
list_t::iterator end = objects.end();
size_t len;
const char *p = format.c_str();
while (*ptr) {
switch (*ptr) {
case '%':
if (ptr[1] != '%')
goto processing;
stream->fill(' ');
stream->flags((ios::fmtflags)0);
while (*p) {
switch (*p) {
case '%': {
if (p[1] == '%') {
*stream << '%';
p += 2;
continue;
}
Format fmt;
bool done = false;
bool end_number = false;
bool have_precision = false;
int number = 0;
while (!done) {
++p;
if (*p >= '0' && *p <= '9') {
if (end_number)
continue;
} else if (number > 0)
end_number = true;
switch (*p) {
case 's':
fmt.format = Format::string;
done = true;
break;
case 'c':
fmt.format = Format::character;
done = true;
break;
case 'l':
continue;
case 'p':
fmt.format = Format::integer;
fmt.base = Format::hex;
fmt.alternate_form = true;
done = true;
break;
case 'X':
fmt.uppercase = true;
case 'x':
fmt.base = Format::hex;
fmt.format = Format::integer;
done = true;
break;
case 'o':
fmt.base = Format::oct;
fmt.format = Format::integer;
done = true;
break;
case 'd':
case 'i':
case 'u':
fmt.format = Format::integer;
done = true;
break;
case 'G':
fmt.uppercase = true;
case 'g':
fmt.format = Format::floating;
fmt.float_format = Format::best;
done = true;
break;
case 'E':
fmt.uppercase = true;
case 'e':
fmt.format = Format::floating;
fmt.float_format = Format::scientific;
done = true;
break;
case 'f':
fmt.format = Format::floating;
fmt.float_format = Format::fixed;
done = true;
break;
case 'n':
*stream << "we don't do %n!!!\n";
done = true;
break;
case '#':
fmt.alternate_form = true;
break;
case '-':
fmt.flush_left = true;
break;
case '+':
fmt.print_sign = true;
break;
case ' ':
fmt.blank_space = true;
break;
case '.':
fmt.width = number;
fmt.precision = 0;
have_precision = true;
number = 0;
end_number = false;
break;
case '0':
if (number == 0) {
fmt.fill_zero = true;
break;
}
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
number = number * 10 + (*p - '0');
break;
case '%':
assert("we shouldn't get here");
break;
default:
done = true;
break;
}
if (end_number) {
if (have_precision)
fmt.precision = number;
else
fmt.width = number;
end_number = false;
number = 0;
}
}
if (iter != end)
{
ios::fmtflags saved_flags = stream->flags();
char old_fill = stream->fill();
int old_precision = stream->precision();
(*iter)->process(*stream, fmt);
stream->flags(saved_flags);
stream->fill(old_fill);
stream->precision(old_precision);
++iter;
} else {
*stream << "<missing arg for format>";
}
++p;
}
stream.put('%');
ptr += 2;
break;
case '\n':
*stream << endl;
++p;
stream << endl;
++ptr;
break;
case '\r':
++p;
if (*p != '\n')
*stream << endl;
++ptr;
if (*ptr != '\n')
stream << endl;
break;
default: {
size_t len = strcspn(p, "%\n\r\0");
stream->write(p, len);
p += len;
}
default:
len = strcspn(ptr, "%\n\r\0");
stream.write(ptr, len);
ptr += len;
break;
}
}
while (iter != end) {
*stream << "<extra arg>";
++iter;
return;
processing:
bool done = false;
bool end_number = false;
bool have_precision = false;
int number = 0;
stream.fill(' ');
stream.flags((ios::fmtflags)0);
while (!done) {
++ptr;
if (*ptr >= '0' && *ptr <= '9') {
if (end_number)
continue;
} else if (number > 0)
end_number = true;
switch (*ptr) {
case 's':
fmt.format = Format::string;
done = true;
break;
case 'c':
fmt.format = Format::character;
done = true;
break;
case 'l':
continue;
case 'p':
fmt.format = Format::integer;
fmt.base = Format::hex;
fmt.alternate_form = true;
done = true;
break;
case 'X':
fmt.uppercase = true;
case 'x':
fmt.base = Format::hex;
fmt.format = Format::integer;
done = true;
break;
case 'o':
fmt.base = Format::oct;
fmt.format = Format::integer;
done = true;
break;
case 'd':
case 'i':
case 'u':
fmt.format = Format::integer;
done = true;
break;
case 'G':
fmt.uppercase = true;
case 'g':
fmt.format = Format::floating;
fmt.float_format = Format::best;
done = true;
break;
case 'E':
fmt.uppercase = true;
case 'e':
fmt.format = Format::floating;
fmt.float_format = Format::scientific;
done = true;
break;
case 'f':
fmt.format = Format::floating;
fmt.float_format = Format::fixed;
done = true;
break;
case 'n':
stream << "we don't do %n!!!\n";
done = true;
break;
case '#':
fmt.alternate_form = true;
break;
case '-':
fmt.flush_left = true;
break;
case '+':
fmt.print_sign = true;
break;
case ' ':
fmt.blank_space = true;
break;
case '.':
fmt.width = number;
fmt.precision = 0;
have_precision = true;
number = 0;
end_number = false;
break;
case '0':
if (number == 0) {
fmt.fill_zero = true;
break;
}
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
number = number * 10 + (*ptr - '0');
break;
case '%':
assert("we shouldn't get here");
break;
default:
done = true;
break;
}
if (end_number) {
if (have_precision)
fmt.precision = number;
else
fmt.width = number;
end_number = false;
number = 0;
}
}
++ptr;
}
string
ArgList::dumpToString(const string &format)
void
Print::end_args()
{
stringstream ss;
size_t len;
dump(ss, format);
while (*ptr) {
switch (*ptr) {
case '%':
if (ptr[1] != '%')
stream << "<extra arg>";
return ss.str();
stream.put('%');
ptr += 2;
break;
case '\n':
stream << endl;
++ptr;
break;
case '\r':
++ptr;
if (*ptr != '\n')
stream << endl;
break;
default:
len = strcspn(ptr, "%\n\r\0");
stream.write(ptr, len);
ptr += len;
break;
}
}
stream.flags(saved_flags);
stream.fill(saved_fill);
stream.precision(saved_precision);
}
}
/* end namespace cp */ }

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__

View file

@ -28,8 +28,8 @@
* Authors: Nathan Binkert
*/
#ifndef __CPRINTF_FORMATS_HH__
#define __CPRINTF_FORMATS_HH__
#ifndef __BASE_CPRINTF_FORMATS_HH__
#define __BASE_CPRINTF_FORMATS_HH__
#include <sstream>
#include <ostream>

View file

@ -36,91 +36,99 @@
#include "base/misc.hh"
#include "base/output.hh"
#include "base/trace.hh"
#include "base/varargs.hh"
#include "sim/host.hh"
#include "sim/root.hh"
using namespace std;
void
__panic(const string &format, cp::ArgList &args, const char *func,
const char *file, int line)
__panic(const char *func, const char *file, int line, const char *fmt,
CPRINTF_DEFINITION)
{
string fmt = "panic: " + format;
switch (fmt[fmt.size() - 1]) {
string format = "panic: ";
format += fmt;
switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
fmt += "\n";
format += "\n";
}
fmt += " @ cycle %d\n[%s:%s, line %d]\n";
format += " @ cycle %d\n[%s:%s, line %d]\n";
args.append(curTick);
args.append(func);
args.append(file);
args.append(line);
args.dump(cerr, fmt);
CPrintfArgsList args(VARARGS_ALLARGS);
delete &args;
args.push_back(curTick);
args.push_back(func);
args.push_back(file);
args.push_back(line);
ccprintf(cerr, format.c_str(), args);
abort();
}
void
__fatal(const string &format, cp::ArgList &args, const char *func,
const char *file, int line)
__fatal(const char *func, const char *file, int line, const char *fmt,
CPRINTF_DEFINITION)
{
string fmt = "fatal: " + format;
CPrintfArgsList args(VARARGS_ALLARGS);
string format = "fatal: ";
format += fmt;
switch (fmt[fmt.size() - 1]) {
switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
fmt += "\n";
format += "\n";
}
fmt += " @ cycle %d\n[%s:%s, line %d]\n";
fmt += "Memory Usage: %ld KBytes\n";
format += " @ cycle %d\n[%s:%s, line %d]\n";
format += "Memory Usage: %ld KBytes\n";
args.append(curTick);
args.append(func);
args.append(file);
args.append(line);
args.append(memUsage());
args.dump(cerr, fmt);
args.push_back(curTick);
args.push_back(func);
args.push_back(file);
args.push_back(line);
args.push_back(memUsage());
delete &args;
ccprintf(cerr, format.c_str(), args);
exit(1);
}
void
__warn(const string &format, cp::ArgList &args, const char *func,
const char *file, int line)
__warn(const char *func, const char *file, int line, const char *fmt,
CPRINTF_DEFINITION)
{
string fmt = "warn: " + format;
string format = "warn: ";
format += fmt;
switch (fmt[fmt.size() - 1]) {
switch (format[format.size() - 1]) {
case '\n':
case '\r':
break;
default:
fmt += "\n";
format += "\n";
}
#ifdef VERBOSE_WARN
fmt += " @ cycle %d\n[%s:%s, line %d]\n";
args.append(curTick);
args.append(func);
args.append(file);
args.append(line);
format += " @ cycle %d\n[%s:%s, line %d]\n";
#endif
args.dump(cerr, fmt);
if (simout.isFile(*outputStream))
args.dump(*outputStream, fmt);
CPrintfArgsList args(VARARGS_ALLARGS);
delete &args;
#ifdef VERBOSE_WARN
args.push_back(curTick);
args.push_back(func);
args.push_back(file);
args.push_back(line);
#endif
ccprintf(cerr, format.c_str(), args);
if (simout.isFile(*outputStream))
ccprintf(*outputStream, format.c_str(), args);
}

View file

@ -32,9 +32,11 @@
#ifndef __MISC_HH__
#define __MISC_HH__
#include <assert.h>
#include <cassert>
#include "base/compiler.hh"
#include "base/cprintf.hh"
#include "base/varargs.hh"
#if defined(__SUNPRO_CC)
#define __FUNCTION__ "how to fix me?"
@ -47,14 +49,20 @@
// calls abort which can dump core or enter the debugger.
//
//
void __panic(const std::string&, cp::ArgList &, const char*, const char*, int)
M5_ATTR_NORETURN;
#define __panic__(format, ...) \
__panic(format, (*(new cp::ArgList), __VA_ARGS__), \
__FUNCTION__ , __FILE__, __LINE__)
#define panic(...) \
__panic__(__VA_ARGS__, cp::ArgListNull())
void __panic(const char *func, const char *file, int line, const char *format,
CPRINTF_DECLARATION) M5_ATTR_NORETURN;
void __panic(const char *func, const char *file, int line,
const std::string &format, CPRINTF_DECLARATION)
M5_ATTR_NORETURN;
inline void
__panic(const char *func, const char *file, int line,
const std::string &format, CPRINTF_DEFINITION)
{
__panic(func, file, line, format.c_str(), VARARGS_ALLARGS);
}
M5_PRAGMA_NORETURN(__panic)
#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
//
// This implements a cprintf based fatal() function. fatal() should
@ -64,34 +72,43 @@ M5_PRAGMA_NORETURN(__panic)
// "normal" exit with an error code, as opposed to abort() like
// panic() does.
//
void __fatal(const std::string&, cp::ArgList &, const char*, const char*, int)
void __fatal(const char *func, const char *file, int line, const char *format,
CPRINTF_DECLARATION) M5_ATTR_NORETURN;
void __fatal(const char *func, const char *file, int line,
const std::string &format, CPRINTF_DECLARATION)
M5_ATTR_NORETURN;
#define __fatal__(format, ...) \
__fatal(format, (*(new cp::ArgList), __VA_ARGS__), \
__FUNCTION__ , __FILE__, __LINE__)
#define fatal(...) \
__fatal__(__VA_ARGS__, cp::ArgListNull())
inline void
__fatal(const char *func, const char *file, int line,
const std::string &format, CPRINTF_DEFINITION)
{
__fatal(func, file, line, format.c_str(), VARARGS_ALLARGS);
}
M5_PRAGMA_NORETURN(__fatal)
#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
//
// This implements a cprintf based warn
//
void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
#define __warn__(format, ...) \
__warn(format, (*(new cp::ArgList), __VA_ARGS__), \
__FUNCTION__ , __FILE__, __LINE__)
#define warn(...) \
__warn__(__VA_ARGS__, cp::ArgListNull())
void __warn(const char *func, const char *file, int line, const char *format,
CPRINTF_DECLARATION);
inline void
__warn(const char *func, const char *file, int line, const std::string &format,
CPRINTF_DECLARATION)
{
__warn(func, file, line, format, VARARGS_ALLARGS);
}
#define warn(...) __warn(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
// Only print the warning message the first time it is seen. This
// doesn't check the warning string itself, it just only lets one
// warning come from the statement. So, even if the arguments change
// and that would have resulted in a different warning message,
// subsequent messages would still be supressed.
#define warn_once(...) do { \
#define warn_once(...) do { \
static bool once = false; \
if (!once) { \
__warn__(__VA_ARGS__, cp::ArgListNull()); \
warn(__VA_ARGS__); \
once = true; \
} \
} while (0)
@ -99,10 +116,10 @@ void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
//
// assert() that prints out the current cycle
//
#define m5_assert(TEST) \
if (!(TEST)) { \
std::cerr << "Assertion failure, curTick = " << curTick << std::endl; \
} \
assert(TEST);
#define m5_assert(TEST) do { \
if (!(TEST)) \
ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \
assert(TEST); \
} while (0)
#endif // __MISC_HH__

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -39,6 +39,7 @@
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/str.hh"
#include "base/varargs.hh"
using namespace std;
@ -153,9 +154,7 @@ Log::dump(ostream &os)
}
PrintfRecord::~PrintfRecord()
{
delete &args;
}
{}
void
PrintfRecord::dump(ostream &os)
@ -164,17 +163,17 @@ PrintfRecord::dump(ostream &os)
if (!name.empty()) {
fmt = "%s: " + fmt;
args.prepend(name);
args.push_front(name);
}
if (cycle != (Tick)-1) {
fmt = "%7d: " + fmt;
args.prepend(cycle);
args.push_front(cycle);
}
fmt += format;
args.dump(os, fmt);
ccprintf(os, fmt.c_str(), args);
os.flush();
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2005 The Regents of The University of Michigan
* Copyright (c) 2001-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -81,14 +81,15 @@ namespace Trace {
class PrintfRecord : public Record
{
private:
const char *format;
const std::string &name;
cp::ArgList &args;
const char *format;
CPrintfArgsList args;
public:
PrintfRecord(const char *_format, cp::ArgList &_args,
Tick cycle, const std::string &_name)
: Record(cycle), format(_format), name(_name), args(_args)
PrintfRecord(Tick cycle, const std::string &_name, const char *_format,
CPRINTF_DECLARATION)
: Record(cycle), name(_name), format(_format),
args(VARARGS_ALLARGS)
{
}
@ -121,7 +122,6 @@ namespace Trace {
Record **wrapRecPtr; // &buffer[size], for quick wrap check
public:
Log();
~Log();
@ -136,22 +136,28 @@ namespace Trace {
extern ObjectMatch ignore;
inline void
dprintf(const char *format, cp::ArgList &args, Tick cycle,
const std::string &name)
dprintf(Tick when, const std::string &name, const char *format,
CPRINTF_DECLARATION)
{
if (name.empty() || !ignore.match(name))
theLog.append(new Trace::PrintfRecord(format, args, cycle, name));
if (!name.empty() && ignore.match(name))
return;
theLog.append(new Trace::PrintfRecord(when, name, format,
VARARGS_ALLARGS));
}
inline void
dataDump(Tick cycle, const std::string &name, const void *data, int len)
dataDump(Tick when, const std::string &name, const void *data, int len)
{
theLog.append(new Trace::DataRecord(cycle, name, data, len));
theLog.append(new Trace::DataRecord(when, name, data, len));
}
extern const std::string DefaultName;
};
std::ostream &DebugOut();
// This silly little class allows us to wrap a string in a functor
// object so that we can give a name() that DPRINTF will like
struct StringWrap
@ -162,7 +168,6 @@ struct StringWrap
};
inline const std::string &name() { return Trace::DefaultName; }
std::ostream &DebugOut();
//
// DPRINTF is a debugging trace facility that allows one to
@ -178,47 +183,36 @@ std::ostream &DebugOut();
#define DTRACE(x) (Trace::IsOn(Trace::x))
#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut()
#define DDUMP(x, data, count) \
do { \
if (Trace::IsOn(Trace::x)) \
Trace::dataDump(curTick, name(), data, count); \
#define DDUMP(x, data, count) do { \
if (DTRACE(x)) \
Trace::dataDump(curTick, name(), data, count); \
} while (0)
#define __dprintf(cycle, name, format, ...) \
Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name)
#define DPRINTF(x, ...) \
do { \
if (Trace::IsOn(Trace::x)) \
__dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
#define DPRINTF(x, args...) do { \
if (DTRACE(x)) \
Trace::dprintf(curTick, name(), args); \
} while (0)
#define DPRINTFR(x, ...) \
do { \
if (Trace::IsOn(Trace::x)) \
__dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull()); \
#define DPRINTFR(x, args...) do { \
if (DTRACE(x)) \
Trace::dprintf((Tick)-1, std::string(), args); \
} while (0)
#define DPRINTFN(...) \
do { \
__dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
#define DPRINTFN(args...) do { \
Trace::dprintf(curTick, name(), args); \
} while (0)
#define DPRINTFNR(...) \
do { \
__dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \
#define DPRINTFNR(args...) do { \
Trace::dprintf((Tick)-1, string(), args); \
} while (0)
#else // !TRACING_ON
#define DTRACE(x) (false)
#define DCOUT(x) if (0) DebugOut()
#define DPRINTF(x, ...) do {} while (0)
#define DPRINTFR(...) do {} while (0)
#define DPRINTFN(...) do {} while (0)
#define DPRINTFNR(...) do {} while (0)
#define DPRINTF(x, args...) do {} while (0)
#define DPRINTFR(args...) do {} while (0)
#define DPRINTFN(args...) do {} while (0)
#define DPRINTFNR(args...) do {} while (0)
#define DDUMP(x, data, count) do {} while (0)
#endif // TRACING_ON

292
src/base/varargs.hh Normal file
View file

@ -0,0 +1,292 @@
/*
* Copyright (c) 2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution;
* neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors: Nathan Binkert
*/
#ifndef __BASE_VARARGS_HH__
#define __BASE_VARARGS_HH__
#include "base/refcnt.hh"
#define VARARGS_DECLARATION(receiver) \
VarArgs::Argument<receiver> a01 = VarArgs::Null(), \
VarArgs::Argument<receiver> a02 = VarArgs::Null(), \
VarArgs::Argument<receiver> a03 = VarArgs::Null(), \
VarArgs::Argument<receiver> a04 = VarArgs::Null(), \
VarArgs::Argument<receiver> a05 = VarArgs::Null(), \
VarArgs::Argument<receiver> a06 = VarArgs::Null(), \
VarArgs::Argument<receiver> a07 = VarArgs::Null(), \
VarArgs::Argument<receiver> a08 = VarArgs::Null(), \
VarArgs::Argument<receiver> a09 = VarArgs::Null(), \
VarArgs::Argument<receiver> a10 = VarArgs::Null(), \
VarArgs::Argument<receiver> a11 = VarArgs::Null(), \
VarArgs::Argument<receiver> a12 = VarArgs::Null(), \
VarArgs::Argument<receiver> a13 = VarArgs::Null(), \
VarArgs::Argument<receiver> a14 = VarArgs::Null(), \
VarArgs::Argument<receiver> a15 = VarArgs::Null(), \
VarArgs::Argument<receiver> a16 = VarArgs::Null()
#define VARARGS_DEFINITION(receiver) \
VarArgs::Argument<receiver> a01, \
VarArgs::Argument<receiver> a02, \
VarArgs::Argument<receiver> a03, \
VarArgs::Argument<receiver> a04, \
VarArgs::Argument<receiver> a05, \
VarArgs::Argument<receiver> a06, \
VarArgs::Argument<receiver> a07, \
VarArgs::Argument<receiver> a08, \
VarArgs::Argument<receiver> a09, \
VarArgs::Argument<receiver> a10, \
VarArgs::Argument<receiver> a11, \
VarArgs::Argument<receiver> a12, \
VarArgs::Argument<receiver> a13, \
VarArgs::Argument<receiver> a14, \
VarArgs::Argument<receiver> a15, \
VarArgs::Argument<receiver> a16
#define VARARGS_ALLARGS \
a01, a02, a03, a04, a05, a06, a07, a08, \
a09, a10, a11, a12, a13, a14, a15, a16
#define VARARGS_ADDARGS(receiver) do { \
do { \
if (!a01) break; \
a01.add_arg(receiver); \
if (!a02) break; \
a02.add_arg(receiver); \
if (!a03) break; \
a03.add_arg(receiver); \
if (!a04) break; \
a04.add_arg(receiver); \
if (!a05) break; \
a05.add_arg(receiver); \
if (!a06) break; \
a06.add_arg(receiver); \
if (!a07) break; \
a07.add_arg(receiver); \
if (!a08) break; \
a08.add_arg(receiver); \
if (!a09) break; \
a09.add_arg(receiver); \
if (!a10) break; \
a10.add_arg(receiver); \
if (!a11) break; \
a11.add_arg(receiver); \
if (!a12) break; \
a12.add_arg(receiver); \
if (!a13) break; \
a13.add_arg(receiver); \
if (!a14) break; \
a14.add_arg(receiver); \
if (!a15) break; \
a15.add_arg(receiver); \
if (!a16) break; \
a16.add_arg(receiver); \
} while (0); \
receiver.end_args(); \
} while (0)
namespace VarArgs {
struct Null {};
template <typename T>
struct Traits
{
enum { enabled = true };
};
template <>
struct Traits<Null>
{
enum { enabled = false };
};
template <class RECV>
struct Base : public RefCounted
{
virtual void add_arg(RECV &receiver) const = 0;
};
template <typename T, class RECV>
struct Any : public Base<RECV>
{
const T &argument;
Any(const T &arg) : argument(arg) {}
virtual void
add_arg(RECV &receiver) const
{
receiver.add_arg(argument);
}
};
template <class RECV>
struct Argument : public RefCountingPtr<Base<RECV> >
{
typedef RefCountingPtr<Base<RECV> > Base;
Argument() { }
Argument(const Null &null) { }
template <typename T>
Argument(const T& arg) : Base(new Any<T, RECV>(arg)) { }
void
add_arg(RECV &receiver) const
{
if (this->data)
this->data->add_arg(receiver);
}
};
template<class RECV>
class List
{
public:
typedef Argument<RECV> Argument;
typedef std::list<Argument> list;
typedef typename list::iterator iterator;
typedef typename list::const_iterator const_iterator;
typedef typename list::size_type size_type;
protected:
list l;
public:
List() {}
List(Argument a01, Argument a02, Argument a03, Argument a04,
Argument a05, Argument a06, Argument a07, Argument a08,
Argument a09, Argument a10, Argument a11, Argument a12,
Argument a13, Argument a14, Argument a15, Argument a16)
{
if (!a01) return;
l.push_back(a01);
if (!a02) return;
l.push_back(a02);
if (!a03) return;
l.push_back(a03);
if (!a04) return;
l.push_back(a04);
if (!a05) return;
l.push_back(a05);
if (!a06) return;
l.push_back(a06);
if (!a07) return;
l.push_back(a07);
if (!a08) return;
l.push_back(a08);
if (!a09) return;
l.push_back(a09);
if (!a10) return;
l.push_back(a10);
if (!a11) return;
l.push_back(a11);
if (!a12) return;
l.push_back(a12);
if (!a13) return;
l.push_back(a13);
if (!a14) return;
l.push_back(a14);
if (!a15) return;
l.push_back(a15);
if (!a16) return;
l.push_back(a16);
}
size_type size() const { return l.size(); }
bool empty() const { return l.empty(); }
iterator begin() { return l.begin(); }
const_iterator begin() const { return l.begin(); }
iterator end() { return l.end(); }
const_iterator end() const { return l.end(); }
void
push_back(const Argument &arg)
{
if (arg)
l.push_back(arg);
}
void
push_front(const Argument &arg)
{
if (arg)
l.push_front(arg);
}
template <typename T>
void
push_back(const T &arg)
{
if (Traits<T>::enabled)
l.push_back(arg);
}
template <typename T>
void
push_front(const T &arg)
{
if (Traits<T>::enabled)
l.push_front(arg);
}
Argument& front() { return l.front(); }
const Argument& front() const { return l.front(); }
Argument& back() { return l.back(); }
const Argument& back() const { return l.back(); }
void erase(iterator position) { return l.erase(position); }
void erase(iterator first, iterator last) { return l.erase(first, last); }
void clear() { return l.clear(); }
void pop_front() { return l.pop_front(); }
void pop_back() { return l.pop_back(); }
void reverse() { l.reverse(); }
/*
* Functions specific to variable arguments
*/
void
add_args(RECV &recv) const
{
const_iterator i = l.begin();
const_iterator end = l.end();
while (i != end) {
i->add_arg(recv);
++i;
}
recv.end_args();
}
};
/* end namespace VarArgs */ }
#endif /* __BASE_VARARGS_HH__ */