| Chris@1808 | 1 #!/bin/bash | 
| Chris@1808 | 2 | 
| Chris@1808 | 3 # Disable shellcheck warnings for useless-use-of-cat. UUOC is good | 
| Chris@1808 | 4 # practice, not bad: clearer, safer, less error-prone. | 
| Chris@1808 | 5 # shellcheck disable=SC2002 | 
| Chris@1808 | 6 | 
| Chris@1808 | 7 sml="$REPOINT_SML" | 
| Chris@1808 | 8 | 
| Chris@1808 | 9 set -eu | 
| Chris@1808 | 10 | 
| Chris@1808 | 11 # avoid gussying up output | 
| Chris@1808 | 12 export HGPLAIN=true | 
| Chris@1808 | 13 | 
| Chris@1808 | 14 mydir=$(dirname "$0") | 
| Chris@1808 | 15 program="$mydir/repoint.sml" | 
| Chris@1808 | 16 | 
| Chris@1808 | 17 hasher= | 
| Chris@1808 | 18 local_install= | 
| Chris@1808 | 19 if [ -w "$mydir" ]; then | 
| Chris@1808 | 20     if echo | sha256sum >/dev/null 2>&1 ; then | 
| Chris@1808 | 21 	hasher=sha256sum | 
| Chris@1808 | 22         local_install=true | 
| Chris@1808 | 23     elif echo | shasum >/dev/null 2>&1 ; then | 
| Chris@1808 | 24 	hasher=shasum | 
| Chris@1808 | 25 	local_install=true | 
| Chris@1808 | 26     else | 
| Chris@1808 | 27         echo "WARNING: sha256sum or shasum program not found" 1>&2 | 
| Chris@1808 | 28     fi | 
| Chris@1808 | 29 fi | 
| Chris@1808 | 30 | 
| Chris@1808 | 31 if [ -n "$local_install" ]; then | 
| Chris@1808 | 32     hash=$(echo "$sml" | cat "$program" - | $hasher | cut -c1-16) | 
| Chris@1808 | 33     gen_sml=$mydir/.repoint-$hash.sml | 
| Chris@1808 | 34     gen_out=$mydir/.repoint-$hash.bin | 
| Chris@1808 | 35     trap 'rm -f $gen_sml' 0 | 
| Chris@1808 | 36 else | 
| Chris@1808 | 37     gen_sml=$(mktemp /tmp/repoint-XXXXXXXX.sml) | 
| Chris@1808 | 38     gen_out=$(mktemp /tmp/repoint-XXXXXXXX.bin) | 
| Chris@1808 | 39     trap 'rm -f $gen_sml $gen_out' 0 | 
| Chris@1808 | 40 fi | 
| Chris@1808 | 41 | 
| Chris@1808 | 42 if [ -x "$gen_out" ]; then | 
| Chris@1808 | 43     exec "$gen_out" "$@" | 
| Chris@1808 | 44 fi | 
| Chris@1808 | 45 | 
| Chris@1808 | 46 # We need one of Poly/ML, SML/NJ, MLton, or MLKit. Since we're running | 
| Chris@1808 | 47 # a single-file SML program as if it were a script, our order of | 
| Chris@1808 | 48 # preference is usually based on startup speed. An exception is the | 
| Chris@1808 | 49 # local_install case, where we retain a persistent binary | 
| Chris@1808 | 50 | 
| Chris@1808 | 51 if [ -z "$sml" ]; then | 
| Chris@1808 | 52     if [ -n "$local_install" ] && mlton 2>&1 | grep -q 'MLton'; then | 
| Chris@1808 | 53 	sml="mlton" | 
| Chris@1808 | 54     elif sml -h 2>&1 | grep -q 'Standard ML of New Jersey'; then | 
| Chris@1808 | 55 	sml="smlnj" | 
| Chris@1808 | 56     # We would prefer Poly/ML to SML/NJ, except that Poly v5.7 has a | 
| Chris@1808 | 57     # nasty bug that occasionally causes it to deadlock on startup. | 
| Chris@1808 | 58     # That is fixed in v5.7.1, so we could promote it up the order | 
| Chris@1808 | 59     # again at some point in future | 
| Chris@1808 | 60     elif echo | poly -v 2>/dev/null | grep -q 'Poly/ML'; then | 
| Chris@1823 | 61 	sml="polyml" | 
| Chris@1808 | 62     elif mlton 2>&1 | grep -q 'MLton'; then | 
| Chris@1808 | 63 	sml="mlton" | 
| Chris@1808 | 64     # MLKit is at the bottom because it leaves compiled files around | 
| Chris@1808 | 65     # in an MLB subdir in the current directory | 
| Chris@1808 | 66     elif mlkit 2>&1 | grep -q 'MLKit'; then | 
| Chris@1808 | 67 	sml="mlkit" | 
| Chris@1808 | 68     else cat 1>&2 <<EOF | 
| Chris@1808 | 69 | 
| Chris@1808 | 70 ERROR: No supported SML compiler or interpreter found | 
| Chris@1808 | 71 EOF | 
| Chris@1808 | 72 	cat 1>&2 <<EOF | 
| Chris@1808 | 73 | 
| Chris@1808 | 74   The Repoint external source code manager needs a Standard ML (SML) | 
| Chris@1808 | 75   compiler or interpreter to run. | 
| Chris@1808 | 76 | 
| Chris@1808 | 77   Please ensure you have one of the following SML implementations | 
| Chris@1808 | 78   installed and present in your PATH, and try again. | 
| Chris@1808 | 79 | 
| Chris@1808 | 80     1. Standard ML of New Jersey | 
| Chris@1808 | 81        - may be found in a distribution package called: smlnj | 
| Chris@1808 | 82        - executable name: sml | 
| Chris@1808 | 83 | 
| Chris@1808 | 84     2. Poly/ML | 
| Chris@1808 | 85        - may be found in a distribution package called: polyml | 
| Chris@1808 | 86        - executable name: poly | 
| Chris@1808 | 87 | 
| Chris@1808 | 88     3. MLton | 
| Chris@1808 | 89        - may be found in a distribution package called: mlton | 
| Chris@1808 | 90        - executable name: mlton | 
| Chris@1808 | 91 | 
| Chris@1808 | 92     4. MLKit | 
| Chris@1808 | 93        - may be found in a distribution package called: mlkit | 
| Chris@1808 | 94        - executable name: mlkit | 
| Chris@1808 | 95 | 
| Chris@1808 | 96 EOF | 
| Chris@1808 | 97 	exit 2 | 
| Chris@1808 | 98     fi | 
| Chris@1808 | 99 fi | 
| Chris@1808 | 100 | 
| Chris@1808 | 101 arglist="" | 
| Chris@1808 | 102 for arg in "$@"; do | 
| Chris@1808 | 103     if [ -n "$arglist" ]; then arglist="$arglist,"; fi | 
| Chris@1808 | 104     if echo "$arg" | grep -q '["'"'"']' ; then | 
| Chris@1808 | 105 	arglist="$arglist\"usage\"" | 
| Chris@1808 | 106     else | 
| Chris@1808 | 107 	arglist="$arglist\"$arg\"" | 
| Chris@1808 | 108     fi | 
| Chris@1808 | 109 done | 
| Chris@1808 | 110 | 
| Chris@1808 | 111 case "$sml" in | 
| Chris@1823 | 112     polyml) | 
| Chris@1808 | 113         if [ -n "$local_install" ] && polyc --help >/dev/null 2>&1 ; then | 
| Chris@1808 | 114             if [ ! -x "$gen_out" ]; then | 
| Chris@1808 | 115                 polyc -o "$gen_out" "$program" | 
| Chris@1808 | 116             fi | 
| Chris@1808 | 117 	    "$gen_out" "$@" | 
| Chris@1808 | 118         else | 
| Chris@1808 | 119             echo 'use "'"$program"'"; repoint ['"$arglist"'];' | | 
| Chris@1808 | 120                 poly -q --error-exit | 
| Chris@1808 | 121         fi ;; | 
| Chris@1808 | 122     mlton) | 
| Chris@1808 | 123         if [ ! -x "$gen_out" ]; then | 
| Chris@1808 | 124 	    echo "[Precompiling Repoint binary...]" 1>&2 | 
| Chris@1808 | 125 	    echo "val _ = main ()" | cat "$program" - > "$gen_sml" | 
| Chris@1808 | 126 	    mlton -output "$gen_out" "$gen_sml" | 
| Chris@1808 | 127         fi | 
| Chris@1808 | 128 	"$gen_out" "$@" ;; | 
| Chris@1808 | 129     mlkit) | 
| Chris@1808 | 130         if [ ! -x "$gen_out" ]; then | 
| Chris@1808 | 131 	    echo "[Precompiling Repoint binary...]" 1>&2 | 
| Chris@1808 | 132 	    echo "val _ = main ()" | cat "$program" - > "$gen_sml" | 
| Chris@1808 | 133 	    mlkit -output "$gen_out" "$gen_sml" | 
| Chris@1808 | 134         fi | 
| Chris@1808 | 135 	"$gen_out" "$@" ;; | 
| Chris@1808 | 136     smlnj) | 
| Chris@1808 | 137 	cat "$program" | ( | 
| Chris@1808 | 138 	    cat <<EOF | 
| Chris@1808 | 139 val smlrun__cp = | 
| Chris@1808 | 140     let val x = !Control.Print.out in | 
| Chris@1808 | 141         Control.Print.out := { say = fn _ => (), flush = fn () => () }; | 
| Chris@1808 | 142         x | 
| Chris@1808 | 143     end; | 
| Chris@1808 | 144 val smlrun__prev = ref ""; | 
| Chris@1808 | 145 Control.Print.out := { | 
| Chris@1808 | 146     say = fn s => | 
| Chris@1808 | 147         (if String.isSubstring " Error" s | 
| Chris@1808 | 148          then (Control.Print.out := smlrun__cp; | 
| Chris@1808 | 149                (#say smlrun__cp) (!smlrun__prev); | 
| Chris@1808 | 150                (#say smlrun__cp) s) | 
| Chris@1808 | 151          else (smlrun__prev := s; ())), | 
| Chris@1808 | 152     flush = fn s => () | 
| Chris@1808 | 153 }; | 
| Chris@1808 | 154 EOF | 
| Chris@1808 | 155 	    cat - | 
| Chris@1808 | 156 	    cat <<EOF | 
| Chris@1808 | 157 val _ = repoint [$arglist]; | 
| Chris@1808 | 158 val _ = OS.Process.exit (OS.Process.success); | 
| Chris@1808 | 159 EOF | 
| Chris@1808 | 160             ) > "$gen_sml" | 
| Chris@1808 | 161 	CM_VERBOSE=false sml "$gen_sml" ;; | 
| Chris@1808 | 162     *) | 
| Chris@1808 | 163 	echo "ERROR: Unknown SML implementation name: $sml" 1>&2; | 
| Chris@1808 | 164 	exit 2 ;; | 
| Chris@1808 | 165 esac | 
| Chris@1808 | 166 |