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:
parent
af698e8b05
commit
1f834b569c
8 changed files with 750 additions and 432 deletions
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -39,49 +39,79 @@ using namespace std;
|
||||||
|
|
||||||
namespace cp {
|
namespace cp {
|
||||||
|
|
||||||
ArgList::~ArgList()
|
Print::Print(std::ostream &stream, const std::string &format)
|
||||||
|
: stream(stream), format(format.c_str()), ptr(format.c_str())
|
||||||
{
|
{
|
||||||
while (!objects.empty()) {
|
saved_flags = stream.flags();
|
||||||
delete objects.front();
|
saved_fill = stream.fill();
|
||||||
objects.pop_front();
|
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()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ArgList::dump(const string &format)
|
Print::process(Format &fmt)
|
||||||
{
|
{
|
||||||
list_t::iterator iter = objects.begin();
|
size_t len;
|
||||||
list_t::iterator end = objects.end();
|
|
||||||
|
|
||||||
const char *p = format.c_str();
|
while (*ptr) {
|
||||||
|
switch (*ptr) {
|
||||||
|
case '%':
|
||||||
|
if (ptr[1] != '%')
|
||||||
|
goto processing;
|
||||||
|
|
||||||
stream->fill(' ');
|
stream.put('%');
|
||||||
stream->flags((ios::fmtflags)0);
|
ptr += 2;
|
||||||
|
break;
|
||||||
|
|
||||||
while (*p) {
|
case '\n':
|
||||||
switch (*p) {
|
stream << endl;
|
||||||
case '%': {
|
++ptr;
|
||||||
if (p[1] == '%') {
|
break;
|
||||||
*stream << '%';
|
case '\r':
|
||||||
p += 2;
|
++ptr;
|
||||||
continue;
|
if (*ptr != '\n')
|
||||||
|
stream << endl;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
len = strcspn(ptr, "%\n\r\0");
|
||||||
|
stream.write(ptr, len);
|
||||||
|
ptr += len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Format fmt;
|
return;
|
||||||
|
|
||||||
|
processing:
|
||||||
bool done = false;
|
bool done = false;
|
||||||
bool end_number = false;
|
bool end_number = false;
|
||||||
bool have_precision = false;
|
bool have_precision = false;
|
||||||
int number = 0;
|
int number = 0;
|
||||||
|
|
||||||
|
stream.fill(' ');
|
||||||
|
stream.flags((ios::fmtflags)0);
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
++p;
|
++ptr;
|
||||||
if (*p >= '0' && *p <= '9') {
|
if (*ptr >= '0' && *ptr <= '9') {
|
||||||
if (end_number)
|
if (end_number)
|
||||||
continue;
|
continue;
|
||||||
} else if (number > 0)
|
} else if (number > 0)
|
||||||
end_number = true;
|
end_number = true;
|
||||||
|
|
||||||
switch (*p) {
|
switch (*ptr) {
|
||||||
case 's':
|
case 's':
|
||||||
fmt.format = Format::string;
|
fmt.format = Format::string;
|
||||||
done = true;
|
done = true;
|
||||||
|
@ -146,7 +176,7 @@ ArgList::dump(const string &format)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
*stream << "we don't do %n!!!\n";
|
stream << "we don't do %n!!!\n";
|
||||||
done = true;
|
done = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -188,7 +218,7 @@ ArgList::dump(const string &format)
|
||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
number = number * 10 + (*p - '0');
|
number = number * 10 + (*ptr - '0');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
|
@ -211,60 +241,45 @@ ArgList::dump(const string &format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iter != end)
|
++ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Print::end_args()
|
||||||
{
|
{
|
||||||
ios::fmtflags saved_flags = stream->flags();
|
size_t len;
|
||||||
char old_fill = stream->fill();
|
|
||||||
int old_precision = stream->precision();
|
|
||||||
|
|
||||||
(*iter)->process(*stream, fmt);
|
while (*ptr) {
|
||||||
|
switch (*ptr) {
|
||||||
|
case '%':
|
||||||
|
if (ptr[1] != '%')
|
||||||
|
stream << "<extra arg>";
|
||||||
|
|
||||||
stream->flags(saved_flags);
|
stream.put('%');
|
||||||
stream->fill(old_fill);
|
ptr += 2;
|
||||||
stream->precision(old_precision);
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
} else {
|
|
||||||
*stream << "<missing arg for format>";
|
|
||||||
}
|
|
||||||
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
*stream << endl;
|
stream << endl;
|
||||||
++p;
|
++ptr;
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case '\r':
|
||||||
++p;
|
++ptr;
|
||||||
if (*p != '\n')
|
if (*ptr != '\n')
|
||||||
*stream << endl;
|
stream << endl;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: {
|
default:
|
||||||
size_t len = strcspn(p, "%\n\r\0");
|
len = strcspn(ptr, "%\n\r\0");
|
||||||
stream->write(p, len);
|
stream.write(ptr, len);
|
||||||
p += len;
|
ptr += len;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iter != end) {
|
stream.flags(saved_flags);
|
||||||
*stream << "<extra arg>";
|
stream.fill(saved_fill);
|
||||||
++iter;
|
stream.precision(saved_precision);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
/* end namespace cp */ }
|
||||||
ArgList::dumpToString(const string &format)
|
|
||||||
{
|
|
||||||
stringstream ss;
|
|
||||||
|
|
||||||
dump(ss, format);
|
|
||||||
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -29,142 +29,135 @@
|
||||||
* Steve Reinhardt
|
* Steve Reinhardt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CPRINTF_HH__
|
#ifndef __BASE_CPRINTF_HH__
|
||||||
#define __CPRINTF_HH__
|
#define __BASE_CPRINTF_HH__
|
||||||
|
|
||||||
|
#include <ios>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/varargs.hh"
|
||||||
#include "base/cprintf_formats.hh"
|
#include "base/cprintf_formats.hh"
|
||||||
|
|
||||||
namespace cp {
|
namespace cp {
|
||||||
|
|
||||||
class ArgList
|
#define CPRINTF_DECLARATION VARARGS_DECLARATION(cp::Print)
|
||||||
{
|
#define CPRINTF_DEFINITION VARARGS_DEFINITION(cp::Print)
|
||||||
private:
|
|
||||||
class Base
|
struct Print
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
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:
|
public:
|
||||||
virtual ~Base() {}
|
Print(std::ostream &stream, const std::string &format);
|
||||||
virtual void process(std::ostream &out, Format &fmt) = 0;
|
Print(std::ostream &stream, const char *format);
|
||||||
};
|
~Print();
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Node : public Base
|
void
|
||||||
|
add_arg(const T &data)
|
||||||
{
|
{
|
||||||
public:
|
Format fmt;
|
||||||
const T &data;
|
process(fmt);
|
||||||
|
|
||||||
public:
|
|
||||||
Node(const T &d) : data(d) {}
|
|
||||||
virtual void process(std::ostream &out, Format &fmt) {
|
|
||||||
switch (fmt.format) {
|
switch (fmt.format) {
|
||||||
case Format::character:
|
case Format::character:
|
||||||
format_char(out, data, fmt);
|
format_char(stream, data, fmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Format::integer:
|
case Format::integer:
|
||||||
format_integer(out, data, fmt);
|
format_integer(stream, data, fmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Format::floating:
|
case Format::floating:
|
||||||
format_float(out, data, fmt);
|
format_float(stream, data, fmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Format::string:
|
case Format::string:
|
||||||
format_string(out, data, fmt);
|
format_string(stream, data, fmt);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
out << "<bad format>";
|
stream << "<bad format>";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void end_args();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<Base *> list_t;
|
/* end namespace cp */ }
|
||||||
|
|
||||||
protected:
|
typedef VarArgs::List<cp::Print> CPrintfArgsList;
|
||||||
list_t objects;
|
|
||||||
std::ostream *stream;
|
|
||||||
|
|
||||||
public:
|
inline void
|
||||||
ArgList() : stream(&std::cout) {}
|
ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args)
|
||||||
~ArgList();
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
void append(const T &data) {
|
|
||||||
Base *obj = new ArgList::Node<T>(data);
|
|
||||||
objects.push_back(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
inline ArgList &
|
|
||||||
operator,(ArgList &alist, const T &data)
|
|
||||||
{
|
{
|
||||||
alist.append(data);
|
cp::Print print(stream, format);
|
||||||
return alist;
|
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
|
inline void
|
||||||
__cprintf(const std::string &format, ArgList &args)
|
ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION)
|
||||||
{ args.dump(format); delete &args; }
|
{
|
||||||
#define __cprintf__(format, ...) \
|
cp::Print print(stream, format);
|
||||||
cp::__cprintf(format, (*(new cp::ArgList), __VA_ARGS__))
|
VARARGS_ADDARGS(print);
|
||||||
#define cprintf(...) \
|
}
|
||||||
__cprintf__(__VA_ARGS__, cp::ArgListNull())
|
|
||||||
|
|
||||||
//
|
|
||||||
// ccprintf(stream, format, args, ...) prints to the specified stream
|
|
||||||
// (analogous to fprintf())
|
|
||||||
//
|
|
||||||
inline void
|
inline void
|
||||||
__ccprintf(std::ostream &stream, const std::string &format, ArgList &args)
|
cprintf(const char *format, CPRINTF_DECLARATION)
|
||||||
{ args.dump(stream, format); delete &args; }
|
{
|
||||||
#define __ccprintf__(stream, format, ...) \
|
ccprintf(std::cout, format, VARARGS_ALLARGS);
|
||||||
cp::__ccprintf(stream, format, (*(new cp::ArgList), __VA_ARGS__))
|
}
|
||||||
#define ccprintf(stream, ...) \
|
|
||||||
__ccprintf__(stream, __VA_ARGS__, cp::ArgListNull())
|
|
||||||
|
|
||||||
//
|
|
||||||
// csprintf(format, args, ...) returns a string
|
|
||||||
// (roughly analogous to sprintf())
|
|
||||||
//
|
|
||||||
inline std::string
|
inline std::string
|
||||||
__csprintf(const std::string &format, ArgList &args)
|
csprintf(const char *format, CPRINTF_DECLARATION)
|
||||||
{ std::string s = args.dumpToString(format); delete &args; return s; }
|
{
|
||||||
#define __csprintf__(format, ...) \
|
std::stringstream stream;
|
||||||
cp::__csprintf(format, (*(new cp::ArgList), __VA_ARGS__))
|
ccprintf(stream, format, VARARGS_ALLARGS);
|
||||||
#define csprintf(...) \
|
return stream.str();
|
||||||
__csprintf__(__VA_ARGS__, cp::ArgListNull())
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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__
|
#endif // __CPRINTF_HH__
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
* Authors: Nathan Binkert
|
* Authors: Nathan Binkert
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CPRINTF_FORMATS_HH__
|
#ifndef __BASE_CPRINTF_FORMATS_HH__
|
||||||
#define __CPRINTF_FORMATS_HH__
|
#define __BASE_CPRINTF_FORMATS_HH__
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
|
@ -36,91 +36,99 @@
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/output.hh"
|
#include "base/output.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
|
#include "base/varargs.hh"
|
||||||
#include "sim/host.hh"
|
#include "sim/host.hh"
|
||||||
#include "sim/root.hh"
|
#include "sim/root.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
void
|
void
|
||||||
__panic(const string &format, cp::ArgList &args, const char *func,
|
__panic(const char *func, const char *file, int line, const char *fmt,
|
||||||
const char *file, int line)
|
CPRINTF_DEFINITION)
|
||||||
{
|
{
|
||||||
string fmt = "panic: " + format;
|
string format = "panic: ";
|
||||||
switch (fmt[fmt.size() - 1]) {
|
format += fmt;
|
||||||
|
switch (format[format.size() - 1]) {
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
break;
|
break;
|
||||||
default:
|
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);
|
CPrintfArgsList args(VARARGS_ALLARGS);
|
||||||
args.append(func);
|
|
||||||
args.append(file);
|
|
||||||
args.append(line);
|
|
||||||
args.dump(cerr, fmt);
|
|
||||||
|
|
||||||
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();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__fatal(const string &format, cp::ArgList &args, const char *func,
|
__fatal(const char *func, const char *file, int line, const char *fmt,
|
||||||
const char *file, int line)
|
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 '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fmt += "\n";
|
format += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt += " @ cycle %d\n[%s:%s, line %d]\n";
|
format += " @ cycle %d\n[%s:%s, line %d]\n";
|
||||||
fmt += "Memory Usage: %ld KBytes\n";
|
format += "Memory Usage: %ld KBytes\n";
|
||||||
|
|
||||||
args.append(curTick);
|
args.push_back(curTick);
|
||||||
args.append(func);
|
args.push_back(func);
|
||||||
args.append(file);
|
args.push_back(file);
|
||||||
args.append(line);
|
args.push_back(line);
|
||||||
args.append(memUsage());
|
args.push_back(memUsage());
|
||||||
args.dump(cerr, fmt);
|
|
||||||
|
|
||||||
delete &args;
|
ccprintf(cerr, format.c_str(), args);
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
__warn(const string &format, cp::ArgList &args, const char *func,
|
__warn(const char *func, const char *file, int line, const char *fmt,
|
||||||
const char *file, int line)
|
CPRINTF_DEFINITION)
|
||||||
{
|
{
|
||||||
string fmt = "warn: " + format;
|
string format = "warn: ";
|
||||||
|
format += fmt;
|
||||||
|
|
||||||
switch (fmt[fmt.size() - 1]) {
|
switch (format[format.size() - 1]) {
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fmt += "\n";
|
format += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef VERBOSE_WARN
|
#ifdef VERBOSE_WARN
|
||||||
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);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
args.dump(cerr, fmt);
|
CPrintfArgsList args(VARARGS_ALLARGS);
|
||||||
if (simout.isFile(*outputStream))
|
|
||||||
args.dump(*outputStream, fmt);
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,11 @@
|
||||||
#ifndef __MISC_HH__
|
#ifndef __MISC_HH__
|
||||||
#define __MISC_HH__
|
#define __MISC_HH__
|
||||||
|
|
||||||
#include <assert.h>
|
#include <cassert>
|
||||||
|
|
||||||
#include "base/compiler.hh"
|
#include "base/compiler.hh"
|
||||||
#include "base/cprintf.hh"
|
#include "base/cprintf.hh"
|
||||||
|
#include "base/varargs.hh"
|
||||||
|
|
||||||
#if defined(__SUNPRO_CC)
|
#if defined(__SUNPRO_CC)
|
||||||
#define __FUNCTION__ "how to fix me?"
|
#define __FUNCTION__ "how to fix me?"
|
||||||
|
@ -47,14 +49,20 @@
|
||||||
// calls abort which can dump core or enter the debugger.
|
// calls abort which can dump core or enter the debugger.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
void __panic(const std::string&, cp::ArgList &, const char*, const char*, int)
|
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;
|
M5_ATTR_NORETURN;
|
||||||
#define __panic__(format, ...) \
|
|
||||||
__panic(format, (*(new cp::ArgList), __VA_ARGS__), \
|
inline void
|
||||||
__FUNCTION__ , __FILE__, __LINE__)
|
__panic(const char *func, const char *file, int line,
|
||||||
#define panic(...) \
|
const std::string &format, CPRINTF_DEFINITION)
|
||||||
__panic__(__VA_ARGS__, cp::ArgListNull())
|
{
|
||||||
|
__panic(func, file, line, format.c_str(), VARARGS_ALLARGS);
|
||||||
|
}
|
||||||
M5_PRAGMA_NORETURN(__panic)
|
M5_PRAGMA_NORETURN(__panic)
|
||||||
|
#define panic(...) __panic(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
//
|
//
|
||||||
// This implements a cprintf based fatal() function. fatal() should
|
// This implements a cprintf based fatal() function. fatal() should
|
||||||
|
@ -64,24 +72,33 @@ M5_PRAGMA_NORETURN(__panic)
|
||||||
// "normal" exit with an error code, as opposed to abort() like
|
// "normal" exit with an error code, as opposed to abort() like
|
||||||
// panic() does.
|
// 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;
|
M5_ATTR_NORETURN;
|
||||||
#define __fatal__(format, ...) \
|
|
||||||
__fatal(format, (*(new cp::ArgList), __VA_ARGS__), \
|
inline void
|
||||||
__FUNCTION__ , __FILE__, __LINE__)
|
__fatal(const char *func, const char *file, int line,
|
||||||
#define fatal(...) \
|
const std::string &format, CPRINTF_DEFINITION)
|
||||||
__fatal__(__VA_ARGS__, cp::ArgListNull())
|
{
|
||||||
|
__fatal(func, file, line, format.c_str(), VARARGS_ALLARGS);
|
||||||
|
}
|
||||||
M5_PRAGMA_NORETURN(__fatal)
|
M5_PRAGMA_NORETURN(__fatal)
|
||||||
|
#define fatal(...) __fatal(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
|
||||||
|
|
||||||
//
|
//
|
||||||
// This implements a cprintf based warn
|
// This implements a cprintf based warn
|
||||||
//
|
//
|
||||||
void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
|
void __warn(const char *func, const char *file, int line, const char *format,
|
||||||
#define __warn__(format, ...) \
|
CPRINTF_DECLARATION);
|
||||||
__warn(format, (*(new cp::ArgList), __VA_ARGS__), \
|
inline void
|
||||||
__FUNCTION__ , __FILE__, __LINE__)
|
__warn(const char *func, const char *file, int line, const std::string &format,
|
||||||
#define warn(...) \
|
CPRINTF_DECLARATION)
|
||||||
__warn__(__VA_ARGS__, cp::ArgListNull())
|
{
|
||||||
|
__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
|
// Only print the warning message the first time it is seen. This
|
||||||
// doesn't check the warning string itself, it just only lets one
|
// doesn't check the warning string itself, it just only lets one
|
||||||
|
@ -91,7 +108,7 @@ void __warn(const std::string&, cp::ArgList &, const char*, const char*, int);
|
||||||
#define warn_once(...) do { \
|
#define warn_once(...) do { \
|
||||||
static bool once = false; \
|
static bool once = false; \
|
||||||
if (!once) { \
|
if (!once) { \
|
||||||
__warn__(__VA_ARGS__, cp::ArgListNull()); \
|
warn(__VA_ARGS__); \
|
||||||
once = true; \
|
once = true; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} 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
|
// assert() that prints out the current cycle
|
||||||
//
|
//
|
||||||
#define m5_assert(TEST) \
|
#define m5_assert(TEST) do { \
|
||||||
if (!(TEST)) { \
|
if (!(TEST)) \
|
||||||
std::cerr << "Assertion failure, curTick = " << curTick << std::endl; \
|
ccprintf(std::cerr, "Assertion failure, curTick = %d\n", curTick); \
|
||||||
} \
|
assert(TEST); \
|
||||||
assert(TEST);
|
} while (0)
|
||||||
|
|
||||||
#endif // __MISC_HH__
|
#endif // __MISC_HH__
|
||||||
|
|
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
#include "base/misc.hh"
|
#include "base/misc.hh"
|
||||||
#include "base/trace.hh"
|
#include "base/trace.hh"
|
||||||
#include "base/str.hh"
|
#include "base/str.hh"
|
||||||
|
#include "base/varargs.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -153,9 +154,7 @@ Log::dump(ostream &os)
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintfRecord::~PrintfRecord()
|
PrintfRecord::~PrintfRecord()
|
||||||
{
|
{}
|
||||||
delete &args;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PrintfRecord::dump(ostream &os)
|
PrintfRecord::dump(ostream &os)
|
||||||
|
@ -164,17 +163,17 @@ PrintfRecord::dump(ostream &os)
|
||||||
|
|
||||||
if (!name.empty()) {
|
if (!name.empty()) {
|
||||||
fmt = "%s: " + fmt;
|
fmt = "%s: " + fmt;
|
||||||
args.prepend(name);
|
args.push_front(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cycle != (Tick)-1) {
|
if (cycle != (Tick)-1) {
|
||||||
fmt = "%7d: " + fmt;
|
fmt = "%7d: " + fmt;
|
||||||
args.prepend(cycle);
|
args.push_front(cycle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt += format;
|
fmt += format;
|
||||||
|
|
||||||
args.dump(os, fmt);
|
ccprintf(os, fmt.c_str(), args);
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -81,14 +81,15 @@ namespace Trace {
|
||||||
class PrintfRecord : public Record
|
class PrintfRecord : public Record
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
const char *format;
|
|
||||||
const std::string &name;
|
const std::string &name;
|
||||||
cp::ArgList &args;
|
const char *format;
|
||||||
|
CPrintfArgsList args;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PrintfRecord(const char *_format, cp::ArgList &_args,
|
PrintfRecord(Tick cycle, const std::string &_name, const char *_format,
|
||||||
Tick cycle, const std::string &_name)
|
CPRINTF_DECLARATION)
|
||||||
: Record(cycle), format(_format), name(_name), args(_args)
|
: Record(cycle), name(_name), format(_format),
|
||||||
|
args(VARARGS_ALLARGS)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +122,6 @@ namespace Trace {
|
||||||
Record **wrapRecPtr; // &buffer[size], for quick wrap check
|
Record **wrapRecPtr; // &buffer[size], for quick wrap check
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Log();
|
Log();
|
||||||
~Log();
|
~Log();
|
||||||
|
|
||||||
|
@ -136,22 +136,28 @@ namespace Trace {
|
||||||
extern ObjectMatch ignore;
|
extern ObjectMatch ignore;
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
dprintf(const char *format, cp::ArgList &args, Tick cycle,
|
dprintf(Tick when, const std::string &name, const char *format,
|
||||||
const std::string &name)
|
CPRINTF_DECLARATION)
|
||||||
{
|
{
|
||||||
if (name.empty() || !ignore.match(name))
|
if (!name.empty() && ignore.match(name))
|
||||||
theLog.append(new Trace::PrintfRecord(format, args, cycle, name));
|
return;
|
||||||
|
|
||||||
|
theLog.append(new Trace::PrintfRecord(when, name, format,
|
||||||
|
VARARGS_ALLARGS));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void
|
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;
|
extern const std::string DefaultName;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream &DebugOut();
|
||||||
|
|
||||||
// This silly little class allows us to wrap a string in a functor
|
// 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
|
// object so that we can give a name() that DPRINTF will like
|
||||||
struct StringWrap
|
struct StringWrap
|
||||||
|
@ -162,7 +168,6 @@ struct StringWrap
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const std::string &name() { return Trace::DefaultName; }
|
inline const std::string &name() { return Trace::DefaultName; }
|
||||||
std::ostream &DebugOut();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// DPRINTF is a debugging trace facility that allows one to
|
// 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 DTRACE(x) (Trace::IsOn(Trace::x))
|
||||||
|
|
||||||
#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut()
|
#define DDUMP(x, data, count) do { \
|
||||||
|
if (DTRACE(x)) \
|
||||||
#define DDUMP(x, data, count) \
|
|
||||||
do { \
|
|
||||||
if (Trace::IsOn(Trace::x)) \
|
|
||||||
Trace::dataDump(curTick, name(), data, count); \
|
Trace::dataDump(curTick, name(), data, count); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define __dprintf(cycle, name, format, ...) \
|
#define DPRINTF(x, args...) do { \
|
||||||
Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name)
|
if (DTRACE(x)) \
|
||||||
|
Trace::dprintf(curTick, name(), args); \
|
||||||
#define DPRINTF(x, ...) \
|
|
||||||
do { \
|
|
||||||
if (Trace::IsOn(Trace::x)) \
|
|
||||||
__dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DPRINTFR(x, ...) \
|
#define DPRINTFR(x, args...) do { \
|
||||||
do { \
|
if (DTRACE(x)) \
|
||||||
if (Trace::IsOn(Trace::x)) \
|
Trace::dprintf((Tick)-1, std::string(), args); \
|
||||||
__dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull()); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DPRINTFN(...) \
|
#define DPRINTFN(args...) do { \
|
||||||
do { \
|
Trace::dprintf(curTick, name(), args); \
|
||||||
__dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define DPRINTFNR(...) \
|
#define DPRINTFNR(args...) do { \
|
||||||
do { \
|
Trace::dprintf((Tick)-1, string(), args); \
|
||||||
__dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \
|
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#else // !TRACING_ON
|
#else // !TRACING_ON
|
||||||
|
|
||||||
#define DTRACE(x) (false)
|
#define DTRACE(x) (false)
|
||||||
#define DCOUT(x) if (0) DebugOut()
|
#define DPRINTF(x, args...) do {} while (0)
|
||||||
#define DPRINTF(x, ...) do {} while (0)
|
#define DPRINTFR(args...) do {} while (0)
|
||||||
#define DPRINTFR(...) do {} while (0)
|
#define DPRINTFN(args...) do {} while (0)
|
||||||
#define DPRINTFN(...) do {} while (0)
|
#define DPRINTFNR(args...) do {} while (0)
|
||||||
#define DPRINTFNR(...) do {} while (0)
|
|
||||||
#define DDUMP(x, data, count) do {} while (0)
|
#define DDUMP(x, data, count) do {} while (0)
|
||||||
|
|
||||||
#endif // TRACING_ON
|
#endif // TRACING_ON
|
||||||
|
|
292
src/base/varargs.hh
Normal file
292
src/base/varargs.hh
Normal 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__ */
|
Loading…
Reference in a new issue