Skip to content

Instantly share code, notes, and snippets.

@izabera
Created November 23, 2016 10:23
Show Gist options
  • Save izabera/54cbe49d7ef6a908361369039515b432 to your computer and use it in GitHub Desktop.
Save izabera/54cbe49d7ef6a908361369039515b432 to your computer and use it in GitHub Desktop.
brainfuck interpreter in posix sh
#!/bin/sh
LANG=C
compile() {
# some preprocessing and basic optimizations
code=$(printf %s "$1" |
(tr -dc '\133\135<>,.+-'; echo) | # ksh's builtin tr doesn't like []<>,.+-
sed -e :a -e 's/<>//g;s/><//g;s/+-//g;s/-+//g
s/\[-]/z/g;s/zzz*/z/g;s/[+-]z/z/g;ta')
while [ "$code" ]; do
case $code in
'['*) echo 'while [ "$((t$p))" != 0 ]; do :' ;; # add : for []
']'*) echo 'done' ;;
'.'*) echo 'putchar' ;;
','*) echo 'getchar' ;;
'z'*) echo ': "$((t$p=0))"' ;;
'+'*) rle=1
while case $code in '++'*) ;; *) false ;; esac; do code=${code#?} rle=$((rle+1)); done
echo ': "$((t$p=(t$p+'"$rle"')&255))"' ;;
'-'*) rle=1
while case $code in '--'*) ;; *) false ;; esac; do code=${code#?} rle=$((rle+1)); done
echo ': "$((t$p=(t$p-'"$rle"')&255))"' ;;
'>'*) rle=1
while case $code in '>>'*) ;; *) false ;; esac; do code=${code#?} rle=$((rle+1)); done
echo 'p=$((p+'"$rle"'))' ;;
'<'*) rle=1
while case $code in '<<'*) ;; *) false ;; esac; do code=${code#?} rle=$((rle+1)); done
echo 'p=$((p-'"$rle"'))' ;;
esac
code=${code#?}
done
}
getchar() {
# some od versions print spaces or leading zeros with -tu1
input=$(dd bs=1 count=1 2>/dev/null | od -An -tu1 | sed 's/^ *0*//')
: "$((t$p=input))"
}
putchar() {
: "$((output=t$p))"
printf "\\$(printf %03o "$output")"
}
p=0
code=$(compile "$(cat "$1")")
eval "$code"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment