essentially provide a little linker language for linking a shell script or a
program together with {\scm} modules.
The command-line processor serially opens structures and loads code into a
given package.
Switches that side-effect a package operate on a particular ``current''
package; there are switches to change this package.
(These switches provide functionality equivalent to the interactive
\ex{,open}\ex{,load}\ex{,in} and \ex{,new} commands.)
Except where indicated, switches specify actions that are executed in a
left-to-right order.
The initial current package is the user package, which is completely
empty and opens (imports the bindings of) the R4RS and scsh structures.
If the Scheme process is started up in an interactive mode, then the current
package in force at the end of switch scanning is the one inside which
the interactive read-eval-print loop is started.
The command-line switch processor works in two passes:
it first parses the switches, building a list of actions to perform,
then the actions are performed serially.
The switch list is terminated by one of the \var{end-option} switches.
The \vari{arg}{i} arguments occurring after an end-option switch are
passed to the scsh program as the value of \ex{command-line-arguments}
and the tail of the list returned by \ex{(command-line)}.
That is, an \var{end-option} switch separates switches that control
the scsh ``machine'' from the actual arguments being passed to the scsh
program that runs on that machine.
The following switches and end options are defined:
\begin{itemize}
\def\Item#1{\item{\ex{#1}}\\}
\Item{-o \var{struct}}
Open the structure in the current package.
\Item{-n \var{package}}
Make and enter a new package. The package has an associated structure
named \var{package} with an empty export list.
If \var{package} is the string ``\ex{\#f}'',
the new package is anonmyous, with no associated named structure.
The new package initially opens no other structures,
not even the R4RS bindings. You must follow a ``\ex{-n foo}''
switch with ``\ex{-o scheme}'' to access the standard identifiers such
as \ex{car} and \ex{define}.
\Item{-m \var{struct}}
Change the current package to the package underlying
structure \var{struct}.
(The \ex{-m} stands for ``module.'')
\Item{-lm \var{module-file-name}}
Load the specified file into scsh's config package --- the file
must contain source written in the Scheme 48 module language
(``load module''). Does not alter the current package.
\Item{-l \var{file-name}}
Load the specified file into the current package.
\Item{-c \var{exp}}
Evaluate expression \var{exp} in the current package and exit.
This is called \ex{-c} after a common shell convention (see sh and csh).
The expression is evaluated in the the current package (and hence is
affected by \ex{-m}'s and \ex{-n}'s.)
When the scsh top-level constructs the scsh command-line in this case,
it takes \ex{"scsh"} to be the program name.
This switch terminates argument scanning; following args become
the tail of the command-line list.
\Item{-e \var{entry-point}}
Specify an entry point for a program. The \var{entry-point} is
a variable that is taken from the current package in force at the end
of switch evaluation. The entry point does not have to be exported
by the package in a structure; it can be internal to the package.
The top level passes control to the entry point by applying it to
the command-line list (so programs executing in private
packages can reference their command-line arguments without opening
the \ex{scsh} package to access the \ex{(command-line)} procedure).
Note that, like the list returned by the \ex{(command-line)} procedure,
the list passed to the entry point includes the name
of the program being executed (as the first element of the list),
not just the arguments to the program.
A \ex{-e} switch can occur anywhere in the switch list, but it is the
\emph{last} action performed by switch scanning if it occurs.
(We violate ordering here as the shell-script \ex{\#!} mechanism
prevents you from putting the \emph{-e} switch last, where it belongs.)
\Item{-s \var{script}}
Specify a file to load.
A \ex{-ds} (do-script) or \ex{-dm} (do-module) switch occurring earlier in
the switch list gives the place where the script should be loaded. If
there is no \ex{-ds} or \ex{-dm} switch, then the script is loaded at the
end of switch scanning, into the module that is current at the end of
switch scanning.
We use the \ex{-ds} switch to violate left-to-right switch execution order
as the \ex{-s} switch is \emph{required} to be last
(because of the \ex{\#!} machinery),
independent of when/where in the switch-processing order
it should be loaded.
When the scsh top-level constructs the scsh command-line in this case,
it takes \var{script} to be the program name.
This switch terminates switch parsing; following args are ignored
by the switch-scanner and are passed through to the program as
the tail of the command-line list.
\Item{-sfd \var{num}}
Loads the script from file descriptor \var{num}.
This switch is like the \ex{-s} switch,
except that the script is loaded from one of the process' open input
file descriptors.
For example, to have the script loaded from standard input, specify
\ex{-sfd 0}.
\Item{--}
Terminate argument scanning and start up scsh in interactive mode.
If the argument list just runs out, without either a terminating
\ex{-s} or \ex{--} arg, then scsh also starts up in interactive mode,
with an empty \ex{command-line-arguments} list
(for example, simply entering \ex{scsh} at a shell prompt with no
args at all).
When the scsh top-level constructs the scsh command-line in this case,
it takes \ex{"scsh"} to be the program name.
This switch terminates switch parsing; following args are ignored
by the switch-scanner and are passed through to the program as
the tail of the command-line list.
\Item{-ds}
Specify when to load the script (``do-script''). If this switch occurs,
the switch list \emph{must} be terminated by a \ex{-s \var{script}}
switch. The script is loaded into the package that is current at the
\ex{-ds} switch.
\Item{-dm}
As above, but the current module is ignored. The script is loaded into the
\ex{config} package (``do-module''), and hence must be written in the
{\scm} module language.
This switch doesn't affect the current module---after executing this
switch, the current module is the same as as it was before.
This switch is provided to make it easy to write shell scripts in the
{\scm} module language.
\end{itemize}
\subsection{The meta argument}
\label{sec:meta-arg}
The scsh switch parser takes a special command-line switch,
a single backslash called the ``meta-argument,'' which is useful for
shell scripts.
If the initial command-line argument is a ``\verb|\|''
argument, followed by a filename argument \var{fname}, scsh 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 the Unix \ex{echo} program:
\begin{code}
#!/usr/local/bin/scsh -e main -s
!#
(define (main args)
(map (\l{arg} (display arg) (display " "))
(cdr args))
(newline))\end{code}
%
The idea would be that the command
\codex{ekko Hi there.}
would by expanded by the \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}} kernel call into
%
\begin{code}
/usr/local/bin/scsh -e main -s ekko Hi there.\end{code}
%
In theory, this would cause scsh to start up, load in file \ex{ekko},
call the entry point on the command-line list
\codex{(main '("ekko" "Hi" "there."))}
and exit.
Unfortunately, the {\Unix}\ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}} syscall's support for scripts is
not very general or well-designed.
It will not handle multiple arguments;
the \ex{\#!} line is usually required to contain no more than 32 characters;
it is not recursive.
If these restrictions are violated, most Unix systems will not provide accurate
error reporting, but either fail silently, or simply incorrectly implement
the desired functionality.
These are the facts of Unix life.
In the \ex{ekko} example above, our \ex{\#!} trigger line has three
arguments (``\ex{-e}'', ``\ex{main}'', and ``\ex{-s}''), so it will not
work.
The meta-argument is how we work around this problem.
We must instead invoke the scsh interpreter with the single \cd{\\} argument,
and put the rest of the arguments on line two of the program.
Here's the correct program:
%
\begin{code}
#!/usr/local/bin/scsh \\
-e main -s
!#
(define (main args)
(map (\l{arg} (display arg) (display " "))
(cdr args))
(newline))\end{code}
%
Now, the invocation starts as
\codex{ekko Hi there.}
and is expanded by exec(2) into
\begin{code}
/usr/local/bin/scsh \\ ekko Hi there.\end{code}
When scsh 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{-e main -s ekko} Hi there.
$\uparrow$
{\rm{}Expanded from}\cd{\\} ekko\end{code}
%
With this argument list, processing proceeds as we intended.
\subsubsection{Secondary argument syntax}
Scsh uses a very simple grammar to encode the extra arguments on
the second line of the scsh script.
The only special characters are space, tab, newline, and backslash.
\begin{itemize}
\item Each space character terminates an argument.
This means that two spaces in a row introduce an empty-string argument.
\item The tab character is not permitted
(unless you quote it with the backslash character described below).
This is to prevent the insidious bug where you believe you have
six space characters, but you really have a tab character,
and \emph{vice-versa}.
\item The newline character terminates an argument, like the space character,
and also terminates the argument sequence.
This means that an empty line parses to the singleton list whose one
element is the empty string: \ex{("")}.
The grammar doesn't admit the empty list.
\item The backslash character is the escape character.
It escapes backslash, space, tab, and newline, turning off their
special functions, and allowing them to be included in arguments.
The {\Ansi} C escape sequences (\verb|\b|, \verb|\n|, \verb|\r|
and \verb|\t|) are also supported;
these also produce argument-constituents---\verb|\n| doesn't act
like a terminating newline.
The escape sequence \verb|\|\emph{nnn} for \emph{exactly} three
octal digits reads as the character whose {\Ascii} code is \emph{nnn}.
It is an error if backslash is followed by just one or two octal digits:
\verb|\3Q| is an error.
Octal escapes are always constituent chars.
Backslash followed by other chars is not allowed
(so we can extend the escape-code space later if we like).
\end{itemize}
You have to construct these line-two argument lines carefully.
In particular, beware of trailing spaces at the end of the line---they'll
give you extra trailing empty-string arguments.
Here's an example:
%
\begin{inset}
\begin{verbatim}
#!/bin/interpreter \
foo bar quux\ yow\end{verbatim}
\end{inset}
%
would produce the arguments
%
\codex{("foo" "bar" "" "quux yow")}
\subsection{Examples}
\begin{itemize}
\def\Item#1{\item{\ex{#1}}\\}
\def\progItem#1{\item{Program \ex{#1}}\\}
\Item{scsh -dm -m myprog -e top -s myprog.scm}
Load \ex{myprog.scm} into the \ex{config} package, then shift to the
\ex{myprog} package and call \ex{(top '("myprog.scm"))}, then exit.
This sort of invocation is typically used in \ex{\#!} script lines
(see below).
\Item{scsh -c '(display "Hello, world.")'}
A simple program.
\Item{scsh -o bigscheme}
Start up interactively in the user package after opening
structure \ex{bigscheme}.
\Item{scsh -o bigscheme -- Three args passed}
Start up interactively in the user package after opening \ex{bigscheme}.
The \ex{command-line-args} variable in the scsh package is bound to the
list \ex{("Three" "args" "passed")}, and the \ex{(command-line)}
procedure returns the list \ex{("scsh" "Three" "args" "passed")}.
\progItem{ekko}
This shell script, called \ex{ekko}, implements a version of
the Unix \ex{echo} program:
\begin{code}
#!/usr/local/bin/scsh -s
!#
(for-each (\l{arg} (display arg) (display " "))
command-line-args)\end{code}
Note this short program is an example of a \emph{script}---it
executes as it loads.
The Unix rule for executing \ex{\#!} shell scripts causes
\codex{ekko Hello, world.}
to expand as
\codex{/usr/local/bin/scsh -s ekko Hello, world.}
\progItem{ekko}
This is the same program, \emph{not} as a script.
Writing it this way makes it possible to compile the program
(and then, for instance, dump it out as a heap image).
%
\begin{code}
#!/usr/local/bin/scsh \\
-e top -s
!#
(define (top args)
(for-each (\l{arg} (display arg) (display " "))
(cdr args)))\end{code}
%
The \ex{\urlh{http://www.FreeBSD.org/cgi/man.cgi?query=exec&apropos=0&sektion=0&manpath=FreeBSD+4.3-RELEASE&format=html}{exec(2)}} expansion of the \ex{\#!} line together with
the scsh expansion of the ``\verb|\ ekko|'' meta-argument
(see section~\ref{sec:meta-arg}) gives the following command-line expansion: