.\" -*-nroff-*-
.\"
.\" Manual for `runlisp'
.\"
.\" (c) 2020 Mark Wooding
.\"
.
.\"----- Licensing notice ---------------------------------------------------
.\"
.\" This file is part of Runlisp, a tool for invoking Common Lisp scripts.
.\"
.\" Runlisp is free software: you can redistribute it and/or modify it
.\" under the terms of the GNU General Public License as published by the
.\" Free Software Foundation; either version 3 of the License, or (at your
.\" option) any later version.
.\"
.\" Runlisp is distributed in the hope that it will be useful, but WITHOUT
.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
.\" for more details.
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with Runlisp. If not, see .
.
.ie t \{\
. ds o \(bu
. if \n(.g \{\
. fam P
. ev an-1
. fam P
. ev
. \}
.\}
.el \{\
. ds o o
.\}
.
.de hP
.IP
\h'-\w'\fB\\$1\ \fP'u'\fB\\$1\ \fP\c
..
.
.\"--------------------------------------------------------------------------
.TH runlisp 1 "2 August 2020" "Mark Wooding"
.SH NAME
runlisp \- run Common Lisp programs as scripts
.
.\"--------------------------------------------------------------------------
.SH SYNOPSIS
.
.B runlisp
.RI [ options ]
.RB [ \-\- ]
.I script
.RI [ arguments
\&...]
.br
.B runlisp
.RI [ options ]
.RB [ \-e
.IR form ]
.RB [ \-l
.IR file ]
.RB [ \-p
.IR form ]
.RB [ \-\- ]
.RI [ arguments
\&...]
.PP
where
.I options
is
.br
\&
.RB [ \-CDEnqv ]
.RB [ +DEn ]
.RB [ \-L
.IB sys , sys , \fR...]
.RB [ \-c
.IR conf ]
.RB [ \-o
.RI [ sect \c
.BR : ] \c
.IB var = \c
.IR value ]
.
.\"--------------------------------------------------------------------------
.SH DESCRIPTION
.
The
.B runlisp
program has two main functions.
.hP 1.
It can be used in a script's
.RB ` #! '
line to run a Common Lisp script.
.hP 2.
It can be used in build scripts
to invoke a Common Lisp system,
e.g., to build a standalone program.
.
.SS "Options"
Options are read from the command line, as usual,
but also (by default) from the script's second line,
following a
.RB ` @RUNLISP: '
marker: see
.B Operation
below for the details.
.
.PP
The options accepted are as follows.
.
.TP
.BR "\-h" ", " "\-\-help"
Write a synopsis of
.BR query-runlisp-config 's
command-line syntax
and a description of the command-line options
to standard output
and immediately exit with status 0.
.
.TP
.BR "\-V" ", " "\-\-version"
Write
.BR query-runlisp-config 's
version number
to standard output
and immediately exit with status 0.
.
.TP
.BR "\-D" ", " "\-\-vanilla-image"
Don't check for a custom Lisp image.
Usually,
.B runlisp
tries to start Lisp systems using a custom image,
so that they'll start more quickly;
the
.RB ` \-D '
option forces the use of the default `vanilla' image
provided with the system.
There's not usually any good reason to prefer the vanilla image,
except for performance comparisons, or debugging
.B runlisp
itself.
Negate with
.B +D
or
.BR \-\-no-vanilla-image .
.
.TP
.BR "\-E" ", " "\-\-command-line-only"
Don't read embedded options from the
second line of the
.I script
file.
Negate with
.B +E
or
.BR \-\-no-command-line-only .
This has no effect in eval mode.
which is set at compile time.
.
.TP
.BI "\-L" "\fR, " "\-\-accept-lisp=" sys , sys ,\fR...
Use one of the named Lisp systems.
Each
.I sys
must name a supported Lisp system;
the names are separated by a comma
.RB ` , '
and/or one or more whitespace characters.
This option may be given more than once:
the effect is the same as a single option
listing all of the systems named, in the same order.
If a system is named more than once,
a warning is issued (at verbosity level 1 or higher),
and all but the first occurrence is ignored.
.
.TP
.BI "\-c" "\fR, " "\-\-config-file=" conf
Read configuration from
.IR conf .
If
.I conf
is a directory, then all of the files within
whose names end with
.RB ` .conf ',
are loaded, in ascending lexicographical order;
otherwise,
.I conf
is opened as a file.
All of the files are expected to as described in
.BR runlisp.conf (5).
.
.TP
.BI "\-e" "\fR, " "\-\-evaluate-expression=" expr
Evaluate the expression(s)
.I expr
and discard the resulting values.
This option causes
.B runlisp
to execute in
.I eval
mode.
.
.TP
.BI "\-l" "\fR, " "\-\-load-file=" file
Read and evaluate forms from the
.IR file .
This option causes
.B runlisp
to execute in
.I eval
mode.
.
.TP
.BR "\-n" ", " "-\-dry-run"
Don't actually start the Lisp environment.
This may be helpful for the curious,
in conjunction with
.RB ` \-v '
to increase the verbosity.
Negate with
.B +n
or
.BR "\-\-no-dry-run" .
.
.TP
.BI "\-p" "\fR, " "\-\-print-expressin=" expr
Evaluate the expression(s)
.I expr
and print the resulting value(s)
to standard output
(as if by
.BR prin1 ).
If a form produces multiple values,
they are printed on a single line,
separated by a single space character;
if a form produces no values at all,
then nothing is printed \(en not even a newline character.
This option causes
.B runlisp
to execute in
.I eval
mode.
.
.TP
.BR "\-q" ", " "\-\-quiet"
Don't print warning messages.
This option may be repeated:
each use reduces verbosity by one step,
counteracting one
.RB ` \-v '
option.
The default verbosity level is 1,
which prints only warning measages.
.
.TP
.BR "\-v" ", " "\-\-verbose"
Print informational or debugging messages.
This option may be repeated:
each use increases verbosity by one step,
counteracting one
.RB ` \-q '
option.
The default verbosity level is 1,
which prints only warning measages.
Higher verbosity levels print informational and debugging messages.
.
.PP
The
.RB ` \-e ',
.RB ` \-l ',
and
.RB ` \-p '
options may only be given on the command-line itself,
not following a
.RB `@ RUNLISP: '
marker in a script.
These options may be given multiple times:
they will be processed in the order given.
If any of these options is given, then no
.I script
name will be parsed;
instead, use
.RB ` \-l '
to load code from files.
The
.IR arguments ,
ppif any,
are still made available to the evaluated forms and loaded files.
.
.SS "Operation"
The
.B runlisp
program behaves as follows.
.
.hP 1.
The first thing it does is parse its command line.
Options must precede positional arguments,
though the boundary may be marked explicitly using
.RB ` \-\- '
if desired.
If the command line contains any of
.RB ` \-e ',
.RB ` \-l ',
or
.RB ` \-p ',
then
.B runlisp
treats all of its positional arguments as
.I arguments
to provide to the given forms and files,
and runs in
.I eval
mode;
otherwise, the first positional argument becomes the
.I script
name, the remaining ones become
.IR arguments ,
and
.B runlisp
runs in
.I script
mode.
.hP 2.
In
.I script
mode,
.B runlisp
reads the second line of the script file,
and checks to see if it contains the string
.RB ` @RUNLISP: '.
If so, then the following text is parsed
for
.IR "embedded options" ,
as follows.
.RS
.PP
The text is split into words
separated by sequences of whitespace characters.
Whitespace,
and other special characters,
can be included in a word by
.I quoting
or
.IR escaping .
Text between single quotes
.BR ' ... '
is included literally, without any further interpretation;
text between double quotes
.BR """" ... """"
is treated literally,
except that escaping can still be used
to escape (e.g.) double quotes and the escape character itself.
Outside of single quotes, a backslash
.RB ` \e '
causes the following character to be included in a word
regardless of its usual meaning.
(None of this allows a newline character
to be included in a word:
this is simply not possible.)
A word which is
.RB ` \-\- '
before processing quoting and escaping
marks the end of embedded options.
As a concession to Emacs users,
if the sequence
.RB ` \-*\- '
appears at the start of a word
before processing quoting and escaping,
then everything up to and including the next occurrence of
.RB ` \-*\- '
is ignored.
.PP
The resulting list of words
is processed as if it held further command-line options.
Currently, only
.RB ` \-D '
and
.RB ` \-L '
options are permitted in embedded option lists:
.RB ` \-h '
and
.RB ` \-v '
are clearly only useful in interactive use;
setting
.RB ` \-q '
or
.RB ` \-v '
would just be annoying;
setting
.RB ` \-c '
or
.RB ` \-o '
would override the user's command-line settings;
it's clearly too late to set
.RB ` \-E ';
and
.B runlisp
is now committed to
.I script
mode, so it's too late for
.RB ` \-e ',
.RB ` \-l ',
and
.RB ` \-p '
too.
.PP
(This feature allows scripts to provide options even if they use
.BR env (1)
to find
.B runlisp
on the
.BR PATH ,
or to provide more than one option,
since many operating systems pass the text following
the interpreter name on a
.RB ` #! '
line as a single argument, without further splitting it at spaces.)
.RE
.
.hP 3.
If no
.RB ` \-c '
options were given,
then the default configuration files are read:
the system configuration from
.B @etcdir@/runlisp.conf
and
.BR @etcdir@/runlisp.d/*.conf ,
and the user configuration from
.B ~/.runlisp.conf
and/or
.BR ~/.config/runlisp.conf :
see
.RB runlisp.conf (5)
for the details.
.
.hP 4.
The list of
.I "acceptable Lisp implementations"
is determined.
If any
.RB ` \-L '
options have been found,
then the list of acceptable implementations
consists of all of the implementations mentioned in
.RB ` -L '
options
in any of the places
.B runlisp
looked for options,
in the order of their first occurrence.
(If an implementation is named more than once,
then
.B runlisp
prints a warning to stderr
and ignores all but the first occurrence.)
If no
.RB ` \-L '
option is given, then
.B runlisp
uses a default list,
which consists of all of the Lisp implementations
defined in its configuration,
in the order in which they were defined.
.
.hP 5.
The list of
.I "preferred Lisp implementations"
is determined.
If the environment variable
.B RUNLISP_PREFER
is set,
then its value should be a list of names of Lisp implementations
separated by a comma and/or one or more whitespace characters.
Otherwise, if there is a setting for the variable
.B prefer
in the
.B @CONFIG
configuration section,
then its (expanded) value should be a list of Lisp implementations,
in the same way.
Otherwise, the list of preferred implementations is empty.
.
.hP 6.
If
.B runlisp
is running in
.I eval
mode, then a new command line is built,
which invokes an internal script,
instructing it to evaluate and print the requested expressions,
and load the requested files.
.
.hP 7.
Acceptable Lisp implementations are tried in turn.
First, the preferred implementations
which are also listed as acceptable implementations
are tried, in the order in which they appear
in the preferred implementations list;
then, the remaining acceptable implementations are tried
in the order in which they appear
in the acceptable implementations list.
.RS
.PP
A Lisp implementation is defined by a configuration section
which defines a variable
.BR run-script .
The name of the configuration section
is the name of the Lisp implementation,
as used in the acceptable and preferred lists described above.
.hP (a)
The variable
.B image-file
is looked up in the configuration section.
If a value is found, then
.B runlisp
looks up and expands
.BR image-path ,
and checks to see if a file exists with the resulting name.
If so, it sets the variable
.B @image
to
.B t
in the configuration section.
.hP (b)
The variable
.B run-script
is expanded and word-split.
The
.I script
(an internal script, in
.I eval
mode)
and
.IR argument s
are appended, and
the entire list is passed to the
.BR execvp (3)
function.
If that succeeds, the Lisp implementation runs;
if it fails with
.B ENOENT
then other Lisp systems are tried;
if it fails with some other error, then
.B runlisp
reports an error message to stderr
and exits unsuccessfully
(with code 127).
If the
.RB ` \-n '
option was given, then
.B runlisp
just simulates the behaviour of
.BR execvp (3),
printing messages to stderr
if the verbosity level is sufficiently high,
and exits.
.
.SS "Script environment"
Many Lisp implementations don't provide a satisfactory environment
for scripts to run in.
The actual task of invoking a Lisp implementation
is left to configuration,
but the basic configuration supplied with
.B runlisp
ensures the following facts about their environment.
.hP \*o
The keyword
.B :runlisp-script
is added to the
.B *features*
list if
.B runlisp
is running in
.I script
mode.
.hP \*o
Most Lisp systems support a user initialization file
which they load before entering the REPL;
some also have a system initialization file.
The
.B runlisp
program arranges
.I not
to read these files,
so that the Lisp environment is reasonably predictable,
and to avoid slowing down script startup
with things which are convenient for use in an interactive session,
but can't be relied upon by a script anyway.
.hP \*o
The Unix standard input, standard output, and standard error files
are available through the Lisp
.BR *standard-input* ,
.BR *standard-output* ,
and
.BR *error-output*
streams, respectively.
.hP \*o
Both
.B *compile-verbose*
and
.B *load-verbose*
are set to nil.
On CMU\ CL,
.B ext:*require-verbose*
is also nil.
Alas, this is insufficient to muffle noise while loading add-on systems
on some implementations.
.hP \*o
If an error is signalled, and not caught by user code,
then the process will print a message to stderr
and exit with a nonzero status.
The reported message may be a long, ugly backtrace,
or a terse error report.
If no error is signalled but not caught,
then the process will exit with status 0.
.hP \*o
The initial package is
.BR COMMON-LISP-USER ,
which has no symbols `present' (i.e., imported or interned).
.hP \*o
The
.B asdf
and
.B uiop
systems are already loaded.
Further systems can be loaded using
.B asdf:load-system
as usual.
The script name
(which is only meaningful if
.B runlisp
is in
.I script
mode, obviously)
and arguments are available through the
.B uiop:argv0
function and
.B uiop:*command-line-arguments*
variable, respectively.
.
.\"--------------------------------------------------------------------------
.
.SH BUGS
.hP \*o
Loading ASDF systems is irritatingly noisy
with some Lisp implementations.
Suggestions for how to improve this are welcome.
.hP \*o
More Lisp implementations should be supported.
I've supported the ones I have installed.
I'm not willing to put a great deal of effort into supporting
non-free Lisp implementations;
but help supporting free Lisps is much appreciated.
.hP \*o
The protocol for passing the script name through to
.B uiop
(specifically, through the
.B __CL_ARGV0
environment variable)
is terribly fragile,
but supporting
.B uiop
is obviously a better approach than introducing a
.BR runlisp -specific
interface to the same information.
I don't know how to fix this:
suggestions are welcome.
.
.SH SEE ALSO
.BR dump-runlisp-image (1),
.BR query-runlisp-config (1),
.BR runlisp.conf (5).
.
.SH AUTHOR
Mark Wooding,
.
.\"----- That's all, folks --------------------------------------------------