#!/bin/bash
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/sys-devel/gcc-config/files/gcc-config-1.3.6,v 1.8 2004/10/11 14:36:40 vapier Exp $
# Author:  Martin Schlemmer <azarah@gentoo.org>

source /etc/init.d/functions.sh || {
	echo "$0: Could not source /etc/init.d/functions.sh!"
	exit 1
}

usage() {
cat << "USAGE_END"
Usage: gcc-config [options] [CC Profile]
Change the current cc/gcc profile, or give info about profiles.

Options:

  -O, --use-old              Use the old profile if one was selected.

  -P, --use-portage-chost    Only set to given profile if its CHOST is the 
                             same as that set for portage in /etc/make.conf
                             (or one of other portage config files...).

  -c, --get-current-profile  Print current used gcc profile.

  -l, --list-profiles        Print a list of available profiles.

  -E, --print-environ        Print environment that can be used to setup the
                             current gcc profile, or a specified one.

  -B, --get-bin-path         Print path where binaries of the given/current
                             profile are located.

  -L, --get-lib-path         Print path where libraries of the given/current
                             profile are located.

  -X, --get-stdcxx-incdir    Print path where g++ include files of the
                             given/current profile are located.

Profile names are of the form:  <CHOST>-<gcc version>
For example:                    i686-pc-linux-gnu-3.2.1
USAGE_END

	exit 1
}

if [ "$#" -lt 1 ]
then
	usage
fi

find_path() {
	[ -z "$1" ] && return 0

	local fullpath="$(type -P $1)"
	
	if [ -x "${fullpath}" ]
	then
		echo "${fullpath}"
		return 0
	fi

	for x in /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin
	do
		if [ -x "${x}/$1" -a -r "${x}/$1" ]
		then
			echo "${x}/$1"
			return 0
		fi
	done

	return 0
}

cmd_setup() {

	# Sourcing /etc/env.d/gcc/${CC_COMP} is going to mess up
	# PATH among things...
	CP="$(find_path cp)"
	RM="$(find_path rm)"
	MV="$(find_path mv)"
	LN="$(find_path ln)"
	CAT="$(find_path cat)"
	AWK="$(find_path gawk)"
	GREP="$(find_path grep)"
	FIND="$(find_path find)"
	CHMOD="$(find_path chmod)"
	TOUCH="$(find_path touch)"
	ENV_UPDATE="$(find_path env-update)"
}

CC_COMP=

get_real_chost() {
	[ -n "${REAL_CHOST}" ] && return 0

	# Use absolute path until all protage versions have portageq in /usr/bin
	export REAL_CHOST="$(/usr/lib/portage/bin/portageq envvar CHOST)"

	if [ -z "${REAL_CHOST}" ]
	then
		eerror "$0:  Could not get portage CHOST!"
		return 1
	fi
}

switch_profile() {
	local MY_LDPATH=
	local GCC_PROFILES=
	local OLD_CC_COMP=
	local GCC_BIN_PATH=

	if [ -r /etc/env.d/gcc/config ]
	then
		source /etc/env.d/gcc/config

		if [ -n "${CURRENT}" ]
		then
			OLD_CC_COMP="${CURRENT}"
		fi
	fi

	if [ "$(id -u)" -ne 0 ]
	then
		eerror "$0: Must be root."
		exit 1
	fi

	ebegin "Switching to ${CC_COMP} compiler"

	# Sourcing /etc/env.d/gcc/${CC_COMP} is going to mess up
	# PATH among things...
	cmd_setup

	# Order our profiles to have the default first...
	# We do this so that we can have them ordered with default
	# first in /etc/ld.so.conf, as the logical is that all
	# compilers for default CHOST will be used to compile stuff,
	# and thus we want all their lib paths in /etc/ld.so.conf ...
	get_real_chost
	GCC_PROFILES="$(${FIND} /etc/env.d/gcc/ -name "${REAL_CHOST}-*")"
	GCC_PROFILES="${GCC_PROFILES/\/etc\/env.d\/gcc\/${CC_COMP}}"
	GCC_PROFILES="/etc/env.d/gcc/${CC_COMP} ${GCC_PROFILES}"

	# Extract all LDPATH's for our CHOST
	for x in ${GCC_PROFILES}
	do
		if [ -f "${x}" ]
		then
			source "${x}"

			# Handle LDPATH's that have multiple directories
			local old_IFS="${IFS}"
			export IFS=":"
			local sub_ldpath=
			for sub_ldpath in ${LDPATH}
			do
				if [ -z "${MY_LDPATH}" ]
				then
					if [ -d "${sub_ldpath}" ]
					then
						MY_LDPATH="${sub_ldpath}"
					fi
				else
					if [ -d "${sub_ldpath}" ]
					then
						MY_LDPATH="${MY_LDPATH}:${sub_ldpath}"
					fi
				fi
			done
			export IFS="${old_IFS}"
		fi
	done

	# Setup things properly again for this profile
	source "/etc/env.d/gcc/${CC_COMP}"

	# Setup /etc/env.d/05gcc
	${AWK} '!/^STDCXX_INCDIR=|^LDPATH=/ {print $0}' \
		"/etc/env.d/gcc/${CC_COMP}" > /etc/env.d/05gcc

	# Add our custom LDPATH
	echo "LDPATH=\"${MY_LDPATH}\"" >> /etc/env.d/05gcc

	# Make sure we do not recreate /lib/cpp and /usr/bin/cc ...
#	echo "DISABLE_GEN_GCC_WRAPPERS=\"yes\"" >> /etc/env.d/05gcc
	
	echo "CURRENT=${CC_COMP}" > /etc/env.d/gcc/config

	# Save PATH
	GCC_BIN_PATH="${PATH}"
	# Fix environment
	source /etc/profile

	# These might not be installed, and we want to update the mtime
	# for ccache and distcc anyhow ...
	${RM} -f /lib/cpp
	${CP} -f /usr/lib/gcc-config/wrapper /lib/cpp
	for x in gcc cpp cc c++ g++ f77 gcj \
	         ${REAL_CHOST}-gcc ${REAL_CHOST}-c++ ${REAL_CHOST}-g++ \
	         ${REAL_CHOST}-f77 ${REAL_CHOST}-gcj
	do
		# Make sure we have no stale wrappers
		${RM} -f "/usr/bin/${x}"
		
		if [ -x "${GCC_BIN_PATH}/${x}" -o \
		     "${x}" = "c++" -o "${x}" = "${REAL_CHOST}-c++" -o \
		     "${x}" = "cpp" -o "${x}" = "cc" ]
		then
			# Only install a wrapper if the binary exists ...
			${CP} -f /usr/lib/gcc-config/wrapper "/usr/bin/${x}"

			if [ "${OLD_CC_COMP}" != "${CC_COMP}" ]
			then
				${TOUCH} -m "/usr/bin/${x}"
			fi
		fi
	done


	${ENV_UPDATE} &> /dev/null

	eend 0

	if [ "${OLD_CC_COMP}" != "${CC_COMP}" ]
	then
		echo
		ewarn "If you intend to use the gcc from the new profile in an already"
		ewarn "running shell, please remember to do:"
		echo
		ewarn "  # source /etc/profile"
		echo
	fi

	return 0
}

get_current_profile() {
	if [ ! -f /etc/env.d/gcc/config ]
	then
		eerror "$0:  No gcc profile is active!"
		return 1
	fi

	source /etc/env.d/gcc/config

	if [ -z "${CURRENT}" ]
	then
		eerror "$0:  No gcc profile is active!"
		return 1
	fi

	echo "${CURRENT}"

	return 0
}

list_profiles() {
	local i=1

	if [ ! -f /etc/env.d/gcc/config ]
	then
		eerror "$0:  No gcc profile is active!"
		return 1
	fi

	get_current_profile > /dev/null

	for x in /etc/env.d/gcc/*
	do
		if [ -f "${x}" -a "${x}" != "/etc/env.d/gcc/config" ]
		then
			x="${x##*/}"
			[ "${x}" == "${CURRENT}" ] && x="${x} *"
			echo "[${i}] ${x}"
			i=$((i + 1))
		fi
	done
}

print_environ() {
	local OLDPATH="${PATH}"
	local ENV_CMD=
	local SET_ELEMENT=

	source "/etc/env.d/gcc/${CC_COMP}"

	case ${SHELL} in
		*/csh|*/tsch)
			ENV_CMD="setenv"
			SET_ELEMENT=" "
			;;
		*)
			ENV_CMD="export"
			SET_ELEMENT="="
			;;
	esac

	echo "${ENV_CMD} PATH${SET_ELEMENT}\"${PATH}:${OLDPATH}\""
#	if [ -z "${LD_LIBRARY_PATH}" ]
#	then
#		echo "${ENV_CMD} LD_LIBRARY_PATH${SET_ELEMENT}\"${LDPATH}\""
#	else
#		echo "${ENV_CMD} LD_LIBRARY_PATH${SET_ELEMENT}\"${LDPATH}:${LD_LIBRARY_PATH}\""
#	fi
	echo "${ENV_CMD} CC${SET_ELEMENT}\"${CC}\""
	echo "${ENV_CMD} CXX${SET_ELEMENT}\"${CXX}\""
}

get_bin_path() {
	if [ -e /etc/env.d/gcc/${CC_COMP} ] ; then
		source "/etc/env.d/gcc/${CC_COMP}"
		echo "${PATH}"
	else
		echo "no-config"
		echo "/etc/env.d/gcc/${CC_COMP} doesnt exist" 1>&2
	fi

	return 0
}

get_lib_path() {
	if [ -e /etc/env.d/gcc/${CC_COMP} ] ; then
		source "/etc/env.d/gcc/${CC_COMP}"
		echo "${LDPATH}"
	else
		echo "no-config"
		echo "/etc/env.d/gcc/${CC_COMP} doesnt exist" 1>&2
	fi

	return 0
}

get_stdcxx_incdir() {
	if [ -e /etc/env.d/gcc/${CC_COMP} ] ; then
		source "/etc/env.d/gcc/${CC_COMP}"
		echo "${LDPATH}/include/${STDCXX_INCDIR}"
	else
		echo "no-config"
		echo "/etc/env.d/gcc/${CC_COMP} doesnt exist" 1>&2
	fi

	return 0
}

NEED_ACTION="yes"
DOIT="switch_profile"
CHECK_CHOST="no"

for x in "$@"
do
	case "${x}" in
		# Only use specified compiler if one is not already selected.
		-O|--use-old)
			if get_current_profile &> /dev/null
			then
				CC_COMP="$(get_current_profile)"
			fi
			;;
		-P|--use-portage-chost)
			CHECK_CHOST="yes"
			;;
		-c|--get-current-profile)
			if [ "${NEED_ACTION}" = "yes" ]
			then
				NEED_ACTION="no"
				DOIT="get_current_profile"
			fi
			;;
		-l|--list-profiles)
			if [ "${NEED_ACTION}" = "yes" ]
			then
				NEED_ACTION="no"
				DOIT="list_profiles"
			fi
			;;
		-E|--print-environ)
			if [ "${NEED_ACTION}" = "yes" ]
			then
				NEED_ACTION="no"
				DOIT="print_environ"
			fi
			;;
		-B|--get-bin-path)
			if [ "${NEED_ACTION}" = "yes" ]
			then
				NEED_ACTION="no"
				DOIT="get_bin_path"
			fi
			;;
		-L|--get-lib-path)
			if [ "${NEED_ACTION}" = "yes" ]
			then
				NEED_ACTION="no"
				DOIT="get_lib_path"
			fi
			;;
		-X|--get-stdcxx-incdir)
			if [ "${NEED_ACTION}" = "yes" ]
			then
				NEED_ACTION="no"
				DOIT="get_stdcxx_incdir"
			fi
			;;
		-h|--help)
			usage
			exit 0
			;;
		-v|--version)
			echo "gcc-config-1.3.6"
			exit 0
			;;
		-*)
			eerror "$0: Invalid switch!  Run $0 without parameters for help."
			exit 1
			;;
		*)
			if [ -z "${CC_COMP}" ]
			then
				if [ -n "`echo ${x} | gawk '/^[[:digit:]]*$/ { print }'`" ]
				then
					i=1
					for y in /etc/env.d/gcc/*
					do
						[ "${y}" = "/etc/env.d/gcc/config" ] && continue
						
						if [ -f "${y}" -a "${x}" -eq "${i}" ]
						then
							CC_COMP="${y##*/}"
							break
						else
							i=$((i + 1))
						fi
					done
				else
					CC_COMP="${x}"
				fi
			fi
			;;
	esac
done

if [ "${DOIT}" = "switch_profile" -a -z "${CC_COMP}" ]
then
	usage
fi

if [ -z "${CC_COMP}" ]
then
	if get_current_profile &> /dev/null
	then
		CC_COMP="$(get_current_profile)"
	else
		eerror "$0: No default profile setup!"
		exit 1
	fi
fi

CC_COMP_NO_SPECS=$(echo ${CC_COMP} | awk -F- '{ print $1"-"$2"-"$3"-"$4"-"$5 }')

if [ ! -d "/usr/lib/gcc-lib/${CC_COMP_NO_SPECS%-*}/${CC_COMP_NO_SPECS##*-}" -o \
     ! -f "/etc/env.d/gcc/${CC_COMP}" ]
then
	eerror "$0: Profile does not exist or invalid setting for /etc/env.d/gcc/${CC_COMP}"
	#exit 1
fi

if [ "${CHECK_CHOST}" = "yes" ]
then
	# Chosen CHOST are not the same as the real CHOST according to
	# make.conf, and --use-portage-chost option was given, so do nothing
	get_real_chost
	[ "${CC_COMP%-*}" != "${REAL_CHOST}" ] && exit 0
fi

eval ${DOIT}


# vim:ts=4
