1
0
mirror of https://github.com/PDP-10/its.git synced 2026-01-15 16:07:01 +00:00
PDP-10.its/src/maxsrc/mload.121
Eric Swenson 85994ed770 Added files to support building and running Macsyma.
Resolves #284.

Commented out uses of time-origin in maxtul; mcldmp (init) until we
can figure out why it gives arithmetic overflows under the emulators.

Updated the expect script statements in build_macsyma_portion to not
attempt to match expected strings, but simply sleep for some time
since in some cases the matching appears not to work.
2018-03-11 13:10:19 -07:00

480 lines
15 KiB
Common Lisp

;;; -*- Mode: Lisp; Package: Macsyma -*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(macsyma-module mload)
;; I decided to move most of the file hacking utilities I used in TRANSL to
;; this file. -GJC
;; Concepts:
;; Lisp_level_filename. Anything taken by the built-in lisp I/O primitives.
;;
;; User_level_filename. Comes through the macsyma reader, so it has an extra "&"
;; in the pname in the case of "filename" or has extra "$" and has undergone
;; ALIAS transformation in the case of 'FOOBAR or '[FOO,BAR,BAZ].
;;
;; Canonical_filename. Can be passed to built-in lisp I/O primitives, and
;; can also be passed back to the user, is specially handled by the DISPLAY.
;;
;; Functions:
;; $FILENAME_MERGE. Takes User_level_filename(s) and Canonical_filename(s) and
;; merges them together, returning a Canonical_filename.
;;
;; TO-MACSYMA-NAMESTRING. Converts a Lisp_level_filename to a Canonical_filename
;;
;; $FILE_SEARCH ............ Takes a user or canonical filename and a list of types of
;; applicable files to look for.
;; $FILE_TYPE ............. Takes a user or canonical filename and returns
;; NIL, $MACSYMA, $LISP, or $FASL.
;; CALL-BATCH1 ............. takes a canonical filename and a no-echop flag.
;; Note: This needs to be generalized some more to take into account
;; the lispmachine situation of access to many different file systems
;; at the same time without, and also take into account the way it presently
;; deals with that situation. The main thing wrong now is that the file-default
;; strings are constants.
;; What a cannonical filename is on the different systems:
;; This is for informational purposes only, as the Macsyma-Namestringp
;; predicate is provided.
;; [PDP-10 Maclisp] An uninterned symbol with various properties.
;; [Franz Lisp] a string or a symbol (whose print name is used).
;; [Multics Maclisp] A STRING.
;; [LispMachine] A generic pathname object, which is a system-provided FLAVOR.
;; [NIL] Not decided yet, but a STRING should do ok, since in NIL files are
;; a low-level primitive, and programs, modules, and environments are the
;; practical abstraction used. No attempt is made to come up with ad-hoc generalizations
;; of the ITS'ish and DEC'ish filenames, as such attempts fail miserably to provide
;; the functionality of filesystems such as on Multics.
(DECLARE (SPECIAL $FILE_SEARCH $FILE_TYPES))
(DEFMFUN $LISTP_CHECK (VAR VAL)
"Gives an error message including its first argument if its second
argument is not a LIST"
(OR ($LISTP VAL)
(MERROR "The variable ~:M being set to a non-LISTP object:~%~M"
VAR VAL)))
(DEFPROP $FILE_SEARCH $LISTP_CHECK ASSIGN)
(DEFPROP $FILE_TYPES $LISTP_CHECK ASSIGN)
#-Franz
(DEFMFUN $FILE_SEARCH (X &OPTIONAL
(LISTP NIL)
(L $FILE_TYPES))
(SETQ X ($FILENAME_MERGE X))
(IF ($LISTP L) (SETQ L (CDR L))
(MERROR "3'rd arg to FILE_SEARCH not a list.~%~M" L))
(DO ((MERGE-SPECS (CONS ($filename_merge)
;; Get a complete "star filename"
(CDR $FILE_SEARCH))
(CDR MERGE-SPECS))
(PROBED)
(FOUND))
((NULL MERGE-SPECS)
(IF LISTP
`((MLIST) ,@(NREVERSE FOUND))
(MERROR "Could not find file which matches ~M" X)))
(IF (DO ((L L (CDR L))
(U ($FILENAME_MERGE (CAR MERGE-SPECS))))
((NULL L) NIL)
(IF (SETQ PROBED (PROBEF ($FILENAME_MERGE X U (CAR L))))
(IF LISTP
(PUSH (TO-MACSYMA-NAMESTRING PROBED) FOUND)
(RETURN T))))
(RETURN (TO-MACSYMA-NAMESTRING PROBED)))))
;; filename merging is unheard of on Unix.
;; If the user doesn't supply a file extension, we look for .o, .l and .v
;; and finally the file itself. If the user supplies one of the standard
;; extensions, we just use that.
#+Franz
(defmfun $file_search (x &optional (listp nil) (l $file_types))
(let ((filelist (cond ((cdr $file_search))
(t '("."))))
(extlist (cond ((member (substring x -2) '(".o" ".l" ".v"))
'(nil))
(t '(".o" ".l" ".v" nil)))))
(do ((dir filelist (cdr dir))
(ret))
((null dir)
(cond (listp '((mlist)))
(t (MERROR "Could not find file ~M" X))))
(cond ((setq ret
(do ((try extlist (cdr try))
(this))
((null try))
(setq this (cond ((null (car try)) x)
(t (concat x (car try)))))
(cond ((not (equal "." (car dir)))
(setq this (concat (car dir) "//" this))))
(cond ((probef this)
(return
(cond (listp `((mlist)
,(to-macsyma-namestring x)))
(t (to-macsyma-namestring this))))))))
(return ret))))))
(DECLARE (SPECIAL $LOADPRINT))
(DEFMFUN LOAD-AND-TELL (FILENAME)
(LOADFILE FILENAME
T ;; means this is a lisp-level call, not user-level.
$LOADPRINT))
#+PDP10
(PROGN 'COMPILE
;; on the PDP10 cannonical filenames are represented as symbols
;; with a DIMENSION-LIST property of DISPLAY-FILENAME.
(DEFUN DIMENSION-FILENAME (FORM RESULT)
(DIMENSION-STRING (CONS #/" (NCONC (EXPLODEN FORM) (LIST #/"))) RESULT))
(DEFUN TO-MACSYMA-NAMESTRING (X)
;; create an uninterned symbol, uninterned so that
;; it will be GC'd.
(SETQ X (PNPUT (PNGET (NAMESTRING X) 7) NIL))
(PUTPROP X 'DIMENSION-FILENAME 'DIMENSION-LIST)
X)
(DEFUN MACSYMA-NAMESTRINGP (X)
(AND (SYMBOLP X) (EQ (GET X 'DIMENSION-LIST) 'DIMENSION-FILENAME)))
(DEFMACRO ERRSET-NAMESTRING (X)
`(LET ((ERRSET NIL))
(ERRSET (NAMESTRING ,X) NIL)))
(DEFMFUN $FILENAME_MERGE N
(DO ((F "" (MERGEF (MACSYMA-NAMESTRING-SUB (ARG J)) F))
(J N (1- J)))
((ZEROP J)
(TO-MACSYMA-NAMESTRING F))))
)
#+Franz
(progn 'compile
;; a first crack at these functions
(defun to-macsyma-namestring (x)
(cond ((macsyma-namestringp x) x)
((symbolp x)
(cond ((memq (getcharn x 1) '(#/& #/$))
(substring (get_pname x) 2))
(t (get_pname x))))
(t (merror "to-macsyma-namestring: non symbol arg ~M~%" x))))
(defun macsyma-namestringp (x)
(stringp x))
;;--- $filename_merge
; may not need this ask filename merging is not done on Unix systems.
;
(defmfun $filename_merge (&rest files)
(cond (files (filestrip (ncons (car files))))))
)
#+MULTICS
(PROGN 'COMPILE
(DEFUN TO-MACSYMA-NAMESTRING (X)
(cond ((macsyma-namestringp x) x)
((symbolp x) (substring (string x) 1))
((listp x) (namestring x))
(t x)))
(DEFUN MACSYMA-NAMESTRINGP (X) (STRINGP X))
(DEFUN ERRSET-NAMESTRING (X)
(IF (ATOM X) (NCONS (STRING X)) (ERRSET (NAMESTRING X) NIL)))
(DEFMFUN $FILENAME_MERGE (&REST FILE-SPECS)
(SETQ FILE-SPECS (cond (file-specs
(MAPCAR #'MACSYMA-NAMESTRING-SUB FILE-SPECS))
(t '("**"))))
(TO-MACSYMA-NAMESTRING (IF (NULL (CDR FILE-SPECS))
(CAR FILE-SPECS)
(APPLY #'MERGEF FILE-SPECS))))
)
#+LISPM
(PROGN 'COMPILE
(DEFUN TO-MACSYMA-NAMESTRING (X)
(FS:PARSE-PATHNAME X))
(DEFUN MACSYMA-NAMESTRINGP (X)
(TYPEP X 'FS:PATHNAME))
(DEFUN ERRSET-NAMESTRING (X)
(LET ((ERRSET NIL))
(ERRSET (FS:PARSE-PATHNAME X) NIL)))
(DEFMFUN $FILENAME_MERGE (&REST FILE-SPECS)
(DO ((F "" (FS:MERGE-PATHNAME-DEFAULTS (MACSYMA-NAMESTRING-SUB
(NTH (1- J) FILE-SPECS))
F))
(J (LENGTH FILE-SPECS) (1- J)))
((ZEROP J)
(TO-MACSYMA-NAMESTRING F))))
)
(DEFUN MACSYMA-NAMESTRING-SUB (USER-OBJECT)
(IF (MACSYMA-NAMESTRINGP USER-OBJECT) USER-OBJECT
(LET* ((SYSTEM-OBJECT
(COND ((ATOM USER-OBJECT)
(FULLSTRIP1 USER-OBJECT))
(($LISTP USER-OBJECT)
(FULLSTRIP (CDR USER-OBJECT)))
(T
(MERROR "Bad file spec:~%~M" USER-OBJECT))))
(NAMESTRING-TRY (ERRSET-NAMESTRING SYSTEM-OBJECT)))
(IF NAMESTRING-TRY (CAR NAMESTRING-TRY)
;; know its small now, so print on same line.
(MERROR "Bad file spec: ~:M" USER-OBJECT)))))
(DEFMFUN open-out-dsk (x)
(open x #-LISPM '(out dsk ascii block)
#+LISPM '(:out :ascii)))
(DEFMFUN open-in-dsk (x)
(open x #-LISPM '(in dsk ascii block)
#+LISPM '(:in :ascii)))
#-MAXII
(PROGN 'COMPILE
(DECLARE (SPECIAL DSKFNP OLDST ST $NOLABELS REPHRASE))
(DEFMFUN CALL-BATCH1 (FILENAME ^W)
(LET ((^R (AND ^R (NOT ^W)))
($NOLABELS T)
($CHANGE_FILEDEFAULTS)
(DSKFNP T)
(OLDST)
(ST))
;; cons #/& to avoid the double-stripdollar problem.
(BATCH1 (LIST (MAKNAM (CONS #/& (EXPLODEN FILENAME))))
NIL
NIL
#-Franz T
#+Franz nil)
(SETQ REPHRASE T)))
(DEFMVAR *IN-$BATCHLOAD* NIL
"I should have a single state variable with a bit-vector or even a list
of symbols for describing the state of file translation.")
(DEFMVAR *IN-TRANSLATE-FILE* NIL "")
(DEFMVAR *IN-MACSYMA-INDEXER* NIL)
(DEFUN TRANSLATE-MACEXPR (FORM &optional FILEPOS)
(COND (*IN-TRANSLATE-FILE*
(TRANSLATE-MACEXPR-ACTUAL FORM FILEPOS))
(*in-macsyma-indexer*
(outex-hook-exp form))
(T
(LET ((R (ERRSET (MEVAL* FORM))))
(COND ((NULL R)
(LET ((^W NIL))
(MERROR "~%This form caused an error in evaluation:~
~%~:M" FORM))))))))
(DEFMFUN $BATCHLOAD (FILENAME)
(LET ((WINP NIL)
(NAME ($FILENAME_MERGE FILENAME))
(*IN-$BATCHLOAD* T))
(IF $LOADPRINT
(MTELL "~%Batching the file ~M~%" NAME))
(UNWIND-PROTECT
(PROGN (CALL-BATCH1 NAME T)
(SETQ WINP T)
NAME)
;; unwind protected.
(IF WINP
(IF $LOADPRINT (MTELL "Batching done."))
(MTELL "Some error in loading this file: ~M" NAME)))))
;; end of moby & crufty #-MAXII
)
#+MAXII
(DEFMFUN $BATCHLOAD (FILENAME)
(LET ((EOF (LIST NIL))
(NAME ($FILENAME_MERGE FILENAME))
(*MREAD-PROMPT* "(Batching) "))
(IF $LOADPRINT
(MTELL "~%Batching the file ~M~%" NAME))
(WITH-OPEN-FILE (STREAM NAME '(:IN :ASCII))
(DO ((FORM NIL (MREAD STREAM EOF)))
((EQ FORM EOF)
(IF $LOADPRINT (MTELL "Batching done."))
'$DONE)
(MEVAL* (CADDR FORM))))))
(DEFMFUN $LOAD (MACSYMA-USER-FILENAME
&AUX
(FILENAME ($FILENAME_MERGE MACSYMA-USER-FILENAME)))
"This is the generic file loading function.
LOAD(/"filename/") will either BATCHLOAD or LOADFILE the file,
depending on wether the file contains Macsyma, Lisp, or Compiled
code. The file specifications default such that a compiled file
is searched for first, then a lisp file, and finally a macsyma batch
file. This command is designed to provide maximum utility and
convenience for writers of packages and users of the macsyma->lisp
translator."
(LET* ((SEARCHED-FOR ($FILE_SEARCH FILENAME))
(TYPE ($FILE_TYPE SEARCHED-FOR)))
(CASEQ TYPE
(($MACSYMA)
($BATCHLOAD SEARCHED-FOR))
(($LISP $FASL)
;; do something about handling errors
;; during loading. Foobar fail act errors.
(LOAD-AND-TELL SEARCHED-FOR))
(T
(MERROR "MACSYMA BUG: Unknown file type ~M" TYPE)))
SEARCHED-FOR
))
#+Multics
(DEFMFUN $FILE_TYPE (FILE)
(SETQ FILE ($FILENAME_MERGE FILE))
(IF (NULL (PROBEF FILE)) NIL
(CASEQ (CAR (LAST (NAMELIST FILE)))
((MACSYMA) '$MACSYMA)
((LISP) '$LISP)
(T '$FASL))))
#-MULTICS
(DEFMFUN $FILE_TYPE (FILENAME &AUX STREAM)
(SETQ FILENAME ($FILENAME_MERGE FILENAME))
(COND ((NULL (PROBEF FILENAME))
NIL)
#-Franz ((FASLP FILENAME)
'$FASL)
#+Franz ((cdr (assoc (substring filename -2)
'((".l" . $lisp) (".o" . $fasl) (".v" . $macsyma)))))
('ELSE
;; This has to be simple and small for greatest utility
;; as an in-core pdp10 function.
(UNWIND-PROTECT
(DO ((C (PROGN (SETQ STREAM (OPEN-IN-DSK FILENAME))
#\SP)
(TYI STREAM -1)))
((NOT (MEMBER C '(#\SP #\TAB #\CR #\LF #\FF)))
;; heuristic number one,
;; check for cannonical language "comment." as first thing
;; in file after whitespace.
(COND ((MEMBER C '(-1 #/;))
'$LISP)
((AND (= C #//)
(= (TYI STREAM -1) #/*))
'$MACSYMA)
#+Franz ((eq c 7) ;; fasl files begin with bytes 7,1
'$fasl) ;; but just seeing 7 is good enough
('ELSE
;; the above will win with all Lisp files written by
;; the macsyma system, e.g. the $SAVE and
;; $TRANSLATE_FILE commands, all lisp files written
;; by macsyma system programmers, and anybody else
;; who starts his files with a "comment," lisp or
;; macsyma.
(FILEPOS STREAM 0)
;; heuristic number two, see if READ returns something
;; evaluable.
(LET ((FORM (LET ((ERRSET NIL))
;; this is really bad to do since
;; it can screw the lisp programmer out
;; of a chance to identify read errors
;; as they happen.
(ERRSET (READ STREAM NIL) NIL))))
(IF (OR (NULL FORM)
(ATOM (CAR FORM)))
'$MACSYMA
'$LISP))))))
;; Unwind protected.
(IF STREAM (CLOSE STREAM))))))
#+LISPM
(defun faslp (filename)
;; wasteful to be opening file objects so many times, one for
;; each predicate and then again to actually load. Fix that perhaps
;; by having the predicates return "failure-objects," which can be
;; passed on to other predicates and on to FS:FASLOAD-INTERNAL and
;; FS:READFILE-INTERNAL.
(with-open-file (stream filename '(:read :fixnum))
(funcall stream ':qfaslp)))
(DEFMVAR $FILE_SEARCH
#+ITS
`((MLIST)
,@(MAPCAR #'TO-MACSYMA-NAMESTRING
'("DSK:SHARE;" "DSK:SHARE1;" "DSK:SHARE2;" "DSK:SHAREM;")))
#+Franz
`((mlist)
,@(mapcar #'to-macsyma-namestring
`("."
,(concat vaxima-main-dir "//share")
,(concat vaxima-main-dir "//demo"))))
#+LISPM
`((MLIST)
,@(MAPCAR #'TO-MACSYMA-NAMESTRING
'("MC:LMMAXR;" "MC:LMMAXQ;")))
#+Multics
'((MLIST))
"During startup initialized to a list of places the LOAD function
should search for files."
)
#+Multics
(PROGN 'COMPILE
;; We need an abstract entry in this list to indicate "working_dir".
(DEFMFUN INITIATE-FILE-SEARCH-LIST ()
(LET ((WHERE-AM-I (CAR (NAMELIST EXECUTABLE-DIR))))
(SETQ
$FILE_SEARCH
`((MLIST)
,@(mapcar #'to-macsyma-namestring
`(,(string-append (PATHNAME-UTIL "hd") ">**")
,(string-append (NAMESTRING `(,WHERE-AM-I "share")) ">**")
,(string-append (NAMESTRING `(,WHERE-AM-I "executable"))
">**")))))))
;; These forms getting evaluated at macsyma start-up time.
(if (boundp 'macsyma-startup-queue)
(PUSH '(INITIATE-FILE-SEARCH-LIST) MACSYMA-STARTUP-QUEUE)
(setq macsyma-startup-queue '((initiate-file-search-list))))
;; Done for debuggings sake.
(eval-when (eval load)
(initiate-file-search-list))
)
#-LISPM
(DEFMVAR $FILE_TYPES
`((MLIST)
,@(MAPCAR #'TO-MACSYMA-NAMESTRING
#+ITS
;; ITS filesystem. Sigh. This should be runtime conditionalization.
'("* FASL" "* TRLISP" "* LISP" "* >")
#+MULTICS
'("**" "**.lisp" "**.macsyma")))
"The types of files that can be loaded into a macsyma automatically")
#+LISPM
(DEFMVAR $FILE_TYPES '((MLIST) "* FASL" "* TRLISP" "* LISP" "* >"))
(defmfun mfilename-onlyp (x)
"Returns T iff the argument could only be reasonably taken as a filename."
(cond ((macsyma-namestringp x) t)
(($listp x) t)
((symbolp x)
(= #/& (getcharn x 1)))
('else
nil)))