From 28be9b613a72dfaef02cb46a51f486831048523c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Tue, 23 Nov 2010 10:37:03 +0000 Subject: [PATCH] Color output. --- formatter.hpp | 162 ++++++++++++++++++++++++++++++++++++++++++++++++ trace_model.cpp | 74 +++++++++++++++------- 2 files changed, 215 insertions(+), 21 deletions(-) create mode 100644 formatter.hpp diff --git a/formatter.hpp b/formatter.hpp new file mode 100644 index 0000000..c1568a6 --- /dev/null +++ b/formatter.hpp @@ -0,0 +1,162 @@ +/************************************************************************** + * + * 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 + + +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 + +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_ */ diff --git a/trace_model.cpp b/trace_model.cpp index 213c872..63968b7 100644 --- a/trace_model.cpp +++ b/trace_model.cpp @@ -24,6 +24,7 @@ **************************************************************************/ +#include "formatter.hpp" #include "trace_model.hpp" @@ -69,39 +70,63 @@ void Blob::visit(Visitor &visitor) { 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) { @@ -122,7 +147,23 @@ public: } 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::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"; } }; @@ -214,17 +255,8 @@ Value & Call::arg(const char *name) { } std::ostream & operator <<(std::ostream &os, Call &call) { - const char *sep = ""; - os << call.name << "("; - for (std::list::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; } -- 2.45.2