mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
79 lines
1.8 KiB
C
79 lines
1.8 KiB
C
#ifndef _LOCFILE_H
|
|
#define _LOCFILE_H
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include <stdarg.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; i<length; i++) {
|
|
if (data[i] == '\n') l->nlines++;
|
|
}
|
|
l->linemap = malloc(sizeof(int) * (l->nlines + 1));
|
|
l->linemap[0] = 0;
|
|
int line = 1;
|
|
for (int i=0; i<length; i++) {
|
|
if (data[i] == '\n') {
|
|
l->linemap[line] = i;
|
|
line++;
|
|
}
|
|
}
|
|
l->linemap[l->nlines] = length;
|
|
}
|
|
|
|
static void locfile_free(struct locfile* l) {
|
|
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, "<unknown location>\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
|