#!/bin/sh

# sh tools/dev/mk_native_pbc [--noconf]
#
# generate t/native_pbc/*_*.pbc
# This should only be run on known systems to regenerate the native pbcs.
# Better do not try that on mingw, use cygwin instead.
#
# NOTE:  For _2/_5/_8 this will need a compiler with long double support
# NOTE2: Installing ccache speeds this process up considerably

#  _1   i386 32 bit opcode_t, 32 bit intval   (linux-gcc-ix86, freebsd-gcc, cygwin)
#  _2   i386 32 bit opcode_t, 32 bit intval, 12 bit long double (linux-gcc-ix86)
#  _3   PPC BE 32 bit opcode_t, 32 bit intval (darwin-ppc)
#  _4   x86_64 double float 64 bit opcode_t   (linux-gcc-x86_64, solaris-cc-64int)
#  _5   x86_64 16 byte long double 64 bit opcode_t (linux-gcc-x86_64, solaris-cc-64int)
#  _6   big-endian 64-bit                     (sparc, irix or similar)
#  _7   i386 32 bit opcode_t, 32 bit intval, 4-byte float --floatval=float
#  _8   big-endian 64-bit 16-byte long-double (sparc64, irix, mips or similar)

#tests:
#parrot -o i.pbc -a - <<EOF
#  print 0x10203040
#  end
#  EOF
# t/op/number_1.pasm
# t/op/string_133.pasm

# check 32/64 bit, endianess, hugefloat
N=
enable_long_double=
conf=
exe=

byteorder=$(./parrot_config byteorder)
ptrsize=$(./parrot_config ptrsize)
# 8 or 12 or 16 on intel
numvalsize=$(./parrot_config numvalsize)

if [ "$ptrsize" = "4" ]
then
    if [ "$byteorder" = "1234" ]
    then
        if [ "$numvalsize" = "12" ]
        then
            N=2
            echo "2: i386 32-bit opcode_t, 32-bit intval, 12-byte long double"
        else
            if [ "$numvalsize" = "4" ]
            then
                N=8
                echo "8: i386 32-bit opcode_t, 32-bit intval, 4-byte float"
            else
                N=1
                echo "1: i386 32-bit opcode_t, 32-bit intval, 8-byte double"
                # try --floatval="long double" and see if that makes 12
                enable_long_double=1
                # force double on 2nd run not to default to long double
                conf=" --floatval=double"
            fi
        fi
    else
        if [ "$byteorder" = "4321" ]
        then
            N=3
            echo "3: PPC BE 32 bit opcode_t, 32 bit intval"
        else
            if [ "$byteorder" = "12345678" \
                 -a "$(./parrot_config osname)" = "cygwin" ]
            then
                echo "1: cygwin use64bitint"
                N=1
                exe=.exe
            else
                echo "Sorry, unsupported perl - parrot ptrsize mismatch."
                exit
            fi
        fi
    fi
else
    if [ "$ptrsize" = "8" ]
    then
        if [ "$byteorder" = "12345678" ]
        then
            if [ "$numvalsize" = "8" ]
            then
                N=4
                echo "4: x86_64 double float 64 bit opcode_t, 8-byte double"
                # try --floatval="long double" and see if that makes 16
                enable_long_double=1
                # force double on 2nd run not to default to long double
                conf=" --floatval=double"
            else
                N=5
                echo "5: x86_64 64 bit opcode_t, 16-byte long double"
            fi
        else
            if [ "$numvalsize" = "8" ]
            then
                N=6
                echo "6: big-endian 64-bit"
                # try --floatval="long double" and see if that makes 16
                enable_long_double=1
                # force double on 2nd run not to default to long double
                conf=" --floatval=double"
            else
                N=7
                echo "7: ppc/BE 64 bit opcode_t, 16-byte long double"
            fi
        fi
    else
        echo "unsupported ptrsize $ptrsize"
        exit 1
    fi
fi

echo ""
if [ "$1" != "--noconf" ]; then
    make -s prog-clean
    perl Configure.pl --debugging $conf --nomanicheck
fi
tail myconfig
make -s || exit 1

./parrot -o t/native_pbc/integer_${N}.pbc -a - <<EOF
print 0x10203040
end
EOF
[ $? -le 0 ] && echo "t/native_pbc/integer_${N}.pbc updated"
./parrot -o t/native_pbc/number_${N}.pbc t/native_pbc/testdata/number.pasm && echo "t/native_pbc/number_${N}.pbc updated"
./parrot -o t/native_pbc/string_${N}.pbc t/native_pbc/testdata/string.pasm  && echo "t/native_pbc/string_${N}.pbc updated"

make pbc_dump$exe
./pbc_dump -h t/native_pbc/number_${N}.pbc

perl t/harness t/native_pbc/integer.t && \
    perl t/harness t/native_pbc/number.t && \
    perl t/harness t/native_pbc/string.t

if [ "$enable_long_double" = "1" ]; then
    if [ "$1" = "--noconf" ]; then
      echo "Hmm. You have no long double, and we want to try --floatval=long double"
      echo "However for this you must reconfigure your parrot and you gave --noconf"
      exit
    fi
    make -s prog-clean
    perl Configure.pl --floatval="long double" --nomanicheck
    tail myconfig
    make -s || exit 1
    hugefloatvalsize=$(./parrot_config hugefloatvalsize)
    numvalsize=$(./parrot_config numvalsize)
    #if [ "hugefloatvalsize" = "12" ]; then echo "Only 12 byte long double. Sorry"; exit; fi
    #if [ "numvalsize" = "12" ]; then echo "Only 12 byte double. Sorry"; exit; fi
    # 1+2, 4+5, 6+7
    M=$((N+1))
    [ -e t/op/number_1.pasm ] || perl t/harness t/op/number.t
    ./parrot -o t/native_pbc/number_${M}.pbc t/op/number_1.pasm && echo "t/native_pbc/number_${M}.pbc updated"
    make pbc_dump$exe
    ./pbc_dump -h t/native_pbc/number_${M}.pbc

    perl t/harness t/native_pbc/integer.t && \
      perl t/harness t/native_pbc/number.t && \
      perl t/harness t/native_pbc/string.t
fi

echo "You should run these commands to update the PBC files in your repo:"
echo "cd t/native_pbc"
echo "git add *.pbc"
echo "git commit -m 'native_pbc platform updates'"
