160 lines
3.3 KiB
C
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);
|
|
}
|