/*
- * 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
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();
-
- const char *p = format.c_str();
-
- 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;
- }
+ size_t len;
+
+ while (*ptr) {
+ switch (*ptr) {
+ case '%':
+ if (ptr[1] != '%')
+ goto processing;
+
+ 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 */ }
/*
- * 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
* 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;
- };
+ 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:
+ Print(std::ostream &stream, const std::string &format);
+ Print(std::ostream &stream, const char *format);
+ ~Print();
template <typename T>
- class Node : public Base
+ void
+ add_arg(const T &data)
{
- 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;
- }
- }
- };
+ Format fmt;
+ process(fmt);
- typedef std::list<Base *> list_t;
+ switch (fmt.format) {
+ case Format::character:
+ format_char(stream, data, fmt);
+ break;
- protected:
- list_t objects;
- std::ostream *stream;
+ case Format::integer:
+ format_integer(stream, data, fmt);
+ break;
- public:
- ArgList() : stream(&std::cout) {}
- ~ArgList();
+ case Format::floating:
+ format_float(stream, data, fmt);
+ break;
- template<class T>
- void append(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_back(obj);
- }
+ case Format::string:
+ format_string(stream, data, fmt);
+ break;
- template<class T>
- void prepend(const T &data) {
- Base *obj = new ArgList::Node<T>(data);
- objects.push_front(obj);
+ default:
+ stream << "<bad format>";
+ break;
+ }
}
- void dump(const std::string &format);
- void dump(std::ostream &strm, const std::string &fmt)
- { stream = &strm; dump(fmt); }
+ void end_args();
+};
- std::string dumpToString(const std::string &format);
+/* end namespace cp */ }
- friend ArgList &operator<<(std::ostream &str, ArgList &list);
-};
+typedef VarArgs::List<cp::Print> CPrintfArgsList;
+
+inline void
+ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args)
+{
+ cp::Print print(stream, format);
+ args.add_args(print);
+}
-template<class T>
-inline ArgList &
-operator,(ArgList &alist, const T &data)
+inline void
+ccprintf(std::ostream &stream, const char *format, CPRINTF_DECLARATION)
{
- alist.append(data);
- return alist;
+ cp::Print print(stream, format);
+ VARARGS_ADDARGS(print);
}
-class ArgListNull {
-};
+inline void
+cprintf(const char *format, CPRINTF_DECLARATION)
+{
+ ccprintf(std::cout, format, VARARGS_ALLARGS);
+}
+
+inline std::string
+csprintf(const char *format, CPRINTF_DECLARATION)
+{
+ std::stringstream stream;
+ ccprintf(stream, format, VARARGS_ALLARGS);
+ return stream.str();
+}
-inline ArgList &
-operator,(ArgList &alist, ArgListNull)
-{ return alist; }
+/*
+ * 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);
+}
-//
-// 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(stream, format, args, ...) prints to the specified stream
-// (analogous to fprintf())
-//
+ccprintf(std::ostream &stream, const std::string &format, CPRINTF_DECLARATION)
+{
+ ccprintf(stream, format, VARARGS_ALLARGS);
+}
+
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())
-
-//
-// 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())
+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__
* 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>
#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);
+
+#ifdef VERBOSE_WARN
+ args.push_back(curTick);
+ args.push_back(func);
+ args.push_back(file);
+ args.push_back(line);
+#endif
- delete &args;
+ ccprintf(cerr, format.c_str(), args);
+ if (simout.isFile(*outputStream))
+ ccprintf(*outputStream, format.c_str(), args);
}
#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?"
// 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
// "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)
//
// 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__
/*
- * 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
#include "base/misc.hh"
#include "base/trace.hh"
#include "base/str.hh"
+#include "base/varargs.hh"
using namespace std;
}
PrintfRecord::~PrintfRecord()
-{
- delete &args;
-}
+{}
void
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();
}
/*
- * 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
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)
{
}
Record **wrapRecPtr; // &buffer[size], for quick wrap check
public:
-
Log();
~Log();
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
};
inline const std::string &name() { return Trace::DefaultName; }
-std::ostream &DebugOut();
//
// DPRINTF is a debugging trace facility that allows one to
#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
--- /dev/null
+/*
+ * 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__ */