.\" -*-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 --------------------------------------------------