#!/bin/sh

# This configure script written by Brian Callahan <bcallah@openbsd.org>
# and released into the Public Domain.

asprintfcheck() {
  cat << EOF > conftest.c
#include <stdio.h>
int main(void){asprintf(NULL,NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

c99check() {
  cat << EOF > conftest.c
#include <stdio.h>
int main(void){long long l;printf("%s",__func__);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

cccheck() {
  if [ ! -z "$CC" ] ; then
cat << EOF > conftest.c
int main(void){return 0;}
EOF
    $CC $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
    if [ $? -eq 0 ] ; then
      ./conftest
      if [ $? -eq 0 ] ; then
	rm -f conftest conftest.o conftest.c
	cc="$CC"
	return 0
      else
	echo "could not build working executables"
	echo "Please ensure your C compiler is a native compiler"
	exit 1
      fi
    else
      rm -f conftest conftest.o conftest.c
    fi
  fi

  for compiler in cc clang pcc xlc gcc ; do
cat << EOF > conftest.c
int main(void){return 0;}
EOF

    $compiler $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1

    if [ $? -eq 0 ] ; then
      ./conftest
      if [ $? -eq 0 ] ; then
	rm -f conftest conftest.o conftest.c
	cc="$compiler"
	return 0
      else
	echo "could not build working executables"
	echo "Please ensure your C compiler is a native compiler"
	exit 1
      fi
    else
      rm -f conftest conftest.o conftest.c
    fi
  done
  return 1
}

confstrcheck() {
  cat << EOF > conftest.c
#include <unistd.h>
int main(void){confstr(0,NULL,0);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

cursescheck() {
  cat << EOF > conftest.c
#include <term.h>
#include <curses.h>
int main(void){setupterm(NULL, 0, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c -lcurses > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

deadcheck() {
  cat << EOF > conftest.c
#include <stdlib.h>
__dead usage(void){exit(1);}int main(void){usage();return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

dead2check() {
  cat << EOF > conftest.c
#include <stdlib.h>
__dead2 usage(void){exit(1);}int main(void){usage();return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

issetugidcheck() {
  cat << EOF > conftest.c
#include <unistd.h>
int main(void){issetugid();return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

ncursescheck() {
  cat << EOF > conftest.c
#include <term.h>
#include <ncurses.h>
int main(void){setupterm(NULL, 0, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c -lncurses > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

ncursesncursescheck() {
  cat << EOF > conftest.c
#include <ncurses/term.h>
#include <ncurses/ncurses.h>
int main(void){setupterm(NULL, 0, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c -lncurses > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

pledgecheck() {
  cat << EOF > conftest.c
#include <unistd.h>
int main(void){pledge(NULL,NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

reallocarraycheck() {
  cat << EOF > conftest.c
#include <stdlib.h>
int main(void){reallocarray(NULL, 0, 0);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

setresgidcheck() {
  cat << EOF > conftest.c
#include <sys/types.h>
#include <unistd.h>
int main(void){setresgid(NULL, NULL, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

setresuidcheck() {
  cat << EOF > conftest.c
#include <sys/types.h>
#include <unistd.h>
int main(void){setresuid(NULL, NULL, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

siglistcheck() {
  cat << EOF > conftest.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main(void){printf("%s",sys_siglist[0]);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

signamecheck() {
  cat << EOF > conftest.c
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main(void){printf("%s",sys_signame[0]);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

sig_tcheck() {
  cat << EOF > conftest.c
#include <signal.h>
int main(void){sig_t s;return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

sranddeterministiccheck() {
  cat << EOF > conftest.c
#include <stdlib.h>
int main(void){srand_deterministic(0);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

st_mtimcheck() {
  cat << EOF > conftest.c
#include <sys/stat.h>
int main(void){struct stat s;s.st_mtim.tv_sec=0;return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

st_mtimespeccheck() {
  cat << EOF > conftest.c
#include <sys/stat.h>
int main(void){struct stat s;s.st_mtimespec.tv_sec=0;return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

stravischeck() {
  cat << EOF > conftest.c
#include <stdlib.h>
#include <vis.h>
int main(void){stravis(NULL, NULL, 0);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

strlcatcheck() {
  cat << EOF > conftest.c
#include <string.h>
int main(void){strlcat(NULL,NULL,0);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

strlcpycheck() {
  cat << EOF > conftest.c
#include <string.h>
int main(void){strlcpy(NULL,NULL,0);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

strtonumcheck() {
  cat << EOF > conftest.c
#include <stdlib.h>
int main(void){strtonum(NULL, 0, 0, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

strunvischeck() {
  cat << EOF > conftest.c
#include <stdlib.h>
#include <vis.h>
int main(void){strunvis(NULL, NULL);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

timeraddcheck() {
  cat << EOF > conftest.c
#include <sys/time.h>
int main(void){struct timeval a, b, res;timeradd(&a, &b, &res);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

timersubcheck() {
  cat << EOF > conftest.c
#include <sys/time.h>
int main(void){struct timeval a, b, res;timersub(&a, &b, &res);return 0;}
EOF
  $cc $cflags $ldflags -o conftest conftest.c > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.o conftest.c
    return 0
  else
    rm -f conftest conftest.o conftest.c
    return 1
  fi
}

wflagcheck() {
  cat << EOF > conftest.c
int main(void){return 0;}
EOF
  $cc -w -o conftest conftest.c > /dev/null 2> conftest.err
  grep ':' conftest.err > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
    rm -f conftest conftest.err conftest.o conftest.c
    return 1
  else
    rm -f conftest conftest.err conftest.o conftest.c
    return 0
  fi
}

# Option variables
if [ ! -z "$PREFIX" ] ; then
  prefix="$PREFIX"
else
  prefix="/usr/local"
fi

mandir="$prefix/man"

instprog="oksh"
libs=""
curses=1
instsh=0
static=0

# Options
for opt
do
  case "$opt" in
    --prefix=*)
	prefix=`echo $opt | cut -d '=' -f 2`
	;;
    --mandir=*)
	mandir=`echo $opt | cut -d '=' -f 2`
	;;
    --disable-curses|--enable-curses)
	if [ "x$opt" = "x--disable-curses" ] ; then
	  curses=0
	else
	  curses=1
	fi
	;;
    --disable-ksh|--enable-ksh)
	if [ "x$opt" = "x--enable-ksh" ] ; then
	  instprog="ksh"
	else
	  instprog="oksh"
	fi
	;;
    --disable-sh|--enable-sh)
	if [ "x$opt" = "x--enable-sh" ] ; then
	  instsh=1
	else
	  instsh=0
	fi
	;;
    --disable-static|--enable-static)
	if [ "x$opt" = "x--enable-static" ] ; then
	  static=1
	else
	  static=0
	fi
	;;
    --help|-h)
	echo "Usage: configure [options]"
	echo ""
	echo "Options:"
	printf "  --help or -h            "
	echo "Display this help message"
	printf "  --prefix=PREFIX         "
	echo "Top level install directory is PREFIX [$prefix]"
	printf "  --mandir=MANDIR         "
	echo "Manual pages are installed to MANDIR [$mandir]"
	printf "  --enable-curses         "
	echo "Use curses library for screen clear [default=yes]"
	printf "  --enable-ksh            "
	echo "Install executable as ksh [default=no]"
	printf "  --enable-sh             "
	echo "Install additional sh executable [default=no]"
	printf "  --enable-static         "
	echo "Statically link executables [default=no]"
	exit 1
	;;
    *)
	;;
  esac
done

if [ ! -z "$CFLAGS" ] ; then
  cflags="$CFLAGS -DEMACS -DVI"
else
  cflags="-DEMACS -DVI"
fi

if [ ! -z "$LDFLAGS" ] ; then
  ldflags="$LDFLAGS "
else
  ldflags=""
fi

if [ $static -ne 0 ] ; then
  ldflags="${ldflags}-static"
fi

printf "checking for C compiler... "
cccheck
if [ $? -ne 0 ] ; then
  echo "not found"
  echo "Please install a C compiler and re-run configure."
  exit 1
else
  echo "$cc"
fi

printf "checking if C compiler can compile C99 without -std=c99... "
c99check
if [ $? -ne 0 ] ; then
  echo "no"
  printf "checking if C compiler can compile C99 with -std=c99... "
  cflags="$cflags -std=c99"
  c99check
  if [ $? -ne 0 ] ; then
    echo "no"
    echo "You must have a C99 compiler to build oksh!"
    exit 1
  else
    echo "yes"
  fi
else
  echo "yes"
fi

printf "checking for -w compiler flag... "
wflagcheck
if [ $? -ne 0 ] ; then
  echo "no"
else
  cflags="$cflags -w"
  echo "yes"
fi

printf "checking for OS... "
os=`uname -s`
echo "$os"

case "x$os" in
  "xLinux"|"xCYGWIN"*)
    cflags="$cflags -D_GNU_SOURCE"
    ;;
  "xNetBSD")
    cflags="$cflags -D_OPENBSD_SOURCE"
    ;;
  "xAIX"|"xOS400")
    cflags="$cflags -D_ALL_SOURCE"
    ldflags="-lbsd"
    ;;
esac

cat << EOF > pconfig.h
/* This file automatically generated by configure.  */

EOF

printf "checking for __dead... "
deadcheck
if [ $? -eq 0 ] ; then
  echo "yes"
else
  echo "no"
  printf "checking for __dead2... "
  dead2check
  if [ $? -eq 0 ] ; then
    echo "#define __dead __dead2" >> pconfig.h
    echo "yes"
  else
    echo "#define __dead __attribute__((__no_return__))" >> pconfig.h
    echo "no"
  fi
fi

printf "checking for asprintf... "
asprintfcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_ASPRINTF" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for confstr... "
confstrcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_CONFSTR" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for curses library... "
if [ $curses -eq 1 ] ; then
  cursescheck
  if [ $? -eq 0 ] ; then
    libs="-lcurses"
    echo "#define HAVE_CURSES" >> pconfig.h
    echo "curses.h"
  else
    ncursescheck
    if [ $? -eq 0 ] ; then
      libs="-lncurses"
      echo "#define HAVE_NCURSES" >> pconfig.h
      echo "ncurses.h"
    else
      ncursesncursescheck
      if [ $? -eq 0 ] ; then
	libs="-lncurses"
	echo "#define HAVE_NCURSESNCURSES" >> pconfig.h
	echo "ncurses/ncurses.h"
      else
	echo "#define NO_CURSES" >> pconfig.h
	echo "not found"
	echo "oksh will be built without screen clearing support"
      fi
    fi
  fi
else
  echo "#define NO_CURSES" >> pconfig.h
  echo "disabled by user"
  echo "oksh will be built without screen clearing support"
fi

printf "checking for issetugid... "
issetugidcheck
if [ $? -eq 0 ] ; then
  echo "yes"
else
  echo "#define issetugid(x) 0" >> pconfig.h
  echo "no"
fi

printf "checking for pledge... "
pledgecheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_PLEDGE" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for reallocarray... "
reallocarraycheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_REALLOCARRAY" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for setresgid... "
setresgidcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_SETRESGID" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for setresuid... "
setresuidcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_SETRESUID" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for sig_t... "
sig_tcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_SIG_T" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for srand_deterministic... "
sranddeterministiccheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_SRAND_DETERMINISTIC" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for st_mtim... "
st_mtimcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_ST_MTIM" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for st_mtimespec... "
st_mtimespeccheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_ST_MTIMESPEC" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for stravis... "
stravischeck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_STRAVIS" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for strlcat... "
strlcatcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_STRLCAT" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for strlcpy... "
strlcpycheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_STRLCPY" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for strtonum... "
strtonumcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_STRTONUM" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for strunvis... "
strunvischeck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_STRUNVIS" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for sys_siglist... "
siglistcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_SIGLIST" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for sys_signame... "
signamecheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_SIGNAME" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for timeradd... "
timeraddcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_TIMERADD" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "checking for timersub... "
timersubcheck
if [ $? -eq 0 ] ; then
  echo "#define HAVE_TIMERSUB" >> pconfig.h
  echo "yes"
else
  echo "no"
fi

printf "creating Makefile... "
cat << EOF > Makefile
# This Makefile automatically generated by configure.

CC =		$cc
CFLAGS =	$cflags
EOF

if [ ! -z "$ldflags" ] ; then
cat << EOF >> Makefile
LDFLAGS =	$ldflags
EOF
fi

cat << EOF >> Makefile
PREFIX =	$prefix
MANDIR =	$mandir
PROG =		$instprog

OBJS =	alloc.o asprintf.o c_ksh.o c_sh.o c_test.o c_ulimit.o edit.o \\
	emacs.o eval.o exec.o expr.o history.o io.o jobs.o lex.o mail.o \\
	main.o misc.o path.o shf.o syn.o table.o trap.o tree.o tty.o var.o \\
	version.o vi.o confstr.o reallocarray.o siglist.o signame.o \\
	strlcat.o strlcpy.o strtonum.o unvis.o vis.o

ETS =	\`grep -w \${PREFIX}/bin/\${PROG} /etc/shells > /dev/null; \\
	[ \$\$? -ne 0 ] && echo "\${PREFIX}/bin/\${PROG}" >> /etc/shells\`

all: \${PROG}

\${PROG}: \${OBJS}
	\${CC} \${LDFLAGS} -o \${PROG} \${OBJS} $libs

install:
	install -d \${DESTDIR}\${PREFIX}/bin
	install -d \${DESTDIR}\${MANDIR}/man1
	install -c -s -m 755 \${PROG} \${DESTDIR}\${PREFIX}/bin
	install -c -m 644 oksh.1 \${DESTDIR}\${MANDIR}/man1/\${PROG}.1
EOF

if [ $instsh -ne 0 ] ; then
cat << EOF >> Makefile
	install -d \${DESTDIR}\${PREFIX}/bin
	install -d \${DESTDIR}\${MANDIR}/man1
	install -c -s -m 755 \${PROG} \${DESTDIR}\${PREFIX}/bin/sh
	install -c -m 644 sh.1 \${DESTDIR}\${MANDIR}/man1
EOF
fi

cat << EOF >> Makefile
	@echo "Please add $prefix/bin/$instprog to /etc/shells"
EOF

if [ $instsh -ne 0 ] ; then
cat << EOF >> Makefile
	@echo "Please add $prefix/bin/sh to /etc/shells"
EOF
fi

cat << EOF >> Makefile

test:
	echo "No tests"

clean:
	rm -f \${PROG} \${OBJS}

distclean: clean
	rm -f Makefile pconfig.h
EOF
echo "done"
