#! /bin/bash

CCROOT="$(dirname "$(which "$0")")"
COMPILER_C='gcc'
COMPILER_CXX='g++'

idx=0
for platform in "${CCROOT}"/*; do
	if [ ! -d "${platform}" ]; then
		continue
	fi

        platform="$(basename "${platform}")"

	if [ ! -d "${CCROOT}/${platform}/${platform}" ]; then
		continue
	fi

	if [ ! -x "${CCROOT}/${platform}/bin/${platform}-gcc" -a ! -x "${CCROOT}/${platform}/bin/${platform}-cc" ]; then
		continue
	fi

        platforms[${idx}]="${platform}"
        idx=$[${idx} + 1]
done

if [ -z "$1" ]; then
	echo "Available platforms:"

	for platform in "${platforms[@]}"; do
		echo "  ${platform}"
	done

	exit 0
fi

CCNAME="$1"
CCROOT="$(cd "${CCROOT}" && pwd)"
CCDIR="${CCROOT}/${CCNAME}"

shift

function writeCLangWrapper() {
	local ccname ccdir
	local clang_wrapper clangxx_wrapper
	local clang_triplet clang_triplet_arch clang_triplet_vendor clang_triplet_sys clang_triplet_abi
	local assemble_clang_triplet
	local clang_args
	local tmpfile
	local gcc
	local libdir

	ccname="$1"
	ccdir="$2"
	gcc="${ccdir}/bin/${ccname}-gcc"

	if [ -z "${ccname}" -o -z "${ccdir}" ]; then
		echo "Usage: writeCLangWrapper <ccname> <ccdir>" >&2
		return 1
	fi

	clang_wrapper="${ccdir}/bin/${ccname}-clang"
	clangxx_wrapper="${ccdir}/bin/${ccname}-clang++"

	if [ -e "${clang_wrapper}" -a -e "${clangxx_wrapper}" ]; then
		return 0
	fi

	clang_args=()
	clang_triplet="${ccname}"
	clang_triplet_arch='unknown'
	clang_triplet_vendor='unknown'
	clang_triplet_sys='unknown'
	clang_triplet_abi='unknown'
	assemble_clang_triplet='true'

	case "${ccname}" in
		x86_64-*|sparc-*|arm-*|powerpc-*|aarch64-*|mips-*|mipsel-*|armv[0-9]*-*)
			clang_triplet_arch="$(echo "${ccname}" | sed 's@-.*$@@')"
			;;
		i?86-*)
			clang_triplet_arch='i386'
			;;
		hppa64-*)
			clang_triplet_arch='hppa2.0'
			;;
		*)
			assemble_clang_triplet='false'
			;;
	esac

	case "${ccname}" in
		*-hardfloat-*)
			clang_args+=('-mfloat-abi=hard')
			;;
	esac

	case "${ccname}" in
		*-netbsd[0-9]*|*-freebsd[0-9]*|*-solaris[0-9].[0-9]*|*-aix[0-9]*.*|*-hpux[0-9]*|*-darwin[0-9]*)
			clang_triplet_sys="$(echo "${ccname}" | sed 's@^.*-@@;s@[0-9].*$@@')"
			;;
		*-linux-musl)
			clang_triplet_sys='linux'
			clang_triplet_abi='musl'
			;;
		*-linux-uclibc)
			clang_triplet_sys='linux'
			clang_triplet_abi='uclibc'
			;;
		*-linux-gnu)
			clang_triplet_sys='linux'
			clang_triplet_abi='gnu'
			;;
		*-linux-gnueabihf)
			clang_triplet_sys='linux'
			clang_triplet_abi='eabi'
			clang_args+=('-mfloat-abi=hard')
			;;
		*-linux-gnueabi)
			clang_triplet_sys='linux'
			clang_triplet_abi='eabi'
			;;
		*-linux-androideabi)
			clang_triplet_sys='linux'
			clang_triplet_abi='android'
			;;
		*-linux)
			clang_triplet_sys='linux'
			;;
		*)
			assemble_clang_triplet='false'
			;;
	esac

	if [ "${assemble_clang_triplet}" = 'true' ]; then
		clang_triplet="${clang_triplet_arch}-${clang_triplet_vendor}-${clang_triplet_sys}-${clang_triplet_abi}"
		clang_triplet="$(echo "${clang_triplet}" | sed 's@-unknown$@@')"
	fi

	while IFS='' read -d ':' -r libdir; do
		if [ -z "${libdir}" ]; then
			continue
		fi
		clang_args+=("-L${libdir}")
	done <<<"$("${gcc}" -print-search-dirs 2>/dev/null | grep '^libraries: ' | sed 's@^libraries: *@@;s@$@:@')"

	tmpfile="${clang_wrapper}.$(openssl rand 20 -hex)"

	echo '#! /usr/bin/env bash' > "${tmpfile}"
	echo '' >> "${tmpfile}"
	set | egrep '^(clang_triplet|clang_args|ccdir|ccname)=' >> "${tmpfile}"
	cat << \_EOF_ >> "${tmpfile}"
exec @TOOL@ -fuse-ld=lld --sysroot "${ccdir}/${ccname}" -target "${clang_triplet}" "${clang_args[@]}" "$@"
_EOF_

	sed 's/@TOOL@/clang/g' < "${tmpfile}" > "${tmpfile}.clang" || return 1
	sed 's/@TOOL@/clang++/g' < "${tmpfile}" > "${tmpfile}.clang++" || return 1
	rm -f "${tmpfile}"

	chmod +x "${tmpfile}.clang" "${tmpfile}.clang++"
	mv "${tmpfile}.clang" "${clang_wrapper}"
	mv "${tmpfile}.clang++" "${clangxx_wrapper}"

	return 0
}

# Canonicalize symbolic links
if [ -L "${CCDIR}" ]; then
	CCNAME="$(readlink "${CCDIR}" | sed 's@^.*/@@')"
fi

found='0'
for platform in "${platforms[@]}"; do
	if [ "${platform}" = "${CCNAME}" ]; then
		found='1'
		break
	fi
done

if [ "${found}" != '1' ]; then
	echo "Unknown platform: ${CCNAME}" >&2

	exit 1
fi

case "${CCNAME}" in
	x86_64-*|hppa64-*|arm64-*|aarch64-*)
		have_64bit='1'
		;;
	*)
		have_64bit='0'
		;;
esac

want_64bit="${have_64bit}"
CC_ADD=""
ADD_CLANG_PATH=''
for arg in "$@"; do
	case "${arg}" in
		64|-m64)
			want_64bit='1'
			;;
		32|-m32)
			want_64bit='0'
			;;
		-m*)
			# Disable any manual added flags
			want_64bit="${have_64bit}"
			CC_ADD="${CC_ADD} ${arg}"
			;;
		-clang)
			COMPILER_C='clang'
			COMPILER_CXX='clang++'
			ADD_CLANG_PATH="$(ls -1d "${CCROOT}"/llvm-*/ | sort | tail -n 1)bin:"
			writeCLangWrapper "${CCNAME}" "${CCDIR}"
			;;
	esac
done

if [ "${have_64bit}" != "${want_64bit}" ]; then
	if [ "${want_64bit}" = "1" ]; then
		CC_ADD="${CC_ADD} -m64"
	else
		CC_ADD="${CC_ADD} -m32"
	fi
fi

if [ -z "${CC_FOR_BUILD}" -a -z "${HOST_CC}" ]; then
	if [ -n "${CC}" ]; then
		CC_FOR_BUILD="${CC}"
	else
		tmpfile="${TMPDIR:-/tmp}/setup-cc-find-cc-$$${RANDOM}${RANDOM}${RANDOM}"
		rm -f "${tmpfile}.o" "${tmpfile}"
		echo 'int main(int argc, char **argv) { return(0); }' > "${tmpfile}"

		for try_cc in cc gcc c89 c99; do
			try_cc="$(which "${try_cc}" 2>/dev/null)"

			if [ ! -f "${try_cc}" ]; then
				continue
			fi

			rm -f "${tmpfile}"
			"${try_cc}" -o "${tmpfile}" "${tmpfile}" 2>/dev/null >/dev/null || continue
			"${tmpfile}" 2>/dev/null >/dev/null || continue

			CC_FOR_BUILD="${try_cc}"

			break
		done

		rm -f "${tmpfile}.o" "${tmpfile}"
	fi
elif [ -z "${CC_FOR_BUILD}" -a -n "${HOST_CC}" ]; then
	CC_FOR_BUILD="${HOST_CC}"
fi

echo "PATH='${ADD_CLANG_PATH}${PATH}:${CCROOT}/${CCNAME}/bin';"
echo "AR='${CCNAME}-ar';"
echo "AS='${CCNAME}-as';"
echo "CC='${CCNAME}-${COMPILER_C}${CC_ADD}';"
echo "CXX='${CCNAME}-${COMPILER_CXX}${CC_ADD}';"
echo "LD='${CCNAME}-ld';"
echo "NM='${CCNAME}-nm';"
echo "RANLIB='${CCNAME}-ranlib';"
echo "STRIP='${CCNAME}-strip';"
echo "PKG_CONFIG='${CCNAME}-pkg-config';"
echo "PKGCONFIG='${CCNAME}-pkg-config';"
echo "CC_FOR_BUILD='${CC_FOR_BUILD}';"
echo "HOST_CC='${CC_FOR_BUILD}';"
echo "PKG_CONFIG_DIR='';"
echo "PKG_CONFIG_LIBDIR='${CCROOT}/${CCNAME}/${CCNAME}/lib/pkgconfig';"
echo 'export PATH AR AS CC CXX LD NM RANLIB STRIP PKG_CONFIG PKGCONFIG CC_FOR_BUILD HOST_CC PKG_CONFIG_DIR PKG_CONFIG_LIBDIR;'
