aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/util.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-06 07:07:26 +0200
committerlemon <lsof@mailbox.org>2022-08-06 07:07:26 +0200
commit1dd19e56fb81d1334bb21e4aa097f9593576feb7 (patch)
treee3e986837c05c3cd0d7f86a3fec6a7798568580c /bootstrap/util.c
parent6c0dc2b1171b22a93e61f50fa46852a70e129e50 (diff)
print source on error
Diffstat (limited to 'bootstrap/util.c')
-rw-r--r--bootstrap/util.c49
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");
}