#!/bin/sh
# $Id: configure,v 1.144 2004/05/14 21:39:36 jmmv Exp $
# Configuration script for buildtool package.
#
# buildtool
# Copyright (c) 2002, 2003, 2004 Julio M. Merino Vidal.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
# 3. Neither the name of the author nor the names of contributors may
#    be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#

PACKAGE=buildtool
VERSION_MAJOR=0
VERSION_MINOR=16
VERSION=${VERSION_MAJOR}.${VERSION_MINOR}

# -------------------------------------------------------------------------
# Functions
# -------------------------------------------------------------------------

usage()
{
# NOLINT_BEGIN
cat <<EOF
${PACKAGE}-${VERSION} automatic configuration tool
usage: ./configure [-h] [-cdeFfimMps dir] [-g gid] [-o uid]

    -c dir    set configuration directory (PREFIX/etc/buildtool)
    -d dir    set documentation directory (PREFIX/share/doc/buildtool)
    -e dir    set exec directory (PREFIX/bin)
    -F dir    set pkgconfig directory (PREFIX/lib/pkgconfig)
    -f dir    set pkgflags directory (PREFIX/share/buildtool/pkgflags)
    -g gid    set group of installed files/directories (none)
    -m dir    set module directory (PREFIX/libexec/buildtool)
    -M dir    set man directory (PREFIX/man)
    -o uid    set owner of installed files/directories (none)
    -p dir    set prefix (/usr/local)
    -s dir    set share directory (PREFIX/share/buildtool)

The prefix \`-p' should be modified before any other directory.

Environment variables that can be used to override checks:
    AWK CC CFLAGS GROFF LDFLAGS LEX SH STRIP YACC
EOF
# NOLINT_END
    exit 0
}

check_mach()
{
    printf "checking for machine type: "
    type=`uname -m`
    if [ "${type}" = powerpc ]; then
        echo "#define TARGET_CHAR unsigned char" >> ${CONFIGH}
    else
        echo "#define TARGET_CHAR signed char" >> ${CONFIGH}
    fi
    printf "${type}\n"
}

check_prog()
{
    var="$1"
    names="$2"
    dirs=`echo ${PATH} | tr ':' ' '`

    eval tmp=\"\${${var}}\"
    if [ -n "${tmp}" ]; then
        printf "using preset value of ${var}: ${tmp}\n"
        echo "${var} = ${tmp}" >> ${CONFIGMK}
        return 0
    fi

    for n in ${names}; do
        printf "checking for program ${n}: "
        for d in ${dirs}; do
            if [ -x ${d}/${n} ]; then
                printf "${d}/${n}\n"
                eval ${var}="${d}/${n}"
                echo "${var} = ${d}/${n}" >> ${CONFIGMK}
                return 0
            fi
        done
        printf "not found\n"
    done
    return 1
}

check_prog_cc() {
    check_prog CC "gcc cc"
    if [ -z "${CC}" ]; then
        echo "ERROR: C compiler not found."
        exit 1
    fi

    printf "checking whether ${CC} is GNU C: "

    cat > bt_test.c <<EOF
#include <stdio.h>

int main(void) {
#ifdef __GNUC__
return 0;
#else
return 1;
#endif
}
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c
    if [ ${cc_status} -ne 0 ]; then
        rm -f bt_test
        printf "failed\n"
        printf "ERROR: C compiler is seriously broken; environment was:\n"
        printf "       CC=${CC}\n"
        printf "       CFLAGS=${CFLAGS}\n"
        exit 1
    fi
    ./bt_test
    if [ $? -eq 0 ]; then
        CC_IS_GNU=yes
        printf "yes\n"
    else
        CC_IS_GNU=no
        printf "no\n"
    fi
    rm -f bt_test
}

check_hdr()
{
    var="$1"
    hdr="$2"

    printf "checking for header ${hdr}: "

    rm -f bt_test.c
    for h in ${INCLUDES}; do
        echo "#include <${h}>" >> bt_test.c
    done
    cat >> bt_test.c <<EOF
#include <${hdr}>
int main() { return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        echo "#define ${var}" >> ${CONFIGH}
        INCLUDES="${INCLUDES} ${hdr}"
        printf "yes\n"
        return 0
    fi
    echo "#undef ${var}" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_func()
{
    var="$1"
    name="$2"

    printf "checking for function ${name}: "
    cat > bt_test.c <<EOF
char ${name}();
int main() { printf("%p", ${name}); return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        echo "#define ${var}" >> ${CONFIGH}
        printf "yes\n"
        return 0
    fi
    echo "#undef ${var}" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_type()
{
    var="$1"
    name="$2"

    printf "checking for type ${name}: "
    rm -f bt_test.c
    for h in ${INCLUDES}; do
        echo "#include <${h}>" >> bt_test.c
    done
    cat >> bt_test.c <<EOF
int main() { ${name} var; return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        echo "#define ${var}" >> ${CONFIGH}
        printf "yes\n"
        return 0
    fi
    echo "#undef ${var}" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_attribute()
{
    printf "checking for __attribute__: "
    if [ ${CC_IS_GNU} = yes ]; then
        cat > bt_test.c <<EOF
static void foo(void) __attribute__((noreturn));
static void foo(void) {}
int main() { return 0; }
EOF
        ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
        cc_status=$?
        rm -f bt_test.c bt_test
        if [ ${cc_status} -eq 0 ]; then
            printf "yes\n"
            return 0
        fi
    fi
    echo "#define __attribute__(x)" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_keyword()
{
    kw=$1
    printf "checking for ${kw}: "
    cat > bt_test.c <<EOF
int main() { ${kw} char *c; return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        printf "yes\n"
        return 0
    fi
    echo "#define ${kw}" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_optreset()
{
    printf "checking for optreset: "
    cat > bt_test.c <<EOF
#include <unistd.h>
int main() { printf("%d", optreset); return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        echo "#define HAVE_OPTRESET" >> ${CONFIGH}
        printf "yes\n"
        return 0
    fi
    echo "#undef HAVE_OPTRESET" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_sys_siglist()
{
    printf "checking for sys_siglist: "
    cat > bt_test.c <<EOF
#include <signal.h>
int main() { printf("%p", sys_siglist); return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        echo "#define HAVE_SYS_SIGLIST" >> ${CONFIGH}
        printf "yes\n"
        return 0
    fi
    echo "#undef HAVE_SYS_SIGLIST" >> ${CONFIGH}
    printf "no\n"
    return 1
}

check_sys_signame()
{
    printf "checking for sys_signame: "
    cat > bt_test.c <<EOF
#include <signal.h>
int main() { printf("%p", sys_signame); return 0; }
EOF
    ${CC} ${CFLAGS} bt_test.c -o bt_test > /dev/null 2>&1
    cc_status=$?
    rm -f bt_test.c bt_test
    if [ ${cc_status} -eq 0 ]; then
        echo "#define HAVE_SYS_SIGNAME" >> ${CONFIGH}
        printf "yes\n"
        return 0
    fi
    echo "#undef HAVE_SYS_SIGNAME" >> ${CONFIGH}
    printf "no\n"
    return 1
}

validate_dir()
{
    var=$1
    eval val=\"\${$1}\"
    if echo ${val} | grep '^/' >/dev/null 2>&1; then :; else
        echo "configure: ${var} must be an absolute path (not \`${val}')" 1>&2
        exit 1
    fi
}

# -------------------------------------------------------------------------
# Main program
# -------------------------------------------------------------------------

# Standard installation directories
PREFIX=/usr/local
DIR_CONF=${PREFIX}/etc/buildtool
DIR_DOC=${PREFIX}/share/doc/buildtool
DIR_EXEC=${PREFIX}/bin
DIR_MAN=${PREFIX}/man
DIR_MODS=${PREFIX}/libexec/buildtool
DIR_PKGCONFIG=${PREFIX}/lib/pkgconfig
DIR_PKGFLAGS=${PREFIX}/share/buildtool/pkgflags
DIR_SHARE=${PREFIX}/share/buildtool

# Owner and group of installed files
OWN=
GRP=

# Optional features
#COMPAT=yes
#WRAPPER=yes

#
# Argument parsing
#

while [ $# -gt 0 ]; do
    echo -- $1 | grep '^-- -' >/dev/null || break

    case $1 in
        -c)
            DIR_CONF=$2
            shift
            ;;
        -d)
            DIR_DOC=$2
            shift
            ;;
        -e)
            DIR_EXEC=$2
            shift
            ;;
        -F)
            DIR_PKGCONFIG=$2
            shift
            ;;
        -f)
            DIR_PKGFLAGS=$2
            shift
            ;;
        -g)
            GRP="$2"
            shift
            ;;
        -m)
            DIR_MODS=$2
            shift
            ;;
        -M)
            DIR_MAN=$2
            shift
            ;;
#        -n)
#            case "$2" in
#                compat)
#                    COMPAT=yes
#                    ;;
#                wrapper)
#                    WRAPPER=no
#                    ;;
#                *)
#                    printf "configure: -n: unknown feature \`$2'\n"
#                    exit 1
#                    ;;
#            esac
#            shift
#            ;;
        -o)
            OWN="$2"
            shift
            ;;
        -p)
            PREFIX=$2
            DIR_CONF=${PREFIX}/etc/buildtool
            DIR_DOC=${PREFIX}/share/doc/buildtool
            DIR_EXEC=${PREFIX}/bin
            DIR_MAN=${PREFIX}/man
            DIR_MODS=${PREFIX}/libexec/buildtool
            DIR_PKGCONFIG=${PREFIX}/lib/pkgconfig
            DIR_PKGFLAGS=${PREFIX}/share/buildtool/pkgflags
            DIR_SHARE=${PREFIX}/share/buildtool
            shift
            ;;
        -s)
            DIR_SHARE=$2
            shift
            ;;
        -h)
            usage
            # NOTREACHED
            ;;
        --)
            shift; break
            ;;
        *)
            echo "configure: unknown option \`$1'" 1>&2
            echo "You can type \`./configure -h' for more information." 1>&2
            exit 1
            ;;
    esac
    shift
done

validate_dir PREFIX
validate_dir DIR_CONF
validate_dir DIR_DOC
validate_dir DIR_EXEC
validate_dir DIR_MAN
validate_dir DIR_MODS
validate_dir DIR_PKGCONFIG
validate_dir DIR_PKGFLAGS
validate_dir DIR_SHARE

#
# Set target files
#

SUBDIR=
SUBDIR="${SUBDIR} bt_config"
SUBDIR="${SUBDIR} bt_dist"
SUBDIR="${SUBDIR} bt_doc"
SUBDIR="${SUBDIR} bt_lint"
SUBDIR="${SUBDIR} bt_logic"
SUBDIR="${SUBDIR} bt_pkgflags"
SUBDIR="${SUBDIR} bt_sh"
SUBDIR="${SUBDIR} bt_swcgen"
SUBDIR="${SUBDIR} bt_wizard"
SUBDIR="${SUBDIR} buildtool"
SUBDIR="${SUBDIR} doc"
SUBDIR="${SUBDIR} mklogic"
SUBDIR="${SUBDIR} templates"
#[ "${WRAPPER}" = yes ] && SUBDIR="${SUBDIR} wrapper"

TARGETS=Makefile
for d in ${SUBDIR}; do
    TARGETS="${TARGETS} ${d}/Makefile"
done

#
# Start configuration process
#

printf "configuring for ${PACKAGE}-${VERSION}\n"

TOPDIR=`pwd`
CONFIGH="${TOPDIR}/config.h"
CONFIGMK="${TOPDIR}/config.mk"
rm -f ${CONFIGMK} ${CONFIGH}
touch ${CONFIGMK} ${CONFIGH}
cat > ${CONFIGH} <<EOF
/* File automatically benerated by Buildtool configuration system
   on `date` */

#ifndef BT_CONFIG_H
#define BT_CONFIG_H

EOF

echo "PACKAGE = ${PACKAGE}" >> ${CONFIGMK}
echo "VERSION = ${VERSION}" >> ${CONFIGMK}
echo "VERSION_MAJOR = ${VERSION_MAJOR}" >> ${CONFIGMK}
echo "VERSION_MINOR = ${VERSION_MINOR}" >> ${CONFIGMK}
echo "TOPDIR = ${TOPDIR}" >> ${CONFIGMK}
echo "WORKDIR = ${WORKDIR}" >> ${CONFIGMK}

echo "#define PACKAGE \"${PACKAGE}\"" >> ${CONFIGH}
echo "#define VERSION \"${VERSION}\"" >> ${CONFIGH}
echo "#define VERSION_MAJOR \"${VERSION_MAJOR}\"" >> ${CONFIGH}
echo "#define VERSION_MINOR \"${VERSION_MINOR}\"" >> ${CONFIGH}

check_mach

#
# Check for required programs
#

check_prog_cc

check_prog STRIP strip
if [ -z "${STRIP}" ]; then
    printf "ERROR: strip binary not found.\n"
    printf "       Set STRIP=true in your environment and try again.\n"
    exit 1
fi

check_prog SH "ksh bash sh"
if [ -z "${SH}" ]; then
    printf "ERROR: Bourne shell interpreter not found.\n"
    exit 1
fi

check_prog AWK "gawk awk"
if [ -z "${AWK}" ]; then
    echo "AWK = echo 'awk not available; cannot lint'; false" >> ${CONFIGMK}
fi

if [ -n "${REGEN_ARITH}" ]; then
    check_prog LEX "flex lex"
    if [ -z "${LEX}" ]; then
        printf "ERROR: lex binary not found.\n"
        exit 1
    fi

    check_prog YACC "yacc byacc bison"
    if [ -z "${YACC}" ]; then
        printf "ERROR: yacc binary not found.\n"
        exit 1
    fi
fi

check_prog GROFF groff
if [ -z "${GROFF}" ]; then
    GROFF=false
fi

#
# Check for headers
#

# Standard headers
check_hdr HAVE_STDIO_H stdio.h
check_hdr HAVE_SYS_CDEFS_H sys/cdefs.h
check_hdr HAVE_SYS_TYPES_H sys/types.h
check_hdr HAVE_SYS_STAT_H sys/stat.h
check_hdr HAVE_SYS_UTSNAME_H sys/utsname.h
check_hdr HAVE_SIGNAL_H signal.h
check_hdr HAVE_STDLIB_H stdlib.h
check_hdr HAVE_STRING_H string.h

# Required by bt_sh
check_hdr HAVE_SYS_PARAM_H sys/param.h
check_hdr HAVE_SYS_RESOURCE_H sys/resource.h
check_hdr HAVE_SYS_SYSCTL_H sys/sysctl.h
check_hdr HAVE_PATHS_H paths.h

#
# Check for functions
#

# Required by bt_sh
check_func HAVE_STRLCPY strlcpy
check_func HAVE_VASPRINTF vasprintf
check_func HAVE__SETJMP _setjmp

#
# Other checks
#
check_func HAVE_GETMODE getmode
check_func HAVE_SETMODE setmode
check_attribute
check_keyword const
check_keyword signed
check_keyword static
check_optreset
check_sys_siglist
check_sys_signame
if check_type HAVE_SIG_T sig_t; then :; else
    echo "typedef void (*sig_t) (int);" >> ${CONFIGH}
fi
if check_type HAVE_SIZE_T size_t; then :; else
    echo "typedef unsigned int size_t;" >> ${CONFIGH}
fi
if check_type HAVE_RLIM_T rlim_t; then :; else
    echo "typedef unsigned long rlim_t;" >> ${CONFIGH}
fi

#
# Write output
#

cat >> ${CONFIGMK} <<EOF
GENFILE = ${TOPDIR}/mklogic/genfile.sh
GENFILE_SH_COMMON = ${TOPDIR}/sh_head.in ${TOPDIR}/sh_tail.in
CFLAGS = -I. -I.. ${CFLAGS}
LDFLAGS = ${LDFLAGS}
DOC = ${DOC}
#WRAPPER = ${WRAPPER}
PREFIX = ${PREFIX}
DIR_CONF = ${DIR_CONF}
DIR_DOC = ${DIR_DOC}
DIR_EXEC = ${DIR_EXEC}
DIR_MAN = ${DIR_MAN}
DIR_MODS = ${DIR_MODS}
DIR_PKGCONFIG = ${DIR_PKGCONFIG}
DIR_PKGFLAGS = ${DIR_PKGFLAGS}
DIR_SHARE = ${DIR_SHARE}
INSTALL_ENV = GRP=${GRP} OWN=${OWN} BIN_MODE=${BIN_MODE} \
              DATA_MODE=${DATA_MODE} DIR_MODE=${DIR_MODE}
INSTALL_DIR = \${INSTALL_ENV} TYPE=dir ${TOPDIR}/mklogic/install.sh
INSTALL_BIN = \${INSTALL_ENV} TYPE=bin ${TOPDIR}/mklogic/install.sh
INSTALL_DATA = \${INSTALL_ENV} TYPE=data ${TOPDIR}/mklogic/install.sh
GROFF_HTML = ${GROFF} -Tlatin1 -mdoc2html -P-b -P-o -P-u
GROFF_MORE = ${GROFF} -Tascii -mdoc -mtty-char
GROFF_PS = ${GROFF} -Tps -mdoc
GROFF_TXT = ${GROFF} -Tascii -mdoc -P-b -P-o -P-u
SUBDIR = ${SUBDIR}
REGEN_ARITH = ${REGEN_ARITH}
EOF

cat >> ${CONFIGH} <<EOF

#endif /* !BT_CONFIG_H */
EOF

#
# Generate Makefile's
#

for t in ${TARGETS}; do
    printf "${t}.in -> ${t}\n"
    cat > ${t} <<EOF
#
# Makefile generated by ${PACKAGE}-${VERSION} configure script
# Changes made here will be lost!
#

# Main target
all: Makefile build

# Detected variables
EOF

    cat ${CONFIGMK} ${TOPDIR}/${t}.in ${TOPDIR}/mklogic/Makefile.tail >> ${t}
done

rm -f ${CONFIGMK}

#
# Generate genfile.sh script
#

subst=
subst="${subst} -e 's|@PACKAGE@|${PACKAGE}|g'"
subst="${subst} -e 's|@VERSION@|${VERSION}|g'"
subst="${subst} -e 's|@VERSION_MAJOR@|${VERSION_MAJOR}|g'"
subst="${subst} -e 's|@VERSION_MINOR@|${VERSION_MINOR}|g'"
subst="${subst} -e 's|@DIR_CONF@|${DIR_CONF}|g'"
subst="${subst} -e 's|@DIR_DOC@|${DIR_DOC}|g'"
subst="${subst} -e 's|@DIR_EXEC@|${DIR_EXEC}|g'"
subst="${subst} -e 's|@DIR_MODS@|${DIR_MODS}|g'"
subst="${subst} -e 's|@DIR_PKGCONFIG@|${DIR_PKGCONFIG}|g'"
subst="${subst} -e 's|@DIR_PKGFLAGS@|${DIR_PKGFLAGS}|g'"
subst="${subst} -e 's|@DIR_SHARE@|${DIR_SHARE}|g'"
#if [ "${COMPAT}" = "yes" ]; then
#    subst="${subst} -e 's|@COMPAT@||g'"
#    subst="${subst} -e 's|@NOCOMPAT@|#|g'"
#else
#    subst="${subst} -e 's|@COMPAT@|#|g'"
#    subst="${subst} -e 's|@NOCOMPAT@||g'"
#fi

echo "mklogic/genfile.sh.in -> mklogic/genfile.sh"
sed -e "s,__SH__,${SH},g" -e "s,__SUBST__,${subst},g" \
    -e "s,__TOPDIR__,${TOPDIR},g" \
    < mklogic/genfile.sh.in > mklogic/genfile.sh
chmod +x mklogic/genfile.sh

#
# Generate install.sh script
#

echo "mklogic/install.sh.in -> mklogic/install.sh"
sed -e "s,__SH__,${SH},g" \
    < mklogic/install.sh.in > mklogic/install.sh
chmod +x mklogic/install.sh

#
# Print configuration summary
#

cat <<EOF

===========================================================================
BUILDTOOL ${VERSION} CONFIGURATION SUMMARY

    Installation prefix: ${PREFIX}
    Configuration directory: ${DIR_CONF}

    Type \`make' to start the build.
    Type \`make install' to install, only _after_ the build has finished.

===========================================================================

EOF
#printf "    Compatibility code: "
#if [ "${COMPAT}" = "no" ]; then
#    printf "disabled\n"
#else
#    printf "enabled\n"
#fi

#if [ "${CC_IS_GNU}" = no ]; then
#    printf "\n*** WARNING ***\n"
#    printf "Using a C compiler (${CC}) that is not GNU C.\n"
#    printf "Install gcc and set the CC variable pointing to it.\n"
#    printf "Then, rerun configure like: CC=/path/to/gcc ./configure\n"
#    printf "*** YOU HAVE BEEN WARNED ***\n"
#fi

exit 0

# Local Variables: ***
# mode: shell-script ***
# End: ***
# vim: syntax=sh
