#include "source.h" #include "util.h" #include #include #include struct source { char* contents; const char* file_name; size_t size; }; static source_t *_source_alloc(struct source data) { source_t *source = malloc(sizeof (struct source)); if (source == NULL) { die("Out of memory: cannot allocate source struct"); } *source = data; return source; } static struct source _read_file(const char *file_name) { FILE *f = fopen(file_name, "r"); if (!f) { die("Cannot read file %s", file_name); } size_t capacity = 1024; // initial buffer size size_t length = 0; char *buffer = malloc(capacity); if (buffer == NULL) { die("Out of memory: cannot allocate buffer for %s", file_name); } int ch; while ((ch = fgetc(f)) != EOF) { if (length + 1 >= capacity) { capacity *= 2; char *tmp = realloc(buffer, capacity); if (tmp == NULL) { fclose(f); die("Out of memory: cannot enlarge buffer for %s", file_name); } buffer = tmp; } buffer[length++] = (char)ch; } buffer[length] = '\0'; // null-terminate fclose(f); struct source it; it.contents = buffer; it.size = length; it.file_name = file_name; return it; } source_t *source_alloc_from_file(char* file_name) { return _source_alloc(_read_file(file_name)); } source_t *source_alloc(const char* file_name, char* contents) { struct source it = { .file_name = file_name, .contents = contents, .size = strlen(contents)}; return _source_alloc(it); } pos_t source_next_pos(source_t *source, pos_t pos) { if (source->contents[pos.idx] == '\n') { pos.idx++; pos.col = 0; pos.line++; } else { pos.idx++; pos.col++; } return pos; } void source_print_pos(source_t *source, pos_t pos) { fprintf(stderr,"%s:%d:%d", source->file_name,pos.line + 1,pos.col + 1); } void source_print_line(source_t *source, pos_t pos, int highlight_len) { fprintf(stderr,"%5d | ",pos.line+1); for (size_t i = pos.idx - pos.col; i < source->size && source->contents[i] != '\n' && source->contents[i] != '\0'; i++) fputc(source->contents[i],stderr); if (highlight_len <= 0) return; fprintf(stderr,"\n | "); for (int i = 0; i < pos.col; i++) fputc(' ',stderr); for (int i = 0; i < highlight_len; i++) fputc('^',stderr); } const char* source_contents_from(source_t* source, pos_t pos) { if (pos.idx >= source->size) { return source->contents + source->size; } else { return source->contents + pos.idx; } } void source_dealloc(source_t* source) { free(source->contents); }