chiark / gitweb /
eval.lisp: Rename `print-form' to make way for other kinds of printing.
[runlisp] / runlisp-base.conf
... / ...
CommitLineData
1;;; -*-conf-windows-*-
2
3;; This file contains essential definitions for `runlisp'. You are
4;; encouraged to put your local changes in the main `runlisp.conf', or in
5;; other files alongside this one in `runlisp.d/', rather then editing this
6;; file.
7
8;; Summary of syntax.
9;;
10;; Sections are started with a line `[NAME]', starting in the leftmost
11;; column. Empty lines and lines starting with `;' -- /without/ preceding
12;; whitespace -- are ignored. Assignments have the form `VAR = VALUE'; the
13;; VALUE may be continued across multiple lines, if they begin with
14;; whitespace. All of the lines are stripped of initial and final whitespace
15;; and concatenated with spaces.
16;;
17;; Values may contain substitutions:
18;;
19;; * ${[SECTION:]VAR[?ALT]} -- replace with the value of VAR in SECTION; if
20;; not found, use ALT instead. (If ALT isn't provided, it's an error.)
21;;
22;; * $?[SECTION:]VAR{YES[|NO]} -- look up VAR in SECTION (or in the
23;; (original) current section, and `@COMMON'); if found, use YES,
24;; otherwise use NO.
25;;
26;; Variables are looked up starting in the home (or explicitly specified)
27;; section, then proceeding to the parents assigned to `@PARENTS'.
28;; (`@PARENTS' usually defaults to `@COMMON'; the parent of `@COMMON' is
29;; `@BUILTIN'; `@BUILTIN' and `@CONFIG' have no parents.)
30;;
31;; At top-level, the text is split into words at whitespace, unless prevented
32;; by double- and single-quote, or escaped by `\'. Within single quotes, all
33;; characters are treated literally. Within double quotes, `\' and `$' still
34;; works. A variable reference within quotes, or within a word, suppresses
35;; word-splitting and quoting, within the variable value -- but `$'
36;; expansions still work.
37
38;;;--------------------------------------------------------------------------
39[@COMMON]
40
41;; Turn `#!' into a comment-to-end-of-line. This is used in all Lisp
42;; invocations, even though some of them don't apparently need it. For
43;; example, SBCL ignores an initial line beginning `#!' as a special feature
44;; of its `--script' option. Other Lisps won't do this, so a countermeasure
45;; like the following is necessary in their case. For the sake of a
46;; consistent environment, we ignore `#!' lines everywhere, even in Lisps
47;; which have their own, more specific, solution to this problem.
48ignore-shebang =
49 (set-dispatch-macro-character
50 #\\# #\\!
51 (lambda (#1=#:stream #2=#:char #3=#:arg)
52 (declare (ignore #2# #3#))
53 (values (read-line #1#))))
54
55;; Clear all present symbols from the `COMMON-LISP-USER' package. Some Lisps
56;; leave débris in `COMMON-LISP-USER' -- for example, ECL leaves some
57;; allegedly useful symbols lying around, while ABCL has a straight-up bug in
58;; its `adjoin.lisp' file.
59clear-cl-user =
60 (let ((#4=#:pkg (find-package "COMMON-LISP-USER")))
61 (with-package-iterator (#5=#:next #4# :internal)
62 (loop (multiple-value-bind (#6=#:anyp #7=#:sym #8=#:how)
63 (#5#)
64 (declare (ignore #8#))
65 (unless #6# (return))
66 (unintern #7# #4#)))))
67
68;; Add `:runlisp-script' to `*features*' so that scripts can tell whether
69;; they're supposed to sit quietly and be debugged in a Lisp session or run
70;; as a script.
71set-script-feature =
72 (pushnew :runlisp-script *features*)
73
74;; Load the system's ASDF.
75require-asdf =
76 (require "asdf")
77
78;; Prevent ASDF from upgrading itself. Otherwise it will do this
79;; automatically if a script invokes `asdf:load-system', but that will have a
80;; bad effect on startup time, and risks spamming the output streams with
81;; drivel.
82inhibit-asdf-upgrade =
83 (funcall (intern "REGISTER-IMMUTABLE-SYSTEM"
84 (find-package "ASDF"))
85 "asdf")
86
87;; Upgrade ASDF from the source registry.
88upgrade-asdf =
89 (funcall (intern "UPGRADE-ASDF" (find-package "ASDF")))
90
91;; Common actions when resuming a custom image.
92image-restore =
93 (uiop:call-image-restore-hook)
94
95;; Common prelude for script startup in vanilla images. Most of this is
96;; already done in custom images.
97run-script-prelude =
98 (progn
99 (setf *load-verbose* nil *compile-verbose* nil)
100 ${require-asdf}
101 ${inhibit-asdf-upgrade}
102 ${ignore-shebang}
103 ${set-script-feature})
104
105;; Common prelude for dumping images.
106dump-image-prelude =
107 (progn
108 ${require-asdf}
109 ${upgrade-asdf}
110 ${inhibit-asdf-upgrade}
111 ${ignore-shebang}
112 ${set-script-feature})
113
114;; An expression to determine the version information for the running Lisp.
115lisp-version =
116 (list (list* \'lisp
117 (lisp-implementation-type)
118 (multiple-value-list (lisp-implementation-version)))
119 (cons \'asdf
120 (asdf:component-version (asdf:find-system "asdf"))))
121
122;; Full pathname to custom image.
123image-path = ${@image-dir}/${image-file}
124
125;;;--------------------------------------------------------------------------
126[sbcl]
127
128command = ${@ENV:SBCL?sbcl}
129image-file = ${@name}+asdf.core
130
131run-script =
132 ${command} --noinform
133 $?@image{--core "${image-path}" --eval "${image-restore}" |
134 --eval "${run-script-prelude}"}
135 --script "${@script}"
136
137dump-image =
138 ${command} --noinform --no-userinit --no-sysinit --disable-debugger
139 --eval "${dump-image-prelude}"
140 --eval "(sb-ext:save-lisp-and-die \"${@image-new|q}\")"
141
142;;;--------------------------------------------------------------------------
143[ccl]
144
145command = ${@ENV:CCL?ccl}
146image-file = ${@name}+asdf.image
147
148run-script =
149 ${command} -b -n -Q
150 $?@image{-I "${image-path}" -e "${image-restore}" |
151 -e "${run-script-prelude}"}
152 -l "${@script}" -e "(ccl:quit)" --
153
154;; A snaglet occurs here. CCL wants to use the image name as a clue to where
155;; the rest of its installation is; but in fact the image is nowhere near its
156;; installation. So we must hack...
157dump-image =
158 ${command} -b -n -Q
159 -e "${dump-image-prelude}"
160 -e "(ccl::in-development-mode
161 (let ((#1=#:real-ccl-dir (ccl::ccl-directory)))
162 (defun ccl::ccl-directory ()
163 (let* ((#2=#:dirpath
164 (ccl:getenv \"CCL_DEFAULT_DIRECTORY\")))
165 (if (and #2# (plusp (length (namestring #2#))))
166 (ccl::native-to-directory-pathname #2#)
167 #1#))))
168 (compile 'ccl::ccl-directory))"
169 -e "(ccl:save-application \"${@image-new|q}\"
170 :init-file nil
171 :error-handler :quit)"
172
173;;;--------------------------------------------------------------------------
174[clisp]
175
176;; CLisp causes much sadness. Superficially, it's the most sensible of all
177;; of the systems supported here: you just run `clisp SCRIPT -- ARGS ...' and
178;; it works.
179;;
180;; The problems come when you want to do some preparatory work (e.g., load
181;; `asdf') and then run the script. There's a `-x' option to evaluate some
182;; Lisp code, but it has three major deficiencies.
183;;
184;; * It insists on printing the values of the forms it evaluates. It
185;; prints a blank line even if the form goes out of its way to produce no
186;; values at all. So the whole thing has to be a single top-level form
187;; which quits the Lisp rather than returning.
188;;
189;; * For some idiotic reason, you can have /either/ `-x' forms /or/ a
190;; script, but not both. So we have to include the `load' here
191;; explicitly. I suppose that was inevitable because we have to inhibit
192;; printing of the result forms, but it's still a separate source of
193;; annoyance.
194;;
195;; * The icing on the cake: the `-x' forms are collectively concatenated --
196;; without spaces! -- and used to build a string stream, which is then
197;; assigned over the top of `*standard-input*', making the original stdin
198;; somewhat fiddly to track down.
199;;
200;; There's a `-i' option which will load a file without any of this
201;; stupidity, but nothing analogous for immediate expressions.
202
203clisp-common-startup =
204 (setf *standard-input* (ext:make-stream :input))
205 (load "${@script|q}" :verbose nil :print nil)
206 (ext:quit)
207
208command = ${@ENV:CLISP?clisp}
209image-file = ${@name}+asdf.mem
210
211run-script =
212 ${command}
213 $?@image{-M "${image-path}" -q
214 -x "(progn
215 ${image-restore}
216 ${clisp-common-startup})" |
217 -norc -q
218 -x "(progn
219 ${run-script-prelude}
220 ${clisp-common-startup})"}
221 --
222
223dump-image =
224 ${command} -norc -q -q
225 -x "${dump-image-prelude}"
226 -x "(ext:saveinitmem \"${@image-new|q}\" :norc t :script t)"
227
228;;;--------------------------------------------------------------------------
229[ecl]
230
231command = ${@ENV:ECL?ecl}
232image-file = ${@name}+asdf
233
234run-script =
235 $?@image{"${image-path}" -s "${@script}" |
236 ${@ENV:ECL?ecl} "${@ecl-opt}norc"
237 "${@ecl-opt}eval" "(progn
238 ${run-script-prelude}
239 ${clear-cl-user})"
240 "${@ecl-opt}shell" "${@script}"}
241 --
242
243dump-image =
244 "${@data-dir}/dump-ecl"
245 "${@image-new}" "${command}" "${@ecl-opt}" "${@tmp-dir}"
246
247;;;--------------------------------------------------------------------------
248[cmucl]
249
250command = ${@ENV:CMUCL?cmucl}
251image-file = ${@name}+asdf.core
252
253run-script =
254 ${command}
255 $?@image{-core "${image-path}" -eval "${image-restore}" |
256 -batch -noinit -nositeinit -quiet
257 -eval "(progn
258 (setf ext:*require-verbose* nil)
259 ${run-script-prelude})"}
260 -load "${@script}" -eval "(ext:quit)" --
261
262dump-image =
263 ${command} -batch -noinit -nositeinit -quiet
264 -eval "${dump-image-prelude}"
265 -eval "(ext:save-lisp \"${@image-new|q}\"
266 :batch-mode t :print-herald nil
267 :site-init nil :load-init-file nil)"
268
269;;;--------------------------------------------------------------------------
270[abcl]
271
272;; CLisp made a worthy effort, but ABCL still manages to take the prize.
273;;
274;; * ABCL manages to avoid touching the `stderr' stream at all, ever. Its
275;; startup machinery finds `stdout' (as `java.lang.System.out'), wraps it
276;; up in a Lisp stream, and uses the result as `*standard-output*' and
277;; `*error-output*' (and a goodly number of other things too). So we
278;; must manufacture a working `stderr' the hard way.
279;;
280;; * There doesn't appear to be any easy way to prevent toplevel errors
281;; from invoking the interactive debugger. For extra fun, the debugger
282;; reads from `stdin' by default, so an input file which somehow manages
283;; to break the script can then take over its brain by providing Lisp
284;; forms for the debugger to evaluate.
285;;
286;; * And, just to really top everything off, ABCL's `adjoin.lisp' is
287;; missing an `(in-package ...)' form at the top, so it leaks symbols
288;; into the `COMMON-LISP-USER' package.
289
290command = ${@ENV:ABCL?abcl}
291
292abcl-startup =
293 (let ((#9=#:script "${@script|q}"))
294 ${run-script-prelude}
295 ${clear-cl-user}
296 (setf *error-output*
297 (java:jnew "org.armedbear.lisp.Stream"
298 \'sys::system-stream
299 (java:jfield "java.lang.System" "err")
300 \'character
301 java:+true+))
302 (handler-case (load #9# :verbose nil :print nil)
303 (error (error)
304 (format *error-output* "~A (unhandled error): ~A~%" #9# error)
305 (ext:quit :status 255))))
306
307run-script =
308 ${command} --batch --noinform --noinit --nosystem
309 --eval "${abcl-startup}"
310 --
311
312;;;----- That's all, folks --------------------------------------------------