225 lines
9.2 KiB
TeX
225 lines
9.2 KiB
TeX
%&latex -*- latex -*-
|
|
|
|
\chapter{Running scsh}
|
|
|
|
Scsh is currently implemented on top of {\scm}, a freely-available
|
|
{\Scheme} implementation written by Jonathan Rees and Richard Kelsey.
|
|
{\scm} uses a byte-code interpreter for good code density, portability
|
|
and medium efficiency. It is {\R4RS}. The version on top of which scsh is
|
|
currently built (0.36) lacks floating point.
|
|
It also has a module system designed by Jonathan Rees.
|
|
|
|
Scsh's design is not {\scm} specific, although the current implementation
|
|
is necessarily so. Scsh is intended to be implementable in other {\Scheme}
|
|
implementations---although such a port may require some work.
|
|
The {\scm} vm that scsh uses is a specially modified version;
|
|
standard {\scm} virtual machines cannot be used with the scsh heap image.
|
|
|
|
To run the {\scm} implementation of scsh, you run a specially modified
|
|
copy of the {\scm} virtual machine with a scsh heap image.
|
|
This command starts the vm up with a 1Mword heap (split into two semispaces):
|
|
\codex{scshvm -o scshvm -h 1000000 -i scsh.image arg1 arg2 \ldots}
|
|
The vm peels off initial vm arguments
|
|
up to the \ex{-i} heap image argument, which terminates vm argument parsing.
|
|
The rest of the arguments are passed off to the scsh top-level.
|
|
Scsh's top-level removes scsh arguments; the rest show up as the value
|
|
of \ex{command-line-arguments}.
|
|
|
|
Alternatively, you can run the scsh top-level binary.
|
|
This is nothing but a small cover program that invokes the
|
|
scsh vm on the scsh heap image for you.
|
|
This allows you to simply start up an interactive scsh from a command
|
|
line, as well as write shell scripts that begin with the simple trigger
|
|
\codex{\#!/usr/local/bin/scsh -s}
|
|
|
|
\section{VM arguments}
|
|
\label{sec:vm-args}
|
|
|
|
Scsh uses a special version of the {\scm} virtual machine.
|
|
It takes arguments in the following form:
|
|
\codex{scshvm [\var{meta-arg}] [\var{vm-options}\+] [\var{end-option} \var{scheme-args}]}
|
|
where
|
|
\begin{inset}
|
|
\begin{tabular}{ll}
|
|
\var{meta-arg:} & \verb|\ |\var{script} \\
|
|
\\
|
|
\var{vm-option}: & \ex{-h }\var{heap-size-in-words} \\
|
|
& \ex{-s }\var{stack-size-in-words} \\
|
|
& \ex{-o }\var{object-file-name} \\
|
|
\\
|
|
\var{end-option:} & \ex{-i }\var{image-file-name} \\
|
|
& \ex{--}
|
|
\end{tabular}
|
|
\end{inset}
|
|
|
|
\subsection{The meta argument}
|
|
The {\scm} vm takes a special command-line switch, a single backslash called
|
|
the ``meta-switch,'' which is useful for shell scripts.
|
|
While parsing the command-line arguments, if the vm sees a ``\verb|\|''
|
|
argument, followed by a filename argument \var{fname}, it will open the file
|
|
\var{fname}, and read more arguments from the second line of this file.
|
|
This list of arguments will then replace the ``\verb|\|'' argument---\ie,
|
|
the new arguments are inserted in front of \var{fname},
|
|
and the argument parser resumes argument scanning.
|
|
This is used to overcome a limitation of the \ex{\#!} feature:
|
|
the \ex{\#!} line can only specify a single argument after the interpreter.
|
|
For example, we might hope the following scsh script, \ex{ekko},
|
|
would implement a simple-minded version of \ex{echo(1)}:
|
|
\begin{code}
|
|
#!/bin/scshvm -o /bin/scshvm -i /lib/scsh.image -s
|
|
!#
|
|
(map (\l{arg} (display arg) (display " "))
|
|
command-line-arguments)
|
|
(newline)\end{code}
|
|
%
|
|
The idea would be that the command
|
|
\codex{ekko Hi there.}
|
|
would by expanded by \ex{exec(2)} into
|
|
%
|
|
\begin{code}
|
|
/bin/scshvm -o /bin/scshvm -i /lib/scsh.image -s ekko Hi there.\end{code}
|
|
%
|
|
In theory, this would cause scsh to start up, set \ex{command-line-arguments}
|
|
to \ex{("Hi" "there.")}, load the source file \ex{ekko}, and exit.
|
|
|
|
However, the {\Unix} \ex{exec(2)} call will not handle multiple arguments
|
|
on the \ex{\#!} line, so this script won't work. We must instead invoke
|
|
the {\scm} vm with the single \cd{\\} argument, and put the rest of the
|
|
arguments on line two of the script. Here's the correct script:\footnote{
|
|
In fact, I'm playing fast and loose with the actual pathnames
|
|
used in this example: \ex{scshvm} is probably not going to be found in
|
|
\ex{/bin}. I've abbreviated things so the long argument lists will fit
|
|
into one line of text.
|
|
See the following sections for the full details.}
|
|
%
|
|
\begin{code}
|
|
#!/bin/scshvm \\
|
|
-o /bin/scshvm -i /lib/scsh.image -s
|
|
!#
|
|
(map (\l{arg} (display arg) (display " "))
|
|
command-line-arguments)
|
|
(newline)\end{code}
|
|
%
|
|
Now, the invocation starts as
|
|
\codex{ekko Hi there.}
|
|
and is expanded by exec(2) into
|
|
\begin{code}
|
|
/bin/scshvm \\ ekko Hi there.\end{code}
|
|
When scshvm starts up, it expands the ``\cd{\\}'' argument into the arguments
|
|
read from line two of \ex{ekko}, producing this argument list:
|
|
\begin{code}\cddollar
|
|
\underline{-o /bin/scshvm -i /lib/scsh.image -s ekko} Hi there.
|
|
$\uparrow$
|
|
{\rm{}Expanded from} \cd{\\} ekko\end{code}
|
|
%
|
|
With this argument list, processing proceeds as we intended.
|
|
|
|
\subsection{VM options}
|
|
The \ex{-o \var{object-file-name}} switch tells the vm where to find
|
|
relocation information for its foreign-function calls.
|
|
Scsh will use a pre-compiled default if it is not specified.
|
|
Scsh must have this information to run,
|
|
since scsh's syscall interfaces are done with foreign-function calls.
|
|
|
|
The \ex{-h} and \ex{-s} options tell the vm how much space to allocate
|
|
for the heap and stack.
|
|
|
|
\subsection{End options}
|
|
End options terminate argument parsing.
|
|
The \ex{-i} switch is followed by the name of a heap image for the
|
|
vm to execute, and terminates vm argument parsing;
|
|
following arguments are passed off to the heap image's top-level program.
|
|
The \ex{--} switch terminates argument parsing without giving
|
|
a specific heap image; the vm will start up with using a default
|
|
heap (whose location is compiled into the vm).
|
|
|
|
Notice that you are not allowed to pass arguments to the heap image's
|
|
top-level program (\eg, scsh) without delimiting them with \ex{-i}
|
|
or \ex{--} flags.
|
|
|
|
\section{Scsh arguments}
|
|
\label{sec:scsh-args}
|
|
|
|
Scsh's top-level argument parser takes arguments in a simple
|
|
format:
|
|
\codex{scsh [\var{end-option} \vari{arg}1 {\ldots} \vari{arg}n]}
|
|
where
|
|
\begin{inset}
|
|
\begin{tabular}{ll}
|
|
\var{end-option:} & \ex{-s} \var{script} \\
|
|
& \ex{--}
|
|
\end{tabular}
|
|
\end{inset}
|
|
The \ex{-s} argument causes scsh to load a script file and exit.
|
|
It also terminates argument parsing; following arguments are passed
|
|
to the scsh program as the value of \ex{command-line-arguments}.
|
|
|
|
If the \ex{-s} argument is not given, scsh runs in interactive mode,
|
|
with a standard {\scm} prompt-read-eval-print loop.
|
|
|
|
The \ex{--} switch terminates argument parsing without specifying a
|
|
script to load; it allows the user to pass arguments to an interactive scsh.
|
|
|
|
Shell scripts can be written and invoked with a \ex{\#!} initial line.
|
|
Scsh defines the sequence \ex{\#!} to be a read-macro similar
|
|
to the comment character \ex{;}.
|
|
The read-macro causes scsh to skip characters until it reads a newline,
|
|
\ex{!}, \ex{\#}, newline sequence.
|
|
So an initial \ex{\#!} line is ignored by scsh.
|
|
|
|
% Since there is no standalone scsh binary, scsh scripts must do a double
|
|
% level-shift, invoking the vm on the scsh heap image on the scsh script.
|
|
% The appropriate magic top three lines are:
|
|
% \begin{code}
|
|
% #!/usr/local/bin/scshvm \\
|
|
% -o /usr/local/bin/scshvm -i /usr/local/lib/scsh/scsh.image -s
|
|
% !#
|
|
% {\ldots} \textnormal{\emph{Your Scheme code goes here}} \ldots\end{code}
|
|
|
|
\section{Compiling shell scripts}
|
|
The {\Scheme} implementation of scsh allows you to create a heap image
|
|
with your own top-level procedure.
|
|
Adding the pair of lines
|
|
\begin{code}
|
|
#!/usr/local/bin/scshvm \\\\
|
|
-o /usr/local/bin/scshvm -i
|
|
\end{code}
|
|
to the top of the heap image will turn it into an executable {\Unix} file.
|
|
|
|
\defun{dump-scsh-program}{main fname}{\undefined}
|
|
\begin{desc}
|
|
This procedure writes out a scsh heap image. When the
|
|
heap image is executed by the {\Scheme} vm, it will call
|
|
the \var{main} procedure on no arguments and then exit.
|
|
The {\Scheme} vm will parse command-line arguments as
|
|
described in section~\ref{sec:vm-args}, and bind remaining
|
|
arguments to the \ex{command-line-arguments} variable before
|
|
calling \ex{main}. Further argument parsing (as described for
|
|
scsh in section~\ref{sec:scsh-args} is not performed.
|
|
|
|
The heap image created by \ex{dump-scsh-program} has unused
|
|
code and data pruned out, so small programs compile to much smaller
|
|
heap images.
|
|
\end{desc}
|
|
|
|
\section{Standard file locations}
|
|
Because the scshvm binary is intended to be used for writing shell
|
|
scripts, it is important that the binary be installed in a standard
|
|
place, so that shell scripts can dependably refer to it.
|
|
The standard directory for the scsh tree should be \ex{/usr/local/lib/scsh/}.
|
|
Whenever possible, the vm should be located in
|
|
\codex{/usr/local/lib/scsh/scshvm}
|
|
and a scsh heap image should be located in
|
|
\codex{/usr/local/lib/scsh/scsh.image}
|
|
The top-level scsh program should be located in
|
|
\codex{/usr/local/lib/scsh/scsh}
|
|
with a symbolic link to it from
|
|
\codex{/usr/local/bin/scsh}
|
|
|
|
The {\scm} image format allows heap images to have \ex{\#!} triggers,
|
|
so \ex{scsh.image} should have a \ex{\#!} trigger of the following form:
|
|
\begin{code}
|
|
#!/usr/local/bin/scshvm \\
|
|
-o /usr/local/bin/scshvm -i
|
|
{\ldots} \textnormal{\emph{heap image goes here}} \ldots\end{code}
|