[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Scheme shellscripts

James William O'Toole Jr. <james@ZERMATT.LCS.MIT.EDU> writes:

>    Date: 16 Jul 88 08:01:32 GMT
>    From: titan!dorai@rice.edu  (Dorai Sitaram)
>    A shellscript written in Scheme is like any other Scheme file, except that its
>    first line has to be:
>			    runschemescript "$*" '
>    and its last line:
>			    '
>    The quotes are used to delimit the Scheme code which forms the body of the
>    script. The script consists of a call of the Un*x command `runschemescript' 
>    with two arguments, the first being the list of arguments to the Scheme 
>    script, and the second the text of the Scheme code in the script. Thus, a 
>    Scheme shellscript is a *true* schellscript, i.e., it is callable at the Un*x 
>    command-line, though the main part of it is a piece of text which is Scheme.
>    The command `runschemescript' used above is a shellscript written in the usual
>    shell language. It is the following relatively simple piece of cshell:
>    ...
>    If anyone can suggest further improvement I'll be glad to hear of it.
>Your method, when executed, requires starting one /bin/csh to interpret
>the shellscript, another /bin/csh to interpret the ``runschemescript''
>shellscript, copying the scheme code into a temporary file, and invoking
>the scheme implementation on that file.
>I would suggest that you instead place your scheme code in a file whose
>first line is ``#!/bin/scheme arg''.  If your file is called foo, and
>its first line is as given above, then when you execute foo, your Unix
>will execute the command ``/bin/scheme arg foo''.  You may omit arg, or
>choose arg to be something which speeds up /bin/scheme, or tells it to
>load the file whose name follows, or whatever.  You will have to
>convince your scheme to ignore the first line of foo, of course.  This
>method avoids starting up extra shells and copying files.
>  --Jim

A Refresher on #!
If `#! A A1 ...' is the first line of a shell script file whose name is B, 
calling B with args B1 ... has the same effect as calling A with args 
A1 ... B B1 ...

In the above, A has to be a full pathname of a *standard* Un*x command (like 
cat, scheme, etc), i.e., it cannot be a user-fashioned command or shell script
(I found this out thru experimentation. Why is this?).

!# no rehserfeR A
Jim [and J A Biep Durieux (private communication)] suggest that 
#! /usr/local/scheme be the first line of a Scheme script: this has the 
unfortunate effect that all arguments to a Scheme script will be loaded as 
Scheme files [even though they are in general, just like any shell script 
arguments, *not* Scheme files]. The script file itself is loaded into Scheme, 
which is ok, provided that its first (non-Scheme) line can somehow be removed.

However, Jim and Biep are right in stating that #! can lead to a concise
and efficient implementation of Scheme scripts. Let the first line of a 
Scheme script be the line

		#! /bin/sh runschemescript

runschemescript is a Bourne script which looks like:
echo > .tmp '(set! $* (quote ('$*')))'
echo -n >> .tmp ';'
cat $foo >> .tmp
echo >> .tmp '(exit)'
scheme .tmp	#this line could be 'exec scheme .tmp' but I don't know if 
		#that saves anything

A Scheme script 'ss' looks like:
#! /bin/sh runschemescript
<a body of Scheme code which
 refers to the list of arguments
 of `ss' by the variable $*>
This Scheme code doesn't have the restriction of not being able to use quotes
in it. It also looks less ugly with the user not having to mention $* and use
Bourne quotes in his Scheme scripts. 

ss, when called with arguments a1 ..., gets converted (by the #!) to the call

	/bin/sh runschemescript ss a1 ...

which is the same as (with one subshell invocation)

	runschemescript ss a1 ...

runschemescript then creates a .tmp file which sets a Scheme global variable
$* to a list (a1 ...) of ss's arguments; followed by the contents of the file
ss; followed by an (exit). [A judicious ';' is inserted at the right spot to 
comment out the only non-Scheme portion of the file ss: the first line (with 
#! ...).] ss can therefore be used as a regular shell script which is written 
in Scheme rather than in Bourne.

I would like the first line of Scheme script to be just

		#! runschemescript

instead of

		#! /bin/sh runschemescript

but as said earlier, only standard Un*x commands seem to be accepted by #!.
Improvements are welcome.