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: