summaryrefslogtreecommitdiff
path: root/err.c
diff options
context:
space:
mode:
Diffstat (limited to 'err.c')
-rw-r--r--err.c88
1 files changed, 79 insertions, 9 deletions
diff --git a/err.c b/err.c
index 0d8c09c..4c81c27 100644
--- a/err.c
+++ b/err.c
@@ -3,15 +3,6 @@
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 ERR_EMACS 1 */
-
-#ifndef USE_COLORED_TEXT
-#if ERR_EMACS
-#define USE_COLORED_TEXT 0
-#else
-#define USE_COLORED_TEXT 1
-#endif
-#endif
#define TEXT_ERR_START "\x1b[91m"
#define TEXT_ERR_END "\x1b[0m"
@@ -23,10 +14,89 @@
#define TEXT_IMPORTANT_START "\x1b[1m"
#define TEXT_IMPORTANT_END "\x1b[0m"
+#define TEXT_INDICATOR_START "\x1b[96m"
+#define TEXT_INDICATOR_END "\x1b[0m"
+
#if defined(TOC_DEBUG) && __STDC_VERSION__ >= 199901
#define ERR_SHOW_SOURCE_LOCATION 1
#endif
+
+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);
+}
+
+
static inline const char *ordinals(size_t x) {
switch (x % 10) {
case 1: return "st";