Subject: Re: Lisp as a script language
From: rpw3@rpw3.org (Rob Warnock)
Date: Mon, 21 Jun 2004 20:53:36 -0500
Newsgroups: comp.lang.lisp
Message-ID: <54KdndLa5cO9DErd4p2dnA@speakeasy.net>
Bj�rn Lindberg <d95-bli@nada.kth.se> wrote:
+---------------
| Frank Buss <fb@frank-buss.de> writes:
| > Looks like standard CL is a bit limited, so perhaps it would be a better 
| > idea to compare a special implementation, but I don't know which is the 
| > most used implementation or the best implementation for this test.
| 
| I suggest that you go with a specific implementation.
+---------------

But remember to isolate the platform-specific stuff so you can easily
add support for more platforms later.

+---------------
| Here are the first five "programs" in Clisp:
+---------------

And just for fun, in CMUCL as well:

+---------------
| #!/usr/bin/clisp -q
| ; Smallest running program:
| ; <empty>
+---------------

As it comes "out of the box", CMUCL doesn't directly support "shebang"
style. However, there are at least three reasonable solutions:

1. Trampoline off /bin/sh (the following "exec" must be all in one line)
   on those operating systems which default to /bin/sh:

      ":" ; exec cmucl -noinit -eval "(setq *load-verbose* nil)" -load "`which $0`" ${1+"-args"} ${1+"$@"}
      ; ...your Lisp code here...

2. Use a specialized trampoline program, such as the one given here:

      <URL:http://www.chez.com/emarsden/downloads/cmucl-trampoline.c>

   which lets your script start something like this:

      #!/usr/bin/cmucl-trampoline \
      -quiet -batch -noinit
      #!
      ; ...your Lisp code here...

3. Make a little hack to "/usr/local/lib/cmucl/lib/site-init.lisp"
   [which I keep saying I'm going to post, but haven't gotten around to
   yet -- maybe this will be enough motivation] that lets you do this:

      #!/usr/local/bin/cmucl -script
      ; ...your Lisp code here...

So given one of the above, then:

+---------------
| ; Hello world:
| (princ "Hello world")
+---------------

Same in CMUCL.

+---------------
| ; Command line arguments:
| (princ (first *args*))
+---------------

  (princ (second ext:*command-line-strings*))

+---------------
| ; Environment variables:
| (princ (getenv "HOME"))
+---------------

Add the following routine to your startup code, then same in CMUCL:

   ;;; GETENV -- Mostly-portable code for accessing Unix
   ;;; (or Windows?) environment variables. Morphed very slightly
   ;;; from <URL:http://cl-cookbook.sourceforge.net/os.html>
   ;;; Copyright (c) 2002 The Common Lisp Cookbook Project 
   ;;; See: <URL:http://cl-cookbook.sourceforge.net/license.html>
   (defun getenv (name &optional default)
     (or
      #+CMU (cdr (assoc name ext:*environment-list* :test #'string=))
      #+Allegro (sys:getenv name)
      #+CLISP (ext:getenv name)
      #+ECL (si:getenv name)
      #+SBCL (sb-unix::posix-getenv name)
      #+LISPWORKS (lispworks:environment-variable name)
      default))

+---------------
| ; Return non-zero exit code when file does not exist:
| (unless (probe-file "/etc/mtab") (exit 1))
+---------------

Same in CMUCL, except use (QUIT 1) instead of (EXIT 1).

Also, see the function EXT:RUN-PROGRAM to see how to run programs
from within CMUCL. E.g., in the simple case where we just want to
run a sub-process, get its output on stdout, and wait for it to exit,
given the following definition:

   #+cmu
   (defun system (command-string)
     (let ((proc (run-program "/bin/sh" (list "-c" command-string)
			      :wait t :input t :output t :error t)))
       (prog1 (process-exit-code proc) (process-close proc))))

you can then do this:

   > (system "ls -l foo*.[0-9]")
   -rw-r--r--  1 rpw3  rpw3   5361 Mar 30 13:40 foo.1
   -rw-r--r--  1 rpw3  rpw3   4504 Apr 14 22:57 foo.2
   -rw-r--r--  1 rpw3  rpw3   6211 Apr 14 23:01 foo.3
   -rw-r--r--  1 rpw3  rpw3  55971 Apr 14 23:04 foo.4

   0
   > (system "ls -l foo3*")
   ls: foo3*: No such file or directory

   1
   > 


-Rob

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607