%&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}