#!/bin/sh
#BHEADER***********************************************************************
# (c) 2000   The Regents of the University of California
#
# See the file COPYRIGHT_and_DISCLAIMER for a complete copyright
# notice, contact person, and disclaimer.
#
# $Revision: 2.11 $
#EHEADER***********************************************************************

#=============================================================================
# Create a few temporary variables, and assign default values to any
# unexported environment variables.
#=============================================================================
initialize_variables ()
{
  seconds; TOTAL=$SECS
  OldMask=`umask`
  umask 007
  Hdr="autotest"
  Skip=0
  Build=1
  Run=2
  PurifytoFile="--with-purify-to-file"
  if [ -z "$MAKE" -o "$MAKE" = "" ] ; then
    MAKE="make -i"
  fi
#
# Assume that we are started from autotest and have done 
# a "cd ${HYPRE_AUTOTEST_DIR}", however as long as we are
# above a "linear_solvers" directory we should be ok.
#
  if test ! "${HYPRE_AUTOTEST_DIR}" ; then
    HYPRE_AUTOTEST_DIR=`pwd`
  else			# assume we're executing from autotest
    if [ ! -d ${HYPRE_AUTOTEST_DIR} ] ; then
      if [ ! -d ./linear_solvers ] ; then
        echo "$0: no HYPRE_AUTOTEST_DIR environment variable"
        exit 2
      fi
    fi
  fi
  if [ -d ${HYPRE_AUTOTEST_DIR}/linear_solvers/test ] ; then
    SRC=linear_solvers
  fi
  if [ -d ${HYPRE_AUTOTEST_DIR}/src/test ] ; then
    SRC=src
  fi
  StdBuildDir=${HYPRE_AUTOTEST_DIR}/${SRC}
  StdTestDir=${HYPRE_AUTOTEST_DIR}/${SRC}/test
#
# Define HYPRE_ARCH
#
  . $StdTestDir/hypre_arch.sh
  if [ -r $StdTestDir/env.${HYPRE_ARCH} ] ; then
    . $StdTestDir/env.${HYPRE_ARCH}
  fi
#
# If NOT started by autotest (hence no HYPRE_*_EMAIL variable
# defined) default mail to UID only.
#
  if test ! "$HYPRE_MAIL" ; then
    [ -x /usr/bin/Mail ] && HYPRE_MAIL=/usr/bin/Mail
    [ -x /usr/bin/mailx ] && HYPRE_MAIL=/usr/bin/mailx
    [ -x /usr/sbin/mailx ] && HYPRE_MAIL=/usr/sbin/mailx
  fi
  if test ! "${HYPRE_DEFAULT_EMAIL}" ; then
    if test ! "${USER}" ; then
      USER=`who am I|cut -f 1 -d \ `
    fi
    HYPRE_DEFAULT_EMAIL=${HYPRE_DEFAULT_EMAIL:=$USER}
    HYPRE_CHECKOUT_EMAIL=${HYPRE_CHECKOUT_EMAIL:=$USER}
    HYPRE_CONFIGURE_EMAIL=${HYPRE_CONFIGURE_EMAIL:=$USER}
    HYPRE_STRUCT_EMAIL=${HYPRE_STRUCT_EMAIL:=$USER}
    HYPRE_IJ_EMAIL=${HYPRE_IJ_EMAIL:=$USER}
    HYPRE_FEI_EMAIL=${HYPRE_FEI_EMAIL:=$USER}
    HYPRE_ALL_EMAIL=${HYPRE_ALL_EMAIL:=$USER}
  fi
}

#=============================================================================
# Function for parsing of input arguments
#=============================================================================

parse_arguments () { 
#
# The getopts follows posix.2, if sh is a posix shell as
# (as required by posix.2) then getopts is a built-in.
# If sh is a non posix.2 or a early Bourne shell (that
# probably implement the obsolute getopt) then
# getopts(1) will be used.
#
  while getopts :a:b:cDdfhmno:p:q:r:st:xy arg
  do
    argcur=$arg
    case $arg in
      a) confbuildtest $OPTARG  " "             "default"   1 1 1 1 1 1 1;;
      b) confbuildtest $OPTARG  " "             "beta"      0 0 0 0 0 1 1;;
      c) build $Build "all++"   "all++"         "test";;
      D) DEBUG_MODE="yes";;
      d) build $Build " "       "docs"          "docs";;
      f) build $Build "all77"   "all77"         "test";;
      h) usage; exit 2;;
      m) HYPRE_SEND_MAIL="no"; MailOpt="";;
     +m) HYPRE_SEND_MAIL="yes"; MailOpt="-mail";;
      n) confbuildtest $Build   "--without-MPI" "no_mpi"    1 0 1 1 1 1 0;;
      o) confbuildtest $OPTARG  "--with-openmp" "openmp"    0 0 0 0 0 1 0;;
      p) confbuildtest $OPTARG  "--with-petac"  "petac"     0 0 0 0 1 0 0;;
      q) confbuildtest $OPTARG  "--with-purify-to-file" \
                                                "purify"    0 0 0 0 1 0 1;;
     +q) confbuildtest $OPTARG  "--with-purify" "purify"    0 0 0 0 1 0 1;;
      r) HYPRE_RUN_MACHINE=$OPTARG;;
      s) confbuildtest $Build   "--with-strict-checking" \
                                         "strict_checking"  1 1 1 1 1 1 0;;
      t) confbuildtest $OPTARG "--with-pthreads" "pthreads" 0 0 1 0 0 0 0;;
      x) build $Build   "beta++" "beta++" "test";;
      y) build $Build   "beta77" "beta77" "test";;
      :) echo "$0: \"$argcur\" requires a value"; exit 2;;
     \?) echo "$0: INVALID option \"$argcur\" at $OPTIND"; exit 2;;
    esac
  done
  shift `expr $OPTIND - 1`
  #printf "Remaining arguments are: %s\n" "$*"
}

#=============================================================================
# Function for display of help/usage
#=============================================================================
usage () {
  printf "Usage: %s [-cdfhmns] [-a opt] [-b opt]\n" $0
  printf "       [-o opt] [-p opt] [-r host] [-t opt]\n"
  printf "\n"
  printf "Hypre autotest (Note: all options are positional dependent\n"
  printf "i.e., options are sequentially executed in left-to-right order).\n"
  printf "\n"
  printf "Options for the "opt" argument are "0", "1", or "2" where:\n"
  printf "  0=skip (ignore this test),\n"
  printf "  1=configure and make, and\n"
  printf "  2=configure, make and run.\n"
  printf "\n"
  printf "-a opt   All; the (default) configure, make, and execute. Also\n"
  printf "         performs make struct, IJ, fei, all, beta, nofei, and\n"
  printf "         fei++, followed by the test_drivers script (when opt=2).\n"
  printf "-b opt   Beta; perform the (default) configure, make beta, nofei,\n"
  printf "         fei++, followed by the test_drivers script (when opt=2).\n"
  printf "-c       C++; make all++ (no configure, or execute).\n"
  printf "-d       Docs; make the documentation directory.\n"
  printf "-f       F77; make all77 (no configure, or execute).\n"
  printf "-h       Help; display this help message.\n"
  printf "-m       Mail; mail error summary to developers.\n"
  printf "+m       Mail+; mail error logs to developers.\n"
  printf "-n       NoMPI; configure --without-MPI, make struct, IJ,\n"
  printf "         all, and beta (no execute option).\n"
  printf "-o opt   openMP; configure --with-openmp, make beta.\n"
  printf "-p opt   PETSc; perform configure --with-petsc, make all.\n"
  printf "-q opt   Purify; perform configure --with-purify-to-file. Output \n"
  printf "         is appended to a file called purify.log.\n"
  printf "+q opt   Purify; no file output option (interactive).\n"
  printf "-r host  Remote; remote exection is performed on "host".\n"
  printf "-s       Strict; configure --with-strict-checking,\n"
  printf "         followed by make struct, IJ, all, beta(no execute option).\n"
  printf "-t opt   Thread; perform configure --with-pthreads, make struct.\n"
  printf "-x       BetaC++; make beta++ (no configure, or execute).\n"
  printf "-y       BetaF77; make beta77 (no configure, or execute).\n"
}

#=============================================================================
# Function for mailing error messages
#=============================================================================

mail_summary () {
  echo "Autotest mailing error summary"
  CTOTCNT=0; ETOTCNT=0
  CLOGCNT=0; ELOGCNT=0
  CERRCNT=0; EERRCNT=0; TOTCNT=0
  CLIST=""; ELIST=""
  cd $HYPRE_AUTOTEST_DIR
  SUMFILE="autotest.$HYPRE_ARCH.`date '+%Y%m%d'`"
  if [ -z "$HYPRE_COMPILE_MACHINE" -o "$HYPRE_COMPILE_MACHINE" = "" ] ; then
    HYPRE_COMPILE_MACHINE=`hostname`
  fi
  if [ -z "$HYPRE_RUN_MACHINE" -o "$HYPRE_RUN_MACHINE" = "" ] ; then
    HYPRE_RUN_MACHINE=`hostname`
  fi
  printf "%s\n" "--------------------------------------------" > $SUMFILE
  printf "Autotest error summary for `date`\n" >> $SUMFILE
  printf "Target architecure: %s\n" $HYPRE_ARCH >> $SUMFILE
  printf "Compile machine:    %s\n" $HYPRE_COMPILE_MACHINE >> $SUMFILE
  printf "Execute machine:    %s\n" $HYPRE_RUN_MACHINE >> $SUMFILE
  printf "Directory:          %s\n" ${HYPRE_AUTOTEST_DIR} >> $SUMFILE
  printf "%s\n" "--------------------------------------------" >> $SUMFILE
  printf "Compile summary:\n" >> $SUMFILE
  for ConfOpt in default beta no_mpi openmp petac \
           pthreads purify strict_checking \
           docs all++ all77 beta++ beta77
  do
    printf "%-15s: " $ConfOpt >> $SUMFILE
    COLFLG=0; COLCNT=0;
    for MakeOpt in ""  all beta configure IJ fei++ \
           fei nofei sstruct struct
    do
      FILE=autotest.$ConfOpt.$MakeOpt
      LFILE=`echo $FILE|sed -e 's/\.$//'`.log
      for i in $LFILE ${SRC}/${LFILE} \
               ${SRC}/test/${LFILE} ${SRC}/docs/${LFILE} 
      do
        if [ -r "${i}" ] ; then
          CTOTCNT=`expr $CTOTCNT + 1`
          EFILE=`echo $i|sed -e 's/log$//'`err
          if [ -s "${EFILE}" ] ; then
            TOTCNT=`expr $TOTCNT + 1`
            CERRCNT=`expr $CERRCNT + 1`
            COLCNT=`expr $COLCNT + 1`
            CLIST="${CLIST}${EFILE}\n"
          else
            CLOGCNT=`expr $CLOGCNT + 1`
            COLFLG=`expr $COLFLG + 1`
          fi
        fi
      done
    done
    if [ "$COLCNT" != "0" ] ; then
      printf "Failed\n" >> $SUMFILE
    elif [ "$COLFLG" != "0" ] ; then
      printf "Passed\n" >> $SUMFILE
    else
      printf "N/A\n" >> $SUMFILE
    fi
  done
  printf "\n" >> $SUMFILE
  printf "%2d test failed\n" $CERRCNT  >> $SUMFILE
  printf "%2d test succeeded\n" $CLOGCNT >> $SUMFILE
  printf "%2d test total\n" $CTOTCNT >> $SUMFILE
  if [ "$CLIST" != "" ] ; then
    printf "non zero error log file(s):\n" >> $SUMFILE
    printf "${CLIST}" >> $SUMFILE
  fi
  printf "%s\n" "--------------------------------------------" >> $SUMFILE
  printf "Execute summary:\n" >> $SUMFILE
  for i in IJ fei sstruct struct ; do
    LFILE=${SRC}/test/${i}_linear_solvers.log
    if [ -r "${LFILE}" ] ; then
      printf "%-15s: " $i >> $SUMFILE
      COLFLG=0; COLCNT=0;
      ETOTCNT=`expr $ETOTCNT + 1`
      EFILE=${SRC}/test/${i}_linear_solvers.err
      if [ -s "${EFILE}" ] ; then
        TOTCNT=`expr $TOTCNT + 1`
        EERRCNT=`expr $EERRCNT + 1`
        COLCNT=`expr $COLCNT + 1`
        ELIST="${ELIST}${EFILE}\n"
      else
        ELOGCNT=`expr $ELOGCNT + 1`
        COLFLG=`expr $COLFLG + 1`
      fi
      if [ "$COLCNT" != "0" ] ; then
        printf "Failed\n" >> $SUMFILE
      elif [ "$COLFLG" != "0" ] ; then
        printf "Passed\n" >> $SUMFILE
      else
        printf "N/A\n" >> $SUMFILE
      fi
    fi
  done
  printf "\n" >> $SUMFILE
  printf "%2d test failed\n" $EERRCNT >> $SUMFILE
  printf "%2d test succeeded\n" $ELOGCNT >> $SUMFILE
  printf "%2d test total\n" $ETOTCNT >> $SUMFILE
  if [ "$ELIST" != "" ] ; then
    printf "non zero error log file(s):\n" >> $SUMFILE
    printf "${ELIST}" >> $SUMFILE
  fi
  printf "%s\n" "--------------------------------------------" >> $SUMFILE
  if [ "$TOTCNT" = "0" ] ; then
    SUBJECT="Autotest NO Errors ($HYPRE_ARCH)"
  else
    SUBJECT="Autotest $TOTCNT Errors ($HYPRE_ARCH)"
  fi
  if [ "$DEBUG_MODE" = "yes" ] ; then
    ${HYPRE_MAIL} -s "$SUBJECT" $USER < $SUMFILE 
  else
    ${HYPRE_MAIL} -s "$SUBJECT" $HYPRE_ALL_EMAIL < $SUMFILE 
  fi
  echo "Autotest mail sent"
}

mail_errors () { 
  if [ "$HYPRE_SEND_MAIL" = "yes" ] ; then
    echo "Autotest mailing error messages"
    cd $HYPRE_AUTOTEST_DIR
    for i in *.err \
        ${SRC}/*.err \
        ${SRC}/test/*.err \
        ${SRC}/docs/*.err
    do 
      if [ -s "$i" ] ; then 
        if [ -r "${i}.email" ] ; then
          RECIPIENTS=`cat ${i}.email` 
          SUBJECT="Autotest error: ${i} ($HYPRE_ARCH)"
          if [ "$DEBUG_MODE" = "yes" ] ; then
            ${HYPRE_MAIL} -s "$SUBJECT" $USER < $i 
          else
            ${HYPRE_MAIL} -s "$SUBJECT" $RECIPIENTS < $i 
          fi
        fi
      fi 
    done 
    echo "Autotest mail sent"
  else
    mail_summary 
  fi
}

cleanup () { 
  umask $OldMask
  seconds; TOTAL=`expr $SECS - $TOTAL`
  echo "Autotest finished leaving $* after $TOTAL seconds"
}
#=============================================================================
# General purpose make function /w strict_checking error output redirection
#=============================================================================

makeit ()
{
MakeStr=$1	 MessageStr=$2
MailGroup=$3
if [ "$MessageStr" = "purify" ]
then				# don't need extra purify status messages
  $MAKE $MakeStr 1> ${Hdr}.${MessageStr}.${MakeStr}.log 2>&1
else
  $MAKE $MakeStr 1> ${Hdr}.${MessageStr}.${MakeStr}.log \
        2> ${Hdr}.${MessageStr}.${MakeStr}.err
fi
echo "$MailGroup" > ${Hdr}.${MessageStr}.${MakeStr}.err.email
}
#=============================================================================
# General purpose function for configure, make and execute
#=============================================================================

confbuildtest () 
{
BuildOpt=$1	 ConfigOption=$2  MessageStr=$3
IJOpt=$4	 FeiOpt=$5	  StructOpt=$6
SstructOpt=$7	 MakeOpt=$8	  BetaOpt=$9
shift
NoFeiOpt=$9
if [ ${BuildOpt} -ne $Skip ] ; then
  seconds; TIME=$SECS
  echo "Autotest starting configure and make of $MessageStr"
  if [ ${BuildOpt} -eq $Build -o ${BuildOpt} -eq $Run ] ; then
    cd $StdBuildDir
    ./configure "$ConfigOption" 1> ${Hdr}.${MessageStr}.configure.log \
	2> ${Hdr}.${MessageStr}.configure.err
    echo "$HYPRE_CONFIGURE_EMAIL" > ${Hdr}.${MessageStr}.configure.err.email

    $MAKE veryclean

    if [ $IJOpt -ne $Skip ] ; then
      makeit "IJ" $MessageStr "$HYPRE_IJ_EMAIL"
    fi

    if [ $FeiOpt -ne $Skip ] ; then
      makeit "fei" $MessageStr "$HYPRE_FEI_EMAIL"
    fi

    if [ $StructOpt -ne $Skip ] ; then
      makeit "struct" $MessageStr "$HYPRE_STRUCT_EMAIL"
    fi

    if [ $SstructOpt -ne $Skip ] ; then
      makeit "sstruct" $MessageStr "$HYPRE_STRUCT_EMAIL"
    fi

    if [ $MakeOpt -ne $Skip ] ; then
      makeit "all" $MessageStr "$HYPRE_DEFAULT_EMAIL"
    fi

    if [ $BetaOpt -ne $Skip ] ; then
      makeit "beta" $MessageStr "$HYPRE_DEFAULT_EMAIL"
    fi
  fi
  if [ ${BuildOpt} -eq $Run ] ; then
    echo "Autotest starting execution of $MessageStr"
    if [ $NoFeiOpt -ne $Skip ] ; then
      makeit "nofei" $MessageStr "$HYPRE_FEI_EMAIL"
      cd ${HYPRE_AUTOTEST_DIR}/${SRC}/test
      makeit "fei++" $MessageStr "$HYPRE_FEI_EMAIL"
    fi
    if test ! "${HYPRE_RUN_MACHINE}" ; then
      cd $HYPRE_AUTOTEST_DIR/${SRC}/test
      ./test_drivers.sh $MailOpt
    else
      ssh ${HYPRE_RUN_MACHINE} "\
      (\
        cd ${HYPRE_AUTOTEST_DIR}/${SRC}/test;\
        [ -r ./env.${HYPRE_ARCH} ] && . ./env.${HYPRE_ARCH};\
        ./test_drivers.sh $MailOpt\
    )"
    fi
  fi
  seconds; TIME=`expr $SECS - $TIME`
  echo "Autotest finished $MessageStr taking $TIME seconds"
fi
}
#=============================================================================
# General purpose make function
#=============================================================================

build () 
{
BuildOpt=$1	 MakeOption=$2	 MessageStr=$3	MakeDir=$4
if [ $BuildOpt -ne $Skip ]
then
  seconds; TIME=$SECS
  echo "Autotest starting make of $MessageStr"
  cd $StdBuildDir/$MakeDir
  if [ -r ./Makefile ] ; then
    cd $StdBuildDir
    ./configure 1> ${Hdr}.${MessageStr}.configure.log \
	2> ${Hdr}.${MessageStr}.configure.err
    cd $StdBuildDir/$MakeDir
  fi
  $MAKE $MakeOption 1> ${Hdr}.${MessageStr}.log \
	2> ${Hdr}.${MessageStr}.err
  echo "$HYPRE_ALL_EMAIL" > ${Hdr}.${MessageStr}.err.email
  seconds; TIME=`expr $SECS - $TIME`
  echo "Autotest finished $MessageStr taking $TIME seconds"
fi
}

#==============================================================================
# return the seconds since midnight in the variable SECS
#==============================================================================

seconds ()
{
HOUR=`date '+%H'`
HOUR=`expr $HOUR \* 3600`
MINS=`date '+%M'`
MINS=`expr $MINS \* 60`
SECS=`date '+%S'`
SECS=`expr $SECS + $MINS`
SECS=`expr $SECS + $HOUR`
}

#==============================================================================
# This script is the implementation script used to regression test hypre.
#==============================================================================

initialize_variables
parse_arguments $*
mail_errors
cleanup
