summaryrefslogtreecommitdiff
path: root/location.c
blob: 12c932f4666910013963e45fcef10aacfc90cb30 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/*
  Copyright (C) 2019, 2020 Leo Tenenbaum.
  This file is part of toc. toc is distributed under version 3 of the GNU General Public License, without any warranty whatsoever.
  You should have received a copy of the GNU General Public License along with toc. If not, see <https://www.gnu.org/licenses/>.
*/

#define TEXT_INDICATOR_START "\x1b[96m"
#define TEXT_INDICATOR_END "\x1b[0m"

static void print_pos_highlight(FILE *out, ErrCtx *ctx, File *file, U32 start_pos, U32 end_pos) {
	char *str = file->contents;
	if (!str) {
		return;
	}
	
	char *start = str + start_pos;
	char *line_start = start;
	char *end = str + end_pos;

	/* go back to last newline / 0 byte */
	while (*line_start != '\0' && *line_start != '\n') --line_start;
	if (line_start < start) ++line_start;

	/* skip space at start of line */
	while (isspace(*line_start) && line_start < end)
		++line_start;
		
	char *line_end = strchr(start, '\n');
	int has_newline = line_end != NULL;
	if (!has_newline)
		line_end = strchr(start, '\0');
	assert(line_end);
	if (!line_start[0])
		fprintf(out, "<end of file>");
	else {
		/* write up to start of error */
		fwrite(line_start, 1, (size_t)(start - line_start), out);
		if (ctx->color_enabled)
			fprintf(out, TEXT_INDICATOR_START);
		if (line_end < end) {
			/* write error part (only go to end of line) */
			fwrite(start, 1, (size_t)(line_end - start), out);
			if (ctx->color_enabled)
				fprintf(out, TEXT_INDICATOR_END);
		} else {
			/* write error part */
			fwrite(start, 1, (size_t)(end - start), out);
			if (ctx->color_enabled)
				fprintf(out, TEXT_INDICATOR_END);
			/* write rest of line */
			fwrite(end, 1, (size_t)(line_end - end), out);
		}
	}
	fprintf(out, "\n");
}

static void print_location_highlight(FILE *out, Location where) {
	if (where.start) {
		ErrCtx *ctx = where.file->ctx;
		print_pos_highlight(out, ctx, where.file, where.start->pos.start, where.end[-1].pos.end);
	}
	
}

/* for debugging */
static void fprint_location(FILE *out, Location location) {
	if (location.start) {
		fprintf(out, "Line %ld of %s: ", (long)location.start->pos.line, location.file->filename);
	} else {
		U32 line = location.simple_location.line;
		if (line)
			fprintf(out, "Line %lu of %s: ", (unsigned long)line, location.file->filename);
		else
			fprintf(out, "In file %s: ", location.file->filename);
		return;
	}
	print_location_highlight(out, location);
}

static void print_location(Location location) {
	fprint_location(stdout, location);
}