#!/bin/sh

# Copyright (c) 2012 dak180
# See http://opensource.org/licenses/bsd-license.php for licence terms
#
# autorevision - extracts metadata about the head version from your repository.

# Usage message.
arUsage() {
	cat > "/dev/stderr" << EOF
usage: ./autorevision {-t output-type | -s symbol} [-o cache-file [-f] ] [-V]
	Options include:
	-t output-type		= specify output type
	-s symbol		= specify symbol output
	-o cache-file		= specify cache file location
	-f			= force the use of cache data
	-V			= emit version and exit
	-?			= help message

The folowing are valid output types:
	h			= Header for use with c/c++
	xcode			= Header useful for populating info.plist files
	sh			= Bash sytax
	py			= Python file
	pl			= Perl file
	lua			= Lua file
	php			= PHP file
	ini			= INI file
	js			= javascript file
	java			= Java file
	javaprop		= Java properties file
	tex			= (La)TeX file
	m4			= m4 file

The following are valid symbols:
	VCS_TYPE
	VCS_BASENAME
	VCS_NUM
	VCS_DATE
	VCS_BRANCH
	VCS_TAG
	VCS_TICK
	VCS_FULL_HASH
	VCS_SHORT_HASH
	VCS_WC_MODIFIED
EOF
	exit 1
}

# Config
ARVERSION="1.4"
TARGETFILE="/dev/stdout"
while getopts ":t:o:s:Vf" OPTION; do
	case "${OPTION}" in
		t)
			AFILETYPE="${OPTARG}"
		;;
		o)
			CACHEFILE="${OPTARG}"
		;;
		f)
			CACHEFORCE="1"
		;;
		s)
			VAROUT="${OPTARG}"
		;;
		V)
			echo "autorevision ${ARVERSION}"
			exit 0
		;;
		?)
			# If an unknown flag is used (or -?):
			arUsage
		;;
	esac
done

if [ ! -z "${VAROUT}" ] && [ ! -z "${AFILETYPE}" ]; then
	# If both -s and -t are specified:
	echo "error: Improper argument combination." 1>&2
	exit 1
elif [ -z "${VAROUT}" ] && [ -z "${AFILETYPE}" ]; then
	# If neither -s or -t are specified:
	arUsage
elif [ -z "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then
	# If -f is specified without -o:
	arUsage
fi


# Functions to extract data from different repo types.
# For git repos
gitRepo() {
	cd "$(git rev-parse --show-toplevel)"

	VCS_TYPE="git"

	VCS_BASENAME="$(basename "${PWD}")"

	 # Is the working copy clean?
	test -z "$(git status -uno --porcelain)"
	VCS_WC_MODIFIED="${?}"

	# Enumeration of changesets
	VCS_NUM="$(git rev-list --count HEAD 2>/dev/null)"
	if [ -z "${VCS_NUM}" ]; then
		echo "warning: Counting the number of revisions may be slower due to an outdated git version less than 1.7.2.3. If something breaks, please update it." 1>&2
		VCS_NUM="$(git rev-list HEAD | wc -l)"
	fi

	# The full revision hash
	VCS_FULL_HASH="$(git rev-parse HEAD)"

	# The short hash
	VCS_SHORT_HASH="$(echo "${VCS_FULL_HASH}" | cut -b 1-7)"

	# Current branch
	VCS_BRANCH="$(git rev-parse --symbolic-full-name --verify "$(git name-rev --name-only --no-undefined HEAD 2>/dev/null)" 2>/dev/null | sed -e 's:refs/heads/::' | sed -e 's:refs/::')"

	# Cache the description
	DESCRIPTION="$(git describe --long --tags 2>/dev/null)"

	# Current or last tag ancestor (empty if no tags)
	VCS_TAG="$(echo "${DESCRIPTION}" | sed -e "s:-g${VCS_SHORT_HASH}\$::" | sed -e 's:-[0-9]*$::')"

	# Distance to last tag or an alias of VCS_NUM if there is no tag
	if [ ! -z "${DESCRIPTION}" ]; then
		VCS_TICK="$(echo "${DESCRIPTION}" | sed -e "s:${VCS_TAG}-::" -e "s:-g${VCS_SHORT_HASH}::")"
	else
		VCS_TICK="${VCS_NUM}"
	fi

	# Date of the current commit
	VCS_DATE="$(git log -1 --pretty=format:%ci | sed -e 's: :T:' | sed -e 's: ::')"
}

# For hg repos
hgRepo() {
	cd "$(hg root)"

	VCS_TYPE="hg"

	VCS_BASENAME="$(basename "${PWD}")"

	# Is the working copy clean?
	hg sum | grep -q 'commit: (clean)'
	VCS_WC_MODIFIED="${?}"

	# Enumeration of changesets
	VCS_NUM="$(hg id -n | tr -d '+')"

	# The full revision hash
	VCS_FULL_HASH="$(hg log -r "${VCS_NUM}" -l 1 --template '{node}\n')"

	# The short hash
	VCS_SHORT_HASH="$(hg id -i | tr -d '+')"

	# Current bookmark (bookmarks are roughly equivalent to git's branches)
	# or branch if no bookmark
	VCS_BRANCH="$(hg id -B | cut -d ' ' -f 1)"
	# Fall back to the branch if there are no bookmarks
	if [ -z "${VCS_BRANCH}" ]; then
		VCS_BRANCH="$(hg id -b)"
	fi

	# Current or last tag ancestor (excluding auto tags, empty if no tags)
	VCS_TAG="$(hg log -r "${VCS_NUM}" -l 1 --template '{latesttag}\n' 2>/dev/null | sed -e 's:qtip::' -e 's:tip::' -e 's:qbase::' -e 's:qparent::' -e "s:$(hg --config 'extensions.color=' --color never qtop 2>/dev/null)::" | cut -d ' ' -f 1)"

	# Distance to last tag or an alias of VCS_NUM if there is no tag
	if [ ! -z "${VCS_TAG}" ]; then
		VCS_TICK="$(hg log -r "${VCS_NUM}" -l 1 --template '{latesttagdistance}\n' 2>/dev/null)"
	else
		VCS_TICK="${VCS_NUM}"
	fi

	# Date of the current commit
	VCS_DATE="$(hg log -r "${VCS_NUM}" -l 1 --template '{date|isodatesec}\n' 2>/dev/null | sed -e 's: :T:' | sed -e 's: ::')"
}

# For bzr repos
bzrRepo() {
	cd "$(bzr root)"

	VCS_TYPE="bzr"

	VCS_BASENAME="$(basename "${PWD}")"

	# Is the working copy clean?
	bzr version-info --custom --template='{clean}\n' | grep -q '1'
	VCS_WC_MODIFIED="${?}"

	# Enumeration of changesets
	VCS_NUM="$(bzr revno)"

	# The full revision hash
	VCS_FULL_HASH="$(bzr version-info --custom --template='{revision_id}\n')"

	# The short hash
	VCS_SHORT_HASH="${VCS_NUM}"

	# Nick of the current branch
	VCS_BRANCH="$(bzr nick)"

	# Current or last tag ancestor (excluding auto tags, empty if no tags)
	VCS_TAG="$(bzr tags --sort=time | sed '/?$/d' | tail -n1 | cut -d ' ' -f1)"

	# Distance to last tag or an alias of VCS_NUM if there is no tag
	if [ ! -z "${VCS_TAG}" ]; then
		VCS_TICK="$(bzr log --line -r "tag:${VCS_TAG}.." | tail -n +2 | wc -l | sed -e 's:^ *::')"
	else
		VCS_TICK="${VCS_NUM}"
	fi

	# Date of the current commit
	VCS_DATE="$(bzr version-info --custom --template='{date}\n' | sed -e 's: :T:' | sed -e 's: ::')"
}

# For svn repos
svnRepo() {
	VCS_TYPE="svn"

	case "${PWD}" in
	/*trunk*|/*branches*|/*tags*)
		fn="${PWD}"
		while [ "$(basename "${fn}")" != 'trunk' ] && [ "$(basename "${fn}")" != 'branches' ] && [ "$(basename "${fn}")" != 'tags' ] && [ "$(basename "${fn}")" != '/' ]; do
			fn="$(dirname "${fn}")"
		done
		fn="$(dirname "${fn}")"
		if [ "${fn}" = '/' ]; then
			VCS_BASENAME="$(basename "${PWD}")"
		else
			VCS_BASENAME="$(basename "${fn}")"
		fi
		;;
	*) VCS_BASENAME="$(basename "${PWD}")" ;;
	esac

	# Cache svnversion output
	SVNVERSION="$(svnversion)"

	# Is the working copy clean?
	echo "${SVNVERSION}" | grep -q "M"
	case "${?}" in
		0) VCS_WC_MODIFIED="1";;
		1) VCS_WC_MODIFIED="0";;
	esac

	# Enumeration of changesets
	VCS_NUM="$(echo "${SVNVERSION}" | cut -d : -f 1 | sed -e 's:M::' -e 's:S::' -e 's:P::')"

	# The full revision hash
	VCS_FULL_HASH="${SVNVERSION}"

	# The short hash
	VCS_SHORT_HASH="${VCS_NUM}"

	# Current branch
	case "${PWD}" in
	/*trunk*|/*branches*|/*tags*)
		lastbase=""
		fn="${PWD}"
		while :
		do
			base="$(basename "${fn}")"
			if [ "${base}" = 'trunk' ]; then
				VCS_BRANCH='trunk'
				break
			elif [ "${base}" = 'branches' ] || [ "${base}" = 'tags' ]; then
				VCS_BRANCH="${lastbase}"
				break
			elif [ "${base}" = '/' ]; then
				VCS_BRANCH=""
				break
			fi
			lastbase="${base}"
			fn="$(dirname "${fn}")"
		done
		;;
	*) VCS_BRANCH="" ;;
	esac

	# Current or last tag ancestor (empty if no tags). But "current tag"
	# can't be extracted reliably because Subversion doesn't have tags the
	# way other VCSes do.
	VCS_TAG=""
	VCS_TICK=""

	# Date of the current commit
	VCS_DATE="$(svn info | sed -n -e 's:Last Changed Date\: ::p' | sed 's: (.*)::' | sed -e 's: :T:' | sed -e 's: ::')"
}


# Functions to output data in different formats.
# For header output
hOutput() {
	cat > "${TARGETFILE}" << EOF
/* Generated by autorevision - do not hand-hack! */
#ifndef AUTOREVISION_H
#define AUTOREVISION_H

#define VCS_TYPE		"${VCS_TYPE}"
#define VCS_BASENAME	"${VCS_BASENAME}"
#define VCS_NUM			${VCS_NUM}
#define VCS_DATE		"${VCS_DATE}"
#define VCS_BRANCH		"${VCS_BRANCH}"
#define VCS_TAG			"${VCS_TAG}"
#define VCS_TICK		${VCS_TICK}

#define VCS_FULL_HASH		"${VCS_FULL_HASH}"
#define VCS_SHORT_HASH		"${VCS_SHORT_HASH}"

#define VCS_WC_MODIFIED		${VCS_WC_MODIFIED}

#endif

/* end */
EOF
}

# A header output for use with xcode to populate info.plist strings
xcodeOutput() {
	cat > "${TARGETFILE}" << EOF
/* Generated by autorevision - do not hand-hack! */
#ifndef AUTOREVISION_H
#define AUTOREVISION_H

#define VCS_TYPE		${VCS_TYPE}
#define VCS_BASENAME	${VCS_BASENAME}
#define VCS_NUM			${VCS_NUM}
#define VCS_DATE		${VCS_DATE}
#define VCS_BRANCH		${VCS_BRANCH}
#define VCS_TAG			${VCS_TAG}
#define VCS_TICK		${VCS_TICK}

#define VCS_FULL_HASH		${VCS_FULL_HASH}
#define VCS_SHORT_HASH		${VCS_SHORT_HASH}

#define VCS_WC_MODIFIED		${VCS_WC_MODIFIED}

#endif

/* end */
EOF
}

# For bash output
shOutput() {
	cat > "${TARGETFILE}" << EOF
# Generated by autorevision - do not hand-hack!

VCS_TYPE="${VCS_TYPE}"
VCS_BASENAME="${VCS_BASENAME}"
VCS_NUM=${VCS_NUM}
VCS_DATE="${VCS_DATE}"
VCS_BRANCH="${VCS_BRANCH}"
VCS_TAG="${VCS_TAG}"
VCS_TICK=${VCS_TICK}

VCS_FULL_HASH="${VCS_FULL_HASH}"
VCS_SHORT_HASH="${VCS_SHORT_HASH}"

VCS_WC_MODIFIED=${VCS_WC_MODIFIED}

# end
EOF
}

# For Python output
pyOutput() {
	case "${VCS_WC_MODIFIED}" in
		0) VCS_WC_MODIFIED="False" ;;
		1) VCS_WC_MODIFIED="True" ;;
	esac
	cat > "${TARGETFILE}" << EOF
# Generated by autorevision - do not hand-hack!

VCS_TYPE = "${VCS_TYPE}"
VCS_BASENAME = "${VCS_BASENAME}"
VCS_NUM = ${VCS_NUM}
VCS_DATE = "${VCS_DATE}"
VCS_BRANCH = "${VCS_BRANCH}"
VCS_TAG = "${VCS_TAG}"
VCS_TICK = ${VCS_TICK}

VCS_FULL_HASH = "${VCS_FULL_HASH}"
VCS_SHORT_HASH = "${VCS_SHORT_HASH}"

VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}

# end
EOF
}

# For Perl output
plOutput() {
	cat << EOF
# Generated by autorevision - do not hand-hack!

\$VCS_TYPE = "${VCS_TYPE}";
\$VCS_BASENAME = "${VCS_BASENAME}"
\$VCS_NUM = ${VCS_NUM};
\$VCS_DATE = "${VCS_DATE}";
\$VCS_BRANCH = "${VCS_BRANCH}";
\$VCS_TAG = "${VCS_TAG}";
\$VCS_TICK = ${VCS_TICK};

\$VCS_FULL_HASH = "${VCS_FULL_HASH}";
\$VCS_SHORT_HASH = "${VCS_SHORT_HASH}";

\$VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};

# end
EOF
}

# For lua output
luaOutput() {
	case "${VCS_WC_MODIFIED}" in
		0) VCS_WC_MODIFIED="false" ;;
		1) VCS_WC_MODIFIED="true" ;;
	esac
	cat > "${TARGETFILE}" << EOF
-- Generated by autorevision - do not hand-hack!

VCS_TYPE = "${VCS_TYPE}"
VCS_BASENAME = "${VCS_BASENAME}"
VCS_NUM = ${VCS_NUM}
VCS_DATE = "${VCS_DATE}"
VCS_BRANCH = "${VCS_BRANCH}"
VCS_TAG = "${VCS_TAG}"
VCS_TICK = ${VCS_TICK}

VCS_FULL_HASH = "${VCS_FULL_HASH}"
VCS_SHORT_HASH = "${VCS_SHORT_HASH}"

VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}

-- end
EOF
}

# For php output
phpOutput() {
	case "${VCS_WC_MODIFIED}" in
		0) VCS_WC_MODIFIED="false" ;;
		1) VCS_WC_MODIFIED="true" ;;
	esac
	cat > "${TARGETFILE}" << EOF
<?php
# Generated by autorevision - do not hand-hack!

$GLOBALS["VCS_TYPE"] = "${VCS_TYPE}";
$GLOBALS["VCS_BASENAME"] = "${VCS_BASENAME}";
$GLOBALS["VCS_NUM"] = ${VCS_NUM};
$GLOBALS["VCS_DATE"] = "${VCS_DATE}";
$GLOBALS["VCS_BRANCH"] = "${VCS_BRANCH}";
$GLOBALS["VCS_TAG"] = "${VCS_TAG}";
$GLOBALS["VCS_TICK"] = ${VCS_TICK};

$GLOBALS["VCS_FULL_HASH"] = "${VCS_FULL_HASH}";
$GLOBALS["VCS_SHORT_HASH"] = "${VCS_SHORT_HASH}";

$GLOBALS["VCS_WC_MODIFIED"] = ${VCS_WC_MODIFIED};

# end
?>
EOF
}

# For ini output
iniOutput() {
	case "${VCS_WC_MODIFIED}" in
		0) VCS_WC_MODIFIED="false" ;;
		1) VCS_WC_MODIFIED="true" ;;
	esac
	cat > "${TARGETFILE}" << EOF
; Generated by autorevision - do not hand-hack!
[VCS]
VCS_TYPE = "${VCS_TYPE}"
VCS_BASENAME = "${VCS_BASENAME}"
VCS_NUM = ${VCS_NUM}
VCS_DATE = "${VCS_DATE}"
VCS_BRANCH = "${VCS_BRANCH}"
VCS_TAG = "${VCS_TAG}"
VCS_TICK = ${VCS_TICK}
VCS_FULL_HASH = "${VCS_FULL_HASH}"
VCS_SHORT_HASH = "${VCS_SHORT_HASH}"
VCS_WC_MODIFIED = ${VCS_WC_MODIFIED}
; end
EOF
}

# For javascript output
jsOutput() {
	case "${VCS_WC_MODIFIED}" in
		1) VCS_WC_MODIFIED="true" ;;
		0) VCS_WC_MODIFIED="false" ;;
	esac
	cat > "${TARGETFILE}" << EOF
/** Generated by autorevision - do not hand-hack! */

var autorevision = {
	VCS_TYPE: "${VCS_TYPE}",
	VCS_BASENAME: "${VCS_BASENAME}",
	VCS_NUM: ${VCS_NUM},
	VCS_DATE: "${VCS_DATE}",
	VCS_BRANCH: "${VCS_BRANCH}",
	VCS_TAG: "${VCS_TAG}",
	VCS_TICK: ${VCS_TICK},

	VCS_FULL_HASH: "${VCS_FULL_HASH}",
	VCS_SHORT_HASH: "${VCS_SHORT_HASH}",

	VCS_WC_MODIFIED: ${VCS_WC_MODIFIED}
};

/** Node.js compatibility */
if (typeof module !== 'undefined') {
	module.exports = autorevision;
}

/** end */
EOF
}

# For Java output
javaOutput() {
	case "${VCS_WC_MODIFIED}" in
		1) VCS_WC_MODIFIED="true" ;;
		0) VCS_WC_MODIFIED="false" ;;
	esac
	cat > "${TARGETFILE}" << EOF
/* Generated by autorevision - do not hand-hack! */

import java.util.Date;

public class autorevision {
    public static final String VCS_TYPE = "${VCS_TYPE}";
    public static final String VCS_BASENAME = "${VCS_BASENAME}";
    public static final long VCS_NUM = ${VCS_NUM};
    public static final Date VCS_DATE = new Date($(date -d ${VCS_DATE} +%s));
    public static final String VCS_BRANCH = "${VCS_BRANCH}";
    public static final String VCS_TAG = "${VCS_TAG}";
    public static final long VCS_TICK = ${VCS_TICK};

    public static final String VCS_FULL_HASH = "${VCS_FULL_HASH}";
    public static final String VCS_SHORT_HASH = "${VCS_SHORT_HASH}";

    public static final boolean VCS_WC_MODIFIED = ${VCS_WC_MODIFIED};
}
EOF
}

# For Java properties output
javapropOutput() {
	case "${VCS_WC_MODIFIED}" in
		1) VCS_WC_MODIFIED="true" ;;
		0) VCS_WC_MODIFIED="false" ;;
	esac
	cat > "${TARGETFILE}" << EOF
# Generated by autorevision - do not hand-hack!

VCS_TYPE=${VCS_TYPE}
VCS_BASENAME=${VCS_BASENAME}
VCS_NUM=${VCS_NUM}
VCS_DATE=${VCS_DATE}
VCS_BRANCH=${VCS_BRANCH}
VCS_TAG=${VCS_TAG}
VCS_TICK=${VCS_TICK}

VCS_FULL_HASH=${VCS_FULL_HASH}
VCS_SHORT_HASH=${VCS_SHORT_HASH}

VCS_WC_MODIFIED=${VCS_WC_MODIFIED}
EOF
}

# For m4 output
m4Output() {
	cat > "${TARGETFILE}" << EOF
define(\`VCS_TYPE', \`${VCS_TYPE}')dnl
define(\`VCS_BASENAME', \`${VCS_BASENAME}')dnl
define(\`VCS_NUM', \`${VCS_NUM}')dnl
define(\`VCS_DATE', \`${VCS_DATE}')dnl
define(\`VCS_BRANCH', \`${VCS_BRANCH}')dnl
define(\`VCS_TAG', \`${VCS_TAG}')dnl
define(\`VCS_TICK', \`${VCS_TICK}')dnl
define(\`VCS_FULLHASH', \`${VCS_FULL_HASH}')dnl
define(\`VCS_SHIRTHASH', \`${VCS_SHORT_HASH}')dnl
define(\`VCS_WC_MODIFIED', \`${VCS_WC_MODIFIED}')dnl
EOF
}

# For (La)TeX output
texOutput() {
	case "${VCS_WC_MODIFIED}" in
		0) VCS_WC_MODIFIED="false" ;;
		1) VCS_WC_MODIFIED="true" ;;
	esac
	cat > "${TARGETFILE}" << EOF
% Generated by autorevision - do not hand-hack!
\def \vcsType {${VCS_TYPE}}
\def \vcsBasename {${VCS_BASENAME}}
\def \vcsNum {${VCS_NUM}}
\def \vcsDate {${VCS_DATE}}
\def \vcsBranch {${VCS_BRANCH}}
\def \vcsTag {${VCS_TAG}}
\def \vcsTick {${VCS_TICK}}
\def \vcsFullHash {${VCS_FULL_HASH}}
\def \vcsShortHash {${VCS_SHORT_HASH}}
\def \vcsWCModified {${VCS_WC_MODIFIED}}
\endinput
EOF
}



# Detect and collect repo data.
if [ -f "${CACHEFILE}" ] && [ "${CACHEFORCE}" = "1" ]; then
	# When requested only read from the cache to populate our symbols.
	source "${CACHEFILE}"
elif [ ! -z "$(git rev-parse HEAD 2>/dev/null)" ]; then
	gitRepo
elif [ ! -z "$(hg root 2>/dev/null)" ]; then
	hgRepo
elif [ ! -z "$(bzr root 2>/dev/null)" ]; then
	bzrRepo
elif [ ! -z "$(svn info 2>/dev/null)" ]; then
	svnRepo
elif [ -f "${CACHEFILE}" ]; then
	# We are not in a repo; try to use a previously generated cache to populate our symbols.
	source "${CACHEFILE}"
else
	echo "error: No repo or cache detected." 1>&2
	exit 1
fi


# -s output is handled here.
if [ ! -z "${VAROUT}" ]; then
	if [ "${VAROUT}" = "VCS_TYPE" ]; then
		echo "${VCS_TYPE}"
	elif [ "${VAROUT}" = "VCS_BASENAME" ]; then
		echo "${VCS_BASENAME}"
	elif [ "${VAROUT}" = "VCS_NUM" ]; then
		echo "${VCS_NUM}"
	elif [ "${VAROUT}" = "VCS_DATE" ]; then
		echo "${VCS_DATE}"
	elif [ "${VAROUT}" = "VCS_BRANCH" ]; then
		echo "${VCS_BRANCH}"
	elif [ "${VAROUT}" = "VCS_TAG" ]; then
		echo "${VCS_TAG}"
	elif [ "${VAROUT}" = "VCS_TICK" ]; then
		echo "${VCS_TICK}"
	elif [ "${VAROUT}" = "VCS_FULL_HASH" ]; then
		echo "${VCS_FULL_HASH}"
	elif [ "${VAROUT}" = "VCS_SHORT_HASH" ]; then
		echo "${VCS_SHORT_HASH}"
	elif [ "${VAROUT}" = "VCS_WC_MODIFIED" ]; then
		echo "${VCS_WC_MODIFIED}"
	fi
fi


# Detect requested output type and use it.
if [ ! -z "${AFILETYPE}" ]; then
	if [ "${AFILETYPE}" = "h" ]; then
		hOutput
	elif [ "${AFILETYPE}" = "xcode" ]; then
		xcodeOutput
	elif [ "${AFILETYPE}" = "sh" ]; then
		shOutput
	elif [ "${AFILETYPE}" = "py" ] || [ "${AFILETYPE}" = "python" ]; then
		pyOutput
	elif [ "${AFILETYPE}" = "pl" ] || [ "${AFILETYPE}" = "perl" ]; then
		plOutput
	elif [ "${AFILETYPE}" = "lua" ]; then
		luaOutput
	elif [ "${AFILETYPE}" = "php" ]; then
		phpOutput
	elif [ "${AFILETYPE}" = "ini" ]; then
		iniOutput
	elif [ "${AFILETYPE}" = "js" ]; then
		jsOutput
	elif [ "${AFILETYPE}" = "java" ]; then
		javaOutput
	elif [ "${AFILETYPE}" = "javaprop" ]; then
		javapropOutput
	elif [ "${AFILETYPE}" = "tex" ]; then
		texOutput
	elif [ "${AFILETYPE}" = "m4" ]; then
		m4Output
	else
		echo "error: Not a valid output type." 1>&2
		exit 1
	fi
fi


# If requested, make a cache file.
if [ ! -z "${CACHEFILE}" ] && [ ! "${CACHEFORCE}" = "1" ]; then
	TARGETFILE="${CACHEFILE}"
	shOutput
fi
