# The Evaluator -- Shell Function Library
-# (c) 2001--2007 Martin Mares <mj@ucw.cz>
+# (c) 2001--2008 Martin Mares <mj@ucw.cz>
# General settings
shopt -s dotglob
ln $1 $2 2>/dev/null || cp $1 $2
}
+# Expand occurrences of `$var' in a given variable
+
+function expand-var
+{
+ eval echo ${!1}
+}
+
+# Given a <prefix>, override each variable <x> by <prefix>_<x>
+
+function override-vars
+{
+ local OR V W
+ declare -a OR
+ # `${!${1}_@}' does not work, so we have to use eval
+ OR=($(eval echo '${!'$1'_@}'))
+ for V in "${OR[@]}" ; do
+ W=${V##$1_}
+ eval $W='"$'$V'"'
+ done
+}
+
# Sandbox subroutines
function box-init
if [ -z "$TEST_USER" -o "$TEST_USER" == $EVAL_USER ] ; then
pcont "running locally (INSECURE), "
TEST_USER=$EVAL_USER
- BOXDIR=box
+ BOXDIR=`pwd`/box
BOXCMD=bin/box
mkdir -p box
else
function compile
{
pstart "Compiling... "
+ override-vars "EXT_$SRCEXT"
# Beware, the original SRCN can be a strange user-supplied name
SRC=$PROBLEM.$SRCEXT
cp "$SDIR/$SRCN" $TDIR/$SRC
box-clean
for a in $SRC $COMP_EXTRAS ; do cp $TDIR/$a $BOXDIR/ ; done
EXE=$PROBLEM
- CCMD=COMP_$SRCEXT
- CCMD=`eval echo ${!CCMD}`
- COMP_SANDBOX_OPTS=`eval echo $COMP_SANDBOX_OPTS`
+ CCMD=$(expand-var COMP)
+ COMP_SANDBOX_OPTS=$(expand-var COMP_SANDBOX_OPTS)
echo "Compiler command: $CCMD"
echo "Compiler sandbox options: $COMP_SANDBOX_OPTS"
eval $COMP_SANDBOX_INIT
# Running of test program according to current task type (returns exit code and TEST_MSG)
+function test-config
+{
+ [ -f $PDIR/$TEST.config ] && . $PDIR/$TEST.config
+ override-vars "TEST_$TEST"
+}
+
function test-run
{
test-run-$TASK_TYPE
rm $TDIR/$TEST.pts
fi
+ # Translate signal numbers to readable strings
+ SG=${M#Caught fatal signal }
+ SG=${SG#Committed suicide by signal }
+ if [ "$SG" != "$M" ] ; then
+ SG=`perl -MConfig -e '@s=split / /,$Config{sig_name}; print $s[$ARGV[0]]' $SG`
+ [ -z "$SG" ] || M="$M (SIG$SG)"
+ fi
+
# Translate Free Pascal runtime errors to readable strings
RE=${M#Exited with error status }
if [ "$FREE_PASCAL_RTE" == 1 -a "$RE" != "$M" ] ; then
box-clean
echo "Executable file: $TDIR/$PROBLEM"
if [ ! -x $TDIR/$PROBLEM ] ; then
- test-result 0 "Compile error."
+ test-result 0 "Compile error"
fi
cp $TDIR/$PROBLEM $BOXDIR/
BOX_EXTRAS=
esac
if [ -n "$EV_PEDANT" -a $IN_TYPE != none ] ; then
pcont "<pedant> "
- bin/pedant <$TDIR/$TEST.in | tr '\n' ' ' >&2
+ if [ "$EV_PEDANT" = 1 ] ; then
+ EV_PEDANT=" "
+ fi
+ bin/pedant <$TDIR/$TEST.in >$TDIR/$TEST.pedant $EV_PEDANT
+ if [ -s $TDIR/$TEST.pedant ] ; then
+ pend
+ sed 's/^/\t/' <$TDIR/$TEST.pedant >&2
+ pstart -e '\t'
+ fi
fi
case $OUT_TYPE in
file) echo "Output file: $PROBLEM.out"
echo "Sandbox contents after exit:"
ls -Al $BOXDIR
case ${OUT_TYPE:-$IO_TYPE} in
- file) [ -f $BOXDIR/$PROBLEM.out ] || test-result 0 "No output file."
+ file) [ -f $BOXDIR/$PROBLEM.out ] || test-result 0 "No output file"
cp $BOXDIR/$PROBLEM.out $TDIR/$TEST.out
;;
- stdio) [ -f $BOXDIR/.stdout ] || test-result 0 "No output file."
+ stdio) [ -f $BOXDIR/.stdout ] || test-result 0 "No output file"
cp $BOXDIR/.stdout $TDIR/$TEST.out
;;
esac
+
+ if [ -n "$OUTPUT_FILTER" -a "$OUT_TYPE" != none -a -z "$EV_NOFILTER" ] ; then
+ pcont "<filter> "
+ FILTER=$(expand-var OUTPUT_FILTER)
+ echo "Output filter command: $FILTER"
+ mv $TDIR/$TEST.out $TDIR/$TEST.raw
+ if ! eval $FILTER 2>$TMPDIR/exec.out ; then
+ cat $TMPDIR/exec.out
+ MSG=`tail -1 $TMPDIR/exec.out`
+ if [ -z "$MSG" ] ; then MSG="Filter failed" ; fi
+ test-result 0 "$MSG"
+ fi
+ cat $TMPDIR/exec.out
+ fi
}
# Running of test program with file input/output
{
test-prolog
pcont "<run> "
- BOXOPTS="`eval echo $TEST_SANDBOX_OPTS`$BOX_EXTRAS"
+ BOXOPTS=$(expand-var TEST_SANDBOX_OPTS)
echo "Sandbox options: $BOXOPTS"
if ! $BOXCMD $BOXOPTS -- ./$PROBLEM 2>$TMPDIR/exec.out ; then
cat $TMPDIR/exec.out
{
test-prolog
pcont "<run> "
- BOXOPTS="`eval echo $TEST_SANDBOX_OPTS`$BOX_EXTRAS"
+ BOXOPTS=$(expand-var TEST_SANDBOX_OPTS)
echo "Sandbox options: $BOXOPTS"
- ICCMD=`eval echo $IA_CHECK`
+ ICCMD=$(expand-var IA_CHECK)
echo "Interactive checker: $ICCMD"
if ! $HDIR/bin/iwrapper $BOXCMD $BOXOPTS -- ./$PROBLEM @@ $ICCMD 2>$TMPDIR/exec.out ; then
cat $TMPDIR/exec.out
function test-run-open-data
{
- [ -f $SDIR/$TEST.out ] || test-result 0 "No solution."
+ [ -f $SDIR/$TEST.out ] || test-result 0 "No solution"
ln $SDIR/$TEST.out $TDIR/$TEST.out
}
[ -n "$SYNTAX_CHECK" ] || return 0
[ -z "$EV_NOCHECK" ] || return 0
pcont "<syntax> "
- SCHECK=`eval echo $SYNTAX_CHECK`
+ SCHECK=$(expand-var SYNTAX_CHECK)
echo "Syntax check command: $SCHECK"
if ! eval $SCHECK 2>$TMPDIR/exec.out ; then
cat $TMPDIR/exec.out
MSG=`tail -1 $TMPDIR/exec.out`
- if [ -z "$MSG" ] ; then MSG="Wrong syntax." ; fi
+ if [ -z "$MSG" ] ; then MSG="Wrong syntax" ; fi
test-result 0 "$MSG"
fi
cat $TMPDIR/exec.out
if [ -n "$OUTPUT_CHECK" -a "$OUT_TYPE" != none -a -z "$EV_NOCHECK" ] ; then
pcont "<check> "
[ -f $PDIR/$TEST.out ] && ln $PDIR/$TEST.out $TDIR/$TEST.ok
- OCHECK=`eval echo $OUTPUT_CHECK`
+ OCHECK=$(expand-var OUTPUT_CHECK)
echo "Output check command: $OCHECK"
if ! eval $OCHECK 2>$TMPDIR/exec.out ; then
cat $TMPDIR/exec.out
MSG=`tail -1 $TMPDIR/exec.out`
- if [ -z "$MSG" ] ; then MSG="Wrong answer." ; fi
+ if [ -z "$MSG" ] ; then MSG="Wrong answer" ; fi
test-result 0 "$MSG"
fi
cat $TMPDIR/exec.out