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