1 ;;********************************************************
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.
14 (defvar *maxima-build-time
* '#.
(multiple-value-list (get-decoded-time)))
15 (export '*maxima-build-time
*))
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.
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
) "*"))))
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
)
64 (setf (symbol-value (get var
'lisp-shadow
)) 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
*
96 #+lispworks
"lispworks"
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)
116 (if (position (character "\\") str
)
118 (setf str
(concatenate 'string
(string-right-trim sep str
) sep
))
120 (let ((dev (pathname-device str
)))
122 (setf dev
(first dev
)))
123 (if (and dev
(not (eq dev
:unspecific
))
124 (not (string= dev
"")))
125 (concatenate 'string
(string-right-trim ":" dev
) ":")
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
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")))
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
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
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"))
180 (maxima-dir (if (string= *autoconf-windows
* "true")
184 (if (and home-env
(string/= home-env
""))
186 (if (string= home-env
"c:\\")
187 ;; but not if home-env = c:\, which results in slow startups
188 ;; under windows. Ick.
191 ;; we have to make a guess
192 (if (string= *autoconf-windows
* "true")
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")))
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
214 (defun set-locale-subdir ()
215 (let (language territory
#+nil 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
))
225 ;; Code to parse code set in locale string, in case we figure out
226 ;; something to do with it; it isn't needed for language
227 ;; subdirectory any more, since all language files are UTF-8.
228 ;; We might make use of code set in ADJUST-CHARACTER-ENCODING.
229 #+nil
(when (eql (position #\. intl
::*locale
*) 5)
230 (setq codeset
(string-downcase (subseq intl
::*locale
* 6))))
231 (when (eql (position #\_ intl
::*locale
*) 2)
232 (setq territory
(string-downcase (subseq intl
::*locale
* 3 5))))
233 (setq language
(string-downcase (subseq intl
::*locale
* 0 2)))
234 ;; Set *maxima-lang-subdir* only for known languages.
235 ;; Extend procedure below as soon as new translation
237 (cond ((equal language
"en") ;; English
238 (setq *maxima-lang-subdir
* nil
))
239 ;; Latin-1 aka iso-8859-1 languages
240 ((member language
'("es" "pt" "de") :test
#'equal
)
241 (if (and (string= language
"pt") (string= territory
"br"))
242 (setq *maxima-lang-subdir
* (concatenate 'string language
"_BR"))
243 (setq *maxima-lang-subdir
* language
)))
245 ((string= language
"ja")
246 (setq *maxima-lang-subdir
* language
))
248 ((string= language
"ru")
249 (setq *maxima-lang-subdir
* language
))
250 (t (setq *maxima-lang-subdir
* nil
))))))))
252 (flet ((sanitize-string (s)
253 (map 'string
(lambda(x) (if (alphanumericp x
) x
#\_
))
254 (subseq s
0 (min 142 (length s
))))))
255 (defun lisp-implementation-version1 ()
256 (sanitize-string (lisp-implementation-version)))
257 (defun maxima-version1 ()
258 (sanitize-string *autoconf-version
*)))
260 (defun set-pathnames ()
261 (let ((maxima-prefix-env (maxima-getenv "MAXIMA_PREFIX"))
262 (maxima-layout-autotools-env (maxima-getenv "MAXIMA_LAYOUT_AUTOTOOLS"))
263 (maxima-userdir-env (maxima-getenv "MAXIMA_USERDIR"))
264 (maxima-docprefix-env (maxima-getenv "MAXIMA_DOC_PREFIX"))
265 (maxima-tempdir-env (maxima-getenv "MAXIMA_TEMPDIR"))
266 (maxima-objdir-env (maxima-getenv "MAXIMA_OBJDIR")))
267 ;; MAXIMA_DIRECTORY is a deprecated substitute for MAXIMA_PREFIX
268 (unless maxima-prefix-env
269 (setq maxima-prefix-env
(maxima-getenv "MAXIMA_DIRECTORY")))
270 (if maxima-prefix-env
271 (setq *maxima-prefix
* maxima-prefix-env
)
272 (setq *maxima-prefix
* (maxima-parse-dirstring *autoconf-prefix
*)))
273 (if maxima-layout-autotools-env
274 (setq *maxima-layout-autotools
*
275 (string-equal maxima-layout-autotools-env
"true"))
276 (setq *maxima-layout-autotools
*
277 (string-equal *maxima-default-layout-autotools
* "true")))
278 (if *maxima-layout-autotools
*
279 (set-pathnames-with-autoconf maxima-prefix-env maxima-docprefix-env
)
280 (set-pathnames-without-autoconf maxima-prefix-env maxima-docprefix-env
))
281 (if maxima-userdir-env
282 (setq *maxima-userdir
* (maxima-parse-dirstring maxima-userdir-env
))
283 (setq *maxima-userdir
* (default-userdir)))
284 (if maxima-tempdir-env
285 (setq *maxima-tempdir
* (maxima-parse-dirstring maxima-tempdir-env
))
286 (setq *maxima-tempdir
* (default-tempdir)))
287 ;; Default *MAXIMA-OBJDIR* is <userdir>/binary/binary-<foo>lisp,
288 ;; because userdir is almost surely writable, and we don't want to clutter up
289 ;; random directories with Maxima stuff.
290 ;; Append binary-<foo>lisp whether objdir is the default or obtained from environment.
291 (setq *maxima-objdir
*
293 (if maxima-objdir-env
294 (maxima-parse-dirstring maxima-objdir-env
)
295 (concatenate 'string
*maxima-userdir
* "/binary"))
296 "/" (maxima-version1) "/" *maxima-lispname
* "/" (lisp-implementation-version1)))
298 ;; On ECL the testbench fails mysteriously if this directory doesn't exist =>
299 ;; let's create it by hand as a workaround.
300 #+ecl
(ensure-directories-exist (concatenate 'string
*maxima-objdir
* "/"))
302 ; On Windows Vista gcc requires explicit include
304 (when (string= *autoconf-windows
* "true")
305 (let ((mingw-gccver (maxima-getenv "mingw_gccver")))
308 (concatenate 'string compiler
::*cc
* " -I\"" *maxima-prefix
* "\\include\""
309 " -I\"" *maxima-prefix
* "\\lib\\gcc-lib\\mingw32\\"
310 mingw-gccver
"\\include\" ")))))
312 ; Assign initial values for Maxima shadow variables
313 (setq $maxima_userdir
*maxima-userdir
*)
314 (setf (gethash '$maxima_userdir
*variable-initial-values
*) *maxima-userdir
*)
315 (setq $maxima_tempdir
*maxima-tempdir
*)
316 (setf (gethash '$maxima_tempdir
*variable-initial-values
*) *maxima-tempdir
*)
317 (setq $maxima_objdir
*maxima-objdir
*)
318 (setf (gethash '$maxima_objdir
*variable-initial-values
*) *maxima-objdir
*))
320 (let* ((ext #+gcl
"o"
321 #+(or cmu scl
) (c::backend-fasl-file-type c
::*target-backend
*)
325 #+openmcl
(pathname-type ccl
::*.fasl-pathname
*)
326 #+lispworks
(pathname-type (compile-file-pathname "foo.lisp"))
329 #-
(or gcl cmu scl sbcl clisp allegro openmcl lispworks ecl abcl
)
331 (lisp-patterns (concatenate 'string
"$$$.{" ext
",lisp,lsp}"))
332 (maxima-patterns "$$$.{mac,mc,wxm}")
333 (lisp+maxima-patterns
(concatenate 'string
"$$$.{" ext
",lisp,lsp,mac,mc,wxm}"))
334 (demo-patterns "$$$.{dem,dm1,dm2,dm3,dmt}")
335 (usage-patterns "$$.{usg,texi}")
336 (share-subdirs-list (share-subdirs-list))
337 ;; Smash the list of share subdirs into a string of the form
338 ;; "{affine,algebra,...,vector}" .
339 (share-subdirs (format nil
"{~{~A~^,~}}" share-subdirs-list
)))
341 (setq $file_search_lisp
343 ;; actually, this entry is not correct.
344 ;; there should be a separate directory for compiled
345 ;; lisp code. jfa 04/11/02
346 (combine-path *maxima-userdir
* lisp-patterns
)
347 (combine-path *maxima-sharedir
* lisp-patterns
)
348 (combine-path *maxima-sharedir
* share-subdirs lisp-patterns
)
349 (combine-path *maxima-srcdir
* lisp-patterns
)
350 (combine-path *maxima-topdir
* lisp-patterns
)))
351 (setq $file_search_maxima
353 (combine-path *maxima-userdir
* maxima-patterns
)
354 (combine-path *maxima-sharedir
* maxima-patterns
)
355 (combine-path *maxima-sharedir
* share-subdirs maxima-patterns
)
356 (combine-path *maxima-topdir
* maxima-patterns
)))
357 (setq $file_search_demo
359 (combine-path *maxima-sharedir
* demo-patterns
)
360 (combine-path *maxima-sharedir
* share-subdirs demo-patterns
)
361 (combine-path *maxima-demodir
* demo-patterns
)))
362 (setq $file_search_usage
364 (combine-path *maxima-sharedir
* usage-patterns
)
365 (combine-path *maxima-sharedir
* share-subdirs usage-patterns
)
366 (combine-path *maxima-docdir
* usage-patterns
)))
367 (setq $file_search_tests
368 `((mlist) ,(combine-path *maxima-testsdir
* lisp
+maxima-patterns
)))
370 ;; If *maxima-lang-subdir* is not nil test whether corresponding info directory
371 ;; with some data really exists. If not this probably means that required
372 ;; language pack wasn't installed and we reset *maxima-lang-subdir* to nil.
373 (when (and *maxima-lang-subdir
*
374 (not (probe-file (combine-path *maxima-infodir
* *maxima-lang-subdir
* "maxima-index.lisp"))))
375 (setq *maxima-lang-subdir
* nil
))))
377 (defun get-dirs (path &aux
(ns (namestring path
)))
378 (directory (concatenate 'string
380 (if (eql #\
/ (char ns
(1- (length ns
)))) "" "/")
382 #+(or :clisp
:sbcl
:ecl
:openmcl
) "/")
383 #+openmcl
:directories
#+openmcl t
))
385 (defun unix-like-basename (path)
386 (let* ((pathstring (namestring path
))
387 (len (length pathstring
)))
388 (when (equal (subseq pathstring
(- len
1) len
) "/")
390 (setf pathstring
(subseq pathstring
0 len
)))
391 (subseq pathstring
(1+ (or (position #\
/ pathstring
:from-end t
)
392 (position #\\ pathstring
:from-end t
))) len
)))
394 (defun unix-like-dirname (path)
395 (let* ((pathstring (namestring path
))
396 (len (length pathstring
)))
397 (when (equal (subseq pathstring
(- len
1) len
) "/")
399 (setf pathstring
(subseq pathstring
0 len
)))
400 (subseq pathstring
0 (or (position #\
/ pathstring
:from-end t
)
401 (position #\\ pathstring
:from-end t
)))))
403 (defun list-avail-action ()
404 (let* ((maxima-verpkglibdir (if (maxima-getenv "MAXIMA-VERPKGLIBDIR")
405 (maxima-getenv "MAXIMA-VERPKGLIBDIR")
406 (if (maxima-getenv "MAXIMA_PREFIX")
407 (combine-path (maxima-getenv "MAXIMA_PREFIX") "lib"
408 *autoconf-package
* *autoconf-version
*)
409 (combine-path (maxima-parse-dirstring *autoconf-libdir
*)
410 *autoconf-package
* *autoconf-version
*))))
411 (len (length maxima-verpkglibdir
))
413 (format t
"Available versions:~%")
414 (unless (equal (subseq maxima-verpkglibdir
(- len
1) len
) "/")
415 (setf maxima-verpkglibdir
(concatenate 'string maxima-verpkglibdir
"/")))
416 (dolist (version (get-dirs (unix-like-dirname maxima-verpkglibdir
)))
417 (dolist (lisp (get-dirs version
))
418 (setf lisp-string
(unix-like-basename lisp
))
419 (when (search "binary-" lisp-string
)
420 (setf lisp-string
(subseq lisp-string
(length "binary-") (length lisp-string
)))
421 (format t
"version ~a, lisp ~a~%" (unix-like-basename version
) lisp-string
))))
424 (defun process-maxima-args (input-stream batch-flag
)
425 ;; (format t "processing maxima args = ")
426 ;; (mapc #'(lambda (x) (format t "\"~a\"~%" x)) (get-application-args))
429 (let ((maxima-options nil
))
430 ;; Note: The current option parsing code expects every short
431 ;; option to have an equivalent long option. No check is made for
432 ;; this, so please make sure this holds. Or change the code in
433 ;; process-args in command-line.lisp.
436 (make-cl-option :names
'("-b" "--batch")
438 :action
#'(lambda (file)
440 (make-string-input-stream
441 (format nil
"batch(\"~a\");"
443 (setf batch-flag
:batch
))
445 "Process maxima file <file> in batch mode.")
446 (make-cl-option :names
'("--batch-lisp")
448 :action
#'(lambda (file)
450 (make-string-input-stream
451 #-sbcl
(format nil
":lisp (load \"~a\");" file
)
452 #+sbcl
(format nil
":lisp (with-compilation-unit nil (load \"~a\"));" file
)))
453 (setf batch-flag
:batch
))
455 "Process lisp file <file> in batch mode.")
456 (make-cl-option :names
'("--batch-string")
458 :action
#'(lambda (string)
460 (make-string-input-stream string
))
461 (setf batch-flag
:batch
))
463 "Process maxima command(s) <string> in batch mode.")
464 (make-cl-option :names
'("-d" "--directories")
465 :action
#'(lambda () (print-directories) ($quit
))
467 "Display maxima internal directory information.")
468 (make-cl-option :names
'("--disable-readline")
471 (if (find :readline
*features
*)
473 :help-string
"Disable readline support.")
474 (make-cl-option :names
'("-g" "--enable-lisp-debugger")
476 (setf *debugger-hook
* nil
))
478 "Enable underlying lisp debugger.")
479 (make-cl-option :names
'("-h" "--help")
481 (format t
"usage: maxima [options]~%")
482 (list-cl-options maxima-options
)
484 :help-string
"Display this usage message.")
485 (make-cl-option :names
'("--userdir")
486 :argument
"<directory>"
488 :help-string
"Use <directory> for user directory (default is %USERPROFILE%/maxima for Windows, and $HOME/.maxima for other operating systems).")
489 (make-cl-option :names
'("--init")
491 :action
#'(lambda (file)
492 (setf *maxima-initmac
* (concatenate 'string file
".mac"))
493 (setf *maxima-initlisp
* (concatenate 'string file
".lisp")))
494 :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))))
495 (make-cl-option :names
'("--init-mac")
497 :action
#'(lambda (file)
498 (setf *maxima-initmac
* file
))
499 :help-string
(format nil
"Set the name of the Maxima initialization file (default is ~a)" *maxima-initmac
*))
500 (make-cl-option :names
'("--init-lisp")
502 :action
#'(lambda (file)
503 (setf *maxima-initlisp
* file
))
504 :help-string
(format nil
"Set the name of the Lisp initialization file (default is ~a)" *maxima-initlisp
*))
505 (make-cl-option :names
'("-l" "--lisp")
508 :help-string
"Use lisp implementation <lisp>.")
509 (make-cl-option :names
'("--list-avail")
510 :action
'list-avail-action
512 "List the installed version/lisp combinations.")
513 (make-cl-option :names
'("-p" "--preload-lisp")
514 :argument
"<lisp-file>"
515 :action
#'(lambda (file)
516 #-sbcl
(load file
) #+sbcl
(with-compilation-unit nil
(load file
)))
517 :help-string
"Preload <lisp-file>.")
518 (make-cl-option :names
'("-q" "--quiet")
519 :action
#'(lambda () (declare (special *maxima-quiet
*)) (setq *maxima-quiet
* t
))
520 :help-string
"Suppress Maxima start-up message.")
521 (make-cl-option :names
'("-r" "--run-string")
523 :action
#'(lambda (string)
524 (declare (special *maxima-run-string
*))
525 (setq *maxima-run-string
* t
)
527 (make-string-input-stream string
))
528 (setf batch-flag nil
))
530 "Process maxima command(s) <string> in interactive mode.")
531 (make-cl-option :names
'("-s" "--server")
533 :action
#'(lambda (port-string)
534 (start-client (parse-integer
536 (setf input-stream
*standard-input
*))
537 :help-string
"Connect Maxima to server on <port>.")
538 (make-cl-option :names
'("-u" "--use-version")
539 :argument
"<version>"
541 :help-string
"Use maxima version <version>.")
542 (make-cl-option :names
'("-v" "--verbose")
545 "Display lisp invocation in maxima wrapper script.")
546 (make-cl-option :names
'("--version")
548 (format t
"Maxima ~a~%"
552 "Display the default installed version.")
553 (make-cl-option :names
'("--very-quiet")
554 :action
#'(lambda () (declare (special *maxima-quiet
* *display-labels-p
*))
555 (setq *maxima-quiet
* t
*display-labels-p
* nil
))
556 :help-string
"Suppress expression labels and Maxima start-up message.")
557 (make-cl-option :names
'("-X" "--lisp-options")
558 :argument
"<Lisp options>"
559 :action
#'(lambda (&rest opts
) (declare (special *maxima-quiet
*))
560 (unless *maxima-quiet
* (format t
"Lisp options: ~A" opts
)))
561 :help-string
"Options to be given to the underlying Lisp")
563 (process-args (get-application-args) maxima-options
))
564 (values input-stream batch-flag
))
566 ;; A list of temporary files that can be deleted on leaving maxima
567 (defvar *temp-files-list
* (make-hash-table :test
'equal
))
569 ;; Delete all files *temp-files-list* contains.
570 (defun delete-temp-files ()
571 (maphash #'(lambda(filename param
)
572 (declare (ignore param
))
573 (let ((file (ignore-errors (probe-file filename
))))
575 (if (not (apparently-a-directory-p file
))
576 (delete-file file
)))))
579 (defun cl-user::run
()
580 "Run Maxima in its own package."
582 (initialize-runtime-globals)
583 (let ((input-stream *standard-input
*)
587 (setf (values input-stream batch-flag
)
588 (process-maxima-args input-stream batch-flag
))
590 (with-simple-restart (macsyma-quit "Maxima top-level")
591 (macsyma-top-level input-stream batch-flag
))))
595 (defun disable-some-lisp-warnings ()
596 ;; Suppress warnings about redefining functions;
597 ;; it appears that only Clisp and SBCL emit these warnings
598 ;; (ECL, GCL, CMUCL, and Clozure CL apparently do not).
599 ;; Such warnings are generated by the autoload mechanism.
600 ;; I guess it is plausible that we could also avoid the warnings by
601 ;; reworking autoload to not trigger them. I don't have enough
602 ;; motivation to attempt that right now.
603 #+sbcl
(setq sb-ext
:*muffled-warnings
* '(or sb-kernel
:redefinition-with-defun
sb-kernel:uninteresting-redefinition
))
604 #+sbcl
(declaim (sb-ext:muffle-conditions sb-ext
:compiler-note
))
605 #+clisp
(setq custom
:*suppress-check-redefinition
* t
)
607 ;; Suppress compiler output messages.
608 ;; These include the "0 errors, 0 warnings" message output from Clisp,
609 ;; and maybe other messages from other Lisps.
610 (setq *compile-verbose
* nil
))
612 (defun enable-some-lisp-warnings ()
613 ;; SB-KERNEL:UNINTERESTING-REDEFINITION appears to be the default value.
614 #+sbcl
(setq sb-ext
:*muffled-warnings
* 'sb-kernel
:uninteresting-redefinition
)
615 #+sbcl
(declaim (sb-ext:unmuffle-conditions sb-ext
:compiler-note
))
616 #+clisp
(setq custom
:*suppress-check-redefinition
* nil
)
617 (setq *compile-verbose
* t
))
619 (defun initialize-runtime-globals ()
620 (setf *load-verbose
* nil
)
622 (disable-some-lisp-warnings)
624 (setf *debugger-hook
* #'maxima-lisp-debugger
)
625 ;; See discussion on the maxima list
626 ;; http://www.math.utexas.edu/pipermail/maxima/2011/024014.html.
627 ;; Set *print-length* and *print-level* to some reasonable values so
628 ;; that normal Lisp structure is shown, but prevent typical circular
629 ;; structures from hanging Lisp.
631 ;; (We do we set these instead of binding them?)
632 (setf *print-circle
* nil
)
633 (setf *print-length
* 100)
634 (setf *print-level
* 15)
636 ;; GCL: print special floats, which are generated whether or not this flag is enabled
637 #+gcl
(setf si
:*print-nans
* t
)
640 (setf ccl
::*invoke-debugger-hook-on-interrupt
* t
)
641 ;; CCL 1.5 makes *read-default-float-format* a thread-local
642 ;; variable. Hence we need to set it here to get our desired
644 (setf *read-default-float-format
* 'double-float
))
648 (set-readtable-for-macsyma)
649 (setf *read-default-float-format
* 'lisp
::double-float
))
651 #+sbcl
(setf *read-default-float-format
* 'double-float
)
653 (initialize-real-and-run-time)
656 (adjust-character-encoding)
658 (catch 'return-from-debugger
659 (cl-info::load-primary-index
))
660 (when (boundp '*maxima-prefix
*)
661 (push (pathname (concatenate 'string
*maxima-prefix
*
662 (if *maxima-layout-autotools
*
665 intl
::*locale-directories
*)))
667 (defun adjust-character-encoding ()
668 #+sbcl
(setf sb-impl
::*default-external-format
* :utf-8
)
670 (handler-bind ((error #'(lambda (c)
671 ;; If there's a continue restart, restart
672 ;; to set the filename encoding anyway.
673 (if (find-restart 'cl
:continue c
)
674 (invoke-restart 'cl
:continue
)))))
675 ;; Set both the terminal external format and filename encoding to
676 ;; utf-8. The handler-bind is needed in case the filename
677 ;; encoding was already set to something else; we forcibly change
678 ;; it to utf-8. (Is that right?)
679 (stream:set-system-external-format
:utf-8
:utf-8
))
682 (progn (setf custom
:*default-file-encoding
*
683 (ext:make-encoding
:input-error-action
#\?))
684 (setf custom
:*terminal-encoding
*
685 custom
:*default-file-encoding
*))))
687 (import 'cl-user
::run
)
690 (format t
"~&Type (to-maxima) to restart, ($quit) to quit Maxima.~%")
691 (let ((old-debugger-hook *debugger-hook
*))
694 (maxima-read-eval-print-loop)
695 (setf *debugger-hook
* old-debugger-hook
)
696 (format t
"Returning to Maxima~%")))))
699 (throw 'to-maxima t
))
701 (defun maxima-read-eval-print-loop ()
702 (when *debugger-hook
*
703 ; Only set a new debugger hook if *DEBUGGER-HOOK* has not been set to NIL
704 (setf *debugger-hook
* #'maxima-lisp-debugger-repl
))
705 (let ((eof (gensym)))
707 (catch 'to-maxima-repl
708 (format-prompt t
"~%~A> " (package-name *package
*))
710 (let ((input (read *standard-input
* nil eof
)))
711 ; Return to Maxima on EOF
715 (format t
"~{~&~S~}" (multiple-value-list (eval input
))))))))
717 (defun maxima-lisp-debugger-repl (condition me-or-my-encapsulation
)
718 (declare (ignore me-or-my-encapsulation
))
719 (format t
"~&Maxima encountered a Lisp error:~%~% ~A" condition
)
720 (format t
"~&~%Automatically continuing.~%To reenable the Lisp debugger set *debugger-hook* to nil.~%")
722 (throw 'to-maxima-repl t
))
724 (defvar $help
"type `describe(topic);' or `example(topic);' or `? topic'")
726 (defmfun $help
(&rest dummy
)
727 (declare (ignore dummy
))
730 (eval-when (:load-toplevel
:execute
)
731 (let ((context '$global
))
732 (declare (special context
))
733 (dolist (x '($%pi $%i $%e $%phi %i $%gamma
;numeric constants
734 $inf $minf $und $ind $infinity
;pseudo-constants
735 t nil
)) ;logical constants (Maxima names: true, false)
737 (setf (get x
'sysconst
) t
))))
739 ;;; Now that all of maxima has been loaded, define the various lists
740 ;;; and hashtables of builtin symbols and values.
742 ;;; The assume database structures for numeric constants such as $%pi and $%e
743 ;;; are circular. Attempting to copy a circular structure
744 ;;; into *builtin-symbol-props* would cause a hang. Therefore
745 ;;; the properties are copied into *builtin-symbol-props* before
746 ;;; initializing the assume database.
747 (let ((maxima-package (find-package :maxima
)))
748 (do-symbols (s maxima-package
)
749 (when (and (eql (symbol-package s
) maxima-package
)
751 (member (char (symbol-name s
) 0) '(#\$
#\%
) :test
#'char
=))
752 (push s
*builtin-symbols
*)
753 (setf (gethash s
*builtin-symbol-props
*)
754 (copy-tree (symbol-plist s
))))))
756 ;; Also store the property lists for symbols associated with operators;
757 ;; e.g. MPLUS, MTIMES, etc.
758 ;; Here we find them via the MHEADER property, which is used by the parser.
759 ;; I don't know any better way to find these properties.
761 (let ((maxima-package (find-package :maxima
)))
762 (do-symbols (s maxima-package
)
763 (let ((h (get s
'mheader
)))
765 (let ((s1 (first h
)))
766 (unless (gethash s1
*builtin-symbol-props
*)
767 (push s1
*builtin-symbols
*)
768 (setf (gethash s1
*builtin-symbol-props
*)
769 (copy-tree (symbol-plist s1
)))))))))
771 ;; Initialize assume database for $%pi, $%e, etc
772 (dolist (c *builtin-numeric-constants
*)
773 (initialize-numeric-constant c
))
775 (dolist (s *builtin-symbols
*)
777 (push s
*builtin-symbols-with-values
*)))
779 (dolist (s *builtin-symbols-with-values
*)
780 (setf (gethash s
*builtin-symbol-values
*) (symbol-value s
)))
782 (setf *builtin-$props
* (copy-list $props
))
783 (setf *builtin-$rules
* (copy-list $rules
))
785 (defun maxima-objdir (&rest subdirs
)
786 "Return a pathname string such that subdirs is a subdirectory of maxima_objdir"
787 (apply #'combine-path
*maxima-objdir
* subdirs
))
789 (defun maxima-load-pathname-directory ()
790 "Return the directory part of *load-pathname*."
791 (let ((path #-gcl
*load-pathname
*
792 ;; Accommodate standard and nonstandard definitions of *LOAD-PATHNAME* in GCL.
793 ;; This can go away someday when nonstandard GCL's (<= 2.6.12) are ancient history.
794 #+gcl
(symbol-value (or (find-symbol "*LOAD-PATHNAME*" :sys
) (find-symbol "*LOAD-PATHNAME*" :common-lisp
)))))
795 (make-pathname :directory
(pathname-directory path
)
796 :device
(pathname-device path
))))