Skip to content

Instantly share code, notes, and snippets.

@marcan
Created April 22, 2016 01:27
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save marcan/347faf7fa09802016d0c253699132539 to your computer and use it in GitHub Desktop.
Save marcan/347faf7fa09802016d0c253699132539 to your computer and use it in GitHub Desktop.
Brainfuck interpreter in POSIX sh
#!/bin/sh
# Brainfuck interpreter implemented in pure POSIX sh builtins only (except I/O)
# Tested in bash and busybox ash (getchar uses a bash-specific read)
# === I/O ===
getchar() {
# bashism
IFS= read -rN 1 a
if [ -z "$a" ]; then
echo $th
else
printf %d "'$a"
fi
}
putchar() {
printf "\x$(printf %x $1)"
}
# === Core BF interpreter: pure POSIX shell with builtins only from here on ===
pl=""
pr=""
while read -r line; do
pl="$pl$line"
done <"$1"
th="0"
tl=""
tr=""
while :; do
case "$pl" in
'+'*)
th=$((th+1));;
'-'*)
th=$((th-1));;
'.'*)
putchar $th;;
','*)
th=$(getchar);;
'>'*)
tl="$th $tl"
set -- $tr
th=${1:-0}
shift
tr="$*"
;;
'<'*)
tr="$th $tr"
set -- $tl
th=${1:-0}
shift
tl="$*"
;;
'['*)
case "$th" in 0)
i=1
while :; do
tmp="${pl#?}"
pr="${pl%"$tmp"}$pr"
pl="$tmp"
case "$pl" in
'['*) i=$((i+1));;
']'*) i=$((i-1));;
esac
case $i in 0) break; esac
done
esac
;;
']'*)
case "$th" in 0);; *)
i=1
while :; do
tmp="${pr#?}"
pl="${pr%"$tmp"}$pl"
pr="$tmp"
case "$pl" in
']'*) i=$((i+1));;
'['*) i=$((i-1));;
esac
case $i in 0) break; esac
done
esac
;;
'')
break
esac
tmp="${pl#?}"
pr="${pl%"$tmp"}$pr"
pl="$tmp"
done
Copy link

ghost commented Jan 10, 2021

putchar(){
    (
    O="$(printf %o $1)"'
    case O in
        ?) O=00"$O";;
        ??) O=0"$O";;
        ????*)
            printf '%s' "$0: putchar: assertion failed: (length of O)<4" 1>&2
            exit 10
            ;;
    esac
    printf '\'"$O"
    )
}

This is shorter;

printf '\'"$(printf %03o "$1")"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment