#!@SHELL@
#
# COPYRIGHT (c) 2022 The Fellowship of SML/NJ (https://smlnj.org)
# All rights reserved.
#
# usage: ml-build [options] root-group [main-function [heapfile]]
#   options:
#       -hack           print this message
#       -S setup
#       -standalone
# usage: ml-build [-S setup] root-group [main-function [heapfile]]
#

thisscript=$0

usage() {
  echo "usage: ml-build [options] root-group [main-function [heapfile]]"
  echo "  options:"
  echo "    -h            -- print this message"
  echo "    -S setup      -- "
  echo "    -standalone   -- build standalone executable"
  echo "    -C<ctl>=<v>   -- compiler control argument (passed to compile command)"
  echo "    -D<sym>=<v>   -- CM-define argument (passed to compile command)"
  echo "    -U<sym>       -- undefine CM argument (passed to compile command)"
  exit $1
}

usage_error() {
  echo ${thisscript}: $*
  usage 1
}

error() {
  echo ${thisscript}: $*
  exit 1
}

if [ x${SMLNJ_HOME} = x ] ; then
  BIN_DIR="@BINDIR@"
  LIB_DIR="@LIBDIR@"
else
  BIN_DIR=${SMLNJ_HOME}/bin
  LIB_DIR=${SMLNJ_HOME}/lib
fi

if [ x"$CM_PATHCONFIG" = x ] ; then
  CM_PATHCONFIG=${LIB_DIR}/pathconfig
  export CM_PATHCONFIG
fi

SML=$BIN_DIR/sml
LINK=$BIN_DIR/.link-sml

dulist=''
setup=
build_exec=no

while [ $# != 0 ] ; do
  case $1 in
  -D*|-U*|-C*)
    dulist="$dulist $1"
    shift
    ;;
  -S)
    shift
    if [ $# = 0 ] ; then
        usage missing argument for -S
    fi
    setup=$1
    shift
    ;;
  -standalone)
    build_exec=yes
    shift
    ;;
  *)
    break
    ;;
  esac
done

if [ $# = 3 ] ; then
  root=$1
  main=$2
  heap=$3
elif [ $# = 2 ] ; then
  root=$1
  main=$2
  heap=`basename "$root" .cm`
elif [ $# = 1 ] ; then
  root=$1
  main=Main.main
  heap=`basename "$root" .cm`
else
  usage_error "no CM description file specified"
fi

# we use a checksum of the CM file as a deterministic prefix
# the "cksum" command is part of the IEEE 1003.2-1992 standard, so it should
# be available.  It outputs "<checksum> <num-octets> <pathname>"; we use the
# <checksum> for the prefix.
#
RES=$(cksum "$root" || error "error running cksum")
# strip the "<num-octets> <pathname>" suffix
ID=${RES%% *}
xx="$ID"

smlfile=$xx-export.sml
cmfile=$xx-export.cm
listfile=$xx-BOOTLIST
linkargsfile=$xx-LINKARGS

# be paranoid and verify that we don't have any file-name collisions
#
for f in "$smlfile" "$cmfile" "$listfile" "$linkargsfile" ; do
  if [ -f "$f" ] ; then
    error "$f already exists; please remove and try again"
  fi
done

# remove temp files on error/termination
#
trap 'rm -rf $smlfile $cmfile $listfile $linkargsfile @CMDIRARC@/*/$smlfile' 0 1 2 3 15

# a structure name that is unlikely to collide with any of the source
# structure names
rare="X_$ID"

cat >$smlfile <<EOF
structure ${rare} = struct val _ = SMLofNJ.exportFn ("${heap}", ${main}) end
EOF

cat >$cmfile <<EOF
Group structure ${rare} is \$/basis.cm ${root} ${smlfile}
EOF

# Invoke sml with special option that causes CM to do its magic.
# Unless the heap image exists and is up-to-date CM will write the arguments
# for the link script into $linkargsfile.
# (See cm/main/cm-boot.sml [function "mlbuild"] for details.)
if "$SML" $dulist @CMbuild $setup "$root" "$cmfile" "$heap" "$listfile" "$linkargsfile"
then
  if [ -r "$linkargsfile" ]; then
    "$LINK" `cat "$linkargsfile"`
  fi
else
    exit $?
fi

if [ x"$build_exec" = xyes ] ; then
  $BIN_DIR/heap2exec "$heap"
fi
