--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _FORMATTER_HPP_
+#define _FORMATTER_HPP_
+
+
+#include <iostream>
+
+
+namespace Formatter {
+
+/*
+ * See also http://bytes.com/topic/c/answers/63822-design-question-little-c-header-colorizing-text-linux-comments-ideas
+ */
+
+class Attribute {
+public:
+ virtual ~Attribute() {}
+
+ virtual std::ostream& apply(std::ostream& os) const { return os; }
+};
+
+
+enum Color {
+ RED,
+ GREEN,
+ BLUE,
+};
+
+
+class Formatter {
+public:
+ virtual ~Formatter() {}
+
+ virtual Attribute *normal(void) const { return new Attribute; }
+ virtual Attribute *bold(void) const { return new Attribute; }
+ virtual Attribute *italic(void) const { return new Attribute; }
+ virtual Attribute *color(Color color) const { return new Attribute; }
+};
+
+
+class AnsiAttribute : public Attribute {
+protected:
+ const char *escape;
+public:
+ AnsiAttribute(const char *_escape) : escape(_escape) {}
+ std::ostream & apply(std::ostream& os) const {
+ return os << "\33[" << escape;
+ }
+};
+
+
+/**
+ * Formatter for plain-text files which outputs ANSI escape codes. See
+ * http://en.wikipedia.org/wiki/ANSI_escape_code for more information
+ * concerning ANSI escape codes.
+ */
+class AnsiFormatter : public Formatter {
+protected:
+public:
+ virtual Attribute *normal(void) const { return new AnsiAttribute("0m"); }
+ virtual Attribute *bold(void) const { return new AnsiAttribute("1m"); }
+ virtual Attribute *italic(void) const { return new AnsiAttribute("3m"); }
+ virtual Attribute *color(Color c) const {
+ static const char *color_escapes[] = {
+ "31m", /* red */
+ "32m", /* green */
+ "34m", /* blue */
+ };
+ return new AnsiAttribute(color_escapes[c]);
+ }
+};
+
+
+inline std::ostream& operator<<(std::ostream& os, const Attribute *attr) {
+ return attr->apply(os);
+}
+
+
+#ifdef WIN32
+
+#include <windows.h>
+
+class WindowsAttribute : public Attribute {
+protected:
+ WORD wAttributes;
+public:
+ WindowsAttribute(WORD _wAttributes) : wAttributes(_wAttributes) {}
+ std::ostream & apply(std::ostream& os) const {
+ DWORD nStdHandleOutput;
+ if (os == std::cout) {
+ nStdHandleOutput = STD_OUTPUT_HANDLE;
+ } else if (os == std::cerr) {
+ nStdHandleOutput = STD_ERROR_HANDLE;
+ } else {
+ return os;
+ }
+
+ HANDLE hConsoleOutput = GetStdHandle(nStdHandleOutput);
+ SetConsoleTextAttribute(hConsoleOutput, wAttributes);
+ }
+};
+
+
+/**
+ * Formatter for the Windows Console.
+ */
+class WindowsFormatter : public Formatter {
+protected:
+public:
+ virtual Attribute *normal(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
+ virtual Attribute *bold(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY); }
+ virtual Attribute *italic(void) const { return new WindowsAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); }
+ virtual Attribute *color(Color c) const {
+ static const WORD color_escapes[] = {
+ FOREGROUND_RED | FOREGROUND_INTENSITY,
+ FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY,
+ };
+ return new WindowsAttribute(color_escapes[c]);
+ }
+};
+
+#endif
+
+
+inline Formatter *defaultFormatter(void) {
+#ifdef WIN32
+ return new WindowsFormatter;
+#else
+ return new AnsiFormatter;
+#endif
+}
+
+
+} /* namespace Formatter */
+
+
+#endif /* _FORMATTER_HPP_ */
**************************************************************************/
+#include "formatter.hpp"
#include "trace_model.hpp"
class Dumper : public Visitor
{
-public:
+protected:
std::ostream &os;
+ Formatter::Formatter *formatter;
+ Formatter::Attribute *normal;
+ Formatter::Attribute *bold;
+ Formatter::Attribute *italic;
+ Formatter::Attribute *red;
+ Formatter::Attribute *pointer;
+ Formatter::Attribute *literal;
- Dumper() : os(std::cout) {}
+public:
+ Dumper(std::ostream &_os) : os(_os) {
+ formatter = Formatter::defaultFormatter();
+ normal = formatter->normal();
+ bold = formatter->bold();
+ italic = formatter->italic();
+ red = formatter->color(Formatter::RED);
+ pointer = formatter->color(Formatter::GREEN);
+ literal = formatter->color(Formatter::BLUE);
+ }
- Dumper(std::ostream &_os) : os(_os) {}
+ ~Dumper() {
+ delete normal;
+ delete bold;
+ delete italic;
+ delete red;
+ delete pointer;
+ delete literal;
+ delete formatter;
+ }
void visit(Null *node) {
os << "NULL";
}
void visit(Bool *node) {
- os << (node->value ? "true" : "false");
+ os << literal << (node->value ? "true" : "false") << normal;
}
void visit(SInt *node) {
- os << node->value;
+ os << literal << node->value << normal;
}
void visit(UInt *node) {
- os << node->value;
+ os << literal << node->value << normal;
}
void visit(Float *node) {
- os << node->value;
+ os << literal << node->value << normal;
}
void visit(String *node) {
- os << '"' << node->value << '"';
+ os << literal << '"' << node->value << '"' << normal;
}
void visit(Const *node) {
- os << node->name;
+ os << literal << node->name << normal;
}
void visit(Array *array) {
}
void visit(Blob *blob) {
- os << "... " << blob->size;
+ os << pointer << "blob(" << blob->size << ")" << normal;
+ }
+
+ void visit(Call *call) {
+ const char *sep = "";
+ os << bold << call->name << normal << "(";
+ for (std::list<Arg>::iterator it = call->args.begin(); it != call->args.end(); ++it) {
+ os << sep << italic << it->first << normal << " = ";
+ it->second->visit(*this);
+ sep = ", ";
+ }
+ os << ")";
+ if (call->ret) {
+ os << " = ";
+ call->ret->visit(*this);
+ }
+ os << "\n";
}
};
}
std::ostream & operator <<(std::ostream &os, Call &call) {
- const char *sep = "";
- os << call.name << "(";
- for (std::list<Arg>::iterator it = call.args.begin(); it != call.args.end(); ++it) {
- os << sep << it->first << " = " << it->second;
- sep = ", ";
- }
- os << ")";
- if (call.ret) {
- os << " = " << call.ret;
- }
- os << "\n";
+ Dumper d(os);
+ d.visit(&call);
return os;
}