#!/bin/sh

prefix="/usr/local"

cc=cc
cflags="-std=c89 -g -Wall -pedantic -Wno-missing-braces"
cppflags=""

if [ ! -z "$CC" ] ; then
	cc="$CC"
fi

if [ ! -z "$CFLAGS" ] ; then
	cflags="$CFLAGS"
fi

if [ ! -z "$CPPFLAGS" ] ; then
	cppflags="$CPPFLAGS"
fi

for opt
do
	case "$opt" in
	--prefix=*)
		prefix=${opt#*=}
		;;
	--libdir=*)
		libdir=${opt#*=}
		;;
	--bindir=*)
		bindir=${opt#*=}
		;;
	--build=*)
		build=${opt#*=}
		;;
	--host=*)
		host=${opt#*=}
		;;
	CC=*)
		cc=${opt#*=}
		;;
	CFLAGS=*)
		cflags=${opt#*=}
		;;
	CPPFLAGS=*)
		cppflags=${opt#*=}
		;;
	--help|-h)
		echo "Usage: configure [options] (build)"
		echo ""
		echo "Options:"
		echo "  --prefix=PREFIX         Top level install directory [$prefix]"
		echo "  --libdir=LIBDIR         Install directory for builtin headers [PREFIX/lib]"
		echo "  --bindir=BINDIR         Install directory for executable [PREFIX/bin]"
		echo "  --build=machine         Build machine type"
		echo "  --host=machine          Compile for specific host machine type"
		echo "  --help or -h            Display this help message"
		echo ""
		echo "Compiler and flags can be overridden:"
		echo "  CC=                     Compiler [$cc]"
		echo "  CFLAGS=                 Compiler flags [$cflags]"
		echo "  CPPFLAGS=               Preprocessor flags [$cppflags]"
		exit 1
		;;
	-*)
		;;
	*=*)
		;;
	*)
		build=${opt}
		;;
	esac
done

if [ -z "$bindir" ] ; then
	bindir="$prefix/bin"
fi

if [ -z "$libdir" ] ; then
	libdir="$prefix/lib"
fi

cat << EOF > config.mak
# This file was generated by configure.
PREFIX = $prefix
BINDIR = $bindir
LIBDIR = $libdir
CC = $cc
CFLAGS = $cflags
CPPFLAGS = $cppflags
EOF

# Host is the machine type where lacc is run. Detect this after any
# cross compiler has been specified for CC. Default to build if set.
if [ -z "$host" ] ; then
	if [ ! -z "$build" ] ; then
		host=$build
	else
		host=$($cc -dumpmachine)
	fi
fi

# Target is the machine type where compiled libraries or executables
# produced by lacc are run. This is not a cross compiler (yet), so it
# is always the same as host.
target=$host

# Default include paths when resolving #include <...>
includepaths='"/usr/local/include", "/usr/include"'

# Store configuration necessary to instruct how the compiler should work
# on the host. This most importantly includes how to invoke the system
# linker, which varies based on operating system and libc.
echo "/* This file was generated by configure. */" > config.h
echo "#define TARGET \"${target}\"" >> config.h

# Build list of source files depending on target architecture.
case "$host" in
	arm64-*)
		echo '#define ARM64 1' >> config.h
		backend=src/backend/arm64
		;;
	aarch64-*)
		echo '#define ARM64 1' >> config.h
		backend=src/backend/arm64
		;;
	*)
		echo '#define x86_64 1' >> config.h
		backend=src/backend/x86_64
		;;
esac

echo "" >> config.mak
echo "SOURCES = \\" >> config.mak
find src -maxdepth 2 -type f -iname '*.c' | xargs -I '{}' echo "	{} \\" >> config.mak
find $backend -type f -iname '*.c' | xargs -I '{}' echo "	{} \\" >> config.mak
echo "" >> config.mak
echo "HEADERS = \\" >> config.mak
find src -maxdepth 2 -type f -iname '*.h' | xargs -I '{}' echo "	{} \\" >> config.mak
find $backend -type f -iname '*.h' | xargs -I '{}' echo "	{} \\" >> config.mak
echo "" >> config.mak
echo "LIBS = \\" >> config.mak
for source in lib/lacc/include/*.h; do
	echo "	$source \\" >> config.mak
done

case "$host" in
	*-linux-gnu)
		echo '#define UNIX 1' >> config.h
		echo '#define LINUX 1' >> config.h
		echo '#define GLIBC 1' >> config.h
		includepaths="\"/usr/local/include\", \"/usr/include/${host}\", \"/usr/include\""
		;;
	*-linux-musl)
		echo '#define UNIX 1' >> config.h
		echo '#define LINUX 1' >> config.h
		echo '#define MUSL 1' >> config.h
		;;
	*-openbsd*)
		echo '#define UNIX 1' >> config.h
		echo '#define OpenBSD 1' >> config.h
		;;
	*-apple-*)
		echo '#define OSX 1' >> config.h
		includepaths="\"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include\", \"/Library/Developer/CommandLineTools/usr/include\", \"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks\""
		;;
	*)
		echo "warning: Host $host is not recognized."
		;;
esac

libpath="${libdir}/lacc"
includepaths="\"${libpath}/include\", ${includepaths}"

echo "#define INCLUDE_PATHS ${includepaths}" >> config.h
echo "#define LIB_PATH \"${libpath}\"" >> config.h
