the hito embeddable programming language
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}