#!/bin/sh
# vim: ts=4 sw=4 expandtab ft=sh
#
# A version of two_module_test that should be more useful for debugging,
# because instead of hiding the action behind shell functions, it exposes
# the details of each step. This allows a Mercury developer to (temporarily)
# modify this script to observe not just the final result of a call to a shell
# function, but also its intermediate results, e.g. by copying files
# suspected to be constructed incorrectly to safe locations before later steps
# overwrite them. It also allows running some compiler invocations under mdb.
# When you suspect, or know, that a step is screwing up, this can be extremely
# helpful. Smart recompilation is NOT idempotent; executing even part of
# a compiler invocation (until e.g. a compiler abort) can, and often will,
# change the contents of files in a way that will cause later, seeming
# identical compiler invocations to take a different execution path.
# By rerunning the whole test process from the start, recreating all
# the relevant files from scratch each time, this script can sidestep
# that problem.
#
# This script also has some limitations compared with two_module_test.
# The main one is that it covers only grades that target C.
# It also handles the <mmake_test 2 should_fail> block differently
# than two_module_test.

# It is easier to look up the contents of e.g. .used files
# if they are in the current directory.
/bin/rm -fr Mercury

test_prog="unchanged_with_type_nr"
expected_mmake_result=should_succeed
module_1="${test_prog}"
module_2="${test_prog}_2"
modules="${module_1} ${module_2}"

tested_compiler="/home/zs/ws/ws31/compiler/mercury_compile"
MERCURY_COMPILER="${tested_compiler}"
export MERCURY_COMPILER

grade_opts="--grade hlc.gc"
dir_opts="--flags ../TESTS_FLAGS"
opt_opts="--no-intermodule-optimization"
smart_opts="--smart-recompilation --find-all-recompilation-reasons"
std_opts="${grade_opts} ${dir_opts} ${opt_opts} ${smart_opts}"

echo "Testing ${test_prog}"

echo "block <test_module ${module_1} ${module_2}>"
rm -f "${module_1}.m"
cp "${module_1}.m.1" "${module_1}.m"
chmod -w "${module_1}.m"
rm -f "${module_2}.m"
cp "${module_2}.m.1" "${module_2}.m"
chmod -w "${module_2}.m"
rm -f "${module_1}.res"
touch "${module_1}.res"
sleep 1

echo "block <mmake_depend>"
mmc --generate-dependencies ${std_opts} ${module_1} > ${module_1}.dep_err 2>&1

echo "block <mmake_test 1 should_succeed>"
mmc --make-short-interface  ${std_opts} ${module_2}
mmc --make-interface        ${std_opts} ${module_2}
mmc --make-interface        ${std_opts} ${module_1}
mmc --compile-to-c          ${std_opts} ${module_1} > ${module_1}.err 2>&1
mmc --compile-to-c          ${std_opts} ${module_2} > ${module_2}.err 2>&1
cp -f ${module_2}.int   ${module_2}.int.step1
cp -f ${module_2}.used  ${module_2}.used.step1
mgnuc ${grade_opts} -- -c ${module_1}.c -o ${module_1}.o
mgnuc ${grade_opts} -- -c ${module_2}.c -o ${module_2}.o
ml ${grade_opts} -- -o ${module_1} ${module_1}_init.o \
	${module_1}.o ${module_2}.o
case "$?" in
    0)
        ;;
    *)
        echo "exiting due to failure of <mmake_test 1 should_succeed>"
        exit 1
        ;;
esac
exp_file="${module_1}.exp.1"
res_file="${module_1}.out"
./${module_1} > "${res_file}"
# We assume ${exp_file} exists.
if diff ${DIFF_OPTS-"-c"} "${exp_file}" "${res_file}" >> "${module_1}.res"
then
    true
else
    echo "** Error in mmake_test 1 should_succeed: ${exp_file} and ${res_file} differ."
    cat "${module_1}.res"
    exit 1
fi

echo "block <update_module ${module_2} 2>"
sleep 1
rm -f "${module_2}.m"
cp "${module_2}.m.2" "${module_2}.m"
chmod -w "${module_2}.m"
sleep 1

case "${expected_mmake_result}" in
    should_succeed)
        echo "block <mmake_test 2 should_succeed>"
        mmc --make-short-interface  ${std_opts} ${module_2}
        mmc --make-interface        ${std_opts} ${module_2}
        mmc --make-interface        ${std_opts} ${module_1}
        cp -f ${module_2}.int   ${module_2}.int.step2
        cp -f ${module_2}.used  ${module_2}.used.step2
        # mdb mmc --compile-to-c      ${std_opts} ${module_1}
        mmc --compile-to-c          ${std_opts} ${module_1} \
            > ${module_1}.err 2>&1
        echo --- ${module_1}.err ---
        cat ${module_1}.err
        echo status = $?
        exit 0
        mmc --compile-to-c          ${std_opts} ${module_2} \
            > ${module_2}.err 2>&1
        mgnuc ${grade_opts} -- -c ${module_1}.c -o ${module_1}.o
        mgnuc ${grade_opts} -- -c ${module_2}.c -o ${module_2}.o
        ml ${grade_opts} -- -o ${module_1} ${module_1}_init.o \
            ${module_1}.o ${module_2}.o
        case "$?" in
            0)
                ;;
            *)
                echo "Error: <mmake_test 2 should_succeed> has failed"
                exit 1
                ;;
        esac
        exp_file="${module_1}.exp.2"
        res_file="${module_1}.out"
        ./${module_1} > "${res_file}"
        # We assume ${exp_file} exists.
        if diff ${DIFF_OPTS-"-c"} "${exp_file}" "${res_file}" \
            >> "${module_1}.res"
        then
            true
        else
            echo "** Error in mmake_test 2 should_succeed: ${exp_file} and ${res_file} differ."
            cat "${module_1}.res"
            exit 1
        fi
        ;;
    should_fail)
        echo "block <mmake_test 2 should_fail>"
        > "${module_1}.should_fail"
        ( \
            mmc --make-short-interface  ${std_opts} ${module_2}; \
            if test "$?" != 0; \
            then \
                echo "failure" >> "${module_1}.should_fail"; \
            fi; \
            mmc --make-interface        ${std_opts} ${module_2}; \
            if test "$?" != 0; \
            then \
                echo "failure" >> "${module_1}.should_fail"; \
            fi; \
            mmc --make-interface        ${std_opts} ${module_1}; \
            if test "$?" != 0; \
            then \
                echo "failure" >> "${module_1}.should_fail"; \
            fi; \
            mmc --compile-to-c          ${std_opts} ${module_1} \
                > ${module_1}.err 2>&1; \
            if test "$?" != 0; \
            then \
                echo "failure" >> "${module_1}.should_fail"; \
            fi; \
            mmc --compile-to-c          ${std_opts} ${module_2} \
                > ${module_2}.err 2>&1; \
            if test "$?" != 0; \
            then \
                echo "failure" >> "${module_1}.should_fail"; \
            fi; \
        ) > "${module_1}.failing_make_output"
        if test ! -s "${module_1}.should_fail)"
        then
            echo "Error: <mmake_test 2 should_fail> has succeeded"
            exit 1
        fi
        ;;
    *)
        echo "** Error: bad expected_mmake_result ${expected_mmake_result}"
        exit 1
        ;;
esac

echo "block <check_err_file ${module_1} 2>"
sed -e '/has CHANGED/d' -e 's/Mercury\/.*\///g' "${module_1}.err" \
    > "${module_1}.err2"
mv "${module_1}.err2" "${module_1}.err"
exp_file="${module_1}.err_exp.2"
res_file="${module_1}.err"
# We assume ${exp_file} exists.
if diff ${DIFF_OPTS-"-c"} "${exp_file}" "${res_file}" >> "${module_1}.res"
then
    true
else
    echo "** Error in check_err_file ${module_1} 2: ${exp_file} and ${res_file} differ."
    cat "${module_1}.res"
    exit 1
fi

echo "block <check_err_file ${module_2} 2>"
sed -e '/has CHANGED/d' -e 's/Mercury\/.*\///g' "${module_2}.err" \
    > "${module_2}.err2"
mv "${module_2}.err2" "${module_2}.err"
exp_file="${module_2}.err_exp.2"
res_file="${module_2}.err"
# We assume ${exp_file} exists.
if diff ${DIFF_OPTS-"-c"} "${exp_file}" "${res_file}" >> "${module_2}.res"
then
    true
else
    echo "** Error in check_err_file ${module_2} 2: ${exp_file} and ${res_file} differ."
    cat "${module_2}.res"
    exit 1
fi

exit 0
