#! /bin/bash

if [ ! -x "./platform" ]; then
	echo 'ERROR: Platform script not found: ./platform' >&2

	exit 1
fi

CLEANONLY=0
DISTCLEAN=0
if [ "$1" = "clean" ]; then
	shift
	CLEANONLY=1
fi
if [ "$1" = "distclean" ]; then
	shift
	CLEANONLY=1
	DISTCLEAN=1
fi
export CLEANONLY DISTCLEAN

CONFIGUREEXTRA="$@"
export CONFIGUREEXTRA

# Determine path to "tclConfig.sh"
rm -rf */out
if [ "${CLEANONLY}" = "1" ]; then
	rm -rf tcl/build tcl/inst-*
	rm -f platform.magic.*
fi
if [ "${DISTCLEAN}" = "1" ]; then
	rm -rf tcl
fi

if [ "${CLEANONLY}" = "0" ]; then
	PROJROOTDIR="$(pwd)"
	export PROJROOTDIR

	for TCLVERS in 8.5.15 8.4.20; do
		TCLSHORTVERS="$(echo "${TCLVERS}" | cut -f 1-2 -d '.')"
		TCLPRIVATE="$(pwd)/tcl/build/tcl${TCLVERS}"
		TCLINSTDIR="$(pwd)/tcl/inst-${TCLSHORTVERS}"
		export TCLVERS TCLPRIVATE TCLINSTDIR

		if [ -f "${TCLINSTDIR}/lib/tclConfig.sh" ]; then
			echo "Skipping build of Tcl ${TCLVERS} (already found)"

			continue
		fi

		mkdir tcl tcl/build >/dev/null 2>/dev/null

		# Clean this up so that other platforms don't use it
		rm -f "${PROJROOTDIR}/platform.magic.dir"

		if [ ! -f "tcl/src/tcl${TCLVERS}.tar.gz" ]; then
			mkdir tcl/src >/dev/null 2>/dev/null
			wget -o /dev/null -O "tcl/src/tcl${TCLVERS}.tar.gz" "http://prdownloads.sourceforge.net/tcl/tcl${TCLVERS}-src.tar.gz"
		fi

		echo "Building Tcl ${TCLVERS}"
		(
			mkdir tcl/build >/dev/null 2>/dev/null
			cd tcl/build || exit 1
			gzip -dc "../src/tcl${TCLVERS}.tar.gz" | tar -xf -

			# Source fix-ups
			## DDE and Reg can fail to compile, but we don't care
			echo '' > "${TCLPRIVATE}/win/tclWinDde.c"
			echo '' > "${TCLPRIVATE}/win/tclWinReg.c"

			## Long-standing bug in Tcl
			echo '#undef strtod' > "${TCLPRIVATE}/compat/strtod.c.new"
			cat "${TCLPRIVATE}/compat/strtod.c" >> "${TCLPRIVATE}/compat/strtod.c.new"
			cat "${TCLPRIVATE}/compat/strtod.c.new" > "${TCLPRIVATE}/compat/strtod.c"
			rm -f "${TCLPRIVATE}/compat/strtod.c.new"

			tcl_platform_dir='unix win macosx'

			case "${CC}" in
				*mingw*)
					# If the compiler looks like Mingw, use Windows
					tcl_platform_dir='win'
					;;
				*-*-*)
					# Default for cross-compiling is UNIX
					tcl_platform_dir='unix'
					;;
			esac

			for dir in ${tcl_platform_dir}; do
				cd "${TCLPRIVATE}/${dir}" || exit 1

				echo " Executing: ./configure --enable-threads ${CONFIGUREEXTRA} --prefix=\"${TCLINSTDIR}\""
				./configure --enable-threads ${CONFIGUREEXTRA} --prefix="${TCLINSTDIR}"

				echo " Executing: ${MAKE:-make}"
				${MAKE:-make} || (
					rm -f tclConfig.sh

					exit 1
				) || continue

				## Kludge to make Tcl install when cross-compiling.
				sed 's@^${TCL_EXE}@blah@' Makefile > Makefile.new
				sed 's@^$(TCLSH)@blah@' Makefile.new > Makefile
				rm -f Makefile.new

				echo " Executing: ${MAKE:-make} install"
				${MAKE:-make} install TCL_EXE="../../../../../../../../../../../../../../../../../$(which "${TCLSH_NATIVE:-tclsh}")" TCLSH="../../../../../../../../../../../../../../../../../$(which "${TCLSH_NATIVE:-tclsh}")" || break

				LD_LIBRARY_PATH=".:${LD_LIBRARY_PATH}"
				LD_RUN_PATH=".:${LD_RUN_PATH}"
				export LD_LIBRARY_PATH LD_RUN_PATH

				file tclsh tclsh*.exe 2>/dev/null | grep -iv 'No such file' > "${PROJROOTDIR}/platform.magic.file"
				if [ -f tclsh*.exe ]; then
					echo 'puts "$::tcl_platform(os)"' | ./tclsh*.exe > "${PROJROOTDIR}/platform.magic.os" 2>/dev/null
				else
					echo 'puts "$::tcl_platform(os)"' | ./tclsh > "${PROJROOTDIR}/platform.magic.os" 2>/dev/null
				fi
				echo "${dir}" > "${PROJROOTDIR}/platform.magic.platform"
				pwd > "${PROJROOTDIR}/platform.magic.dir"

				break
			done

			exit 0
		) > "tcl/build/build-${TCLVERS}.log" 2>&1 || (
			echo "Failed to build Tcl.  See \"./tcl/build/build-${TCLVERS}.log\"" >&2
			echo 'Aborting.' >&2

			exit 1
		) || exit 1

		(
			rm -f "${PROJROOTDIR}/platform.magic.env-${TCLSHORTVERS}"

			TCLBUILDDIR="$(cat "${PROJROOTDIR}/platform.magic.dir")"
			export TCLBUILDDIR

			if [ -z "${TCLBUILDDIR}" ]; then
				TCLBUILDDIR="/dev/null"
			fi

			if [ -d "${TCLINSTDIR}" -a -f "${TCLINSTDIR}/lib/tclConfig.sh" ]; then
				TCLCONFIGDIR="${TCLINSTDIR}/lib"
			elif [ -d "${TCLBUILDDIR}" -a -f "${TCLBUILDDIR}/tclConfig.sh" ]; then
				TCLCONFIGDIR="${TCLBUILDDIR}"
			else
				echo 'Unable to find appropriate tclConfig.sh, aborting' >&2

				exit 1
			fi

			ADDFLAGS=""
			if [ -n "${TCLPRIVATE}" ]; then
				ADDFLAGS="${ADDFLAGS} -I${TCLPRIVATE} -I${TCLPRIVATE}/generic"
			fi
			if [ -n "${TCLBUILDDIR}" ]; then
				ADDFLAGS="${ADDFLAGS} -I${TCLBUILDDIR}"
			fi
			CFLAGS="${ADDFLAGS} ${CFLAGS}"
			CPPFLAGS="${ADDFLAGS} ${CPPFLAGS}"

			unset TCLVERS
			unset ADDFLAGS
			export TCLBUILDDIR TCLCONFIGDIR TCLPRIVATE CFLAGS CPPFLAGS

			rm -f "${PROJROOTDIR}/platform.magic.env-${TCLSHORTVERS}"
			set > "${PROJROOTDIR}/platform.magic.env-${TCLSHORTVERS}"
			export >> "${PROJROOTDIR}/platform.magic.env-${TCLSHORTVERS}"
		)
	done

	rm -f "${PROJROOTDIR}/platform.magic.dir"
fi

# Determine platform
if [ -z "${FORCE_PLATFORM}" ]; then
	PLATFORM="$(echo 'package require platform; puts [platform::identify]' | ./tcl/inst-8.5/bin/tclsh8.5 2>/dev/null)"

	if [ -z "${PLATFORM}" ]; then
		PLATFORM="$(./platform)"
	fi
else
	PLATFORM="${FORCE_PLATFORM}"
fi
export PLATFORM

# Set platform specific configuration
case "${PLATFORM}" in
	solaris2*)
		LDFLAGS="${LDFLAGS} -static-libgcc"
		export LDFLAGS
		;;
esac

# Build all appropriate directories
faileddirs=""
if [ -z "${DIRS}" ]; then
	DIRS="`echo */`"
	PKGHASHCODE=''
else
	PKGHASHCODE="$((echo "${DIRS}" | tr ' ' "\n" | sort | tr "\n" ' '; echo ) | sed 's@[/ ]@@g' | openssl sha1 | sed 's@^.*= *@@')"
fi
for dir in ${DIRS}; do
	export dir

	if [ ! -f "${dir}/build.sh" ]; then
		continue
	fi

	if [ "${CLEANONLY}" = "0" ]; then
		echo "Building ${dir}"
	fi

	failed=0
	(
		cd "${dir}" || exit 1

		rm -rf "build" "out"
		rm -f failed-*.log
		if [ "${DISTCLEAN}" = "1" ]; then
			rm -rf "src"
		fi
		if [ "${CLEANONLY}" = "1" ]; then
			exit 0
		fi

		mkdir -p "out" >/dev/null 2>/dev/null

		./build.sh > "out/build-${PLATFORM}.log" 2>&1 || exit 1
	) || failed=1

	if [ "${failed}" = "1" ]; then
		cp "${dir}/out/build-${PLATFORM}.log" "${dir}/failed-${PLATFORM}-`hostname`.log"

		rm -rf "${dir}/out"
		faileddirs="${faileddirs} ${dir}"
		echo "Failed to build ${dir}"
	else
		if [ "${CLEANONLY}" != "1" ]; then
			outdir="$(ls -1d "${dir}/out"/*/"${PLATFORM}/" 2>/dev/null | head -1)"

			mv "${dir}/out/build-${PLATFORM}.log" "${outdir}/build.log" >/dev/null 2>/dev/null
		fi
	fi
done

# Cleanup is done at this point
if [ "${CLEANONLY}" = "1" ]; then
	exit 0
fi

# Let the user know what failed to build
if [ -n "${faileddirs}" ]; then
	echo "The following failed to build:${faileddirs}"
fi

# Create tarfile of built packages
DATECODE="$(date +%Y%m%d%H%M)"

if [ -z "${PKGHASHCODE}" ]; then
	OUTFILEBASE="tclpkgs-${PLATFORM}-${DATECODE}"
else
	OUTFILEBASE="tclpkgs-${PKGHASHCODE}-${PLATFORM}-${DATECODE}"
fi

rm -rf __tmp__
mkdir __tmp__
instdir="$(cd __tmp__ && pwd)"
for dir in */; do
	basename="$(dirname "${dir}")"
	pkginstdir="${instdir}/${dir}"

	(
		cd "${dir}/out" 2>/dev/null >/dev/null || exit 1

		mkdir "${pkginstdir}"

		cp -r * "${pkginstdir}/" >/dev/null 2>/dev/null
	)
done

(
	cd __tmp__ || exit 1

	tar -cf - *
) | bzip2 -9c > "${OUTFILEBASE}.tar.bz2"

rm -rf __tmp__

exit 0
