diff options
Diffstat (limited to 'src/context.c')
-rw-r--r-- | src/context.c | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/src/context.c b/src/context.c index ff0291a..be93db0 100644 --- a/src/context.c +++ b/src/context.c @@ -1,6 +1,7 @@ #include <assert.h> -#include <stdio.h> +#include <math.h> #include <stdlib.h> +#include <string.h> #include <context.h> #include <tokenize.h> @@ -10,23 +11,23 @@ struct ctx *context_create(const char *path) { struct ctx *ctx = calloc(1, sizeof(*ctx)); ctx->tokens = calloc(TOKENS_MAX, sizeof(*ctx->tokens)); - ctx->path = path; // TODO: strdup? + ctx->location.path = path; // TODO: strdup? FILE *file = fopen(path, "r"); assert(file); // Find size of file fseek(file, 0, SEEK_END); - ctx->size = ftell(file); + ctx->location.size = ftell(file); rewind(file); - assert(ctx->size); + assert(ctx->location.size); - ctx->raw = malloc(ctx->size + 1); - assert(ctx->raw); - fread(ctx->raw, 1, ctx->size, file); + ctx->location.data = malloc(ctx->location.size + 1); + assert(ctx->location.data); + fread(ctx->location.data, 1, ctx->location.size, file); fclose(file); - ctx->raw[ctx->size] = 0; + ctx->location.data[ctx->location.size] = 0; ctx->tree.head = tree_create(); ctx->tree.current = NULL; @@ -39,10 +40,10 @@ void context_destroy(struct ctx *ctx) if (!ctx) return; - if (ctx->raw) - free(ctx->raw); + if (ctx->location.data) + free(ctx->location.data); - if (ctx->data && ctx->data != ctx->raw) + if (ctx->data && ctx->data != ctx->location.data) free(ctx->data); if (ctx->tokens) @@ -54,8 +55,47 @@ void context_destroy(struct ctx *ctx) free(ctx); } +#define CONTEXT_COUNT 3 +void context_print(FILE *fd, struct ctx_location *location) +{ + size_t start_line = fmax((int)location->line - CONTEXT_COUNT, 0); + size_t end_line = location->line + CONTEXT_COUNT + 1; + + for (size_t line = 0, index = 0; line < end_line;) { + if (line < start_line) { + if (location->data[index++] == '\n') + line++; + continue; + } + + const char *end = strchr(location->data + index, '\n') + 1; + assert(end); + size_t length = end - (location->data + index) - 1; + + if (location->line == line) { + int pointer_length = location->column + 9; + char *pointer = malloc(pointer_length); // Literally a pointer + fprintf(fd, + "\x1B[1;32m%6lu | %.*s\x1B[1;31m%c\x1B[1;32m%.*s\n\x1B[1;31m%.*s%c\x1B[0m\n", + line + 1, (int)location->column, location->data + index, + *(location->data + index + location->column), + (int)(length - location->column - 1), + location->data + index + location->column + 1, pointer_length, + (char *)memset(pointer, '~', pointer_length), '^'); + free(pointer); + } else { + fprintf(fd, "%6lu | %.*s\n", line + 1, (int)length, location->data + index); + } + + index = end - location->data; + line++; + if (index >= location->size) + return; + } +} + void context_rewind(struct ctx *ctx) { - ctx->line = 0; - ctx->column = 0; + ctx->location.line = 0; + ctx->location.column = 0; } |