diff options
-rw-r--r-- | COPYING (renamed from LICENSE) | 0 | ||||
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | README.md | 9 | ||||
-rw-r--r-- | examples/add2.tf | 500 | ||||
-rw-r--r-- | examples/hello-world.bf | 55 | ||||
-rw-r--r-- | examples/hello-world.tf | 388 | ||||
-rw-r--r-- | examples/printchar.bf | 5 | ||||
-rw-r--r-- | examples/printchar.tf | 10 | ||||
-rw-r--r-- | examples/rot13.tf | 215 | ||||
-rwxr-xr-x | fucktrain | 53 | ||||
-rwxr-xr-x | fucktrain.awk | 97 | ||||
-rwxr-xr-x | trainfuck | 19 | ||||
-rwxr-xr-x | trainfuck.awk | 53 |
13 files changed, 1351 insertions, 73 deletions
diff --git a/LICENSE b/COPYING index 0f6c35a..0f6c35a 100644 --- a/LICENSE +++ b/COPYING | |||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ebe8bf4 --- /dev/null +++ b/Makefile | |||
@@ -0,0 +1,20 @@ | |||
1 | # TRAINFUCK MOTHER CHOO-ER | ||
2 | # Version #9 | ||
3 | |||
4 | PREFIX = /usr/local | ||
5 | |||
6 | .PHONY: help install uninstall | ||
7 | |||
8 | help: | ||
9 | @echo "TRAINFUCK!" | ||
10 | @echo " make install Install to $(PREFIX)" | ||
11 | @echo " make uninstall Remove from $(PREFIX)" | ||
12 | |||
13 | install: trainfuck trainfuck.awk fucktrain fucktrain.awk | ||
14 | install -Dt $(DESTDIR)$(PREFIX)/bin/ $? | ||
15 | |||
16 | uninstall: | ||
17 | rm $(DESTDIR)$(PREFIX)/trainfuck | ||
18 | rm $(DESTDIR)$(PREFIX)/trainfuck.awk | ||
19 | rm $(DESTDIR)$(PREFIX)/fucktrain | ||
20 | rm $(DESTDIR)$(PREFIX)/fucktrain.awk | ||
diff --git a/README.md b/README.md index c552d91..bf4da7b 100644 --- a/README.md +++ b/README.md | |||
@@ -1,7 +1,8 @@ | |||
1 | # TRAINFUCK | 1 | # TRAINFUCK |
2 | 2 | ||
3 | an esolang that transpiles to everyone's favorite esolange | 3 | an esolang that transpiles to everyone's favorite esolang |
4 | (so basically an awk script) | 4 | (so basically an awk script) |
5 | **NOW WITH MORE SCRIPTING CAPABILITIES!** | ||
5 | 6 | ||
6 | ## LANGUAGE | 7 | ## LANGUAGE |
7 | 8 | ||
@@ -33,19 +34,19 @@ because fuck you, that's why. | |||
33 | ## INVOKING | 34 | ## INVOKING |
34 | 35 | ||
35 | ``` | 36 | ``` |
36 | trainfuck FILE | BRAINFUCK_INTERPRETER | 37 | trainfuck FILE.tf |
37 | ``` | 38 | ``` |
38 | 39 | ||
39 | Or, for round-tripping ... | 40 | Or, for round-tripping ... |
40 | 41 | ||
41 | ``` | 42 | ``` |
42 | fucktrain FILE | trainfuck | BRAINFUCK_INTERPRETER | 43 | fucktrain FILE.bf | trainfuck |
43 | ``` | 44 | ``` |
44 | 45 | ||
45 | ## INSTALL | 46 | ## INSTALL |
46 | 47 | ||
47 | ``` | 48 | ``` |
48 | cp trainfuck /usr/sbin/ | 49 | make install |
49 | ``` | 50 | ``` |
50 | 51 | ||
51 | ## UNINSTALL | 52 | ## UNINSTALL |
diff --git a/examples/add2.tf b/examples/add2.tf new file mode 100644 index 0000000..3c1529b --- /dev/null +++ b/examples/add2.tf | |||
@@ -0,0 +1,500 @@ | |||
1 | Add two values | ||
2 | from https://en.wikipedia.org/wiki/Brainfuck#Adding_two_values | ||
3 | |||
4 | |||
5 | |||
6 | |||
7 | ALL ABOARD | ||
8 | chug chug | ||
9 | END OF THE LINE | ||
10 | Cell c0 = 2 | ||
11 | |||
12 | ALL ABOARD | ||
13 | choo | ||
14 | |||
15 | END OF THE LINE | ||
16 | |||
17 | ALL ABOARD | ||
18 | chug chug chug chug chug | ||
19 | END OF THE LINE | ||
20 | Cell c1 = 5 | ||
21 | |||
22 | |||
23 | ALL ABOARD | ||
24 | tickets please | ||
25 | END OF THE LINE | ||
26 | Start your loops with your cell pointer on the loop counter (c1 in our case) | ||
27 | |||
28 | ALL ABOARD | ||
29 | choo choo | ||
30 | |||
31 | END OF THE LINE | ||
32 | |||
33 | ALL ABOARD | ||
34 | chug | ||
35 | END OF THE LINE | ||
36 | Add 1 to c0 | ||
37 | |||
38 | ALL ABOARD | ||
39 | choo | ||
40 | |||
41 | END OF THE LINE | ||
42 | |||
43 | ALL ABOARD | ||
44 | chugga | ||
45 | END OF THE LINE | ||
46 | Subtract 1 from c1 | ||
47 | |||
48 | ALL ABOARD | ||
49 | your ticket please | ||
50 | END OF THE LINE | ||
51 | End your loops with the cell pointer on the loop counter | ||
52 | |||
53 | At this point our program has added 5 to 2 leaving 7 in c0 and 0 in c1 | ||
54 | but we cannot output this value to the terminal since it is not ASCII encoded | ||
55 | |||
56 | To display the ASCII character "7" we must add 48 to the value 7 | ||
57 | We use a loop to compute 48 = 6 * 8 | ||
58 | |||
59 | |||
60 | ALL ABOARD | ||
61 | chug chug chug chug | ||
62 | END OF THE LINE | ||
63 | |||
64 | ALL ABOARD | ||
65 | chug chug chug chug | ||
66 | END OF THE LINE | ||
67 | c1 = 8 and this will be our loop counter again | ||
68 | |||
69 | ALL ABOARD | ||
70 | tickets please | ||
71 | choo choo | ||
72 | |||
73 | END OF THE LINE | ||
74 | |||
75 | ALL ABOARD | ||
76 | chug chug chug | ||
77 | END OF THE LINE | ||
78 | |||
79 | ALL ABOARD | ||
80 | chug chug chug | ||
81 | END OF THE LINE | ||
82 | Add 6 to c0 | ||
83 | |||
84 | ALL ABOARD | ||
85 | choo | ||
86 | |||
87 | END OF THE LINE | ||
88 | |||
89 | ALL ABOARD | ||
90 | chugga | ||
91 | END OF THE LINE | ||
92 | Subtract 1 from c1 | ||
93 | |||
94 | ALL ABOARD | ||
95 | your ticket please | ||
96 | choo choo | ||
97 | |||
98 | END OF THE LINE | ||
99 | |||
100 | ALL ABOARD | ||
101 | click | ||
102 | END OF THE LINE | ||
103 | Print out c0 which has the value 55 which translates to "7"! | ||
104 | |||
105 | Finally print a newline: | ||
106 | |||
107 | ALL ABOARD | ||
108 | chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga | ||
109 | chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga | ||
110 | chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga | ||
111 | chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga chugga | ||
112 | chugga click | ||
113 | This program prints "Hello World!" and a newline to the screen, its | ||
114 | length is 106 active command characters. [It is not the shortest.] | ||
115 | |||
116 | This loop is an "initial comment loop", a simple way of adding a comment | ||
117 | to a BF program such that you don't have to worry about any command | ||
118 | characters. Any ".", ",", "+", "-", "<" and ">" characters are simply | ||
119 | ignored, the "[" and "]" characters just have to be balanced. This | ||
120 | loop and the commands it contains are ignored because the current cell | ||
121 | defaults to a value of 0; the 0 value causes this loop to be skipped. | ||
122 | |||
123 | from https://en.wikipedia.org/wiki/Brainfuck#Hello_World! | ||
124 | |||
125 | |||
126 | ALL ABOARD | ||
127 | chug chug chug chug chug chug chug chug | ||
128 | END OF THE LINE | ||
129 | Set Cell #0 to 8 | ||
130 | |||
131 | ALL ABOARD | ||
132 | tickets please | ||
133 | choo | ||
134 | chug chug chug chug | ||
135 | END OF THE LINE | ||
136 | Add 4 to Cell #1; this will always set Cell #1 to 4 | ||
137 | |||
138 | ALL ABOARD | ||
139 | tickets please | ||
140 | END OF THE LINE | ||
141 | as the cell will be cleared by the loop | ||
142 | |||
143 | ALL ABOARD | ||
144 | choo | ||
145 | chug chug | ||
146 | END OF THE LINE | ||
147 | Add 2 to Cell #2 | ||
148 | |||
149 | ALL ABOARD | ||
150 | choo | ||
151 | chug chug chug | ||
152 | END OF THE LINE | ||
153 | Add 3 to Cell #3 | ||
154 | |||
155 | ALL ABOARD | ||
156 | choo | ||
157 | chug chug chug | ||
158 | END OF THE LINE | ||
159 | Add 3 to Cell #4 | ||
160 | |||
161 | ALL ABOARD | ||
162 | choo | ||
163 | chug | ||
164 | END OF THE LINE | ||
165 | Add 1 to Cell #5 | ||
166 | |||
167 | ALL ABOARD | ||
168 | choo choo | ||
169 | choo choo | ||
170 | choo choo | ||
171 | choo choo | ||
172 | chugga | ||
173 | END OF THE LINE | ||
174 | Decrement the loop counter in Cell #1 | ||
175 | |||
176 | ALL ABOARD | ||
177 | your ticket please | ||
178 | END OF THE LINE | ||
179 | Loop until Cell #1 is zero; number of iterations is 4 | ||
180 | |||
181 | ALL ABOARD | ||
182 | choo | ||
183 | chug | ||
184 | END OF THE LINE | ||
185 | Add 1 to Cell #2 | ||
186 | |||
187 | ALL ABOARD | ||
188 | choo | ||
189 | chug | ||
190 | END OF THE LINE | ||
191 | Add 1 to Cell #3 | ||
192 | |||
193 | ALL ABOARD | ||
194 | choo | ||
195 | chugga | ||
196 | END OF THE LINE | ||
197 | Subtract 1 from Cell #4 | ||
198 | |||
199 | ALL ABOARD | ||
200 | choo | ||
201 | choo | ||
202 | chug | ||
203 | END OF THE LINE | ||
204 | Add 1 to Cell #6 | ||
205 | |||
206 | ALL ABOARD | ||
207 | tickets please choo choo | ||
208 | your ticket please | ||
209 | END OF THE LINE | ||
210 | Move back to the first zero cell you find; this will | ||
211 | be Cell #1 which was cleared by the previous loop | ||
212 | |||
213 | ALL ABOARD | ||
214 | choo choo | ||
215 | chugga | ||
216 | END OF THE LINE | ||
217 | Decrement the loop Counter in Cell #0 | ||
218 | |||
219 | ALL ABOARD | ||
220 | your ticket please | ||
221 | END OF THE LINE | ||
222 | Loop until Cell #0 is zero; number of iterations is 8 | ||
223 | |||
224 | The result of this is: | ||
225 | Cell no : 0 1 2 3 4 5 6 | ||
226 | Contents: 0 0 72 104 88 32 8 | ||
227 | Pointer : ^ | ||
228 | |||
229 | |||
230 | ALL ABOARD | ||
231 | choo | ||
232 | choo | ||
233 | click | ||
234 | END OF THE LINE | ||
235 | Cell #2 has value 72 which is 'H' | ||
236 | |||
237 | ALL ABOARD | ||
238 | choo | ||
239 | chugga chugga chugga click | ||
240 | END OF THE LINE | ||
241 | Subtract 3 from Cell #3 to get 101 which is 'e' | ||
242 | |||
243 | ALL ABOARD | ||
244 | chug chug chug chug chug chug chug clickety click chug chug chug click | ||
245 | |||
246 | END OF THE LINE | ||
247 | Likewise for 'llo' from Cell #3 | ||
248 | |||
249 | ALL ABOARD | ||
250 | choo | ||
251 | choo | ||
252 | click | ||
253 | END OF THE LINE | ||
254 | Cell #5 is 32 for the space | ||
255 | |||
256 | ALL ABOARD | ||
257 | choo choo | ||
258 | chugga clickety | ||
259 | END OF THE LINE | ||
260 | Subtract 1 from Cell #4 for 87 to give a 'W' | ||
261 | |||
262 | ALL ABOARD | ||
263 | choo choo | ||
264 | clickety | ||
265 | END OF THE LINE | ||
266 | Cell #3 was set to 'o' from the end of 'Hello' | ||
267 | |||
268 | ALL ABOARD | ||
269 | chug chug chug click chugga chugga chugga chugga chugga chugga clickety | ||
270 | chugga chugga chugga chugga chugga chugga chugga chugga click | ||
271 | END OF THE LINE | ||
272 | Cell #3 for 'rl' and 'd' | ||
273 | |||
274 | ALL ABOARD | ||
275 | choo | ||
276 | choo | ||
277 | chug click | ||
278 | END OF THE LINE | ||
279 | Add 1 to Cell #5 gives us an exclamation point | ||
280 | |||
281 | ALL ABOARD | ||
282 | choo | ||
283 | chug chug click | ||
284 | END OF THE LINE | ||
285 | And finally a newline from Cell #6 | ||
286 | ROT13 in Brainfuck | ||
287 | from https://en.wikipedia.org/wiki/Brainfuck#ROT13 | ||
288 | |||
289 | |||
290 | |||
291 | |||
292 | ALL ABOARD | ||
293 | chugga clack chug tickets please | ||
294 | END OF THE LINE | ||
295 | Read first character and start outer character reading loop | ||
296 | |||
297 | ALL ABOARD | ||
298 | chugga tickets please | ||
299 | END OF THE LINE | ||
300 | Skip forward if character is 0 | ||
301 | |||
302 | ALL ABOARD | ||
303 | choo | ||
304 | choo | ||
305 | chug chug chug chug tickets please choo | ||
306 | chug chug chug chug chug chug chug chug | ||
307 | choo choo | ||
308 | chugga your ticket please | ||
309 | END OF THE LINE | ||
310 | Set up divisor (32) for division loop | ||
311 | (MEMORY LAYOUT: dividend copy remainder divisor quotient zero zero) | ||
312 | |||
313 | ALL ABOARD | ||
314 | choo choo | ||
315 | chug choo choo | ||
316 | chugga tickets please | ||
317 | END OF THE LINE | ||
318 | Set up dividend (x minus 1) and enter division loop | ||
319 | |||
320 | ALL ABOARD | ||
321 | choo | ||
322 | chug choo | ||
323 | chug choo | ||
324 | chugga tickets please choo | ||
325 | choo | ||
326 | choo | ||
327 | your ticket please | ||
328 | END OF THE LINE | ||
329 | Increase copy and remainder / reduce divisor / Normal case: skip forward | ||
330 | |||
331 | ALL ABOARD | ||
332 | choo choo | ||
333 | tickets please tickets please choo | ||
334 | chug choo choo | ||
335 | chugga your ticket please choo | ||
336 | choo | ||
337 | chug choo | ||
338 | your ticket please | ||
339 | |||
340 | END OF THE LINE | ||
341 | Special case: move remainder back to divisor and increase quotient | ||
342 | |||
343 | ALL ABOARD | ||
344 | choo choo | ||
345 | choo choo | ||
346 | choo choo | ||
347 | choo choo | ||
348 | choo choo | ||
349 | chugga | ||
350 | END OF THE LINE | ||
351 | Decrement dividend | ||
352 | |||
353 | ALL ABOARD | ||
354 | your ticket please | ||
355 | END OF THE LINE | ||
356 | End division loop | ||
357 | |||
358 | ALL ABOARD | ||
359 | your ticket please choo | ||
360 | choo | ||
361 | choo | ||
362 | tickets please chugga your ticket please chug | ||
363 | END OF THE LINE | ||
364 | End skip loop; zero former divisor and reuse space for a flag | ||
365 | |||
366 | ALL ABOARD | ||
367 | choo | ||
368 | chugga chugga tickets please chugga tickets please choo choo | ||
369 | chugga choo | ||
370 | chug chug chug | ||
371 | tickets please chugga your ticket please your ticket please your ticket please | ||
372 | choo choo | ||
373 | tickets please | ||
374 | END OF THE LINE | ||
375 | Zero that flag unless quotient was 2 or 3; zero quotient; check flag | ||
376 | |||
377 | ALL ABOARD | ||
378 | chug chug chug chug chug chug chug chug chug chug chug chug choo choo | ||
379 | tickets please | ||
380 | |||
381 | END OF THE LINE | ||
382 | If flag then set up divisor (13) for second division loop | ||
383 | (MEMORY LAYOUT: zero copy dividend divisor remainder quotient zero zero) | ||
384 | |||
385 | ALL ABOARD | ||
386 | choo | ||
387 | chugga tickets please choo | ||
388 | chug choo | ||
389 | choo | ||
390 | your ticket please | ||
391 | END OF THE LINE | ||
392 | Reduce divisor; Normal case: increase remainder | ||
393 | |||
394 | ALL ABOARD | ||
395 | choo | ||
396 | tickets please chug tickets please choo choo | ||
397 | chug choo | ||
398 | chugga your ticket please choo | ||
399 | chug | ||
400 | choo | ||
401 | choo | ||
402 | your ticket please | ||
403 | END OF THE LINE | ||
404 | Special case: increase remainder / move it back to divisor / increase quotient | ||
405 | |||
406 | ALL ABOARD | ||
407 | choo choo | ||
408 | choo choo | ||
409 | choo choo | ||
410 | choo choo | ||
411 | choo choo | ||
412 | chugga | ||
413 | END OF THE LINE | ||
414 | Decrease dividend | ||
415 | |||
416 | ALL ABOARD | ||
417 | your ticket please | ||
418 | END OF THE LINE | ||
419 | End division loop | ||
420 | |||
421 | ALL ABOARD | ||
422 | choo | ||
423 | choo | ||
424 | tickets please choo choo | ||
425 | chug choo | ||
426 | chugga your ticket please | ||
427 | END OF THE LINE | ||
428 | Add remainder back to divisor to get a useful 13 | ||
429 | |||
430 | ALL ABOARD | ||
431 | choo | ||
432 | tickets please | ||
433 | END OF THE LINE | ||
434 | Skip forward if quotient was 0 | ||
435 | |||
436 | ALL ABOARD | ||
437 | chugga tickets please | ||
438 | END OF THE LINE | ||
439 | Decrement quotient and skip forward if quotient was 1 | ||
440 | |||
441 | ALL ABOARD | ||
442 | chugga choo choo | ||
443 | choo choo | ||
444 | tickets please chugga your ticket please choo | ||
445 | choo | ||
446 | |||
447 | END OF THE LINE | ||
448 | Zero quotient and divisor if quotient was 2 | ||
449 | |||
450 | ALL ABOARD | ||
451 | your ticket please choo choo | ||
452 | choo choo | ||
453 | tickets please choo choo | ||
454 | choo choo | ||
455 | chugga choo | ||
456 | choo | ||
457 | chugga your ticket please choo | ||
458 | choo | ||
459 | |||
460 | END OF THE LINE | ||
461 | Zero divisor and subtract 13 from copy if quotient was 1 | ||
462 | |||
463 | ALL ABOARD | ||
464 | your ticket please choo choo | ||
465 | choo choo | ||
466 | tickets please choo choo | ||
467 | choo choo | ||
468 | chug choo | ||
469 | choo | ||
470 | chugga your ticket please | ||
471 | END OF THE LINE | ||
472 | Zero divisor and add 13 to copy if quotient was 0 | ||
473 | |||
474 | ALL ABOARD | ||
475 | your ticket please | ||
476 | END OF THE LINE | ||
477 | End outer skip loop (jump to here if ((character minus 1)/32) was not 2 or 3) | ||
478 | |||
479 | ALL ABOARD | ||
480 | choo choo | ||
481 | tickets please chugga your ticket please | ||
482 | END OF THE LINE | ||
483 | Clear remainder from first division if second division was skipped | ||
484 | |||
485 | ALL ABOARD | ||
486 | choo choo | ||
487 | click tickets please chugga your ticket please | ||
488 | END OF THE LINE | ||
489 | Output ROT13ed character from copy and clear it | ||
490 | |||
491 | ALL ABOARD | ||
492 | choo choo | ||
493 | chugga clack chug | ||
494 | END OF THE LINE | ||
495 | Read next character | ||
496 | |||
497 | ALL ABOARD | ||
498 | your ticket please | ||
499 | END OF THE LINE | ||
500 | End character reading loop | ||
diff --git a/examples/hello-world.bf b/examples/hello-world.bf index dce24e2..eab99ed 100644 --- a/examples/hello-world.bf +++ b/examples/hello-world.bf | |||
@@ -8,38 +8,37 @@ ignored, the "[" and "]" characters just have to be balanced. This | |||
8 | loop and the commands it contains are ignored because the current cell | 8 | loop and the commands it contains are ignored because the current cell |
9 | defaults to a value of 0; the 0 value causes this loop to be skipped. | 9 | defaults to a value of 0; the 0 value causes this loop to be skipped. |
10 | 10 | ||
11 | from https://en.wikipedia.org/wiki/Brainfuck#Hello_World! | 11 | from https://en.wikipedia.org/wiki/Brainfuck#Hello_World! ] |
12 | ] | 12 | ++++++++ Set Cell #0 to 8 |
13 | ++++++++ Set Cell #0 to 8 | ||
14 | [ | 13 | [ |
15 | >++++ Add 4 to Cell #1; this will always set Cell #1 to 4 | 14 | >++++ Add 4 to Cell #1; this will always set Cell #1 to 4 |
16 | [ as the cell will be cleared by the loop | 15 | [ as the cell will be cleared by the loop |
17 | >++ Add 2 to Cell #2 | 16 | >++ Add 2 to Cell #2 |
18 | >+++ Add 3 to Cell #3 | 17 | >+++ Add 3 to Cell #3 |
19 | >+++ Add 3 to Cell #4 | 18 | >+++ Add 3 to Cell #4 |
20 | >+ Add 1 to Cell #5 | 19 | >+ Add 1 to Cell #5 |
21 | <<<<- Decrement the loop counter in Cell #1 | 20 | <<<<- Decrement the loop counter in Cell #1 |
22 | ] Loop until Cell #1 is zero; number of iterations is 4 | 21 | ] Loop until Cell #1 is zero; number of iterations is 4 |
23 | >+ Add 1 to Cell #2 | 22 | >+ Add 1 to Cell #2 |
24 | >+ Add 1 to Cell #3 | 23 | >+ Add 1 to Cell #3 |
25 | >- Subtract 1 from Cell #4 | 24 | >- Subtract 1 from Cell #4 |
26 | >>+ Add 1 to Cell #6 | 25 | >>+ Add 1 to Cell #6 |
27 | [<] Move back to the first zero cell you find; this will | 26 | [<] Move back to the first zero cell you find; this will |
28 | be Cell #1 which was cleared by the previous loop | 27 | be Cell #1 which was cleared by the previous loop |
29 | <- Decrement the loop Counter in Cell #0 | 28 | <- Decrement the loop Counter in Cell #0 |
30 | ] Loop until Cell #0 is zero; number of iterations is 8 | 29 | ] Loop until Cell #0 is zero; number of iterations is 8 |
31 | 30 | ||
32 | The result of this is: | 31 | The result of this is: |
33 | Cell no : 0 1 2 3 4 5 6 | 32 | Cell no : 0 1 2 3 4 5 6 |
34 | Contents: 0 0 72 104 88 32 8 | 33 | Contents: 0 0 72 104 88 32 8 |
35 | Pointer : ^ | 34 | Pointer : ^ |
36 | 35 | ||
37 | >>. Cell #2 has value 72 which is 'H' | 36 | >>. Cell #2 has value 72 which is 'H' |
38 | >---. Subtract 3 from Cell #3 to get 101 which is 'e' | 37 | >---. Subtract 3 from Cell #3 to get 101 which is 'e' |
39 | +++++++..+++. Likewise for 'llo' from Cell #3 | 38 | +++++++..+++. Likewise for 'llo' from Cell #3 |
40 | >>. Cell #5 is 32 for the space | 39 | >>. Cell #5 is 32 for the space |
41 | <-. Subtract 1 from Cell #4 for 87 to give a 'W' | 40 | <-. Subtract 1 from Cell #4 for 87 to give a 'W' |
42 | <. Cell #3 was set to 'o' from the end of 'Hello' | 41 | <. Cell #3 was set to 'o' from the end of 'Hello' |
43 | +++.------.--------. Cell #3 for 'rl' and 'd' | 42 | +++.------.--------. Cell #3 for 'rl' and 'd' |
44 | >>+. Add 1 to Cell #5 gives us an exclamation point | 43 | >>+. Add 1 to Cell #5 gives us an exclamation point |
45 | >++. And finally a newline from Cell #6 | 44 | >++. And finally a newline from Cell #6 |
diff --git a/examples/hello-world.tf b/examples/hello-world.tf new file mode 100644 index 0000000..397bc43 --- /dev/null +++ b/examples/hello-world.tf | |||
@@ -0,0 +1,388 @@ | |||
1 | This program prints "Hello World!" and a newline to the screen, its | ||
2 | length is 106 active command characters. [It is not the shortest.] | ||
3 | |||
4 | This loop is an "initial comment loop", a simple way of adding a comment | ||
5 | to a BF program such that you don't have to worry about any command | ||
6 | characters. Any ".", ",", "+", "-", "<" and ">" characters are simply | ||
7 | ignored, the "[" and "]" characters just have to be balanced. This | ||
8 | loop and the commands it contains are ignored because the current cell | ||
9 | defaults to a value of 0; the 0 value causes this loop to be skipped. | ||
10 | |||
11 | from https://en.wikipedia.org/wiki/Brainfuck#Hello_World! | ||
12 | |||
13 | |||
14 | ALL ABOARD | ||
15 | chug chug chug chug chug chug chug chug | ||
16 | END OF THE LINE | ||
17 | Set Cell #0 to 8 | ||
18 | |||
19 | ALL ABOARD | ||
20 | tickets please | ||
21 | choo | ||
22 | chug chug chug chug | ||
23 | END OF THE LINE | ||
24 | Add 4 to Cell #1; this will always set Cell #1 to 4 | ||
25 | |||
26 | ALL ABOARD | ||
27 | tickets please | ||
28 | END OF THE LINE | ||
29 | as the cell will be cleared by the loop | ||
30 | |||
31 | ALL ABOARD | ||
32 | choo | ||
33 | chug chug | ||
34 | END OF THE LINE | ||
35 | Add 2 to Cell #2 | ||
36 | |||
37 | ALL ABOARD | ||
38 | choo | ||
39 | chug chug chug | ||
40 | END OF THE LINE | ||
41 | Add 3 to Cell #3 | ||
42 | |||
43 | ALL ABOARD | ||
44 | choo | ||
45 | chug chug chug | ||
46 | END OF THE LINE | ||
47 | Add 3 to Cell #4 | ||
48 | |||
49 | ALL ABOARD | ||
50 | choo | ||
51 | chug | ||
52 | END OF THE LINE | ||
53 | Add 1 to Cell #5 | ||
54 | |||
55 | ALL ABOARD | ||
56 | choo choo | ||
57 | choo choo | ||
58 | choo choo | ||
59 | choo choo | ||
60 | chugga | ||
61 | END OF THE LINE | ||
62 | Decrement the loop counter in Cell #1 | ||
63 | |||
64 | ALL ABOARD | ||
65 | your ticket please | ||
66 | END OF THE LINE | ||
67 | Loop until Cell #1 is zero; number of iterations is 4 | ||
68 | |||
69 | ALL ABOARD | ||
70 | choo | ||
71 | chug | ||
72 | END OF THE LINE | ||
73 | Add 1 to Cell #2 | ||
74 | |||
75 | ALL ABOARD | ||
76 | choo | ||
77 | chug | ||
78 | END OF THE LINE | ||
79 | Add 1 to Cell #3 | ||
80 | |||
81 | ALL ABOARD | ||
82 | choo | ||
83 | chugga | ||
84 | END OF THE LINE | ||
85 | Subtract 1 from Cell #4 | ||
86 | |||
87 | ALL ABOARD | ||
88 | choo | ||
89 | choo | ||
90 | chug | ||
91 | END OF THE LINE | ||
92 | Add 1 to Cell #6 | ||
93 | |||
94 | ALL ABOARD | ||
95 | tickets please choo choo | ||
96 | your ticket please | ||
97 | END OF THE LINE | ||
98 | Move back to the first zero cell you find; this will | ||
99 | be Cell #1 which was cleared by the previous loop | ||
100 | |||
101 | ALL ABOARD | ||
102 | choo choo | ||
103 | chugga | ||
104 | END OF THE LINE | ||
105 | Decrement the loop Counter in Cell #0 | ||
106 | |||
107 | ALL ABOARD | ||
108 | your ticket please | ||
109 | END OF THE LINE | ||
110 | Loop until Cell #0 is zero; number of iterations is 8 | ||
111 | |||
112 | The result of this is: | ||
113 | Cell no : 0 1 2 3 4 5 6 | ||
114 | Contents: 0 0 72 104 88 32 8 | ||
115 | Pointer : ^ | ||
116 | |||
117 | |||
118 | ALL ABOARD | ||
119 | choo | ||
120 | choo | ||
121 | click | ||
122 | END OF THE LINE | ||
123 | Cell #2 has value 72 which is 'H' | ||
124 | |||
125 | ALL ABOARD | ||
126 | choo | ||
127 | chugga chugga chugga click | ||
128 | END OF THE LINE | ||
129 | Subtract 3 from Cell #3 to get 101 which is 'e' | ||
130 | |||
131 | ALL ABOARD | ||
132 | chug chug chug chug chug chug chug clickety click chug chug chug click | ||
133 | |||
134 | END OF THE LINE | ||
135 | Likewise for 'llo' from Cell #3 | ||
136 | |||
137 | ALL ABOARD | ||
138 | choo | ||
139 | choo | ||
140 | click | ||
141 | END OF THE LINE | ||
142 | Cell #5 is 32 for the space | ||
143 | |||
144 | ALL ABOARD | ||
145 | choo choo | ||
146 | chugga clickety | ||
147 | END OF THE LINE | ||
148 | Subtract 1 from Cell #4 for 87 to give a 'W' | ||
149 | |||
150 | ALL ABOARD | ||
151 | choo choo | ||
152 | clickety | ||
153 | END OF THE LINE | ||
154 | Cell #3 was set to 'o' from the end of 'Hello' | ||
155 | |||
156 | ALL ABOARD | ||
157 | chug chug chug click chugga chugga chugga chugga chugga chugga clickety | ||
158 | chugga chugga chugga chugga chugga chugga chugga chugga click | ||
159 | END OF THE LINE | ||
160 | Cell #3 for 'rl' and 'd' | ||
161 | |||
162 | ALL ABOARD | ||
163 | choo | ||
164 | choo | ||
165 | chug click | ||
166 | END OF THE LINE | ||
167 | Add 1 to Cell #5 gives us an exclamation point | ||
168 | |||
169 | ALL ABOARD | ||
170 | choo | ||
171 | chug chug click | ||
172 | END OF THE LINE | ||
173 | And finally a newline from Cell #6 | ||
174 | ROT13 in Brainfuck | ||
175 | from https://en.wikipedia.org/wiki/Brainfuck#ROT13 | ||
176 | |||
177 | |||
178 | |||
179 | |||
180 | ALL ABOARD | ||
181 | chugga clack chug tickets please | ||
182 | END OF THE LINE | ||
183 | Read first character and start outer character reading loop | ||
184 | |||
185 | ALL ABOARD | ||
186 | chugga tickets please | ||
187 | END OF THE LINE | ||
188 | Skip forward if character is 0 | ||
189 | |||
190 | ALL ABOARD | ||
191 | choo | ||
192 | choo | ||
193 | chug chug chug chug tickets please choo | ||
194 | chug chug chug chug chug chug chug chug | ||
195 | choo choo | ||
196 | chugga your ticket please | ||
197 | END OF THE LINE | ||
198 | Set up divisor (32) for division loop | ||
199 | (MEMORY LAYOUT: dividend copy remainder divisor quotient zero zero) | ||
200 | |||
201 | ALL ABOARD | ||
202 | choo choo | ||
203 | chug choo choo | ||
204 | chugga tickets please | ||
205 | END OF THE LINE | ||
206 | Set up dividend (x minus 1) and enter division loop | ||
207 | |||
208 | ALL ABOARD | ||
209 | choo | ||
210 | chug choo | ||
211 | chug choo | ||
212 | chugga tickets please choo | ||
213 | choo | ||
214 | choo | ||
215 | your ticket please | ||
216 | END OF THE LINE | ||
217 | Increase copy and remainder / reduce divisor / Normal case: skip forward | ||
218 | |||
219 | ALL ABOARD | ||
220 | choo choo | ||
221 | tickets please tickets please choo | ||
222 | chug choo choo | ||
223 | chugga your ticket please choo | ||
224 | choo | ||
225 | chug choo | ||
226 | your ticket please | ||
227 | |||
228 | END OF THE LINE | ||
229 | Special case: move remainder back to divisor and increase quotient | ||
230 | |||
231 | ALL ABOARD | ||
232 | choo choo | ||
233 | choo choo | ||
234 | choo choo | ||
235 | choo choo | ||
236 | choo choo | ||
237 | chugga | ||
238 | END OF THE LINE | ||
239 | Decrement dividend | ||
240 | |||
241 | ALL ABOARD | ||
242 | your ticket please | ||
243 | END OF THE LINE | ||
244 | End division loop | ||
245 | |||
246 | ALL ABOARD | ||
247 | your ticket please choo | ||
248 | choo | ||
249 | choo | ||
250 | tickets please chugga your ticket please chug | ||
251 | END OF THE LINE | ||
252 | End skip loop; zero former divisor and reuse space for a flag | ||
253 | |||
254 | ALL ABOARD | ||
255 | choo | ||
256 | chugga chugga tickets please chugga tickets please choo choo | ||
257 | chugga choo | ||
258 | chug chug chug | ||
259 | tickets please chugga your ticket please your ticket please your ticket please | ||
260 | choo choo | ||
261 | tickets please | ||
262 | END OF THE LINE | ||
263 | Zero that flag unless quotient was 2 or 3; zero quotient; check flag | ||
264 | |||
265 | ALL ABOARD | ||
266 | chug chug chug chug chug chug chug chug chug chug chug chug choo choo | ||
267 | tickets please | ||
268 | |||
269 | END OF THE LINE | ||
270 | If flag then set up divisor (13) for second division loop | ||
271 | (MEMORY LAYOUT: zero copy dividend divisor remainder quotient zero zero) | ||
272 | |||
273 | ALL ABOARD | ||
274 | choo | ||
275 | chugga tickets please choo | ||
276 | chug choo | ||
277 | choo | ||
278 | your ticket please | ||
279 | END OF THE LINE | ||
280 | Reduce divisor; Normal case: increase remainder | ||
281 | |||
282 | ALL ABOARD | ||
283 | choo | ||
284 | tickets please chug tickets please choo choo | ||
285 | chug choo | ||
286 | chugga your ticket please choo | ||
287 | chug | ||
288 | choo | ||
289 | choo | ||
290 | your ticket please | ||
291 | END OF THE LINE | ||
292 | Special case: increase remainder / move it back to divisor / increase quotient | ||
293 | |||
294 | ALL ABOARD | ||
295 | choo choo | ||
296 | choo choo | ||
297 | choo choo | ||
298 | choo choo | ||
299 | choo choo | ||
300 | chugga | ||
301 | END OF THE LINE | ||
302 | Decrease dividend | ||
303 | |||
304 | ALL ABOARD | ||
305 | your ticket please | ||
306 | END OF THE LINE | ||
307 | End division loop | ||
308 | |||
309 | ALL ABOARD | ||
310 | choo | ||
311 | choo | ||
312 | tickets please choo choo | ||
313 | chug choo | ||
314 | chugga your ticket please | ||
315 | END OF THE LINE | ||
316 | Add remainder back to divisor to get a useful 13 | ||
317 | |||
318 | ALL ABOARD | ||
319 | choo | ||
320 | tickets please | ||
321 | END OF THE LINE | ||
322 | Skip forward if quotient was 0 | ||
323 | |||
324 | ALL ABOARD | ||
325 | chugga tickets please | ||
326 | END OF THE LINE | ||
327 | Decrement quotient and skip forward if quotient was 1 | ||
328 | |||
329 | ALL ABOARD | ||
330 | chugga choo choo | ||
331 | choo choo | ||
332 | tickets please chugga your ticket please choo | ||
333 | choo | ||
334 | |||
335 | END OF THE LINE | ||
336 | Zero quotient and divisor if quotient was 2 | ||
337 | |||
338 | ALL ABOARD | ||
339 | your ticket please choo choo | ||
340 | choo choo | ||
341 | tickets please choo choo | ||
342 | choo choo | ||
343 | chugga choo | ||
344 | choo | ||
345 | chugga your ticket please choo | ||
346 | choo | ||
347 | |||
348 | END OF THE LINE | ||
349 | Zero divisor and subtract 13 from copy if quotient was 1 | ||
350 | |||
351 | ALL ABOARD | ||
352 | your ticket please choo choo | ||
353 | choo choo | ||
354 | tickets please choo choo | ||
355 | choo choo | ||
356 | chug choo | ||
357 | choo | ||
358 | chugga your ticket please | ||
359 | END OF THE LINE | ||
360 | Zero divisor and add 13 to copy if quotient was 0 | ||
361 | |||
362 | ALL ABOARD | ||
363 | your ticket please | ||
364 | END OF THE LINE | ||
365 | End outer skip loop (jump to here if ((character minus 1)/32) was not 2 or 3) | ||
366 | |||
367 | ALL ABOARD | ||
368 | choo choo | ||
369 | tickets please chugga your ticket please | ||
370 | END OF THE LINE | ||
371 | Clear remainder from first division if second division was skipped | ||
372 | |||
373 | ALL ABOARD | ||
374 | choo choo | ||
375 | click tickets please chugga your ticket please | ||
376 | END OF THE LINE | ||
377 | Output ROT13ed character from copy and clear it | ||
378 | |||
379 | ALL ABOARD | ||
380 | choo choo | ||
381 | chugga clack chug | ||
382 | END OF THE LINE | ||
383 | Read next character | ||
384 | |||
385 | ALL ABOARD | ||
386 | your ticket please | ||
387 | END OF THE LINE | ||
388 | End character reading loop | ||
diff --git a/examples/printchar.bf b/examples/printchar.bf new file mode 100644 index 0000000..e0d73ad --- /dev/null +++ b/examples/printchar.bf | |||
@@ -0,0 +1,5 @@ | |||
1 | [ printchar is a small example input/output trainfuck program. | ||
2 | it waits for the user to press a key, then prints that key | ||
3 | and a newline to the screen. | ||
4 | ] | ||
5 | ,.>++++++++++. | ||
diff --git a/examples/printchar.tf b/examples/printchar.tf new file mode 100644 index 0000000..c9092be --- /dev/null +++ b/examples/printchar.tf | |||
@@ -0,0 +1,10 @@ | |||
1 | printchar is a small example input/output trainfuck program. | ||
2 | it waits for the user to press a key, then prints that key | ||
3 | and a newline to the screen. | ||
4 | ALL ABOARD | ||
5 | clack clickety | ||
6 | choo | ||
7 | chug chug chug chug chug | ||
8 | chug chug chug chug chug | ||
9 | click | ||
10 | END OF THE LINE | ||
diff --git a/examples/rot13.tf b/examples/rot13.tf new file mode 100644 index 0000000..f7c24df --- /dev/null +++ b/examples/rot13.tf | |||
@@ -0,0 +1,215 @@ | |||
1 | ROT13 in Brainfuck | ||
2 | from https://en.wikipedia.org/wiki/Brainfuck#ROT13 | ||
3 | |||
4 | |||
5 | |||
6 | |||
7 | ALL ABOARD | ||
8 | chugga clack chug tickets please | ||
9 | END OF THE LINE | ||
10 | Read first character and start outer character reading loop | ||
11 | |||
12 | ALL ABOARD | ||
13 | chugga tickets please | ||
14 | END OF THE LINE | ||
15 | Skip forward if character is 0 | ||
16 | |||
17 | ALL ABOARD | ||
18 | choo | ||
19 | choo | ||
20 | chug chug chug chug tickets please choo | ||
21 | chug chug chug chug chug chug chug chug | ||
22 | choo choo | ||
23 | chugga your ticket please | ||
24 | END OF THE LINE | ||
25 | Set up divisor (32) for division loop | ||
26 | (MEMORY LAYOUT: dividend copy remainder divisor quotient zero zero) | ||
27 | |||
28 | ALL ABOARD | ||
29 | choo choo | ||
30 | chug choo choo | ||
31 | chugga tickets please | ||
32 | END OF THE LINE | ||
33 | Set up dividend (x minus 1) and enter division loop | ||
34 | |||
35 | ALL ABOARD | ||
36 | choo | ||
37 | chug choo | ||
38 | chug choo | ||
39 | chugga tickets please choo | ||
40 | choo | ||
41 | choo | ||
42 | your ticket please | ||
43 | END OF THE LINE | ||
44 | Increase copy and remainder / reduce divisor / Normal case: skip forward | ||
45 | |||
46 | ALL ABOARD | ||
47 | choo choo | ||
48 | tickets please tickets please choo | ||
49 | chug choo choo | ||
50 | chugga your ticket please choo | ||
51 | choo | ||
52 | chug choo | ||
53 | your ticket please | ||
54 | |||
55 | END OF THE LINE | ||
56 | Special case: move remainder back to divisor and increase quotient | ||
57 | |||
58 | ALL ABOARD | ||
59 | choo choo | ||
60 | choo choo | ||
61 | choo choo | ||
62 | choo choo | ||
63 | choo choo | ||
64 | chugga | ||
65 | END OF THE LINE | ||
66 | Decrement dividend | ||
67 | |||
68 | ALL ABOARD | ||
69 | your ticket please | ||
70 | END OF THE LINE | ||
71 | End division loop | ||
72 | |||
73 | ALL ABOARD | ||
74 | your ticket please choo | ||
75 | choo | ||
76 | choo | ||
77 | tickets please chugga your ticket please chug | ||
78 | END OF THE LINE | ||
79 | End skip loop; zero former divisor and reuse space for a flag | ||
80 | |||
81 | ALL ABOARD | ||
82 | choo | ||
83 | chugga chugga tickets please chugga tickets please choo choo | ||
84 | chugga choo | ||
85 | chug chug chug | ||
86 | tickets please chugga your ticket please your ticket please your ticket please | ||
87 | choo choo | ||
88 | tickets please | ||
89 | END OF THE LINE | ||
90 | Zero that flag unless quotient was 2 or 3; zero quotient; check flag | ||
91 | |||
92 | ALL ABOARD | ||
93 | chug chug chug chug chug chug chug chug chug chug chug chug choo choo | ||
94 | tickets please | ||
95 | |||
96 | END OF THE LINE | ||
97 | If flag then set up divisor (13) for second division loop | ||
98 | (MEMORY LAYOUT: zero copy dividend divisor remainder quotient zero zero) | ||
99 | |||
100 | ALL ABOARD | ||
101 | choo | ||
102 | chugga tickets please choo | ||
103 | chug choo | ||
104 | choo | ||
105 | your ticket please | ||
106 | END OF THE LINE | ||
107 | Reduce divisor; Normal case: increase remainder | ||
108 | |||
109 | ALL ABOARD | ||
110 | choo | ||
111 | tickets please chug tickets please choo choo | ||
112 | chug choo | ||
113 | chugga your ticket please choo | ||
114 | chug | ||
115 | choo | ||
116 | choo | ||
117 | your ticket please | ||
118 | END OF THE LINE | ||
119 | Special case: increase remainder / move it back to divisor / increase quotient | ||
120 | |||
121 | ALL ABOARD | ||
122 | choo choo | ||
123 | choo choo | ||
124 | choo choo | ||
125 | choo choo | ||
126 | choo choo | ||
127 | chugga | ||
128 | END OF THE LINE | ||
129 | Decrease dividend | ||
130 | |||
131 | ALL ABOARD | ||
132 | your ticket please | ||
133 | END OF THE LINE | ||
134 | End division loop | ||
135 | |||
136 | ALL ABOARD | ||
137 | choo | ||
138 | choo | ||
139 | tickets please choo choo | ||
140 | chug choo | ||
141 | chugga your ticket please | ||
142 | END OF THE LINE | ||
143 | Add remainder back to divisor to get a useful 13 | ||
144 | |||
145 | ALL ABOARD | ||
146 | choo | ||
147 | tickets please | ||
148 | END OF THE LINE | ||
149 | Skip forward if quotient was 0 | ||
150 | |||
151 | ALL ABOARD | ||
152 | chugga tickets please | ||
153 | END OF THE LINE | ||
154 | Decrement quotient and skip forward if quotient was 1 | ||
155 | |||
156 | ALL ABOARD | ||
157 | chugga choo choo | ||
158 | choo choo | ||
159 | tickets please chugga your ticket please choo | ||
160 | choo | ||
161 | |||
162 | END OF THE LINE | ||
163 | Zero quotient and divisor if quotient was 2 | ||
164 | |||
165 | ALL ABOARD | ||
166 | your ticket please choo choo | ||
167 | choo choo | ||
168 | tickets please choo choo | ||
169 | choo choo | ||
170 | chugga choo | ||
171 | choo | ||
172 | chugga your ticket please choo | ||
173 | choo | ||
174 | |||
175 | END OF THE LINE | ||
176 | Zero divisor and subtract 13 from copy if quotient was 1 | ||
177 | |||
178 | ALL ABOARD | ||
179 | your ticket please choo choo | ||
180 | choo choo | ||
181 | tickets please choo choo | ||
182 | choo choo | ||
183 | chug choo | ||
184 | choo | ||
185 | chugga your ticket please | ||
186 | END OF THE LINE | ||
187 | Zero divisor and add 13 to copy if quotient was 0 | ||
188 | |||
189 | ALL ABOARD | ||
190 | your ticket please | ||
191 | END OF THE LINE | ||
192 | End outer skip loop (jump to here if ((character minus 1)/32) was not 2 or 3) | ||
193 | |||
194 | ALL ABOARD | ||
195 | choo choo | ||
196 | tickets please chugga your ticket please | ||
197 | END OF THE LINE | ||
198 | Clear remainder from first division if second division was skipped | ||
199 | |||
200 | ALL ABOARD | ||
201 | choo choo | ||
202 | click tickets please chugga your ticket please | ||
203 | END OF THE LINE | ||
204 | Output ROT13ed character from copy and clear it | ||
205 | |||
206 | ALL ABOARD | ||
207 | choo choo | ||
208 | chugga clack chug | ||
209 | END OF THE LINE | ||
210 | Read next character | ||
211 | |||
212 | ALL ABOARD | ||
213 | your ticket please | ||
214 | END OF THE LINE | ||
215 | End character reading loop | ||
diff --git a/fucktrain b/fucktrain index 7ade621..1c25aff 100755 --- a/fucktrain +++ b/fucktrain | |||
@@ -1,37 +1,30 @@ | |||
1 | #!/bin/awk -f | 1 | #!/bin/sh |
2 | # FUCKTRAIN: FUCKAMUTHA CHOO CHOO -*- awk -*- | 2 | # TRAINFUCK: CHOO CHOO MUTHAFUCKA -*- sh -*- |
3 | # Author: Case Duckworth <acdw@acdw.net> | 3 | # Author: Case Duckworth <acdw@acdw.net> |
4 | # License: WTFPL | 4 | # License: WTFPL |
5 | # Version: #9 | 5 | # Version: #9 |
6 | BEGIN { | ||
7 | print "ALL ABOARD" | ||
8 | } | ||
9 | 6 | ||
10 | { | 7 | ### Commentary: |
11 | gsub(/[^-+<>.,\[\]]/, "", $0) | ||
12 | gsub(/+/, "chug ", $0) | ||
13 | gsub(/-/, "chugga ", $0) | ||
14 | gsub(/>/, "choo\n", $0) | ||
15 | gsub(/</, "choo choo\n", $0) | ||
16 | gsub(/\./, clicketyClick(), $0) | ||
17 | gsub(/,/, "clack ", $0) | ||
18 | gsub(/\[/, "tickets please ", $0) | ||
19 | gsub(/\]/, "your ticket please ", $0) | ||
20 | if ($0) { | ||
21 | |||
22 | } | ||
23 | } | ||
24 | 8 | ||
25 | END { | 9 | # shell wrapper around fucktrain.awk, which see. |
26 | print "END OF THE LINE" | ||
27 | } | ||
28 | 10 | ||
11 | ### Code: | ||
29 | 12 | ||
30 | function clicketyClick() | 13 | FUCKTRAIN="$(dirname "$0")/fucktrain.awk" |
31 | { | 14 | |
32 | if (rand() <= 0.5) { | 15 | case "$(realpath "$(command -v awk)")" in |
33 | return "click " | 16 | *gawk) |
34 | } else { | 17 | AWK=gawk |
35 | return "clickety " | 18 | EXTRA_AWK_ARGS="--characters-as-bytes" # --posix overrides |
36 | } | 19 | ;; |
37 | } | 20 | *mawk) |
21 | AWK=mawk | ||
22 | EXTRA_AWK_ARGS="-Wposix" | ||
23 | ;; | ||
24 | *) | ||
25 | AWK=awk | ||
26 | EXTRA_AWK_ARGS= | ||
27 | ;; | ||
28 | esac | ||
29 | |||
30 | "$AWK" -v EXE_NAME="$(basename $0)" -f "$FUCKTRAIN" $EXTRA_AWK_ARGS -- "$@" | ||
diff --git a/fucktrain.awk b/fucktrain.awk new file mode 100755 index 0000000..4ab5f5b --- /dev/null +++ b/fucktrain.awk | |||
@@ -0,0 +1,97 @@ | |||
1 | #!/bin/awk -f | ||
2 | # FUCKTRAIN: FUCKAMUTHA CHOO CHOO -*- awk -*- | ||
3 | # Author: Case Duckworth <acdw@acdw.net> | ||
4 | # License: WTFPL | ||
5 | # Version: #9 | ||
6 | |||
7 | ### Commentary: | ||
8 | |||
9 | # FUCKTRAIN turns brainfuck code into trainfuck code. | ||
10 | |||
11 | ### Code: | ||
12 | BEGIN { | ||
13 | buffer = "" | ||
14 | fold_width = 70 | ||
15 | width = 0 | ||
16 | } | ||
17 | |||
18 | { | ||
19 | buffer = buffer $0 "\n" | ||
20 | } | ||
21 | |||
22 | END { | ||
23 | sub(/^[ \t\n\r\f]+/, "", buffer) | ||
24 | sub(/[ \t\n\r\f]+$/, "", buffer) | ||
25 | split(buffer, bufa, "") | ||
26 | boarded = 0 | ||
27 | header = 1 | ||
28 | for (c in bufa) { | ||
29 | if (bufa[c] == "[" && header) { | ||
30 | header++ | ||
31 | if (header == 2) { | ||
32 | c++ | ||
33 | } | ||
34 | } | ||
35 | if (bufa[c] == "]" && header) { | ||
36 | header-- | ||
37 | if (header == 1) { | ||
38 | header = 0 | ||
39 | c++ | ||
40 | } | ||
41 | } | ||
42 | if (! boarded && ! header && bufa[c] ~ /[-+<>.,\[\]]/) { | ||
43 | printf "\n%s\n", "ALL ABOARD" | ||
44 | boarded = 1 | ||
45 | } | ||
46 | if (boarded) { | ||
47 | if (width > fold_width) { | ||
48 | print "" | ||
49 | width = 0 | ||
50 | } | ||
51 | if (bufa[c] == ">") { | ||
52 | printf "%s", "choo\n" | ||
53 | } else if (bufa[c] == "<") { | ||
54 | printf "%s", "choo choo\n" | ||
55 | } else if (bufa[c] == "+") { | ||
56 | printf "%s", "chug " | ||
57 | width += 5 | ||
58 | } else if (bufa[c] == "-") { | ||
59 | printf "%s", "chugga " | ||
60 | width += 7 | ||
61 | } else if (bufa[c] == ".") { | ||
62 | click = clickety_click() | ||
63 | printf "%s", click | ||
64 | width += length(click) | ||
65 | } else if (bufa[c] == ",") { | ||
66 | printf "%s", "clack " | ||
67 | width += 6 | ||
68 | } else if (bufa[c] == "[") { | ||
69 | printf "%s", "tickets please " | ||
70 | width += 15 | ||
71 | } else if (bufa[c] == "]") { | ||
72 | printf "%s", "your ticket please " | ||
73 | width += 19 | ||
74 | } else if (bufa[c] ~ /[\n]/) { | ||
75 | printf "%s", bufa[c] | ||
76 | width = 0 | ||
77 | } else { | ||
78 | printf "\n%s\n%s", "END OF THE LINE", bufa[c] | ||
79 | boarded = 0 | ||
80 | } | ||
81 | } else { | ||
82 | width = 0 | ||
83 | printf "%s", bufa[c] | ||
84 | } | ||
85 | } | ||
86 | print "" | ||
87 | } | ||
88 | |||
89 | |||
90 | function clickety_click() | ||
91 | { | ||
92 | if (rand() <= 0.5) { | ||
93 | return "clickety " | ||
94 | } else { | ||
95 | return "click " | ||
96 | } | ||
97 | } | ||
diff --git a/trainfuck b/trainfuck index 22d1009..dec743b 100755 --- a/trainfuck +++ b/trainfuck | |||
@@ -10,6 +10,21 @@ | |||
10 | 10 | ||
11 | ### Code: | 11 | ### Code: |
12 | 12 | ||
13 | TRAINFUCK=trainfuck.awk | 13 | TRAINFUCK="$(dirname "$0")/trainfuck.awk" |
14 | 14 | ||
15 | gawk -v EXE_NAME="$(basename $0)" -f "$TRAINFUCK" -- "$@" | 15 | case "$(realpath "$(command -v awk)")" in |
16 | *gawk) | ||
17 | AWK=gawk | ||
18 | EXTRA_AWK_ARGS="--characters-as-bytes" # --posix overrides | ||
19 | ;; | ||
20 | *mawk) | ||
21 | AWK=mawk | ||
22 | EXTRA_AWK_ARGS="-Wposix" | ||
23 | ;; | ||
24 | *) | ||
25 | AWK=awk | ||
26 | EXTRA_AWK_ARGS= | ||
27 | ;; | ||
28 | esac | ||
29 | |||
30 | "$AWK" -v EXE_NAME="$(basename $0)" -f "$TRAINFUCK" $EXTRA_AWK_ARGS -- "$@" | ||
diff --git a/trainfuck.awk b/trainfuck.awk index df89821..1a6c19c 100755 --- a/trainfuck.awk +++ b/trainfuck.awk | |||
@@ -39,6 +39,7 @@ BEGIN { | |||
39 | # Constants | 39 | # Constants |
40 | EXE_NAME = (EXE_NAME ? EXE_NAME : "trainfuck") | 40 | EXE_NAME = (EXE_NAME ? EXE_NAME : "trainfuck") |
41 | ERR_SYNTAX = 1 | 41 | ERR_SYNTAX = 1 |
42 | ERR_ARGUMENT = 2 | ||
42 | } | 43 | } |
43 | 44 | ||
44 | BEGIN { | 45 | BEGIN { |
@@ -46,6 +47,7 @@ BEGIN { | |||
46 | ABOARD = 0 | 47 | ABOARD = 0 |
47 | FIRST_LINE = 1 | 48 | FIRST_LINE = 1 |
48 | OFS = "\t" | 49 | OFS = "\t" |
50 | header = 0 | ||
49 | } | 51 | } |
50 | 52 | ||
51 | BF_MODE == "brainfuck" { | 53 | BF_MODE == "brainfuck" { |
@@ -54,14 +56,16 @@ BF_MODE == "brainfuck" { | |||
54 | } | 56 | } |
55 | 57 | ||
56 | FIRST_LINE { | 58 | FIRST_LINE { |
57 | if (BF_PRINT_COMMENTS && first_line != "[") { | 59 | if (BF_PRINT_COMMENTS && $0 !~ /^[ \t]\[/) { |
58 | eprint("[") | 60 | eprint("[ ", 1) |
59 | } | 61 | } |
60 | eprint(first_line) | ||
61 | FIRST_LINE = 0 | 62 | FIRST_LINE = 0 |
62 | } | 63 | } |
63 | 64 | ||
64 | /^ALL ABOARD$/ { | 65 | /^ALL ABOARD$/ { |
66 | if (NR == 1) { | ||
67 | eprint(ARGV[1] " ", 1) | ||
68 | } | ||
65 | if (! header && BF_PRINT_COMMENTS) { | 69 | if (! header && BF_PRINT_COMMENTS) { |
66 | eprint("]") | 70 | eprint("]") |
67 | } | 71 | } |
@@ -94,6 +98,7 @@ END { | |||
94 | exit dead | 98 | exit dead |
95 | } | 99 | } |
96 | printbuf() | 100 | printbuf() |
101 | print "" | ||
97 | if (BF_EXECUTE) { | 102 | if (BF_EXECUTE) { |
98 | brainfuck(bf_program) | 103 | brainfuck(bf_program) |
99 | } | 104 | } |
@@ -108,8 +113,11 @@ function brainfuck(buffer) | |||
108 | for (n = 1; n < 30000; n++) { | 113 | for (n = 1; n < 30000; n++) { |
109 | tape[n] = 0 | 114 | tape[n] = 0 |
110 | } | 115 | } |
111 | while (c <= length(bf)) { | 116 | len_bf = 0 |
112 | # print i, tape[i], c, bf[c] | 117 | for (i in bf) { |
118 | len_bf++ | ||
119 | } | ||
120 | while (c <= len_bf) { | ||
113 | if (bf[c] == "<" && c > 1) { | 121 | if (bf[c] == "<" && c > 1) { |
114 | i-- | 122 | i-- |
115 | } else if (bf[c] == ">") { | 123 | } else if (bf[c] == ">") { |
@@ -163,10 +171,32 @@ function brainfuck(buffer) | |||
163 | } | 171 | } |
164 | } | 172 | } |
165 | 173 | ||
166 | function die(message, errnum) | 174 | function char2number(ch) |
175 | { | ||
176 | ascii = "" # NUL is undefined in POSIX awk ... XXX: | ||
177 | ascii = ascii "\001\002\003\004\005\006\a\b\t\n\v\f\r\016\017" | ||
178 | ascii = ascii "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" | ||
179 | ascii = ascii " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNO" | ||
180 | ascii = ascii "PQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177" | ||
181 | ascii = ascii "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217" | ||
182 | ascii = ascii "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237" | ||
183 | ascii = ascii "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257" | ||
184 | ascii = ascii "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" | ||
185 | ascii = ascii "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" | ||
186 | ascii = ascii "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" | ||
187 | ascii = ascii "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" | ||
188 | ascii = ascii "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377" | ||
189 | # print ch | ||
190 | return index(ascii, ch) | ||
191 | } | ||
192 | |||
193 | function die(message, errnum, now) | ||
167 | { | 194 | { |
168 | print(message) > "/dev/stderr" | 195 | print(message) > "/dev/stderr" |
169 | dead = errnum | 196 | dead = errnum |
197 | if (now) { | ||
198 | exit errnum | ||
199 | } | ||
170 | } | 200 | } |
171 | 201 | ||
172 | function eprint(message, suppress_newline) | 202 | function eprint(message, suppress_newline) |
@@ -177,9 +207,9 @@ function eprint(message, suppress_newline) | |||
177 | function getchar() | 207 | function getchar() |
178 | { | 208 | { |
179 | system("stty raw") | 209 | system("stty raw") |
180 | cmd = "dd bs=1 count=1 2>/dev/null" | 210 | chcmd = "dd bs=1 count=1 2>/dev/null" |
181 | cmd | getline ch | 211 | chcmd | getline ch |
182 | close(cmd) | 212 | close(chcmd) |
183 | system("stty cooked") | 213 | system("stty cooked") |
184 | return ch | 214 | return ch |
185 | } | 215 | } |
@@ -236,6 +266,11 @@ function process_commandline() | |||
236 | BF_MODE = "brainfuck" | 266 | BF_MODE = "brainfuck" |
237 | BF_MODE_FORCE = 1 | 267 | BF_MODE_FORCE = 1 |
238 | delete ARGV[a] | 268 | delete ARGV[a] |
269 | } else if (ARGV[a] == "-q" || ARGV[a] == "--quiet") { | ||
270 | BF_OUTPUT = "/dev/null" | ||
271 | delete ARGV[a] | ||
272 | } else if (ARGV[a] ~ /^-/) { | ||
273 | die("Unknown option '" ARGV[a] "'", ERR_ARGUMENT, 1) | ||
239 | } | 274 | } |
240 | } | 275 | } |
241 | if (! BF_MODE_FORCE) { | 276 | if (! BF_MODE_FORCE) { |