@@ -28,7 +28,7 @@ void verify_delayed_error(odin_error error_type) {
2828 }
2929}
3030
31- static std::string make_marker_from_str (std::string str, int column) {
31+ static std::string make_marker_from_str (std::string str, unsigned long column) {
3232 str.erase (column);
3333 for (size_t i = 0 ; i < str.size (); i++) {
3434 if (str[i] != ' ' && str[i] != ' \t ' ) {
@@ -40,36 +40,54 @@ static std::string make_marker_from_str(std::string str, int column) {
4040 return str;
4141}
4242
43- static void print_culprit_line (long column, long line_number, long file) {
43+ static std::string get_culprit_line (long line_number, const char * file) {
4444 std::string culprit_line = " " ;
45-
46- if (file >= 0 && (size_t )file < include_file_names.size ()
47- && line_number >= 0 ) {
48- FILE* input_file = fopen (include_file_names[file].first .c_str (), " r" );
49- if (input_file) {
50- bool copy_characters = false ;
51- int current_line_number = 0 ;
52-
53- for (;;) {
54- int c = fgetc (input_file);
55- if (EOF == c) {
56- break ;
57- } else if (' \n ' == c) {
58- ++current_line_number;
59- if (line_number == current_line_number) {
60- copy_characters = true ;
61- } else if (copy_characters) {
62- break ;
63- }
45+ FILE* input_file = fopen (file, " r" );
46+ if (input_file) {
47+ bool copy_characters = false ;
48+ int current_line_number = 0 ;
49+
50+ for (;;) {
51+ int c = fgetc (input_file);
52+ if (EOF == c) {
53+ break ;
54+ } else if (' \n ' == c) {
55+ ++current_line_number;
56+ if (line_number == current_line_number) {
57+ copy_characters = true ;
6458 } else if (copy_characters) {
65- culprit_line. push_back (c) ;
59+ break ;
6660 }
61+ } else if (copy_characters) {
62+ culprit_line.push_back (c);
6763 }
68- fclose (input_file);
6964 }
70- fprintf (stderr, " %s\n " , culprit_line.c_str ());
65+ fclose (input_file);
66+ }
67+ return culprit_line;
68+ }
69+
70+ static void print_culprit_line (long column, long line_number, const char * file) {
71+ std::string culprit_line = get_culprit_line (line_number, file);
72+ if (!culprit_line.empty ()) {
73+ int num_printed;
74+ fprintf (stderr, " %ld: %n%s\n " , line_number + 1 , &num_printed, culprit_line.c_str ());
7175 if (column >= 0 ) {
72- fprintf (stderr, " %s\n " , make_marker_from_str (culprit_line, column).c_str ());
76+ fprintf (stderr, " %s\n " , make_marker_from_str (culprit_line, num_printed + column).c_str ());
77+ }
78+ }
79+ }
80+
81+ static void print_culprit_line_with_context (long target_line, const char * file, long num_context_lines) {
82+ for (long curr_line = std::max (target_line - num_context_lines, 0l ); curr_line <= target_line + num_context_lines; curr_line++) {
83+ std::string culprit_line = get_culprit_line (curr_line, file);
84+ if (!culprit_line.empty ()) {
85+ int num_printed;
86+ fprintf (stderr, " %ld: %n%s\n " , curr_line + 1 , &num_printed, culprit_line.c_str ());
87+ if (curr_line == target_line) {
88+ const unsigned long first_char_pos = culprit_line.find_first_not_of (" \t " );
89+ fprintf (stderr, " %s\n " , make_marker_from_str (culprit_line, num_printed + first_char_pos).c_str ());
90+ }
7391 }
7492 }
7593}
@@ -94,7 +112,7 @@ void _log_message(odin_error error_type, long column, long line_number, long fil
94112 file_name = file_name.substr (slash_location + 1 );
95113 }
96114
97- fprintf (stderr, " %s:: %ld" , file_name.c_str (), line_number + 1 );
115+ fprintf (stderr, " %s:%ld" , file_name.c_str (), line_number + 1 );
98116 }
99117
100118 if (message != NULL ) {
@@ -107,8 +125,29 @@ void _log_message(odin_error error_type, long column, long line_number, long fil
107125 fprintf (stderr, " \n " );
108126 }
109127
110- print_culprit_line (column, line_number, file);
128+ if (file >= 0 && (size_t )file < include_file_names.size ()
129+ && line_number >= 0 ) {
130+ print_culprit_line (column, line_number, include_file_names[file].first .c_str ());
131+ }
111132
112133 fflush (stderr);
113- _verbose_assert (!fatal_error, " " , function_file_name, function_line, function_name);
134+ _verbose_assert (!fatal_error, NULL , function_file_name, function_line, function_name);
135+ }
136+
137+ void _verbose_assert (bool condition, const char * condition_str, const char * odin_file_name, long odin_line_number, const char * odin_function_name) {
138+ fflush (stdout);
139+ if (!condition) {
140+ fprintf (stderr, " %s:%ld: %s: " , odin_file_name, odin_line_number, odin_function_name);
141+ if (condition_str) {
142+ // We are an assertion, print the condition that failed and which line it occurred on
143+ fprintf (stderr, " Assertion %s failed\n " , condition_str);
144+ // odin_line_number-1 since __LINE__ starts from 1
145+ print_culprit_line_with_context (odin_line_number - 1 , odin_file_name, 2 );
146+ } else {
147+ // We are a parsing error, dont print the culprit line
148+ fprintf (stderr, " Fatal error\n " );
149+ }
150+ fflush (stderr);
151+ std::abort ();
152+ }
114153}
0 commit comments