diff options
Diffstat (limited to 'src/compiler/error_helper/error_helper.c')
-rw-r--r-- | src/compiler/error_helper/error_helper.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/compiler/error_helper/error_helper.c b/src/compiler/error_helper/error_helper.c new file mode 100644 index 0000000..fd648e4 --- /dev/null +++ b/src/compiler/error_helper/error_helper.c @@ -0,0 +1,85 @@ +#include "error_helper.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +void printError(char const *error, SourceCode code, char const *begin, + char const *end, ...) { + va_list args; + va_start(args, end); + char *errorStr; + vasprintf(&errorStr, error, args); + + char const *lineBegin = code; + int line = 1; + + char const *iter = code; + for (; iter < begin; ++iter) { + const char c = *iter; + switch (c) { + case '\0': + fprintf(stderr, + "Compiler Internal Error: in printing errors at compiler %s:%d", + __FILE_NAME__, __LINE__); + exit(1); + case '\n': + lineBegin = iter + 1; + ++line; + break; + } + } + char const *lineEnd = end; + + for (;; ++iter) { + const char c = *iter; + switch (c) { + case '\0': + if (iter < end) { + fprintf( + stderr, + "Compiler Internal Error: in printing errors at compiler %s:%d", + __FILE_NAME__, __LINE__); + exit(1); + } + lineEnd = iter; + goto AFTER_LOOP; + case '\n': + lineEnd = iter; + if (iter >= end) { + goto AFTER_LOOP; + } + break; + } + } +AFTER_LOOP: + + fprintf(stderr, "Error: %s at line %d\n", errorStr, line); + + int printed = 0; + for (iter = lineBegin; iter < lineEnd; ++iter) { + fprintf(stderr, "%c", *iter); + if (*iter == '\n') { + PRINT_LINE: + for (int i = 0; i < printed; ++i) { + const char *ch = iter - printed + i; + if (begin <= ch && ch < end) { + fprintf(stderr, "^"); + } else { + fprintf(stderr, " "); + } + } + if (iter + 1 != lineEnd) { + fprintf(stderr, "\n"); + printed = 0; + } + } else if (iter + 1 == lineEnd) { + fprintf(stderr, "\n"); + goto PRINT_LINE; + } else { + ++printed; + } + } + fprintf(stderr, "\n"); + free(errorStr); +} |