sim: Make it possible to override the breakpoint length check.
[gem5.git] / src / base / trace.cc
index 2dde1f6886c54ca20e0cb515270b3ab6362ce70a..711d496554391e928206ce7d5f7841777eb68266 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2014 ARM Limited
+ * All rights reserved
+ *
  * Copyright (c) 2001-2006 The Regents of The University of Michigan
  * All rights reserved.
  *
  *
  * Authors: Nathan Binkert
  *          Steve Reinhardt
+ *          Andrew Bardsley
  */
 
-#include <ctype.h>
+#include <cctype>
 #include <fstream>
 #include <iostream>
-#include <list>
+#include <sstream>
 #include <string>
-#include <vector>
 
 #include "base/misc.hh"
 #include "base/output.hh"
 #include "base/str.hh"
 #include "base/trace.hh"
-#include "base/varargs.hh"
-
-using namespace std;
-
-namespace Trace {
-const string DefaultName("global");
-FlagVec flags(NumFlags, false);
-bool enabled = false;
 
-//
-// This variable holds the output stream for debug information.  Other
-// than setting up/redirecting this stream, do *NOT* reference this
-// directly; use DebugOut() (see below) to access this stream for
-// output.
-//
-ostream *dprintf_stream = &cerr;
-ostream &
-output()
+const std::string &name()
 {
-    return *dprintf_stream;
-}
+    static const std::string default_name("global");
 
-void
-setOutput(const string &filename)
-{
-    dprintf_stream = simout.find(filename);
+    return default_name;
 }
 
-ObjectMatch ignore;
-
-void
-dprintf(Tick when, const std::string &name, const char *format,
-        CPRINTF_DEFINITION)
+namespace Trace
 {
-    if (!name.empty() && ignore.match(name))
-        return;
 
-    std::ostream &os = *dprintf_stream;
+bool enabled = false;
 
-    string fmt = "";
-    CPrintfArgsList args(VARARGS_ALLARGS);
+// This variable holds the output logger for debug information.  Other
+// than setting up/redirecting this logger, do *NOT* reference this
+// directly
 
-    if (!name.empty()) {
-        fmt = "%s: " + fmt;
-        args.push_front(name);
-    }
+Logger *debug_logger = NULL;
 
-    if (when != (Tick)-1) {
-        fmt = "%7d: " + fmt;
-        args.push_front(when);
-    }
+Logger *
+getDebugLogger()
+{
+    /* Set a default logger to cerr when no other logger is set */
+    if (!debug_logger)
+        debug_logger = new OstreamLogger(std::cerr);
 
-    fmt += format;
+    return debug_logger;
+}
 
-    ccprintf(os, fmt.c_str(), args);
-    os.flush();
+std::ostream &
+output()
+{
+    return getDebugLogger()->getOstream();
 }
 
 void
-dump(Tick when, const std::string &name, const void *d, int len)
+setDebugLogger(Logger *logger)
 {
-    if (!name.empty() && ignore.match(name))
-        return;
-
-    std::ostream &os = *dprintf_stream;
-
-    string fmt = "";
-    CPrintfArgsList args;
+    if (!logger)
+        warn("Trying to set debug logger to NULL\n");
+    else
+        debug_logger = logger;
+}
 
-    if (!name.empty()) {
-        fmt = "%s: " + fmt;
-        args.push_front(name);
-    }
+ObjectMatch ignore;
 
-    if (when != (Tick)-1) {
-        fmt = "%7d: " + fmt;
-        args.push_front(when);
-    }
+void
+Logger::dump(Tick when, const std::string &name, const void *d, int len)
+{
+    if (!name.empty() && ignore.match(name))
+        return;
 
     const char *data = static_cast<const char *>(d);
     int c, i, j;
+
     for (i = 0; i < len; i += 16) {
-        ccprintf(os, fmt, args);
-        ccprintf(os, "%08x  ", i);
+        std::ostringstream line;
+
+        ccprintf(line, "%08x  ", i);
         c = len - i;
         if (c > 16) c = 16;
 
         for (j = 0; j < c; j++) {
-            ccprintf(os, "%02x ", data[i + j] & 0xff);
+            ccprintf(line, "%02x ", data[i + j] & 0xff);
             if ((j & 0xf) == 7 && j > 0)
-                ccprintf(os, " ");
+                ccprintf(line, " ");
         }
 
         for (; j < 16; j++)
-            ccprintf(os, "   ");
-        ccprintf(os, "  ");
+            ccprintf(line, "   ");
+        ccprintf(line, "  ");
 
         for (j = 0; j < c; j++) {
             int ch = data[i + j] & 0x7f;
-            ccprintf(os, "%c", (char)(isprint(ch) ? ch : ' '));
+            ccprintf(line, "%c", (char)(isprint(ch) ? ch : ' '));
         }
 
-        ccprintf(os, "\n");
+        ccprintf(line, "\n");
+        logMessage(when, name, line.str());
 
         if (c < 16)
             break;
     }
 }
 
-bool
-changeFlag(const char *s, bool value)
-{
-    using namespace Trace;
-    std::string str(s);
-
-    for (int i = 0; i < numFlagStrings; ++i) {
-        if (str != flagStrings[i])
-            continue;
-
-        if (i < NumFlags) {
-            flags[i] = value;
-        } else {
-            i -= NumFlags;
-
-            const Flags *flagVec = compoundFlags[i];
-            for (int j = 0; flagVec[j] != -1; ++j) {
-                if (flagVec[j] < NumFlags)
-                    flags[flagVec[j]] = value;
-            }
-        }
-
-        return true;
-    }
-
-    // the flag was not found.
-    return false;
-}
-
 void
-dumpStatus()
+OstreamLogger::logMessage(Tick when, const std::string &name,
+                          const std::string &message)
 {
-    using namespace Trace;
-    for (int i = 0; i < numFlagStrings; ++i) {
-        if (flags[i])
-            cprintf("%s\n", flagStrings[i]);
-    }
-}
-
-/* namespace Trace */ }
+    if (!name.empty() && ignore.match(name))
+        return;
 
+    if (when != MaxTick)
+        ccprintf(stream, "%7d: ", when);
 
-// add a set of functions that can easily be invoked from gdb
-extern "C" {
-    void
-    setTraceFlag(const char *string)
-    {
-        Trace::changeFlag(string, true);
-    }
+    if (!name.empty())
+        stream << name << ": ";
 
-    void
-    clearTraceFlag(const char *string)
-    {
-        Trace::changeFlag(string, false);
-    }
+    stream << message;
+    stream.flush();
+}
 
-    void
-    dumpTraceStatus()
-    {
-        Trace::dumpStatus();
-    }
-/* extern "C" */ }
+} // namespace Trace