bfck.c
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <ncurses.h>
5
6#define ALLOCATION_SIZE 1024
7#define BETWEEN(x, a, b) (((x) >= (a)) && ((x) <= (b)))
8
9static unsigned char *cols;
10static char *bf;
11
12void
13allocate(int alc)
14{
15 size_t s = ALLOCATION_SIZE * (alc + 1);
16 char *new;
17
18 if ((new = calloc(s, sizeof(char))) == NULL)
19 memset(new, 0, s * sizeof(char));
20 memmove(new, cols, (ALLOCATION_SIZE * alc));
21
22 free(cols);
23 cols = new;
24}
25
26void
27run()
28{
29 int i, j, l, x;
30 int idx = 0, /* index of column */
31 pos = 0, /* possitiong in debug */
32 beg = 0, /* begining in debug */
33 alc = 1, /* allocation count */
34 lix = 0; /* loop index */
35 char ch = 0;
36
37 cols = calloc(ALLOCATION_SIZE, sizeof(char));
38 memset(cols, 0, ALLOCATION_SIZE * sizeof(char));
39
40 /* remove non-brainfuck */
41 for (i = j = 0, l = strlen(bf); i < l; i++)
42 if (strchr("[]<>+-,.!", bf[i]))
43 bf[j++] = bf[i];
44 bf[(l = j)] = 0;
45
46 for (i = 0; i < l; i++) {
47 switch (bf[i]) {
48 case '>':
49 /* check if more columns are needed */
50 if (idx++ >= (ALLOCATION_SIZE * alc) - 1)
51 allocate(alc++);
52 break;
53 case '<':
54 if (idx <= 0)
55 break;
56 idx--;
57 break;
58 case '[':
59 /* skip if zero */
60 if (cols[idx] == 0) {
61 for (x = 0, i++; i < l; i++) {
62 if (bf[i] == '[')
63 x++;
64 else if (bf[i] == ']' && x > 0)
65 x--;
66 else if (bf[i] == ']')
67 break;
68 }
69 break;
70 }
71 lix++;
72 break;
73 case ']':
74 /* go back if not zero */
75 if (cols[idx] != 0) {
76 for (x = 0, j = i - 1; j > 0; j--) {
77 if (bf[j] == ']')
78 x++;
79 else if (bf[j] == '[' && x > 0)
80 x--;
81 else if (bf[j] == '[')
82 break;
83 }
84 i = j; /* jump to beginning */
85 break;
86 }
87 lix--; /* leave loop */
88 break;
89 case '+':
90 if (cols[idx] < 255)
91 cols[idx]++;
92 break;
93 case '-':
94 if (cols[idx] > 0)
95 cols[idx]--;
96 break;
97 case '.':
98 putchar(cols[idx]);
99 break;
100 case ',':
101 cols[idx] = getchar();
102 break;
103 case '!':
104 initscr();
105 cbreak();
106 noecho();
107
108 for (pos = idx;;) {
109 clear();
110
111 if (ch == 0x1B)
112 break;
113 else if (ch == 0x68 && pos > 0)
114 pos--;
115 else if (ch == 0x6C && pos < alc * ALLOCATION_SIZE)
116 pos++;
117 else if (ch == 0x6A && cols[pos] > 0)
118 cols[pos]--;
119 else if (ch == 0x6B && cols[pos] < 255)
120 cols[pos]++;
121
122 beg = pos < 5 ? 0 : pos - 5;
123 if (beg > (alc * ALLOCATION_SIZE - 10))
124 beg = alc * ALLOCATION_SIZE - 10;
125
126 printw("breakpoint: %d\n\n\n", i);
127
128 if ((beg - idx) < 0)
129 printw("%*s!\n", (beg - idx) * 4 - 1, " ");
130 else
131 printw("\n");
132
133 for (int p = beg; p < beg + 11; p++)
134 cols[p] < 10 \
135 ? printw(" %-2d ", cols[p]) \
136 : printw("%-3d ", cols[p]);
137 printw("\n");
138
139 for (int p = beg; p < beg + 11; p++)
140 printw("[%c] ",
141 BETWEEN(cols[p], 32, 126) ? cols[p] : ' ');
142 printw("\n");
143
144 printw("%*s^\n",
145 (pos - beg != 5 ? (pos - beg) : 5) * 4 + 1, " ");
146 pos < 10 \
147 ? printw("%*s%d\n",
148 (pos - beg != 5 ? (pos - beg) : 5) * 4 + 1, " ", pos) \
149 : printw("%*s%d\n",
150 (pos - beg != 5 ? (pos - beg) : 5) * 4 + 0, " ", pos);
151
152 printw("\n press [ESC] to continue...\n");
153 ch = getch();
154 }
155
156 refresh();
157 endwin();
158 break;
159 }
160 }
161 free(cols);
162 free(bf);
163}
164
165void
166load(const char *fn)
167{
168 int b, n = 0;
169 char buf[1024];
170 FILE *f = NULL;
171
172 if (!(f = fopen(fn, "r")))
173 exit(0);
174
175 while (!feof(f)) {
176 b = fread(buf, 1, sizeof buf, f);
177 if (!(bf = (char *)realloc(bf, (n += b) + 1)))
178 exit(1);
179 memcpy(bf + n - b, buf, b);
180 }
181 fclose(f);
182}
183
184int
185main(int argc, char *argv[])
186{
187 load(argv[1]);
188 run();
189}