#!/bin/bash

arch="x86_64"
name="brokk0"

# ---- copied from /var/lib/jenkins/workspace/Cforall_master_2/tools/jenkins/setup.sh.in ----

# check if stdout is a terminal...
if test -t 1; then

	# see if it supports colors...
	ncolors=$(tput colors)

	if test -n "$ncolors" && test $ncolors -ge 8; then
		bold="$(tput bold)"
		underline="$(tput smul)"
		standout="$(tput smso)"
		normal="$(tput sgr0)"
		black="$(tput setaf 0)"
		red="$(tput setaf 1)"
		green="$(tput setaf 2)"
		yellow="$(tput setaf 3)"
		blue="$(tput setaf 4)"
		magenta="$(tput setaf 5)"
		cyan="$(tput setaf 6)"
		white="$(tput setaf 7)"
	fi
fi

function error
{
	>&2 echo "${red}$1${normal}"
}

# helper function to get the runpath (-Wl,-rpath in gcc)
function getrunpath()
{
	local elfout=$(readelf -d $1 | grep -E "RPATH|RUNPATH")
	regex='\[/([[:alpha:][:digit:]@/_.-]+)\]'
	if [[ $elfout =~ $regex ]]; then
		local myRPath=${BASH_REMATCH[1]}
	else
		error "Could not find RUNPATH for test $2"
	fi
	echo "$myRPath"
}

# helper function to list the dependencies of each executable
function getdeps()
{
	local deps=$(ldd $1)
	retlcldeps=()
	retsysdeps=()
	while IFS= read -r line; do
		regex1='(libcfa[[:alpha:][:digit:].]+)'
		regex2='/([[:alpha:][:digit:]@/_.-]+)'
		regex3='linux-vdso.so.1|linux-gate.so.1'
		if [[ $line =~ $regex1 ]]; then
			retlcldeps+=(${BASH_REMATCH[1]})
		elif [[ $line =~ $regex2 ]]; then
			retsysdeps+=(${BASH_REMATCH[1]})
		elif [[ $line =~ $regex3 ]]; then
			# echo "ignoring '$line}': intrinsic"
			:
		else
			error "Could not find dependency '$line' for test $2"
		fi
	done <<< "$deps"
}

# make a symlink, with better errors
function makelink()
{
	local source=$1
	local target=$2
	if [ ! -f $source ]; then
		error "Source of link $source does not exist"
	fi

	if [ ! -e $target ] && [ ! -L $target ]; then
		ln -s $source $target
		return
	fi

	if [ ! -L $target ]; then
		error "Cannot create link $target for $source, existing regular file"
	else
		want=$(readlink -f $source)
		have=$(readlink -f $target)
		if [ $want == $have ]; then
			return
		fi
		error "Target link $(basename $target) for $source already exists and has incorrect target $have"
	fi
}

# ========================================
# make sure this computer is acceptable
myarch=$(uname -m)
if [ ! -z $arch ] && [ "$myarch" != "$arch" ]; then
	error "Wrong architecture, is : $myarch, need: $arch"
	exit 1
fi

myname=$(uname -n)
if [ ! -z $name ] && [ "$myname" != "$name" ]; then
	>&2 echo "${yellow}Unexpected machine name, is: $myname, expected: $name${normal}"
fi

# ========================================
# make sure we use the right paths
srcdir=$(readlink -f $(dirname "$0"))
outdir=$(readlink -f $(pwd))

rnpaths=()
sysdeps=()
lcldeps=()

# find all the tests
programs=($(find $srcdir/tests/crashes -name exe))
if [ ${#programs[@]} -eq 0 ]; then
	error "ERROR no executables found in archive"
	exit 1
fi

# ========================================
# for each tests
echo "generating command files ..."
for pgm in "${programs[@]}"
do
	# find the test's name
	regex='tests/crashes/(short|full-debug|full-nodebug)/([[:alpha:][:digit:]@/_.-]+)/exe'
	if [[ $pgm =~ $regex ]]; then
		name=${BASH_REMATCH[2]}
	else
		error "Executable '$pgm' has ill-formed path"
	fi

	# get a path to the executable
	exe=$(readlink -f "$pgm")

	# check the executable exist
	if [ ! -x $exe ]; then
		error "Executable for '$name' does not have execute permission"
		continue
	fi

	ldd $exe > /dev/null 2>&1
	if [ $? -ne 0 ]; then
		error "Executable for '$name' is not valid for this architecture"
		continue
	fi

	# get the corresponding core file
	core="$(dirname "$exe")/core"
	if [ ! -f "$core" ]; then
		error "No core found for test '$name'"
	fi

	# create the command file
	file="${name//\//.}.com"
	echo "$file"
	echo "set solib-absolute-prefix $outdir" > $file
	echo "file $exe" >> $file
	echo "core-file $core" >> $file

	# find the system dependencies
	getdeps $exe $name
	sysdeps+=("${retsysdeps[@]}")
	lcldeps+=("${retlcldeps[@]}")

	# find it's expected runpath
	rnpaths+=("$(getrunpath $exe $name)")
done <<< "$programs"

echo "done"

# ========================================
# eliminate duplicates from the list of dependencies

# get unique elements of array
function getuniques()
{
	echo "$*" | tr ' ' '\n' | sort -u | tr '\n' ' '
}

rnpaths=($(getuniques ${rnpaths[@]}))
sysdeps=($(getuniques ${sysdeps[@]}))
lcldeps=($(getuniques ${lcldeps[@]}))

# ========================================
# create symlinks to cforall dependencies
echo "setting up local dependencies ..."

for rpath in "${rnpaths[@]}"
do
	# find the debug level
	if [[ $rpath =~ 'nodebug' ]]; then
		level="-nodebug"
	elif [[ $rpath =~ 'debug' ]]; then
		level="-debug"
	else
		error "Executable(s) with ill-formed rpath"
	fi

	# create the right directory
	mkdir -p "$outdir/$rpath"

	# for each dependencies create them
	# this might create unnecessary pairs, but I don't care
	for lib in "${lcldeps[@]}"
	do
		echo "$lib$level"
		source=$(find "$srcdir" -name "$lib*" -a -path "*$level*")
		target="$outdir/$rpath/$lib"
		makelink $source $target
	done
done

echo "done"

# ========================================
# create symlinks to system dependencies
echo "setting up system dependencies ..."

for dep in "${sysdeps[@]}"
do
	echo $dep
	mkdir -p "$outdir/$(dirname $dep)"
	makelink "/$dep" "$outdir/$dep"
done

echo "done"