#!/bin/bash # Copyright 2005 Kevin Reid, under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ................ # --- Configuration --- # Names of Common Lisp implementations we support. LISPS="sbcl openmcl lisp cmucl clisp gcl" # --- State --- # The executable for the implementation we will use. LISP=`which $LISPS 2>/dev/null | grep '^/' | head -1` # Command uses to start the Lisp process. --show replaces it with 'echo'. EXEC=exec # If t, attempts to remove all startup-progress-related messages LOADQUIET=nil # Print usage help DO_USAGE= # Extra arguments for the Lisp executable # code copied from E rune; I don't know how bash arrays work -- kpreid 2005-08-06 declare -a LISP_EXTRA function lisp_extra_push { LISP_EXTRA[${#LISP_EXTRA[@]}]=$1 } # --- Option parsing --- OPTION_PARSING_ENDED= # Interpret our own command-line options # modified from rune-template.txt while [ $(($# >= 1)) = 1 ]; do case $1 in --lisp | -l) shift if [ $(($# < 1)) = 1 ]; then usage; fi LISP="$1" shift;; -l*) LISP="${1#-l}"; shift;; --lisp-option | -L) shift if [ $(($# < 1)) = 1 ]; then usage; fi lisp_extra_push "$1" shift;; -L*) lisp_extra_push "${1#-L}"; shift;; --help) DO_USAGE=t; shift;; --show) EXEC=echo; shift;; --quiet | -q) LOADQUIET=t; shift;; --end-clrune-options) shift; break;; -- | *) # not shifting OPTION_PARSING_ENDED=t; break;; esac done # I'm feeling too lazy to look up the syntax for logical and if [ "$OPTION_PARSING_ENDED" ]; then if [ "$LOADQUIET" = nil ]; then echo "; $0: assuming '$1' ends my options" >&2 fi fi # --- Usage --- if [ "$DO_USAGE" ]; then cat < Specifies the path to the Common Lisp implementation. --lisp-option|-L Pass an extra argument to the command specified by --lisp. --help Print this help. --show Print the command line which would be used to start the Lisp instead of executing it. --quiet|-q Avoid printing messages about startup progress. --end-clrune-options Pass all further options to the Lisp level. An unrecognized argument or "--" terminates clrune option parsing; that and all further arguments are passed to the Lisp level. clrune supports starting SBCL, OpenMCL, CLISP, GCL, and ABCL; however, ABCL will not be searched for (use the --lisp option to give the path to j.jar). Now attempting to start Lisp to give further usage help... USAGE exec $0 --lisp $LISP --quiet --end-clrune-options --help "$@" fi # --- Review --- if [ "$LISP" = "" ]; then echo "$0: Sorry, I couldn't find a Common Lisp implementation. Use the --lisp/-l option to specify one." >&2 echo "$0: I looked for any of ($LISPS) using '`which which`'." >&2 exit 254 fi # --- Startup --- # Choose the argument format appropriate to the CL implementation # XXX we should eventually have support for independently specifying the type LISPTYPE=`basename $LISP` if [ "$LISPTYPE" = lisp ]; then LISPTYPE=cmucl fi if [ "$LISPTYPE" = j.jar ]; then LISPTYPE=abcl fi QUOTED_HERE=`dirname $0 | perl -pe 's&(["\\\\])&\\$1&g'` # Arguments as a string of Lisp expressions, for implementations which don't provide access to argv from within the Lisp environment. CLRUNE_PASS_ARGS="$@" function quote_args { perl -e 'print map {(my $x=$_) =~ s&(["\\\\])&\\$1&g; qq& "$x" &} @ARGV' -- $CLRUNE_PASS_ARGS } JHOME=`rune -show | grep -- '^-De.home=' | cut -c 10-` QUOTED_JHOME=`echo "$JHOME/" | perl -pe 's&(["\\\\])&\\$1&g'` # COMMON_INIT1/2 are separated since INIT2 needs to be read after INIT1 is evaluated, as the E.KNOT package will not exist until then. COMMON_INIT1='(progn (setf *compile-print* nil) (when '"$LOADQUIET"' (setf *compile-verbose* nil) (setf *load-verbose* nil)) (pushnew "'"$QUOTED_HERE"'/" asdf:*central-registry*) (asdf:operate (quote asdf:load-op) :e-on-cl :verbose (not '"$LOADQUIET"')) (values))' COMMON_INIT2='(progn (e.knot:found-e-on-java-home #p"'$QUOTED_JHOME'") (values))' if [ "$LOADQUIET" = nil ]; then echo "; $0 starting $LISP as $LISPTYPE: $@" >&2 fi case "$LISPTYPE" in sbcl) "$EXEC" "$LISP" \ --noinform \ "${LISP_EXTRA[@]}" \ --eval '(require :asdf)' \ --eval "$COMMON_INIT1" \ --eval "$COMMON_INIT2" \ --eval '(apply (function e.rune:rune) (cdr sb-ext:*posix-argv*))' \ --end-toplevel-options \ "$@" ;; cmucl) "$EXEC" "$LISP" \ -quiet \ "${LISP_EXTRA[@]}" \ -eval '(require :asdf)' \ -eval "$COMMON_INIT1" \ -eval "$COMMON_INIT2" \ -eval "(e.rune:rune `quote_args`)" ;; openmcl) "$EXEC" "$LISP" \ "${LISP_EXTRA[@]}" \ -e '(require :asdf)' \ -e "$COMMON_INIT1" \ -e "$COMMON_INIT2" \ -e "(e.rune:rune `quote_args`)" ;; clisp) if [ "`uname`" = "Darwin" -a \! \( "$LANG" -o "$LC_ALL" -o "$LC_CTYPE" \) ]; then lisp_extra_push "-E" lisp_extra_push "utf-8" fi # XXX config option for -on-error mode, and similar for other lisps - check if we can control such from Lisp code lisp_extra_push "-on-error" lisp_extra_push "debug" # make toplevel option --nothing work the way we want lisp_extra_push "-repl" #"$EXEC" "$LISP" -q -ansi "${LISP_EXTRA[@]}" \ # -x "(require :asdf \"$QUOTED_HERE/lisp/asdf.lisp\")" \ # "$COMMON_INIT1" \ # "$COMMON_INIT2" \ # "(e.rune:rune `quote_args`)" # xxx Ick! We load .clisprc because using this form of clisp startup unconditionally disables the rc file, and we want the rc so that the user's ASDF configuration is available. "$EXEC" "$LISP" -q -ansi "${LISP_EXTRA[@]}" \ <(echo \ '(let ((p (or (probe-file (merge-pathnames ".clisprc.lisp" (user-homedir-pathname))) (probe-file (merge-pathnames ".clisprc" (user-homedir-pathname)))))) (when p (load p)))' \ "(require :asdf \"$QUOTED_HERE/lisp/asdf.lisp\")" \ "$COMMON_INIT1" "$COMMON_INIT2" \ "(apply (function e.rune:rune) ext:*args*)") \ "$@" ;; gcl) if [ "$LOADQUIET" = nil ]; then echo "; $0: GNU Common Lisp was not sufficiently ANSI-compliant to run E-on-CL as of 2005-02-18. We'll try anyway:" >&2 fi "$EXEC" "$LISP" -batch \ "${LISP_EXTRA[@]}" \ -eval "(require :asdf \"$QUOTED_HERE/asdf.lisp\")" \ -eval "$COMMON_INIT1" "$COMMON_INIT2" \ -eval "(e.rune:rune `quote_args`)" ;; abcl) "$EXEC" java -cp "$LISP" org.armedbear.lisp.Main \ "${LISP_EXTRA[@]}" \ --eval '(require :asdf)' \ --eval "$COMMON_INIT1" \ --eval "$COMMON_INIT2" \ --eval "(e.rune:rune `quote_args`)" ;; *) echo "$0: don't know how to start implementation type '$LISPTYPE' at $LISP" >&2 exit 254 ;; esac