1;; Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
2;; All rights reserved.
3;;
4;; Redistribution and use in source and binary forms, with or without
5;; modification, are permitted provided that the following conditions are
6;; met:
7;;
8;;     - Redistributions of source code must retain the above copyright
9;;       notice, this list of conditions and the following disclaimer.
10;;
11;;     - Redistributions in binary form must reproduce the above copyright
12;;       notice, this list of conditions and the following disclaimer in
13;;       the documentation and/or other materials provided with the
14;;       distribution.
15;;
16;;     - Neither the name of The Numerical ALgorithms Group Ltd. nor the
17;;       names of its contributors may be used to endorse or promote products
18;;       derived from this software without specific prior written permission.
19;;
20;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21;; IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22;; TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23;; PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
24;; OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25;; EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26;; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32#|
33This file is a collection of utility functions that are useful
34for system level work.  {\bf build-interpsys} interfaces to the
35src/interp/Makefile.
36
37A fifth group of related functions are some translated boot
38functions we need to define here so they work and are available
39at load time.
40|#
41(in-package "BOOT")
42(export '($spadroot $directory-list reroot
43          make-absolute-filename |$defaultMsgDatabaseName|))
44
45;;; Various lisps use different ``extensions'' on the filename to indicate
46;;; that a file has been compiled. We set this variable correctly depending
47;;; on the system we are using.
48(defvar |$lisp_bin_filetype|
49  #+:GCL "o"
50  #+lucid "bbin"
51  #+symbolics "bin"
52  #+:cmu (c:backend-fasl-file-type c:*target-backend*)
53  #+:sbcl "fasl"
54  #+:clisp "fas"
55  #+:openmcl (subseq (namestring CCL:*.FASL-PATHNAME*) 1)
56  #+:ecl "fas"
57  #+:lispworks (pathname-type (compile-file-pathname "foo.lisp"))
58  #+:poplog "lsp"
59  )
60
61;;; The relative directory list specifies a search path for files
62;;; for the current directory structure.
63(defvar $relative-directory-list
64  '("/share/msgs/"
65    "/share/spadhelp/" ))
66
67;;; The relative directory list specifies how to find the algebra
68;;; directory from the current {\bf FRICAS} shell variable.
69(defvar $relative-library-directory-list '("/algebra/"))
70
71;;; This is the system-wide list of directories to search.
72;;; It is set up in the {\bf reroot} function.
73(defvar $directory-list ())
74
75;;; This is the system-wide search path for library files.
76;;; It is set up in the {\bf reroot} function.
77(defvar $library-directory-list ())
78
79;;; Prefix a filename with the {\bf FRICAS} shell variable.
80(defun make-absolute-filename (name)
81 (concatenate 'string $spadroot name))
82
83#|
84The reroot function is used to reset the important variables used by
85the system. In particular, these variables are sensitive to the
86{\bf FRICAS} shell variable. That variable is renamed internally to
87be {\bf \$spadroot}. The {\bf reroot} function will change the
88system to use a new root directory and will have the same effect
89as changing the {\bf FRICAS} shell variable and rerunning the system
90from scratch.  A correct call looks like:
91\begin{verbatim}
92(in-package "BOOT")
93(reroot "${FRICAS}")
94\end{verbatim}
95where the [[${FRICAS}]] variable points to installed tree.
96|#
97(defun reroot (dir)
98  (setq $spadroot dir)
99  (setq $directory-list
100   (mapcar #'make-absolute-filename $relative-directory-list))
101  (setq $library-directory-list
102   (mapcar #'make-absolute-filename $relative-library-directory-list))
103  (setq |$defaultMsgDatabaseName|
104        (pathname (make-absolute-filename "/share/msgs/s2-us.msgs")))
105  )
106
107;;; Sets up the system to use the {\bf FRICAS} shell variable if we can
108;;; and default to the {\bf \$spadroot} variable (which was the value
109;;; of the {\bf FRICAS} shell variable at build time) if we can't.
110;;; Use the parent directory of FRICASsys binary as fallback.
111(defun initroot (&optional (newroot nil))
112  (reroot (or (|getEnv| "FRICAS") newroot
113              (if (|fricas_probe_file| $spadroot) $spadroot)
114              (let ((bin-parent-dir
115                     (concatenate 'string
116                                  (directory-namestring (car (|getCLArgs|)))
117                                  "/../")))
118                (if (|fricas_probe_file| (concatenate 'string bin-parent-dir
119                                                      "algebra/interp.daase"))
120                    bin-parent-dir))
121              (error "setenv FRICAS or (setq $spadroot)"))))
122
123;;; Gnu Common Lisp (GCL) (at least 2.6.[78]) requires some changes
124;;; to the default memory setup to run FriCAS efficiently.
125;;; This function performs those setup commands.
126(defun init-memory-config (&key
127                           (cons 500)
128                           (fixnum 200)
129                           (symbol 500)
130                           (package 8)
131                           (array 400)
132                           (string 500)
133                           (cfun 100)
134                           (cpages 3000)
135                           (rpages 1000)
136                           (hole 2000) )
137  ;; initialize GCL memory allocation parameters
138  #+:GCL
139  (progn
140    (system:allocate 'cons cons)
141    (system:allocate 'fixnum fixnum)
142    (system:allocate 'symbol symbol)
143    (system:allocate 'package package)
144    (system:allocate 'array array)
145    (system:allocate 'string string)
146    (system:allocate 'cfun cfun)
147    (system:allocate-contiguous-pages cpages)
148    (system:allocate-relocatable-pages rpages)
149    (system:set-hole-size hole))
150  #-:GCL
151  nil)
152
153#|
154;############################################################################
155;# autoload dependencies
156;#
157;# if you are adding a file which is to be autoloaded the following step
158;# information is useful:
159;#  there are 2 cases:
160;#   1) adding files to currently autoloaded parts
161;#      (as of 2/92: browser old parser and old compiler)
162;#   2) adding new files
163;#   case 1:
164;#     a) you have to add the file to the list of files currently there
165;#        (e.g. see BROBJS above)
166;#     b) add an autolaod rule
167;#        (e.g. ${AUTO}/parsing.${O}: ${OUT}/parsing.${O})
168;#     c) edit util.lisp to add the 'external' function (those that
169;#        should trigger the autoload
170;#   case 2:
171;#     build-interpsys (in util.lisp) needs an extra argument for the
172;#     new autoload things and several functions in util.lisp need hacking.
173;############################################################################
174
175The {\bf build-interpsys} function takes a list of files to load
176into the image ({\bf load-files}). It also takes several lists of files,
177one for each subsystem which will be autoloaded. Autoloading is explained
178below. Next it takes a set of shell variables, the most important of
179which is the {\bf spad} variable. This is normally set to be the same
180as the final build location. This function is called in the
181src/interp/Makefile.
182
183This function calls {\bf initroot} to set up pathnames we need. Next
184it sets up the lisp system memory (at present only for GCL). Next
185it loads all of the named files, resets a few global state variables,
186loads the databases, sets up autoload triggers and clears out hash tables.
187After this function is called the image is clean and can be saved.
188|#
189(defun build-interpsys (load-files spad)
190  #-:ecl
191  (progn
192      (mapcar #'load load-files)
193      (interpsys-image-init spad))
194  (if (and (boundp 'FRICAS-LISP::*building-fricassys*)
195                FRICAS-LISP::*building-fricassys*)
196       (progn
197           #+:GCL(setf compiler::*default-system-p* nil)
198           #+:GCL(compiler::emit-fn nil)
199           (setq *load-verbose* nil)
200           #+:clisp(setf custom:*suppress-check-redefinition* t)
201       )
202  )
203  #+:ecl
204  (progn
205      (setf FRICAS-LISP::*fricas-initial-lisp-objects*
206           (append FRICAS-LISP::*fricas-initial-lisp-objects*
207                   '("util.o")
208                   load-files))
209      (let ((initforms nil))
210          (dolist (el '(|$build_date| |$build_version| |$createLocalLibDb|))
211              (if (boundp el)
212                  (push (list 'defparameter el (symbol-value el))
213                        initforms)))
214          (push `(interpsys-ecl-image-init ,spad) initforms)
215          (push `(fricas-restart) initforms)
216          (setf initforms (reverse initforms))
217          (push `progn initforms)
218          (setf FRICAS-LISP::*fricas-initial-lisp-forms* initforms)
219      )
220  )
221)
222
223(defun interpsys-ecl-image-init (spad)
224     (format *standard-output* "Starting interpsys~%")
225     #+:ecl (let ((sym (or (find-symbol "TRAP-FPE" "EXT")
226                           (find-symbol "TRAP-FPE" "SI"))))
227                 (if (and sym (fboundp sym))
228                     (funcall sym T T)))
229     #+:ecl (let ((sym (find-symbol "*BREAK-ENABLE*" "SI")))
230                (if (and sym (boundp sym))
231                    (setf (symbol-value sym) t)))
232     (initroot spad)
233     (setf spad $spadroot)
234     (format *standard-output* "spad = ~s~%" spad)
235     (force-output  *standard-output*)
236     (interpsys-image-init spad)
237     (format *standard-output* "before fricas-restart~%")
238     (force-output  *standard-output*)
239)
240
241(defun interpsys-image-init (spad)
242  (setf *package* (find-package "BOOT"))
243  (initroot spad)
244  #+:GCL
245  (init-memory-config :cons 500 :fixnum 200 :symbol 500 :package 8
246                      :array 400 :string 500 :cfun 100 :cpages 1000
247                      :rpages 1000 :hole 2000)
248  #+:GCL
249  (setq compiler::*suppress-compiler-notes* t)
250  (|interpsysInitialization|)
251  (setq *load-verbose* nil)
252  (resethashtables) ; the databases into core, then close the streams
253 )
254
255;; the following are for conditional reading
256(setq |$opSysName| '"shell")
257
258;;; moved from bookvol5
259
260(defvar |$HiFiAccess| t               "t means turn on history mechanism")
261
262(defvar |$reportUndo| nil "t means we report the steps undo takes")
263(defvar $openServerIfTrue t "t means try starting an open server")
264(defparameter $SpadServerName "/tmp/.d" "the name of the spad server socket")
265(defvar |$SpadServer| nil "t means Scratchpad acts as a remote server")
266
267
268(defun |loadExposureGroupData| ()
269 (cond
270  ((load "./exposed" :verbose nil :if-does-not-exist nil)
271    '|done|)
272  ((load (concat (|getEnv| "FRICAS") "/algebra/exposed")
273     :verbose nil :if-does-not-exist nil)
274   '|done|)
275  (t '|failed|) ))
276
277(defvar *fricas-load-libspad* t)
278
279(defun fricas-init ()
280#+:GCL
281  (init-memory-config :cons 500 :fixnum 200 :symbol 500 :package 8
282    :array 400 :string 500 :cfun 100 :cpages 3000 :rpages 1000 :hole 2000)
283#+:GCL (setq compiler::*compile-verbose* nil)
284#+:GCL (setq compiler::*suppress-compiler-warnings* t)
285#+:GCL (setq compiler::*suppress-compiler-notes* t)
286  (in-package "BOOT")
287  (initroot)
288#+:poplog (setf POPLOG:*READ-PROMPT* "") ;; Turn off Poplog read prompts
289#+:GCL (system:gbc-time 0)
290    #+(or :sbcl :clisp :openmcl :lispworks)
291    (if *fricas-load-libspad*
292        (let* ((ax-dir (|getEnv| "FRICAS"))
293               (spad-lib (concatenate 'string ax-dir "/lib/libspad.so")))
294            (format t "Checking for foreign routines~%")
295            (format t "FRICAS=~S~%" ax-dir)
296            (format t "spad-lib=~S~%" spad-lib)
297            (if (|fricas_probe_file| spad-lib)
298                (progn
299                    (setf *fricas-load-libspad* nil)
300                    (format t "foreign routines found~%")
301                    #+(or :sbcl :openmcl :lispworks)
302                    (|quiet_load_alien| spad-lib)
303                    #+(or :sbcl :openmcl)
304                    (fricas-lisp::init-gmp
305                        (concatenate 'string ax-dir "/lib/gmp_wrap.so"))
306                    #+(and :clisp :ffi)
307                    (progn
308                        (eval `(FFI:DEFAULT-FOREIGN-LIBRARY ,spad-lib))
309                        (FRICAS-LISP::clisp-init-foreign-calls))
310                )
311                (setf $openServerIfTrue nil))))
312    #+(or :GCL (and :clisp :ffi) :sbcl :cmu :openmcl :ecl :lispworks)
313    (if $openServerIfTrue
314        (let ((os (|openServer| $SpadServerName)))
315             (format t "openServer result ~S~%" os)
316             (if (zerop os)
317                 (progn
318                      (setf $openServerIfTrue nil)
319                      #+:GCL
320                      (if (fboundp 'si::readline-off)
321                          (si::readline-off))
322                      (setq |$SpadServer| t)))))
323  (|interpsys_restart|)
324)
325
326(DEFVAR |$trace_stream| *standard-output*)
327(DEFVAR CUROUTSTREAM *standard-output*)
328
329(defun fricas-restart ()
330  ;;; Need to reinitialize CUROUTSTREAM and |$trace_stream| because
331  ;;;  clisp closes it when dumping executable
332  (setf CUROUTSTREAM *standard-output*)
333  (setf |$trace_stream| *standard-output*)
334  (fricas-init)
335  #+(or :GCL :poplog)
336  (|spad|)
337  #-(or :GCL :poplog)
338  (let ((*debugger-hook*
339            (lambda (condition previous-handler)
340                (spad-system-error-handler condition))
341       ))
342     (handler-bind ((error #'spad-system-error-handler))
343       (|spad|)))
344)
345
346
347(defun spad-save (save-file do-restart)
348  (setq |$SpadServer| nil)
349  (setq $openServerIfTrue t)
350  (FRICAS-LISP::save-core-restart save-file
351         (if do-restart #'boot::fricas-restart nil))
352)
353
354(defun |statisticsInitialization| ()
355 "initialize the garbage collection timer"
356 #+:GCL (system:gbc-time 0)
357 nil)
358
359(defun |mkAutoLoad| (fn cname)
360   (function (lambda (&rest args)
361                 #+:sbcl
362                 (handler-bind ((style-warning #'muffle-warning))
363                     (|autoLoad| fn cname))
364                 #-:sbcl
365                 (|autoLoad| fn cname)
366                 (apply cname args))))
367
368(defun |eval|(x)
369    #-:GCL
370    (handler-bind ((warning #'muffle-warning)
371                   #+:sbcl (sb-ext::compiler-note #'muffle-warning))
372            (eval  x))
373    #+:GCL
374    (eval  x)
375)
376
377;;; For evaluating categories we need to bind $.
378(defun |c_eval|(u) (let (($ '$)) (declare (special $)) (|eval| u)))
379
380;;; Accesed from HyperDoc
381(defun |setViewportProcess| ()
382  (setq |$ViewportProcessToWatch|
383     (stringimage (CDR
384         (|processInteractive|  '(|key| (|%%| -2)) NIL) ))))
385
386;;; Accesed from HyperDoc
387(defun |waitForViewport| ()
388  (progn
389   (do ()
390       ((not (zerop (obey
391        (concat
392         "ps "
393         |$ViewportProcessToWatch|
394         " > /dev/null")))))
395       ())
396   (|sockSendInt| |$MenuServer| 1)
397   (|setIOindex| (- |$IOindex| 3))
398  )
399)
400