chiark / gitweb /
runlisp.c, eval.lisp, etc.: Add new `-p' option to `princ' expressions.
[runlisp] / runlisp-base.conf
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.
48 ignore-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.
59 clear-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.
71 set-script-feature =
72         (pushnew :runlisp-script *features*)
73
74 ;; Load the system's ASDF.
75 require-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.
82 inhibit-asdf-upgrade =
83         (funcall (intern "REGISTER-IMMUTABLE-SYSTEM"
84                          (find-package "ASDF"))
85                  "asdf")
86
87 ;; Upgrade ASDF from the source registry.
88 upgrade-asdf =
89         (funcall (intern "UPGRADE-ASDF" (find-package "ASDF")))
90
91 ;; Common actions when resuming a custom image.
92 image-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.
97 run-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.
106 dump-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.
115 lisp-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.
123 image-path = ${@image-dir}/${image-file}
124
125 ;;;--------------------------------------------------------------------------
126 [sbcl]
127
128 command = ${@ENV:SBCL?sbcl}
129 image-file = ${@name}+asdf.core
130
131 run-script =
132         ${command} --noinform
133                 $?@image{--core "${image-path}" --eval "${image-restore}" |
134                          --eval "${run-script-prelude}"}
135                 --script "${@script}"
136
137 dump-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
145 command = ${@ENV:CCL?ccl}
146 image-file = ${@name}+asdf.image
147
148 run-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...
157 dump-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
203 clisp-common-startup =
204         (setf *standard-input* (ext:make-stream :input))
205         (load "${@script|q}" :verbose nil :print nil)
206         (ext:quit)
207
208 command = ${@ENV:CLISP?clisp}
209 image-file = ${@name}+asdf.mem
210
211 run-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
223 dump-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
231 command = ${@ENV:ECL?ecl}
232 image-file = ${@name}+asdf
233
234 run-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
243 dump-image =
244         "${@data-dir}/dump-ecl"
245                 "${@image-new}" "${command}" "${@ecl-opt}" "${@tmp-dir}"
246
247 ;;;--------------------------------------------------------------------------
248 [cmucl]
249
250 command = ${@ENV:CMUCL?cmucl}
251 image-file = ${@name}+asdf.core
252
253 run-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
262 dump-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
290 command = ${@ENV:ABCL?abcl}
291
292 abcl-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
307 run-script =
308         ${command} --batch --noinform --noinit --nosystem
309                 --eval "${abcl-startup}"
310                 --
311
312 ;;;----- That's all, folks --------------------------------------------------