#include #include #include #include #include #include #include #include #include struct ctx *context_create(const char *path) { struct ctx *ctx = calloc(1, sizeof(*ctx)); ctx->tokens = calloc(TOKENS_MAX, sizeof(*ctx->tokens)); ctx->location.path = path; // TODO: strdup? FILE *file = fopen(path, "r"); assert(file); // Find size of file fseek(file, 0, SEEK_END); ctx->location.size = ftell(file); rewind(file); assert(ctx->location.size); ctx->location.data = malloc(ctx->location.size + 1); assert(ctx->location.data); fread(ctx->location.data, 1, ctx->location.size, file); fclose(file); ctx->location.data[ctx->location.size] = 0; ctx->tree.head = tree_create(); ctx->tree.current = NULL; return ctx; } void context_destroy(struct ctx *ctx) { if (!ctx) return; if (ctx->location.data) free(ctx->location.data); if (ctx->data && ctx->data != ctx->location.data) free(ctx->data); if (ctx->tokens) free(ctx->tokens); if (ctx->tree.head) tree_destroy(ctx->tree.head); free(ctx); } char context_getch(struct ctx *ctx, size_t i) { if (i >= ctx->size || !ctx->data[i]) errln(&ctx->location, "Unexpected end of buffer"); return ctx->data[i]; } #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' || location->data[index] == MACRO_NEWLINE) line++; index++; continue; } const char *end = strchr(location->data + index, '\n') + 1; assert(end > location->data); 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%s\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), "^ (around here)"); 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->location.line = 0; ctx->location.column = 0; }