#include "../include/mrc_diagnostic.h"
static void
line_and_column_by_start_and_offset(const uint8_t *source_start, const uint8_t *location_start, uint32_t *line, uint32_t *column)
{
if (!location_start) {
*line = 0;
*column = 0;
return;
}
uint32_t start_offset = (uint32_t)(location_start - source_start);
uint32_t l = 1, c = 1;
const uint8_t *p = source_start;
while (p < source_start + start_offset) {
if (*p == '\n') {
l++;
c = 1;
} else {
c++;
}
p++;
}
*line = l;
*column = c;
}
const char *
mrc_diagnostic_code_to_string(mrc_diagnostic_code code)
{
switch (code) {
case MRC_PARSER_ERROR:
return "syntax error";
case MRC_GENERATOR_ERROR:
return "generator error";
case MRC_PARSER_WARNING:
return "syntax warning";
case MRC_GENERATOR_WARNING:
return "generator warning";
default:
return "unknown";
}
}
void
mrc_diagnostic_list_append(mrc_ccontext *c, const uint8_t * location_start, const char *message, mrc_diagnostic_code code)
{
mrc_diagnostic_list *list = mrc_calloc(c, 1, sizeof(mrc_diagnostic_list));
line_and_column_by_start_and_offset(c->p->start, location_start, &list->line, &list->column);
char buf[256];
const char *diagnostic_code_str = mrc_diagnostic_code_to_string(code);
snprintf(buf, sizeof(buf), "%s, %s", diagnostic_code_str, message);
size_t len = strlen(buf);
list->message = (char *)mrc_malloc(c, len + 1);
strcpy(list->message, buf);
list->message[len] = '\0';
list->code = code;
if (c->diagnostic_list == NULL) {
c->diagnostic_list = list;
} else {
mrc_diagnostic_list *p = c->diagnostic_list;
while (p->next) {
p = p->next;
}
p->next = list;
}
if (code == MRC_PARSER_ERROR || code == MRC_GENERATOR_ERROR) {
c->capture_errors = TRUE;
}
}
void
mrc_diagnostic_list_free(mrc_ccontext *c)
{
mrc_diagnostic_list *p = c->diagnostic_list;
while (p) {
mrc_diagnostic_list *next = p->next;
mrc_free(c, p->message);
mrc_free(c, p);
p = next;
}
c->diagnostic_list = NULL;
}