aboutsummaryrefslogtreecommitdiff
path: root/src/error.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2023-02-28 12:15:54 +0000
committerGitHub <noreply@github.com>2023-02-28 12:15:54 +0000
commit9afd9f9beae310d2a3bea98cd713b22d2f167cf9 (patch)
tree1f5ed60d50eeb282ae4dd451dfe75fab73e32052 /src/error.cpp
parenteb60ec3899922b6b98a5ee1a00766d5d9b9917e1 (diff)
parentc8d3a9121bbed1cff1fee45d6ecf0fa4748f4d21 (diff)
Merge branch 'master' into new-temp-allocator
Diffstat (limited to 'src/error.cpp')
-rw-r--r--src/error.cpp218
1 files changed, 169 insertions, 49 deletions
diff --git a/src/error.cpp b/src/error.cpp
index a0bb4ad5b..2974dc039 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -97,15 +97,57 @@ gb_internal AstFile *thread_safe_get_ast_file_from_id(i32 index) {
+// NOTE: defined in build_settings.cpp
+gb_internal bool global_warnings_as_errors(void);
+gb_internal bool global_ignore_warnings(void);
+gb_internal bool show_error_line(void);
+gb_internal bool has_ansi_terminal_colours(void);
+gb_internal gbString get_file_line_as_string(TokenPos const &pos, i32 *offset);
+
+gb_internal void warning(Token const &token, char const *fmt, ...);
+gb_internal void error(Token const &token, char const *fmt, ...);
+gb_internal void error(TokenPos pos, char const *fmt, ...);
+gb_internal void error_line(char const *fmt, ...);
+gb_internal void syntax_error(Token const &token, char const *fmt, ...);
+gb_internal void syntax_error(TokenPos pos, char const *fmt, ...);
+gb_internal void syntax_warning(Token const &token, char const *fmt, ...);
+gb_internal void compiler_error(char const *fmt, ...);
+
gb_internal void begin_error_block(void) {
mutex_lock(&global_error_collector.block_mutex);
global_error_collector.in_block.store(true);
}
gb_internal void end_error_block(void) {
- if (global_error_collector.error_buffer.count > 0) {
- isize n = global_error_collector.error_buffer.count;
- u8 *text = gb_alloc_array(permanent_allocator(), u8, n+1);
+ isize n = global_error_collector.error_buffer.count;
+ if (n > 0) {
+ u8 *text = global_error_collector.error_buffer.data;
+
+ bool add_extra_newline = false;
+
+ if (show_error_line()) {
+ if (n >= 2 && !(text[n-2] == '\n' && text[n-1] == '\n')) {
+ add_extra_newline = true;
+ }
+ } else {
+ isize newline_count = 0;
+ for (isize i = 0; i < n; i++) {
+ if (text[i] == '\n') {
+ newline_count += 1;
+ }
+ }
+ if (newline_count > 1) {
+ add_extra_newline = true;
+ }
+ }
+
+ if (add_extra_newline) {
+ // add an extra new line as padding when the error line is being shown
+ error_line("\n");
+ }
+
+ n = global_error_collector.error_buffer.count;
+ text = gb_alloc_array(permanent_allocator(), u8, n+1);
gb_memmove(text, global_error_collector.error_buffer.data, n);
text[n] = 0;
String s = {text, n};
@@ -149,15 +191,8 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) {
gb_file_write(f, buf, n);
}
-
gb_global ErrorOutProc *error_out_va = default_error_out_va;
-// NOTE: defined in build_settings.cpp
-gb_internal bool global_warnings_as_errors(void);
-gb_internal bool global_ignore_warnings(void);
-gb_internal bool show_error_line(void);
-gb_internal gbString get_file_line_as_string(TokenPos const &pos, i32 *offset);
-
gb_internal void error_out(char const *fmt, ...) {
va_list va;
va_start(va, fmt);
@@ -165,6 +200,49 @@ gb_internal void error_out(char const *fmt, ...) {
va_end(va);
}
+enum TerminalStyle {
+ TerminalStyle_Normal,
+ TerminalStyle_Bold,
+ TerminalStyle_Underline,
+};
+
+enum TerminalColour {
+ TerminalColour_White,
+ TerminalColour_Red,
+ TerminalColour_Yellow,
+ TerminalColour_Green,
+ TerminalColour_Cyan,
+ TerminalColour_Blue,
+ TerminalColour_Purple,
+ TerminalColour_Black,
+};
+
+gb_internal void terminal_set_colours(TerminalStyle style, TerminalColour foreground) {
+ if (has_ansi_terminal_colours()) {
+ char const *ss = "0";
+ switch (style) {
+ case TerminalStyle_Normal: ss = "0"; break;
+ case TerminalStyle_Bold: ss = "1"; break;
+ case TerminalStyle_Underline: ss = "4"; break;
+ }
+ switch (foreground) {
+ case TerminalColour_White: error_out("\x1b[%s;37m", ss); break;
+ case TerminalColour_Red: error_out("\x1b[%s;31m", ss); break;
+ case TerminalColour_Yellow: error_out("\x1b[%s;33m", ss); break;
+ case TerminalColour_Green: error_out("\x1b[%s;32m", ss); break;
+ case TerminalColour_Cyan: error_out("\x1b[%s;36m", ss); break;
+ case TerminalColour_Blue: error_out("\x1b[%s;34m", ss); break;
+ case TerminalColour_Purple: error_out("\x1b[%s;35m", ss); break;
+ case TerminalColour_Black: error_out("\x1b[%s;30m", ss); break;
+ }
+ }
+}
+gb_internal void terminal_reset_colours(void) {
+ if (has_ansi_terminal_colours()) {
+ error_out("\x1b[0m");
+ }
+}
+
gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
if (!show_error_line()) {
@@ -181,26 +259,33 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
// TODO(bill): This assumes ASCII
enum {
- MAX_LINE_LENGTH = 76,
+ MAX_LINE_LENGTH = 80,
MAX_TAB_WIDTH = 8,
- ELLIPSIS_PADDING = 8
+ ELLIPSIS_PADDING = 8, // `... ...`
+ MAX_LINE_LENGTH_PADDED = MAX_LINE_LENGTH-MAX_TAB_WIDTH-ELLIPSIS_PADDING,
};
- error_out("\n\t");
- if (line.len+MAX_TAB_WIDTH+ELLIPSIS_PADDING > MAX_LINE_LENGTH) {
- i32 const half_width = MAX_LINE_LENGTH/2;
- i32 left = cast(i32)(offset);
- i32 right = cast(i32)(line.len - offset);
- left = gb_min(left, half_width);
- right = gb_min(right, half_width);
+ error_out("\t");
+
+ terminal_set_colours(TerminalStyle_Bold, TerminalColour_White);
- line.text += offset-left;
- line.len -= offset+right-left;
- line = string_trim_whitespace(line);
+ i32 error_length = gb_max(end.offset - pos.offset, 1);
- offset = left + ELLIPSIS_PADDING/2;
+ isize squiggle_extra = 0;
+ if (line.len > MAX_LINE_LENGTH_PADDED) {
+ i32 left = MAX_TAB_WIDTH;
+ line.text += offset-left;
+ line.len -= offset-left;
+ offset = left+MAX_TAB_WIDTH/2;
+ if (line.len > MAX_LINE_LENGTH_PADDED) {
+ line.len = MAX_LINE_LENGTH_PADDED;
+ if (error_length > line.len-left) {
+ error_length = cast(i32)line.len - left;
+ squiggle_extra = 1;
+ }
+ }
error_out("... %.*s ...", LIT(line));
} else {
error_out("%.*s", LIT(line));
@@ -210,6 +295,9 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
for (i32 i = 0; i < offset; i++) {
error_out(" ");
}
+
+ terminal_set_colours(TerminalStyle_Bold, TerminalColour_Green);
+
error_out("^");
if (end.file_id == pos.file_id) {
if (end.line > pos.line) {
@@ -217,34 +305,54 @@ gb_internal bool show_error_on_line(TokenPos const &pos, TokenPos end) {
error_out("~");
}
} else if (end.line == pos.line && end.column > pos.column) {
- i32 length = gb_min(end.offset - pos.offset, cast(i32)(line.len-offset));
- for (i32 i = 1; i < length-1; i++) {
+ for (i32 i = 1; i < error_length-1+squiggle_extra; i++) {
error_out("~");
}
- if (length > 1) {
+ if (error_length > 1 && squiggle_extra == 0) {
error_out("^");
}
}
}
- error_out("\n\n");
+ terminal_reset_colours();
+
+ error_out("\n");
return true;
}
return false;
}
+gb_internal void error_out_pos(TokenPos pos) {
+ terminal_set_colours(TerminalStyle_Bold, TerminalColour_White);
+ error_out("%s ", token_pos_to_string(pos));
+ terminal_reset_colours();
+}
+
+gb_internal void error_out_coloured(char const *str, TerminalStyle style, TerminalColour foreground) {
+ terminal_set_colours(style, foreground);
+ error_out(str);
+ terminal_reset_colours();
+}
+
+
+
gb_internal void error_va(TokenPos const &pos, TokenPos end, char const *fmt, va_list va) {
global_error_collector.count.fetch_add(1);
mutex_lock(&global_error_collector.mutex);
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
- error_out("Error: %s\n", gb_bprintf_va(fmt, va));
+ error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
+ error_out_va(fmt, va);
+ error_out("\n");
} else if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
- error_out("%s %s\n",
- token_pos_to_string(pos),
- gb_bprintf_va(fmt, va));
+ error_out_pos(pos);
+ if (has_ansi_terminal_colours()) {
+ error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
+ }
+ error_out_va(fmt, va);
+ error_out("\n");
show_error_on_line(pos, end);
}
mutex_unlock(&global_error_collector.mutex);
@@ -263,12 +371,15 @@ gb_internal void warning_va(TokenPos const &pos, TokenPos end, char const *fmt,
if (!global_ignore_warnings()) {
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
- error_out("Warning: %s\n", gb_bprintf_va(fmt, va));
+ error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
+ error_out_va(fmt, va);
+ error_out("\n");
} else if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
- error_out("%s Warning: %s\n",
- token_pos_to_string(pos),
- gb_bprintf_va(fmt, va));
+ error_out_pos(pos);
+ error_out_coloured("Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
+ error_out_va(fmt, va);
+ error_out("\n");
show_error_on_line(pos, end);
}
}
@@ -285,12 +396,15 @@ gb_internal void error_no_newline_va(TokenPos const &pos, char const *fmt, va_li
global_error_collector.count++;
// NOTE(bill): Duplicate error, skip it
if (pos.line == 0) {
- error_out("Error: %s", gb_bprintf_va(fmt, va));
+ error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
+ error_out_va(fmt, va);
} else if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
- error_out("%s %s",
- token_pos_to_string(pos),
- gb_bprintf_va(fmt, va));
+ error_out_pos(pos);
+ if (has_ansi_terminal_colours()) {
+ error_out_coloured("Error: ", TerminalStyle_Normal, TerminalColour_Red);
+ }
+ error_out_va(fmt, va);
}
mutex_unlock(&global_error_collector.mutex);
if (global_error_collector.count > MAX_ERROR_COLLECTOR_COUNT) {
@@ -305,12 +419,15 @@ gb_internal void syntax_error_va(TokenPos const &pos, TokenPos end, char const *
// NOTE(bill): Duplicate error, skip it
if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
- error_out("%s Syntax Error: %s\n",
- token_pos_to_string(pos),
- gb_bprintf_va(fmt, va));
- show_error_on_line(pos, end);
+ error_out_pos(pos);
+ error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
+ error_out_va(fmt, va);
+ error_out("\n");
+ // show_error_on_line(pos, end);
} else if (pos.line == 0) {
- error_out("Syntax Error: %s\n", gb_bprintf_va(fmt, va));
+ error_out_coloured("Syntax Error: ", TerminalStyle_Normal, TerminalColour_Red);
+ error_out_va(fmt, va);
+ error_out("\n");
}
mutex_unlock(&global_error_collector.mutex);
@@ -330,12 +447,15 @@ gb_internal void syntax_warning_va(TokenPos const &pos, TokenPos end, char const
// NOTE(bill): Duplicate error, skip it
if (global_error_collector.prev != pos) {
global_error_collector.prev = pos;
- error_out("%s Syntax Warning: %s\n",
- token_pos_to_string(pos),
- gb_bprintf_va(fmt, va));
- show_error_on_line(pos, end);
+ error_out_pos(pos);
+ error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
+ error_out_va(fmt, va);
+ error_out("\n");
+ // show_error_on_line(pos, end);
} else if (pos.line == 0) {
- error_out("Warning: %s\n", gb_bprintf_va(fmt, va));
+ error_out_coloured("Syntax Warning: ", TerminalStyle_Normal, TerminalColour_Yellow);
+ error_out_va(fmt, va);
+ error_out("\n");
}
}
mutex_unlock(&global_error_collector.mutex);