#!/bin/sh
# vim: ts=4 sw=4 expandtab
#
# A program to prepare batches of versions of the compiler.
#
# The control and output files are all in the subdirectory batch.
# The control files are $batch.MCFLAGS and possibly $batch.CFLAGS,
# $batch.MGNUCFLAGS, $batch.MLFLAGS, $batch.GRADE, $batch.MMAKE,
# $batch.MMAKE.$n where $batch is the last argument of makebatch.
# They are all consulted if they exist.
#
# All the control files except $batch.MMAKE and $batch.MMAKE.$n
# must have the same number of lines. Each line corresponds to a version
# of the compiler that is built with the MCFLAGS, EXTRA_CFLAGS,
# EXTRA_MGNUCFLAGS, EXTRA_MLFLAGS and GRADE make variables being set
# from that line.
#
# The control file $batch.MMAKE.$n contains an Mmakefile fragment that is
# included in the parameters of the version numbered $n.
#
# The control file $batch.MMAKE contains an Mmakefile fragment that is
# included in the parameters of all the versions being built.
#
# The output goes in $batch.mercury_compile.$n.gz; the sizes of the versions
# are put in $batch.sizes. If a bootcheck fails, the bootcheck output goes
# in $batch.out.$n.
#
# The file $batch.checkpoint records which version is to be built next.
# Reinvoking makebatch while this file exists will cause it to start from
# that version. When makebatch exits normally, it removes the file to indicate
# completion.

usage="Usage: makebatch [-jN] [-cdeoqst] [--compile-times] [--save-stage2-on-error] [--save-stage2-on-no-compiler] [--test-params] batchname"
jfactor=-j1
runtests=""
objects=""
cfiles="false"
save_stage2="false"
save_stage2_on_error="false"
save_stage2_on_no_compiler="false"
errfiles="false"
compile_times=""
test_params=""
stop_after_stage_2=""
failed="continue"

if test -f $HOME/.makebatch_save_stage2
then
        save_stage2="true"
fi

while test $# -gt 0
do
    case $1 in

    -c|--c-files)
        cfiles="true" ;;

    -d|--save-stage2-dirs)
        save_stage2="true" ;;

    -e|--err-files)
        errfiles="true" ;;

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

    -o|--object-files)
        objects="-k" ;;

    --save-stage2-on-error)
        save_stage2_on_error="true" ;;

    --save-stage2-on-no-compiler)
        save_stage2_on_no_compiler="true" ;;

    -s|--stop-at-failure)
        failed="stop" ;;

    -q|--quick)
        stop_after_stage_2="--stop-after-stage-2"
        runtests="-t-"
        ;;

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

    --compile-times)
        compile_times="--compile-times" ;;

    --test-params)
        test_params="--test-params" ;;

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

    *)  break ;;

    esac
    shift
done

if test $# != 1
then
    echo $usage
    exit 1
fi

batch=$1

if test ! -r batch/$batch.MCFLAGS
then
    echo "batch/$batch.MCFLAGS does not exist or is not readable"
    exit 1
fi

if test -r batch/$batch.MGNUCFLAGS
then
    needmgnucflags=true
else
    needmgnucflags=false
fi

if test -r batch/$batch.CFLAGS
then
    needcflags=true
else
    needcflags=false
fi

if test -r batch/$batch.MLFLAGS
then
    needmlflags=true
else
    needmlflags=false
fi

if test -r batch/$batch.GRADE
then
    needgrade=true
else
    needgrade=false
fi

if test -r batch/$batch.MMAKE
then
    needmmake=true
else
    needmmake=false
fi

if test -f Mmake.stage.params
then
    echo moving Mmake.stage.params to Mmake.stage.params.$$
    mv Mmake.stage.params Mmake.stage.params.$$
fi

if test -r batch/$batch.checkpoint
then
    n=`cat batch/$batch.checkpoint`
else
    n=1
    cat /dev/null > batch/$batch.sizes
fi

maxn=`wc -l < batch/$batch.MCFLAGS`

while test $n -le $maxn
do
    echo $n > batch/$batch.checkpoint
    if $needmmake
    then
        cp batch/$batch.MMAKE Mmake.stage.params
    else
        cat < /dev/null > Mmake.stage.params
    fi

    mcflags=`awk "NR == $n" batch/$batch.MCFLAGS`
    echo "EXTRA_MCFLAGS = $mcflags" >> Mmake.stage.params

    if $needcflags
    then
        cflags=`awk "NR == $n" batch/$batch.CFLAGS`
        echo "EXTRA_CFLAGS = $cflags" >> Mmake.stage.params
    fi

    if $needmgnucflags
    then
        mgnucflags=`awk "NR == $n" batch/$batch.MGNUCFLAGS`
        echo "EXTRA_MGNUCFLAGS = $mgnucflags" >> Mmake.stage.params
    fi

    if $needmlflags
    then
        mlflags=`awk "NR == $n" batch/$batch.MLFLAGS`
        echo "EXTRA_MLFLAGS = $mlflags" >> Mmake.stage.params
    fi

    if test -f batch/$batch.MMAKE.$n
    then
        cat batch/$batch.MMAKE.$n >> Mmake.stage.params
    fi

    if $needgrade
    then
        grade=`awk "NR == $n" batch/$batch.GRADE`
        gradeopt="--grade $grade"
    else
        gradeopt=""
    fi

    if test $n -lt 10
    then
        visn="0$n"
    else
        visn="$n"
    fi

    cp Mmake.stage.params batch/$batch.params.$visn
    if $needgrade
    then
        echo "GRADE = $grade" >> batch/$batch.params.$visn
    fi

    echo starting bootcheck of version $visn
    succeeded=false
    created_compiler=false
    if tools/bootcheck $gradeopt --copy-runtime $jfactor $runtests \
        $objects $compile_times $stop_after_stage_2 $test_params \
        > batch/$batch.out.$visn 2>&1
    then
        succeeded=true
        created_compiler=true
        echo bootcheck of version $visn succeeded
        cp stage2/compiler/mercury_compile batch/$batch.mercury_compile.$visn
        size batch/$batch.mercury_compile.$visn | tail -1 | \
            sed -e 's/mercury_compile.//' | sed -e 's/batch\///' \
            >> batch/$batch.sizes
        /bin/rm -f batch/$batch.mercury_compile.$visn.gz > /dev/null 2>&1
        gzip batch/$batch.mercury_compile.$visn
    elif test "$failed" = "stop"
    then
        echo bootcheck of version $visn failed
        exit 1
    else
        if test -x stage2/compiler/mercury_compile
        then
            created_compiler=true
            echo bootcheck of version $visn failed but produced compiler
            cp stage2/compiler/mercury_compile \
                batch/$batch.mercury_compile.$visn
            size batch/$batch.mercury_compile.$visn | tail -1 | \
                sed -e 's/mercury_compile.//' | sed -e 's/batch\///' \
                >> batch/$batch.sizes
            /bin/rm -f batch/$batch.mercury_compile.$visn.gz > /dev/null 2>&1
            gzip batch/$batch.mercury_compile.$visn
        else
            echo bootcheck of version $visn failed and did not produce compiler
        fi
    fi

    if test "$objects" = "-k" -a "$save_stage2" = "false"
    then
        echo saving object files
        mkdir -p batch/objs/$batch.library.$visn
        /bin/rm -fr batch/objs/$batch.library.$visn/*
        cp stage2/library/*.o batch/objs/$batch.library.$visn
        gzip batch/objs/$batch.library.$visn/*
        mkdir -p batch/objs/$batch.compiler.$visn
        /bin/rm -fr batch/objs/$batch.compiler.$visn/*
        cp stage2/compiler/*.o batch/objs/$batch.compiler.$visn
        gzip batch/objs/$batch.compiler.$visn/*
    fi

    if "$cfiles"
    then
        echo saving c files
        mkdir -p batch/cfiles/$batch.library.$visn
        /bin/rm -fr batch/cfiles/$batch.library.$visn/* > /dev/null
        gzip stage2/library/*.c > /dev/null
        cp stage2/library/*.c.gz batch/cfiles/$batch.library.$visn > /dev/null
        mkdir -p batch/cfiles/$batch.compiler.$visn
        /bin/rm -fr batch/cfiles/$batch.compiler.$visn/* > /dev/null
        gzip stage2/compiler/*.c > /dev/null
        cp stage2/compiler/*.c.gz batch/cfiles/$batch.compiler.$visn > /dev/null
    fi

    if "$errfiles"
    then
        echo saving err files
        mkdir -p batch/errfiles/$batch.library.$visn
        /bin/rm -fr batch/errfiles/$batch.library.$visn/*
        cp stage2/library/*.err batch/errfiles/$batch.library.$visn
        # gzip batch/errfiles/$batch.library.$visn/*
        mkdir -p batch/errfiles/$batch.compiler.$visn
        /bin/rm -fr batch/errfiles/$batch.compiler.$visn/*
        cp stage2/compiler/*.err batch/errfiles/$batch.compiler.$visn
        # gzip batch/errfiles/$batch.compiler.$visn/*
    fi

    if $save_stage2
    then
        # If a directory with this name already exists,
        # it probably came from a previous invocation of this script.
        # This invocation supersedes earlier ones.
        /bin/rm -fr stage2.batch.$visn > /dev/null
        mv stage2 stage2.batch.$visn
    elif $save_stage2_on_error && test $succeeded = false
    then
        /bin/rm -fr stage2.batch.$visn > /dev/null
        mv stage2 stage2.batch.$visn
    elif $save_stage2_on_no_compiler && test $created_compiler = false
    then
        /bin/rm -fr stage2.batch.$visn > /dev/null
        mv stage2 stage2.batch.$visn
    fi

    n=`expr $n + 1`
done

/bin/rm -f batch/$batch.checkpoint

if test -f Mmake.stage.params.$$
then
    echo moving Mmake.stage.params.$$ to Mmake.stage.params
    mv Mmake.stage.params.$$ Mmake.stage.params
fi

exit 0
