#!/bin/sh
#---------------------------------------------------------------------------#
# Copyright (C) 1995-1997 The University of Melbourne.
# This file may only be copied under the terms of the GNU General
# Public License - see the file COPYING in the Mercury distribution.
#---------------------------------------------------------------------------#

usage="\
Usage: $0 [options]
Options:
	-h, --help
		Display this usage message.
	-j <num-jobs>, --jobs <num-jobs>
		Run using <num-jobs> different parallel processes.
	-m <mmake-args>, --mmake-args <mmake-args>
		Pass <mmake-args> as options to \`mmake'.
	-o <filename>, --output-file <filename>
		Output results to <filename>.
	-r, --copy-runtime
		Copy the runtime directory instead of linking it.
		This is necessary if one wants to bootcheck a grade
		that is not compatible with the standard one.
	-t, --no-test-suite
		By default, bootcheck will also run the test quite.
		This option prevents that.
	-s, --sicstus
		As well as running the normal bootcheck, also build a SICStus
		Prolog version of the compiler and check it against the
		stage 2 directory.
	-2, --keep-stage-2
		Don't rebuild the stage 2 directory from scratch after
		building stage 1.  Instead use the existing stage 2 directory.
	-3, --keep-stage-3
		Don't rebuild the stage 3 directory from scratch after
		building stage 1.  Instead use the existing stage 3 directory.
	--keep-stage-2-sicstus
		Don't rebuild the SICStus stage 2 directory from scratch after
		building stage 1.  Instead use the existing SICStus stage 2
		directory.
"

jfactor=""
mmake_opts="-k"
outfile=""
runtests=true
copy_runtime=false
keep_stage_2=false
keep_stage_3=false
keep_stage_2_sicstus=false
test_sicstus=false

while [ $# -gt 0 ]; do
	case "$1" in

	-h|--help)
		echo "$usage"
		exit 0 ;;

	-j|--jobs)
		jfactor="-j$2"; shift ;;
	-j*)
		jfactor="-j` expr $1 : '-j\(.*\)' `" ;;
	--jobs*)
		jfactor="--jobs` expr $1 : '--jobs\(.*\)' `" ;;

	-m|--mmake)
		mmake_opts="$mmake_opts $2"; shift ;;

	-o|--output-file)
		outfile="$2"; shift ;;
	-o*)
		outfile="` expr $1 : '-o\(.*\)' `"; ;;

	-r|--copy-runtime)
		copy_runtime=true ;;

	-t|--no-test-suite)
		runtests=false ;;

	-s|--sicstus)
		test_sicstus=true ;;

	-2|--keep-stage-2)
		keep_stage_2=true ;;

	-3|--keep-stage-3)
		keep_stage_3=true ;;

	--keep-stage-2-sicstus)
		keep_stage_2_sicstus=true ;;

	--)	
		shift; break ;;
	-*)
		echo "$0: unknown option \`$1'" 1>&2
		echo "$usage" 1>&2
		exit 1 ;;
	*)
		break ;;
	esac
	shift
done

if [ $# -ne 0 ]; then
	echo "$0: unexpected argument(s) \`$*'" 1>&2
	echo "$usage" 1>&2
	exit 1
fi

echo "starting at `date`"

set -x

root=`/bin/pwd | sed 's:/mount/munkora/mercury:/home/mercury:'`
PATH=$root/tools:$PATH
export PATH

if test "$RMSTAGECMD" = ""
then
	RMSTAGECMD="/bin/rm -fr"
fi

if $test_sicstus
then
	echo "Building SICStus stage 1..." 1>&2
	if 
		cd $root/library &&
		mmake $mmake_opts $jfactor sicstus &&
		cd $root/compiler &&
		mmake $mmake_opts $jfactor sicstus &&
		cd $root
	then
		echo "building of SICStus stage 1 successful"
	else
		echo "building of SICStus stage 1 not successful"
		exit 1
	fi

	MERCURY_COMPILER=$root/compiler/mercury_compile.sicstus
	export MERCURY_COMPILER
	MERCURY_INT_DIR=$root/stage2_sicstus/library
	export MERCURY_INT_DIR

	[ -d stage2_sicstus ] || mkdir stage2_sicstus
	if $keep_stage_2_sicstus
	then
		echo keeping existing stage2_sicstus
	else
		# We try to do the removal of the stage 2 directory in parallel
		# since recursive rm's across NFS can be quite slow ...
		$RMSTAGECMD $root/stage2_sicstus/compiler < /dev/null &
		$RMSTAGECMD $root/stage2_sicstus/library < /dev/null &
		wait
		$RMSTAGECMD $root/stage2_sicstus/* < /dev/null
	fi

	set +x
	echo linking SICStus stage 2... 1>&2
	cd stage2_sicstus
	mkdir compiler
	cd compiler
	# Break up the links into several chunks.
	# This is needed to cope with small limits on the size of argument
	# vectors.

	ln -s $root/compiler/[a-h]*.m .
	ln -s $root/compiler/[i-s]*.m .
	ln -s $root/compiler/[t-z]*.m .
	cp $root/compiler/Mmake* .
	cd $root/stage2_sicstus
	mkdir library
	cd library
	ln -s $root/library/library.nu.nl.in .
	ln -s $root/library/[a-l]*.m .
	ln -s $root/library/[m-z]*.m .
	ln -s $root/library/*.nl .
	cp $root/library/Mmake* .
	ln -s $root/library/libmercury.init .
	cd $root/stage2_sicstus
	if test "$copy_runtime" = "true"
	then
		mkdir runtime
		cd runtime
		ln -s $root/runtime/*.h .
		ln -s $root/runtime/*.c .
		ln -s $root/runtime/*.mod .
		ln -s $root/runtime/*.in .
		cp $root/runtime/Mmake* .
		ln -s $root/runtime/machdeps .
		cd $root/stage2_sicstus
	else
		ln -s $root/runtime .
	fi
	ln -s $root/boehm_gc .
	ln -s $root/doc .
	ln -s $root/scripts .
	ln -s $root/util .
	ln -s $root/profiler .
	ln -s $root/conf* .
	ln -s $root/VERSION .
	ln -s $root/.README.in .
	ln -s $root/.INSTALL.in .
	rm -f config*.log
	cp $root/Mmake* .
	if test -f $root/Mmake.stage.params
	then
		/bin/rm -f Mmake.params
		cp $root/Mmake.stage.params Mmake.params
	fi
	cd $root

	set -x

	if 
		cd stage2_sicstus &&
		mmake $mmake_opts depend_library depend_compiler &&
		cd $root
	then
		echo "building of SICStus stage 2 dependencies successful"
	else
		echo "building of SICStus stage 2 dependencies not successful"
		exit 1
	fi

	MMAKE_VPATH=.
	export MMAKE_VPATH
	MMAKE_DIR=$root/scripts
	export MMAKE_DIR

	if 
		cd stage2_sicstus/library &&
		mmake $mmake_opts $jfactor ints &&
		mmake $mmake_opts $jfactor cs
	then
		echo "building of SICStus stage 2 library successful"
	else
		echo "building of SICStus stage 2 library not successful"
		exit 1
	fi
	cd $root

	if 
		cd stage2_sicstus/compiler &&
		mmake $mmake_opts $jfactor cs
	then
		echo "building of SICStus stage 2 compiler successful"
	else
		echo "building of SICStus stage 2 compiler not successful"
		exit 1
	fi
	cd $root

	sicstus_diff_status=0

	exec 3>&1		# save stdout in fd 3
	if [ -n "$outfile" ]
	then
		exec > "$outfile"	# redirect stdout to $outfile
	fi

	for dir in library compiler; do
		for file in stage2/$dir/*.c; do
			diff -u $file stage2_sicstus/$dir/`basename $file` ||
				sicstus_diff_status=1
		done
	done

	exec >&3		# restore stdout from fd 3
	if [ $sicstus_diff_status -ne 0 ]; then
		echo "error - SICStus stage 2 and Mercury stage 2 differ!"
		exit 1
	else
		echo "SICStus stage 2 and Mercury stage 2 compare ok"
		echo "removing SICStus stage 2..."
		# We try to do the removal of the SICStus stage 2 directory
		# in parallel since recursive rm's across NFS can be quite
		# slow ...
		$RMSTAGECMD $root/stage2_sicstus/compiler < /dev/null &
		$RMSTAGECMD $root/stage2_sicstus/library < /dev/null &
		wait
		$RMSTAGECMD $root/stage2_sicstus/* < /dev/null
		exit 0
	fi

fi

if mmake $mmake_opts MMAKEFLAGS=$jfactor all
then
	echo "building of stage 1 successful"
else
	echo "building of stage 1 not successful"
	exit 1
fi

# the stage 1 compiler is copied to allow it to be worked on (slightly)
# in parallel with the bootcheck itself.

[ -d stage1 ] || mkdir stage1

cp compiler/mercury_compile stage1
MERCURY_COMPILER=$root/stage1/mercury_compile
export MERCURY_COMPILER
MERCURY_INT_DIR=$root/stage2/library
export MERCURY_INT_DIR

[ -d stage2 ] || mkdir stage2
if $keep_stage_2
then
	echo keeping existing stage2
else
	# We try to do the removal of the stage 2 directory in parallel
	# since recursive rm's across NFS can be quite slow ...
	$RMSTAGECMD $root/stage2/compiler < /dev/null &
	$RMSTAGECMD $root/stage2/library < /dev/null &
	wait
	$RMSTAGECMD $root/stage2/* < /dev/null
fi

set +x
echo linking stage 2... 1>&2
cd stage2
mkdir compiler
cd compiler
# Break up the links into several chunks.
# This is needed to cope with small limits on the size of argument vectors.

ln -s $root/compiler/[a-h]*.m .
ln -s $root/compiler/[i-s]*.m .
ln -s $root/compiler/[t-z]*.m .
cp $root/compiler/Mmake* .
cd $root/stage2
mkdir library
cd library
ln -s $root/library/library.nu.nl.in .
ln -s $root/library/[a-l]*.m .
ln -s $root/library/[m-z]*.m .
ln -s $root/library/*.nl .
cp $root/library/Mmake* .
ln -s $root/library/libmercury.init .
cd $root/stage2
if test "$copy_runtime" = "true"
then
	mkdir runtime
	cd runtime
	ln -s $root/runtime/*.h .
	ln -s $root/runtime/*.c .
	ln -s $root/runtime/*.mod .
	ln -s $root/runtime/*.in .
	cp $root/runtime/Mmake* .
	ln -s $root/runtime/machdeps .
	cd $root/stage2
else
	ln -s $root/runtime .
fi
ln -s $root/boehm_gc .
ln -s $root/doc .
ln -s $root/scripts .
ln -s $root/util .
ln -s $root/profiler .
ln -s $root/conf* .
ln -s $root/VERSION .
ln -s $root/.README.in .
ln -s $root/.INSTALL.in .
rm -f config*.log
cp $root/Mmake* .
if test -f $root/Mmake.stage.params
then
	/bin/rm -f Mmake.params
	cp $root/Mmake.stage.params Mmake.params
fi
cd $root

set -x

if (cd stage2 && mmake $mmake_opts $jfactor runtime)
then
	echo "building of stage 2 runtime successful"
else
	echo "building of stage 2 runtime not successful"
	exit 1
fi

if (cd stage2 && mmake $mmake_opts depend_library depend_compiler)
then
	echo "building of stage 2 dependencies successful"
else
	echo "building of stage 2 dependencies not successful"
	exit 1
fi

MMAKE_VPATH=.
export MMAKE_VPATH
MMAKE_DIR=$root/scripts
export MMAKE_DIR

# the `RM_C=:' ensures that the `.c' files do not get deleted

if (cd stage2/library && mmake $mmake_opts $jfactor RM_C=: mercury)
then
	echo "building of stage 2 library successful"
else
	echo "building of stage 2 library not successful"
	exit 1
fi

if (cd stage2/compiler && mmake $mmake_opts $jfactor RM_C=: mercury_compile)
then
	echo "building of stage 2 compiler successful"
else
	echo "building of stage 2 compiler not successful"
	exit 1
fi

unset MMAKE_VPATH
unset MMAKE_DIR

if (cd stage2 && mmake $mmake_opts $jfactor all)
then
	echo "building of stage 2 successful"
else
	echo "building of stage 2 not successful"
	exit 1
fi

MERCURY_COMPILER=$root/stage2/compiler/mercury_compile
export MERCURY_COMPILER
MERCURY_INT_DIR=$root/stage3/library
export MERCURY_INT_DIR

[ -d stage3 ] || mkdir stage3
if $keep_stage_3
then
	echo keeping existing stage3
else
	# We try to do the removal of the stage 3 directory in parallel
	# since recursive rm's across NFS can be quite slow ...
	$RMSTAGECMD $root/stage3/compiler < /dev/null &
	$RMSTAGECMD $root/stage3/library < /dev/null &
	wait
	$RMSTAGECMD $root/stage3/* < /dev/null
fi

echo linking stage 3... 1>&2
set +x
cd stage3
mkdir compiler
cd compiler
# Break up the links into several chunks.
# This is needed to cope with small limits on the size of argument vectors.
ln -s $root/compiler/[a-h]*.m .
ln -s $root/compiler/[i-s]*.m .
ln -s $root/compiler/[t-z]*.m .
cp $root/compiler/Mmake* .
cd $root/stage3
mkdir library
cd library
ln -s $root/library/library.nu.nl.in .
ln -s $root/library/[a-l]*.m .
ln -s $root/library/[m-z]*.m .
ln -s $root/library/*.nl .
cp $root/library/Mmake* .
ln -s $root/library/libmercury.init .
cd $root/stage3
ln -s $root/boehm_gc .
ln -s $root/doc .
ln -s $root/runtime .
ln -s $root/scripts .
ln -s $root/util .
ln -s $root/profiler .
ln -s $root/conf* .
ln -s $root/VERSION .
ln -s $root/.README.in .
ln -s $root/.INSTALL.in .
rm -f config*.log
cp $root/Mmake* .
if test -f $root/Mmake.stage.params
then
	/bin/rm -f Mmake.params
	ln -s $root/Mmake.stage.params Mmake.params
fi
cd $root
set -x

if (cd stage3 && mmake $mmake_opts depend_library depend_compiler)
then
	echo "building of stage 3 dependencies successful"
else
	echo "building of stage 3 dependencies not successful"
	exit 1
fi

MMAKE_VPATH=.
export MMAKE_VPATH
MMAKE_DIR=$root/scripts
export MMAKE_DIR

if (cd stage3/library && mmake $mmake_opts $jfactor ints && mmake $mmake_opts $jfactor cs)
then
	echo "building of stage 3 library successful"
else
	echo "building of stage 3 library not successful"
	exit 1
fi

if (cd stage3/compiler && mmake $mmake_opts $jfactor cs)
then
	echo "building of stage 3 compiler successful"
else
	echo "building of stage 3 compiler not successful"
	exit 1
fi

diff_status=0

exec 3>&1		# save stdout in fd 3
if [ -n "$outfile" ]
then
	exec > "$outfile"	# redirect stdout to $outfile
fi

for dir in library compiler; do
	for file in stage2/$dir/*.c; do
		diff -u $file stage3/$dir/`basename $file` || diff_status=1
	done
done

exec >&3		# restore stdout from fd 3
if [ $diff_status -ne 0 ]; then
	echo "error - stage 2 and stage 3 differ!"
else
	echo "stage 2 and stage 3 compare ok"
	echo "removing stage 3..."
	# We try to do the removal of the stage 3 directory in parallel
	# since recursive rm's across NFS can be quite slow ...
	$RMSTAGECMD $root/stage3/compiler < /dev/null &
	$RMSTAGECMD $root/stage3/library < /dev/null &
	wait
	$RMSTAGECMD $root/stage3/* < /dev/null
fi

# since we may have removed the stage3 library, use the one in stage2
MERCURY_INT_DIR=$root/stage2/library
export MERCURY_INT_DIR

if $runtests
then
	echo "finishing stage3 at `date`"

	# we'll use the stage 2 libraries to link against
	MERCURY_LIBS="$root/stage2/library/libmercury.a
                $root/stage2/runtime/libmer.a
                $root/boehm_gc/libgc.a
                -lm"
	export MERCURY_LIBS

	if test -d ../tests
	then
		cd ../tests
		./runtests $jfactor
		test_status=$?
		cd $root
	elif test -d tests
	then
		cd tests
		./runtests $jfactor
		test_status=$?
		cd $root
	else
		echo "cannot find test directory"
		test_status=1
	fi
else
	test_status=0
fi


echo "finishing at `date`"

if test "$diff_status" = 0 -a "$test_status" = 0
then
	exit 0
else
	exit 1
fi
