#!/bin/bash # Copyright 2005-2007 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= # Going to make an image SAVING=nil # 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 } # Which startup argument syntax to use LISPTYPE= # --- Option parsing --- OPTION_PARSING_ENDED= function missing { echo "$0: missing argument to option" DO_USAGE=t } # 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 missing;break; fi LISP="$1" shift;; -l*) LISP="${1#-l}"; shift;; --type | -t) shift if [ $(($# < 1)) = 1 ]; then missing;break; fi LISPTYPE="$1" shift;; -t*) LISPTYPE="${1#-t}"; shift;; --lisp-option | -L) shift if [ $(($# < 1)) = 1 ]; then missing;break; 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;; --save) SAVING=t; break;; -- | *) # not shifting OPTION_PARSING_ENDED=t; break;; esac done if [ "$OPTION_PARSING_ENDED" -a "$LOADQUIET" = nil ]; then echo "; $0: assuming '$1' ends my options" >&2 fi # --- Usage --- if [ "$DO_USAGE" ]; then cat < Specifies the path to the Common Lisp implementation. If not specified, searches for one of: $LISPS --type|-t Specifies type of CL implementation; may be one of: sbcl cmucl openmcl ecl clisp gcl abcl abcl-jar Guessed from program name if not specified. --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. ABCL-specific note: ABCL will not be searched for; use the --lisp option to give the path to j.jar or abcl.jar explicitly. 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 --- if [ "$LISPTYPE" = "" ]; then case "`basename $LISP`" in j.jar | abcl.jar) LISPTYPE=abcl-jar ;; *sbcl*) LISPTYPE=sbcl ;; *openmcl*) LISPTYPE=openmcl ;; *ecl*) LISPTYPE=ecl ;; *clisp*) LISPTYPE=clisp ;; *abcl*) LISPTYPE=abcl ;; *gcl*) LISPTYPE=gcl ;; lisp | *cmu*) LISPTYPE=cmucl ;; *) echo "$0: Could not guess lisp type from name '`basename $LISP`'. Specify it with the --type/-t option." exit 254;; esac fi HERE=`dirname $0` 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 } # Called COMMON_INIT1 because there used to be a COMMON_INIT2 (for reader # sequencing) and might be again. COMMON_INIT1='(progn (setf *compile-print* nil) (when '"$SAVING"' ;; using *features* because we have no packages to put a variable in yet (pushnew :e.saving-image *features*)) (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))' 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 '(apply (function e.rune:rune-then-exit) (cdr sb-ext:*posix-argv*))' \ --end-toplevel-options \ "$@" ;; cmucl) "$EXEC" "$LISP" \ -quiet \ "${LISP_EXTRA[@]}" \ -eval '(require :asdf)' \ -eval "$COMMON_INIT1" \ -eval "(e.rune:rune-then-exit `quote_args`)" ;; openmcl) "$EXEC" "$LISP" \ "${LISP_EXTRA[@]}" \ -e '(require :asdf)' \ -e "$COMMON_INIT1" \ -e "(e.rune:rune-then-exit `quote_args`)" ;; ecl) # xxx is there a quiet flag? "$EXEC" "$LISP" \ -eval '(require :asdf)' \ -eval "$COMMON_INIT1" \ -eval "(e.rune:rune-then-exit $QUOTED_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)" \ # "$COMMON_INIT1" \ # "(e.rune:rune-then-exit `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)" \ "$COMMON_INIT1" \ "(apply (function e.rune:rune-then-exit) 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)" \ -eval "$COMMON_INIT1" \ -eval "(e.rune:rune-then-exit `quote_args`)" ;; abcl-jar) # XXX using e.jar only as a source of Antlr JHOME=`rune -show | grep -- '^-De.home=' | cut -c 10-` "$EXEC" java -cp "$LISP":"$HERE/antlr/":"$JHOME/e.jar" org.armedbear.lisp.Main \ "${LISP_EXTRA[@]}" \ --eval '(require :asdf)' \ --eval "$COMMON_INIT1" \ --eval "(e.rune:rune-then-exit `quote_args`)" ;; abcl) # oops, can't set classpath "$EXEC" "$LISP" \ "${LISP_EXTRA[@]}" \ --eval '(require :asdf)' \ --eval "$COMMON_INIT1" \ --eval "(e.rune:rune-then-exit `quote_args`)" ;; *) echo "$0: don't know how to start implementation type '$LISPTYPE' at $LISP" >&2 exit 254 ;; esac