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