-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.c
166 lines (131 loc) · 2.52 KB
/
main.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include <fcntl.h>
// How many memory 'cells' are allocated
#define MEMORY_SIZE (30000)
char *find_matching_open(char *p) {
int skip = 0;
while (*(--p)) {
if (*p == ']') {
skip++;
} else if (*p == '[') {
if (skip == 0) {
return p;
} else {
skip--;
}
}
}
return NULL; /* matching bracket not found */
}
char *find_matching_close(char *p) {
int skip = 0;
while (*(++p)) {
if (*p == '[') {
skip++;
} else if (*p == ']') {
if (skip == 0) {
return p;
} else {
skip--;
}
}
}
return NULL; /* matching bracket not found */
}
int run(char *program) {
char *p;
char mem[MEMORY_SIZE];
char *m;
char c;
// set cells to zero
bzero(mem, sizeof(mem));
// instruction pointer
p = program;
// memory pointer
m = mem;
// current instruction
c = *p;
// Reads to end of string.
while (c != '\0') {
switch (c) {
case '>':
m++;
break;
case '<':
m--;
break;
case '+':
(*m)++;
break;
case '-':
(*m)--;
break;
case '.':
fputc(*m, stdout);
break;
case ',':
(*m) = getc(stdin);
break;
case '[':
if (*m == 0) {
p = find_matching_close(p);
if (p == NULL) {
printf("unbalanced brackets\n");
return 1;
}
}
break;
case ']':
if (*m) {
p = find_matching_open(p);
if (p == NULL) {
printf("unbalanced brackets\n");
return 1;
}
}
break;
default:
break;
}
// move instruction pointer forward
c = *(++p);
}
return 0;
}
char *alloc_file(char *filename) {
int fd;
struct stat info;
char *buf;
ssize_t size;
if (stat(filename, &info) == -1)
{ perror("stat"); return NULL; }
if ((fd = open(filename, O_RDONLY)) == -1)
{ perror("open"); return NULL; }
if ((buf = (char *)malloc(info.st_size + 2)) == NULL)
{ perror("malloc"); close(fd); return NULL; }
if ((size = read(fd, buf + 1, info.st_size)) == -1)
{ perror("read"); close(fd); return NULL; }
if (size != info.st_size)
{ printf("unexpected read (%ld != %lld)\n", size, info.st_size); close(fd); return NULL; }
/* We pad the beginning and end with nul bytes, so the interpreter knows where to halt.
*/
buf[0] = buf[size] = '\0';
close(fd);
return buf + 1;
}
int main(int argc, char **argv) {
char *program;
if ((argc == 2)
&& (program = alloc_file(argv[1]))
&& program) {
return run(program);
}
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}