/
input_reader.c
143 lines (110 loc) · 3.12 KB
/
input_reader.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <terror/dbg.h>
#include <terror/bstrlib.h>
#include <terror/input_reader.h>
#include <terror/value.h>
/*
* Return the filesize of `filename` or -1.
*/
static inline off_t
file_size(bstring filename) {
struct stat s;
int rc = stat(bdata(filename), &s);
if (rc < 0) return -1;
return s.st_size;
}
/*
* Read the contents of `filename` or return NULL.
*/
static inline bstring
file_read(bstring filename) {
off_t len = file_size(filename);
check(len >= 0, "Invalid file length.");
char *buf = malloc(len + 1);
check_mem(buf);
int fd = open(bdata(filename), O_RDONLY);
check(fd >= 0, "Error opening file.");
ssize_t size = read(fd, buf, len);
check(size == len, "Read length is invalid");
bstring retval = bfromcstr(buf);
free(buf);
return retval;
error:
return NULL;
}
static inline void
parse_string(bstring buf, BytecodeFile *file)
{
struct bstrList *lines = bsplit(buf, '\n');
int i = 0;
int cnt = 0;
bstring *line = lines->entry;
while(1) {
// eof
if (bstrcmp(bmidstr(*line, 0, 1), bfromcstr("_")) != 0) break;
// Get method name
int num_literals, num_instructions;
bstring method = bmidstr(*line, 1, (*line)->mlen);
line++; cnt++;
// Get counts
sscanf(bdata(*line), ":%i:%i",
&num_literals, &num_instructions);
line++; cnt++;
DArray *literals = DArray_create(sizeof(VALUE), 10);
// Parse the actual literals
if (num_literals > 0) {
literals = DArray_create(sizeof(VALUE), num_literals);
for(i=0; i < num_literals; i++) {
if (bdata(*line)[0] == '"') {
bstring strData = bmidstr(*line, 1, (*line)->mlen);
// TODO: This causes a leak in the string literals because they are
// never freed on destruction.
DArray_push(literals, String_new(bdata(bstrcpy(strData))));
bdestroy(strData);
} else {
DArray_push(literals, Number_new(atof(bdata(*line))));
}
line++; cnt++;
}
}
// Parse the instructions
int *instructions = calloc(num_instructions, sizeof(int));
for(i=0; i < num_instructions; i++) {
int num;
sscanf(bdata(*line), "%i", &num);
instructions[i] = num;
line++; cnt++;
}
Function *fn = Function_new(instructions, literals);
DArray_push(file->function_names, method);
Hashmap_set(file->functions, method, fn);
if(cnt >= lines->qty) break; // EOF
}
bstrListDestroy(lines);
}
BytecodeFile *BytecodeFile_new(bstring filename)
{
BytecodeFile *file = calloc(1, sizeof(BytecodeFile));
check_mem(file);
file->filename = filename;
file->functions = Hashmap_create(NULL, NULL);
file->function_names = DArray_create(sizeof(bstring), 10);
bstring buf = file_read(filename);
check(buf, "Cannot read file %s", bdata(filename));
parse_string(buf, file);
bdestroy(buf);
return file;
error:
return NULL;
}
void
BytecodeFile_destroy(BytecodeFile *file)
{
if(file->filename) bdestroy(file->filename);
if(file->functions) Hashmap_destroy(file->functions);
free(file);
}