From: Nathan Binkert Date: Thu, 8 Feb 2007 06:11:30 +0000 (-0800) Subject: Get rid of the gross operator,()/variadic macro hack X-Git-Tag: m5_2.0_beta3~213 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=1f834b569c8a39f44882c2f2010a9f0ecffdaab1;p=gem5.git 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 --- diff --git a/src/base/cprintf.cc b/src/base/cprintf.cc index dd8ce858b..d4ba9ca21 100644 --- a/src/base/cprintf.cc +++ b/src/base/cprintf.cc @@ -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(); - - 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 << ""; - } - - ++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 << ""; - ++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 << ""; - 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 */ } diff --git a/src/base/cprintf.hh b/src/base/cprintf.hh index dd2256e69..7f8e33367 100644 --- a/src/base/cprintf.hh +++ b/src/base/cprintf.hh @@ -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 #include #include #include +#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 - 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 << ""; - break; - } - } - }; + Format fmt; + process(fmt); - typedef std::list 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 - void append(const T &data) { - Base *obj = new ArgList::Node(data); - objects.push_back(obj); - } + case Format::string: + format_string(stream, data, fmt); + break; - template - void prepend(const T &data) { - Base *obj = new ArgList::Node(data); - objects.push_front(obj); + default: + stream << ""; + 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 CPrintfArgsList; + +inline void +ccprintf(std::ostream &stream, const char *format, const CPrintfArgsList &args) +{ + cp::Print print(stream, format); + args.add_args(print); +} -template -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__ diff --git a/src/base/cprintf_formats.hh b/src/base/cprintf_formats.hh index 0af493217..4e8b2b09e 100644 --- a/src/base/cprintf_formats.hh +++ b/src/base/cprintf_formats.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 #include diff --git a/src/base/misc.cc b/src/base/misc.cc index 991a33736..29b6d2d88 100644 --- a/src/base/misc.cc +++ b/src/base/misc.cc @@ -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); + +#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); } diff --git a/src/base/misc.hh b/src/base/misc.hh index c12c2fe20..1509ea2d2 100644 --- a/src/base/misc.hh +++ b/src/base/misc.hh @@ -32,9 +32,11 @@ #ifndef __MISC_HH__ #define __MISC_HH__ -#include +#include + #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__ diff --git a/src/base/trace.cc b/src/base/trace.cc index 9fa615f4d..6e9838456 100644 --- a/src/base/trace.cc +++ b/src/base/trace.cc @@ -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(); } diff --git a/src/base/trace.hh b/src/base/trace.hh index a46643159..55dd1bd4e 100644 --- a/src/base/trace.hh +++ b/src/base/trace.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 @@ -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 diff --git a/src/base/varargs.hh b/src/base/varargs.hh new file mode 100644 index 000000000..2ba8c240a --- /dev/null +++ b/src/base/varargs.hh @@ -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 a01 = VarArgs::Null(), \ + VarArgs::Argument a02 = VarArgs::Null(), \ + VarArgs::Argument a03 = VarArgs::Null(), \ + VarArgs::Argument a04 = VarArgs::Null(), \ + VarArgs::Argument a05 = VarArgs::Null(), \ + VarArgs::Argument a06 = VarArgs::Null(), \ + VarArgs::Argument a07 = VarArgs::Null(), \ + VarArgs::Argument a08 = VarArgs::Null(), \ + VarArgs::Argument a09 = VarArgs::Null(), \ + VarArgs::Argument a10 = VarArgs::Null(), \ + VarArgs::Argument a11 = VarArgs::Null(), \ + VarArgs::Argument a12 = VarArgs::Null(), \ + VarArgs::Argument a13 = VarArgs::Null(), \ + VarArgs::Argument a14 = VarArgs::Null(), \ + VarArgs::Argument a15 = VarArgs::Null(), \ + VarArgs::Argument a16 = VarArgs::Null() + +#define VARARGS_DEFINITION(receiver) \ + VarArgs::Argument a01, \ + VarArgs::Argument a02, \ + VarArgs::Argument a03, \ + VarArgs::Argument a04, \ + VarArgs::Argument a05, \ + VarArgs::Argument a06, \ + VarArgs::Argument a07, \ + VarArgs::Argument a08, \ + VarArgs::Argument a09, \ + VarArgs::Argument a10, \ + VarArgs::Argument a11, \ + VarArgs::Argument a12, \ + VarArgs::Argument a13, \ + VarArgs::Argument a14, \ + VarArgs::Argument a15, \ + VarArgs::Argument 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 +struct Traits +{ + enum { enabled = true }; +}; + +template <> +struct Traits +{ + enum { enabled = false }; +}; + +template +struct Base : public RefCounted +{ + virtual void add_arg(RECV &receiver) const = 0; +}; + +template +struct Any : public Base +{ + const T &argument; + + Any(const T &arg) : argument(arg) {} + + virtual void + add_arg(RECV &receiver) const + { + receiver.add_arg(argument); + } +}; + +template +struct Argument : public RefCountingPtr > +{ + typedef RefCountingPtr > Base; + + Argument() { } + Argument(const Null &null) { } + template + Argument(const T& arg) : Base(new Any(arg)) { } + + void + add_arg(RECV &receiver) const + { + if (this->data) + this->data->add_arg(receiver); + } +}; + +template +class List +{ + public: + typedef Argument Argument; + typedef std::list 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 + void + push_back(const T &arg) + { + if (Traits::enabled) + l.push_back(arg); + } + + template + void + push_front(const T &arg) + { + if (Traits::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__ */