Commit | Line | Data |
---|---|---|
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. | |
55 | ignore-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. | |
66 | clear-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. | |
78 | set-script-feature = | |
79 | (pushnew :runlisp-script *features*) | |
80 | ||
81 | ;; Load the system's ASDF. | |
82 | require-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. | |
89 | inhibit-asdf-upgrade = | |
90 | (funcall (intern "REGISTER-IMMUTABLE-SYSTEM" | |
91 | (find-package "ASDF")) | |
92 | "asdf") | |
93 | ||
94 | ;; Upgrade ASDF from the source registry. | |
95 | upgrade-asdf = | |
96 | (funcall (intern "UPGRADE-ASDF" (find-package "ASDF"))) | |
97 | ||
98 | ;; Common actions when resuming a custom image. | |
99 | image-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. | |
104 | run-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. | |
113 | dump-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. |
122 | lisp-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 |
130 | image-path = ${@image-dir}/${image-file} |
131 | ||
132 | ;;;-------------------------------------------------------------------------- | |
133 | [sbcl] | |
134 | ||
135 | command = ${@ENV:SBCL?sbcl} | |
136 | image-file = ${@name}+asdf.core | |
137 | ||
138 | run-script = | |
139 | ${command} --noinform | |
140 | $?@image{--core "${image-path}" --eval "${image-restore}" | | |
141 | --eval "${run-script-prelude}"} | |
142 | --script "${@script}" | |
143 | ||
144 | dump-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 | ||
152 | command = ${@ENV:CCL?ccl} | |
153 | image-file = ${@name}+asdf.image | |
154 | ||
155 | run-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... | |
164 | dump-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 | ||
210 | clisp-common-startup = | |
211 | (setf *standard-input* (ext:make-stream :input)) | |
212 | (load "${@script|q}" :verbose nil :print nil) | |
213 | (ext:quit) | |
214 | ||
215 | command = ${@ENV:CLISP?clisp} | |
216 | image-file = ${@name}+asdf.mem | |
217 | ||
218 | run-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 | ||
230 | dump-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 | ||
238 | command = ${@ENV:ECL?ecl} | |
239 | image-file = ${@name}+asdf | |
240 | ||
241 | run-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 | ||
250 | dump-image = | |
251 | "${@data-dir}/dump-ecl" | |
252 | "${@image-new}" "${command}" "${@ecl-opt}" "${@tmp-dir}" | |
253 | ||
254 | ;;;-------------------------------------------------------------------------- | |
255 | [cmucl] | |
256 | ||
257 | command = ${@ENV:CMUCL?cmucl} | |
258 | image-file = ${@name}+asdf.core | |
259 | ||
260 | run-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 | ||
270 | dump-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 | ||
298 | command = ${@ENV:ABCL?abcl} | |
299 | ||
300 | abcl-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 | ||
315 | run-script = | |
316 | ${command} --batch --noinform --noinit --nosystem | |
317 | --eval "${abcl-startup}" | |
318 | -- | |
319 | ||
320 | ;;;----- That's all, folks -------------------------------------------------- |