#!/bin/sh

FILE="$1"
test="${FILE%.*}"
ext="${FILE##*.}"
case $ext in
    ctst) log=clog; out=cout; ref=cref; ;;
    *)    log=log;  out=out; ref=ref; ;;
esac
dir=`echo $PWD | sed "s:$BASILISK_WIKI/::"`

case $CC in
    *-D_MPI=*) test -z "$EXEC" && EXEC="mpirun -np "`echo $CC | sed 's/.*-D_MPI=\([0-9]*\).*/\1/'`;
esac

for opt in $CFLAGS; do
    case $opt in
	-catch) test -z "$EXEC" && EXEC=" "; # turn off gdb
    esac
done

script()
{
    rm -f $test.c
    if test -f fail; then
	return 1
    fi
    cat warn
    test -s warn || rm -f warn

    pass=true
    rm -f log-* stencil stencil-* fine fine-* coarse coarse-*
    if test -n "$EXEC" -o -z "`which gdb`"; then
	if ! $EXEC ./$test 2> $log > $out; then
	    pass=false
	    if test "$EXEC" = " " -a -f core -a -n "`which gdb`"; then
		cat $log
		xterm -e "gnuplot plot -" &
		gdb -q ./$test core
	    fi
	fi
    else
	if ! gdb -batch -return-child-result -ex "run 2> $log > $out" ./$test > gdb.log 2> gdb.err; then
	    pass=false
	    awk '
     {
       if (NF > 0)
         a[nb++] = $0;
     }
     / at .*:[0-9]*$/ {
       for (i = 0; i < nb - 1; i++)
	 print $(NF) ":error: " a[i];
     }
     ' < gdb.log >> $log
	fi
	rm -f gdb.log
    fi

    if test -f log-1; then
	mv -f $log log-0
	cat log-* > $log
    fi
    
    if $pass; then
	if test -f $test.$ref; then
	    ref=$ref
	else
	    ref=ref
	fi
	if test -f $test.$ref; then
            echo diff $log $test.$ref > fail
            diff $log $test.$ref >> fail && rm -f fail
            rm -f $test.$ref
	fi
    else
	cp -f $log fail
    fi
    if test -f fail; then
	return 1
    fi
    touch pass
}

expirecache()
{
    rm -f $BASILISK_WIKI/cache/$dir/$test.c.page
}

# run locally
locally()
{
    echo \[$test.$ext\]
    qcc -autolink $CFLAGS -o $test/$test $test.c $LIBS -lm > $test/warn 2>&1 \
	|| mv -f $test/warn $test/fail
    cd $test
    script
    expirecache
    cd ..
}

# compile/run on a remote "sandbox"
remotely()
{
    rhost=$1
    autolink=`qcc -autolink -source $CFLAGS $test.c`
    chksum=`$GENSUM $test.s | cut -d' ' -f1`.$ext
    mkdir $test/$chksum
    mv -f _$test.c $test/$test.c
    cd $test
    cp -f $test.* $chksum 2> /dev/null || true
    rm -f $chksum/$test.c.page
    PCC="\$CC99"
    case "$CFLAGS" in
	*-cadna*) PCC="\$CADNACC" ;;
    esac
    PCFLAGS=`echo $CFLAGS | sed -e 's/-grid=[^-]*//' -e 's/-cadna//'`
    NCORES=`echo $EXEC | awk 'BEGIN{ np = 1 }{
      if ($1 == "mpirun") np = $3; }END{ print np;}'`
    cat <<EOF >$chksum/$test.sh
#!/bin/sh
$PCC $PCFLAGS -I\$HOME/include -o $test $test.c -L\$HOME/lib $LIBS $autolink -lm > warn 2>&1 || mv -f warn fail
rm -f $test.c
if ! test -f fail; then
  test -s warn || rm -f warn

  pass=true
  if test -n "$EXEC" -o -z "`which gdb`"; then
    if ! timeout 1h $EXEC ./$test 2> $log > $out; then
       pass=false
    fi
  else
    if ! timeout 1h gdb -batch -return-child-result -ex "run 2> $log > $out" ./$test > gdb.log 2> gdb.err; then
       pass=false
       awk '
       {
         if (NF > 0)
           a[nb++] = \$0;
       }
       / at .*:[0-9]*\$/ {
         for (i = 0; i < nb - 1; i++)
   	   print \$(NF) ":error: " a[i];
       }
       ' < gdb.log >> $log
    fi
    rm -f gdb.log
  fi

  if test -f log-1; then
      mv -f $log log-0
      cat log-* > $log
  fi

  if \$pass; then
    if test -f $test.$ref; then
      ref=$ref
    else
      ref=ref
    fi
    if test -f $test.\$ref; then
        echo diff $log $test.\$ref > fail
        diff $log $test.\$ref >> fail && rm -f fail
        rm -f $test.\$ref
    fi
  else
    cp -f $log fail
  fi
  if ! test -f fail; then
    touch pass
  fi
fi
rm -f $test $test.c $test.sh $test.*ref
tar czf \$HOME/$chksum.tgz *
rm -r -f \$HOME/$chksum
EOF
    tar czf $chksum.tgz $chksum
    rm -r -f $chksum

    if ! ( scp $chksum.tgz $rhost: && rm -f $chksum.tgz && \
	ssh $rhost bash -c "\"tar xmzf $chksum.tgz && cd $chksum && tsp -N \$(test \$(tsp -S) -le $NCORES && echo \$(tsp -S) || echo $NCORES) -n nice -19 sh $test.sh\" && sleep 0 && tsp -p && tsp -w" > tspid.$ext && \
	scp -q $rhost:$chksum.tgz $chksum.tgz && \
	ssh $rhost rm -r -f $chksum.tgz && \
	tar xmzf $chksum.tgz && \
	rm -f $chksum.tgz $test.c $test.*ref ) > /dev/null 2>> ssh.log;
    then
	cat ssh.log >> fail
    fi
    rm -f ssh.log

    if test -f fail; then
	mv -f ../$test.$ext fail.$ext
	echo
	echo \[$test.$ext\]
	cat fail
	if test -n "$MAINTAINER"; then
	    (
		echo Latest change:
		echo
		darcs changes --last=1
		echo
		if test -f ../$test.c.page; then
		    cat <<EOF
See http://basilisk.fr/$dir/$test.c
EOF
		else
		    cat fail
		fi 
	    ) | mail -s "basilisk: $test.$ext failed" $MAINTAINER
	fi
    fi
    cd ..
    # generate graphics
    if test -f $test.plot -o -f $test.plot.page; then
	if ! make $test/plot.png > $test/.tmp 2>&1; then
	    cat $test/.tmp >> warn
	fi
    fi
    cd $test
    if ! sh $BASILISK/gnuplot.sh > .tmp; then
	cat .tmp >> warn
    fi
    # Complete
    rm -f *pid.$ext .tmp
    expirecache
}

checksum()
{
    if grep $1 $2 | $CHECKSUM; then 
	return 0;
    else
	return 1;
    fi
}

# check sum for test.c
source_modified=false
if ! test -f $test.$ext || ! checksum $test.c $test.$ext; then
    source_modified=true
fi

# check sum for test.s
if test -f $test.$ext && checksum $test.s $test.$ext; then
    touch $test.$ext
    echo "make: '$test.$ext' is up to date."
    if test -n "$SANDBOX" && $source_modified; then
	rm -f $test/warn && make $test/plots
    fi
# check sum for test.s in fail.tst
elif ! test -f $test/fail.$ext || ! checksum $test.s $test/fail.$ext; then
    if test -n "$SANDBOX" -a -f $test/pid.$ext; then
	echo Killing `cat $test/pid.$ext`
	kill `cat $test/pid.$ext`
	ssh $SANDBOX kill `cat $test/tspid.$ext`
	rm -f $test/*pid.$ext
    fi

    rm -f $test.$ext $test/pass \
	$test/fail $test/fail.* $test/warn $test/plot.png $test/plots $test/core
    $GENSUM $test.c $test.s > $test.$ext
    expirecache

    mkdir -p $test && cp -f $test.c $test
    awk -f $BASILISK/gnuplot.awk < $test.c > $test/plots
    cp -f $test.* $test 2> /dev/null || true
    rm -f $test/*.[sd] $test/*.*tst $test/$test.c.page 2> /dev/null || true
    if test -d $BASILISK_WIKI/static -a -f $test.c.page; then
	if test ! -L $BASILISK_WIKI/static/$dir/$test; then
	    mkdir -p $BASILISK_WIKI/static/$dir
	    ln -s $PWD/$test $BASILISK_WIKI/static/$dir/$test
	fi
    fi

    if test -n "$SANDBOX"; then
        ( remotely $SANDBOX ) &
	echo $! > $test/pid.$ext
	sleep 1
    else
	locally
	rm -f $test/plots
    fi
fi

if test -f $test/fail; then
    cat $test/fail
    rm -f $test.$ext
    exit 1
elif test -f $test/pid.$ext; then
    echo \[$test.$ext on $SANDBOX \(`cat $test/pid.$ext`\)\]
    echo "  running..."
fi
