#!/usr/bin/nawk -f
#  uu2b64: convert uuencoded file to base64
#  $Id$
#
#  Possible usage:
#      tar cf - <dir> | compress -c | uuencode "${EXP_FNAME}.tar.Z" | nawk -f uu2b64

BEGIN {
	ORS = "";

	for (i = 32; i < 96; i++) {
		uuchars = uuchars sprintf("%c", i);
	}

	b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	b64chars = b64chars "abcdefghijklmnopqrstuvwxyz";
	b64chars = b64chars "0123456789+/";

}

#
# convert a string of uuencoded characters to base64 characters
#
function uu2b64 (uustring, b64string) {
	for (i = 1; i <= length(uustring); i++) {
		if (val = index(uuchars, substr(uustring, i, 1))) {
			b64string = b64string substr(b64chars, val, 1);
		}
	}
	return b64string;
}

# uuencode and base64 both follow a 3-bytes => 4-printable-characters scheme.
# base64 specifies that when the input is not a multiple of three, that bytes
# of all zeroes be encoded.  uuencode, however, leaves slop it its remaining
# bits, and instead has a length of valid bytes (not sextets) specified as the
# first character of each line.

# so, sex2() and sex3() will "clean up" the 2nd or 3rd sextet that was left
# behind by uuencode, assuming the 2nd or 3rd byte is invalid.

function sex2 (uuchar, uuvalue, clean) {
	uuvalue = index(uuchars, uuchar) - 1;
	clean = 16 * int(uuvalue / 16);
	return substr(b64chars, clean + 1, 1);
}

function sex3 (uuchar, uuvalue, clean) {
	uuvalue = index(uuchars, uuchar) - 1;
	clean = 4 * int(uuvalue / 4);
	return substr(b64chars, clean + 1, 1);
}

# main loop assumes that only the last line of uuencode output may have
# a number of valid bytes not divisible by three.

! /(^begin |^end$|^ $)/ {
	uubytes = index(uuchars, substr($0, 1, 1)) - 1;
	trios = int(uubytes / 3);
	clean = trios * 4;
	cruft = uubytes % 3;

	print uu2b64(substr($0, 2, clean));

	if (cruft != 0) {
		print uu2b64(substr($0, 2 + clean, 1));
		if (cruft == 1) {
			print sex2(substr($0, 3 + clean, 1)) "==";
		} else {
			print uu2b64(substr($0, 3 + clean, 1));
			print sex3(substr($0, 4 + clean, 1)) "=";
		}
	}

	print "\n";
}
