From 1dd19e56fb81d1334bb21e4aa097f9593576feb7 Mon Sep 17 00:00:00 2001 From: lemon Date: Sat, 6 Aug 2022 07:07:26 +0200 Subject: print source on error --- bootstrap/util.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'bootstrap/util.c') diff --git a/bootstrap/util.c b/bootstrap/util.c index be3aea0..c9be845 100644 --- a/bootstrap/util.c +++ b/bootstrap/util.c @@ -16,6 +16,7 @@ jkhash(u32 h, const u8 *data, size_t length) { } static const char *filepaths[100]; +static const char *filemmaps[100]; static int nfilepaths = 0; int addfilepath(const char *s) { @@ -81,6 +82,50 @@ xstrdup(const char *s) { return strcpy(xmalloc(strlen(s) + 1), s); } +#include +#include +#include +#include + +static void +eprifileline(struct span span) { + const char *src = filemmaps[span.fileid]; + long i, j ,n; + if (!src) { + const char *path = fileid2path(span.fileid); + struct stat st; + int fd = open(path, O_RDONLY); + if (fd < -1) { + perror("open()"); + return; + } + if (stat(path, &st) < 0) { + perror("stat()"); + close(fd); + return; + } + filemmaps[span.fileid] = src = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + assert(src && src != (void *)-1 && "mmap"); + close(fd); + } + // line begin + for (i = span.idx; i > 0 && src[i] != '\n'; --i) ; + ++i; + + // line end + for (j = span.idx; src[j] && src[j] != '\n'; ++j) ; + --j; + + n = fprintf(stderr, "%4d| ", span.line); + for (long k = i; k < j; ++k) + epri("%c", src[k]); + epri("\n"); + while (n--) + epri(" "); + for (int k = 0; src[k] && src[k] != '\n'; ++k) + fprintf(stderr, "%s", k + 1 == span.col ? "^" : " "); + epri("\n"); +} void noreturn fatal(struct parser *P, struct span span, const char *fmt, ...) { @@ -91,12 +136,14 @@ fatal(struct parser *P, struct span span, const char *fmt, ...) { epri("%s:%d:%d: error: ", fileid2path(span.fileid), span.line, span.col); vepri(fmt, ap); epri("\n"); + eprifileline(span); for (struct expan *ep = P->curexpan; ep; ep = ep->prev, ++i) { if (ep->name && (i < 8 || !ep->prev || !ep->prev->prev)) { span = ep->span; - epri(" while expanding macro `%s' at %s:%d:%d\n", + epri("* while expanding macro `%s' at %s:%d:%d\n", ep->name, fileid2path(ep->span.fileid), span.line, span.col); + eprifileline(span); } else if (ep->name && i == 10) { epri(" ... (some expansions omitted)\n"); } -- cgit v1.2.3