the hito embeddable programming language
at main 102 lines 2.7 kB view raw
1#include "source.h" 2#include "util.h" 3#include <stdlib.h> 4#include <string.h> 5#include <stdio.h> 6 7struct source { 8 char* contents; 9 const char* file_name; 10 size_t size; 11}; 12 13static source_t *_source_alloc(struct source data) { 14 source_t *source = malloc(sizeof (struct source)); 15 if (source == NULL) { 16 die("Out of memory: cannot allocate source struct"); 17 } 18 *source = data; 19 return source; 20} 21 22static struct source _read_file(const char *file_name) { 23 FILE *f = fopen(file_name, "r"); 24 if (!f) { 25 die("Cannot read file %s", file_name); 26 } 27 size_t capacity = 1024; // initial buffer size 28 size_t length = 0; 29 char *buffer = malloc(capacity); 30 if (buffer == NULL) { 31 die("Out of memory: cannot allocate buffer for %s", file_name); 32 } 33 int ch; 34 while ((ch = fgetc(f)) != EOF) { 35 if (length + 1 >= capacity) { 36 capacity *= 2; 37 char *tmp = realloc(buffer, capacity); 38 if (tmp == NULL) { 39 fclose(f); 40 die("Out of memory: cannot enlarge buffer for %s", file_name); 41 } 42 buffer = tmp; 43 } 44 buffer[length++] = (char)ch; 45 } 46 47 buffer[length] = '\0'; // null-terminate 48 fclose(f); 49 struct source it; 50 it.contents = buffer; 51 it.size = length; 52 it.file_name = file_name; 53 return it; 54} 55 56source_t *source_alloc_from_file(char* file_name) { 57 return _source_alloc(_read_file(file_name)); 58} 59 60source_t *source_alloc(const char* file_name, char* contents) { 61 struct source it = { .file_name = file_name, .contents = contents, .size = strlen(contents)}; 62 return _source_alloc(it); 63} 64 65pos_t source_next_pos(source_t *source, pos_t pos) { 66 if (source->contents[pos.idx] == '\n') { 67 pos.idx++; 68 pos.col = 0; 69 pos.line++; 70 } else { 71 pos.idx++; 72 pos.col++; 73 } 74 return pos; 75} 76 77void source_print_pos(source_t *source, pos_t pos) { 78 fprintf(stderr,"%s:%d:%d", source->file_name,pos.line + 1,pos.col + 1); 79} 80 81void source_print_line(source_t *source, pos_t pos, int highlight_len) { 82 fprintf(stderr,"%5d | ",pos.line+1); 83 for (size_t i = pos.idx - pos.col; 84 i < source->size && source->contents[i] != '\n' && source->contents[i] != '\0'; 85 i++) fputc(source->contents[i],stderr); 86 if (highlight_len <= 0) return; 87 fprintf(stderr,"\n | "); 88 for (int i = 0; i < pos.col; i++) fputc(' ',stderr); 89 for (int i = 0; i < highlight_len; i++) fputc('^',stderr); 90} 91 92const char* source_contents_from(source_t* source, pos_t pos) { 93 if (pos.idx >= source->size) { 94 return source->contents + source->size; 95 } else { 96 return source->contents + pos.idx; 97 } 98} 99 100void source_dealloc(source_t* source) { 101 free(source->contents); 102}