From 45de80c852dc0498d0be3149a5aa2865f9501a12 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 23 Apr 2018 23:11:30 -0400 Subject: [PATCH] show source line on error --- src/parser/parser.c | 77 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/src/parser/parser.c b/src/parser/parser.c index e3f71cc..117f257 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -1,5 +1,9 @@ #include "parser.h" #include +#include +#include +#include +#include extern FILE * yyin; @@ -21,10 +25,83 @@ void parse(const char * filename) } } +static char * read_file(const char * filename, size_t * length) +{ + int fd = open(filename, O_RDONLY); + if (fd < 0) + return NULL; + size_t size = (size_t)lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + *length = size; + size_t n_bytes_read = 0u; + char * buf = (char *)malloc(size); + if (buf == NULL) + { + close(fd); + return NULL; + } + for (;;) + { + off_t rd_size = read(fd, &buf[n_bytes_read], size - n_bytes_read); + if (rd_size <= 0) + break; + n_bytes_read += (size_t)rd_size; + if (n_bytes_read >= size) + break; + } + if (n_bytes_read != size) + { + free(buf); + close(fd); + return NULL; + } + close(fd); + return buf; +} + +static void display_error_source(int line, int column) +{ + if (line < 0) + return; + + size_t length = 0u; + + char * file = read_file(input_fname, &length); + if (file == NULL) + return; + + int search_line = 1; + const char * line_begin = NULL; + for (size_t i = 0u; i < length; i++) + { + if (search_line == line) + { + line_begin = &file[i]; + search_line++; + } + if (file[i] == '\n') + { + if (line_begin != NULL) + { + file[i] = '\0'; + fprintf(stderr, "%s\n", line_begin); + for (int i = 0; i < column; i++) + { + fprintf(stderr, " "); + } + fprintf(stderr, "^\n"); + break; + } + search_line++; + } + } +} + void handle_parse_error(const char * str, const YYLTYPE * yylloc) { fprintf(stderr, "error: %s (line %d, column %d)\n", str, yylloc->first_line, yylloc->first_column); + display_error_source(yylloc->first_line, yylloc->first_column); }