#!/bin/sh

# compile a Pascal file using p5c Pascal, then test with valgrind
#
# rv <-cpp> <file> <arg1> <arg2> ...
#
# <file> is the pascal filename without extention.
# <-cpp> optionally runs the c preprocessor
# <arg1> is a file that is bound to the first parameter in the program heading
# program is compiled if it doesn't exist or if source is newer than program
# use c preprocessor for conditional compilation, include, etc
# p5c compiler is in current directory or in env variable $P5CDIR
#

# show brief help if no pascal file specified on command line
if [ -z "$1" ]
then
   echo usage:
   echo $0 [-cpp] 'file arg1 arg2 ...'
   echo "where file is a pascal file, optionally without the extension (.pas or .p)"
   echo "test a pascal file with valgrind"
   echo "arg1, etc is file bound to pascal file variable"
   echo "run the c preprocessor if"
   echo "    - optional command line parameter -cpp is present on the command line"
   echo "    - one of the first 10 lines of the pascal file starts with a '#' char"
   exit 0
fi

test -z "$P5CDIR" && P5CDIR=.

if [ ! -x $P5CDIR/p5c ]
then
  echo "can't find p5c compiler, or it is not executable"  > /dev/stderr
  exit 1
fi

if [ "$1" == "-cpp" ]; then
  WITHCPP=1
  shift
else
  WITHCPP=0
fi

if [ -f $1 ] && [ "`basename $1 .pas`.pas" = "`basename $1`" ] ; then
    PASFILE=`dirname $1`/`basename $1 .pas`
    EXT=pas
elif [ -f $1 ] && [ `basename $1 .p`.p = "`basename $1`" ] ; then
    PASFILE=`dirname $1`/`basename $1 .p`
    EXT=p
elif [ -f $1 ] && [ `basename $1 .pp`.pp = "`basename $1`" ] ; then
    PASFILE=`dirname $1`/`basename $1 .pp`
    EXT=pp
elif [ -f $1.pas ] ; then
    PASFILE=$1
    EXT=pas
elif [ -f $1.p ] ; then
    PASFILE=$1
    EXT=p
elif [ -f $1.pp ] ; then
    PASFILE=$1
    EXT=pp
else
    echo "can't find $1 or $1.pas or $1.p or $1.pp"  > /dev/stderr
    exit 1
fi

if head --lines=10 $PASFILE.$EXT | grep -qe "^#" ; then
    WITHCPP=1
fi

echo
echo "valgrind test for $PASFILE ..."
echo
echo -n ".... this is likely to take quite a while ...."
echo
echo '{$n+,d- -- force line numbers, omit debug code }' > $PASFILE.1.$EXT
if [ $WITHCPP -ne 0 ]; then
    echo "NOTE: using c preprocessor"  > /dev/stderr
    cpp -E -nostdinc $PASFILE.$EXT -w | grep -v -e "^# 1 \"<" >> $PASFILE.1.$EXT
else
    echo "#1 \"$PASFILE.$EXT\"" >> $PASFILE.1.$EXT
    cat $PASFILE.$EXT >> $PASFILE.1.$EXT
fi

$P5CDIR/p5c $PASFILE.1.$EXT $PASFILE.c >  $PASFILE.lst

# The status of the compile is not returned,
# so convert a non-zero error message to fail status
if ! grep -qF "Errors in program: 0" $PASFILE.lst
then
    #tail  $PASFILE.lst
    awk '{ if( $2=="****" ) {print l0 "\n" l1 "\n" $0 ;} \
           else { l0=l1; l1 = $0; }; } \
           /^Errors in program/,0; \
        ' $PASFILE.lst > /dev/stderr

    echo "cannot compile $PASFILE, quitting" > /dev/stderr
    exit 1
fi

#compile with debug symbols
gcc -g -std=gnu99 -I $P5CDIR -o $PASFILE -lm $PASFILE.c 2> $PASFILE.err
if [ -s $PASFILE.err ]
then
    head $PASFILE.err
    if grep -qF ": error: " $PASFILE.err
    then
        echo "gcc compile failed, not running $PASFILE" > /dev/stderr
        exit 1
    fi
fi
rm $PASFILE.1.$EXT

# now run the program with arguments
if ! test -x ./$PASFILE ; then
    echo "failed: executable file not created"
    exit 1
fi

# now we can run the test program
shift
valgrind ./$PASFILE $@ 2>  "$PASFILE".vlg

#echo results are in "$PASFILE".vlg
cat "$PASFILE".vlg
