#include "error_helper.h" #include #include #include #include void printError(char const *error, SourceCode *sourceCode, char const *begin, char const *end, ...) { va_list args; va_start(args, end); char *errorStr; vasprintf(&errorStr, error, args); const Code *code = NULL; for (size_t i = 0; i < sourceCode->size; ++i) { const Code *source = sourceCode->codes[i]; if (source->code <= begin && strlen(source->code) + source->code >= end) { code = source; } } if (code == NULL) { fprintf(stderr, "Compiler Internal Error: the error is in no source code\n"); return; } char const *lineBegin = code->code; int line = 1; char const *iter = code->code; for (; iter < begin; ++iter) { const char c = *iter; switch (c) { case '\0': fprintf(stderr, "Compiler Internal Error: in printing errors\n"); 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 %s:%d\n", errorStr, code->filePath, 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); }