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.
|
||||
*
|
||||
* 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 */ }
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
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