Get rid of the gross operator,()/variadic macro hack
authorNathan Binkert <binkertn@umich.edu>
Thu, 8 Feb 2007 06:11:30 +0000 (22:11 -0800)
committerNathan Binkert <binkertn@umich.edu>
Thu, 8 Feb 2007 06:11:30 +0000 (22:11 -0800)
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

src/base/cprintf.cc
src/base/cprintf.hh
src/base/cprintf_formats.hh
src/base/misc.cc
src/base/misc.hh
src/base/trace.cc
src/base/trace.hh
src/base/varargs.hh [new file with mode: 0644]

index dd8ce858b88b2c2454b574edd772b9f2ea3f223d..d4ba9ca21352605abb98b178f9f64062e40394bd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,232 +39,247 @@ using namespace std;
 
 namespace cp {
 
-ArgList::~ArgList()
+Print::Print(std::ostream &stream, const std::string &format)
+    : stream(stream), format(format.c_str()), ptr(format.c_str())
+{
+    saved_flags = stream.flags();
+    saved_fill = stream.fill();
+    saved_precision = stream.precision();
+}
+
+Print::Print(std::ostream &stream, const char *format)
+    : stream(stream), format(format), ptr(format)
+{
+    saved_flags = stream.flags();
+    saved_fill = stream.fill();
+    saved_precision = stream.precision();
+}
+
+Print::~Print()
 {
-    while (!objects.empty()) {
-        delete objects.front();
-        objects.pop_front();
-    }
 }
 
 void
-ArgList::dump(const string &format)
+Print::process(Format &fmt)
 {
-    list_t::iterator iter = objects.begin();
-    list_t::iterator end = objects.end();
-
-    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 */ }
index dd2256e699d6a2e016465bf60bf253df3a6c101d..7f8e33367ea91906e161cc51b1e76ddcab4076fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002-2005 The Regents of The University of Michigan
+ * Copyright (c) 2002-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *          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__
index 0af493217d9787d84a0f78315e5a892cc9542d01..4e8b2b09eee986c997e08c03496421fb28e6eada 100644 (file)
@@ -28,8 +28,8 @@
  * Authors: Nathan Binkert
  */
 
-#ifndef __CPRINTF_FORMATS_HH__
-#define __CPRINTF_FORMATS_HH__
+#ifndef __BASE_CPRINTF_FORMATS_HH__
+#define __BASE_CPRINTF_FORMATS_HH__
 
 #include <sstream>
 #include <ostream>
index 991a337368caf0aa726b4d5ff8601a03d35b0d38..29b6d2d88f61cef4c290ba2be0425f2b4bdf2349 100644 (file)
 #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);
 }
index c12c2fe202247cd91bc4295e6d7d734f87891264..1509ea2d2738a775b8080dfe31b23f9055fd4b71 100644 (file)
 #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
@@ -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__
index 9fa615f4d5ba628fa913a814d2f049d33b01b8b5..6e98384562e82ae2014d19aef1450c40da56fc8d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
 #include "base/misc.hh"
 #include "base/trace.hh"
 #include "base/str.hh"
+#include "base/varargs.hh"
 
 using namespace std;
 
@@ -153,9 +154,7 @@ Log::dump(ostream &os)
 }
 
 PrintfRecord::~PrintfRecord()
-{
-    delete &args;
-}
+{}
 
 void
 PrintfRecord::dump(ostream &os)
@@ -164,17 +163,17 @@ PrintfRecord::dump(ostream &os)
 
     if (!name.empty()) {
         fmt = "%s: " + fmt;
-        args.prepend(name);
+        args.push_front(name);
     }
 
     if (cycle != (Tick)-1) {
         fmt = "%7d: " + fmt;
-        args.prepend(cycle);
+        args.push_front(cycle);
     }
 
     fmt += format;
 
-    args.dump(os, fmt);
+    ccprintf(os, fmt.c_str(), args);
     os.flush();
 }
 
index a466431598d14ce4a6a8f32397ea89f41fef6e93..55dd1bd4eac0c7df9fee93da1ffdf6d0f80ee878 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001-2005 The Regents of The University of Michigan
+ * Copyright (c) 2001-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -81,14 +81,15 @@ namespace Trace {
     class PrintfRecord : public Record
     {
       private:
-        const char *format;
         const std::string &name;
-        cp::ArgList &args;
+        const char *format;
+        CPrintfArgsList args;
 
       public:
-        PrintfRecord(const char *_format, cp::ArgList &_args,
-                     Tick cycle, const std::string &_name)
-            : Record(cycle), format(_format), name(_name), args(_args)
+        PrintfRecord(Tick cycle, const std::string &_name, const char *_format,
+                     CPRINTF_DECLARATION)
+            : Record(cycle), name(_name), format(_format),
+              args(VARARGS_ALLARGS)
         {
         }
 
@@ -121,7 +122,6 @@ namespace Trace {
         Record **wrapRecPtr;   // &buffer[size], for quick wrap check
 
       public:
-
         Log();
         ~Log();
 
@@ -136,22 +136,28 @@ namespace Trace {
     extern ObjectMatch ignore;
 
     inline void
-    dprintf(const char *format, cp::ArgList &args, Tick cycle,
-            const std::string &name)
+    dprintf(Tick when, const std::string &name, const char *format,
+            CPRINTF_DECLARATION)
     {
-        if (name.empty() || !ignore.match(name))
-            theLog.append(new Trace::PrintfRecord(format, args, cycle, name));
+        if (!name.empty() && ignore.match(name))
+            return;
+
+        theLog.append(new Trace::PrintfRecord(when, name, format,
+                                              VARARGS_ALLARGS));
     }
 
     inline void
-    dataDump(Tick cycle, const std::string &name, const void *data, int len)
+    dataDump(Tick when, const std::string &name, const void *data, int len)
     {
-        theLog.append(new Trace::DataRecord(cycle, name, data, len));
+        theLog.append(new Trace::DataRecord(when, name, data, len));
     }
 
     extern const std::string DefaultName;
+
 };
 
+std::ostream &DebugOut();
+
 // This silly little class allows us to wrap a string in a functor
 // object so that we can give a name() that DPRINTF will like
 struct StringWrap
@@ -162,7 +168,6 @@ struct StringWrap
 };
 
 inline const std::string &name() { return Trace::DefaultName; }
-std::ostream &DebugOut();
 
 //
 // DPRINTF is a debugging trace facility that allows one to
@@ -178,47 +183,36 @@ std::ostream &DebugOut();
 
 #define DTRACE(x) (Trace::IsOn(Trace::x))
 
-#define DCOUT(x) if (Trace::IsOn(Trace::x)) DebugOut()
-
-#define DDUMP(x, data, count) \
-do { \
-    if (Trace::IsOn(Trace::x)) \
-        Trace::dataDump(curTick, name(), data, count); \
+#define DDUMP(x, data, count) do {                     \
+    if (DTRACE(x))                                     \
+        Trace::dataDump(curTick, name(), data, count); \
 } while (0)
 
-#define __dprintf(cycle, name, format, ...) \
-    Trace::dprintf(format, (*(new cp::ArgList), __VA_ARGS__), cycle, name)
-
-#define DPRINTF(x, ...) \
-do { \
-    if (Trace::IsOn(Trace::x)) \
-        __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
+#define DPRINTF(x, args...) do {                       \
+    if (DTRACE(x))                                     \
+        Trace::dprintf(curTick, name(), args);         \
 } while (0)
 
-#define DPRINTFR(x, ...) \
-do { \
-    if (Trace::IsOn(Trace::x)) \
-        __dprintf((Tick)-1, std::string(), __VA_ARGS__, cp::ArgListNull());    \
+#define DPRINTFR(x, args...) do {                      \
+    if (DTRACE(x))                                     \
+        Trace::dprintf((Tick)-1, std::string(), args); \
 } while (0)
 
-#define DPRINTFN(...) \
-do { \
-    __dprintf(curTick, name(), __VA_ARGS__, cp::ArgListNull()); \
+#define DPRINTFN(args...) do {                         \
+    Trace::dprintf(curTick, name(), args);             \
 } while (0)
 
-#define DPRINTFNR(...) \
-do { \
-    __dprintf((Tick)-1, string(), __VA_ARGS__, cp::ArgListNull()); \
+#define DPRINTFNR(args...) do {                        \
+    Trace::dprintf((Tick)-1, string(), args);          \
 } while (0)
 
 #else // !TRACING_ON
 
 #define DTRACE(x) (false)
-#define DCOUT(x) if (0) DebugOut()
-#define DPRINTF(x, ...) do {} while (0)
-#define DPRINTFR(...) do {} while (0)
-#define DPRINTFN(...) do {} while (0)
-#define DPRINTFNR(...) do {} while (0)
+#define DPRINTF(x, args...) do {} while (0)
+#define DPRINTFR(args...) do {} while (0)
+#define DPRINTFN(args...) do {} while (0)
+#define DPRINTFNR(args...) do {} while (0)
 #define DDUMP(x, data, count) do {} while (0)
 
 #endif // TRACING_ON
diff --git a/src/base/varargs.hh b/src/base/varargs.hh
new file mode 100644 (file)
index 0000000..2ba8c24
--- /dev/null
@@ -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__ */