# Manually written configuration script for yash
# (C) 2007-2009 magicant
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
# 
# 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, see <http://www.gnu.org/licenses/>.

makefile="Makefile"
makefilein="Makefile.in"
configcache="config.cache"
configlog="config.log"
configh="config.h"
versionh="version.h"
tempsrc=".temp.c"
tempo=".temp.o"
tempout="./.temp.out"
temptxt="./.temp.txt"

target="yash"
package="yash"
version="2.5"
copyrightyear="2007-2009"

# all source files in this directory
sources="alias.c alias.h arith.c arith.h builtin.c builtin.h common.h exec.c exec.h expand.c expand.h hashtable.c hashtable.h history.c history.h job.c job.h input.c input.h option.c option.h mail.c mail.h mksignum.c parser.c parser.h path.c path.h plist.c plist.h redir.c redir.h sig.c sig.h siglist.h strbuf.c strbuf.h util.c util.h variable.c variable.h wfnmatch.c wfnmatch.h yash.h yash.c" 

# object files to be linked as `yash'
objs="arith.o builtin.o exec.o expand.o hashtable.o input.o job.o mail.o option.o parser.o path.o plist.o redir.o sig.o strbuf.o util.o variable.o wfnmatch.o yash.o"
# object files compiled into builtins.a
builtin_objs=""
builtins_archive="builtins.a"

alias_objs="alias.o"
history_objs="history.o"
printf_objs="printf.o"
test_objs="test.o"
ulimit_objs="ulimit.o"

help="no"
gcc=""
debug="no"
enable_alias="yes"
enable_array="yes"
enable_dirstack="yes"
enable_help="yes"
enable_history="yes"
enable_printf="yes"
enable_socket="yes"
enable_test="yes"
enable_ulimit="yes"
ctags_args=""
etags_args=""
unset prefix eprefix bindir cacheentry cachekey checkresult
umask u=rwx,go=rx
cd "$(dirname "$0")"

parseenable() {
    case "$1" in
	*=yes|*=no|*=true|*=false) ;;
	*=*)  echo "$0: $1: invalid option" >&2;  exit 2 ;;
    esac
    opt="${1#--*able-}"
    opt="${opt%%=*}"
    case "$opt" in
	alias)        enable_alias=$2 ;;
	array)        enable_array=$2 ;;
	dirstack)     enable_dirstack=$2 ;;
	help)         enable_help=$2 ;;
	history)      enable_history=$2 ;;
	printf)       enable_printf=$2 ;;
	socket)       enable_socket=$2 ;;
	test)         enable_test=$2 ;;
	ulimit)       enable_ulimit=$2 ;;
	*)            echo "$0: $1: invalid option" >&2;  exit 2 ;;
    esac
}

# parse options
for i
do
    case "$i" in
	-h|--help)
	    help="yes" ;;
	-d|--debug)
	    debug="yes" ;;
	--prefix=*)
	    prefix="${i#--prefix=}" ;;
	--exec-prefix=*)
	    execprefix="${i#--exec-prefix=}" ;;
	--bindir=*)
	    bindir="${i#--bindir=}" ;;
	--enable-*=no|--enable-*=false|--disable-*)
	    parseenable "$i" "no" ;;
	--enable-*)
	    parseenable "$i" "yes" ;;
	?*=*)
	    # parse variable assignment
	    if echo "$i" |
		LC_ALL=C grep -E "^[[:alpha:]][[:alnum:]]*=" >/dev/null
	    then
		eval "${i%%=*}="'${i#*=}'
	    else
		echo "$0: $i: unknown argument" >&2
		exit 1
	    fi
	    ;;
	*)
	    echo "$0: $i: unknown argument" >&2
	    exit 1
    esac
done

if [ x"${help}" = x"yes" ]
then
    cat <<END
Usage: ./configure [options...]

Available options:
  --debug                configure for debug build (GCC required)

Installation options:
  --prefix=PREFIX        install architecture-independent files in PREFIX
                         [/usr/local]
  --exec-prefix=EPREFIX  install architecture-dependent files in EPREFIX
                         [PREFIX]
  --bindir=DIR           install executable in DIR [EPREFIX/bin]

Optional features:
  --enable-FEATURE[=ARG]      enable or disable FEATURE [ARG=yes]
  --disable-FEATURE           disable FEATURE (same as --enable-FEATURE=no)
  --enable-alias              enable aliases
  --enable-array              enable the array builtin
  --enable-dirstack           enable the directory stack (pushd, popd, dirs)
  --enable-help               enable the help builtin
  --enable-history            enable history
  --enable-printf             enable the echo/printf builtins
  --enable-socket             enable socket redirection by /dev/tcp, /dev/udp
  --enable-test               enable the test builtin
  --enable-ulimit             enable the ulimit builtin

Influential environment variables:
  CC, CFLAGS, CADDS, LDFLAGS, LDADDS, LDLIBS, AR, ARFLAGS, INSTALL_PROGRAM
END
    exit 0
fi


trap 'rm -f "${tempsrc}" "${tempo}" "${tempout}" "${temptxt}"' EXIT
trap 'rm -f "${tempsrc}" "${tempo}" "${tempout}" "${temptxt}"; exit 1' \
    HUP INT QUIT ABRT TERM PIPE USR1 USR2
trap '' ALRM

if [ -r "${configcache}" ] &&
    grep -Fqx "uname -a	$(uname -a)" "${configcache}"
then
    havecache="yes"
else
    havecache="no"
    printf "uname -a\t%s\n" "$(uname -a)" >"${configcache}"
fi

exec 4>>"${configcache}"
exec 5>"${configlog}"
exec 6>"${configh}"

echo "===== Configuration log: generated by configure =====" >&5
echo >&5
date >&5
echo >&5
echo "# Invocation command line was:" >&5
echo "%" $(for i in "$0" "$@"; do echo "$i"; done | sed -e '
/[^[:alnum:]./=-]/ {
s/'"'"'/'"'\\''"'/g
s/\(.*\)/'"'"'\1'"'"'/
}') >&5
echo >&5
echo "#" uname -n = $(uname -n) >&5
echo "#" uname -m = $(uname -m) >&5
echo "#" uname -r = $(uname -r) >&5
echo "#" uname -s = $(uname -s) >&5
echo "#" uname -v = $(uname -v) >&5
echo >&5
echo "#" PATH="${PATH}" >&5
echo >&5
echo >&5

echo "/* ${configh##*/}: generated by configure */" >&6

checking () {
    printf "%s" "checking $1... "
    echo >&5
    echo "# checking $1..." >&5
    if [ $# -ge 2 ]
    then
	cachekey="$2"
    else
	unset cachekey
    fi
    unset cacheentry checkresult
}
getcache () {
    if [ x"${havecache}" = x"no" ] || [ x"${cachekey+set}" != x"set" ]
    then
	return 1
    fi
    if cacheentry="$(grep -F "${cachekey}	" "${configcache}")"
    then
	printf "(cached) "
	checkresult="${cacheentry#*	}"
    else
	unset cacheentry
	return 1
    fi
}
checkby () {
    echo "%" "$@" >&5
    eval "$@" >&5 2>&1
    laststatus=$?
    if [ ${laststatus} -eq 0 ]
    then
	checkresult="yes"
    else
	echo "# exit status: ${laststatus}" >&5
	checkresult="no"
	return ${laststatus}
    fi
}
trymake () {
    checkby ${cc} ${cflags} ${CADDS} ${ldflags} ${LDADDS} -o "${tempout}" \
	"${tempsrc}" "$@" ${ldlibs}
}
trycompile () {
    checkby ${cc} ${cflags} ${CADDS} -c -o "${tempo}" "${tempsrc}" "$@"
}
trylink () {
    checkby ${cc} ${ldflags} ${LDADDS} -o "${tempout}" "${tempo}" "$@" ${ldlibs}
}
tryexec () {
    checkby "${tempout}"
}
checked () {
    if [ $# -ge 1 ]
    then
	checkresult="$1"
    fi
    echo "${checkresult}"
    echo "# result: ${checkresult}" >&5
    if [ x"${cachekey+set}" = x"set" ] && [ x"${cacheentry+set}" != x"set" ]
    then
	printf "%s\t%s\n" "${cachekey}" "${checkresult}" >&4
    fi
}
defconfigh () {
    echo "#define" $1 ${2-1} >&6
    echo "# defining $1='${2-1}' in ${configh}" >&5
}
fail () {
    echo "configuration failed" >&2
    exit 1
}

cc="${CC:-c99}"
cflags="${CFLAGS--O1 -g}"
ldflags="${LDFLAGS}"
ldlibs="${LDLIBS--lm}"
ar="${AR:-ar}"
arflags="${ARFLAGS--rc}"

# check OS type
checking "operating system"
ostype=$(uname -s | tr "[:upper:]" "[:lower:]")
checked "${ostype}"
case "${ostype}" in
    darwin)
	defconfigh "_DARWIN_C_SOURCE"
	;;
esac

# check POSIX conformance
checking "POSIX conformance"
posix=$(getconf _POSIX_VERSION 2>/dev/null)
if [ -n "${posix}" ] && [ x"${posix}" != x"undefined" ]
then
    checked "${posix}"
    if [ "${posix}" -lt 200112 ]
    then
	posix=""
    fi
else
    posix=""
    checked "no"
fi

# check SUS conformance
if [ -n "${posix}" ]
then
    checking "SUS conformance"
    xopen=$(getconf _XOPEN_VERSION 2>/dev/null)
    if [ -n "${xopen}" ] && [ x"${xopen}" != x"undefined" ]
    then
	checked "${xopen}"
	if [ "${xopen}" -lt 600 ]
	then
	    xopen=""
	fi
    else
	xopen=""
	checked "no"
    fi
fi

# determine the compiler and its flags
if [ x"${debug}" = x"yes" ]
then
    checking "whether GCC is available"
    if checkby "${CC:-gcc} --version | grep -i gcc"
    then
	checked "yes"
	gcc="yes" cc="${CC:-gcc}"
	cflags="-std=c99 -pedantic -O1 -fno-inline -ggdb -Wall -Wextra"
    else
	checked "no"
	echo "--debug option specified but GCC is not available" 2>&1
	fail
    fi
fi
if [ x"${debug}" = x"no" ]
then
    defconfigh "NDEBUG"
fi

# check if the compiler works
checking "whether the compiler works"
cat >"${tempsrc}" <<END
int main() { return 0; }
END
if trymake && tryexec
then
    checked "yes"
else
    checked "no"
    fail
fi

# check if the compiler accepts the -O2 option if we are not debugging
if [ x"${debug}" = x"no" ]
then
    checking "whether the compiler accepts -O2 flag"
    cat >"${tempsrc}" <<END
int main() { return 0; }
END
    savecflags=${cflags}
    cflags="-O2 -g"
    if trycompile
    then
	checked "yes"
    else
	checked "no"
	cflags=${savecflags}
    fi
    unset savecflags
fi

# check whether system has /proc/self/exe
checking "whether system has /proc/self/exe"
if [ -x /proc/self/exe ]
then
    checked "yes"
    defconfigh "HAVE_PROC_SELF_EXE"
else
    checked "no"
fi

# check for strnlen
checking "for strnlen" strnlen
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#include <stddef.h>
size_t strnlen(const char*, size_t);
int main() { return strnlen("12345", 3) != 3; }
END
	trymake && tryexec
    fi
then
    defconfigh "HAVE_STRNLEN"
fi
checked

# check for wcsnlen
checking "for wcsnlen" wcsnlen
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#include <stddef.h>
size_t wcsnlen(const wchar_t*, size_t);
int main() { return wcsnlen(L"12345", 3) != 3; }
END
	trymake && tryexec
    fi
then
    defconfigh "HAVE_WCSNLEN"
fi
checked

# check if sys/stat.h defines S_ISVTX
checking "if <sys/stat.h> defines S_ISVTX" S_ISVTX
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#define _POSIX_C_SOURCE 200112
#define _XOPEN_SOURCE   600
#include <sys/stat.h>
int main() { return S_ISVTX & 0; }
END
	trymake
    fi
then
    defconfigh "HAVE_S_ISVTX"
fi
checked

# check for eaccess
checking "for eaccess" eaccess
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#define _POSIX_C_SOURCE 200112
#include <unistd.h>
extern int eaccess(const char *, int);
int main() { (void) eaccess(".", F_OK | R_OK | W_OK | X_OK); }
END
	trymake
    fi
then
    defconfigh "HAVE_EACCESS"
fi
checked

# check for strsignal
checking "for strsingal" strsignal
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#define _POSIX_C_SOURCE 200112
#include <signal.h>
extern char *strsignal(int);
int main() { (void) strsignal(SIGKILL); }
END
	trymake
    fi
then
    defconfigh "HAVE_STRSIGNAL"
fi
checked

# check for paths.h
checking "for paths.h" paths.h
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#include <paths.h>
#include <stdio.h>
int main() { printf("%s\n", _PATH_BSHELL); }
END
	trycompile
    fi
then
    defconfigh "HAVE_PATHS_H"
fi
checked

# check if getcwd accepts (NULL,0) as argument
checking "if getcwd(NULL,0) returns malloc'ed string" getcwd:automalloc
if
    if getcache
    then
	[ x"${checkresult}" = x"yes" ]
    else
	cat >"${tempsrc}" <<END
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
char *xgetcwd(void) {
    size_t pwdlen = 80;
    char *pwd = malloc(pwdlen);
    if (!pwd) return NULL;
    while (getcwd(pwd, pwdlen) == NULL) {
	if (errno == ERANGE) {
	    pwdlen *= 2;
	    pwd = realloc(pwd, pwdlen);
	    if (!pwd) return NULL;
	} else {
	    free(pwd);
	    return NULL;
	}
    }
    return pwd;
}
int main(void) {
    char *wd1 = getcwd(NULL, 0);
    if (!wd1) return 1;
    char *wd2 = xgetcwd();
    if (!wd2 || strcmp(wd1, wd2) != 0) return 1;
    char *wd11 = realloc(wd1, strlen(wd1) + 10);
    if (!wd11 || strcmp(wd11, wd2) != 0) return 1;
    free(wd11); free(wd2); return 0;
}
END
	trymake && tryexec
    fi
then
    defconfigh "GETCWD_AUTO_MALLOC"
fi
checked

# enable/disable aliases
if [ x"$enable_alias" = x"yes" ]
then
    defconfigh "YASH_ENABLE_ALIAS"
    objs="$objs $alias_objs"
fi

# enable/disable the array builtin
if [ x"$enable_array" = x"yes" ]
then
    defconfigh "YASH_ENABLE_ARRAY"
fi

# enable/disable the directory stack
if [ x"$enable_dirstack" = x"yes" ]
then
    defconfigh "YASH_ENABLE_DIRSTACK"
fi

# enable/disable the help builtin
if [ x"$enable_help" = x"yes" ]
then
    defconfigh "YASH_ENABLE_HELP"
fi

# enable/disable history
if [ x"$enable_history" = x"yes" ]
then
    defconfigh "YASH_ENABLE_HISTORY"
    objs="$objs $history_objs"
fi

# enable/disable the echo/printf builtins
if [ x"$enable_printf" = x"yes" ]
then
    defconfigh "YASH_ENABLE_PRINTF"
    builtin_objs="$builtin_objs $printf_objs"
fi

# enable/disable socket redirection
if [ x"$enable_socket" = x"yes" ]
then
    defconfigh "YASH_ENABLE_SOCKET"
fi

# enable/disable the test builtin
if [ x"$enable_test" = x"yes" ]
then
    defconfigh "YASH_ENABLE_TEST"
    builtin_objs="$builtin_objs $test_objs"
fi

# check for getrlimit and setrlimit
if [ x"$enable_ulimit" = x"yes" ]
then
    checking "for getrlimit and setrlimit" getrlimit_setrlimit
    if
	if getcache
	then
	    [ x"${checkresult}" = x"yes" ]
	else
	    cat >"${tempsrc}" <<END
#define _XOPEN_SOURCE 600
#include <sys/resource.h>
int main() {
struct rlimit l;
getrlimit(RLIMIT_FSIZE, &l);
setrlimit(RLIMIT_FSIZE, &l);
}
END
	    trymake
	fi
    then
	defconfigh "YASH_ENABLE_ULIMIT"
	builtin_objs="$builtin_objs $ulimit_objs"
    else
	enable_ulimit="no"
    fi
fi
checked

# check for RLIMIT_***
if [ x"$enable_ulimit" = x"yes" ]
then
    for i in LOCKS MEMLOCK MSGQUEUE NICE NPROC RSS RTPRIO SIGPENDING
    do
	checking "for RLIMIT_${i}" "RLIMIT_${i}"
	if
	    if getcache
	    then
		[ x"${checkresult}" = x"yes" ]
	    else
		cat >"${tempsrc}" <<END
#define _XOPEN_SOURCE 600
#include "${configh}"
#include <sys/resource.h>
int main() { return RLIMIT_${i} == RLIMIT_AS; getrlimit(RLIMIT_${i}, 0); }
END
		trymake && tryexec
	    fi
	then
	    defconfigh "HAVE_RLIMIT_${i}"
	fi
	checked
    done
fi

# check if ctags/etags accepts the --recurse option
if ctags --recurse -f /dev/null /dev/null >/dev/null 2>&1
then
    ctags_args='--recurse'
else
    ctags_args='*.[ch]'
fi
if etags --recurse -o /dev/null /dev/null >/dev/null 2>&1
then
    etags_args='--recurse'
else
    etags_args='*.[ch]'
fi


if [ -n "${builtin_objs}" ]
then
    objs="${objs} builtins/${builtins_archive}"
fi

cflags="${cflags} -D HAVE_CONFIG_H"

CC="${CC-${cc}}"
CFLAGS="${CFLAGS-${cflags}} ${CADDS}"
LDFLAGS="${LDFLAGS-${ldflags}} ${LDADDS}"
LDLIBS="${LDLIBS-${ldlibs}}"
AR="${AR-${ar}}"
ARFLAGS="${ARFLAGS-${arflags}}"
CTAGSARGS="${ctags_args}"
ETAGSARGS="${etags_args}"
SOURCES="${sources}"
OBJS="${objs}"
BUILTIN_OBJS="${builtin_objs}"
BUILTINS_ARCHIVE="${builtins_archive}"
PACKAGE="${package}"
TARGET="${target}"
VERSION="${version}"
INSTALL_PROGRAM="${INSTALL_PROGRAM-./install-sh}"
PREFIX="${prefix-/usr/local}"
EPREFIX="${eprefix-${PREFIX}}"
if [ x"${PREFIX}" = x"/" ]; then PREFIX=""; fi
if [ x"${EPREFIX}" = x"/" ]; then EPREFIX=""; fi
BINDIR="${bindir-${EPREFIX}/bin}"
DISTDIR=$(echo $PACKAGE $VERSION | sed -e 's/[[:space:]]/-/g')

# create Makefile($1) from Makefile.in($2)
makemakefile () {
    printf "%s" "creating $1... "
    sed -e "1i\\
# ${1##*/}: generated by configure" -f "${temptxt}" "$2" >"$1"
    echo "done"
}
cat <<END >"${temptxt}"
s!@CC@!${CC}!g
s!@CFLAGS@!${CFLAGS}!g
s!@LDFLAGS@!${LDFLAGS}!g
s!@LDLIBS@!${LDLIBS}!g
s!@AR@!${AR}!g
s!@ARFLAGS@!${ARFLAGS}!g
s!@CTAGSARGS@!${CTAGSARGS}!g
s!@ETAGSARGS@!${ETAGSARGS}!g
s!@SOURCES@!${SOURCES}!g
s!@OBJS@!${OBJS}!g
s!@BUILTIN_OBJS@!${BUILTIN_OBJS}!g
s!@BUILTINS_ARCHIVE@!${BUILTINS_ARCHIVE}!g
s!@PACKAGE@!${PACKAGE}!g
s!@TARGET@!${TARGET}!g
s!@VERSION@!${VERSION}!g
s!@INSTALL_PROGRAM@!${INSTALL_PROGRAM}!g
s!@PREFIX@!${PREFIX}!g
s!@EPREFIX@!${EPREFIX}!g
s!@BINDIR@!${BINDIR}!g
s!@DISTDIR@!${DISTDIR}!g
END
for d in . builtins
do
    makemakefile "${d}/${makefile}" "${d}/${makefilein}"
done

echo >&5
echo "===== Output variables =====" >&5
echo CC="'${CC}'" >&5
echo CFLAGS="'${CFLAGS}'" >&5
echo LDFLAGS="'${LDFLAGS}'" >&5
echo LDLIBS="'${LDLIBS}'" >&5
echo AR="'${AR}'" >&5
echo ARFLAGS="'${ARFLAGS}'" >&5
echo CTAGSARGS="'${CTAGSARGS}'" >&5
echo ETAGSARGS="'${ETAGSARGS}'" >&5
echo SOURCES="'${SOURCES}'" >&5
echo OBJS="'${OBJS}'" >&5
echo BUILTIN_OBJS="'${BUILTIN_OBJS}'" >&5
echo BUILTINS_ARCHIVE="'${BUILTINS_ARCHIVE}'" >&5
echo PACKAGE="'${PACKAGE}'" >&5
echo TARGET="'${TARGET}'" >&5
echo VERSION="'${VERSION}'" >&5
echo INSTALL_PROGRAM="'${INSTALL_PROGRAM}'" >&5
echo PREFIX="'${PREFIX}'" >&5
echo EPREFIX="'${EPREFIX}'" >&5
echo BINDIR="'${BINDIR}'" >&5
echo DISTDIR="'${DISTDIR}'" >&5


# create version.h
printf "%s" "creating ${versionh}... "
cat >"${versionh}" <<END
/* ${versionh##*/}: generated by configure */
#ifndef YASH_VERSION_H
#define YASH_VERSION_H
#define PACKAGE_NAME "${PACKAGE}"
#define PACKAGE_STRING "${PACKAGE} ${VERSION}"
#define PACKAGE_VERSION "${VERSION}"
#define PACKAGE_COPYRIGHT "Copyright (C) ${copyrightyear} magicant"
#endif
END
echo "done"


echo "configuration complete"


# print warning if POSIX conformance is missing
if [ -z "${posix}" ]; then
    echo "WARNING: yash is designed for systems that conform to POSIX.1-2001"
    echo "         but your system does not"
fi


# vim: set ft=sh ts=8 sts=4 sw=4 noet:
