#!/bin/sh

##########################################################################
#
# Configure script for the IeeeCC754 suite
#
# information about the usage can be obtained by giving one of the
# options -h, -help or --help to this script.
#
# $Id: configure 80 2006-03-29 12:30:15Z sbecuwe $
#
##########################################################################


# help 

show_help()
{
    cat <<EOF

Configure script for the IeeeCC754 suite


Possible options:

 -h | -help | --help
          - show this information

 -cxx
          - C++ compiler to compile IeeeCC754
          - possible values: g++ (default), icc (Intel), CC (Sun)

 -fxx 
          - Fortran compiler to compile external library
          - possible values: ifc, f95 (default)

 -libdir
          - directory where to find the specific
            math libraries.  For SunOS, this is libsunmath.a
	    which can be found in /opt/SUNWspro/lib.
	    (/opt/SUNWspro/lib will be default if platform is SunSparc*)
	    (multiple directories should be specified by multiple -libdir)

-incdir
          - directory where to find the library specific include files
	    (multiple directories should be specified by multiple -incdir)

 -o | -output | --output
          - name of the output file; Makefile is default


 -target
          - target of test
          - possible values: BasicOperations (default), Conversions, both

 -platform
          - the implementation of floating-point arithmetic to be tested
          - possible values:
            when target=BasicOperations:
               SunSparc (default), IntelPentium, AMD, MpIeee, FMLib
            when target=Conversions:
               SunSparc_cpp (default), SunSparc_for, IntelPentium_cpp, AMD_cpp,
               MpIeee, FMLib


Examples:

     configure -target BasicOperations -platform SunSparc 
	generates a makefile to test the basic operations on a Sun Sparc
	platform 
   
     configure -cxx g++ -target Conversions -platform IntelPentium_cpp
	generates a makefile to test the conversions of the combined
        (Intel Pentium/g++ compiler) floating-point platform

     configure -cxx g++ -target Conversions -platform SunSparc_for
	generates a makefile to test the conversions of the combined
        (Sun Sparc/Fortran 90 compiler) floating-point platform 

EOF
}


# some warnings / errors

error_invalid_cxx_compiler()
{
    echo "Error: it seems you've chosen ${CXX} as C++ compiler."
    echo "       This version only supports g++, icc (Intel), CC (Sun)."
    echo
    show_help;
    exit 1;
}


error_invalid_fxx_compiler()
{
    echo "Error: it seems you've chosen ${FXX} as Fortran 90/95 compiler."
    echo "       This version only supports f90, f95 (Sun), ifc (Intel)."
    echo
    show_help;
    exit 1;
}


error_invalid_target()
{
    echo "Error: it seems you've chosen ${TARGET} as target."
    echo "       This version only supports BasicOperations and Conversions."
    echo
    show_help;
    exit 1;

}


error_gcc_version()
{
    echo "Error: it seems you're using version ${CXXVERSION} of g++."
    echo "       This version requires g++ 3.x."
    echo
    show_help;
    exit 1;
}


error_platformlibdir()
{
    echo "Error: the specified library directory ${PLATFORMLIBDIR}"
    echo "       for the specific math libraries does not exist";
    echo
    show_help;
    exit 1;
}


error_softwareincdir()
{
    echo "Error: the specified include directory ${SOFTWAREINCDIR}"
    echo "       for the specific math libraries does not exist";
    echo
    show_help;
    exit 1;
}


error_target_platform()
{
    echo "Error: target ${TARGET} and platform ${PLATFORM}: invalid combination";
    echo
    show_help;
    exit 1;
}


warning_machine_platform()
{
    echo "Warning: it seems you're running on a ${UNAME_MACHINE} architecture"
    echo "         but have chosen ${PLATFORM} as platform."
    echo "         Results may not be correct!"
    echo
}


warning_system_platform()
{
    echo "Warning: it seems you're running ${UNAME_SYSTEM}"
    echo "         but have chosen ${PLATFORM} as platform."
    echo "         Results may not be correct!"
    echo
}


unknown_architecture()
{
    echo "It seems you're running on a ${UNAME_MACHINE} architecture."
    echo "We've never run our testtool on that platform."
    echo "Please send us more information such that we can update"
    echo "our program."
    echo
    echo "cant@ua.ac.be"
    echo
}


# find some machine specific information

UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown


# default values for variables

MAKEFILE=Makefile
CXX=g++
FXX=f95
TARGET=BasicOperations
PLATFORM=""
HELP=no
PLATFORMLIBDIR=""
EXTRADEFS=""

BASICOPDIR=BasicOp
CONVERSIONDIR=Conversion
BOTHDIR=both
TYPE=${TARGET}
TYPEDIR=${BASICOPDIR}
SOFTWARE=NONE_TEST
SOFTWAREINCDIR=""

basicopcppsuffix=''


# some defaults for Sun CC and Intel icc compilers
PLATFORMSUNLIBDIR=/opt/SUNWspro/lib/
PLATFORMSUNLIBS='-lsunmath -lfsu -lfai'
if [ ! -d ${PLATFORMSUNLIBDIR} ]
then
    PLATFORMSUNLIBDIR=
    PLATFORMSUNLIBS=
fi

PLATFORMINTELLIBDIR=/opt/intel/compiler80/lib
PLATFORMINTELLIBS='-lifcore'
if [ ! -d ${PLATFORMINTELLIBDIR} ]
then
    PLATFORMINTELLIBDIR=
    PLATFORMINTELLIBS=
fi


if [ -z "${USER}" ]
then
  USER="unknown"
fi

today=`date`
if [ -z "${today}" ]
then
  today="unknown"
fi

# process command line options

while [ -n "$1" ]; do
   case $1 in
    -cxx)
	shift;
	CXX=$1;
	;;
    -fxx)
	shift;
	FXX=$1;
	;;
    -target)
	shift;
	TARGET=$1;
	;;
    -platform)
	shift;
	PLATFORM=$1;
	;;
    -libdir)
	shift;
	DPLATFORMLIBDIR=${PLATFORMLIBDIR}
	PLATFORMLIBDIR=$1
	if [ ! -d ${PLATFORMLIBDIR} ]
	then
	   error_platformlibdir;
        fi
	PLATFORMLIBDIR="-L${PLATFORMLIBDIR} ${DPLATFORMLIBDIR}"
	;;
    -incdir)
	shift;
	DSOFTWAREINCDIR=${SOFTWAREINCDIR}
	SOFTWAREINCDIR=$1
	if [ ! -d ${SOFTWAREINCDIR} ]
	then
	   error_softwareincdir;
        fi
	SOFTWAREINCDIR="-I${SOFTWAREINCDIR} ${DSOFTWAREINCDIR}"
	;;
    -o | -output | --output)
	shift;
	MAKEFILE=$1;
	;;
    -h | -help | --help)
	HELP=yes
	;;
    *)
        HELP=yes
        ;;
    esac
    shift
done


if [ -z "${PLATFORM}" ]
then
    PLATFORM=SunSparc
fi


# perform some checks on the input

# check for a valid compiler

if [ "${CXX}" = "icc" ]
then
  CXX=icpc
fi
case "${CXX}" in
  "g++"* | "icpc"* | "CC"*)
    ;;
  *)
    error_invalid_cxx_compiler;
    ;;
esac


case "${FXX}" in
  "f90" | "f95" | "ifc")
    ;;
  *)
    error_invalid_fxx_compiler;
    ;;
esac


# check for problems with gcc compiler versions < 3.x

case ${CXX} in
 g++*)
    CXXVERSION=`${CXX} -dumpversion 2>&1 | grep -v "command not found"`
    case ${CXXVERSION} in
	3.* | 4.*)
	    ;;
	*)
	    error_gcc_version;
	    ;;
    esac
 ;;
esac


# check for a valid combination of ${TARGET} and ${PLATFORM}

echo "TARGET: $TARGET"
case "${TARGET}" in
    "BasicOperations")
	case "${PLATFORM}" in
	    "SunSparc" | "IntelPentium" | "AMD" | "MpIeee" | "FMLib" )
		;;
	    *)
		error_target_platform;
		;;
	esac
	;;
    "Conversions")
	case "${PLATFORM}" in
	    "SunSparc_cpp" | "SunSparc_for" | "IntelPentium_cpp" | "AMD_cpp" | "MpIeee" | "FMLib" )
		;;
	    *)
		error_target_platform;
		;;
	esac
    ;;
    "both")
	case "${PLATFORM}" in
	    "SunSparc_cpp" | "SunSparc_for" | "IntelPentium" | "AMD" | "MpIeee" | "FMLib" )
		;;
	    *)
		error_target_platform;
		;;
	esac
	;;
    *)
	error_invalid_target;
	;;
esac


# display help message

if [ "${HELP}" = "yes" ]
then
  show_help
  exit 0;
fi

# display an empty line

echo


# initial setup of PLATFORMLIBDIR and SOFTWAREINCDIR

if [ -z "${PLATFORMLIBDIR}" ] && [ -d "${PLATFORMSUNLIBDIR}" ] && \
    ([ "${PLATFORM}" = "SunSparc" ] || [ "${PLATFORM}" = "SunSparc_cpp" ] \
     || [ "${PLATFORM}" = "SunSparc_for" ])
then
    PLATFORMLIBDIR=-L${PLATFORMSUNLIBDIR}
fi


if [ -z "${SOFTWAREINCDIR}" ]
then
    SOFTWAREINCDIR=-Iinclude
fi


# assign correct values to TYPE, TYPEDIR, SOFTWARE, SOFTWAREINCDIR

case "${TARGET}" in

    "Conversions")
	TYPE=Conversions;
	TYPEDIR=${CONVERSIONDIR};
	;;

    "BasicOperations")
	TYPE=BasicOperations;
	TYPEDIR=${BASICOPDIR};
	;;

    "both")
	TYPE=both;
	TYPEDIR=${BOTHDIR};
	SOFTWAREINCDIR="-Iboth/include"

	;;

    *)        # BasicOperations: default
	TYPE=BasicOperations;
	TYPEDIR=${BASICOPDIR};
	;;
esac


case "${PLATFORM}" in
    "MpIeee") 
	SOFTWARE=MPIEEE_TEST;
	;;
    "FMLib")
	SOFTWARE=FMLIB_TEST;
	SOFTWAREINCDIR=-I${TYPEDIR}/${PLATFORM}/include;
        case "${UNAME_MACHINE}" in
        sun*)
	    PLATFORMLIBDIR=-L${PLATFORMSUNLIBDIR}
            PLATFORMLIBS=${PLATFORMSUNLIBS}
            CXX=CC
	    ;;
        i?86* | x86_64)
            PLATFORMLIBDIR=-L${PLATFORMINTELLIBDIR}
            PLATFORMLIBS=${PLATFORMINTELLIBS}
            CXX=icpc
            FXX=ifort
            ;;
        esac
        ;;
    *)
	SOFTWARE=NONE_TEST;
	;;
esac




# compare ${UNAME_SYSTEM} ${UNAME_MACHINE} with ${PLATFORM}


case "${UNAME_SYSTEM}" in
    CYGWIN*)
      EXTRADEFS='-D__STRICT_ANSI__';
      ;;
    *)
      ;;
esac

case "${UNAME_MACHINE}" in
    sun*)
	if [ "${PLATFORM}" = "IntelPentium" ] || [ "${PLATFORM}" = "IntelPentium_cpp" ] \
           || [ "${PLATFORM}" = "AMD" ] || [ "${PLATFORM}" = "AMD_cpp" ]
	then
	    warning_machine_platform;
	fi

	ARCHITECTURE="SunSparc"

	;;
    i?86 | x86_64)
	if ([ "${PLATFORM}" = "SunSparc" ] || [ "${PLATFORM}" = "SunSparc_cpp" ] \
            || [ "${PLATFORM}" = "SunSparc_for" ]) && [ "${UNAME_SYSTEM}" != "SunOS" ]
	then
	    warning_machine_platform;
	fi

	ARCHITECTURE="IntelPentium"
	
	;;
    Power*)

	ARCHITECTURE="PowerMac"

	;;

    *)

        ARCHITECTURE="unknown_arch"
        unknown_architecture;

        ;;
esac





# Give feedback...

echo "Compiler:           ${CXX}"
echo "Math lib directory: ${PLATFORMLIBDIR}"
echo "Math include directory: ${SOFTWAREINCDIR}"
echo "Architecture:       ${ARCHITECTURE}"
echo "Platform:           ${PLATFORM}"
echo "Target:             ${TARGET}"
echo

echo
echo "Creating ${MAKEFILE}..."
echo

cat > ${MAKEFILE} <<EOF
####################################################################
#
# Makefile for the IeeeCC754 suite
# Generated by ${USER} at ${today}
#
# Compiler:           ${CXX}
EOF

if [ "${PLATFORM}" = "SunSparc_for" ]
then
    cat >> ${MAKEFILE} <<EOF
#                     ${FXX}
EOF
fi

cat >> ${MAKEFILE} <<EOF
# Math lib directory: ${PLATFORMLIBDIR}
# Math include directory: ${SOFTWAREINCDIR}
# Platform:           ${PLATFORM}
# Target:             ${TARGET}
#
####################################################################


CXX=${CXX}
FXX=${FXX}

EOF

case ${CXX} in
  CC*) cat >> ${MAKEFILE} <<EOF
CXXFLAGS=-Iinclude -g

EOF
  ;;
  
  icpc*)cat >> ${MAKEFILE} <<EOF
CXXFLAGS=-Iinclude -w1 -g

EOF
  ;;
  
  *) cat >> ${MAKEFILE} <<EOF
CXXFLAGS=-Iinclude -Wall -g

EOF
  ;;
esac

SOURCES="src/bitstring.cc src/fp.cc src/hex.cc src/IeeeCC754.cc"
OBJECTS="src/bitstring.o src/fp.o src/hex.o src/IeeeCC754.o"
if [ "${TARGET}" = "both" ]
then
  SOURCES="src/bitstring.cc src/fp.cc src/hex.cc both/src/IeeeCC754.cc both/src/Error.cc"
  OBJECTS="src/bitstring.o src/fp.o src/hex.o both/src/IeeeCC754.o both/src/Error.o" 
fi 

cat >> ${MAKEFILE} <<EOF
PLATFORMLIBDIR=${PLATFORMLIBDIR}
PLATFORM=${PLATFORM}
DEFINES=${EXTRADEFS} -D${ARCHITECTURE}

TYPE=${TYPE}
TYPEDIR=${TYPEDIR}

SOFTWARE=${SOFTWARE}
SOFTWAREINCDIR=${SOFTWAREINCDIR}

SOURCES=${SOURCES}
OBJECTS=${OBJECTS}

EOF


if [ "${PLATFORM}" = "FMLib" ]
then
  cat >> ${MAKEFILE} <<EOF
SOURCES+=\${TYPEDIR}/\${PLATFORM}/FMSAVE.f90 \${TYPEDIR}/\${PLATFORM}/FMZM90.f90 \${TYPEDIR}/\${PLATFORM}/FM.f90 
OBJECTS+=\${TYPEDIR}/\${PLATFORM}/FMSAVE.o \${TYPEDIR}/\${PLATFORM}/FMZM90.o \${TYPEDIR}/\${PLATFORM}/FM.o 
 
EOF
fi


case "${TARGET}" in

    "BasicOperations")
	cat >> ${MAKEFILE} <<EOF
BasicOperations=\${TYPEDIR}/\${PLATFORM}/fpenv_${PLATFORM}.o \\
                  \${TYPEDIR}/\${PLATFORM}/BasicOptest.o

EOF
	;;

    "Conversions")
    cat >> ${MAKEFILE} <<EOF
Conversions=\${TYPEDIR}/\${PLATFORM}/Conversiontest.o \\
              \${TYPEDIR}/\${PLATFORM}/fpenv_${PLATFORM}.o

EOF
	;;

    "both")
	cat >> ${MAKEFILE} <<EOF
both=\${TYPEDIR}/\${PLATFORM}/fpenv_${PLATFORM}.o \\
                  \${TYPEDIR}/\${PLATFORM}/Tests.o

EOF
	;;

    *)        # BasicOperations: default
	cat >> ${MAKEFILE} <<EOF
BasicOperations=\${TYPEDIR}/\${PLATFORM}/fpenv_${PLATFORM}.o  \\
                  \${TYPEDIR}/\${PLATFORM}/BasicOptest.o

EOF
	;;

esac



cat >> ${MAKEFILE} <<EOF
all: \${OBJECTS} \${PLATFORM}
	@echo
	@echo "Built target \\"${TYPE}\\""
	@echo

EOF


if [ ${TYPE} = "both" ]
then
    cat >> ${MAKEFILE} <<EOF
.cc.o:
	\${CXX} \${DEFINES} -DBasicOperations -DConversions -c \${CXXFLAGS} \${SOFTWAREINCDIR} -o \$@ \$<

EOF
else
    cat >> ${MAKEFILE} <<EOF
.cc.o:
	\${CXX} \${DEFINES} -D\${TYPE} -D\${SOFTWARE} -c \${CXXFLAGS} \${SOFTWAREINCDIR} -o \$@ \$<

EOF
fi


if [ "${PLATFORM}" = "SunSparc_for" ]
then
    cat >> ${MAKEFILE} <<EOF
Ops.o: Ops.f90
	\${FXX} -c -o \$@ \$<

EOF
fi;

if [ "${PLATFORM}" = "FMLib" ]
then
    case "${UNAME_MACHINE}" in
        sun*)
	    cat >> ${MAKEFILE} <<EOF
.SUFFIXES: .f90
.f90.o:
	\${FXX} -I\${TYPEDIR}/\${PLATFORM} -c -free -o \$@ \$<

EOF
	    ;;
        i?86* | x86_64)
	    cat >> ${MAKEFILE} <<EOF
.SUFFIXES: .f90
.f90.o:
	\${FXX} -I\${TYPEDIR}/\${PLATFORM} -c -FR -o \$@ \$<

EOF
            ;;
        esac

fi


case "${PLATFORM}" in

    "SunSparc" | "SunSparc_cpp" )
	cat >> ${MAKEFILE} <<EOF
${PLATFORM}: \${\${TYPE}}
	\${CXX} \${DEFINES} -o IeeeCC754 \${PLATFORMLIBDIR} -lsunmath \${OBJECTS} \${\${TYPE}}

EOF
	;;


    "IntelPentium" | "IntelPentium_cpp" | "AMD" | "AMD_cpp" )
	cat >> ${MAKEFILE} <<EOF
${PLATFORM}: \${\${TYPE}} \${TYPEDIR}/\${PLATFORM}/myfenv.o
	\${CXX} \${DEFINES} -o IeeeCC754 -lm \${OBJECTS} \${TYPEDIR}/\${PLATFORM}/myfenv.o \${\${TYPE}}

EOF
	;;

    "SunSparc_for")
	cat >> ${MAKEFILE} <<EOF
${PLATFORM}: \${\${TYPE}}
	\${FXX} -c \${TYPEDIR}/\${PLATFORM}/Ops.f90 -o \${TYPEDIR}/\${PLATFORM}/Ops.o
	\${CXX} \${DEFINES} -o IeeeCC754 -lsunmath -lfsu \${OBJECTS} \${\${TYPE}} \${TYPEDIR}/\${PLATFORM}/Ops.o

EOF
	;;

    "MpIeee")
	cat >> ${MAKEFILE} <<EOF
MpIeee: \${\${TYPE}}
	\${CXX} \${DEFINES} -o IeeeCC754 \${OBJECTS} \${\${TYPE}} \${PLATFORMLIBDIR} -lArithmos -lIMpIeee -lMpIeee -lgmp -lSpecHardware -lRational -lSpecialValue

EOF
        ;;

    "FMLib")
	cat >> ${MAKEFILE} <<EOF
FMLib: \${\${TYPE}} \${TYPEDIR} \${TYPEDIR}/\${PLATFORM}/FM.o \${TYPEDIR}/\${PLATFORM}/FMSAVE.o \${TYPEDIR}/\${PLATFORM}/FMZM90.o
	\${CXX} \${DEFINES} -o IeeeCC754 \${OBJECTS} \${\${TYPE}} \${TYPEDIR}/\${PLATFORM}/FMSAVE.o \${TYPEDIR}/\${PLATFORM}/FMZM90.o \${TYPEDIR}/\${PLATFORM}/FM.o \${PLATFORMLIBDIR} ${PLATFORMLIBS}

EOF
	;;
	
    "Library")
	cat >> ${MAKEFILE} <<EOF
Library: \${\${TYPE}}
	\${CXX} \${DEFINES} -o IeeeCC754 \${OBJECTS} \${\${TYPE}}

EOF
	;;
esac



case "${PLATFORM}" in
    "IntelPentium" | "IntelPentium_cpp" | "AMD" | "AMD_cpp" )
	
	cat >> ${MAKEFILE} <<EOF
clean:
	-rm -f IeeeCC754
	-rm -f \${OBJECTS} \${\${TYPE}} \${TYPEDIR}/\${PLATFORM}/myfenv.o
	-rm -f ieee.log

EOF
	;;
    *)
	cat >> ${MAKEFILE} <<EOF
clean:
	-rm -f IeeeCC754
	-rm -f \${OBJECTS} \${\${TYPE}}
	-rm -f ieee.log
	-rm -f *.mod ifc*

EOF
	;;
esac

if [ "${TARGET}" = "both" ]
then
	
	cat >> ${MAKEFILE} <<EOF
decode:
	cd both/src; \\
	configure \${CXX}; \\
	make clean && make

EOF
fi

# generate "info" 
cat >> ${MAKEFILE} <<EOF
info:
	@echo
	@echo "Configured for:"
	@echo
	@echo "Target:             \${TYPE}"
	@echo "Platform:           \${PLATFORM}"
	@echo "Compiler:           \${CXX}"
	@echo

EOF
