diff options
author | Marvin Borner | 2021-08-07 23:39:21 +0200 |
---|---|---|
committer | Marvin Borner | 2021-08-07 23:39:21 +0200 |
commit | 51c4defc436c0d119941eb6d5b953d27b5b8e6f7 (patch) | |
tree | c90b6329b81a4c4715f7860cb3a6a7b1d3174e37 | |
parent | 55e5ec54eaef97e87efefc2294a5afaf8935566b (diff) |
Better error logging
-rw-r--r-- | inc/context.h | 14 | ||||
-rw-r--r-- | inc/log.h | 3 | ||||
-rw-r--r-- | inc/tokenize.h | 1 | ||||
-rw-r--r-- | src/context.c | 66 | ||||
-rw-r--r-- | src/lint.c | 2 | ||||
-rw-r--r-- | src/log.c | 66 | ||||
-rw-r--r-- | src/main.c | 9 | ||||
-rw-r--r-- | src/preprocess.c | 34 | ||||
-rw-r--r-- | src/tokenize.c | 32 | ||||
-rw-r--r-- | src/treeify.c | 2 |
10 files changed, 116 insertions, 113 deletions
diff --git a/inc/context.h b/inc/context.h index b11e23d..5b314d7 100644 --- a/inc/context.h +++ b/inc/context.h @@ -2,18 +2,25 @@ #define CONTEXT_H #include <stddef.h> +#include <stdio.h> typedef struct { size_t start, end; } ctx_string; -struct ctx { +struct ctx_location { size_t line; size_t column; const char *path; - char *raw; - char *data; + char *data; // Raw + size_t size; +}; + +struct ctx { + struct ctx_location location; + + char *data; // Preprocessed size_t size; size_t token_count; @@ -27,6 +34,7 @@ struct ctx { struct ctx *context_create(const char *path); void context_destroy(struct ctx *ctx); +void context_print(FILE *fd, struct ctx_location *location); void context_rewind(struct ctx *ctx); #endif @@ -3,7 +3,6 @@ #include <context.h> -__attribute__((noreturn)) void errln(struct ctx *ctx, const char *fmt, ...); -__attribute__((noreturn)) void err(const char *fmt, ...); +__attribute__((noreturn)) void errln(struct ctx_location *location, const char *fmt, ...); #endif diff --git a/inc/tokenize.h b/inc/tokenize.h index d1a2931..f5e8600 100644 --- a/inc/tokenize.h +++ b/inc/tokenize.h @@ -28,6 +28,7 @@ enum token_type { struct token { enum token_type type; + struct ctx_location location; ctx_string string; }; 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; } @@ -17,5 +17,5 @@ void lint(struct ctx *ctx) } if (parens != 0) - errln(ctx, "Invalid parens balance"); + errln(&ctx->location, "Invalid parens balance"); } @@ -1,78 +1,24 @@ +#include <assert.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <log.h> -static void context_print(FILE *fd, struct ctx *ctx) +void errln(struct ctx_location *location, const char *fmt, ...) { - const char *data = ctx->data ? ctx->data : ctx->raw; + fprintf(stderr, "\x1B[1;36m%s:%lu:%lu:\x1B[0m ", location->path, location->line + 1, + location->column + 1); - // Find line, column - size_t line = 0, column = 0, index = 0; - for (; index < ctx->size; index++) { - char cur = data[index]; + fprintf(stderr, "\x1B[1;31mError:\x1B[0m "); - column++; - - if (line == ctx->line && column == ctx->column) - break; - - if (cur == '\n') { - line++; - column = 0; - continue; - } else if (cur == '\0') { - fprintf(stderr, "Invalid context!"); - context_destroy(ctx); - exit(1); - break; - } - } - - if (++index >= ctx->size) - return; // Couldn't find context, idc? - - fprintf(fd, "\x1B[1;36m%s:%ld:%ld:\x1B[0m '", ctx->path, ctx->line + 1, ctx->column + 1); - - // Print line context - size_t start = ctx->column > 5 ? index - 5 : index; - size_t end = ctx->size - index > 5 ? index + 5 : index + 1; - for (size_t i = start; i < end; i++) { - if (i == index) { - fprintf(fd, "\x1B[1;32m%c\x1B[0m", data[i]); - } else { - fprintf(fd, "%c", data[i]); - } - } - fprintf(fd, "': "); -} - -void errln(struct ctx *ctx, const char *fmt, ...) -{ - context_print(stderr, ctx); - - fprintf(stderr, "\x1B[1;31m"); va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); va_end(ap); - fprintf(stderr, "\x1B[0m"); - context_destroy(ctx); - exit(1); -} - -void err(const char *fmt, ...) -{ - fprintf(stderr, "\x1B[1;31m"); - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); - va_end(ap); - fprintf(stderr, "\x1B[0m"); + context_print(stderr, location); exit(1); } @@ -1,3 +1,6 @@ +#include <stdio.h> +#include <stdlib.h> + #include <context.h> #include <lint.h> #include <log.h> @@ -7,8 +10,10 @@ int main(int argc, char *argv[]) { - if (argc < 2) - err("Not enough arguments!"); + if (argc < 2) { + fprintf(stderr, "Not enough arguments!"); + exit(1); + } struct ctx *ctx = context_create(argv[1]); preprocess(ctx); diff --git a/src/preprocess.c b/src/preprocess.c index 8d9394a..3a0c0bc 100644 --- a/src/preprocess.c +++ b/src/preprocess.c @@ -1,6 +1,7 @@ #include <assert.h> #include <math.h> #include <stddef.h> +#include <stdlib.h> #include <string.h> #include <log.h> @@ -8,43 +9,46 @@ static void preprocess_erase(struct ctx *ctx, size_t start) { - assert(ctx->raw[start] == '#'); + assert(ctx->data[start] == '#'); for (size_t i = start; i < ctx->size; i++) { - char cur = ctx->raw[i]; + char cur = ctx->data[i]; if (cur == '\n' || cur == '\0') break; - ctx->raw[i] = ' '; // Spaces get skipped by tokenizer anyways + ctx->data[i] = ' '; // Spaces get skipped by tokenizer anyways } } void preprocess(struct ctx *ctx) { - for (size_t i = 0; i < ctx->size; i++) { - const char cur = ctx->raw[i]; + ctx->size = ctx->location.size; + ctx->data = malloc(ctx->size); + memcpy(ctx->data, ctx->location.data, ctx->size); - ctx->column++; + for (size_t i = 0; i < ctx->location.size; i++) { + const char cur = ctx->location.data[i]; + + ctx->location.column++; if (cur == '\n') { - ctx->line++; - ctx->column = 0; + ctx->location.line++; + ctx->location.column = 0; continue; } else if (cur == '\0') { break; - } else if (cur == '#' && ctx->column == 1) { - if (strncmp(ctx->raw + i + 1, "inc ", fmin(4, ctx->size - i)) == 0) { + } else if (cur == '#' && ctx->location.column == 1) { + if (strncmp(ctx->location.data + i + 1, "inc ", + fmin(4, ctx->location.size - i)) == 0) { // TODO: Add include features - } else if (*(ctx->raw + i + 1) == '#') { + } else if (*(ctx->location.data + i + 1) == '#') { // Comment } else { - errln(ctx, "Invalid preprocessing directive"); + errln(&ctx->location, "Invalid preprocessing directive"); } preprocess_erase(ctx, i); } } - ctx->data = ctx->raw; - ctx->line = 0; - ctx->column = 0; + context_rewind(ctx); } diff --git a/src/tokenize.c b/src/tokenize.c index 02059a8..2a0eea6 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -13,7 +13,7 @@ static char next_non_alnum(struct ctx *ctx, size_t start) if (!isalnum(ctx->data[i])) return ctx->data[i]; - errln(ctx, "Unexpected end of buffer"); + errln(&ctx->location, "Unexpected end of buffer"); } static bool peek_to_is_alnum(struct ctx *ctx, size_t start, char ch) @@ -28,7 +28,7 @@ static bool peek_to_is_alnum(struct ctx *ctx, size_t start, char ch) return false; } - errln(ctx, "Unexpected end of buffer"); + errln(&ctx->location, "Unexpected end of buffer"); } static size_t peek_alnum_to(struct ctx *ctx, size_t start, char ch) @@ -40,10 +40,10 @@ static size_t peek_alnum_to(struct ctx *ctx, size_t start, char ch) return i; if (!isalnum(cur)) - errln(ctx, "'%c' is not alpha-numeric", cur); + errln(&ctx->location, "'%c' is not alpha-numeric", cur); } - errln(ctx, "Unexpected end of buffer"); + errln(&ctx->location, "Unexpected end of buffer"); } static size_t peek_identifier(struct ctx *ctx, size_t start, char ch) @@ -55,10 +55,10 @@ static size_t peek_identifier(struct ctx *ctx, size_t start, char ch) return i; if (!isalnum(cur) && (cur < '!' || cur > '~')) - errln(ctx, "'%c' is not an identifier", cur); + errln(&ctx->location, "'%c' is not an identifier", cur); } - errln(ctx, "Unexpected end of buffer"); + errln(&ctx->location, "Unexpected end of buffer"); } static size_t peek_to(struct ctx *ctx, size_t start, char ch) @@ -70,7 +70,7 @@ static size_t peek_to(struct ctx *ctx, size_t start, char ch) return i; } - errln(ctx, "Unexpected end of buffer"); + errln(&ctx->location, "Unexpected end of buffer"); } static void token_add(struct ctx *ctx, enum token_type type, size_t start, size_t end) @@ -79,15 +79,16 @@ static void token_add(struct ctx *ctx, enum token_type type, size_t start, size_ token.type = type; token.string.start = start; token.string.end = end; + token.location = ctx->location; assert(++ctx->token_count < TOKENS_MAX); ctx->tokens[ctx->token_count] = token; if (type == NEWLINE) { - ctx->line++; - ctx->column = 0; + ctx->location.line++; + ctx->location.column = 0; } else { - ctx->column += end - start; + ctx->location.column += end - start; } } @@ -95,15 +96,14 @@ void token_print(struct ctx *ctx, struct token *token) { assert(token->type != UNKNOWN); - printf("[token type=%d] '", token->type); + printf("[token type=%d] ", token->type); if (token->type == NEWLINE || token->type == END) { printf("' (Unprintable)\n"); return; } - for (size_t i = token->string.start; i < token->string.end; i++) - printf("%c", ctx->data[i]); - printf("'\n"); + printf("'%.*s'\n", (int)(token->string.end - token->string.start), + ctx->data + token->string.start); } void tokenize(struct ctx *ctx) @@ -131,7 +131,7 @@ void tokenize(struct ctx *ctx) token_add(ctx, EQUAL, i, i + 1); continue; case ' ': - ctx->column++; + ctx->location.column++; continue; default: break; @@ -145,7 +145,7 @@ void tokenize(struct ctx *ctx) } else { // Unnamed identifier ('_') end_param = peek_to(ctx, start_param, ' '); if (end_param - start_param != 1 || ctx->data[start_param] != '_') - errln(ctx, "Invalid param identifier"); + errln(&ctx->location, "Invalid param identifier"); } token_add(ctx, TYPE, i, start_param - 1); diff --git a/src/treeify.c b/src/treeify.c index 8da6481..5539d21 100644 --- a/src/treeify.c +++ b/src/treeify.c @@ -12,7 +12,7 @@ static void __expect(struct ctx *ctx, struct token *token, enum token_type type, if (token->type != type) { printf("[DBG] %s:%d: %s\n", file, line, func); token_print(ctx, token); - err("Expected token of type %s!\n", type_enum); + errln(&token->location, "Expected token of type %s", type_enum); } } |