Files
Chloride/src/err.c
William Bell 81efaaac07 fix path bug
2025-09-17 17:25:42 +01:00

199 lines
5.0 KiB
C

/*
* SPDX-FileCopyrightText: 2025 William Bell
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "err.h"
#include "../external/libdye/include/dye.h"
#include <ctype.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
if (lineptr == NULL || n == NULL || stream == NULL) {
return -1;
}
size_t pos = 0;
int c;
if (*lineptr == NULL || *n == 0) {
*n = 128; // initial buffer size
*lineptr = malloc(*n);
if (*lineptr == NULL) {
return -1;
}
}
while ((c = fgetc(stream)) != EOF) {
// Resize buffer if needed
if (pos + 1 >= *n) {
size_t new_size = *n * 2;
char *new_ptr = realloc(*lineptr, new_size);
if (new_ptr == NULL) {
return -1;
}
*lineptr = new_ptr;
*n = new_size;
}
(*lineptr)[pos++] = (char)c;
if (c == '\n') {
break;
}
}
if (pos == 0 && c == EOF) {
return -1; // EOF and no data read
}
(*lineptr)[pos] = '\0';
return (ssize_t)pos;
}
#endif
const ArErr no_err = (ArErr){"", "", "", 0, 0, 0, false};
ArErr create_err(int64_t line, int64_t column, int length, char *path,
const char *type, const char *fmt, ...) {
ArErr err;
err.exists = true;
if (path)
strcpy(err.path, path);
else {
err.path[0] = '\0';
}
err.line = line;
err.column = column;
err.length = length;
// Copy error type safely
snprintf(err.type, sizeof(err.type), "%s", (char *)type);
// Format error message
va_list args;
va_start(args, fmt);
vsnprintf(err.message, sizeof(err.message), fmt, args);
va_end(args);
return err;
}
void output_err(ArErr err) {
if (!err.exists)
return;
dye(stderr, DYE_WHITE, DYE_RED);
fprintf(stderr, "ERROR!");
dye(stderr, DYE_RESET, DYE_RESET);
fprintf(stderr, " ");
dyefg(stderr, DYE_RED);
dye_style(stderr, DYE_STYLE_BOLD);
fprintf(stderr, "%s", err.type);
dye_style(stderr, DYE_STYLE_RESET);
dyefg(stderr, DYE_RESET);
fprintf(stderr, ": ");
dyefg(stderr, DYE_RED);
fprintf(stderr, "%s", err.message);
dye_style(stderr, DYE_STYLE_RESET);
dyefg(stderr, DYE_RESET);
fprintf(stderr, "\n");
if (strlen(err.path) && err.line) {
dyefg(stderr, DYE_GRAY);
fprintf(stderr, " --> ");
dyefg(stderr, DYE_CYAN);
fprintf(stderr, "%s", err.path);
dyefg(stderr, DYE_GRAY);
fprintf(stderr, ":");
dyefg(stderr, DYE_YELLOW);
fprintf(stderr, "%" PRIu64, err.line);
dyefg(stderr, DYE_GRAY);
fprintf(stderr, ":");
dyefg(stderr, DYE_YELLOW);
fprintf(stderr, "%" PRIu64, err.column);
dye_style(stderr, DYE_STYLE_RESET);
dyefg(stderr, DYE_RESET);
fprintf(stderr, "\n");
FILE *file = fopen(err.path, "r");
if (file) {
dye_style(stderr, DYE_STYLE_RESET);
dyefg(stderr, DYE_RESET);
int line_number_width = snprintf(NULL, 0, "%" PRIu64, err.line);
char *buffer = NULL;
size_t size = 0;
int current_line = 1;
ssize_t len;
while ((len = getline(&buffer, &size, file)) != -1) {
if (current_line == err.line) {
break;
}
current_line++;
}
fprintf(stderr, " ");
for (int i = 0; i < line_number_width; i++) {
fprintf(stderr, " ");
}
fprintf(stderr, "|\n");
for (ssize_t i = 0; i < len; i++) {
if (buffer[i] == '\n') {
buffer[i] = '\0';
break;
}
}
char *line_starts = buffer;
size_t skipped_chars = 0;
while (*line_starts && isspace((unsigned char)*line_starts) &&
line_starts - buffer < err.column - 1) {
line_starts++;
err.column--;
skipped_chars++;
}
fprintf(stderr, " %" PRIu64 " | ", err.line);
if (err.length) {
fprintf(stderr, "%.*s", (int)err.column - 1, line_starts);
dyefg(stderr, DYE_RED);
dye_style(stderr, DYE_STYLE_BOLD);
fprintf(stderr, "%.*s", err.length, line_starts + err.column - 1);
dye_style(stderr, DYE_STYLE_RESET);
dyefg(stderr, DYE_RESET);
fprintf(stderr, "%.*s",
(int)len - (int)skipped_chars - (int)err.column -
(int)err.length + 1,
line_starts + (int)err.column + err.length - 1);
for (int64_t i = 0; i < err.column - 1; i++) {
fprintf(stderr, " ");
}
} else {
fprintf(stderr, "%s", line_starts);
}
free(buffer);
fprintf(stderr, "\n ");
for (int i = 0; i < line_number_width; i++) {
fprintf(stderr, " ");
}
fprintf(stderr, "| ");
for (int i = 1; i < err.column; i++) {
fprintf(stderr, " ");
}
dyefg(stderr, DYE_RED);
dye_style(stderr, DYE_STYLE_BOLD);
for (int i = 0; i < err.length; i++) {
fprintf(stderr, "^");
}
dye_style(stderr, DYE_STYLE_RESET);
dyefg(stderr, DYE_RESET);
fprintf(stderr, "\n");
}
}
}