#!/bin/sh
# Copyleft valabind 2009-2013 pancake

LANG=$1
MOD=$2

show_help () {
  echo "Usage: valabind-cc [lang] [module-name] [-flags] vapifile .."
  echo "Example: valabind-cc python r_bp -I/usr/include/r_bp r_bp.vapi"
  echo "  lang: ctypes, python, dlang, nodejs, guile, go, ruby, perl, lua, java, csharp, ..."
  echo "  --help,-h      show this help message"
  echo "  --version      show version of valabind"
  echo "  --vapidir=dir  specify path to vapi files"
  echo "  --glib         assume vapi source is glib/gobject based"
  echo "  --test [lang]  test if it is possible to build"
  echo "  -x             generate C++ swig code"
  echo "  -X             output C++ instead of SWIG interface"
  echo "  -I[path]       add includepath for SWIGFLAGS and CFLAGS"
  echo "  -V[path]       add includepath for vapi files"
  echo "  -L[path]       append library path to LDFLAGS"
  echo "  -l[lib]        append to LDFLAGS to link a library"
  echo "  -C             do not compile, just let the .c/.cxx and .i files"
  echo "  -n             do not generate .i/.c/.cxx code, but compile it"
  echo "  -N[nspace]     include namespace in the output"
  echo "  -D[SYMBOL]       define vala symbol Symbol"
  echo " Environment:"
  echo "  VALABIND_DEBUG if not empty show stderr of commands"
  echo "  PYTHON_CONFIG  path to python-config program (select py2 or py3)"
  echo "  SWIGFLAGS      extra flags to be passed to swig"
  echo "  SOEXT          force specific extension for shared library (so, dll, dylib)"
  echo "  SWIG           path to swig program"
  exit 0
}

OMOD=${MOD}
[ -z "${SWIG}" ] && SWIG=swig
[ -z "${LANG}" ] && show_help
[ -z "${CC}" ] && CC=gcc
[ -z "${CXX}" ] && CXX=g++
COMPILE=Yes
ARG_VAPIDIR=""
EXT="c"
CXXOUT=0
NOGEN=0
if [ -z "${SOEXT}" ]; then
  if [ -n "`uname -a | grep -i darwin`" ]; then
    SOEXT="dylib"
  elif [ -n "`echo ${CC} | grep mingw`" ]; then
    SOEXT="dll"
  else
    SOEXT="so"
  fi
fi
if [ -z "${VALABIND_DEBUG}" ]; then
  NULLPIPE=">/dev/null"
else
  NULLPIPE=""
fi

use_cxx() {
    CC="${CXX}"
    EXT="cxx"
    CFLAGS="${CFLAGS} ${CXXFLAGS}"
    SWIGFLAGS="-c++ ${SWIGFLAGS}"
    VALABINDFLAGS="-x ${VALABINDFLAGS}"
}

TEST=0
case "$1" in
"--test")
  TEST=1
  LANG=$2
  ;;
"--version")
  printf "valabind " ; valabind --version
  ${SWIG} -version | grep SWIG
  ${CC} --version | grep ${CC}
  exit 0
  ;;
"--help"|"-h")
  show_help
  ;;
esac

SWIG="${SWIG} -small"
case "${LANG}" in
ctypes)
  python2 --version >/dev/null 2>&1 || \
  python --version > /dev/null 2>&1 || \
  exit 1
  ;;
dlang)
  dmd --help >/dev/null 2>&1 || \
  ldc2 --help >/dev/null 2>&1 || \
  exit 1
  ;;
nodejs|node|node-ffi)
  node --version >/dev/null 2>&1 || exit 1
  ;;
guile)
  use_cxx
  CFLAGS="${CFLAGS} `guile-config compile 2>/dev/null`"
  LDFLAGS="${LDFLAGS} `guile-config link 2>/dev/null`"
  ;;
python)
  use_cxx
  LDFLAGS="-L/usr/local/lib -L/usr/pkg/lib"
  if [ -n "`echo ${CXX} | grep mingw`" ]; then
    CFLAGS="${CFLAGS} -I${HOME}/.wine/drive_c/Python27/include"
    LDFLAGS="${LDFLAGS} -L${HOME}/.wine/drive_c/Python27/libs -lpython27"
  else
    PYCFG=""
    for a in ${PYTHON_CONFIG} python-config python2-config python3-config ; do
      $a --help >/dev/null 2>&1
      if [ $? = 0 ]; then
        PYCFG=$a
        break
      fi
    done
    if [ -z "$PYCFG" ]; then
      echo "No valid PYTHON_CONFIG command found" >&2
      exit 1
    fi
    CFLAGS="${CFLAGS} `$PYCFG --cflags | sed -e 's,-arch .*,,g'`"
    LDFLAGS="${LDFLAGS} `$PYCFG --ldflags`"
  fi
  OMOD="_${MOD}"
  # XXX SWIGFLAGS="${SWIGFLAGS} -threads"
  ;;
ruby)
  if [ "`ruby --version 2>/dev/null | grep 1.8`" ]; then
    RB_CFLAGS=`ruby -e 'require "mkmf"; print "-I" + RbConfig::CONFIG["archdir"];' 2>/dev/null`
  else
  if [ "`ruby --version 2>/dev/null | grep 1.9`" ]; then
    RB_CFLAGS=`ruby -e 'require "mkmf"; a=RbConfig::CONFIG["rubyhdrdir"]; print "-I#{a} -I#{a}/" + RbConfig::CONFIG["arch"];'`
  fi ; fi
  CFLAGS="${CFLAGS} ${RB_CFLAGS}"
  ;;
perl)
  LC_ALL=C # fix anoying perl warning
  export LC_ALL
  CFLAGS="${CFLAGS} `perl -MExtUtils::Embed -e ccopts 2>/dev/null`"
  LDFLAGS="${LDFLAGS} `perl -MExtUtils::Embed -e ldopts 2>/dev/null`"
  ;;
java)
  if [ -f /opt/java/include/jni.h ]; then
    CFLAGS="${CFLAGS} -I/opt/java/include -I/opt/java/include/linux"
  else
  if [ "$JAVA_HOME" ]; then
    CFLAGS="${CFLAGS} -I$JAVA_HOME/include -I$JAVA_HOME/include/linux"
  fi ; fi
  ;;
php5)
  CFLAGS="`php-config --includes 2>/dev/null` `pkg-config --libs libpng 2>/dev/null`"
  LDFLAGS=`php-config --libs 2>/dev/null`
  ;;
lua)
  SOEXT=so
  LUAPKG=`pkg-config --list-all|awk '/lua|lua-/{print $1;}'`
  if [ -n "${LUAPKG}" ]; then
    CFLAGS="${CFLAGS} `pkg-config --cflags ${LUAPKG}`"
    LDFLAGS="${LDFLAGS} `pkg-config --libs ${LUAPKG}`"
  fi
  ;;
go|csharp)
  ;;
esac

shift
shift

while : ; do
  [ -z "$1" ] && break
  if [ "`echo $1 | grep -- '-I'`" ]; then
    CFLAGS="${CFLAGS} $1"
    SWIGFLAGS="$1 ${SWIGFLAGS}"
    VALABINDFLAGS="`echo $1|sed -e 's,^-I,-I ,'` ${VALABINDFLAGS}"
  elif [ "`echo $1 | grep -- '-V'`" ]; then
    CFLAGS="${CFLAGS} $1"
    VALABINDFLAGS="`echo $1|sed -e 's,^-V,-V ,'` ${VALABINDFLAGS}"
  elif [ "`echo $1 | grep -- '--vapidir'`" ]; then
    ARG_VAPIDIR="`echo $1|sed -e 's,=, ,'`"
  elif [ "`echo $1 | grep -- '-x'`" ]; then
    use_cxx
  elif [ "`echo $1 | grep -- '-n'`" ]; then
    NOGEN=1
  elif [ "`echo $1 | grep -- '-N'`" ]; then
    VALABINDFLAGS="`echo $1|sed -e 's,^-N,-N ,'` ${VALABINDFLAGS}"
  elif [ "`echo $1 | grep -- '-X'`" ]; then
    EXT="cxx"
    CXXOUT=1
  elif [ "`echo $1 | grep -- '-l'`" ]; then
    LDFLAGS="$1 ${LDFLAGS}"
  elif [ "`echo $1 | grep -- '--glib'`" ]; then
    SWIGFLAGS="$1 ${SWIGFLAGS}"
  elif [ "`echo $1 | grep -- '-L'`" ]; then
    LDFLAGS="$1 ${LDFLAGS}"
  elif [ "`echo $1 | grep -- '-C'`" ]; then
    COMPILE=""
  elif [ "`echo $1 | grep -- '-pthread'`" ]; then
    echo ignored $1
  elif [ "`echo $1 | grep -- '-D'`" ]; then
    VALABINDFLAGS="`echo $1|sed -e 's,^-D,-D ,'` ${VALABINDFLAGS}"
  else
    FILES="$1 ${FILES}"
  fi
  shift
done

SWIGCPP="-DG_BEGIN_DECLS -DG_END_DECLS -DG_GNUC_CONST -DSWIG_PYTHON_SILENT_MEMLEAK"

# strip problematic cflags. can be problematic if not used
CFLAGS="`echo "${CFLAGS}" | sed -e 's,-pie,,g' -e 's,-PIE,,g'`"
LDFLAGS="`echo "${LDFLAGS}" | sed -e 's,-pie,,g' -e 's,-PIE,,g'`"

if [ "$CXXOUT" = 1 ]; then
  echo valabind -X ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.i -m ${MOD} ${FILES}
  valabind -X ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.cxx -m ${MOD} ${FILES} || exit 1
  #TODO:
  #if [ -n "${COMPILE}" ]; then
  #  echo ${CC} ${MOD}.cxx -fPIC -shared ${MOD}_wrap.${EXT} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS}
  #  ${CC} $@ -fPIC -shared ${MOD}_wrap.${EXT} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS} || exit 1
  #fi
#  echo ${CXX} ${MOD}.cxx $@ -fPIC -shared ${MOD}.cxx ${CXXFLAGS} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS}
#  ${CXX} ${MOD}.cxx $@ -fPIC -shared ${MOD}.cxx ${CXXFLAGS} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS} > /dev/null 2>&1
elif [ "$TEST" = 1 ]; then
  case "${LANG}" in
  ctypes)
    python2 --version >/dev/null 2>&1 || \
    python --version > /dev/null 2>&1 || \
    exit 1
    ;;
  dlang)
    dmd --help >/dev/null 2>&1 || \
    ldc2 --help >/dev/null 2>&1 || \
    exit 1
    ;;
  "nodejs"|"node"|"node-ffi")
    exec node --version > /dev/null 2>&1
    ;;
  *)
    DIR=`mktemp -d /tmp/tmp.XXXXXX`
    if [ ! $? = 0 ]; then
      echo "Cannot create temporary directory"
      exit 1
    fi
    cd ${DIR}
    MOD=test # hack to fix guile
    echo "%module ${MOD}" > ${MOD}.i
    eval echo ${SWIG} -O -o ${MOD}_wrap.${EXT} ${SWIGCPP} ${SWIGFLAGS} -${LANG} ${MOD}.i ${NULLPIPE}
    eval ${SWIG} -O -o ${MOD}_wrap.${EXT} ${SWIGCPP} ${SWIGFLAGS} -${LANG} ${MOD}.i ${NULLPIPE}
    if [ ! $? = 0 ]; then rm -rf ${DIR} ; exit 1 ; fi
    eval echo ${CC} $@ -fPIC -shared ${MOD}_wrap.${EXT} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS} ${NULLPIPE}
    eval ${CC} $@ -fPIC -shared ${MOD}_wrap.${EXT} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS} ${NULLPIPE}
    if [ ! $? = 0 ]; then rm -rf ${DIR} ; exit 1 ; fi
    rm -rf ${DIR}
    ;;
  esac
else
  case "${LANG}" in
  "ctypes")
    eval echo valabind --ctypes ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.py -m ${MOD} ${FILES}
    eval valabind --ctypes ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.py -m ${MOD} ${FILES} ${NULLPIPE}
    exit $?
    ;;
  "nodejs"|"node"|"node-ffi")
    eval echo valabind --node-ffi ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.js -m ${MOD} ${FILES}
    eval valabind --node-ffi ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.js -m ${MOD} ${FILES} ${NULLPIPE}
    exit $?
    ;;
  *)
    if [ "${NOGEN}" = 0 ]; then
      echo valabind --swig ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.i -m ${MOD} ${FILES}
      valabind --swig ${VALABINDFLAGS} ${ARG_VAPIDIR} -o ${MOD}.i -m ${MOD} ${FILES} || exit 1
      eval echo ${SWIG} -O -o ${MOD}_wrap.cxx ${SWIGCPP} ${SWIGFLAGS} -${LANG} ${MOD}.i ${NULLPIPE}
      ${SWIG} -O -o ${MOD}_wrap.cxx ${SWIGCPP} ${SWIGFLAGS} -${LANG} ${MOD}.i || exit 1
    fi
    if [ -n "${COMPILE}" ]; then
      eval echo ${CC} $@ -fPIC -shared ${MOD}_wrap.${EXT} ${SWIGCPP} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS} ${NULLPIPE}
      ${CC} $@ -fPIC -shared ${MOD}_wrap.${EXT} ${SWIGCPP} ${CFLAGS} -o ${OMOD}.${SOEXT} ${LDFLAGS} || exit 1
    fi
  esac
fi
