#!/bin/sh

# Script to run the GPC Test Suite
#
# NOTE: Don't invoke this script manually. Run `make' instead.
#
# Copyright (C) 1996-2002 Free Software Foundation, Inc.
#
# Authors: Frank Heckenbach <frank@pascal.gnu.de>
#          Matthias Klose <doko@cs.tu-berlin.de>
#          Peter Gerwinski <peter@gerwinski.de>
#
# This file is part of GNU Pascal.
#
# GNU Pascal is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# GNU Pascal is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with GNU Pascal; see the file COPYING. If not, write to the
# Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.

if [ x"$TEST_MAKE_FLAG" != x"test-make-flag" ]; then
  echo "`basename $0`: Don't invoke this script manually. Run \`make' instead," >&2
  echo "          unless you know what you're doing (in which case you'll" >&2
  echo "          also know how to get rid of this message :-)." >&2
  exit 1
fi

# Maximum time allowed per process (compiler and test programs).
# I hope the value (seconds) is ok for most systems. Otherwise we
# might have to run a little timing test at the beginning.
#
# Set the hard limit a little higher than the soft limit, so we get
# a SIGXCPU rather than SIGKILL in the normal timeout case, but if
# a process ignores SIGXCPU, it will be killed a little later.
#
# Note: Some strange shells (e.g., the native shell on OSF/Alpha)
# abort the whole script when trying to set a hard limit as
# non-root.
if [ x"$BASH" != x ]; then
  ulimit -H -t 2010 2> /dev/null
fi
ulimit -S -t 2000 2> /dev/null

if [ -z "$PC" ]; then
  PC=gpc
fi

if [ -z "$PFLAGS" ]; then
  PFLAGS="--automake -g -O3 -Wall -Werror"
fi

if [ -z "$SRCDIR" ]; then
  SRCDIR=.
fi

echo "program Dummy; begin WriteLn ('1723') end." > dummy.pas
NEEDED_OPTIONS="`$PC $PFLAGS --print-needed-options dummy.pas 3>&2 2>&1 1>&3`"
PFLAGS="$PFLAGS $NEEDED_OPTIONS"
DEFAULT_UNIT_DIR="`$PC $PFLAGS --print-file-name=units`"

if $PC $PFLAGS dummy.pas; then
  rm -f dummy.pas
  if [ -r "a.out" ]; then
    A_OUT=a.out
  elif [ -r "a.exe" ]; then
    A_OUT=a.exe
  else
    echo "$0: fatal: cannot find either a.out or a.exe after compilation" >&2
    exit 1
  fi
else
  rm -f dummy.pas
  echo "$0: fatal: cannot compile a simple program" >&2
  exit 1
fi
export A_OUT

rm -f dummy.out
./"$A_OUT" > dummy.out ||
  {
    echo "$0: fatal: cannot run a simple program" >&2
    echo "  (if this is a cross-compiler, you can't run the test suite easily)" >&2
    exit 1
  }

diff_cr ()
{
  "$FIXCR" < "$1" > diff_cr1.tmp
  "$FIXCR" < "$2" > diff_cr2.tmp
  diff diff_cr1.tmp diff_cr2.tmp
  stat=$?
  rm -f diff_cr1.tmp diff_cr2.tmp
  return $stat
}

DIFF=diff
"$DIFF" dummy.out "$SRCDIR/basic.out" > /dev/null ||
  {
    $PC $PFLAGS -o fixcr "$SRCDIR/fixcr.pas" ||
      { echo "$0: fatal: cannot compile fixcr.pas" >&2; exit 1; }
    if [ -r "./fixcr" ]; then
      FIXCR=./fixcr
    elif [ -r "./fixcr.exe" ]; then
      FIXCR=./fixcr.exe
    else
      echo "$0: fatal: cannot find either fixcr or fixcr.exe" >&2
      exit 1
    fi
    export FIXCR
    DIFF=diff_cr
    "$DIFF" dummy.out "$SRCDIR/basic.out" > /dev/null ||
      {
        echo "$0: fatal: output of a simple program differs" >&2
        exit 1
      }
  }
rm -f dummy.out

# Find a good echo. !:-/
if [ "`echo -n foo; echo bar`" = "foobar" ]; then
  echomode=1
elif [ "`echo 'foo\c'; echo bar`" = "foobar" ]; then
  echomode=2
elif [ "`echo -e 'foo\c'; echo bar`" = "foobar" ]; then
  echomode=3
else
  echo "Cannot find a way to echo without newline. :-(" >&2
  echo "(If you know one for this system, please add it in" >&2
  echo "$0 and report it to the GPC developers.)" >&2
  exit 1
fi

echon ()
{
  if [ $echomode = 1 ]; then
    echo -n "$*"
  elif [ $echomode = 2 ]; then
    echo "$*\c"
  elif [ $echomode = 3 ]; then
    echo -e "$*\c"
  fi
}

testfile ()
{
  x="$1"
  if echo "$x" | grep '\.pas$' > /dev/null; then
    :
  else
    x="$x.pas"
  fi
  if [ -r "$x" ]; then
    if grep -i "program.*;" "$x" > /dev/null; then
      xb="`basename "$x"`"
      x1="$SRCDIR/`echo "$xb" | sed -e 's/\.[^.]*$//'`"
      xr="$x1.run"
      xi="$x1.in"
      xo="$x1.out"
      xc="`sed -ne '/COMPILE-CMD:/{s/.*COMPILE-CMD: *//;s/ *\*).*//;s/ *}.*//;p;}' "$x"`"
      PC_WITH_FLAGS="$PC $PFLAGS \
        --unit-path=$SRCDIR --unit-path=$SRCDIR/../rts \
        --unit-path=$SRCDIR/../units --unit-path=$DEFAULT_UNIT_DIR \
        -I $DEFAULT_UNIT_DIR -I $SRCDIR -I $SRCDIR/../units --executable-path=. \
        `sed -ne '/FLAG/{s/.*FLAG *//;s/ *\*).*//;s/ *}.*//;p;}' "$x"`"
      export PC_WITH_FLAGS
      rm -f "$A_OUT" 2> /dev/null
      echon "TEST	$xb:	"
      if [ x"$xc" != x ]; then
        { sh "$SRCDIR/$xc" "$PC_WITH_FLAGS -o $A_OUT" "$x"; } 2>&1
      elif grep WRONG "$x" > /dev/null; then
        $PC_WITH_FLAGS -w -o "$A_OUT" "$x" 2> stderr.out
        stat=$?
        if [ $stat -eq 0 ] || [ -r "$A_OUT" ]; then
          echon "failed: "
          { ./"$A_OUT"; } 2>&1
        elif [ $stat -ge 127 ] || grep -i "internal compiler error" stderr.out > /dev/null || grep -i "fatal signal" stderr.out > /dev/null; then
          echon "failed: "
          cat stderr.out
        else
          echo "OK"
        fi
      elif grep WARN "$x" > /dev/null; then
        $PC_WITH_FLAGS -Werror -o "$A_OUT" "$x" 2> stderr.out
        stat=$?
        if [ $stat -eq 0 ] || [ -r "$A_OUT" ]; then
          echon "failed: "
          { ./"$A_OUT"; } 2>&1
        elif [ $stat -ge 127 ] || grep -i "internal compiler error" stderr.out > /dev/null || grep -i "fatal signal" stderr.out > /dev/null; then
          echon "failed: "
          cat stderr.out
        else
          echo "OK"
        fi
      else
        if { $PC_WITH_FLAGS -Werror -o "$A_OUT" "$x"; } 2>&1; then
          if [ -r "$xr" ]; then
            if [ -r "$xo" ]; then
              if [ -r "$xi" ]; then
                { sh "$xr" "$x" < "$xi"; } > testmake.tmp 2>&1
              else
                { sh "$xr" "$x"; } > testmake.tmp 2>&1
              fi
              if "$DIFF" testmake.tmp "$xo"; then
                echo "OK"
              else
                echo "failed"
              fi
            else
              if [ -r "$xi" ]; then
                { sh "$xr" "$x" < "$xi"; } 2>&1
              else
                { sh "$xr" "$x"; } 2>&1
              fi
            fi
          else
            if [ -r "$A_OUT" ]; then
              if [ -r "$xo" ]; then
                if [ -r "$xi" ]; then
                  { ./"$A_OUT" "$x" < "$xi"; } > testmake.tmp 2>&1
                else
                  { ./"$A_OUT" "$x"; } > testmake.tmp 2>&1
                fi
                if "$DIFF" testmake.tmp "$xo"; then
                  echo "OK"
                else
                  echo "failed"
                fi
              else
                if [ -r "$xi" ]; then
                  { ./"$A_OUT" "$x" < "$xi"; } 2>&1
                else
                  { ./"$A_OUT" "$x"; } 2>&1
                fi
              fi
            else
              echo "failed"
            fi
          fi
        else
          echo "failed"
        fi
      fi
    fi
    true
  else
    false
  fi
}

echo "GPC-TEST-BEGIN"
echo "=========================="
for f in `cd "$SRCDIR"; if [ x"$*" = x ]; then echo *.pas; else echo $*; fi`; do
  found=n
  for x in "$SRCDIR"/$f; do
    testfile "$x" && found=y
  done
  if [ $found = n ]; then
    echo "$f: No such program" >&2
  fi
done
echo "=========================="
echo "GPC-TEST-END"  # be sure that GPC-TEST-END starts in a new line ...
