Files
fz-lang/src/compiler/utils/fzl_linked.c
T

160 lines
3.3 KiB
C

#include <compiler/utils/fzl_linked.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char llast_err[256];
fzl_linked_t *fzl_mklinked()
{
fzl_linked_t *l = malloc(sizeof(fzl_linked_t));
if (!l)
{
snprintf(llast_err, sizeof(llast_err), "potato PC...");
return NULL;
}
l->entries = NULL;
l->entries_count = 0;
l->source = NULL;
l->total_sz = 0;
return l;
}
bool fzl_linked_add_files(fzl_linked_t *l, char **files, size_t files_count)
{
if (!l)
return false;
size_t eremainder = 2;
size_t ecount = 0;
fzl_linked_entry_t *entries = malloc(eremainder * sizeof(fzl_linked_entry_t));
size_t current_start = 0;
for (size_t i = 0; i < files_count; i++)
{
char *source;
FILE *fd = fopen(files[i], "r");
if (!fd)
{
snprintf(llast_err, sizeof(llast_err), "failed to open file '%s'\n",
files[i]);
free(entries);
return false;
}
fseek(fd, 0L, SEEK_END);
size_t file_sz = ftell(fd);
rewind(fd);
source = malloc(file_sz + 1);
fread(source, file_sz, 1, fd);
fclose(fd);
source[file_sz] = 0;
if (eremainder <= ecount)
{
eremainder *= 2;
entries = realloc(entries, eremainder * sizeof(fzl_linked_entry_t));
if (!entries)
{
snprintf(llast_err, sizeof(llast_err), "potato pc...");
free(source);
return NULL;
}
}
entries[ecount++] =
(fzl_linked_entry_t){.name = files[i],
.start = current_start,
.end = current_start + file_sz - 1};
if (!l->source)
l->source = malloc(file_sz + 1);
else
l->source = realloc(l->source, current_start + file_sz + 1);
if (!l->source)
{
snprintf(llast_err, sizeof(llast_err),
"failed to allocate space for source code holder");
free(entries);
free(source);
return NULL;
}
strcpy(l->source + current_start, source);
current_start += file_sz;
}
l->source = realloc(l->source, current_start + 1);
if (!l->source)
{
snprintf(llast_err, sizeof(llast_err),
"not enough space for entire source\n");
free(entries);
return NULL;
}
l->source[current_start] = 0;
l->entries = entries;
l->entries_count = ecount;
l->total_sz = current_start;
return true;
}
char *fzl_linked_geterror() { return llast_err; }
bool fzl_linked_getpos(fzl_linked_t *l, size_t pos, fzl_file_loc *res)
{
if (!l)
return false;
bool found = false;
fzl_linked_entry_t e;
for (size_t i = 0; i < l->entries_count; i++)
{
e = l->entries[i];
if (pos >= e.start && pos <= e.end)
{
found = true;
break;
}
}
if (!found)
return NULL;
size_t line = 1;
size_t line_start = e.start;
for (size_t p = e.start; p < pos; p++)
{
if (l->source[p] == '\n')
{
line++;
line_start = p + 1;
}
}
*res =
(fzl_file_loc){.filename = e.name, .line = line, .col = pos - line_start};
return true;
}
void fzl_freelinked(fzl_linked_t *linked)
{
if (!linked)
return;
if (linked->source)
free(linked->source);
if (linked->entries)
free(linked->entries);
free(linked);
}