A few days ago, in <news:e86dncxCt-gJSN_anZ2dnUVZ_ualnZ2d@speakeasy.net>,
I mentioned my CMUCL "-script" hack once again [which I've done far too
many times over the past few years], that lets you do stuff like this:
$ cat ./hello.cmucl
#!/usr/local/bin/cmucl -script
(format t "Hello, world!~%")
(loop for arg in (cons *script-name* *script-args*)
and i from 0
do (format t "argv[~a] = ~s~%" i arg))
$ ./hello.cmucl -foo=37 -bar baz gorp
Hello, world!
argv[0] = "./hello.cmucl"
argv[1] = "-foo=37"
argv[2] = "-bar"
argv[3] = "baz"
argv[4] = "gorp"
$
and promised [once again!] to share it. Well, it's here:
http://rpw3.org/hacks/lisp/site-switch-script.lisp
I have *not* cleaned it up at all, so if you actually want to
understand what it does [or even worse, *why* it does it that way]
you're probably in for some rough slogging. But if you just want
to *use* it to write scripts like the above, here's all you have
to do [instructions are also embedded in the file itself]:
1. Download the above URL & save it in "library:site-switch-script.lisp"
["library:" is typically "/usr/local/lib/cmucl/lib/", but YMMV].
2. Append the following expression to your "library:site-init.lisp" file:
(let ((option (second *command-line-strings*)))
(when (equal option "-script")
(load (merge-pathnames "site-switch-script" *load-pathname*))))
3. The startup time for scripts will be measurably faster if you
COMPILE-FILE both "site-switch-script.lisp" & "site-init.lisp".
[But *don't* do this if you tend to change versions of CMUCL often,
since if "site-init.lisp" is compiled with the wrong version,
CMUCL won't start up correctly.]
4. Prepend source or FASL "scripts" with "#!/usr/local/bin/cmucl -script"
[or wherever you have an executable of CMUCL installed] and then
"chmod a+x" them. Such files will now run much the same as if you said:
$ cmucl -noinit -quiet -batch -load {filename} -eval '(quit)'
Some of that behavior may be modified by pushing items onto the
*SCRIPT-EXIT-HOOKS* variable [see inside the file for details].
Again, this is a hack, albeit a *very* useful one in my experience
with it over the past several years. If enough other people also
find it useful, I'll try to get the CMUCL maintainers to include
a version of the "-script" option in the standard distribution at
some point.
[I would have pushed for such before now, but the CMUCL command-line
option decoding is... well, "baroque" would be too kind. It needs a
*lot* of cleaning up, and I confess, I was lazy. I just hacked around
it altogether. (*blush*)]
-Rob
p.s. Yes, #3 above said "source *or* FASL" -- it works for either
[though not both at the same time!]. And you can concatenate multiple
FASLs into a single "script", e.g.:
$ cat script_header.cmucl
#!/usr/local/bin/cmucl -script
$ head foo{1,2,3}.lisp
==> foo1.lisp <==
(defun foo1 () (format t "This is foo1.~%"))
==> foo2.lisp <==
(defun foo2 () (format t "This is foo2.~%"))
==> foo3.lisp <==
(declaim (ftype function foo1 foo2))
(foo1)
(foo2)
$ cmu-compile foo{1,2,3}.lisp
...[compile chatter]...
$ cat script_header.cmucl foo1.x86f foo2.x86f foo3.x86f > foo
$ chmod a+x foo
$ ./foo
This is foo1.
This is foo2.
$
p.p.s. If you want a script which just sets up an environment
and then fall into a standard top-level REPL, here's an example:
$ cat ./test-repl
#!/usr/local/bin/cmucl -script
(format t "~%Welcome to the customized test REPL~%~%")
(setf *batch-mode* t) ; So EOF will exit.
(setf *prompt* "test> ") ; Custom prompt.
;;; ...[any other initializations/customizations you might want]...
(push :repl *script-exit-hooks*)
$ ./test-repl
Welcome to the customized test REPL
test> (expt 2 100)
1267650600228229401496703205376
test> ^D^D
$
[Yes, it is an artifact of CMUCL's READ processing that even with
*BATCH-MODE* set, it still takes *two* EOFs in a row to get it to exit.]
p.p.p.s. If you want interrupts (SIGINT, ^C) to just exit instead of
dropping into the debugger, include this in your script:
(system:enable-interrupt unix:sigint (lambda (signal code scp)
(declare (ignore signal code scp))
(unix:unix-exit 1)
(error "Unix-exit didn't exit!")))
-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607