# The Evaluator -- Shell Function Library
-# (c) 2001--2004 Martin Mares <mj@ucw.cz>
+# (c) 2001--2007 Martin Mares <mj@ucw.cz>
# General settings
shopt -s dotglob
exit 1
}
+function try-ln
+{
+ ln $1 $2 2>/dev/null || cp $1 $2
+}
+
# Sandbox subroutines
function box-init
pend "OK"
}
-# Locating source file in SDIR, pass name in SRCN (without path) and extension in SRCEXT
+# Locate source file.
+# If no parameter is given, locate it in SDIR and return name as SRCN and extension as SRCEXT
+# Or a file name can be given and then SDIR, SRCN and SRCEXT are set.
+# Beware, SDIR and SRCN can contain spaces and other strange user-supplied characters.
function locate-source
{
pstart "Finding source... "
- SBASE=${1:-$PROBLEM}
+ local SBASE
+ if [ -n "$1" ] ; then
+ SDIR=`dirname "$1"`
+ local S=`basename "$1"`
+ SBASE=$(echo "$S" | sed 's/\.\([^.]\+\)//')
+ SRCEXT=$(echo "$S" | sed '/\./!d; s/.*\.\([^.]\+\)/\1/')
+ if [ -n "$SRCEXT" ] ; then
+ # Full name given, so just check the extension and existence
+ SRCN="$S"
+ [ -f "$SDIR/$SRCN" ] || die "Cannot find source file $SDIR/$SRCN"
+ SRCEXT_OK=
+ for a in $EXTENSIONS ; do
+ if [ $a == $SRCEXT ] ; then
+ pend $SDIR/$SRCN
+ echo "Explicitly set source file: $SDIR/$SRCN"
+ return 0
+ fi
+ done
+ die "Unknown extension .$SRCEXT"
+ fi
+ else
+ SBASE=$PROBLEM
+ fi
for a in $EXTENSIONS ; do
- if [ -f $SDIR/$SBASE.$a ] ; then
+ if [ -f "$SDIR/$SBASE.$a" ] ; then
[ -z "$SRCN" ] || die "Multiple source files found: $SDIR/$PROBLEM.$a and $SDIR/$SRCN. Please fix."
- SRCN=$SBASE.$a
+ SRCN="$SBASE.$a"
SRCEXT=$a
fi
done
function compile
{
pstart "Compiling... "
- cp -a $SDIR/$SRCN $TDIR/$SRCN
+ # Beware, the original SRCN can be a strange user-supplied name
+ SRC=$PROBLEM.$SRCEXT
+ cp "$SDIR/$SRCN" $TDIR/$SRC
if [ -n "$COMP_EXTRAS" ] ; then
echo "Extras: $COMP_EXTRAS"
for a in $COMP_EXTRAS ; do cp $PDIR/$a $TDIR/ ; done
fi
box-clean
- for a in $SRCN $COMP_EXTRAS ; do cp $TDIR/$a $BOXDIR/ ; done
- SRC=$SRCN
+ for a in $SRC $COMP_EXTRAS ; do cp $TDIR/$a $BOXDIR/ ; done
EXE=$PROBLEM
CCMD=COMP_$SRCEXT
CCMD=`eval echo ${!CCMD}`
P=`cat $TDIR/$TEST.pts`
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
+ N="Runtime error $RE"
+ case "$RE" in
+ 200) M="$N: Division by zero" ;;
+ 201) M="$N: Range check error" ;;
+ 202) M="$N: Stack overflow" ;;
+ 203) M="$N: Heap overflow" ;;
+ 205) M="$N: Floating point overflow" ;;
+ 215) M="$N: Arithmetic overflow" ;;
+ 216) M="$N: Segmentation fault" ;;
+ ???) M="$N" ;;
+ esac
+ fi
+
echo "Verdict: $M"
echo "Points: $P"
test-verdict $P "$M"
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=
OUT_TYPE=${OUT_TYPE:-$IO_TYPE}
case $IN_TYPE in
file) echo "Input file: $PROBLEM.in (from $PDIR/$TEST.in)"
- ln $PDIR/$TEST.in $TDIR/$TEST.in
+ try-ln $PDIR/$TEST.in $TDIR/$TEST.in
cp $PDIR/$TEST.in $BOXDIR/$PROBLEM.in
- BOX_EXTRAS="$BOX_EXTRAS -i/dev/null"
+ [ $TASK_TYPE == interactive ] || BOX_EXTRAS="$BOX_EXTRAS -i/dev/null"
;;
stdio) echo "Input file: <stdin> (from $PDIR/$TEST.in)"
- ln $PDIR/$TEST.in $TDIR/$TEST.in
+ try-ln $PDIR/$TEST.in $TDIR/$TEST.in
cp $PDIR/$TEST.in $BOXDIR/.stdin
BOX_EXTRAS="$BOX_EXTRAS -i.stdin"
;;
*) die "Unknown IN_TYPE $IN_TYPE"
;;
esac
+ if [ -n "$EV_PEDANT" -a $IN_TYPE != none ] ; then
+ pcont "<pedant> "
+ bin/pedant <$TDIR/$TEST.in | tr '\n' ' ' >&2
+ fi
case $OUT_TYPE in
file) echo "Output file: $PROBLEM.out"
- BOX_EXTRAS="$BOX_EXTRAS -o/dev/null"
+ [ $TASK_TYPE == interactive ] || BOX_EXTRAS="$BOX_EXTRAS -o/dev/null"
;;
stdio) echo "Output file: <stdout>"
BOX_EXTRAS="$BOX_EXTRAS -o.stdout"
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
echo "Interactive checker: $ICCMD"
if ! $HDIR/bin/iwrapper $BOXCMD $BOXOPTS -- ./$PROBLEM @@ $ICCMD 2>$TMPDIR/exec.out ; then
cat $TMPDIR/exec.out
- MSG="`tail -1 $TMPDIR/exec.out`"
+ MSG="`head -1 $TMPDIR/exec.out`"
test-result 0 "$MSG"
fi
cat $TMPDIR/exec.out
test-epilog
}
+# "Running" of open-data problems
+
+function test-run-open-data
+{
+ [ -f $SDIR/$TEST.out ] || test-result 0 "No solution"
+ ln $SDIR/$TEST.out $TDIR/$TEST.out
+}
+
# Syntax checks
function syntax-check
{
[ -n "$SYNTAX_CHECK" ] || return 0
+ [ -z "$EV_NOCHECK" ] || return 0
pcont "<syntax> "
SCHECK=`eval echo $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
function output-check
{
- [ -n "$OUTPUT_CHECK" ] || return 0
- pcont "<check> "
- [ -f $PDIR/$TEST.out ] && ln $PDIR/$TEST.out $TDIR/$TEST.ok
- OCHECK=`eval echo $OUTPUT_CHECK`
- echo "Output check command: $OCHECK"
- if ! eval $OCHECK 2>$TMPDIR/exec.out ; then
+ MSG=
+ 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`
+ 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
+ test-result 0 "$MSG"
+ fi
cat $TMPDIR/exec.out
MSG=`tail -1 $TMPDIR/exec.out`
- if [ -z "$MSG" ] ; then MSG="Wrong answer." ; fi
- test-result 0 "$MSG"
fi
- cat $TMPDIR/exec.out
- MSG=`tail -1 $TMPDIR/exec.out`
if [ -z "$MSG" ] ; then MSG="OK" ; fi
test-result $POINTS_PER_TEST "$MSG"
}
function public-setup
{
- HDIR=$MO_PUBLIC
- PDIR=$MO_PUBLIC/problems/$PROBLEM
+ HDIR=$MO_ROOT
+ PDIR=$MO_ROOT/problems/$PROBLEM
SDIR=.
TDIR=~/.test
TMPDIR=~/.test
BOXDIR=~/.box
mkdir -p $BOXDIR
rm -rf $BOXDIR/*
- BOXCMD="$MO_PUBLIC/bin/box -c$BOXDIR"
- exec >log
- pend "OK (see 'log' for details)"
+ BOXCMD="$MO_ROOT/bin/box -c$BOXDIR"
+ exec >check-log
+ pend "OK (see 'check-log' for details)"
}
# Locate output of open data problem, test case TEST
+# Beware, SDIR and SRCN can contain spaces and other strange user-supplied characters.
function open-locate
{
[ -f $PDIR/$TEST.in ] || die "Unknown test $TEST"
- SRCN=$SDIR/$PROBLEM$TEST.out
- [ -f $SRCN ] || fatal "Output file $SRCN not found"
+ if [ -n "$1" ] ; then
+ SDIR=`dirname "$1"`
+ SRCN=`basename "$1"`
+ else
+ SRCN=$SDIR/$PROBLEM$TEST.out
+ fi
+ [ -f "$SDIR/$SRCN" ] || fatal "Output file $SRCN not found"
}