#!/usr/bin/env sh

# set -o pipefail

CONFIGURE_CMD_ARGS="${*}"

PACKAGE_VERSION="2.9.1"
PACKAGE_DATE="04-Oct-2025"
PACKAGE_STRING="gcli $PACKAGE_VERSION"
PACKAGE_BUGREPORT="https://lists.sr.ht/~herrhotzenplotz/gcli-discuss"
PACKAGE_URL="https://sr.ht/~herrhotzenplotz/gcli"

find_program() {
	varname=$1
	shift

	printf "Checking for $varname ..." >&2
	for x in $*; do
		if command -v $x >/dev/null 2>&1 && [ -x $(command -v $x) ]; then
			binary="$(command -v $x)"
			printf " $binary\n" >&2
			echo "${binary}"
			exit 0
		fi
	done
	printf " not found\n" >&2
	exit 1

}

die() {
	printf "%s\n" "${*}"
	exit 1
}

tolower() {
	tr '[:upper:]' '[:lower:]'
}

check_compiler() {
	command -v "${1}" > /dev/null 2>&1 || die " '${1}' not found"
}

compiler_type() {
	if ${1} -v 2>&1 | grep clang > /dev/null; then
		echo "clang"
	elif ${1} -v 2>&1 | grep '^gcc' > /dev/null; then
		echo "gcc"
	elif ${1} -qversion 2>&1 | grep 'IBM XL C' >/dev/null; then
		echo "xlc"
	elif ${1} -V 2>&1 | grep 'Studio' > /dev/null; then
		echo "sunstudio"
	else
		echo "unknown"
	fi
}

normalise_compiler_target() {
	tolower | sed -e 's|x86_64|amd64|g' -e 's| ||g'
}

compiler_target() {
	ccom=$1
	cc=$2

	case $ccom in
		gcc|clang)
			$cc -v 2>&1 \
				| grep '^Target' \
				| cut -d: -f2
			;;
		xlc)
			# for xlc we can't easily get its target. instead we ask its
			# configured assembler for the target. Right now I assume it
			# is a GNU assembler. If this doesn't work for you please fix!
			# I don't have access to any equipment running anything else
			# and I will not beg IBM for giving me access.
			xlc_config=$($cc -v 2>&1 | grep XL_CONFIG | sed 's|.*XL_CONFIG=\([^:]*\):.*|\1|')
			[ -z "${xlc_config}" ] && die "xlc config file not detected"
			xlc_as=$(cat $xlc_config | grep -E 'as[\t ]+.*=[ ]+' | sed 1q | cut -d= -f2 | sed 's| ||g')
			[ -z "${xlc_as}" ] && die "failed to figure out assembler used by XL C"
			$xlc_as --version 2>&1 | grep 'GNU assembler' >/dev/null || die "Can only derive compiler target from GNU assembler, please submit fix for your assembler"
			$xlc_as --version 2>&1 | grep target | sed "s|.*\`\([^']*\)'.*|\1|"
			;;
		sunstudio)
			# Only tested on Solaris 10 ... if this messes up on Linux or SunOS
			# i86pc feel free to send a patch...
			if $cc -V 2>&1 | grep SunOS_sparc > /dev/null; then
				echo "sparc64-unknown-solaris"
			else
				echo "unknown-unknown-unknown"
			fi
			;;
		*)
			echo "unknown-unknown-unknown"
			;;
	esac | normalise_compiler_target
}

# args= pkgconfig-name variable-name is-mandatory
find_package() {
	printf "Checking for $1 ..." >&2
	if ! $PKG_CONFIG --exists $1; then
		if [ "${3}" = optional ]; then
			printf " not found\n"
			export ${2}_FOUND=0
			return
		else # $3 = required
			die "not found"
		fi
	fi

	# readline and possibly other dependencies in Debian (yikes)
	# return -D_XOPEN_SOURCE which breaks builds. Rip it out -
	# we know what we're doing... ha!
	export ${2}_CFLAGS="$($PKG_CONFIG --cflags $1 | sed 's|-D_XOPEN_SOURCE=[[:digit:]]*||g')"
	export ${2}_LIBS="$($PKG_CONFIG --libs $1)"
	export ${2}_FOUND=1
	export ${2}_VERSION="$($PKG_CONFIG --modversion $1)"

	printf " found\n" >&2
}

usage() {
	cat >&2 <<EOF
usage: ./configure [options]

Configure build directory of gcli.

OPTIONS:
    --prefix=PREFIX         Set installation prefix to PREFIX [DEFAULT: /usr/local]
    --enable-libedit        Search and use libedit for interactive editing [DEFAULT: yes]
    --disable-libedit       Do not use libedit
    --enable-libreadline    Search and use libreadline for interactive editing [DEFAULT: yes]
    --disable-libreadline   Disable use of libreadline
    --enable-liblowdown     Search and use liblowdown for markdown rendering [DEFAULT: yes]
    --disable-liblowdown    Disable use of liblowdown
    --disable-librt         Forcefully disable linking librt [DEFAULT: no, except on Darwin]
    --enable-maintainer     Enable Maintainer Mode [DEFAULT: no]
                            You only want this if you're working on the gcli source code.
                            In this case certain build targets get enabled that only work
                            when the source directory is writable.
    --debug                 Compile without optimisations, generate code with
                            debug information and enable additional compiler-specific
                            warnings and portability checks.
    --release               Optimise for release
    --help                  Print this help

ENVIRONMENT:
    CC                      Host system compiler to use [DEFAULT: cc]
    CC_FOR_BUILD            Build system compiler [DEFAULT: \$CC]
    CFLAGS                  Host system C compiler flags
    CFLAGS_FOR_BUILD        Build system compiler flags
    CPPFLAGS                C Preprocessor flags for host system compiler
    CPPFLAGS_FOR_BUILD      C Preprocessor flags for build system compiler
    LDFLAGS                 Host system linker flags
    LDFLAGS_FOR_BUILD       Build system linker flags
    PKG_CONFIG              pkg-config to use [DEFAULT: autodetect]
    AR                      Archiver to use [DEFAULT: autodetect]
    RANLIB                  Ranlib to use [DEFAULT: autodetect]
    RM                      rm to use [DEFAULT: autodetect]
    KYUA                    Path to Kyua [DEFAULT: autodetect]
    CCACHE                  Path to ccache [DEFAULT: autodetect]
    INSTALL                 Path to install [DEFAULT: autodetect]
    EXEEXT                  File extension of executable files for the host system [DEFAULT: '', '.exe' on Windows]
    OBJEXT                  File extension of object files for the host system [DEFAULT: '.o', '.obj' on Windows]
    LIBEXT                  File extension of static libraries for the host system [DEFAULT: '.a', '.lib' on Windows]
    EXEEXT_FOR_BUILD        File extension of executable files for the build system [DEFAULT: '', '.exe' on Windows]
    OBJEXT_FOR_BUILD        File extension of object files for the build system [DEFAULT: '.o', '.obj' on Windows]
    LIBEXT_FOR_BUILD        File extension of static libraries for the build system [DEFAULT: '.a', '.lib' on Windows]
EOF
	exit 1
}

# Install options
#
PREFIX=/usr/local
OPTIMISE=
ENABLE_LIBEDIT=1
ENABLE_LIBREADLINE=1
ENABLE_LIBLOWDOWN=1
ENABLE_LIBRT=1
ENABLE_MAINTAINER=${ENABLE_MAINTAINER:-0}

# Parse flags
while [ $# -gt 0 ]; do
	case "$1" in
		--prefix=*)
			PREFIX=${1##--prefix=}
			shift
			;;
		--prefix)
			PREFIX=${2}
			shift; shift
			;;
		--enable-libedit)
			ENABLE_LIBEDIT=1
			shift
			;;
		--disable-libedit)
			ENABLE_LIBEDIT=0
			shift
			;;
		--enable-libreadline)
			ENABLE_LIBREADLINE=1
			shift
			;;
		--disable-libreadline)
			ENABLE_LIBREADLINE=0
			shift
			;;
		--enable-liblowdown)
			ENABLE_LIBLOWDOWN=1
			shift
			;;
		--disable-librt)
			ENABLE_LIBRT=0
			shift
			;;
		--disable-liblowdown)
			ENABLE_LIBLOWDOWN=0
			shift
			;;
		--enable-maintainer)
			ENABLE_MAINTAINER=1
			shift
			;;
		--debug)
			OPTIMISE=debug
			shift
			;;
		--release)
			OPTIMISE=release
			shift
			;;
		--help)
			usage
			;;
		*)
			die "error: unknown flag: $1"
			;;
	esac
done

REALPATH=${REALPATH:-$(find_program realpath realpath grealpath)}
[ $? -eq 0 ] || die "error: need realpath" # exit code of find_program()

rel_srcdir="$(dirname ${0})"
srcdir="$(${REALPATH} ${rel_srcdir})"

###############################################################
# COMPILERS
###############################################################

# Host Compiler
printf "Checking host compiler ..."
CC=${CC:-cc}
check_compiler "${CC}"
printf " $CC\n"

# Detect the compiler type and enable dependency tracking
printf "Checking host compiler type ..."
CCOM=$(compiler_type "${CC}")
printf " $CCOM\n"

printf "Checking host compiler target ..."
HOST=$(compiler_target $CCOM "$CC $CFLAGS $CPPFLAGS")
printf " $HOST\n"

# Build compiler
CC_FOR_BUILD=${CC_FOR_BUILD:-${CC}}

printf "Checking for build compiler..."
check_compiler "${CC_FOR_BUILD}"
printf " ${CC_FOR_BUILD}\n"

printf "Checking build compiler type..."
CCOM_FOR_BUILD=$(compiler_type "${CC_FOR_BUILD}")
printf " ${CCOM_FOR_BUILD}\n"

printf "Checking build compiler target ..."
BUILD=$(compiler_target $CCOM_FOR_BUILD $CC_FOR_BUILD)
printf " $BUILD\n"

############################################################################
# LIBRARIES
############################################################################
PKG_CONFIG=${PKG_CONFIG:-$(find_program pkg-config pkg-config pkgconf)}
[ $? -eq 0 ] || die "error: need pkg-config or pkgconf"

find_package libcurl LIBCURL required
find_package atf-c LIBATFC optional
find_package libcrypto LIBCRYPTO required

# Look for libedit if not disabled
if [ $ENABLE_LIBEDIT -eq 1 ]; then
	find_package libedit LIBEDIT optional
else
	LIBEDIT_FOUND=0
fi

# Now only look for readline if libedit hasn't been found/enabled
# and readline support hasn't been disabled.
if [ $LIBEDIT_FOUND -eq 1 ]; then
	LIBREADLINE_FOUND=0
elif [ $ENABLE_LIBREADLINE -eq 1 ]; then
	find_package readline LIBREADLINE optional
else
	LIBREADLINE_FOUND=0
fi

# Lowdown
if [ $ENABLE_LIBLOWDOWN -eq 1 ]; then
	find_package lowdown LIBLOWDOWN optional

	# Workaround for breaking API changes and header without versions:
	#
	# See https://github.com/kristapsdz/lowdown/issues/148
	LIBLOWDOWN_MAJOR=$(echo $LIBLOWDOWN_VERSION | cut -d. -f1)
	LIBLOWDOWN_MINOR=$(echo $LIBLOWDOWN_VERSION | cut -d. -f2)
else
	LIBLOWDOWN_FOUND=0
fi

# If there is no system-provided pdjson, use the vendored one
find_package pdjson PDJSON optional

# On Darwin the POSIX Real-Time extensions are in libc. We must not
# link against librt because it doesn't exist.
if [ $ENABLE_LIBRT -eq 1 ]; then
	printf "Checking whether host is Darwin for -lrt..."
	case "${HOST}" in
		*-apple-darwin*)
			printf " yes, won't link -lrt\n"
			ENABLE_LIBRT=0
			;;
		*)
			printf " no\n"
			;;
	esac
fi

###################################################################
# File extensions for operating systems
#
# LIBEXT refers to static libraries.
guess_extension() {
	# Executables
	if [ "$1" = EXE ]; then
		case "${2}" in
		*mingw*|*cygwin*|*winnt*) echo ".exe" ;;
		*)                        echo "" ;;
		esac

	# Objects
	elif [ "$1" = OBJ ]; then
		case "${2}" in
		*mingw*|*cygwin*|*winnt*) echo ".obj" ;;
		*)                        echo ".o" ;;
		esac

	# Static Libraries
	elif [ "$1" = LIB ]; then
		case "${2}" in
		*mingw*|*cygwin*|*winnt*) echo ".lib" ;;
		*)                        echo ".a" ;;
		esac

	else
		die "internal configure error"
	fi
}

EXEEXT=${EXEEXT:-$(guess_extension EXE $HOST)} || die "error: failed to guess executable extension for $HOST"
OBJEXT=${OBJEXT:-$(guess_extension OBJ $HOST)} || die "error: failed to guess object extension for $HOST"
LIBEXT=${LIBEXT:-$(guess_extension LIB $HOST)} || die "error: failed to guess static library extension for $HOST"

EXEEXT_FOR_BUILD=${EXEEXT_FOR_BUILD:-$(guess_extension EXE $BUILD)} || die "error: failed to guess executable extension for $BUILD"
OBJEXT_FOR_BUILD=${OBJEXT_FOR_BUILD:-$(guess_extension OBJ $BUILD)} || die "error: failed to guess object extension for $BUILD"
LIBEXT_FOR_BUILD=${LIBEXT_FOR_BUILD:-$(guess_extension LIB $BUILD)} || die "error: failed to guess static library extension for $BUILD"

###################################################################
# TESTS and other programs
###################################################################
AR=${AR:-ar}
RANLIB=${RANLIB:-ranlib}
RM=${RM:-rm}
KYUA=${KYUA:-$(find_program kyua kyua)}
CCACHE=${CCACHE:-$(find_program ccache ccache)}
INSTALL=${INSTALL:-$(find_program install install ginstall)}
SHELL=${SHELL:-$(find_program sh sh zsh bash)}
[ $? -eq 0 ] || die "error: need install program"

# If maintainer mode is enabled, we need lowdown(1)
if [ ${ENABLE_MAINTAINER} -eq 1 ]; then
	LOWDOWN=${LOWDOWN:-$(find_program lowdown lowdown)}
fi

###################################################################
# Configure Makefile
###################################################################
#
# FIXME: this escapes the source directory in case it contains
#        spaces. however, both GNU and BSD make are incapable of
#        handling hese situations in combination with VPATH. On
#        NetBSD we get a bug where it hard-splits the path on spaces
#        in a prerequisite no matter whether it is escaped or not.
ESC_SRCDIR="$(echo ${srcdir} | sed -e 's| |\\\\ |g')"

sed \
	-e "s|@SRCDIR@|${ESC_SRCDIR}|g" \
	-e "s|@OPTIMISE@|$OPTIMISE|g" \
	-e "s|@LIBCURL_CFLAGS@|$LIBCURL_CFLAGS|g" \
	-e "s|@LIBCURL_LIBS@|$LIBCURL_LIBS|g" \
	-e "s|@LIBCRYPTO_CFLAGS@|$LIBCRYPTO_CFLAGS|g" \
	-e "s|@LIBCRYPTO_LIBS@|$LIBCRYPTO_LIBS|g" \
	-e "s|@LIBATFC_CFLAGS@|$LIBATFC_CFLAGS|g" \
	-e "s|@LIBATFC_LIBS@|$LIBATFC_LIBS|g" \
	-e "s|@LIBEDIT_FOUND@|$LIBEDIT_FOUND|g" \
	-e "s|@LIBEDIT_CFLAGS@|$LIBEDIT_CFLAGS|g" \
	-e "s|@LIBEDIT_LIBS@|$LIBEDIT_LIBS|g" \
	-e "s|@LIBREADLINE_FOUND@|$LIBREADLINE_FOUND|g" \
	-e "s|@LIBREADLINE_CFLAGS@|$LIBREADLINE_CFLAGS|g" \
	-e "s|@LIBREADLINE_LIBS@|$LIBREADLINE_LIBS|g" \
	-e "s|@LIBLOWDOWN_FOUND@|$LIBLOWDOWN_FOUND|g" \
	-e "s|@LIBLOWDOWN_CFLAGS@|$LIBLOWDOWN_CFLAGS|g" \
	-e "s|@LIBLOWDOWN_LIBS@|$LIBLOWDOWN_LIBS|g" \
	-e "s|@LIBLOWDOWN_MAJOR@|$LIBLOWDOWN_MAJOR|g" \
	-e "s|@LIBLOWDOWN_MINOR@|$LIBLOWDOWN_MINOR|g" \
	-e "s|@PDJSON_FOUND@|$PDJSON_FOUND|g" \
	-e "s|@PDJSON_CFLAGS@|$PDJSON_CFLAGS|g" \
	-e "s|@PDJSON_LIBS@|$PDJSON_LIBS|g" \
	-e "s|@ENABLE_LIBRT@|$ENABLE_LIBRT|g" \
	-e "s|@CONFIGURE_CMD_ARGS@|$CONFIGURE_CMD_ARGS|g" \
	-e "s|@CC@|$CC|g" \
	-e "s|@CCOM@|$CCOM|g" \
	-e "s|@ENV_CFLAGS@|$CFLAGS|g" \
	-e "s|@ENV_LDFLAGS@|$LDFLAGS|g" \
	-e "s|@ENV_LDFLAGS_FOR_BUILD@|$LDFLAGS_FOR_BUILD|g" \
	-e "s|@ENV_CPPFLAGS@|$CPPFLAGS|g" \
	-e "s|@CC_FOR_BUILD@|$CC_FOR_BUILD|g" \
	-e "s|@CCOM_FOR_BUILD@|$CCOM_FOR_BUILD|g" \
	-e "s|@ENV_CFLAGS_FOR_BUILD@|$CFLAGS_FOR_BUILD|g" \
	-e "s|@ENV_CPPFLAGS_FOR_BUILD@|$CPPFLAGS_FOR_BUILD|g" \
	-e "s|@ENV_PKG_CONFIG@|$PKG_CONFIG|g" \
	-e "s|@ENV_PKG_CONFIG_PATH@|$PKG_CONFIG_PATH|g" \
	-e "s|@AR@|$AR|g" \
	-e "s|@CCACHE@|$CCACHE|g" \
	-e "s|@RANLIB@|$RANLIB|g" \
	-e "s|@RM@|$RM|g" \
	-e "s|@KYUA@|$KYUA|g" \
	-e "s|@INSTALL@|$INSTALL|g" \
	-e "s|@SHELL@|$SHELL|g" \
	-e "s|@PREFIX@|$PREFIX|g" \
	-e "s|@PACKAGE_STRING@|$PACKAGE_STRING|g" \
	-e "s|@PACKAGE_DATE@|$PACKAGE_DATE|g" \
	-e "s|@PACKAGE_BUGREPORT@|$PACKAGE_BUGREPORT|g" \
	-e "s|@PACKAGE_URL@|$PACKAGE_URL|g" \
	-e "s|@PACKAGE_VERSION@|$PACKAGE_VERSION|g" \
	-e "s|@EXEEXT@|$EXEEXT|g" \
	-e "s|@OBJEXT@|$OBJEXT|g" \
	-e "s|@LIBEXT@|$LIBEXT|g" \
	-e "s|@EXEEXT_FOR_BUILD@|$EXEEXT_FOR_BUILD|g" \
	-e "s|@OBJEXT_FOR_BUILD@|$OBJEXT_FOR_BUILD|g" \
	-e "s|@LIBEXT_FOR_BUILD@|$LIBEXT_FOR_BUILD|g" \
	-e "s|@ENABLE_MAINTAINER@|$ENABLE_MAINTAINER|g" \
	-e "s|@LOWDOWN@|$LOWDOWN|g" \
	< "${srcdir}/Makefile.in" > Makefile

echo "Writing config.h"
cat > config.h <<EOF
#define PACKAGE_STRING "$PACKAGE_STRING"
#define PACKAGE_URL "$PACKAGE_URL"
#define PACKAGE_VERSION "$PACKAGE_VERSION"
#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
#define PACKAGE_DATE "$PACKAGE_DATE"
#define HOSTOS "$HOST"
EOF

echo "Configuration summary for ${PACKAGE_STRING}:"
echo ""
echo "    Build system type: ${BUILD}"
echo "     Host system type: ${HOST}"
echo "         optimise for: ${OPTIMISE:-none}"
echo " Executable extension: Host: '${EXEEXT}', Build: '${EXEEXT_FOR_BUILD}'"
echo "     Object extension: Host: '${OBJEXT}', Build: '${OBJEXT_FOR_BUILD}'"
echo "    Library extension: Host: '${LIBEXT}', Build: '${LIBEXT_FOR_BUILD}'"
echo "                   CC: ${CC}"
echo "         CC_FOR_BUILD: ${CC_FOR_BUILD}"
echo "               CFLAGS: ${CFLAGS}"
echo "     CFLAGS_FOR_BUILD: ${CFLAGS_FOR_BUILD}"
echo "              LDFLAGS: ${LDFLAGS}"
echo "    LDFLAGS_FOR_BUILD: ${LDFLAGS_FOR_BUILD}"
echo "       LIBCURL_CFLAGS: ${LIBCURL_CFLAGS}"
echo "         LIBCURL_LIBS: ${LIBCURL_LIBS}"
echo "       LIBATFC_CFLAGS: ${LIBATFC_CFLAGS}"
echo "         LIBATFC_LIBS: ${LIBATFC_LIBS}"
if [ $LIBEDIT_FOUND -eq 1 ]; then
echo " Using libedit:"
echo "       LIBEDIT_CFLAGS: ${LIBEDIT_CFLAGS}"
echo "         LIBEDIT_LIBS: ${LIBEDIT_LIBS}"
elif [ $LIBREADLINE_FOUND -eq 1 ]; then
echo " Using libreadline:"
echo "   LIBREADLINE_CFLAGS: ${LIBREADLINE_CFLAGS}"
echo "     LIBREADLINE_LIBS: ${LIBREADLINE_LIBS}"
fi
if [ $LIBLOWDOWN_FOUND -eq 1 ]; then
echo " Using lowdown ${LIBLOWDOWN_VERSION}:"
echo "    LIBLOWDOWN_CFLAGS: ${LIBLOWDOWN_CFLAGS}"
echo "      LIBLOWDOWN_LIBS: ${LIBLOWDOWN_LIBS}"
fi
if [ $PDJSON_FOUND -eq 1 ]; then
echo " Using pdjson:"
echo "        PDJSON_CFLAGS: ${PDJSON_CFLAGS}"
echo "          PDJSON_LIBS: ${PDJSON_LIBS}"
else
echo ""
echo "     WARNING: pdjson not found, using vendored version."
echo "              You may wish to install a system version instead."
fi
if [ $ENABLE_LIBRT -eq 0 ]; then
echo " Not linking -lrt because it was disabled"
fi
if [ $ENABLE_MAINTAINER -eq 1 ]; then
echo ""
echo "     WARNING: Maintainer mode is enabled!"
fi
echo ""
echo "Configuration done. You may now run make."
echo "For more information about available build targets, run 'make help'."
echo ""

# vim: ft=sh
