Chris@303: #!/bin/bash
Chris@303: 
Chris@303: # Disable shellcheck warnings for useless-use-of-cat. UUOC is good
Chris@303: # practice, not bad: clearer, safer, less error-prone.
Chris@303: # shellcheck disable=SC2002
Chris@303: 
Chris@303: sml="$VEXT_SML"
Chris@303: 
Chris@303: set -eu
Chris@303: 
Chris@303: mydir=$(dirname "$0")
Chris@303: program="$mydir/vext.sml"
Chris@303: 
Chris@303: # We need one of Poly/ML, SML/NJ, or MLton. Since we're running a
Chris@303: # single-file SML program as if it were a script, our order of
Chris@303: # preference is based on startup speed.
Chris@303: 
Chris@303: if [ -z "$sml" ]; then
Chris@303:     if sml -h 2>&1 | grep -q 'Standard ML of New Jersey'; then
Chris@303: 	sml="smlnj"
Chris@303:     # We would prefer Poly/ML to SML/NJ, except that Poly v5.7 has a
Chris@303:     # nasty bug that occasionally causes it to deadlock on startup.
Chris@303:     # That appears to be fixed in their repo, so we could promote it
Chris@303:     # up the order again at some point in future
Chris@303:     elif echo | poly -v 2>/dev/null | grep -q 'Poly/ML'; then
Chris@303: 	sml="poly"
Chris@303:     elif mlton 2>&1 | grep -q 'MLton'; then
Chris@303: 	sml="mlton"
Chris@303:     else cat 1>&2 <<EOF
Chris@303: 
Chris@303: ERROR: No supported SML compiler or interpreter found       
Chris@303: EOF
Chris@303: 	cat <<EOF
Chris@303: 
Chris@303:   The Vext external source code manager needs a Standard ML (SML)
Chris@303:   compiler or interpreter to run.
Chris@303: 
Chris@303:   Please ensure you have one of the following SML implementations
Chris@303:   installed and present in your PATH, and try again.
Chris@303: 
Chris@303:     1. Standard ML of New Jersey
Chris@303:        - often found in a distribution package called: smlnj
Chris@303:        - executable name: sml
Chris@303: 
Chris@303:     2. Poly/ML
Chris@303:        - often found in a distribution package called: polyml
Chris@303:        - executable name: poly
Chris@303: 
Chris@303:     3. MLton
Chris@303:        - often found in a distribution package called: mlton
Chris@303:        - executable name: mlton
Chris@303: 
Chris@303: EOF
Chris@303: 	exit 2
Chris@303:     fi
Chris@303: fi
Chris@303: 
Chris@303: tmp_sml=$(mktemp /tmp/vext-XXXXXXXX.sml)
Chris@303: tmp_out=$(mktemp /tmp/vext-XXXXXXXX.bin)
Chris@303: 
Chris@303: trap 'rm -f $tmp_sml $tmp_out' 0
Chris@303: 
Chris@303: arglist=""
Chris@303: for arg in "$@"; do
Chris@303:     if [ -n "$arglist" ]; then arglist="$arglist,"; fi
Chris@303:     if echo "$arg" | grep -q '[^a-z]' ; then
Chris@303: 	arglist="$arglist\"usage\""
Chris@303:     else
Chris@303: 	arglist="$arglist\"$arg\""
Chris@303:     fi
Chris@303: done
Chris@303: 
Chris@303: case "$sml" in
Chris@303:     poly) echo 'use "'"$program"'"; vext ['"$arglist"'];' |
Chris@303: 		poly -q --error-exit ;;
Chris@303:     mlton)
Chris@303: 	cat "$program" > "$tmp_sml"
Chris@303: 	echo 'val _ = main ()' >> "$tmp_sml"
Chris@303: 	mlton -output "$tmp_out" "$tmp_sml"
Chris@303: 	"$tmp_out" "$@" ;;
Chris@303:     smlnj)
Chris@303: 	cat "$program" | (
Chris@303: 	    cat <<EOF
Chris@303: val smlrun__cp = 
Chris@303:     let val x = !Control.Print.out in
Chris@303:         Control.Print.out := { say = fn _ => (), flush = fn () => () };
Chris@303:         x
Chris@303:     end;
Chris@303: val smlrun__prev = ref "";
Chris@303: Control.Print.out := { 
Chris@303:     say = fn s => 
Chris@303:         (if String.isSubstring " Error" s
Chris@303:          then (Control.Print.out := smlrun__cp;
Chris@303:                (#say smlrun__cp) (!smlrun__prev);
Chris@303:                (#say smlrun__cp) s)
Chris@303:          else (smlrun__prev := s; ())),
Chris@303:     flush = fn s => ()
Chris@303: };
Chris@303: EOF
Chris@303: 	    cat -
Chris@303: 	    cat <<EOF
Chris@303: val _ = vext [$arglist];
Chris@303: val _ = OS.Process.exit (OS.Process.success);
Chris@303: EOF
Chris@303:             ) > "$tmp_sml"
Chris@303: 	CM_VERBOSE=false sml "$tmp_sml" ;;
Chris@303:     *)
Chris@303: 	echo "Unknown SML implementation name: $sml";
Chris@303: 	exit 2 ;;
Chris@303: esac
Chris@303: