-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
104 lines (91 loc) · 2.39 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
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <termios.h>
// Thanks to offirgolan at https://github.com/offirgolan/Shell/blob/master/tty-raw-mode.c
void enableRawMode(void) {
struct termios tty_attr;
tcgetattr(0, &tty_attr);
tty_attr.c_lflag &= ~(ICANON|ECHO);
tty_attr.c_cc[VTIME] = 0;
tty_attr.c_cc[VMIN] = 1;
tcsetattr(0, TCSANOW, &tty_attr);
}
struct Instruction {
enum {NO, YES} end, out, in;
int math;
int seek;
enum {ZERO, NONZERO} cond;
int jump;
};
int findMatchingBracketDist(struct Instruction *instr) {
int depth = 0;
int dist = 0;
do {
if ((instr-dist)->jump < 0) depth++;
if ((instr-dist)->jump > 0) depth--;
dist++;
} while (depth > 0);
dist--;
return dist;
}
int charmatch(char *match, char c) {
while (*match != '\0') if (*match++ == c) return 1;
return 0;
}
int storeInstruction(char c, struct Instruction *instr) {
if (c=='>' || c=='<' || c=='+' || c=='-' || c==',' || c=='.' || c=='[' || c==']') {
int next = 0;
if (
instr->jump != 0
|| (charmatch(",.+-", c) && instr->seek != 0)
|| (charmatch(",.", c) && instr->math != 0)
|| (c=='.' && instr->in != 0)
) next=1;
if (next) instr++;
if (c=='>') instr->seek++;
if (c=='<') instr->seek--;
if (c=='+') instr->math++;
if (c=='-') instr->math--;
if (c==',') instr->in = YES;
if (c=='.') instr->out = YES;
if (c=='[') instr->jump = 1;
if (c==']') {
instr->jump = -1;
int dist = findMatchingBracketDist(instr);
(instr-dist)->jump = dist;
(instr-dist)->cond = ZERO;
instr->jump = -dist;
instr->cond = NONZERO;
}
return next;
}
return 0;
}
void compile(char *filename, struct Instruction *program) {
int c;
FILE *file = fopen(filename, "r");
if (file == NULL) return;
while ((c = fgetc(file)) != EOF) program += storeInstruction(c, program);
program->end = YES;
fclose(file);
}
void interpret(struct Instruction *program, unsigned char *tape) {
do {
if (program->out == YES) putc(*tape, stdout);
if (program->in == YES) *tape = getc(stdin);
(*tape) += program->math;
tape += program->seek;
if (program->cond == ZERO && *tape == 0 || program->cond == NONZERO && *tape != 0) program += program->jump;
} while ((program++)->end == NO);
}
struct Instruction program[65536];
unsigned char tape[65536];
int main(int argc, char *argv[]) {
if (argc > 1) {
compile(argv[1], program);
enableRawMode();
interpret(program, tape);
}
return 0;
}