

# --8<--8<--8<--8<--
#
# Copyright (C) 2006 Smithsonian Astrophysical Observatory
#
# This file is part of mst_envs
#
# mst_envs is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# mst_envs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
#       Free Software Foundation, Inc.
#       51 Franklin Street, Fifth Floor
#       Boston, MA  02110-1301, USA
#
# -->8-->8-->8-->8--

# mst_envs/share/mst_envs.sh @VERSION@

#------------------------------------------------
# exit with error to STDERR

die() { echo 1>&2 "$@"; exit 1;  }

#------------------------------------------------
# return true if a variable is set

is_set() {

    # some version of bash are buggy and if a variable is declared
    # it is considered set. in that case, just check if
    # the variable is empty

    local test

    if [ "${test-_}" ] ; then

        # if the variable is not empty, it's set
        # if it is empty, then set to _ if not set, and check length

	[[ ${!1} || ! ${!1-_} ]]

    else

	[[ ${!1} ]]
    fi

}

# find the actual physical directory containing the executable
# not all systems support readlink -f
findparentdir() {

    local exe="$1"

    ( cd -P -- "$(dirname -- "$exe")"
      link="$(readlink -- "$(basename -- "$exe")")" \
          && cd -P -- "$(dirname "$link")"
      cd ..
      pwd -P
    )

}

dirname() {

    local path="$1"
    [[ path == -- ]] && path="$2"

   local dir="${1%${1##*/}}"
   test "${dir:=./}" != "/" && dir="${dir%?}"
   test "$dir" = '.' && dir="$PWD"
   echo "$dir"
}


# initialize MST variables if not specified; allow (somewhat)
# overriding of variables note that these ARE NOT EXPORTED.
set_mst_envs () {

    is_set @MST_ROOT_VAR@  || @MST_ROOT_VAR@="@MST_ROOT@"
    @MST_SIMUL_ROOT_VAR@="@MST_SIMUL_ROOT_VAL@"
    @MST_OTS_ROOT_VAR@="@MST_OTS_ROOT_VAL@"
    @MST_TEMPLATE_ROOT_VAR@="@MST_TEMPLATE_ROOT_VAL@"

    SYSARCH="@SYSARCH_VAL@"

}


#------------------------------------------------
# simple stack push.

# TODO: this is so old skool. use arrays and += operator. but
# make sure it runs on all of the platforms first!

declare -a stack

push () {

    stack[${#stack[*]}]="$1"

}

push_if () {

    test "$1" -eq 0 && return

    stack[${#stack[*]}]="$2"

}

#------------------------------------------------
# set and restore IFS

set_IFS() { oIFS="$IFS"; IFS="$1"; }
restore_IFS() { IFS="$oIFS"; }

#------------------------------------------------
# path manipulation

# join paths with a ':'
# usage: join-path *array variable name*
join-path () { local IFS=':'; var="$1[*]"; echo "${!var}"; }

# given colon delimited platforms, create paths by prefixing $1/ and
# appending /$2 to each element in platforms
interpolate-platforms () {

    echo $1/${platforms//:/\/$2:$1\/}/$2

}


# given a colon delimited path, return a set of unique existing paths
clean-path () {

    local IFS=':'

    # remove duplicate path. do this by constructing a string (pathchk)
    # containing the paths (with each path bracketed with colons) and
    # comparing that to a prospective new path (also bracketed with
    # colons) can't use associative arrays as that's available in all
    # the bashes

    # make sure that each element in pathchk is bracketed with a colon
    # so test below works
    local pathchk=':'

    local paths=( )
    for path in $1 ; do
	if [[ $pathchk != *":$path:"* ]]; then
	    pathchk="$pathchk$path:"
	    test -d "$path" && paths[${#paths[*]}]=$path
	fi
    done

    echo "${paths[*]}"
}

# takes as arguments path and command
find-exe ()  { local PATH="$1"; hash -d $2 ; command -v $2 ; }


get_platforms() {

    platforms=$("$SYSARCH" platform_os_generic)
    err=$?
    if [ $err -ne 0 ] ; then
	die "$0: error running "$SYSARCH": exit value = $err"
    fi

    if [ -z "$platforms" ] ; then
	die "$0: error running "$SYSARCH": platforms is an empty list"
    fi

}

get_interpreter_exe() {

    test -z "$platforms" && get_platforms

    local iexe=$1
    local outvar
    local wrapvar="MSTENVS_WRAP_$1"
    local exe

    # wrapvar allows one to override the mechanisms for finding the interpreter
    # during installation of a new interpreter

    if [ -n "${!wrapvar}" ]; then

	exe=${!wrapvar}

	if [ ! -f $exe -o ! -x $exe ]; then
	    die "$0: $wrapvar: $exe is not executable"

	fi
    else

	local path="$(interpolate-platforms "$@MST_OTS_ROOT_VAR@/pkgs/$iexe" bin):/usr/local/bin:/usr/bin"
	exe=$(find-exe "$path" $iexe )

	test $? -ne 0 && die "$0: unable to find $iexe in path ($path)"
    fi

    # need absolute path to intepreter; if it is found relative
    # to current dir, preface it with current dir
    [[ $exe = \.* ]] && exe="$PWD/$exe"

    [[ "$exe" == $@MST_OTS_ROOT_VAR@/pkgs/* ]] && eval "is_mst_ots_pkgs_$iexe=1"

    echo "$exe"
}

get_perl_exe() {

    local exe=${1:-perl}

    PERL=$(get_interpreter_exe $exe)
}

set_perl_environment () {

    stack=()

    # We want to use PERL5LIB.
    #  1. PERL5LIB causes PERLLIB to be ignored
    #  2. If PERLLIB and no PERL5LIB, set PERL5LIB = PERLLIB

    if [ -n "$PERLLIB" -a -z "$PERL5LIB" ]; then
	PERL5LIB="$PERLLIB"
    fi


    # create list of directories in search order (most to least specific)

    push "$MST_SIMUL_ROOT/lib/perl5"


    if (( is_mst_ots_pkgs_perl )); then

	# if it's an MST supplied Perl, it already has the MST OTS Perl
	# paths hardwired; just add MST non-OTS directories

	push "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ lib/perl5)"

    else

        # If the system provided executable is being used then must be
        # explicit about where the MST installed OTS Perl modules
        # live

	push "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ lib/perl5)"
	push "$(interpolate-platforms $@MST_OTS_ROOT_VAR@ lib/perl5)"

    fi

    # the final list of prospective paths
    push "$PERL5LIB"

    export PERL5LIB=$(clean-path $(join-path stack))
    test "$MSTENVS_DUMP_INTERPRETER_PATH" \
	&& echo "PERL5LIB=$PERL5LIB"

}

get_python_exe() {

    local exe=${1:-python2}

    PYTHON=$(get_interpreter_exe $exe)
    PYTHON_VERSION=( $($PYTHON -V 2>&1) )
    PYTHON_VERSION=${PYTHON_VERSION[1]%.*}
}


set_python_environment () {

    stack=()

    local libpath="lib/python$PYTHON_VERSION"
    local lib64path="lib64/python$PYTHON_VERSION"

    local has_lib64=0

    test -d /usr/lib64 -a ! -L /usr/lib64 \
	&&  has_lib64=1

    push "$MST_SIMUL_ROOT/$libpath/site-packages"

    push_if $has_lib64 "$MST_SIMUL_ROOT/$lib64path/site-packages"


    if (( is_mst_ots_pkgs_python )); then

	# if it's MST supplied, it already has the MST OTS paths
	# hardwired; just add MST non-OTS directories

	push "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $libpath)"
	push "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $libpath/site-packages)"

	push_if $has_lib64 "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $lib64path)"
	push_if $has_lib64 "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $lib64path/site-packages)"

    else

        # If the system provided executable is being used then must be
        # explicit about where the MST installed OTS modules
        # live

	push "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $libpath)"
	push "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $libpath/site-packages)"

	push_if $has_lib64 "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $lib64path)"
	push_if $has_lib64 "$(interpolate-platforms $@MST_SIMUL_ROOT_VAR@ $lib64path/site-packages)"

	push "$(interpolate-platforms $@MST_OTS_ROOT_VAR@ $libpath)"
	push "$(interpolate-platforms $@MST_OTS_ROOT_VAR@ $libpath/site-packages)"

	push_if $has_lib64 "$(interpolate-platforms $@MST_OTS_ROOT_VAR@ $lib64path)"
	push_if $has_lib64 "$(interpolate-platforms $@MST_OTS_ROOT_VAR@ $lib64path/site-packages)"

    fi

    # the final list of prospective paths
    push "$PYTHONPATH"

    paths=$(join-path stack)

    export PYTHONPATH=$(clean-path $(join-path stack))
    test "$MSTENVS_DUMP_INTERPRETER_PATH" \
	&& echo "PYTHONPATH=$PYTHONPATH"
}
