misc-scripts/basedec.sh

90 lines
1.7 KiB
Bash

#!/bin/sh
usage() {
printf 'usage: %s [-s] [-t type] [file ...]\n' "${0##*/}" >&2
exit 64
}
case "$(printf %s "${0##*/}" | tr A-Z a-z)" in
*16*) type=16;;
*32hex*|*32x*)
type=32x;;
*32*) type=32;;
*64s*) type=64s;;
*64*) type=64;;
*) type=64;;
esac
b16=0123456789ABCDEF
b32=ABCDEFGHIJKLMNOPQRSTUVWXYZ234567
b32hex=0123456789ABCDEFGHIJKLMNOPQRSTUV
b64=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
b64safe=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_
strict=0
while getopts t:s opt; do
case "$opt" in
t) case "$(printf %s "$OPTARG" | tr A-Z a-z)" in
16) type=16;;
32) type=32;;
32x) type=32x;;
64) type=64;;
64s|64safe)
type=64s;;
*) usage;;
esac
;;
s) strict=1;;
*) usage;;
esac
done
shift $((OPTIND - 1))
case "$type" in
16) alphabet="$b16"
insensitive=1
bits=4;;
32) alphabet="$b32"
insensitive=1
bits=5;;
32x) alphabet="$b32hex"
insensitive=1
bits=5;;
64) alphabet="$b64"
insensitive=0
bits=6;;
64s) alphabet="$b64safe"
insensitive=0
bits=6;;
*) usage;; # Unreachable
esac
cat -- "$@" | awk -vbits="$bits" -valphabet="$alphabet" \
-vinsensitive="$insensitive" -vstrict="$strict" '
function leftshift(a, b) {
return a * 2 ** b
}
function rightshift(a, b) {
return int(a / 2 ** b)
}
function mask(a, b) {
return a > 0 ? a % leftshift(1, b) : a
}
BEGIN {
FS=""
split(alphabet, al, "")
for (n in al)
a[al[n]] = n - 1
if (insensitive)
for (c in a)
a[tolower(c)] = a[c]
} {
for (i = 1; i <= NF; i++) {
if ($i in a) {
t = leftshift(t, bits) + a[$i]
b += bits
while (b >= 8) {
b -= 8
printf "%c", rightshift(t, b)
t = mask(t, b)
count++
}
} else if (strict && $i != "=")
exit 65
}
}'