Replace Python program auto-generated for documentation categories
[maxima/cygwin.git] / src / init-cl.lisp
blob6e955cd7e5eea2a09a41f1d0f46bc47ea0115bf8
1 ;;********************************************************
2 ;; file: init-cl.lisp
3 ;; description: Initialize Maxima
4 ;; date: Wed Jan 13 1999 - 20:27
5 ;; author: Liam Healy <Liam.Healy@nrl.navy.mil>
6 ;;********************************************************
8 ;;; An ANSI-CL portable initializer to replace init_max1.lisp
10 ;; CL-USER:*MAXIMA-BUILD-TIME* is defined in maxima.asd and maxima.system,
11 ;; but I guess ECL doesn't see that, so define it here.
12 #+ecl (progn
13 (in-package :cl-user)
14 (defvar *maxima-build-time* '#.(multiple-value-list (get-decoded-time)))
15 (export '*maxima-build-time*))
17 (in-package :maxima)
19 ;;; Locations of various types of files. These variables are discussed
20 ;;; in more detail in the file doc/implementation/dir_vars.txt. Since
21 ;;; these are already in the maxima package, the maxima- prefix is
22 ;;; redundant. It is kept for consistency with the same variables in
23 ;;; shell scripts, batch scripts and environment variables.
24 ;;; jfa 02/07/04
26 (defvar *maxima-prefix*)
27 (defvar *maxima-topdir*) ;; top-level installation or build directory
28 (defvar *maxima-imagesdir*)
29 (defvar *maxima-sharedir*)
30 (defvar *maxima-srcdir*)
31 (defvar *maxima-docdir*)
32 (defvar *maxima-infodir*)
33 (defvar *maxima-htmldir*)
34 (defvar *maxima-layout-autotools*)
35 (defvar *maxima-userdir*)
36 (defvar *maxima-initmac* "maxima-init.mac")
37 (defvar *maxima-initlisp* "maxima-init.lisp")
38 (defvar *maxima-tempdir*)
39 (defvar *maxima-lang-subdir* nil)
40 (defvar *maxima-demodir*)
41 (defvar *maxima-objdir*) ;; Where to store object (fasl) files.
42 (defvar $maxima_frontend nil "The frontend maxima is used with.")
43 (defvar $maxima_frontend_version nil "The version of the maxima frontend.")
45 (eval-when (:load-toplevel :compile-toplevel :execute)
46 (defmacro def-lisp-shadow (root-name)
47 "Create a maxima variable $root_name that is an alias for the lisp name *root-name*.
48 When one changes, the other does too."
49 (let ((maxima-name (intern (concatenate 'string "$"
50 (substitute #\_ #\- (string root-name)))))
51 (lisp-name (intern (concatenate 'string "*" (string root-name) "*"))))
52 `(progn
53 (defmvar ,maxima-name)
54 (putprop ',maxima-name 'shadow-string-assignment 'assign)
55 (putprop ',maxima-name ',lisp-name 'lisp-shadow)))))
57 (def-lisp-shadow maxima-tempdir)
58 (def-lisp-shadow maxima-userdir)
59 (def-lisp-shadow maxima-objdir)
61 (defun shadow-string-assignment (var value)
62 (cond
63 ((stringp value)
64 (setf (symbol-value (get var 'lisp-shadow)) value)
65 value)
67 (merror (intl:gettext "assignment: must assign a string to ~:M; found: ~M") var value))))
69 (defun print-directories ()
70 (format t "maxima-prefix=~a~%" *maxima-prefix*)
71 (format t "maxima-topdir=~a~%" *maxima-topdir*)
72 (format t "maxima-imagesdir=~a~%" *maxima-imagesdir*)
73 (format t "maxima-sharedir=~a~%" *maxima-sharedir*)
74 (format t "maxima-srcdir=~a~%" *maxima-srcdir*)
75 (format t "maxima-demodir=~a~%" *maxima-demodir*)
76 (format t "maxima-testsdir=~a~%" *maxima-testsdir*)
77 (format t "maxima-docdir=~a~%" *maxima-docdir*)
78 (format t "maxima-infodir=~a~%" *maxima-infodir*)
79 (format t "maxima-htmldir=~a~%" *maxima-htmldir*)
80 (format t "maxima-plotdir=~a~%" *maxima-plotdir*)
81 (format t "maxima-layout-autotools=~a~%" *maxima-layout-autotools*)
82 (format t "maxima-userdir=~a~%" *maxima-userdir*)
83 (format t "maxima-tempdir=~a~%" *maxima-tempdir*)
84 (format t "maxima-lang-subdir=~a~%" *maxima-lang-subdir*)
85 (format t "maxima-objdir=~A~%" *maxima-objdir*))
87 (defvar *maxima-lispname*
88 #+clisp "clisp"
89 #+cmu "cmucl"
90 #+scl "scl"
91 #+sbcl "sbcl"
92 #+gcl "gcl"
93 #+allegro "acl"
94 #+openmcl "openmcl"
95 #+abcl "abcl"
96 #+lispworks "lispworks"
97 #+ecl "ecl"
98 #-(or clisp cmu scl sbcl gcl allegro openmcl abcl lispworks ecl) "unknownlisp")
100 (defvar $file_search_lisp nil
101 "Directories to search for Lisp source code.")
103 (defvar $file_search_maxima nil
104 "Directories to search for Maxima source code.")
106 (defvar $file_search_demo nil
107 "Directories to search for demos.")
109 (defvar $file_search_usage nil)
111 (defvar $file_search_tests nil
112 "Directories to search for maxima test suite")
114 (defun maxima-parse-dirstring (str)
115 (let ((sep "/"))
116 (if (position (character "\\") str)
117 (setq sep "\\"))
118 (setf str (concatenate 'string (string-right-trim sep str) sep))
119 (concatenate 'string
120 (let ((dev (pathname-device str)))
121 (if (consp dev)
122 (setf dev (first dev)))
123 (if (and dev (not (eq dev :unspecific))
124 (not (string= dev "")))
125 (concatenate 'string (string-right-trim ":" dev) ":")
126 ""))
128 (apply #'combine-path (rest (pathname-directory str))))))
130 (defun set-pathnames-with-autoconf (maxima-prefix-env maxima-docprefix-env)
131 (declare (ignore maxima-docprefix-env))
132 (let (libdir libexecdir datadir infodir
133 (package-version (combine-path *autoconf-package* *autoconf-version*))
134 (binary-subdirectory (concatenate 'string "binary-" *maxima-lispname*)))
135 (if maxima-prefix-env
136 (progn
137 (setq libdir (combine-path maxima-prefix-env "lib"))
138 (setq libexecdir (combine-path maxima-prefix-env "libexec"))
139 (setq datadir (combine-path maxima-prefix-env "share"))
140 (setq infodir (combine-path maxima-prefix-env #+(or cygwin windows win32 win64) "share" "info")))
141 (progn
142 (setq libdir (maxima-parse-dirstring *autoconf-libdir*))
143 (setq libexecdir (maxima-parse-dirstring *autoconf-libexecdir*))
144 (setq datadir (maxima-parse-dirstring *autoconf-datadir*))
145 (setq infodir (maxima-parse-dirstring *autoconf-infodir*))))
146 (setq *maxima-topdir* (combine-path datadir package-version))
147 (setq *maxima-imagesdir* (combine-path libdir package-version binary-subdirectory))
148 (setq *maxima-sharedir* (combine-path datadir package-version "share"))
149 (setq *maxima-srcdir* (combine-path datadir package-version "src"))
150 (setq *maxima-demodir* (combine-path datadir package-version "demo"))
151 (setq *maxima-testsdir* (combine-path datadir package-version "tests"))
152 (setq *maxima-docdir* (combine-path datadir package-version "doc"))
153 (setq *maxima-infodir* infodir)
154 (setq *maxima-htmldir* (combine-path datadir package-version "doc" "html"))
155 (setq *maxima-plotdir* (combine-path libexecdir package-version))))
157 (defun set-pathnames-without-autoconf (maxima-prefix-env maxima-docprefix-env)
158 (let* ((maxima-prefix (if maxima-prefix-env
159 maxima-prefix-env
160 (maxima-parse-dirstring *autoconf-prefix*)))
161 (binary-subdirectory (concatenate 'string "binary-" *maxima-lispname*)))
163 (setq *maxima-topdir* maxima-prefix)
164 (setq *maxima-imagesdir* (combine-path maxima-prefix "src" binary-subdirectory))
165 (setq *maxima-sharedir* (combine-path maxima-prefix "share"))
166 (setq *maxima-srcdir* (combine-path maxima-prefix "src"))
167 (setq *maxima-demodir* (combine-path maxima-prefix "demo"))
168 (setq *maxima-testsdir* (combine-path maxima-prefix "tests"))
169 (let ((maxima-doc-prefix (if maxima-docprefix-env
170 maxima-docprefix-env
171 maxima-prefix)))
172 (setq *maxima-docdir* (combine-path maxima-doc-prefix "doc"))
173 (setq *maxima-infodir* (combine-path maxima-doc-prefix "doc" "info"))
174 (setq *maxima-htmldir* (combine-path maxima-doc-prefix "doc" "html")))
175 (setq *maxima-plotdir* (combine-path maxima-prefix "plotting"))))
177 (defun default-userdir ()
178 (let ((home-env (maxima-getenv "HOME"))
179 (base-dir "")
180 (maxima-dir (if (string= *autoconf-windows* "true")
181 "maxima"
182 ".maxima")))
183 (setf base-dir
184 (if (and home-env (string/= home-env ""))
185 ;; use home-env...
186 (if (string= home-env "c:\\")
187 ;; but not if home-env = c:\, which results in slow startups
188 ;; under windows. Ick.
189 "c:\\user\\"
190 home-env)
191 ;; we have to make a guess
192 (if (string= *autoconf-windows* "true")
193 "c:\\user\\"
194 "/tmp")))
195 (combine-path (maxima-parse-dirstring base-dir) maxima-dir)))
197 (defun default-tempdir ()
198 (maxima-parse-dirstring
199 (let ((tmpdir-windows (maxima-getenv "TEMP"))
200 (tmpdir-posix (maxima-getenv "TMPDIR"))
201 (tmpdir-nonstandard1 (maxima-getenv "TMP"))
202 (tmpdir-nonstandard2 (maxima-getenv "TEMPDIR")))
204 (cond
205 ((and tmpdir-windows (string/= tmpdir-windows "")) tmpdir-windows)
206 ((and tmpdir-posix (string/= tmpdir-windows "")) tmpdir-posix)
207 ((and tmpdir-nonstandard1 (string/= tmpdir-nonstandard1 "")) tmpdir-nonstandard1)
208 ((and tmpdir-nonstandard2 (string/= tmpdir-nonstandard2 "")) tmpdir-nonstandard2)
209 ; A fallback for windows if everything else has failed
210 ((string= *autoconf-windows* "true") "C:\\Windows\\temp")
211 ; A fallback for the rest of the operating systems
212 (t "/tmp")))))
214 (defun set-locale-subdir ()
215 (let (language territory codeset)
216 ;; Determine *maxima-lang-subdir*
217 ;; 1. from MAXIMA_LANG_SUBDIR environment variable
218 ;; 2. from INTL::*LOCALE* if (1) fails
219 (unless (setq *maxima-lang-subdir* (maxima-getenv "MAXIMA_LANG_SUBDIR"))
220 (cond ((or (null intl::*locale*) (equal intl::*locale* ""))
221 (setq *maxima-lang-subdir* nil))
222 ((member intl::*locale* '("C" "POSIX" "c" "posix") :test #'equal)
223 (setq *maxima-lang-subdir* nil))
224 (t (when (eql (position #\. intl::*locale*) 5)
225 (setq codeset (string-downcase (subseq intl::*locale* 6))))
226 (when (eql (position #\_ intl::*locale*) 2)
227 (setq territory (string-downcase (subseq intl::*locale* 3 5))))
228 (setq language (string-downcase (subseq intl::*locale* 0 2)))
229 ;; Set *maxima-lang-subdir* only for known languages.
230 ;; Extend procedure below as soon as new translation
231 ;; is available.
232 (cond ((equal language "en") ;; English
233 (setq *maxima-lang-subdir* nil))
234 ;; Latin-1 aka iso-8859-1 languages
235 ((member language '("es" "pt" "fr" "de" "it") :test #'equal)
236 (if (and (string= language "pt") (string= territory "br"))
237 (setq *maxima-lang-subdir* (concatenate 'string language "_BR"))
238 (setq *maxima-lang-subdir* language))
239 (if (member codeset '("utf-8" "utf8") :test #'equal)
240 (setq *maxima-lang-subdir* (concatenate 'string *maxima-lang-subdir* ".utf8"))))
241 ;; Russian. Default codepage cp1251
242 ((string= language "ru")
243 (setq *maxima-lang-subdir* language)
244 (cond ((member codeset '("utf-8" "utf8") :test #'equal)
245 (setq *maxima-lang-subdir* (concatenate 'string *maxima-lang-subdir* ".utf8")))
246 ((member codeset '("koi8-r" "koi8r") :test #'equal)
247 (setq *maxima-lang-subdir* (concatenate 'string *maxima-lang-subdir* ".koi8r")))))
248 (t (setq *maxima-lang-subdir* nil))))))))
250 (flet ((sanitize-string (s)
251 (map 'string (lambda(x) (if (alphanumericp x) x #\_))
252 (subseq s 0 (min 142 (length s))))))
253 (defun lisp-implementation-version1 ()
254 (sanitize-string (lisp-implementation-version)))
255 (defun maxima-version1 ()
256 (sanitize-string *autoconf-version*)))
258 (defun set-pathnames ()
259 (let ((maxima-prefix-env (maxima-getenv "MAXIMA_PREFIX"))
260 (maxima-layout-autotools-env (maxima-getenv "MAXIMA_LAYOUT_AUTOTOOLS"))
261 (maxima-userdir-env (maxima-getenv "MAXIMA_USERDIR"))
262 (maxima-docprefix-env (maxima-getenv "MAXIMA_DOC_PREFIX"))
263 (maxima-tempdir-env (maxima-getenv "MAXIMA_TEMPDIR"))
264 (maxima-objdir-env (maxima-getenv "MAXIMA_OBJDIR")))
265 ;; MAXIMA_DIRECTORY is a deprecated substitute for MAXIMA_PREFIX
266 (unless maxima-prefix-env
267 (setq maxima-prefix-env (maxima-getenv "MAXIMA_DIRECTORY")))
268 (if maxima-prefix-env
269 (setq *maxima-prefix* maxima-prefix-env)
270 (setq *maxima-prefix* (maxima-parse-dirstring *autoconf-prefix*)))
271 (if maxima-layout-autotools-env
272 (setq *maxima-layout-autotools*
273 (string-equal maxima-layout-autotools-env "true"))
274 (setq *maxima-layout-autotools*
275 (string-equal *maxima-default-layout-autotools* "true")))
276 (if *maxima-layout-autotools*
277 (set-pathnames-with-autoconf maxima-prefix-env maxima-docprefix-env)
278 (set-pathnames-without-autoconf maxima-prefix-env maxima-docprefix-env))
279 (if maxima-userdir-env
280 (setq *maxima-userdir* (maxima-parse-dirstring maxima-userdir-env))
281 (setq *maxima-userdir* (default-userdir)))
282 (if maxima-tempdir-env
283 (setq *maxima-tempdir* (maxima-parse-dirstring maxima-tempdir-env))
284 (setq *maxima-tempdir* (default-tempdir)))
285 ;; Default *MAXIMA-OBJDIR* is <userdir>/binary/binary-<foo>lisp,
286 ;; because userdir is almost surely writable, and we don't want to clutter up
287 ;; random directories with Maxima stuff.
288 ;; Append binary-<foo>lisp whether objdir is the default or obtained from environment.
289 (setq *maxima-objdir*
290 (concatenate 'string
291 (if maxima-objdir-env
292 (maxima-parse-dirstring maxima-objdir-env)
293 (concatenate 'string *maxima-userdir* "/binary"))
294 "/" (maxima-version1) "/" *maxima-lispname* "/" (lisp-implementation-version1)))
296 ;; On ECL the testbench fails mysteriously if this directory doesn't exist =>
297 ;; let's create it by hand as a workaround.
298 #+ecl (ensure-directories-exist (concatenate 'string *maxima-objdir* "/"))
300 ; On Windows Vista gcc requires explicit include
301 #+gcl
302 (when (string= *autoconf-windows* "true")
303 (let ((mingw-gccver (maxima-getenv "mingw_gccver")))
304 (when mingw-gccver
305 (setq compiler::*cc*
306 (concatenate 'string compiler::*cc* " -I\"" *maxima-prefix* "\\include\""
307 " -I\"" *maxima-prefix* "\\lib\\gcc-lib\\mingw32\\"
308 mingw-gccver "\\include\" ")))))
310 ; Assign initial values for Maxima shadow variables
311 (setq $maxima_userdir *maxima-userdir*)
312 (setf (gethash '$maxima_userdir *variable-initial-values*) *maxima-userdir*)
313 (setq $maxima_tempdir *maxima-tempdir*)
314 (setf (gethash '$maxima_tempdir *variable-initial-values*) *maxima-tempdir*)
315 (setq $maxima_objdir *maxima-objdir*)
316 (setf (gethash '$maxima_objdir *variable-initial-values*) *maxima-objdir*))
318 (let* ((ext #+gcl "o"
319 #+(or cmu scl) (c::backend-fasl-file-type c::*target-backend*)
320 #+sbcl "fasl"
321 #+clisp "fas"
322 #+allegro "fasl"
323 #+openmcl (pathname-type ccl::*.fasl-pathname*)
324 #+lispworks (pathname-type (compile-file-pathname "foo.lisp"))
325 #+ecl "fas"
326 #+abcl "abcl"
327 #-(or gcl cmu scl sbcl clisp allegro openmcl lispworks ecl abcl)
329 (lisp-patterns (concatenate 'string "$$$.{" ext ",lisp,lsp}"))
330 (maxima-patterns "$$$.{mac,mc,wxm}")
331 (lisp+maxima-patterns (concatenate 'string "$$$.{" ext ",lisp,lsp,mac,mc,wxm}"))
332 (demo-patterns "$$$.{dem,dm1,dm2,dm3,dmt}")
333 (usage-patterns "$$.{usg,texi}")
334 (share-subdirs-list (share-subdirs-list))
335 ;; Smash the list of share subdirs into a string of the form
336 ;; "{affine,algebra,...,vector}" .
337 (share-subdirs (format nil "{~{~A~^,~}}" share-subdirs-list)))
339 (setq $file_search_lisp
340 (list '(mlist)
341 ;; actually, this entry is not correct.
342 ;; there should be a separate directory for compiled
343 ;; lisp code. jfa 04/11/02
344 (combine-path *maxima-userdir* lisp-patterns)
345 (combine-path *maxima-sharedir* lisp-patterns)
346 (combine-path *maxima-sharedir* share-subdirs lisp-patterns)
347 (combine-path *maxima-srcdir* lisp-patterns)
348 (combine-path *maxima-topdir* lisp-patterns)))
349 (setq $file_search_maxima
350 (list '(mlist)
351 (combine-path *maxima-userdir* maxima-patterns)
352 (combine-path *maxima-sharedir* maxima-patterns)
353 (combine-path *maxima-sharedir* share-subdirs maxima-patterns)
354 (combine-path *maxima-topdir* maxima-patterns)))
355 (setq $file_search_demo
356 (list '(mlist)
357 (combine-path *maxima-sharedir* demo-patterns)
358 (combine-path *maxima-sharedir* share-subdirs demo-patterns)
359 (combine-path *maxima-demodir* demo-patterns)))
360 (setq $file_search_usage
361 (list '(mlist)
362 (combine-path *maxima-sharedir* usage-patterns)
363 (combine-path *maxima-sharedir* share-subdirs usage-patterns)
364 (combine-path *maxima-docdir* usage-patterns)))
365 (setq $file_search_tests
366 `((mlist) ,(combine-path *maxima-testsdir* lisp+maxima-patterns)))
368 ;; If *maxima-lang-subdir* is not nil test whether corresponding info directory
369 ;; with some data really exists. If not this probably means that required
370 ;; language pack wasn't installed and we reset *maxima-lang-subdir* to nil.
371 (when (and *maxima-lang-subdir*
372 (not (probe-file (combine-path *maxima-infodir* *maxima-lang-subdir* "maxima-index.lisp"))))
373 (setq *maxima-lang-subdir* nil))))
375 (defun get-dirs (path &aux (ns (namestring path)))
376 (directory (concatenate 'string
378 (if (eql #\/ (char ns (1- (length ns)))) "" "/")
380 #+(or :clisp :sbcl :ecl :openmcl) "/")
381 #+openmcl :directories #+openmcl t))
383 (defun unix-like-basename (path)
384 (let* ((pathstring (namestring path))
385 (len (length pathstring)))
386 (when (equal (subseq pathstring (- len 1) len) "/")
387 (decf len)
388 (setf pathstring (subseq pathstring 0 len)))
389 (subseq pathstring (1+ (or (position #\/ pathstring :from-end t)
390 (position #\\ pathstring :from-end t))) len)))
392 (defun unix-like-dirname (path)
393 (let* ((pathstring (namestring path))
394 (len (length pathstring)))
395 (when (equal (subseq pathstring (- len 1) len) "/")
396 (decf len)
397 (setf pathstring (subseq pathstring 0 len)))
398 (subseq pathstring 0 (or (position #\/ pathstring :from-end t)
399 (position #\\ pathstring :from-end t)))))
401 (defun list-avail-action ()
402 (let* ((maxima-verpkglibdir (if (maxima-getenv "MAXIMA-VERPKGLIBDIR")
403 (maxima-getenv "MAXIMA-VERPKGLIBDIR")
404 (if (maxima-getenv "MAXIMA_PREFIX")
405 (combine-path (maxima-getenv "MAXIMA_PREFIX") "lib"
406 *autoconf-package* *autoconf-version*)
407 (combine-path (maxima-parse-dirstring *autoconf-libdir*)
408 *autoconf-package* *autoconf-version*))))
409 (len (length maxima-verpkglibdir))
410 (lisp-string nil))
411 (format t "Available versions:~%")
412 (unless (equal (subseq maxima-verpkglibdir (- len 1) len) "/")
413 (setf maxima-verpkglibdir (concatenate 'string maxima-verpkglibdir "/")))
414 (dolist (version (get-dirs (unix-like-dirname maxima-verpkglibdir)))
415 (dolist (lisp (get-dirs version))
416 (setf lisp-string (unix-like-basename lisp))
417 (when (search "binary-" lisp-string)
418 (setf lisp-string (subseq lisp-string (length "binary-") (length lisp-string)))
419 (format t "version ~a, lisp ~a~%" (unix-like-basename version) lisp-string))))
420 (bye)))
422 (defun process-maxima-args (input-stream batch-flag)
423 ;; (format t "processing maxima args = ")
424 ;; (mapc #'(lambda (x) (format t "\"~a\"~%" x)) (get-application-args))
425 ;; (terpri)
426 ;; (finish-output)
427 (let ((maxima-options nil))
428 ;; Note: The current option parsing code expects every short
429 ;; option to have an equivalent long option. No check is made for
430 ;; this, so please make sure this holds. Or change the code in
431 ;; process-args in command-line.lisp.
432 (setf maxima-options
433 (list
434 (make-cl-option :names '("-b" "--batch")
435 :argument "<file>"
436 :action #'(lambda (file)
437 (setf input-stream
438 (make-string-input-stream
439 (format nil "batch(\"~a\");"
440 file)))
441 (setf batch-flag :batch))
442 :help-string
443 "Process maxima file <file> in batch mode.")
444 (make-cl-option :names '("--batch-lisp")
445 :argument "<file>"
446 :action #'(lambda (file)
447 (setf input-stream
448 (make-string-input-stream
449 #-sbcl (format nil ":lisp (load \"~a\");" file)
450 #+sbcl (format nil ":lisp (with-compilation-unit nil (load \"~a\"));" file)))
451 (setf batch-flag :batch))
452 :help-string
453 "Process lisp file <file> in batch mode.")
454 (make-cl-option :names '("--batch-string")
455 :argument "<string>"
456 :action #'(lambda (string)
457 (setf input-stream
458 (make-string-input-stream string))
459 (setf batch-flag :batch))
460 :help-string
461 "Process maxima command(s) <string> in batch mode.")
462 (make-cl-option :names '("-d" "--directories")
463 :action #'(lambda () (print-directories) ($quit))
464 :help-string
465 "Display maxima internal directory information.")
466 (make-cl-option :names '("--disable-readline")
467 :action #'(lambda ()
468 #+gcl
469 (if (find :readline *features*)
470 (si::readline-off)))
471 :help-string "Disable readline support.")
472 (make-cl-option :names '("-g" "--enable-lisp-debugger")
473 :action #'(lambda ()
474 (setf *debugger-hook* nil))
475 :help-string
476 "Enable underlying lisp debugger.")
477 (make-cl-option :names '("-h" "--help")
478 :action #'(lambda ()
479 (format t "usage: maxima [options]~%")
480 (list-cl-options maxima-options)
481 (bye))
482 :help-string "Display this usage message.")
483 (make-cl-option :names '("--userdir")
484 :argument "<directory>"
485 :action nil
486 :help-string "Use <directory> for user directory (default is %USERPROFILE%/maxima for Windows, and $HOME/.maxima for other operating systems).")
487 (make-cl-option :names '("--init")
488 :argument "<file>"
489 :action #'(lambda (file)
490 (setf *maxima-initmac* (concatenate 'string file ".mac"))
491 (setf *maxima-initlisp* (concatenate 'string file ".lisp")))
492 :help-string (format nil "Set the name of the Maxima & Lisp initialization files to <file>.mac & <file>.lisp (default is ~a)" (subseq *maxima-initmac* 0 (- (length *maxima-initmac*) 4))))
493 (make-cl-option :names '("--init-mac")
494 :argument "<file>"
495 :action #'(lambda (file)
496 (setf *maxima-initmac* file))
497 :help-string (format nil "Set the name of the Maxima initialization file (default is ~a)" *maxima-initmac*))
498 (make-cl-option :names '("--init-lisp")
499 :argument "<file>"
500 :action #'(lambda (file)
501 (setf *maxima-initlisp* file))
502 :help-string (format nil "Set the name of the Lisp initialization file (default is ~a)" *maxima-initlisp*))
503 (make-cl-option :names '("-l" "--lisp")
504 :argument "<lisp>"
505 :action nil
506 :help-string "Use lisp implementation <lisp>.")
507 (make-cl-option :names '("--list-avail")
508 :action 'list-avail-action
509 :help-string
510 "List the installed version/lisp combinations.")
511 (make-cl-option :names '("-p" "--preload-lisp")
512 :argument "<lisp-file>"
513 :action #'(lambda (file)
514 #-sbcl (load file) #+sbcl (with-compilation-unit nil (load file)))
515 :help-string "Preload <lisp-file>.")
516 (make-cl-option :names '("-q" "--quiet")
517 :action #'(lambda () (declare (special *maxima-quiet*)) (setq *maxima-quiet* t))
518 :help-string "Suppress Maxima start-up message.")
519 (make-cl-option :names '("-r" "--run-string")
520 :argument "<string>"
521 :action #'(lambda (string)
522 (declare (special *maxima-run-string*))
523 (setq *maxima-run-string* t)
524 (setf input-stream
525 (make-string-input-stream string))
526 (setf batch-flag nil))
527 :help-string
528 "Process maxima command(s) <string> in interactive mode.")
529 (make-cl-option :names '("-s" "--server")
530 :argument "<port>"
531 :action #'(lambda (port-string)
532 (start-client (parse-integer
533 port-string))
534 (setf input-stream *standard-input*))
535 :help-string "Connect Maxima to server on <port>.")
536 (make-cl-option :names '("-u" "--use-version")
537 :argument "<version>"
538 :action nil
539 :help-string "Use maxima version <version>.")
540 (make-cl-option :names '("-v" "--verbose")
541 :action nil
542 :help-string
543 "Display lisp invocation in maxima wrapper script.")
544 (make-cl-option :names '("--version")
545 :action #'(lambda ()
546 (format t "Maxima ~a~%"
547 *autoconf-version*)
548 ($quit))
549 :help-string
550 "Display the default installed version.")
551 (make-cl-option :names '("--very-quiet")
552 :action #'(lambda () (declare (special *maxima-quiet* *display-labels-p*))
553 (setq *maxima-quiet* t *display-labels-p* nil))
554 :help-string "Suppress expression labels and Maxima start-up message.")
555 (make-cl-option :names '("-X" "--lisp-options")
556 :argument "<Lisp options>"
557 :action #'(lambda (&rest opts) (declare (special *maxima-quiet*))
558 (unless *maxima-quiet* (format t "Lisp options: ~A" opts)))
559 :help-string "Options to be given to the underlying Lisp")
561 (process-args (get-application-args) maxima-options))
562 (values input-stream batch-flag))
564 ;; A list of temporary files that can be deleted on leaving maxima
565 (defvar *temp-files-list* (make-hash-table :test 'equal))
567 ;; Delete all files *temp-files-list* contains.
568 (defun delete-temp-files ()
569 (maphash #'(lambda(filename param)
570 (declare (ignore param))
571 (let ((file (ignore-errors (probe-file filename))))
572 (if file
573 (if (not (apparently-a-directory-p file))
574 (delete-file file)))))
575 *temp-files-list*))
577 (defun cl-user::run ()
578 "Run Maxima in its own package."
579 (in-package :maxima)
580 (initialize-runtime-globals)
581 (let ((input-stream *standard-input*)
582 (batch-flag nil))
583 (unwind-protect
584 (catch 'to-lisp
585 (setf (values input-stream batch-flag)
586 (process-maxima-args input-stream batch-flag))
587 (loop
588 (with-simple-restart (macsyma-quit "Maxima top-level")
589 (macsyma-top-level input-stream batch-flag))))
590 (delete-temp-files)
593 (defun disable-some-lisp-warnings ()
594 ;; Suppress warnings about redefining functions;
595 ;; it appears that only Clisp and SBCL emit these warnings
596 ;; (ECL, GCL, CMUCL, and Clozure CL apparently do not).
597 ;; Such warnings are generated by the autoload mechanism.
598 ;; I guess it is plausible that we could also avoid the warnings by
599 ;; reworking autoload to not trigger them. I don't have enough
600 ;; motivation to attempt that right now.
601 #+sbcl (setq sb-ext:*muffled-warnings* '(or sb-kernel:redefinition-with-defun sb-kernel:uninteresting-redefinition))
602 #+sbcl (declaim (sb-ext:muffle-conditions sb-ext:compiler-note))
603 #+clisp (setq custom:*suppress-check-redefinition* t)
605 ;; Suppress compiler output messages.
606 ;; These include the "0 errors, 0 warnings" message output from Clisp,
607 ;; and maybe other messages from other Lisps.
608 (setq *compile-verbose* nil))
610 (defun enable-some-lisp-warnings ()
611 ;; SB-KERNEL:UNINTERESTING-REDEFINITION appears to be the default value.
612 #+sbcl (setq sb-ext:*muffled-warnings* 'sb-kernel:uninteresting-redefinition)
613 #+sbcl (declaim (sb-ext:unmuffle-conditions sb-ext:compiler-note))
614 #+clisp (setq custom:*suppress-check-redefinition* nil)
615 (setq *compile-verbose* t))
617 (defun initialize-runtime-globals ()
618 (setf *load-verbose* nil)
620 (disable-some-lisp-warnings)
622 (setf *debugger-hook* #'maxima-lisp-debugger)
623 ;; See discussion on the maxima list
624 ;; http://www.math.utexas.edu/pipermail/maxima/2011/024014.html.
625 ;; Set *print-length* and *print-level* to some reasonable values so
626 ;; that normal Lisp structure is shown, but prevent typical circular
627 ;; structures from hanging Lisp.
629 ;; (We do we set these instead of binding them?)
630 (setf *print-circle* nil)
631 (setf *print-length* 100)
632 (setf *print-level* 15)
634 ;; GCL: print special floats, which are generated whether or not this flag is enabled
635 #+gcl (setf si:*print-nans* t)
636 #+ccl
637 (progn
638 (setf ccl::*invoke-debugger-hook-on-interrupt* t)
639 ;; CCL 1.5 makes *read-default-float-format* a thread-local
640 ;; variable. Hence we need to set it here to get our desired
641 ;; behavior.
642 (setf *read-default-float-format* 'double-float))
644 #+allegro
645 (progn
646 (set-readtable-for-macsyma)
647 (setf *read-default-float-format* 'lisp::double-float))
649 #+sbcl (setf *read-default-float-format* 'double-float)
651 (initialize-real-and-run-time)
652 (intl::setlocale)
653 (set-locale-subdir)
654 (adjust-character-encoding)
655 (set-pathnames)
656 (catch 'return-from-debugger
657 (cl-info::load-primary-index))
658 (when (boundp '*maxima-prefix*)
659 (push (pathname (concatenate 'string *maxima-prefix*
660 (if *maxima-layout-autotools*
661 "/share/locale/"
662 "/locale/")))
663 intl::*locale-directories*)))
665 (defun adjust-character-encoding ()
666 #+sbcl (setf sb-impl::*default-external-format* :utf-8)
667 #+cmu
668 (handler-bind ((error #'(lambda (c)
669 ;; If there's a continue restart, restart
670 ;; to set the filename encoding anyway.
671 (if (find-restart 'cl:continue c)
672 (invoke-restart 'cl:continue)))))
673 ;; Set both the terminal external format and filename encoding to
674 ;; utf-8. The handler-bind is needed in case the filename
675 ;; encoding was already set to something else; we forcibly change
676 ;; it to utf-8. (Is that right?)
677 (stream:set-system-external-format :utf-8 :utf-8))
678 #+clisp
679 (ignore-errors
680 (progn (setf custom:*default-file-encoding*
681 (ext:make-encoding :input-error-action #\?))
682 (setf custom:*terminal-encoding*
683 custom:*default-file-encoding*))))
685 (import 'cl-user::run)
687 (defmfun $to_lisp ()
688 (format t "~&Type (to-maxima) to restart, ($quit) to quit Maxima.~%")
689 (let ((old-debugger-hook *debugger-hook*))
690 (catch 'to-maxima
691 (unwind-protect
692 (maxima-read-eval-print-loop)
693 (setf *debugger-hook* old-debugger-hook)
694 (format t "Returning to Maxima~%")))))
696 (defun to-maxima ()
697 (throw 'to-maxima t))
699 (defun maxima-read-eval-print-loop ()
700 (when *debugger-hook*
701 ; Only set a new debugger hook if *DEBUGGER-HOOK* has not been set to NIL
702 (setf *debugger-hook* #'maxima-lisp-debugger-repl))
703 (let ((eof (gensym)))
704 (loop
705 (catch 'to-maxima-repl
706 (format-prompt t "~%~A> " (package-name *package*))
707 (finish-output)
708 (let ((input (read *standard-input* nil eof)))
709 ; Return to Maxima on EOF
710 (when (eq input eof)
711 (fresh-line)
712 (to-maxima))
713 (format t "~{~&~S~}" (multiple-value-list (eval input))))))))
715 (defun maxima-lisp-debugger-repl (condition me-or-my-encapsulation)
716 (declare (ignore me-or-my-encapsulation))
717 (format t "~&Maxima encountered a Lisp error:~%~% ~A" condition)
718 (format t "~&~%Automatically continuing.~%To reenable the Lisp debugger set *debugger-hook* to nil.~%")
719 (finish-output)
720 (throw 'to-maxima-repl t))
722 (defvar $help "type `describe(topic);' or `example(topic);' or `? topic'")
724 (defmfun $help (&rest dummy)
725 (declare (ignore dummy))
726 $help)
728 (eval-when (:load-toplevel :execute)
729 (let ((context '$global))
730 (declare (special context))
731 (dolist (x '($%pi $%i $%e $%phi %i $%gamma ;numeric constants
732 $inf $minf $und $ind $infinity ;pseudo-constants
733 t nil)) ;logical constants (Maxima names: true, false)
734 (kind x '$constant)
735 (setf (get x 'sysconst) t))))
737 ;;; Now that all of maxima has been loaded, define the various lists
738 ;;; and hashtables of builtin symbols and values.
740 ;;; The assume database structures for numeric constants such as $%pi and $%e
741 ;;; are circular. Attempting to copy a circular structure
742 ;;; into *builtin-symbol-props* would cause a hang. Therefore
743 ;;; the properties are copied into *builtin-symbol-props* before
744 ;;; initializing the assume database.
745 (let ((maxima-package (find-package :maxima)))
746 (do-symbols (s maxima-package)
747 (when (and (eql (symbol-package s) maxima-package)
748 (not (eq s '||))
749 (member (char (symbol-name s) 0) '(#\$ #\%) :test #'char=))
750 (push s *builtin-symbols*)
751 (setf (gethash s *builtin-symbol-props*)
752 (copy-tree (symbol-plist s))))))
754 ;; Also store the property lists for symbols associated with operators;
755 ;; e.g. MPLUS, MTIMES, etc.
756 ;; Here we find them via the MHEADER property, which is used by the parser.
757 ;; I don't know any better way to find these properties.
759 (let ((maxima-package (find-package :maxima)))
760 (do-symbols (s maxima-package)
761 (let ((h (get s 'mheader)))
762 (when h
763 (let ((s1 (first h)))
764 (unless (gethash s1 *builtin-symbol-props*)
765 (push s1 *builtin-symbols*)
766 (setf (gethash s1 *builtin-symbol-props*)
767 (copy-tree (symbol-plist s1)))))))))
769 ;; Initialize assume database for $%pi, $%e, etc
770 (dolist (c *builtin-numeric-constants*)
771 (initialize-numeric-constant c))
773 (dolist (s *builtin-symbols*)
774 (when (boundp s)
775 (push s *builtin-symbols-with-values*)))
777 (dolist (s *builtin-symbols-with-values*)
778 (setf (gethash s *builtin-symbol-values*) (symbol-value s)))
780 (setf *builtin-$props* (copy-list $props))
781 (setf *builtin-$rules* (copy-list $rules))
783 (defun maxima-objdir (&rest subdirs)
784 "Return a pathname string such that subdirs is a subdirectory of maxima_objdir"
785 (apply #'combine-path *maxima-objdir* subdirs))
787 (defun maxima-load-pathname-directory ()
788 "Return the directory part of *load-pathname*."
789 (let ((path #-gcl *load-pathname*
790 ;; Accommodate standard and nonstandard definitions of *LOAD-PATHNAME* in GCL.
791 ;; This can go away someday when nonstandard GCL's (<= 2.6.12) are ancient history.
792 #+gcl (symbol-value (or (find-symbol "*LOAD-PATHNAME*" :sys) (find-symbol "*LOAD-PATHNAME*" :common-lisp)))))
793 (make-pathname :directory (pathname-directory path)
794 :device (pathname-device path))))