#!/bin/sh
# -*- mode: sh; -*-

############################################################
# Copyright (c) 2009-2020 by Aleksey Cheusov
#
# See LICENSE file in the distribution.
############################################################

set -e

LC_ALL=C
export LC_ALL

: ${CHECK_COMMON_SH_DIR:=/usr/pkg/libexec/mk-configure}

##################################################
# options
usage (){
    cat <<'EOF'
mkc_check_custom - tries to compile source file specified by user,
   optionally builds and runs an application, and
   returns the result (1 - build succeded, 0 - build failed,
   other value returned by built application)

Usage:
 mkc_check_custom [OPTIONS] source_file
 mkc_check_custom [OPTIONS] cmd [args...]

OPTIONS:
   -h          display this help
   -t          set the testname (mandatory option)
   -l          build application, not only compile it
   -r          build application and run it
   -m text     A part of verbose message, defaults to -n args
   -s          exit status of executable will be check
   -d          delete cache files and temporary files
   -D          delete cache files
   -e          print 0 if compiler/cmd print something to stderr
   -b          print yes/no instead of 1/0
Examples:
   mkc_check_custom my_custom_test.c
   mkc_check_custom -r mmap_works_perfectly.c
EOF
}

while getopts bdDehlm:rst: f; do
    case "$f" in
	h)
	    usage
	    exit 0;;
	t)
	    testname="$OPTARG";;
	l)
	    buildit=1;;
	r)
	    buildit=1
	    runit=1;;
	m)
	    msg="$OPTARG";;
	s)
	    check_status=1;;
	d)
	    delcache=all;;
	D)
	    delcache=result;;
	e)
	    empty_stderr=1;;
	b)
	    boolean=1;;
	*)
	    echo "Bad option $f" 1>&2
	    exit 1;;
    esac
done
shift `expr $OPTIND - 1`

if test $# -lt 1; then
    usage
    exit 1
fi

if test -z "$testname"; then
    echo 'Option -t should be specified' 1>&2
    usage
    exit 1
fi

##################################################
# initializing
pathpart="${testname}"

. ${CHECK_COMMON_SH_DIR}/mkc_check_common.sh

src_or_exe="$1"

shquote (){
    __cmd=`printf '%s\n' "$1" | sed "s|'|'\\\\\''|g"`
    printf "%s\n" "'$__cmd'"
}

for i in "$@"; do
    cmd="$cmd "`shquote "$1"`
    shift
done

##################################################
# functions
check_itself (){
    if test -x "$src_or_exe"; then
	if test -n "$check_status"; then
	    set +e # workaround for buggy FreeBSD shell
	    if eval "$cmd"; then
		echo 1
	    else
		echo 0
	    fi
	    set -e # workaround for buggy FreeBSD shell
	else
	    eval "$cmd"
	fi
	return 0
    else
	case "$src_or_exe" in
	    *.c)
		compiler="$CC"
		flags="-o $tmpo $CFLAGS $CPPFLAGS $src_or_exe";;
	    *.cc|*.C|*.cxx|*.cpp|*.c++)
		compiler="$CXX"
		flags="-o $tmpo $CXXFLAGS $CPPFLAGS $src_or_exe";;
	    *)
		echo 'Bad filename for custom check. What to do?' 1>&2
		return 1
	esac
    fi

    if test -n "$buildit"; then
	flags="$flags $LDFLAGS $LDADD"
    else
	flags="-c $flags"
    fi

    if test -z "$compiler"; then
	echo "Bad compiler for $src_or_exe. What to do?" 1>&2
	return 1
    fi

    if ! $compiler $flags 2>"$tmperr"; then
	echo 0
    elif test -n "$empty_stderr" -a -s "$tmperr"; then
	echo 0
    else
	echo 1
    fi
}

##################################################
# test
msg=${msg-"custom test $testname"}

check_and_cache "checking ${msg}" "$cache"

##################################################
# clean-ups

KEEP_SOURCE=1 # do not delete user's source file!
cleanup

##################################################
# finishing
case "${boolean}_$ret" in
    1_0) printme 'no\n' 1>&2;;
    1_1) printme 'yes\n' 1>&2;;
    *)   printme '%s\n' "$ret" 1>&2;;
esac

echo $ret
