diff options
Diffstat (limited to 'bootstrap')
| -rw-r--r-- | bootstrap/parse.c | 4 | ||||
| -rw-r--r-- | bootstrap/util.c | 49 |
2 files changed, 50 insertions, 3 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c index 4372cdc..381cfcc 100644 --- a/bootstrap/parse.c +++ b/bootstrap/parse.c @@ -544,7 +544,7 @@ parsefntype(struct parser *P) { ty.fn.variadic = 1; } else { const struct type *param; - lexexpects(P, TKident, "parameter name"); + tok = lexexpects(P, TKident, "parameter name"); param = parsetype(P); if (!completetype(param)) fatal(P, tok.span, "parameter type is incomplete (%t)", @@ -1863,7 +1863,7 @@ parsefn(struct decl *decl, struct parser *P) { if (lexmatch(P, &tok, '...')) { fn->variadic = 1; } else { - param.name = lexexpects(P, TKident, "parameter name").str; + param.name = (tok = lexexpects(P, TKident, "parameter name")).str; param.ty = parsetype(P); if (!completetype(param.ty)) fatal(P, tok.span, "parameter type is incomplete (%t)", 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"); } |