#!/bin/bash
# Copyright 1999-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/x11-base/opengl-update/files/opengl-update-2.2.1,v 1.2 2005/04/27 21:45:29 eradicator Exp $
# Author:  Martin Schlemmer <azarah@gentoo.org>
# Further modifications by Donnie Berkholz <spyderous@gentoo.org>
# Further modifications based off submissions to bug #54984 <cyfred@gentoo.org>
# Further modifications by Jeremy Huddleston <eradicator@gentoo.org>

. /etc/init.d/functions.sh

hasq() {
	local x

	local me=${1}
	shift
        
	for x in "${@}"; do
		if [[ "${x}" == "${me}" ]]; then
			return 0
		fi
	done
	return 1
}

check_user() {
	if [[ $(id -u) -ne 0 ]]; then
		eerror "${0}: Must be run as root."
		exit 1
	fi
}

check_version() {
	if ! portageq has_version / '>=x11-base/xorg-x11-6.8.0-r4'; then
		eerror "This version requires >=x11-base/xorg-x11-6.8.0-r4"
		exit 1
	fi
}

get_current_implem() {
	local implem
	if [[ -f ${ENV_D} ]]; then
		source ${ENV_D}
		if [[ -n "${OPENGL_PROFILE}" ]]; then
			implem="${OPENGL_PROFILE}"
		elif [[ -n "${LDPATH}" ]]; then
			implem="${LDPATH%%:*}"
			implem="${implem##*opengl/}"
			implem="${implem%/lib*}"
		fi
		unset LDPATH
		unset OPENGL_PROFILE
	fi

	echo ${implem}
}

get_implementations() {
	local implems
	for dir in ${PREFIX}/lib{,32,64}/opengl/*; do 
		if [[ -d "${dir}" && ${dir##*/} != "global" ]] && ! hasq ${dir##*/} ${implems}; then
			implems=${implems:+${implems} }${dir##*/}
		fi
	done
	echo ${implems}
}

print_version() {
	echo "opengl-update ${VERSION}"
}

print_usage() {
	# Get grammar right in message
	local IS_ARE IMPLEM_PLURAL
	if [[ $(echo ${AVAIL_IMPLEMS} | wc -w) -eq 1 ]]; then
		IS_ARE="is"
		IMPLEM_PLURAL=""
	else
		IS_ARE="are"
		IMPLEM_PLURAL="s"
	fi

	print_version

	cat << FOO
Usage: ${0##*/} [<options>] <GL implementation>
       Set the opengl implementation.
       Valid options:
       --use-old:          If an implementation is already set, use that one.
       --prefix=<val>:     Set the source prefix (default: /usr)
       --dst-prefix=<val>: Set the destination prefix (default: /usr)
       --impl-headers:     Use headers provided by this implementation to
                           override golbal ones provided by opengl-update.

Usage: ${0##*/} --get-implementation
       Print the current implementaion

Notes:
       --impl-headers was default in <opengl-update-2.2.

       This utility switches between OpenGL implementations.  There ${IS_ARE}
       $(echo ${AVAIL_IMPLEMS} | wc -w) available implementation${IMPLEM_PLURAL}: ${AVAIL_IMPLEMS}

Examples:
       ${0##*/} xorg-x11
       This will setup things to use libGL.so from X.org.

       ${0##*/} nvidia
       This will setup things to use libGL.so from the nVidia drivers.

FOO
	exit 1
}

parse_options() {
	local opt
	while [[ ${#} -gt 0 ]]; do
		opt=${1}
		shift
		case ${opt} in
			--use-old)
				if [[ -n "${ACTION}" ]]; then
					ACTION="error"
					eerror "Invalid usage."
				else
					if [[ -n "${CURRENT_GL_IMPLEM}" ]] && hasq ${CURRENT_GL_IMPLEM} ${AVAIL_IMPLEMS}; then
						ACTION="old-implementation"
					fi
				fi				
			;;
			--get-implementation)
				if [[ -n "${ACTION}" ]]; then
					ACTION="error"
					eerror "Invalid usage."
				else
					ACTION="get-implementation"
				fi				
			;;
			--prefix=*)
				PREFIX=${opt#*=}
				AVAIL_IMPLEMS=$(get_implementations)
			;;
			--dst-prefix=*)
				DST_PREFIX=${opt#*=}
			;;
			--impl-headers)
				USE_PROFILE_HEADERS="yes"
			;;
			--help|-h|-?)
				ACION="usage"
			;;
			--version)
				ACTION="version"
			;;
			*)
				if hasq ${opt} ${AVAIL_IMPLEMS}; then
					if [[ "${ACTION}" != "old-implementation" ]]; then
						if [[ -n "${ACTION}" ]]; then
							ACTION="error"
							eerror "Invalid usage."
						else
							ACTION="set-implementation"
							NEW_GL_IMPLEM="${opt}"
						fi
					fi				
				else
					eerror "Unrecognized option: ${opt}"
					ACTION="error"
				fi
			;;
		esac
	done
}

set-new-implementation() {
	local GL_IMPLEM=${1}
	local GL_LOCAL

	check_version
	check_user

	# Set a sane umask... bug #83115
	umask 022

	if ! hasq ${GL_IMPLEM} ${AVAIL_IMPLEMS}; then
		eerror "Invalid profile selected."
		exit 1
	fi

	ebegin "Switching to ${GL_IMPLEM} OpenGL interface"
		rm -f ${ENV_D} &> /dev/null

		LIBDIRS="lib32 lib lib64"
		for LIBDIR in ${LIBDIRS}; do
			# Special case handling of lib32 because it can be a symlink to
			# emul libs
			if [[ "${LIBDIR}" = "lib32" ]]; then
				[[ -d "${PREFIX}/${LIBDIR}/opengl" ]] || continue
			else
				[[ -d "${PREFIX}/${LIBDIR}/opengl" && ! -h "${PREFIX}/${LIBDIR}" ]] || continue
			fi

			# Fallback on xorg-x11 if we don't have this implementation for this LIBDIR.
			if [[ ! -d ${PREFIX}/${LIBDIR}/opengl/"${GL_IMPLEM}" ]]; then
				GL_LOCAL="xorg-x11"
			else
				GL_LOCAL="${GL_IMPLEM}"
			fi
		
			mkdir -p ${DST_PREFIX}/${LIBDIR}
			pushd ${DST_PREFIX}/${LIBDIR} &> /dev/null
				# First remove old symlinks
				for file in libGL{,core}.{a,so,la} ; do
					[[ -h ${file} ]] && rm -f ${file}
				done

				# Note that we don't do .so*, just .so on purpose.  The
				# loader knows to look in the profile dir, and the
				# linked just needs the .so
				for file in ${PREFIX}/${LIBDIR}/opengl/${GL_LOCAL}/lib/libGL{,core}.{so,a,la}; do
					[[ -f "${file}" ]] || continue
					[[ -f "${file##*/}" ]] && rm -f ${file##*/}

					# Fix libtool archives (#48297)
					if [[ "${file%.la}" != "${file}" ]]; then
						sed "s:${PREFIX}/[^/]*/opengl/[^/]*/lib:${DST_PREFIX}/${LIBDIR}:g" ${file} > ${file##*/}
					else
						ln -s ${file}
					fi
				done
			popd &> /dev/null

			if [[ -e "${PREFIX}/${LIBDIR}/${LIBDIR}/opengl/${GL_LOCAL}/lib/tls" ]]; then
				mkdir -p ${DST_PREFIX}/${LIBDIR}/tls
				pushd ${DST_PREFIX}/${LIBDIR}/tls &> /dev/null
					# First remove old symlinks
					for file in libGL{,core}.{a,so,la} ; do
						[[ -h ${file} ]] && rm -f ${file}
					done

					for file in ${PREFIX}/${LIBDIR}/opengl/${GL_LOCAL}/lib/tls/libGL{,core}.{so,a,la}; do
						[[ -f "${file}" ]] || continue
						[[ -f "${file##*/}" ]] && rm -f ${file##*/}

						# Fix libtool archives (#48297)
						if [ "${file%.la}" != "${file}" ]; then
							sed "s:${PREFIX}/[^/]*/opengl/[^/]*/lib:${DST_PREFIX}/${LIBDIR}:g" ${file} > ${file##*/}
						else
							ln -s ${file}
						fi
					done
				popd &> /dev/null
			fi

			if [[ -e "${PREFIX}/${LIBDIR}/opengl/${GL_LOCAL}/extensions" ]]; then
				mkdir -p ${DST_PREFIX}/${LIBDIR}/modules/extensions
				pushd ${DST_PREFIX}/${LIBDIR}/modules/extensions &> /dev/null
					# First remove old symlinks
					for file in libglx.so libglx.a; do
						[[ -h ${file} ]] && rm -f ${file}
					done

					for file in ${PREFIX}/${LIBDIR}/opengl/${GL_LOCAL}/extensions/*.{so,a,la}; do
						[[ -f "${file}" ]] || continue
						[[ -f "${file##*/}" ]] && rm -f ${file##*/}

						# Fix libtool archives (#48297)
						if [[ "${file%.la}" != "${file}" ]]; then
							sed "s:${PREFIX}/[^/]*/opengl/[^/]*/lib:${DST_PREFIX}/${LIBDIR}:g" ${file} > ${file##*/}
						else
							ln -s ${file}
						fi
					done
				popd &> /dev/null
			fi

			# Setup the includes
			mkdir -p ${DST_PREFIX}/include/GL
			pushd ${DST_PREFIX}/include/GL &> /dev/null
				for file in gl.h glx.h glxtokens.h glext.h glxext.h glxmd.h glxproto.h; do
					# IMPORTANT
					# It is preferable currently to use the standard glext.h file
					# however if an OpenGL provider must use a self produced glext.h
					# then it should be installed to ${GL_IMPLEM}/include and the user
					# can add the --impl-headers option to select it.

					if [[ ${USE_PROFILE_HEADERS} == "yes" ]] ; then
						# Check the profile first.
						if [[ -e ${PREFIX}/${LIBDIR}/opengl/${GL_IMPLEM}/include/${file} ]]; then
							[[ -f "${file}" || ( -L "${file}" && ! -e "${file}" ) ]] && rm -f ${file}
							ln -s ${PREFIX}/${LIBDIR}/opengl/${GL_IMPLEM}/include/${file}
						fi
					fi

					if [[ -e ${PREFIX}/${LIBDIR}/opengl/global/include/${file} ]]; then
						[[ -f "${file}" || ( -L "${file}" && ! -e "${file}" ) ]] && rm -f ${file}
						ln -s ${PREFIX}/${LIBDIR}/opengl/global/include/${file}
					elif [[ -e ${PREFIX}/${LIBDIR}/opengl/${GL_IMPLEM}/include/${file} ]]; then
						[[ -f "${file}" || ( -L "${file}" && ! -e "${file}" ) ]] && rm -f ${file}
						ln -s ${PREFIX}/${LIBDIR}/opengl/${GL_IMPLEM}/include/${file}
					elif [[ -e ${PREFIX}/${LIBDIR}/opengl/xorg-x11/include/${file} ]]; then
						[[ -f "${file}" || ( -L "${file}" && ! -e "${file}" ) ]] && rm -f ${file}
						ln -s ${PREFIX}/${LIBDIR}/opengl/xorg-x11/include/${file}
					fi
				done
			popd &> /dev/null

			# Setup the $LDPATH
			ldpath="${ldpath:+${ldpath}:}${PREFIX}/${LIBDIR}/opengl/${GL_LOCAL}/lib"

		done

		echo "LDPATH=\"${ldpath}\"" > ${ENV_D}
		echo "OPENGL_PROFILE=\"${GL_IMPLEM}\"" >> ${ENV_D}

		env-update

	eend 0
}

## START PROGRAM ##

ENV_D="/etc/env.d/03opengl"
NEW_GL_IMPLEM=""
ACTION=""
PREFIX="/usr"
DST_PREFIX="/usr"
AVAIL_IMPLEMS=$(get_implementations)
CURRENT_GL_IMPLEM=$(get_current_implem)
USE_PROFILE_HEADERS="no"
VERSION="2.2.1"

parse_options ${@}

case ${ACTION} in
	get-implementation)
		if [[ -n "${CURRENT_GL_IMPLEM}" ]]; then
			echo ${CURRENT_GL_IMPLEM}
			exit 0
		else
			exit 2
		fi
	;;
	old-implementation)
		set-new-implementation ${CURRENT_GL_IMPLEM}
		exit $?
	;;
	set-implementation)
		if [[ -n "${NEW_GL_IMPLEM}" ]]; then
			set-new-implementation ${NEW_GL_IMPLEM}
			exit $?
		else
			print_usage
			exit 1
		fi
	;;
	version)
		print_version
		exit 0
	;;
	usage)
		print_usage
		exit 0
	;;
	error)
		print_usage
		exit 1
	;;
	*)
		print_usage
		exit 1
	;;
esac