Support ANSI escape code on Windows

In some cases (e.g. when a build system pipes stderr) the Windows console
API cannot be used to color output. For these, provide a way to switch to
ANSI escape codes. This is required for Clang's -fansi-escape-codes option.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190460 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nico Rieck 2013-09-11 00:36:48 +00:00
parent f495a26792
commit 44a61bde15
4 changed files with 41 additions and 19 deletions

View File

@ -216,6 +216,12 @@ public:
/// terminal, this function returns false. /// terminal, this function returns false.
static bool StandardErrHasColors(); static bool StandardErrHasColors();
/// Enables or disables whether ANSI escape sequences are used to output
/// colors. This only has an effect on Windows.
/// Note: Setting this option is not thread-safe and should only be done
/// during initialization.
static void UseANSIEscapeCodes(bool enable);
/// Whether changing colors requires the output to be flushed. /// Whether changing colors requires the output to be flushed.
/// This is needed on systems that don't support escape sequences for /// This is needed on systems that don't support escape sequences for
/// changing colors. /// changing colors.

View File

@ -80,6 +80,24 @@ TimeValue self_process::get_wall_time() const {
#endif #endif
#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][10] = {
{ ALLCOLORS("3",""), ALLCOLORS("3","1;") },
{ ALLCOLORS("4",""), ALLCOLORS("4","1;") }
};
// Include the platform-specific parts of this class. // Include the platform-specific parts of this class.
#ifdef LLVM_ON_UNIX #ifdef LLVM_ON_UNIX
#include "Unix/Process.inc" #include "Unix/Process.inc"

View File

@ -310,29 +310,15 @@ bool Process::StandardErrHasColors() {
return FileDescriptorHasColors(STDERR_FILENO); return FileDescriptorHasColors(STDERR_FILENO);
} }
void Process::UseANSIEscapeCodes(bool /*enable*/) {
// No effect.
}
bool Process::ColorNeedsFlush() { bool Process::ColorNeedsFlush() {
// No, we use ANSI escape sequences. // No, we use ANSI escape sequences.
return false; 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][10] = {
{ ALLCOLORS("3",""), ALLCOLORS("3","1;") },
{ ALLCOLORS("4",""), ALLCOLORS("4","1;") }
};
const char *Process::OutputColor(char code, bool bold, bool bg) { const char *Process::OutputColor(char code, bool bold, bool bg) {
return colorcodes[bg?1:0][bold?1:0][code&7]; return colorcodes[bg?1:0][bold?1:0][code&7];
} }

View File

@ -216,6 +216,11 @@ bool Process::StandardErrHasColors() {
return FileDescriptorHasColors(2); return FileDescriptorHasColors(2);
} }
static bool UseANSI = false;
void Process::UseANSIEscapeCodes(bool enable) {
UseANSI = enable;
}
namespace { namespace {
class DefaultColors class DefaultColors
{ {
@ -237,10 +242,12 @@ DefaultColors defaultColors;
} }
bool Process::ColorNeedsFlush() { bool Process::ColorNeedsFlush() {
return true; return !UseANSI;
} }
const char *Process::OutputBold(bool bg) { const char *Process::OutputBold(bool bg) {
if (UseANSI) return "\033[1m";
WORD colors = DefaultColors::GetCurrentColor(); WORD colors = DefaultColors::GetCurrentColor();
if (bg) if (bg)
colors |= BACKGROUND_INTENSITY; colors |= BACKGROUND_INTENSITY;
@ -251,6 +258,8 @@ const char *Process::OutputBold(bool bg) {
} }
const char *Process::OutputColor(char code, bool bold, bool bg) { const char *Process::OutputColor(char code, bool bold, bool bg) {
if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
WORD colors; WORD colors;
if (bg) { if (bg) {
colors = ((code&1) ? BACKGROUND_RED : 0) | colors = ((code&1) ? BACKGROUND_RED : 0) |
@ -276,6 +285,8 @@ static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
} }
const char *Process::OutputReverse() { const char *Process::OutputReverse() {
if (UseANSI) return "\033[7m";
const WORD attributes const WORD attributes
= GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE)); = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
@ -302,6 +313,7 @@ const char *Process::OutputReverse() {
} }
const char *Process::ResetColor() { const char *Process::ResetColor() {
if (UseANSI) return "\033[0m";
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors()); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
return 0; return 0;
} }