diff options
author | Torok Edwin <edwintorok@gmail.com> | 2009-06-04 07:09:50 +0000 |
---|---|---|
committer | Torok Edwin <edwintorok@gmail.com> | 2009-06-04 07:09:50 +0000 |
commit | 9b5a47fc3c5acad4f1637e1825787834d8357b70 (patch) | |
tree | 42872f1f633198ea769de9ee8d3bddb4d4e514bc /llvm/lib | |
parent | 75ac061fdb28f3b0135fbf45c3fd283c1463edb0 (diff) | |
download | bcm5719-llvm-9b5a47fc3c5acad4f1637e1825787834d8357b70.tar.gz bcm5719-llvm-9b5a47fc3c5acad4f1637e1825787834d8357b70.zip |
Add support for outputting ANSI colors to raw_fd_ostream.
llvm-svn: 72854
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Support/raw_ostream.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/System/Unix/Process.inc | 59 | ||||
-rw-r--r-- | llvm/lib/System/Win32/Process.inc | 66 |
3 files changed, 155 insertions, 0 deletions
diff --git a/llvm/lib/Support/raw_ostream.cpp b/llvm/lib/Support/raw_ostream.cpp index 6ac37bc840c..42e6fda97ba 100644 --- a/llvm/lib/Support/raw_ostream.cpp +++ b/llvm/lib/Support/raw_ostream.cpp @@ -14,6 +14,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Support/Format.h" #include "llvm/System/Program.h" +#include "llvm/System/Process.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Config/config.h" #include "llvm/Support/Compiler.h" @@ -301,6 +302,35 @@ uint64_t raw_fd_ostream::seek(uint64_t off) { return pos; } +raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold, + bool bg) { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = + (colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg) + : sys::Process::OutputColor(colors, bold, bg); + if (colorcode) { + unsigned len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + +raw_ostream &raw_fd_ostream::resetColor() { + if (sys::Process::ColorNeedsFlush()) + flush(); + const char *colorcode = sys::Process::ResetColor(); + if (colorcode) { + unsigned len = strlen(colorcode); + write(colorcode, len); + // don't account colors towards output characters + pos -= len; + } + return *this; +} + //===----------------------------------------------------------------------===// // raw_stdout/err_ostream //===----------------------------------------------------------------------===// diff --git a/llvm/lib/System/Unix/Process.inc b/llvm/lib/System/Unix/Process.inc index 74b9bb8b142..2da31c9f215 100644 --- a/llvm/lib/System/Unix/Process.inc +++ b/llvm/lib/System/Unix/Process.inc @@ -235,3 +235,62 @@ unsigned Process::StandardErrColumns() { return getColumns(2); } + +static bool terminalHasColors() { + if (const char *term = std::getenv("TERM")) { + // Most modern terminals support ANSI escape sequences for colors. + // We could check terminfo, or have a list of known terms that support + // colors, but that would be overkill. + // The user can always ask for no colors by setting TERM to dumb, or + // using a commandline flag. + return strcmp(term, "dumb") != 0; + } + return false; +} + +bool Process::StandardOutHasColors() { + if (!StandardOutIsDisplayed()) + return false; + return terminalHasColors(); +} + +bool Process::StandardErrHasColors() { + if (!StandardErrIsDisplayed()) + return false; + return terminalHasColors(); +} + +bool Process::ColorNeedsFlush() { + // No, we use ANSI escape sequences. + return false; +} + +#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m" + +#define ALLCOLORS(FGBG,BOLD) {\ + COLOR(FGBG, "0", BOLD),\ + COLOR(FGBG, "1", BOLD),\ + COLOR(FGBG, "2", BOLD),\ + COLOR(FGBG, "3", BOLD),\ + COLOR(FGBG, "4", BOLD),\ + COLOR(FGBG, "5", BOLD),\ + COLOR(FGBG, "6", BOLD),\ + COLOR(FGBG, "7", BOLD)\ + } + +static const char* colorcodes[2][2][8] = { + { ALLCOLORS("3",""), ALLCOLORS("3","1;") }, + { ALLCOLORS("4",""), ALLCOLORS("4","1;") } +}; + +const char *Process::OutputColor(char code, bool bold, bool bg) { + return colorcodes[bg?1:0][bold?1:0][code&7]; +} + +const char *Process::OutputBold(bool bg) { + return "\033[1m"; +} + +const char *Process::ResetColor() { + return "\033[0m"; +} diff --git a/llvm/lib/System/Win32/Process.inc b/llvm/lib/System/Win32/Process.inc index e1d7a9222f7..97eba5808df 100644 --- a/llvm/lib/System/Win32/Process.inc +++ b/llvm/lib/System/Win32/Process.inc @@ -147,4 +147,70 @@ unsigned Process::StandardErrColumns() { return Columns; } +// it always has colors +bool Process::StandardErrHasColors() { + return StandardErrIsDisplayed(); +} + +bool Process::StandardOutHasColors() { + return StandardOutIsDisplayed(); +} +namespace { +class DefaultColors +{ + private: + WORD defaultColor; + public: + DefaultColors() + :defaultColor(GetCurrentColor()) {} + static unsigned GetCurrentColor() { + CONSOLE_SCREEN_BUFFER_INFO csbi; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) + return csbi.wAttributes; + return 0; + } + WORD operator()() const { return defaultColor; } +}; + +DefaultColors defaultColors; +} + +bool Process::ColorNeedsFlush() { + return true; +} + +const char *Process::OutputBold(bool bg) { + WORD colors = DefaultColors::GetCurrentColor(); + if (bg) + colors |= BACKGROUND_INTENSITY; + else + colors |= FOREGROUND_INTENSITY; + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::OutputColor(char code, bool bold, bool bg) { + WORD colors; + if (bg) { + colors = ((code&1) ? BACKGROUND_RED : 0) | + ((code&2) ? BACKGROUND_GREEN : 0 ) | + ((code&4) ? BACKGROUND_BLUE : 0); + if (bold) + colors |= BACKGROUND_INTENSITY; + } else { + colors = ((code&1) ? FOREGROUND_RED : 0) | + ((code&2) ? FOREGROUND_GREEN : 0 ) | + ((code&4) ? FOREGROUND_BLUE : 0); + if (bold) + colors |= FOREGROUND_INTENSITY; + } + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors); + return 0; +} + +const char *Process::ResetColor() { + SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); + return 0; +} + } |