diff options
| author | 2022-08-06 07:07:26 +0200 | |
|---|---|---|
| committer | 2022-08-06 07:07:26 +0200 | |
| commit | 1dd19e56fb81d1334bb21e4aa097f9593576feb7 (patch) | |
| tree | e3e986837c05c3cd0d7f86a3fec6a7798568580c /bootstrap/util.c | |
| parent | 6c0dc2b1171b22a93e61f50fa46852a70e129e50 (diff) | |
print source on error
Diffstat (limited to 'bootstrap/util.c')
| -rw-r--r-- | bootstrap/util.c | 49 |
1 files changed, 48 insertions, 1 deletions
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 <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +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"); } |