#! /bin/sh
echo "===" > configure.log

#===
# Initialize variables
CFLAGS=
CPP=
LIBS=
VERSION="v0.06"
USEPOLL=
HASPTHREADKILL=
HASDLFCN=
HASSIGNEDCHAR=
#===
# We can't "test" for this, as some systems have problems
# upon initing and exiting ncurses. (they mess up the
# display.) So, on funky systems with no ncurses color
# support, we will require the user to pass a --force.
HASNCURSESCOLOR=yes
DEBUG=no

#===
# checkCpp
#   Ok, some systems don't seem to gave g++, let's try c++.
checkCpp() {
  echo -n "Checking for a compiler, "
  cat > configure.cpp <<ENDL
int main( void) {
  return 0;
}
ENDL
  if g++ configure.cpp -o configure.out 2>> configure.log; then
    CPP="g++";
  else
    if c++ configure.cpp -o configure.out 2>> configure.log; then
      CPP="c++";
    else
      echo "not found.";
      echo "Fatal: We were unable to find a c++ compiler on this system.";
      exit 1;
    fi
  fi
  echo "$CPP"
}

#===
# checkDlfcn
#   Prereq - Must checkLibDL first.
checkDlfcn() {
  echo -n "Checking for dlfcn.h, "
  cat > configure.cpp <<ENDL
#include <dlfcn.h>
int main( void) {
  //char *tmp = dlerror();
  return 0;
}
ENDL
  if $CPP configure.cpp -o configure.out 2>> configure.log; then
    echo "found."
    HASDLFCN="yes";
  else
    echo "not found."
    HASDLFCN="no";
  fi
}

#===
# checkExportDynamic
checkExportDynamic() {
  echo -n "Checking for -export-dynamic, "
  cat > configure.cpp <<ENDL
int main( void) {
  return 0;
}
ENDL
  if $CPP -export-dynamic configure.cpp -o configure.out 2>> configure.log; then
    echo "yes."
    LIBS="$LIBS -export-dynamic"
  else
    echo "no."
  fi
}

#===
# checkGnome
#   Check if gnome-config exists, I'm not sure what will
#   happen if you *don't* have gnomeui. <shrugs>
checkGnome() {
  FOUND=
  echo -n "Checking for GnomeUI, "

  if [ -f /usr/X11R6/bin/gnome-config ]; then
    FOUND="/usr/X11R6/bin/gnome-config"
  fi
  if [ -f /opt/gnome/bin/gnome-config ]; then
    FOUND="/opt/gnome/bin/gnome-config"
  fi
  if [ -z "$FOUND" ]; then
    echo "not found."
    echo "Fatal: The gtk version of Prolix requires gnomeui."
    exit 1;
  else
    echo "found."
    CFLAGS="$CFLAGS `$FOUND --cflags gnomeui`"
    LIBS="$LIBS `$FOUND --libs gnomeui`"
  fi
}

#===
# checkGtkConfig
#   Searches for gtk-config or gtk12-config.
checkGtkConfig() {
  FOUND=
  echo -n "Checking for Gtk, "
  if [ -f /opt/gnome/bin/gtk-config ]; then
    FOUND="/opt/gnome/bin/gtk-config"
  fi
  if [ -f /opt/gnome/bin/gtk12-config ]; then
    FOUND="/opt/gnome/bin/gtk12-config"
  fi
  if [ -f /usr/X11R6/bin/gtk-config ]; then
    FOUND="/usr/X11R6/bin/gtk-config"
  fi
  if [ -f /usr/X11R6/bin/gtk12-config ]; then
    FOUND="/usr/X11R6/bin/gtk12-config"
  fi
  if [ -z "$FOUND" ]; then
    echo "not found."
    echo "Fatal: The gtk version of Prolix require gtk :)"
    echo "       If you have gtk, perhaps the configure"
    echo "       script needs to be updated to search for"
    echo "       your gtk-config script."
    exit 1;
  else
    echo "found."
    CFLAGS="$CFLAGS `$FOUND --cflags gtk gthread`"
    LIBS="$LIBS `$FOUND --libs gtk gthread`"
  fi
}

#===
# checkLibDL
#   FreeBSD does not need you to specify -ldl and should fail
#   this test, where Linux *does* need you to specify -ldl
#   and should pass just fine. Either way - it's not an error.
checkLibDL() {
  echo -n "Checking for LibDL, "
  cat > configure.cpp <<ENDL
#include <dlfcn.h>
int main( void) {
  char *buf = dlerror();
  return 0;
}
ENDL
  if $CPP -ldl configure.cpp -o configure.out 2>> configure.log; then
    echo "found."
    LIBS="$LIBS -ldl"
  else
    echo "not found."
  fi
}

#===
# checkNCurses
checkNCurses() {
  echo -n "Checking for NCurses, "
  cat > configure.cpp <<ENDL
#include <ncurses.h>
int main( void) {
  initscr();
  return( has_colors());
}
ENDL
  rm -f ./configure.out
  if $CPP -lncurses configure.cpp -o configure.out 2>&1 >> configure.log; then
    echo "found."
    LIBS="$LIBS -lncurses"
  else
    if $CPP configure.cpp -o configure.out 2>> configure.log; then
      echo "found."
    else
      echo "not found."
      echo "Fatal: You need to install ncurses."
      exit 1
    fi
  fi
  # We can't do this as initscr() messes up the display on some boxen.
  #echo -n "Checking for NCurses color support, "
  #if [ -z "$HASNCURSESCOLOR" ]; then
  #  if ./configure.out; then
  #    echo "no."
  #    HASNCURSESCOLOR="no";
  #  else
  #    echo "yes."
  #    HASNCURSESCOLOR="yes";
  #  fi
  #else
  #  echo "skipping."
  #fi
}

#===
# checkPThread
checkPThread() {
  echo -n "Checking for -pthread, "
  cat > configure.cpp <<ENDL
#include <pthread.h>
int main( void) {
  return 0;
}
ENDL
  rm -f configure.out 2>> configure.log
  $CPP -pthread configure.cpp -o configure.out 2>> configure.log
  if test -f configure.out; then
    echo "yes."
    LIBS="$LIBS -pthread"
  else
    echo "no."
  fi
}

#===
# checkPThreadKill
checkPThreadKill() {
  echo -n "Checking for pthread_kill, "
  if [ -z "$HASPTHREADKILL" ]; then
    cat > configure.cpp <<ENDL
#include <pthread.h>
#include <signal.h>
int main( void) {
  pthread_t thread;
  int n = pthread_kill( thread, SIGHUP);
  return n;
}
ENDL
    if $CPP -pthread configure.cpp -o configure.out 2>> configure.log; then
      echo "found."
      HASPTHREADKILL="yes"
    else
      echo "not found."
      HASPTHREADKILL="no"
      echo "Warning: pthread_kill was *NOT* found on the system, we will"
      echo "         have-to signal ALL threads to pass messages. Not a "
      echo "         big deal, just not quite as efficient."
    fi
  else
    echo "skipping."
  fi
}

#===
# checkPoll
checkPoll() {
  echo -n "Checking for POLL, "
  if [ -z "$USEPOLL" ]; then
  # 1) Check for FreeBSD style poll
  cat > configure.cpp <<ENDL
#include <sys/types.h>
#include <poll.h>
const int MAX_FD = 1;
int main( void) {
  struct pollfd fds[ MAX_FD];
  poll( &fds[0], MAX_FD, 1000);
  return( 0);
}
ENDL
  if $CPP configure.cpp -o configure.out 2>> configure.log; then
    echo "found <poll.h>."
    USEPOLL="poll"
  else
    # 2) Check for Linux Style poll
    cat >> configure.cpp <<ENDL
#include <sys/poll.h>
const int MAX_FD = 1;
int main( void) {
  struct pollfd fds[ MAX_FD];
  poll( &fds[0], MAX_FD, 1000);
  return( 0);
}
ENDL
    if $CPP configure.cpp -o configure.out 2>> configure.log; then
      echo "found <sys/poll.h>."
      USEPOLL="syspoll"
    else
      echo "not found."
      echo -n "Checking for SELECT, "
      # 3) Fine, let's try for select
      cat > configure.cpp <<ENDL
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main( void) {
  fd_set rfds;
  FD_ZERO(&rfds);
  FD_SET(0, &rfds);
  struct timeval tv;
  tv.tv_usec = 1;
  tv.tv_usec = 0;
  int n = select(1, &rfds, NULL, NULL, &tv);
  return 0;
}
ENDL
      if $CPP configure.cpp -o configure.out 2>> configure.log; then
        echo "found."
        USEPOLL="select"
      else
        echo "not found."
        echo "We were unable to find either <poll.h>, <sys/poll.h>, or"
        echo "a means to use select. You can try using"
        echo "  ./configure --force_select"
        echo "If you know you have select."
        exit 1;
      fi
    fi
  fi
  else
    echo "skipping."
  fi
}

#===
# checkSignedChar
checkSignedChar() {
  echo -n "Checking for signed char, "
  if [ -z "$HASSIGNEDCHAR" ]; then
    cat > configure.cpp <<ENDL
#include <stdio.h>
int main( void) {
  char a = -1;
  if (a != -1)
    printf("no");
  else
    printf("yes");
  return 0;
}
ENDL
    if $CPP configure.cpp -o configure.out 2>> configure.log; then
      HASSIGNEDCHAR=`./configure.out`;
      echo "$HASSIGNEDCHAR";
    else
      echo "error."
      echo "Unable to compile the test program to see if the system has"
      echo "a signed char. Use --force_signedchar on most x86 platforms"
      echo "or --force_unsignedchar on most PPC platforms. Do report"
      echo "this bug though, so we can solve it. :)"
      exit 1
    fi
  else
    echo "skipping.";
  fi
}

#===
# writeConfig
writeConfig() {
  echo "==="
  echo "Creating config.h"
  echo "// This file is auto-generated. See the configure script" > config.h
  echo "#ifndef CONFIG_H" >> config.h
  echo "#define CONFIG_H" >> config.h

  echo "#define VERSION \"$VERSION\"" >> config.h

  case "$ACTION" in
    console) echo "#define DISP_CON" >> config.h;;
    gtk)     echo "#define DISP_GTK" >> config.h;;
    *) break;;
  esac

  case "$USEPOLL" in
    poll) echo "#define USE_POLL" >> config.h;;
    syspoll) echo "#define USE_SYSPOLL" >> config.h;;
    select) echo "#define USE_SELECT" >> config.h;;
  esac

  case "$HASPTHREADKILL" in
    yes) echo "#define HAS_PTHREADKILL" >> config.h;;
    no)  echo "// #define HAS_PTHREADKILL" >> config.h;;
  esac

  case "$DEBUG" in
    yes) echo "#define DEBUG" >> config.h;;
    no)  echo "// #define DEBUG" >> config.h;;
  esac

  case "$HASSIGNEDCHAR" in
    yes) echo "// #define USE_UNSIGNEDCHAR" >> config.h;;
    no) echo "#define USE_UNSIGNEDCHAR" >> config.h;;
  esac

  case "$HASDLFCN" in
    yes) echo "#define HAS_DLFCN" >> config.h;;
    no) echo "// #define HAS_DLFCN" >> config.h;;
  esac

  case "$HASNCURSESCOLOR" in
    yes) echo "#define HAS_NCURSESCOLOR" >> config.h;;
    no) echo "// #define HAS_NCURSESCOLOR" >> config.h;;
  esac

  echo "#endif" >> config.h
}

#===
# writeMakefile
writeMakefile() {
  echo "==="
  echo "Creating makefile"
  echo "# Makefile for Prolix" > Makefile
  echo "CC=$CPP" >> Makefile
  echo "CFLAGS=$CFLAGS" >> Makefile
  echo "LIBS=$LIBS" >> Makefile

  cat >> Makefile <<ENDL
OBJSMAIN=main.o \\
     auth/cdkey.o auth/sha1.o auth/auththread.o auth/vercheck.o \\
     base/thread.o \\
     bot/botthread.o bot/botlist.o bot/bot.o bot/queuelevels.o bot/queue.o \\
     config/config.o config/object.o config/vars.o \\
     config/userdblist.o config/userdb.o \\
     display/disp.o display/input.o display/displist.o display/dispthread.o \\
     log/log.o log/loglist.o log/logthread.o \\
     modules/modules.o \\
     net/net.o net/netmsgs.o net/netthread.o \\
     dns/dns.o dns/dnsllist.o dns/dnsbtree.o dns/dnsthread.o \\
     parse/string.o parse/lib.o
OBJSNCURSES=display/ncurses.o
OBJSGTK=main/main_gtk.o display/disp-gtk.o
ENDL
  case "$ACTION" in
    console) echo "OBJS=\${OBJSMAIN} \${OBJSNCURSES}" >> Makefile;;
    gtk)     echo "OBJS=\${OBJSMAIN} \${OBJSGTK}" >> Makefile;;
    *) break;;
  esac

  cat Makefile.in >> Makefile
  echo "Now type 'make' to compile"
}

#===
# showVras
showVars() {
  echo "==="
  echo "CFLAGS=$CFLAGS"
  echo "LIBS=$LIBS"
}

#===
# doBase
doBase() {
  checkCpp;
  checkLibDL;
  checkDlfcn;
  checkPoll;
  checkPThread;
  checkPThreadKill;
  checkSignedChar;
  checkExportDynamic;
}

#===
# doConsole
doConsole() {
  cat <<ENDL
#===
# Prolix - Sesquipedalian Chimerical Juju
#   Compiling for console.
ENDL
  doBase;

  checkNCurses;

  writeConfig;
  writeMakefile;
  showVars;
}

#===
# doGtk
doGtk() {
  cat <<ENDL
#===
# Prolix - Sesquipedalian Chimerical Juju
#   Compiling for gtk.
ENDL
  doBase;

  checkGnome;
  checkGtkConfig;

  writeConfig;
  writeMakefile;
  showVars;
}

#===
# doHelp
doHelp() {
  cat <<ENDL
#===
# Prolix - Sesquipedalian Chimerical Juju
#
# Options:
#  --force_select          : Use select, don't check for it.
#  --force_no_pthread_kill : For Darwin mainly
#  --force_signedchar      : char ch = -1; // Does work
#  --force_unsignedchar    : char ch = -1; // Does not work
#  --force_noncursescolor  : For systems that do not have color ncurses
#  --debug                 : Include various debugging
#
# Commands:
#  -c or --console : Build the console version of prolix
#  -h or --help    : This menu
#  -g or --gtk     : Build the gtk version of prolix
#
# Examples:
#    ./configure --console
#  or
#    ./configure --gtk
#
ENDL
}

#===
# Main
ACTION=help
while [ -n "$1" ]; do
case $1 in
  -h) ACTION=help; shift 1;;
  --help) ACTION=help; shift 1;;
  -c) ACTION=console; shift 1;;
  --console) ACTION=console; shift 1;;
  --debug) DEBUG="yes"; shift 1;;
  --force_select) USEPOLL="select"; shift 1;;
  --force_no_pthread_kill) HASPTHREADKILL="no"; shift 1;;
  --force_signedchar) HASSIGNEDCHAR="yes"; shift 1;;
  --force_unsignedchar) HASSIGNEDCHAR="no"; shift 1;;
  --force_noncursescolor) HASNCURSESCOLOR="no"; shift 1;;
  -g) ACTION=gtk; shift 1;;
  --gtk) ACTION=gtk; shift 1;;
  -*) echo "error: no such option $1. -h for help"; exit 1;;
  *) break;;
esac
done

case "$ACTION" in
  help) doHelp;;
  console) doConsole;;
  gtk) doGtk;;
  *) break;;
esac
