#include "log.h" #include "util.h" #include #include #include #include static LogError* s_logError = NULL; void log_set_output(LogError* destination) { s_logError = destination; } void log_error(const char* msg) { if (s_logError != NULL) { s_logError(msg); } else { fprintf(stderr, "Error: %s\n", msg); } } void log_on_line(Location* loc, const char* msg, ...) { /* Declarations first for C89 */ char* line_prefix = NULL; char* formatted_msg = NULL; char* header = NULL; char* buffer = NULL; va_list args; int caret_len; char* p; int i1, i2; size_t i3; size_t total_size; line_prefix = format_string("%d| ", loc->line); if (!line_prefix) goto cleanup; caret_len = loc->column_end - loc->column_start + 1; if (caret_len < 1) caret_len = 1; /* Format the message */ va_start(args, msg); formatted_msg = format_string_va(msg, args); va_end(args); if (!formatted_msg) goto cleanup; /* Header logic */ if (loc->filename && loc->filename[0] != '\0') { header = format_string("--- %s ---\n", loc->filename); } else { header = format_string("--- \n"); } if (!header) goto cleanup; total_size = strlen(header) + 20 + strlen(line_prefix) + loc->line_text.length + 2 + /* line| text\n */ strlen(line_prefix) + loc->column_start - 1 + caret_len + 2 + /* indent + ^^\n */ strlen(line_prefix) + 3 + strlen(formatted_msg) + 2 + /* indent + msg\n */ 10; buffer = (char*)malloc(total_size); if (!buffer) goto cleanup; p = buffer; p += sprintf(p, "%s", header); p += sprintf(p, "%s%.*s\n", line_prefix, (int)loc->line_text.length, loc->line_text.data); /* Caret line */ for (i1 = 0; i1 < (int)(strlen(line_prefix) + loc->column_start - 1); i1++) *p++ = ' '; for (i2 = 0; i2 < caret_len; i2++) *p++ = '^'; *p++ = '\n'; /* Message line */ for (i3 = 0; i3 < strlen(line_prefix); i3++) *p++ = ' '; p += sprintf(p, "%s\n", formatted_msg); *p = '\0'; log_error(buffer); cleanup: free(line_prefix); free(formatted_msg); free(header); free(buffer); }