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