CMUCL "-script" hack now available



A few days ago, in <news:e86dncxCt-gJSN_anZ2dnUVZ_ualnZ2d@xxxxxxxxxxxxx>,
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@xxxxxxxx>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

.



Relevant Pages

  • Re: Batch Cisco Configuration Script
    ... configuration of many routers but now I cannot find it unfortunately. ... The way the script would work is as follows. ... I can't use Kiwi Cat ... open telnet session. ...
    (comp.dcom.sys.cisco)
  • Re: script reports file not found
    ... any and all feedback on this script appreciated. ... when it's kicking out the cat of the file in question. ... primitive linux script to run some ruby stuff. ... why all the cat commands? ...
    (Fedora)
  • Re: My auth.log analyze script
    ... users on this group I decided to write my own auth.log analyzing script. ... rm $TMPFILE1 ... You don't need cat: ... # Sort out Unique IPs ...
    (alt.os.linux)
  • Re: Plain text file on web server, questions please...
    ... strictly for online viewing that would add the HTML tags to the online ... a utility that would do this or can it be done with a shell script ... thing, this way that if anything changed in the FAQ, it would also be ... cat head.html joke.txt tail.html> joke_$.html ...
    (alt.os.linux)
  • dnscache not answering on FreeBSD (it did under OpenBSD)
    ... script I'm using to test my DNS setup, ... dnsq a lair.cybernude.org $(cat $/env/IP) ... dnsip yahoo.com ... 1602 packets received by filter ...
    (freebsd-questions)