summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/color.cc84
-rw-r--r--src/color.h71
-rw-r--r--src/config.h.in3
-rw-r--r--src/source-error-handler.cc16
-rw-r--r--src/source-error-handler.h6
5 files changed, 175 insertions, 5 deletions
diff --git a/src/color.cc b/src/color.cc
new file mode 100644
index 00000000..f1657728
--- /dev/null
+++ b/src/color.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "color.h"
+
+#include <cstdlib>
+
+#include "common.h"
+
+#if _WIN32
+#include <io.h>
+#include <windows.h>
+#elif HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+namespace wabt {
+
+Color::Color(FILE* file, bool enabled) : file_(file) {
+ enabled_ = enabled && SupportsColor(file_);
+}
+
+// static
+bool Color::SupportsColor(FILE* file) {
+ char* force = getenv("FORCE_COLOR");
+ if (force) {
+ return atoi(force) != 0;
+ }
+
+#if _WIN32
+
+ {
+#if HAVE_WIN32_VT100
+ HANDLE handle;
+ if (file == stdout) {
+ handle = GetStdHandle(STD_OUTPUT_HANDLE);
+ } else if (file == stderr) {
+ handle = GetStdHandle(STD_ERROR_HANDLE);
+ } else {
+ return false;
+ }
+ DWORD mode;
+ if (!_isatty(_fileno(file)) || !GetConsoleMode(handle, mode) ||
+ !SetConsoleMode(handle, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) {
+ return false;
+ }
+ return true;
+#else
+ // TODO(binji): Support older Windows by using SetConsoleTextAttribute?
+ return false;
+#endif
+ }
+
+#elif HAVE_UNISTD_H
+
+ return isatty(fileno(file));
+
+#else
+
+ return false;
+
+#endif
+}
+
+void Color::WriteCode(const char* code) const {
+ if (enabled_) {
+ fputs(code, file_);
+ }
+}
+
+} // namespace wabt
diff --git a/src/color.h b/src/color.h
new file mode 100644
index 00000000..ba64e5d2
--- /dev/null
+++ b/src/color.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_COLOR_H_
+#define WABT_COLOR_H_
+
+#include <cstdio>
+
+namespace wabt {
+
+#define WABT_FOREACH_COLOR_CODE(V) \
+ V(Default, "\x1b[0m") \
+ V(Bold, "\x1b[1m") \
+ V(NoBold, "\x1b[22m") \
+ V(Black, "\x1b[30m") \
+ V(Red, "\x1b[31m") \
+ V(Green, "\x1b[32m") \
+ V(Yellow, "\x1b[33m") \
+ V(Blue, "\x1b[34m") \
+ V(Magenta, "\x1b[35m") \
+ V(Cyan, "\x1b[36m") \
+ V(White, "\x1b[37m")
+
+class Color {
+ public:
+ Color(FILE*, bool enabled = true);
+
+ // Write the given color to the file, if enabled.
+#define WABT_COLOR(Name, code) \
+ void Name() const { WriteCode(Name##Code()); }
+ WABT_FOREACH_COLOR_CODE(WABT_COLOR)
+#undef WABT_COLOR
+
+ // Get the color code as a string, if enabled.
+#define WABT_COLOR(Name, code) \
+ const char* Maybe##Name##Code() const { return enabled_ ? Name##Code() : ""; }
+ WABT_FOREACH_COLOR_CODE(WABT_COLOR)
+#undef WABT_COLOR
+
+ // Get the color code as a string.
+#define WABT_COLOR(Name, code) \
+ static const char* Name##Code() { return code; }
+ WABT_FOREACH_COLOR_CODE(WABT_COLOR)
+#undef WABT_COLOR
+
+ private:
+ static bool SupportsColor(FILE*);
+ void WriteCode(const char*) const;
+
+ FILE* file_;
+ bool enabled_;
+};
+
+#undef WABT_FOREACH_COLOR_CODE
+
+} // namespace wabt
+
+#endif // WABT_COLOR_H_
diff --git a/src/config.h.in b/src/config.h.in
index b2dc04b4..cb6af598 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -37,6 +37,9 @@
/* Whether strcasecmp is defined by strings.h */
#cmakedefine01 HAVE_STRCASECMP
+/* Whether ENABLE_VIRTUAL_TERMINAL_PROCESSING is defined by windows.h */
+#cmakedefine01 HAVE_WIN32_VT100
+
#cmakedefine01 COMPILER_IS_CLANG
#cmakedefine01 COMPILER_IS_GNU
#cmakedefine01 COMPILER_IS_MSVC
diff --git a/src/source-error-handler.cc b/src/source-error-handler.cc
index acd3641f..7424b973 100644
--- a/src/source-error-handler.cc
+++ b/src/source-error-handler.cc
@@ -24,6 +24,7 @@ SourceErrorHandler::SourceErrorHandler(Location::Type location_type)
: location_type_(location_type) {}
std::string SourceErrorHandler::DefaultErrorMessage(
+ const Color& color,
const Location* loc,
const std::string& error,
const std::string& source_line,
@@ -31,12 +32,14 @@ std::string SourceErrorHandler::DefaultErrorMessage(
int indent) {
std::string indent_str(indent, ' ');
std::string result = indent_str;
+ result += color.MaybeBoldCode();
if (location_type_ == Location::Type::Text) {
result += string_printf("%s:%d:%d: ", loc->filename, loc->line,
loc->first_column);
} else {
result += string_printf("%s:%" PRIzd ": ", loc->filename, loc->offset);
}
+ result += color.MaybeDefaultCode();
result += error;
result += '\n';
result += indent_str;
@@ -50,7 +53,10 @@ std::string SourceErrorHandler::DefaultErrorMessage(
num_carets = std::min(num_carets, source_line.size() - num_spaces);
num_carets = std::max<size_t>(num_carets, 1);
result.append(num_spaces, ' ');
+ result += color.MaybeBoldCode();
+ result += color.MaybeGreenCode();
result.append(num_carets, '^');
+ result += color.MaybeDefaultCode();
result += '\n';
}
return result;
@@ -69,7 +75,8 @@ SourceErrorHandlerFile::SourceErrorHandlerFile(FILE* file,
file_(file),
header_(header),
print_header_(print_header),
- source_line_max_length_(source_line_max_length) {}
+ source_line_max_length_(source_line_max_length),
+ color_(file) {}
bool SourceErrorHandlerFile::OnError(const Location* loc,
const std::string& error,
@@ -77,7 +84,7 @@ bool SourceErrorHandlerFile::OnError(const Location* loc,
size_t source_line_column_offset) {
PrintErrorHeader();
int indent = header_.empty() ? 0 : 2;
- std::string message = DefaultErrorMessage(loc, error, source_line,
+ std::string message = DefaultErrorMessage(color_, loc, error, source_line,
source_line_column_offset, indent);
fwrite(message.data(), 1, message.size(), file_);
return true;
@@ -105,13 +112,14 @@ SourceErrorHandlerBuffer::SourceErrorHandlerBuffer(
size_t source_line_max_length,
Location::Type location_type)
: SourceErrorHandler(location_type),
- source_line_max_length_(source_line_max_length) {}
+ source_line_max_length_(source_line_max_length),
+ color_(nullptr, false) {}
bool SourceErrorHandlerBuffer::OnError(const Location* loc,
const std::string& error,
const std::string& source_line,
size_t source_line_column_offset) {
- buffer_ += DefaultErrorMessage(loc, error, source_line,
+ buffer_ += DefaultErrorMessage(color_, loc, error, source_line,
source_line_column_offset, 0);
return true;
}
diff --git a/src/source-error-handler.h b/src/source-error-handler.h
index 45e049b0..5e09dc26 100644
--- a/src/source-error-handler.h
+++ b/src/source-error-handler.h
@@ -19,6 +19,7 @@
#include <string>
+#include "color.h"
#include "common.h"
namespace wabt {
@@ -38,7 +39,8 @@ class SourceErrorHandler {
// OnError will be called with with source_line trimmed to this length.
virtual size_t source_line_max_length() const = 0;
- std::string DefaultErrorMessage(const Location*,
+ std::string DefaultErrorMessage(const Color&,
+ const Location*,
const std::string& error,
const std::string& source_line,
size_t source_line_column_offset,
@@ -93,6 +95,7 @@ class SourceErrorHandlerFile : public SourceErrorHandler {
std::string header_;
PrintHeader print_header_;
size_t source_line_max_length_;
+ Color color_;
};
class SourceErrorHandlerBuffer : public SourceErrorHandler {
@@ -114,6 +117,7 @@ class SourceErrorHandlerBuffer : public SourceErrorHandler {
private:
size_t source_line_max_length_;
std::string buffer_;
+ Color color_;
};
} // namespace wabt