#!/bin/bash

set -eo pipefail

CC=(@CC@)
CXX=(@CXX@)
PREFIX=@PREFIX@
PLUGIN=@PLUGIN@
SCRIPT=@SCRIPT@

usage() {
    cat 1>&2 <<-EOF
usage: ffi-cdecl [-c compiler] [-d dependency] [-o output.lua] [-n] [-D…|-I…|-U…]* input.c

    -c compiler    Select compiler: c or c++ (otherwise determined by the input extension)
    -d dependency  Add additional cflags from specified pkg-config dependency
    -o output      Set output file (instead of stdout)
    -f flags       Extra flags forwarded to the compiler

    -D/-I/-U       Those flags are forwarded to the compiler

    -n             Dry-run, show final compiler command only
EOF
    exit 1
}

[[ $# -gt 0 ]] || usage

pkg-config() {
    env \
        PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig" \
        pkg-config --env-only --cflags "$@"
}

compiler=''
dry_run=0
output='-'

cflags=(
    -fplugin="${PLUGIN}"
    -fplugin-arg-gcclua-script="${SCRIPT}"
    -I"${PREFIX}/include/ffi-cdecl"
    -I"${PREFIX}/include"
)

while getopts 'c:d:f:o:D:I:U:h:n' opt; do
    case "${opt}" in
        c)
            case "${OPTARG}" in
                c | c++)
                    compiler="${OPTARG}"
                    ;;
                *)
                    usage
                    ;;
            esac
            ;;
        d)
            read -ra a < <(pkg-config --cflags "${OPTARG}")
            cflags+=("${a[@]}")
            ;;
        f)
            declare -a "a=(${OPTARG})"
            cflags+=("${a[@]}")
            ;;
        n)
            dry_run=1
            ;;
        o)
            output="${OPTARG}"
            ;;
        [DIU])
            cflags+=("-${opt}${OPTARG}")
            ;;
        [h?])
            usage
            ;;
    esac
done

shift $((OPTIND - 1))

# echo "OPTIND: ${OPTIND}"
# echo "$#: $@"
# echo "output: ${output}"
# echo "cflags: ${cflags[@]}"
# exit

[[ $# -eq 1 ]] || usage

if [[ -z "${compiler}" ]]; then
    case "$1" in
        *.C | *.cc | *.cpp | *.CPP | *.c++ | *.cp | *.cxx)
            compiler='c++'
            ;;
        *)
            compiler='c'
            ;;
    esac
fi

case "${compiler}" in
    c)
        cmd=("${CC[@]}")
        ;;
    c++)
        cmd=("${CXX[@]}")
        ;;
esac

cmd+=("${cflags[@]}")

cmd+=(-fplugin-arg-gcclua-output=- -S -o /dev/null "$1")

if [[ ${dry_run} -ne 0 ]]; then
    printf '%q ' "${cmd[@]}"
    echo
    exit
fi

result="$("${cmd[@]}")"

if [[ "${output}" != '-' ]]; then
    exec >"${output}"
fi

printf -- '-- Automatically generated with ffi-cdecl.\n\n'
# shellcheck disable=SC2001
sed 's/ __attribute__((visibility("default")));$/;/' <<<"${result}"

# vim: sw=4
