#!/bin/sh
#
#	configure - configure script for DeuTex
#	AYM 2005-08-17
#

# This file is copyright André Majorel 2002-2005.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of version 2 of the GNU General Public License as published by the
# Free Software Foundation.
#
# This program 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
# this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.


set -e

APPNAME=deutex
VERSION=`cat VERSION`

AWK=awk
CC=
# On HP-UX 11.11, /bin/sh unsetting an unset variable returns 1
# On HP-UX 11.11 "x= unset x" is equivalent to "x=; unset x". Same with
# Bash 3.0 except when invoked through #!/bin/sh, in which case it's
# equivalent to "x=".
CFLAGS=
unset CFLAGS
HAVE_INTTYPES=
unset HAVE_INTTYPES
HAVE_SNPRINTF=
INTTYPES=
LDFLAGS=
PREFIX=/usr/local

tmpdir="$TMPDIR"
[ -n "$tmpdir" ] || tmpdir=/tmp
cbasename=${APPNAME}_$$.c
obasename=${APPNAME}_$$.o
ebasename=${APPNAME}_$$
cout=${APPNAME}_$$.out
cerr=${APPNAME}_$$.err


#
#	check - perform a test (given C code compiles and links)
#
check () {
  printf '%s' "$3" >"$tmpdir/$cbasename"
  printf 'checking %s...' "$1"
  if
  (
    cd "$tmpdir"							&&
      "$CC" $CFLAGS -o $obasename -c $cbasename				&&
      "$CC" $LDFLAGS -o $ebasename $obasename
  ) >"$tmpdir/$cout" 2>&1
  then
    echo " yes"
    eval "$2=1"
    return 0
  else
    echo " no"
    sed 's/^/> /' "$tmpdir/$cout"
    eval "$2="
    return 1
  fi
}


#
#	genbool - generate a boolean macro definition
#
genbool () {
  name=$1
  if [ -n "`eval echo \\$HAVE_$name`" ]; then
    echo "#define HAVE_$name"
  else
    echo "#undef  HAVE_$name"
  fi
}


#
#	genh - generate config.h
#
genh () {
  pathname=$BUILDDIR/config.h
  echo generating $pathname
  (
    set -e
    echo '/* DO NOT EDIT -- generated by ./configure */'
    echo
    genbool INTTYPES
    genbool SNPRINTF
    [ -z "$INTTYPES" ] || printf '\n%s\n' "$INTTYPES"
  ) >$pathname
}


#
#	fatal - abort with an error message to stderr
#
fatal ()
{
  printf 'configure: %s\n' "$@" >&2
  exit 1
}


#
#	Parse the command line
#
while [ "$#" -ge 1 ]
do
  case "$1" in
    --help)
      cat <<EOF
Usage:
  configure --help
  configure [--cc string] [--cflags string] [--ldflags strings] [--prefix path]
    [--inttypes auto|no|yes]
EOF
      exit 0
      ;;

    --cc)
      shift
      [ "$#" -ge 1 ] || fatal "--cc requires an argument"
      CC="$1"
      ;;

    --cc=*)
      CC=`expr "x$1" : 'x--cc=\(.*\)'`
      ;;

    --cflags)
      shift
      [ "$#" -ge 1 ] || fatal "--cflags requires an argument"
      CFLAGS="$1"
      ;;

    --cflags=*)
      CFLAGS=`expr "x$1" : 'x--cflags=\(.*\)'`
      ;;

    --ldflags)
      shift
      [ "$#" -ge 1 ] || fatal "--ldflags requires an argument"
      LDFLAGS="$1"
      ;;

    --ldflags=*)
      LDFLAGS=`expr "x$1" : 'x--ldflags=\(.*\)'`
      ;;

    --inttypes)
      shift
      [ "$#" -ge 1 ] || fatal "--inttypes requires an argument"
      HAVE_INTTYPES="$1"
      if [ "x$HAVE_INTTYPES" = xauto ]
      then
	unset HAVE_INTTYPES
      elif [ "x$HAVE_INTTYPES" = xno ]
      then
        HAVE_INTTYPES=
      elif [ "x$HAVE_INTTYPES" = xyes ]
      then
	HAVE_INTTYPES=1
      else
	fatal "--inttypes: the argument must be \"auto\", \"no\" or \"yes\""
      fi
      ;;

    --inttypes=*)
      HAVE_INTTYPES=`expr "x$1" : 'x--inttypes=\(.*\)'`
      if [ "x$HAVE_INTTYPES" = xauto ]
      then
	unset HAVE_INTTYPES
      elif [ "x$HAVE_INTTYPES" = xno ]
      then
        HAVE_INTTYPES=
      elif [ "x$HAVE_INTTYPES" = xyes ]
      then
	HAVE_INTTYPES=1
      else
	fatal "--inttypes: the argument must be \"auto\", \"no\" or \"yes\""
      fi
      ;;

    --prefix)
      shift
      [ "$#" -ge 1 ] || fatal "--prefix requires an argument"
      PREFIX="$1"
      ;;

    --prefix=*)
      PREFIX=`expr "x$1" : 'x--prefix=\(.*\)'`
      ;;

    -*)
      echo "configure: bad argument \"$1\"" 1>&2
      exit 1
      ;;

    *)
      echo "configure: too many arguments" 1>&2
      exit 1
  esac
  shift
done

#
#	Sanity checks
#
if expr "x$PREFIX" : x/ >/dev/null
then
  true
else
  echo "configure: --prefix: argument is not an absolute path" 1>&2
  exit 1
fi

# Solaris /bin/grep doesn't know about -Fx.
GREP=/usr/xpg4/bin/grep
[ -x $GREP ] || GREP=grep

#
#	Look for a C compiler
#
#	We try "gcc" first as commercial Unixen often have a bundled
#	"cc" command that's useless for our purposes (antiquated KNR
#	compiler or front-end that just hangs waiting for an answer from
#	some licence manager).
#
printf "looking for a C compiler..."
if [ -n "$CC" ]
then
  printf ' using user-supplied value:'
else
  CC=gcc
  if type $CC >/dev/null 2>&1
  then
    set | $GREP -q '^CFLAGS=' || CFLAGS='-O2 -Wall'
  else
    CC=c89
    if type $CC >/dev/null 2>&1
    then
      set | $GREP -q '^CFLAGS=' || CFLAGS=-O
    else
      CC=cc
      if type $CC >/dev/null 2>&1
      then
	set | $GREP -q '^CFLAGS=' || CFLAGS=-O
      else
	echo " none"
	echo "error: none of (gcc, c89, cc) work, is your PATH set right?" 1>&2
	exit 1
      fi
    fi
  fi
fi
echo " $CC"

#
#	does the C compiler actually work ?
#
printf "checking whether the C compiler works..."
(
  cd "$tmpdir"
  echo 'main (int argc, char *argv[]) { return 0; }' >$cbasename
  if
  (
    "$CC" $CFLAGS -o $obasename -c $cbasename				&&
    rm -f $ebasename							&&
    "$CC" $LDFLAGS -o $ebasename $obasename				&&
    ./$ebasename
  ) >$cout 2>&1
  then
    echo " yes"
  else
    echo " no"
    sed 's/^/> /' $cout
    echo "error: looks like the C compiler is not working" 1>&2
    exit 1
  fi
)

#
#	Do we have snprintf() ?
#
check "for snprintf" HAVE_SNPRINTF '
#include <stdio.h>
int main (int argc, char *argv[])
{
  char buf[1];
  int n = snprintf (buf, sizeof buf, "%d", 42);
  return n;
}
' || true

#
#	Do we have inttypes.h ?
#
printf 'checking for inttypes.h...'
if [ -n "$HAVE_INTTYPES" ]
then
  echo " yes (forced)"
elif set | $GREP -q '^HAVE_INTTYPES='
then
  echo " no (forced)"
else
  if
  (
    cd "$tmpdir"							&&
      cat <<\EOF >$cbasename						&&
#include <inttypes.h>
#include <stdio.h>

#define CHECKSIZE(type, size)						\
do									\
{									\
  printf ("%s %u\n", #type, (unsigned) sizeof (type));			\
  if (sizeof (type) != (size))						\
  {									\
    fflush (stdout);							\
    fprintf (stderr, "inttypes: size of %s is %u, expected %u\n",	\
      #type, (unsigned) sizeof (type), (unsigned) (size));		\
    status = 1;								\
  }									\
}									\
while (0)

int main (int argc, char *argv[])
{
  int status = 0;

  CHECKSIZE (int8_t,   1);
  CHECKSIZE (int16_t,  2);
  CHECKSIZE (int32_t,  4);
  CHECKSIZE (uint8_t,  1);
  CHECKSIZE (uint16_t, 2);
  CHECKSIZE (uint32_t, 4);
  return status;
}
EOF
      "$CC" $CFLAGS -o $obasename -c $cbasename				&&
      rm -f $ebasename							&&
      "$CC" $LDFLAGS -o $ebasename $obasename				&&
      ./$ebasename
  ) >"$tmpdir/$cout" 2>&1
  then
    echo " yes"
    HAVE_INTTYPES=1
  else
    echo " no"
  fi
fi

#
#	If we don't have <inttypes.h>, make our own definitions for
#	{int,uint}{8,16,32}_t
#
if [ -z "$HAVE_INTTYPES" ]
then
  printf 'guessing at appropriate types for {int,uint}{8,16,32}_t...'
  if
  (
    cd "$tmpdir"							&&
      cat <<\EOF >$cbasename						&&
#include <assert.h>
#include <stdio.h>

int main (int argc, char *argv[])
{
  assert (sizeof (signed char) == 1);
  puts ("typedef signed char    int8_t;");
  assert (sizeof (short) == 2);
  puts ("typedef short          int16_t;");
  if (sizeof (long) == 4)
    puts ("typedef long           int32_t;");
  else if (sizeof (int) == 4)
    puts ("typedef int            int32_t;");
  else
    fprintf (stderr,
      "no 32-bit signed type (sizeof (long) = %u, sizeof (int) = %u)\n",
      (unsigned) sizeof (long), (unsigned) sizeof (int));

  assert (sizeof (unsigned char) == 1);
  puts ("typedef unsigned char  uint8_t;");
  assert (sizeof (unsigned short) == 2);
  puts ("typedef unsigned short uint16_t;");
  if (sizeof (unsigned long) == 4)
    puts ("typedef unsigned long  uint32_t;");
  else if (sizeof (unsigned int) == 4)
    puts ("typedef unsigned int   uint32_t;");
  else
    fprintf (stderr,
      "no 32-bit unsigned type (sizeof (unsigned long) = %u, sizeof (unsigned)"
      " = %u)\n",
      (unsigned) sizeof (unsigned long), (unsigned) sizeof (unsigned int));
  return 0;
}
EOF
      "$CC" $CFLAGS -o $obasename -c $cbasename				&&
      rm -f $ebasename							&&
      "$CC" $LDFLAGS -o $ebasename $obasename				&&
      ./$ebasename >$cout 2>$cerr
  )
  then
    echo " success"
    INTTYPES=`cat "$tmpdir/$cout"`
  else
    echo " failure"
    cat "$tmpdir/$cerr"
    echo 'Report this bug to the maintainer!'
    exit 1
  fi
fi

#
#	Locate a POSIX-compatible awk(1)
#
printf "checking for a standard-compliant awk..."
if
(
  cd "$tmpdir"								&&
    echo a | $AWK '{ print sub(/^a/, "b") $0 }' >$cout 2>&1		&&
    [ "x`cat $tmpdir/$cout`" = "x1b" ]
)
then
  echo " yes"
else
  AWK=/usr/xpg4/bin/awk
  if
  (
    cd "$tmpdir"							&&
      echo a | $AWK '{ print sub(/^a/, "b") $0 }' >$cout 2>&1		&&
      [ "x`cat $tmpdir/$cout`" = "x1b" ]
  )
  then
    echo " yes ($AWK)"
  else
    echo " no"
    fatal "no suitable awk found, is your PATH set right?"
  fi
fi

#
#	Create the directory where the build-specific files go
#
SYSTEM_RAW=`uname -n`_`uname -a | cksum`
SYSTEM=`echo "$SYSTEM_RAW" | tr -dc '[:alnum:]._-'`
BUILDDIR=src
echo "build directory is $BUILDDIR"
[ -d $BUILDDIR ] || mkdir -p $BUILDDIR

#
#	FHS paths
#
if expr "$PREFIX" : '//*usr/*$' >/dev/null
then
  BINDIR=/usr/bin		# FHS-ly correct is /usr/games
  ETCDIR=/etc/$APPNAME/%v
  ETCDIRNV=/etc/$APPNAME
  MANDIR=/usr/share/man
  SHAREDIR=/usr/share/games/$APPNAME/%v
  SHAREDIRNV=/usr/share/games/$APPNAME
elif expr "$PREFIX" : '//*usr//*local/*$' >/dev/null
then
  BINDIR=/usr/local/bin		# FHS-ly correct is /usr/local/games
  ETCDIR=/etc/$APPNAME/%v
  ETCDIRNV=/etc/$APPNAME
  MANDIR=/usr/local/man
  SHAREDIR=/usr/local/share/games/$APPNAME/%v
  SHAREDIRNV=/usr/local/share/games/$APPNAME
elif expr "$PREFIX" : '//*opt/*$' >/dev/null
then
  echo '/opt ? Surely you mean /opt/something, Mr. Feynman !' 1>&2
  exit 1
elif expr "$PREFIX" : '//*opt//*[^/]' >/dev/null
then
  BINDIR=$PREFIX/bin
  ETCDIR=/etc/opt/`expr "$PREFIX" : '//*opt//*\(.*\)'`
  ETCDIRNV=
  MANDIR=$PREFIX/man
  SHAREDIR=$PREFIX/share
  SHAREDIRNV=
else					# Probably /home/joe/*
  BINDIR=$PREFIX/bin
  ETCDIR=$PREFIX/etc
  ETCDIRNV=
  MANDIR=$PREFIX/man
  SHAREDIR=$PREFIX/share
  SHAREDIRNV=
fi

#
#	Write Makefile.config
#
echo generating Makefile
(
  echo "# DO NOT EDIT -- generated by ./configure"
  echo
  echo "AWK               = $AWK"
  echo "BINDIR            = $BINDIR"
  echo "CC                = $CC"
  echo "CFLAGS            = $CFLAGS"
  echo "ETCDIR            = $ETCDIR" | sed "s/%v/$VERSION/g"
  echo "ETCDIRNV          = $ETCDIRNV"
  echo "HAVE_INTTYPES     = $HAVE_INTTYPES"
  echo "HAVE_SNPRINTF     = $HAVE_SNPRINTF"
  echo "LDFLAGS           = $LDFLAGS"
  echo "MANDIR            = $MANDIR"
  echo "SHAREDIR          = $SHAREDIR" | sed "s/%v/$VERSION/g"
  echo "SHAREDIRNV        = $SHAREDIRNV"
  echo
  cat Makefile.in
) >Makefile

#
#	Write config.h
#
genh

exit 0
