#include #include #include #include #include #include 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); }