DEFINE shl == 2 *; shr == 2 /; and63 == [64 / 64 *] nullary -; b64enc1 == ord 16 [shl] times [ord 8 [shl] times] dip + [ord] dip +; b64enc2 == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" swap [] [ [18 [shr] times and63 at] [12 [shr] times and63 at] [6 [shr] times and63 at] [and63 at] ] construct "" cons cons cons cons [pop] dip; s2l == [null] [pop []] [uncons] [cons] linrec; b64enc == s2l "" swap # pad with null bytes # calculate how many bytes to pad [size 3 rem 3 swap - 3 rem] nullary # i cant use null bytes in strings (hence s2l) [0 chr [] cons concat] times # len(s)/3 times [size 3 /] nullary [[3 take] nullary s2l [b64enc1 b64enc2] infra first rollup [swap concat] dip 3 drop] times # remove the now-empty string pop "\n" concat END stdin [feof not] [fgets b64enc putchars] while fclose.