DEPENDS="path"

### section configure

option()
{
    _default_cachedir="${LOCALSTATEDIR}/lib"
    _default_configdir="${DATADIR}/config"

    case "$LOCALSTATEDIR" in
        "/var")
            _default_cachedir="/var/lib/likewise"
            ;;
        "/private/var")
            _default_cachedir="/private/var/lib/likewise"
            ;;
    esac

    case "$MK_HOST_OS" in
        aix)
            _default_initdir="/etc/rc.d/init.d"
            ;;
        freebsd)
            _default_initdir="/etc/rc.d"
            ;;
        hpux)
            _default_initdir="/sbin/init.d"
            ;;
        *)
            _default_initdir="/etc/init.d"
            ;;
    esac

    mk_option \
        OPTION=lw-tool-dir \
        PARAM="name" \
        VAR=LW_TOOL_DIRNAME \
        DEFAULT="tools" \
        HELP="Subdirectory of build root where developer tools are placed"

    mk_option \
        OPTION=lw-cachedir \
        PARAM="path" \
        VAR=LW_CACHEDIR \
        DEFAULT="${_default_cachedir}" \
        HELP="Location of cache files"

    mk_option \
        OPTION=lw-configdir \
        PARAM="path" \
        VAR=LW_CONFIGDIR \
        DEFAULT="${_default_configdir}" \
        HELP="Location of registry files"

    mk_option \
        OPTION=lw-initdir \
        PARAM="path" \
        VAR=LW_INITDIR \
        DEFAULT="${_default_initdir}" \
        HELP="Location where init scripts should be installed"
}

configure()
{
    mk_msg "cache dir: $LW_CACHEDIR"
    mk_msg "config dir: $LW_CONFIGDIR"
    mk_msg "init script dir: $LW_INITDIR"
    mk_msg "developer tool dir: $LW_TOOL_DIRNAME"

    LW_TOOL_DIR="@$LW_TOOL_DIRNAME"
    _LW_TOOL_TARGETS=""
    _LW_UNIT_TARGETS=""
    _LW_DOC_TARGETS=""
}

lw_add_tool_target()
{
    mk_push_vars result
    mk_resolve_target "$1"
    mk_quote "$result"
    _LW_TOOL_TARGETS="$_LW_TOOL_TARGETS $result"
    mk_pop_vars
}

lw_add_unit_test_target()
{
    mk_push_vars result
    mk_resolve_target "$1"
    mk_quote "$result"
    _LW_UNIT_TARGETS="$_LW_UNIT_TARGETS $result"
    mk_pop_vars
}

lw_add_doc_target()
{
    mk_push_vars result
    mk_resolve_target "$1"
    mk_quote "$result"
    _LW_DOC_TARGETS="$_LW_DOC_TARGETS $result"
    mk_pop_vars
}

lw_define_feature_macros()
{
    case "$MK_OS" in
        linux)
            mk_define __LWI_LINUX__
            mk_define _GNU_SOURCE
            mk_define _XOPEN_SOURCE 500
            mk_define _POSIX_C_SOURCE 200112L
            mk_define _REENTRANT
            ;;
        solaris)
            mk_define __LWI_SOLARIS__
            mk_define _XOPEN_SOURCE 500
            mk_define __EXTENSIONS__
            mk_define _POSIX_PTHREAD_SEMANTICS
            mk_define _REENTRANT
            ;;
        freebsd)
            mk_define __LWI_FREEBSD__
            ;;
        darwin)
            mk_define __LWI_DARWIN__
            ;;
        aix)
            mk_define __LWI_AIX__
            mk_define _THREAD_SAFE
            ;;
        hpux)
            mk_define __LWI_HP_UX__
            mk_define _HPUX_SOURCE 1
            mk_define _REENTRANT
            mk_define _XOPEN_SOURCE_EXTENDED 1
            if [ "$MK_ARCH" = "ia64" ]
            then
                mk_define _XOPEN_SOURCE 500
            fi
            # HACK HACK HACK
            mk_write_config_header "union mpinfou {};"
            ;;
    esac
}

lw_check_iconv()
{
    mk_check_headers FAIL=yes iconv.h
    mk_check_libraries iconv

    mk_msg_checking "iconv() input type"

    if ! mk_check_cache ICONV_IN_TYPE
    then
        # GNU libiconv attempts to mimic the prototype
        # of the system iconv() function, or falls back
        # on char** if it could not find one.  Even if
        # we build libiconv ourselves, we still need to
        # perform these checks so we know what prototype it
        # will use.  This is why we use LDFLAGS to attempt
        # linking to the system libiconv
        if [ "$HAVE_LIB_ICONV" = "internal" ]
        then
            if mk_check_function \
                FUNCTION="iconv_open" \
                HEADERDEPS="iconv.h stddef.h" \
                LDFLAGS="-liconv"
            then
                _ICONV_LDFLAGS="-liconv"
            else
                _ICONV_LDFLAGS=""
            fi
        elif [ "$HAVE_LIB_ICONV" = "external" ]
        then
            _ICONV_LDFLAGS="-liconv"
        fi

        if mk_check_function \
            PROTOTYPE='size_t iconv (iconv_t, char **, size_t *, char **, size_t*)' \
            HEADERDEPS="iconv.h stddef.h" \
            LDFLAGS="$_ICONV_LDFLAGS"
        then
            result="char**"
        elif mk_check_function \
            PROTOTYPE='size_t iconv (iconv_t, const char **, size_t *, char **, size_t*)' \
            HEADERDEPS="iconv.h stddef.h" \
            LDFLAGS="$_ICONV_LDFLAGS"
        then
            result="const char**"
        elif [ "$HAVE_LIB_ICONV" = "internal" ]
        then
            # We didn't find either function, but
            # we build libiconv ourselves, so it
            # should fall back on char**
            result="char**"
        else
            mk_fail "could not find usable iconv() function"
        fi
        mk_cache ICONV_IN_TYPE "$result"
    fi

    mk_msg_result "$ICONV_IN_TYPE"
    mk_define ICONV_IN_TYPE "$ICONV_IN_TYPE"
}

lw_check_strerror_r()
{
    mk_msg_checking "return type of strerror_r"

    if ! mk_check_cache STRERROR_R_RETURN_TYPE
    then
        # Check which version of strerror_r we have
        if mk_check_function \
            PROTOTYPE="char* strerror_r(int,char*,size_t)" \
            HEADERDEPS="string.h"
        then
            result="char*"
        elif mk_check_function \
            PROTOTYPE="int strerror_r(int,char*,size_t)" \
            HEADERDEPS="string.h"
        then
            result="int"
        else
            result="none"
        fi
        mk_cache STRERROR_R_RETURN_TYPE "$result"
    fi

    mk_msg_result "$STRERROR_R_RETURN_TYPE"

    case "$STRERROR_R_RETURN_TYPE" in
        "char*")
            mk_define STRERROR_R_CHAR_P 1
            ;;
        "int")
            mk_define STRERROR_R_INT 1
            ;;
    esac
}

lw_check_pthread_once_init()
{
    mk_msg_checking "broken PTHREAD_ONCE_INIT"

    if ! mk_check_cache HAVE_BROKEN_ONCE_INIT
    then
        if mk_try_compile \
            CODE="pthread_once_t once = PTHREAD_ONCE_INIT; *(&once) = once; return 0;" \
            CFLAGS="-Wall -Werror" \
            HEADERDEPS="pthread.h"
        then
            result="no"
        else
            result="yes"
        fi

        mk_cache HAVE_BROKEN_ONCE_INIT "$result"
    fi

    mk_msg_result "$HAVE_BROKEN_ONCE_INIT"

    if [ "$HAVE_BROKEN_ONCE_INIT" = "yes" ]
    then
        mk_define BROKEN_ONCE_INIT 1
    else
        mk_define BROKEN_ONCE_INIT 0
    fi

    result="$HAVE_BROKEN_ONCE_INIT"
}

lw_check_getsockname()
{
    mk_msg_checking "getsockname takes socklen_t"

    if ! mk_check_cache GETSOCKNAME_TAKES_SOCKLEN_T
    then
        if mk_check_function \
            HEADERDEPS="sys/socket.h" \
            LIBDEPS="$LIB_SOCKET $LIB_NSL" \
            PROTOTYPE="int getsockname(int,struct sockaddr*,socklen_t*)" ||
           mk_check_function \
            HEADERDEPS="sys/socket.h" \
            LIBDEPS="$LIB_SOCKET $LIB_NSL" \
            PROTOTYPE="int getsockname(int,__SOCKADDR_ARG,socklen_t*)" # Hack for clang on linux
        then
            result="yes"
        elif mk_check_function \
            HEADERDEPS="sys/socket.h" \
            LIBDEPS="$LIB_SOCKET $LIB_NSL" \
            PROTOTYPE="int getsockname(int,struct sockaddr*,int*)"
        then
            result="no"
        else
            mk_fail "could not find usable getsockname()"
        fi
        mk_cache GETSOCKNAME_TAKES_SOCKLEN_T "$result"
    fi

    if [ "$GETSOCKNAME_TAKES_SOCKLEN_T" = "yes" ]
    then
        mk_define GETSOCKNAME_TAKES_SOCKLEN_T 1
    else
        mk_define GETSOCKNAME_TAKES_SOCKLEN_T 0
    fi

    mk_msg_result "$GETSOCKNAME_TAKES_SOCKLEN_T"
}

lw_service()
{
    mk_push_vars SERVICE SOURCES GROUPS HEADERDEPS LIBDEPS INCLUDEDIRS CPPFLAGS LDFLAGS CFLAGS CXXFLAGS DEPS
    mk_parse_params

    mk_dlo \
        INSTALLDIR="$MK_LIBDIR/lw-svcm" \
        DLO="$SERVICE" \
        SOURCES="$SOURCES" \
        GROUPS="$GROUPS" \
        HEADERDEPS="$HEADERDEPS" \
        LIBDEPS="$LIBDEPS" \
        INCLUDEDIRS="$INCLUDEDIRS" \
        CPPFLAGS="$CPPFLAGS" \
        CFLAGS="$CFLAGS" \
        CXXFLAGS="$CXXFLAGS" \
        LDFLAGS="$LDFLAGS" \
        DEPS="$DEPS"

    mk_pop_vars
}

lw_moonunit()
{
    mk_moonunit "$@"
    lw_add_unit_test_target "$result"
}

lw_doxygen_html()
{
    mk_doxygen_html "$@"
    lw_add_doc_target "$result"
}

lw_check_endian()
{
    mk_check_endian
    case "$ENDIANNESS" in
        big) mk_define LW_BIG_ENDIAN;;
        little) mk_define LW_LITTLE_ENDIAN;;
    esac
}

lw_check_isa()
{
    case "${MK_ISA}" in
	x86_32)
	    mk_msg "architecture: x86 ($MK_CANONICAL_SYSTEM)"
	    mk_define LW_ISA_X86 1
	    ;;
	x86_64)
	    mk_msg "architecture: x86_64 ($MK_CANONICAL_SYSTEM)"
	    mk_define LW_ISA_X86_64 1
	    ;;
	*)
	    mk_msg "architecture: Unknown.  Expect reduced performance."
	    mk_define LW_ISA_UNKNOWN 1
	    ;;
    esac
}

make()
{
    mk_target \
        TARGET="${LW_TOOL_DIR}" \
        DEPS="$_LW_TOOL_TARGETS"

    mk_add_phony_target "$result"
    mk_add_scrub_target "$result"

    if [ -n "$_LW_UNIT_TARGETS" ]
    then
        mk_target \
            TARGET="@unit-tests" \
            DEPS="$_LW_UNIT_TARGETS"

        mk_add_phony_target "$result"
    fi

    if [ -n "$_LW_DOC_TARGETS" ]
    then
        mk_target \
            TARGET="@doc" \
            DEPS="$_LW_DOC_TARGETS"
    fi
}
