#!/bin/sh

die_unknown(){
    echo "Unknown option \"$1\"."
    echo "See $0 --help for available options."
    exit 1
}

#check whether option is supported by this cpu
check_cpu(){
    ok=0
    grep "^flags.* $1 " /proc/cpuinfo >/dev/null 2>&1
    if test $? -eq 0; then
      ok=1
    else
      grep "^flags.* $1\$" /proc/cpuinfo >/dev/null 2>&1
      if test $? -eq 0; then
        ok=1
      fi
    fi
    eval test $ok -eq 1
}

#try to figure out best FFdecsa compiler options
get_cpu_optimization() {
   FLAGS="FLAGS=-O3 -fexpensive-optimizations -funroll-loops"
   arch=`uname -m`
   processors_flags=`cat /proc/cpuinfo | grep "flags" | head -n 1`
   vendor=`cat /proc/cpuinfo |grep "vendor_id" | head -n 1 | sed -e "s/.*:\W*//"`
   gcc_ver=`$CXX -v 2>&1 | grep "gcc version" | head -n 1`
   gcc_major=`echo $gcc_ver | sed -e 's/^gcc version \([0-9]*\)\..*/\1/'`
   gcc_minor=`echo $gcc_ver | sed -e 's/^gcc version [0-9]*\.\([0-9]*\).*/\1/'`
   if test $gcc_major -gt 4; then
     ARCH="native"
   elif test $gcc_major -eq 4 && test $gcc_minor -ge 2; then
     ARCH="native"
   elif test "x$arch" = "xx86_64"; then
     if test "x$vendor" = "xAuthenticAMD"; then
        ARCH="k8"
     elif test "x$vendor" = "xGenuineIntel"; then
        ARCH="nocona"
     else
        echo **WARNING** - Unknown vendor $vendor - assuming nocona
        ARCH="nocona"
     fi
     FLAGS="$FLAGS -finline-limit=6000000 --param max-unrolled-insns=500"
   elif test "x$arch" = "xathlon-xp"; then
     ARCH="athlon-xp"
     FLAGS="$FLAGS -finline-limit=6000000 --param max-unrolled-insns=500"
   else
     ARCH="pentium"
   fi
   OPTS=""
   for opt in mmx sse sse2; do
     if check_cpu $opt; then
       OPTS="$OPTS $opt"
       FLAGS="$FLAGS -m$opt"
     fi
   done
   FLAGS="$FLAGS -march=$ARCH"
   echo "Processor capabilities: $ARCH ($OPTS )"
}

show_help() {
  echo "Usage: configure [options]"
  echo "Options: [defaults in brackets after descriptions]"
  echo
  echo "Standard options:"
  echo "  --help                   print this message"
  echo "  --compiletype=<type>     specify compile type of release or debug,"
  echo "                           default is debug"
  echo "  --shared                 compile sc shared libs instaed of static"
  echo "  --dvb-dir=<path>         use <path> for DVB headers"
  echo "  --auxserver              use auxserver with localhost:7777:auxserver"
  echo "  --auxserver=<host:port:password>"
  echo "                           use auxserver with given parms"
  echo "  --optimize=<opts>        set FFDecsa optimiation detection"
  echo "                           yes: Try most common optimizations (default)"
  echo "                           long: Try all known optimizations"
  echo "                           no: Don't do any optimizations"
  echo "  --ffdecsa_mode=<val>     use <val> optimization"
  echo "  -cxx=<c++ compiler>      command for C++ compilation (default: g++)"
  exit 0
}
MAX_MODE=PARALLEL_32_INT
ffdecsa_opt="yes"
compiletype_opt="debug"
for opt do
  optval="${opt#*=}"
  case "$opt" in
  --dvb-dir=*) dvb_path=`eval echo $optval`
  ;;
  --cxx=*) CXX="$optval"
  ;;
  --ffdecsa_mode=*) ffdecsa_opt="no"; MAX_MODE="$optval"
  ;;
  --ffdecsa_flags=*) ffdecsa_flags="$optval"
  ;;
  --optimize=*) ffdecsa_opt="$optval"
  ;;
  --auxserver) auxserver_opt="localhost:7777:auxserver"
  ;;
  --auxserver=*) auxserver_opt="$optval"
  ;;
  --compiletype=*) compiletype_opt="$optval"
  ;;
  --shared) shared_opt="1"
  ;;
  --help) show_help
  ;;
  *)
  die_unknown $opt
  ;;
  esac
done

if test "x$CXX" = "x"; then
  CXX=g++
fi
echo "Using C++ compiler: $CXX"

if test "x$ffdecsa_opt" = "xlong"; then
  FFDECSA_MODES="PARALLEL_32_INT PARALLEL_32_4CHAR PARALLEL_32_4CHARA \
                 PARALLEL_64_8CHAR PARALLEL_64_8CHARA PARALLEL_64_2INT \
                 PARALLEL_64_LONG PARALLEL_64_MMX PARALLEL_128_16CHAR \
                 PARALLEL_128_16CHARA PARALLEL_128_4INT PARALLEL_128_2LONG \
                 PARALLEL_128_2MMX PARALLEL_128_SSE PARALLEL_128_SSE2"
elif test "x$ffdecsa_opt" = "xyes"; then
  FFDECSA_MODES="PARALLEL_32_INT PARALLEL_64_2INT PARALLEL_64_LONG \
                 PARALLEL_64_MMX PARALLEL_128_2LONG PARALLEL_128_2MMX \
                 PARALLEL_128_SSE PARALLEL_128_SSE2"
elif test "x$ffdecsa_opt" != "xno"; then
  echo "Bad option to --optimize '$ffdecsa_opt'.  Should be 'yes, no, long'"
  exit 1
fi
if test "x${TMPDIR}" = "x"; then
  TMPDIR="/tmp"
fi

echo "# Automatically generated by configure - do not modify" > config.mak

if test "x$compiletype_opt" = "xrelease"; then
  echo "Using compile type release"
  echo "RELEASE=1" >> config.mak
elif test "x$compiletype_opt" = "xdebug"; then
  echo "Using compile type debug"
else
  echo "Bad option to --compiletype '$compiletype_opt'. Should be 'release, debug'"
  exit 1
fi

if test "x$auxserver_opt" != "x"; then
  echo $auxserver_opt | {
    IFS=: read host port pass
    echo "AUXSERVER_OPTS=-DAUXSERVER_HOST=\\\"$host\\\" -DAUXSERVER_PORT=\\\"$port\\\" -DAUXSERVER_PASSWD=\\\"$pass\\\" -DUSE_AUXSERVER" >> config.mak
  }
fi

if test "x$shared_opt" = "x1"; then
  echo "Compiling sc for shared libraries"
  echo "USE_DLOAD=1" >> config.mak
fi

TMPDIR="${TMPDIR}/sasc-ng.${RANDOM}"
mkdir ${TMPDIR}

#Test FFDECSA compile
MAX_val=0
if test "x$ffdecsa_opt" != "xno"; then
   if test "x$ffdecsa_flags" = "x"; then
     if test -f /proc/cpuinfo; then
       get_cpu_optimization
     fi
   else
     FLAGS=$ffdecsa_flags
   fi
   FFdecsaDIR="../../FFdecsa"
   TMPOUT="${TMPDIR}/FFdecsa/out"
   mkdir "${TMPDIR}/FFdecsa"
   cp $FFdecsaDIR/*.c $FFdecsaDIR/*.h $FFdecsaDIR/Makefile "${TMPDIR}/FFdecsa/"
   echo "Trying various FFdecsa optimizations..."
   for var in ${FFDECSA_MODES}; do
     make -C "${TMPDIR}/FFdecsa" FFdecsa_test "PARALLEL_MODE=${var}" "${FLAGS}" "COMPILER=$CXX" >/dev/null 2>&1
     if test $? -ne 0 ; then
       echo "    ${var}: build failed"
     else
       rm -f ${TMPOUT}
       sync;sleep 2; "${TMPDIR}/FFdecsa/FFdecsa_test" > /dev/null 2>"${TMPOUT}"
       if test $? -ne 0; then
         echo "    ${var}: test failed"
       else
         grep FAILED "${TMPOUT}" >/dev/null 2>&1
         if test $? -ne 1; then
           echo "    ${var}: test failed"
         else
           res=`grep "speed=.*Mbit" "${TMPOUT}" | sed -e 's/^.*=\([0-9]*\)\.[0-9]* Mbit.*$/\1/'`
           echo "    ${var}: $res"
           if test $res -gt $MAX_val; then
             MAX_val=$res
             MAX_MODE=$var
           fi
         fi
       fi
     fi
     make -C "${TMPDIR}/FFdecsa" clean >/dev/null 2>&1
   done
   echo "Choosing PARALLEL_MODE = ${MAX_MODE}"
   echo "FFDECSA_OPTS = \"$FLAGS\" PARALLEL_MODE=${MAX_MODE} COMPILER=$CXX" >> config.mak
else
   if test "x$ffdecsa_flags" != "x"; then
     echo "FFDECSA_OPTS = \"$ffdecsa_flags\" PARALLEL_MODE=${MAX_MODE} COMPILER=$CXX" >> config.mak
   elif test "x$MAX_MODE" != "xPARALLEL_32_INT"; then
     echo "FFDECSA_OPTS = PARALLEL_MODE=${MAX_MODE} COMPILER=$CXX" >> config.mak
   fi
fi

if test "x$dvb_path" != "x"; then
  if test -e "${dvb_path}/include/linux/dvb/frontend.h"; then
    echo "DVB_DIR=${dvb_path}" >> config.mak
    echo "Using DVB_DIR: ${dvb_path}"
  elif test -e "${dvb_path}/linux/include/linux/dvb/frontend.h"; then
    echo "DVB_DIR=${dvb_path}/linux" >> config.mak
    echo "Using DVB_DIR: ${dvb_path}/linux"
  else
    echo "Could not find DVB headers within $dvb_path"
  fi
fi
rm -rf "${TMPDIR}"
echo "CXX=$CXX" >> config.mak
date >> config.log
echo "	$0 $*" >> config.log
