#!/bin/sh

if test -f config.mk; then
    exit 0
fi

if test -z "$CC"; then
    CC=cc
fi

if test -z "$YASM"; then
    YASM=yasm
fi

# test yasm
$YASM -f elf64 -o /tmp/secp256k1-$$.o - <<EOF
	BITS 64
	GLOBAL testyasm
	ALIGN 32
testyasm:
	xor r9,r9
EOF
if [ "$?" = 0 ]; then
    $CC $CFLAGS -std=c99 -x c -c - -o /tmp/secp256k1-$$-2.o 2>/dev/null <<EOF
void __attribute__ ((sysv_abi)) testyasm(void);
int main() {
    testyasm();
    return 0;
}
EOF
    $CC $CFLAGS -std=c99 /tmp/secp256k1-$$-2.o /tmp/secp256k1-$$.o -o /dev/null 2>/dev/null
    if [ "$?" = 0 ]; then
        HAVE_YASM=1
    fi
    rm -rf /tmp/secp256k1-$$-2.o /tmp/secp256k1-$$.o
fi

# test openssl
HAVE_OPENSSL=0
$CC $CFLAGS -std=c99 -x c - -o /dev/null -lcrypto 2>/dev/null <<EOF
#include <openssl/bn.h>
int main() {
    BN_CTX *ctx = BN_CTX_new();
    BN_CTX_free(ctx);
    return 0;
}
EOF
if [ "$?" = 0 ]; then
    HAVE_OPENSSL=1
fi

# test openssl/EC
HAVE_OPENSSL_EC=0
if [ "$HAVE_OPENSSL" = "1" ]; then
$CC $CFLAGS -std=c99 -x c - -o /dev/null -lcrypto 2>/dev/null <<EOF
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
int main() {
    EC_KEY *eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
    ECDSA_sign(0, NULL, 0, NULL, NULL, eckey);
    ECDSA_verify(0, NULL, 0, NULL, 0, eckey);
    EC_KEY_free(eckey);
    return 0;
}
EOF
if [ "$?" = 0 ]; then
    HAVE_OPENSSL_EC=1
fi
fi

# test gmp
HAVE_GMP=0
$CC $CFLAGS -std=c99 -x c - -o /dev/null -lgmp 2>/dev/null <<EOF
#include <gmp.h>
int main() {
    mpz_t n;
    mpz_init(n);
    mpz_clear(n);
    return 0;
}
EOF
if [ "$?" = 0 ]; then
    HAVE_GMP=1
fi

# test __int128
HAVE_INT128=0
$CC $CFLAGS -std=c99 -x c - -o /dev/null 2>/dev/null <<EOF
#include <stdint.h>
int main() {
    __int128 x = 0;
    return 0;
}
EOF
if [ "$?" = 0 ]; then
    HAVE_INT128=1
fi

#default limb size
HAVE_LIMB=52

for arg in "$@"; do
    case "$arg" in
        --no-yasm)
            HAVE_YASM=0
            ;;
        --no-gmp)
            HAVE_GMP=0
            ;;
        --no-openssl)
            HAVE_OPENSSL=0
	    ;;
	--use-5x64)
	    HAVE_LIMB=64
            ;;
    esac
done

LINK_OPENSSL=0
LINK_GMP=0
USE_ASM=0

# select field implementation
if [ "$HAVE_YASM" = "1" ]; then
    CFLAGS_FIELD="-DUSE_FIELD_5X$HAVE_LIMB -DUSE_FIELD_5X${HAVE_LIMB}_ASM"
    USE_ASM=1
elif [ "$HAVE_INT128" = "1" ]; then
    CFLAGS_FIELD="-DUSE_FIELD_5X$HAVE_LIMB -DUSE_FIELD_5X${HAVE_LIMB}_INT128"
elif [ "$HAVE_GMP" = "1" ]; then
    CFLAGS_FIELD="-DUSE_FIELD_GMP"
    LINK_GMP=1
else
    CFLAGS_FIELD="-DUSE_FIELD_10X26"
fi

# select num implementation
if [ "$HAVE_GMP" = "1" ]; then
    CFLAGS_NUM="-DUSE_NUM_GMP -DUSE_FIELD_INV_NUM"
    LINK_GMP=1
elif [ "$HAVE_OPENSSL" =  "1" ]; then
    CFLAGS_NUM="-DUSE_NUM_OPENSSL -DUSE_FIELD_INV_BUILTIN"
    LINK_OPENSSL=1
else
    echo "No usable num implementation found" >&2
    exit 1
fi

CFLAGS_EXTRA="$CFLAGS_FIELD $CFLAGS_NUM"
LDFLAGS_EXTRA=""
if [ "$LINK_GMP" = "1" ]; then
    LDFLAGS_EXTRA="-lgmp"
fi
if [ "$LINK_OPENSSL" = "1" ]; then
    LDFLAGS_EXTRA="-lcrypto"
else
    if [ "$HAVE_OPENSSL_EC" = "1" ]; then
        LDFLAGS_TEST_EXTRA="-lcrypto"
    fi
fi

CFLAGS_TEST_EXTRA=""
if [ "$HAVE_OPENSSL_EC" = "1" ]; then
    CFLAGS_TEST_EXTRA="-DENABLE_OPENSSL_TESTS"
fi

echo "CC=$CC" > config.mk
echo "YASM=$YASM" >>config.mk
echo "CFLAGS_EXTRA=$CFLAGS_EXTRA" >> config.mk
echo "CFLAGS_TEST_EXTRA=$CFLAGS_TEST_EXTRA" >> config.mk
echo "LDFLAGS_EXTRA=$LDFLAGS_EXTRA" >> config.mk
echo "LDFLAGS_TEST_EXTRA=$LDFLAGS_TEST_EXTRA" >> config.mk
echo "USE_ASM=$USE_ASM" >>config.mk
echo "HAVE_LIMB=$HAVE_LIMB" >>config.mk
echo "OPTLEVEL=O2" >>config.mk
