#!/bin/sh
# Test the stage2 directory to see whether it passes
# a bootstrap check and/or a check using the tests directory.
# If stage2 passes, binary_step returns an exit status of 0 (true);
# if it fails, binary_step returns an exit status of 1 (false).
#
# binary_step remakes the archive in stage2/library and the executable
# in stage2/compiler. In the intended use, the binary script sets up
# these directories so that these actions cause no recompilations,
# either Mercury to C or C to object, only linking. Other uses probably
# won't work.

usage="\
Usage: $0 [options]
Options:
	-b-, --no-bootcheck
		Do not perform a bootcheck; check only the tests directory.
	-c, --compile-only
		Check the successful creation of the stage3 .c files,
		but do not compare stage2.ok and stage3.
	-C, --compare-to-bad
		Compile stage3 using the parameter settings in the stage2.bad
		directory, and compare stage3 to stage2.bad, not stage2.ok.
	-d, --dependency-only
		Check only that the dependencies can be made in stage3.
	-h, --help
		Display this usage message.
	-j <num-jobs>, --jobs <num-jobs>
		Run using <num-jobs> different parallel processes.
	-l, --library-only
		Check the successful creation of the stage3 .c files in the
		library, but do not compile the compiler directory.
	-m <mmake-args>, --mmake-args <mmake-args>
		Pass <mmake-args> as options to \`mmake'.
	-o <filename>, --output-file <filename>
		Output results to <filename>.
	-s <command>, --single-command <command>
		Execute the given command using the constructed compiler.
	-t <testdir>, --test-dir <testdir>
		Execute runtests from the named subdirectory of tests.
"

# If you change this, you will also need to change the files indicated
# in scripts/c2init.in.
STD_LIB_NAME=mer_std

set -x

alltestdirs="benchmarks general hard_coded invalid valid warnings"

bootcheck="true"
compile_only="false"
dependency_only="false"
library_only="false"
jfactor=""
mmake_opts=""
outfile="DIFF.BINARY"
single_command=""
testdirs=""
basis="ok"

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

	-b-|--no-bootcheck)
		bootcheck="false" ;;

	-c|--compile-only)
		compile_only="true" ;;

	-C|--compare-to-bad)
		basis="bad" ;;

	-d|--dependency-only)
		dependency_only="true" ;;

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

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

	-l|--library-only)
		library_only="true" ;;

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

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

	-s|--single-command)
		single_command="$2"; shift ;;
	-s*)
		single_command="` expr $1 : '-s\(.*\)' `" ;;
	--single-command*)
		single_command="` expr $1 : '--single-command\(.*\)' `" ;;

	-t|--test-dir)
		testdir="$2"; shift
		if test -d tests/$testdir
		then
			testdirs="$testdirs $testdir"
		else
			if test "$testdir" = "all"
			then
				testdirs="$alltestdirs"
			else
				echo "tests has no subdirectory named $testdir"
			fi
		fi ;;
	-t*)
		testdir="` expr $1 : '-t\(.*\)' `"
		if test -d tests/$testdir
		then
			testdirs="$testdirs $testdir"
		else
			if test "$testdir" = "all"
			then
				testdirs="$alltestdirs"
			else
				echo "tests has no subdirectory named $testdir"
			fi
		fi ;;

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

	*)
		echo "$usage" 1>&2
		exit 1 ;;
	esac
	shift
done

root=`/bin/pwd`

MERCURY_COMPILER=$root/compiler/mercury_compile
export MERCURY_COMPILER

MERCURY_CONFIG_FILE=$root/scripts/Mercury.config
export MERCURY_CONFIG_FILE

MMAKE_VPATH=.
export MMAKE_VPATH
MMAKE_DIR=../scripts
export MMAKE_DIR

# Ensure that mmake will not disturb the .o and .c files placed there by binary

set +x

touch stage2/library/*.c
touch stage2/compiler/*.c

sleep 2

touch stage2/library/*.int3
touch stage2/compiler/*.int3

sleep 2

touch stage2/library/*.date3
touch stage2/compiler/*.date3

touch stage2/library/*.int2
touch stage2/library/*.int
touch stage2/compiler/*.int2
touch stage2/compiler/*.int

sleep 2

touch stage2/library/*.date
touch stage2/compiler/*.date

touch stage2/library/*.opt

sleep 2

touch stage2/library/*.optdate
touch stage2/library/*.trans_opt

sleep 2

touch stage2/library/*.trans_opt_date
touch stage2/library/*.o
touch stage2/library/*.pic_o
touch stage2/compiler/*.o

# Rebuild the stage2 library and compiler from the components already there.

/bin/rm -f stage2/library/lib$STD_LIB_NAME.a stage2/library/lib$STD_LIB_NAME.so
/bin/rm -f stage2/compiler/mercury_compile

set -x

if (cd stage2/library ; mmake $mmake_opts $jfactor)
then
	echo "building of stage 2 library successful"
else
	echo "building of stage 2 library not successful"
	touch .stage2_problem
	exit 1
fi

if (cd stage2/compiler ; mmake $mmake_opts $jfactor mercury_compile)
then
	echo "building of stage 2 compiler successful"
else
	echo "building of stage 2 compiler not successful"
	touch .stage2_problem
	exit 1
fi

unset MMAKE_VPATH
unset MMAKE_DIR

MERCURY_COMPILER=$root/stage2/compiler/mercury_compile
export MERCURY_COMPILER

ulimit -t 200

if test "$single_command" != ""
then
	echo "executing $single_command"
	arg $single_command
	if $single_command
	then
		echo "command successful"
	else
		echo "command not successful"
		exit 1
	fi
fi

if "$bootcheck"
then

	# Rebuild the stage3 library and compiler from scratch

	/bin/rm -f stage3/library/*.c
	/bin/rm -f stage3/library/*.c_date
	/bin/rm -f stage3/library/*.d
	/bin/rm -f stage3/library/*.optdate
	/bin/rm -f stage3/library/*.trans_opt_date
	/bin/rm -f stage3/library/*.date3
	/bin/rm -f stage3/library/*.date
	/bin/rm -f stage3/library/*.opt
	/bin/rm -f stage3/library/*.trans_opt
	/bin/rm -f stage3/library/*.int3
	/bin/rm -f stage3/library/*.int2
	/bin/rm -f stage3/library/*.int
	/bin/rm -f stage3/compiler/*.c
	/bin/rm -f stage3/compiler/*.c_date
	/bin/rm -f stage3/compiler/*.d
	/bin/rm -f stage3/compiler/*.optdate
	/bin/rm -f stage3/compiler/*.trans_opt_date
	/bin/rm -f stage3/compiler/*.date3
	/bin/rm -f stage3/compiler/*.date
	/bin/rm -f stage3/compiler/*.opt
	/bin/rm -f stage3/compiler/*.trans_opt
	/bin/rm -f stage3/compiler/*.int3
	/bin/rm -f stage3/compiler/*.int2
	/bin/rm -f stage3/compiler/*.int

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

	MMAKE_VPATH=.
	export MMAKE_VPATH
	MMAKE_DIR=../scripts
	export MMAKE_DIR

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

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

	if test "$compile_only" = false
	then
		founddiff=false
		cat /dev/null > $outfile
		for dir in library compiler
		do
			# `mmake cs' in the compiler directory doesn't build
			# `top_level_init.c', so we only compare the `.c'
			# files present in the stage3 directory.
			for stage3file in stage3/$dir/*.c
			do
				stage2file="stage2.$basis/$dir/`basename $file`"
				diff -u $stage2file $stage3file >> $outfile ||
					founddiff=true
			done
		done

		if "$founddiff" = true
		then
			echo "error - stage2.$basis and stage3 differ!"
			exit 1
		else
			echo "stage2.$basis and stage3 compare ok"
		fi
	fi
fi

for testdir in $testdirs
do
	if (cd tests/$testdir; runtests)
	then
		echo "tests in the $testdir directory successful"
	else
		echo "tests in the $testdir directory not successful"
		exit 1
	fi
done

exit 0
