aboutsummaryrefslogtreecommitdiff
path: root/file_loader.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2021-01-15 19:27:25 -0800
committerBruce Hill <bruce@bruce-hill.com>2021-01-15 19:27:25 -0800
commit77b33d6a3cdc2655fa0319a2c5a077eb709cb6aa (patch)
treef4d29634e49c71f4688bcb08b6ec8da40d00be31 /file_loader.c
parent10dbcdd4fd7bf2f14d49bdf19139f8dd5d53aebd (diff)
Renaming files: printing->print, file_loader->files
Diffstat (limited to 'file_loader.c')
-rw-r--r--file_loader.c230
1 files changed, 0 insertions, 230 deletions
diff --git a/file_loader.c b/file_loader.c
deleted file mode 100644
index 0d92241..0000000
--- a/file_loader.c
+++ /dev/null
@@ -1,230 +0,0 @@
-//
-// file_loader.c - Implementation of some file loading functionality.
-//
-
-#include <ctype.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include "file_loader.h"
-#include "utils.h"
-
-__attribute__((nonnull))
-static void populate_lines(file_t *f);
-
-//
-// In the file object, populate the `lines` array with pointers to the
-// beginning of each line.
-//
-static void populate_lines(file_t *f)
-{
- // Calculate line numbers:
- size_t linecap = 10;
- f->lines = xcalloc(sizeof(const char*), linecap);
- f->nlines = 0;
- char *p = f->contents;
- for (size_t n = 0; p && p < f->end; ++n) {
- ++f->nlines;
- if (n >= linecap)
- f->lines = xrealloc(f->lines, sizeof(const char*)*(linecap *= 2));
- f->lines[n] = p;
- p = strchr(p, '\n');
- if (p) ++p;
- }
-}
-
-//
-// Read an entire file into memory.
-//
-file_t *load_file(file_t **files, const char *fmt, ...)
-{
- char filename[PATH_MAX+1] = {0};
- va_list args;
- va_start(args, fmt);
- check(vsnprintf(filename, PATH_MAX, fmt, args) <= PATH_MAX,
- "File name is too large");
- va_end(args);
-
- int fd = filename[0] == '\0' ? STDIN_FILENO : open(filename, O_RDONLY);
- if (fd < 0) return NULL;
- size_t length;
- file_t *f = new(file_t);
- f->filename = strdup(filename);
-
- struct stat sb;
- if (fstat(fd, &sb) == -1)
- goto skip_mmap;
-
- f->contents = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (f->contents == MAP_FAILED)
- goto skip_mmap;
-
- f->mmapped = 1;
- length = (size_t)sb.st_size;
- goto finished_loading;
-
- skip_mmap:
- f->mmapped = 0;
- size_t capacity = 1000;
- length = 0;
- f->contents = xcalloc(sizeof(char), capacity);
- ssize_t just_read;
- while ((just_read=read(fd, &f->contents[length], capacity - length)) > 0) {
- length += (size_t)just_read;
- if (length >= capacity)
- f->contents = xrealloc(f->contents, sizeof(char)*(capacity *= 2) + 1);
- }
- if (fd != STDIN_FILENO) close(fd);
-
- finished_loading:
- f->end = &f->contents[length];
- populate_lines(f);
- if (files != NULL) {
- f->next = *files;
- *files = f;
- }
- return f;
-}
-
-//
-// Create a virtual file from a string.
-//
-file_t *spoof_file(file_t **files, const char *filename, const char *text)
-{
- if (filename == NULL) filename = "";
- file_t *f = new(file_t);
- f->filename = strdup(filename);
- f->contents = strdup(text);
- f->end = &f->contents[strlen(text)];
- populate_lines(f);
- if (files != NULL) {
- f->next = *files;
- *files = f;
- }
- return f;
-}
-
-//
-// Ensure that the file's contents are held in memory, rather than being memory
-// mapped IO.
-//
-void intern_file(file_t *f)
-{
- if (!f->mmapped) return;
- size_t size = (size_t)(f->end - f->contents);
- char *buf = xcalloc(sizeof(char), size + 1);
- memcpy(buf, f->contents, size);
- munmap(f->contents, size);
- f->contents = buf;
- f->end = buf + size;
- f->mmapped = 0;
- xfree(&f->lines);
- populate_lines(f);
-}
-
-//
-// Free a file and all memory contained inside its members, then set the input
-// pointer to NULL.
-//
-void destroy_file(file_t **f)
-{
- if ((*f)->filename) {
- xfree(&((*f)->filename));
- }
-
- if ((*f)->lines) {
- xfree(&((*f)->lines));
- }
-
- if ((*f)->contents) {
- if ((*f)->mmapped) {
- munmap((*f)->contents, (size_t)((*f)->end - (*f)->contents));
- (*f)->contents = NULL;
- } else {
- xfree(&((*f)->contents));
- }
- }
-
- for (allocated_pat_t *next; (*f)->pats; (*f)->pats = next) {
- next = (*f)->pats->next;
- destroy_pat(&(*f)->pats->pat);
- xfree(&(*f)->pats);
- }
-
- xfree(f);
-}
-
-//
-// Given a pointer, determine which line number it points to.
-//
-size_t get_line_number(file_t *f, const char *p)
-{
- // TODO: binary search
- for (size_t n = 1; n < f->nlines; n++) {
- if (f->lines[n] > p)
- return n;
- }
- return f->nlines;
-}
-
-//
-// Given a pointer, determine which character offset within the line it points to.
-//
-size_t get_char_number(file_t *f, const char *p)
-{
- size_t linenum = get_line_number(f, p);
- return 1 + (size_t)(p - f->lines[linenum-1]);
-}
-
-//
-// Return a pointer to the line with the specified line number.
-//
-const char *get_line(file_t *f, size_t line_number)
-{
- if (line_number == 0 || line_number > f->nlines) return NULL;
- return f->lines[line_number - 1];
-}
-
-//
-// Print the filename/line number, followed by the given message, followed by
-// the line itself.
-//
-void fprint_line(FILE *dest, file_t *f, const char *start, const char *end, const char *fmt, ...)
-{
- if (start < f->contents) start = f->contents;
- if (start > f->end) start = f->end;
- if (end < f->contents) end = f->contents;
- if (end > f->end) end = f->end;
- size_t linenum = get_line_number(f, start);
- const char *line = get_line(f, linenum);
- size_t charnum = get_char_number(f, start);
- fprintf(dest, "\033[1m%s:%ld:\033[0m ", f->filename, linenum);
-
- va_list args;
- va_start(args, fmt);
- vfprintf(dest, fmt, args);
- va_end(args);
- fputc('\n', dest);
-
- const char *eol = linenum == f->nlines ? strchr(line, '\0') : strchr(line, '\n');
- if (end == NULL || end > eol) end = eol;
- fprintf(dest, "\033[2m% 5ld |\033[0m %.*s\033[41;30m%.*s\033[0m%.*s\n",
- linenum,
- (int)charnum - 1, line,
- (int)(end - &line[charnum-1]), &line[charnum-1],
- (int)(eol - end), end);
- fprintf(dest, " \033[34;1m");
- const char *p = line - 1;
- for (; p < start; ++p) fputc(' ', dest);
- if (start == end) ++end;
- for (; p < end; ++p) fputc('^', dest);
- fprintf(dest, "\033[0m\n");
-}
-
-// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1