#ifndef _LOCFILE_H #define _LOCFILE_H #include #include #include #include #include "jv_alloc.h" typedef struct { int start, end; } location; static const location UNKNOWN_LOCATION = {-1, -1}; struct locfile { const char* data; int length; int* linemap; int nlines; }; static void locfile_init(struct locfile* l, const char* data, int length) { l->data = data; l->length = length; l->nlines = 1; for (int i=0; inlines++; } l->linemap = jv_mem_alloc(sizeof(int) * (l->nlines + 1)); l->linemap[0] = 0; int line = 1; for (int i=0; ilinemap[line] = i; line++; } } l->linemap[l->nlines] = length; } static void locfile_free(struct locfile* l) { jv_mem_free(l->linemap); } static int locfile_get_line(struct locfile* l, int pos) { assert(pos < l->length); int line = 0; while (l->linemap[line+1] < pos) line++; assert(line < l->nlines); return line; } static int locfile_line_length(struct locfile* l, int line) { assert(line < l->nlines); return l->linemap[line+1] - l->linemap[line]; } static void locfile_locate(struct locfile* l, location loc, const char* fmt, ...) { va_list fmtargs; va_start(fmtargs, fmt); vfprintf(stderr, fmt, fmtargs); va_end(fmtargs); fprintf(stderr, "\n"); if (loc.start == -1) { fprintf(stderr, "\n"); return; } int startline = locfile_get_line(l, loc.start); int offset = l->linemap[startline]; fprintf(stderr, "%.*s\n", locfile_line_length(l, startline), l->data + offset); fprintf(stderr, "%*s", loc.start - offset, ""); for (int i = loc.start; i < loc.end && i < offset + locfile_line_length(l, startline); i++){ fprintf(stderr, "^"); } fprintf(stderr, "\n"); } #endif