slsh, also known as the S-Lang shell, is an application that is included in the stock S-Lang distribution. As some binary distributions include slsh as a separate package it must be installed separately, e.g.,
apt-get install slsh
on Debian Linux systems. The use of slsh in its interactive mode
was discussed briefly in the
Introduction. This chapter
concentrates on the use of slsh for writing executable S-Lang
scripts.
When run the --help
command-line argument, slsh displays a
brief usage message:
# slsh --help
Usage: slsh [OPTIONS] [-|file [args...]]
--help Print this help
--version Show slsh version information
-e string Execute 'string' as S-Lang code
-g Compile with debugging code, tracebacks, etc
-n Don't load personal init file
--init file Use this file instead of ~/.slshrc
--no-readline Do not use readline
-i Force interactive input
-t Test mode. If slsh_main exists, do not call it
-v Show verbose loading messages
-Dname Define "name" as a preprocessor symbol
Note: - and -i are mutually exclusive
Default search path: /usr/local/share/slsh
When started with no arguments, slsh will start in interactive mode
and take input from the terminal. As the usage message indicates
slsh loads a personal initialization file called .slshrc
(on
non-Unix systems, this file is called slsh.rc
). The contents
of this file must be valid S-Lang code, but are otherwise arbitrary.
One use of this file is to define commonly used functions and to
setup personal search paths.
slsh will run in non-interactive mode when started with a file (also
known as a ``script'') as its first (non-option) command-line
argument. The rest of the arguments on the command line serve as
arguments for the script. The next section deals with the use of the
cmdopt
routines for parsing those arguments.
slsh will read the script and feed it to the S-Lang interpreter for
execution. If the script defines a public function called
slsh_main
, then slsh will call it after the script has been
loaded. In this sense, slsh_main
is analogous to main
in C or C++.
A typical slsh script is be structured as
#!/usr/bin/env slsh
.
.
define slsh_main ()
{
.
.
}
The first line of the script Unix-specific and should be familiar to
Unix users. Typically, the code before slsh_main
will load
any required modules or packages, and define other functions to be
used by the script.
Although the use of slsh_main
is not required, its use is
strongly urged for several reasons. In addition to lending
uniformity to S-Lang scripts, slsh_main
is well supported by
the S-Lang debugger (sldb) and the S-Lang profiler (slprof), which
look for slsh_main
as a starting point for script execution.
Also as scripts necessarily do something (otherwise they have no
use), slsh's -t
command-line option may be used to turn off
the automatic execution of slsh_main
. This allows the syntax
of the entire script to be checked for errors instead of running it.
The script's command-line arguments are availble to it via the
__argc
and __argv
intrinsic variables. Any optional
arguments represented by these variables may be parsed using slsh's
cmdopt routines.
As a useful illustration, consider the script that the author uses to
rip tracks from CDs to OGG encoded files. The name of the script
is cd2ogg.sl
. Running the script without arguments causes it
to issue a usage message:
Usage: cd2ogg.sl [options] device
Options:
--help This help
--work DIR Use DIR as working dir [/tmp/29848]
--root DIR Use DIR/GENRE as root for final output [/data/CDs]
--genre GENRE Use GENRE for output dir
--no-rip Skip rip stage
--no-normalize Skip normalizing stage
--no-encode Don't encode to ogg
--albuminfo PERFORMER/TITLE
Use PERFORMER/TITLE if audio.cddb is absent
As the message shows, some of the options require an argument while
others do not. The cd2ogg.sl script looks like:
#!/usr/bin/env slsh
require ("cmdopt");
.
.
private define exit_usage ()
{
() = fprintf (stderr, "Usage: %s [options] device\n",
path_basename (__argv[0]));
() = fprintf (stderr, "Options:\n");
.
.
exit (1);
}
private define parse_album_info (albuminfo)
{
...
}
define slsh_main ()
{
variable genre = NULL;
variable no_rip = 0;
variable no_normalize = 0;
variable no_encode = 0;
variable opts = cmdopt_new ();
opts.add ("help", &exit_usage);
opts.add ("device", &CD_Device; type="str");
opts.add ("work", &Work_Dir; type="str");
opts.add ("root", &Root_Dir; type="str");
opts.add ("genre", &genre; type="str");
opts.add ("albuminfo", &parse_album_info; type="str");
opts.add ("no-normalize", &no_normalize);
opts.add ("no-encode", &no_encode);
variable i = opts.process (__argv, 1);
if (i + 1 != __argc)
exit_usage ();
CD_Device = __argv[i];
.
.
}
There are several points that one should take from the above example.
First, to use the cmdopt
interface it is necessary to load it.
This is accomplished using the require
statement. Second, the
above example uses cmdopt
's object-oriented style interface
through the use of the add
and process
methods of the
cmdopt
object created by the call to cmdopt_new
. Third,
two of the command line options make use of callback functions: the
exit_usage
function will get called when --help
appears
on the command line, and the parse_album_info
function will
get called to handle the --albuminfo
option. Options such as
--no-encode
do not take a value and the presence of such an
option on the command line causes the variable associated with the
option to be set to 1. Other options such as --genre
will
cause the variable associated with them to be set of the value
specified on the command-line. Finally, the process
method
returns the index of __argv
that corresponds to ``non-option''
argument. In this case, for proper usage of the script, that
argument would correspond to device representing the CD drive.
For more information about the cmdopt
interface, see the
documentation for cmdopt_add
:
slsh> help cmdopt_add