"$Header: /usr/lib/lisp/toplevel.l,v 1.1 83/01/29 18:40:43 jkf Exp $")
;; toplevel.l -[Sat Jan 29 18:29:43 1983 by jkf]-
;; toplevel read eval print loop
(declare (special debug-level-count break-level-count
errlist tpl-errlist user-top-level
franz-not-virgin piport ER%tpl ER%all
$ldprint evalhook funcallhook
franz-minor-version-number
top-level-print top-level-read
top-level-eof * ** *** + ++ +++ ^w)
(localf autorunlisp cvtsearchpathtolist)
(setq top-level-eof (gensym 'Q)
;--- read and print functions are user-selectable by just
; assigning another value to top-level-print and top-level-read
(defmacro top-print (&rest args)
`(cond (top-level-print (funcall top-level-print ,@args))
(defmacro top-read (&rest args)
`(cond ((and top-level-read
(funcall top-level-read ,@args))
;------------------------------------------------------
; Top level function for franz jkf, march 1980
; The following function contains the top-level read, eval, print
; loop. With the help of the error handling functions,
; break-err-handler and debug-err-handler, franz-top-level provides
; a reasonable enviroment for working with franz lisp.
(putd 'reset (getd 'franz-reset))
(username-to-dir-flush-cache) ; clear tilde expansion knowledge
(cond ((or (not (boundp 'franz-not-virgin))
(setq ER%tpl 'break-err-handler)
(cond ((not (autorunlisp))
; franz-minor-version-number defined in version.l
(cond ((boundp 'franz-minor-version-number)
(patom franz-minor-version-number)))
(read-in-lisprc-file)))))
'(top-level-catch break-catch)
; begin or return to top level
(setq debug-level-count 0 break-level-count 0
evalhook nil funcallhook nil)
(cond (tpl-errlist (mapc 'eval tpl-errlist)))
(cond (user-top-level (funcall user-top-level))
(car (errset (top-read nil
(cond ((not (status isatty))
(cond ((null (status ignoreeof))
; update list of old forms
; update list of old values
(patom "[Return to top level]")
(cond ((eq 'reset retval) (old-reset-function))))))
; debug-err-handler is the clb of ER%all when we are doing debugging
; and we want to catch all errors.
; It is just a read eval print loop with errset.
; the only way to leave is:
; (reset) just back to top level
; (return x) return the value to the error checker.
; if nil is returned then we will continue as if the error
; didn't occur. Otherwise if the returned value is a list,
; then if the error is continuable, the car of that list
; will be returned to recontinue computation.
; ^D continue as if this handler wasn't called.
; the form of errmsgs is:
; (error_type unique_id continuable message_string other_args ...)
((lambda (message debug-level-count retval ^w piport)
(mapc '(lambda (a) (patom " ") (patom a) )
(setq ER%all 'debug-err-handler)
(patom debug-level-count)
(cond ((null (status isatty))
(return (eval (cadr form))))
(t (setq form (eval form))
(return (car retval))))))
; this is the break handler, it should be tied to
; it is entered if there is an error which no one wants to handle.
; We loop forever, printing out our error level until someone
; types a ^D which goes to the next break level above us (or the
; top-level if there are no break levels above us.
; a (return n) will return that value to the error message
; which called us, if that is possible (that is if the error is
((lambda (message break-level-count retval rettype ^w piport)
(mapc '(lambda (a) (patom " ") (patom a) )
(cond ((caddr (arg 1)) (setq rettype 'contuab))
(t (setq rettype 'localcall)))
(patom break-level-count)
(cond ((null (status isatty))
(eval 1) ; force interrupt check
(return (sub1 break-level-count)))
(cond ((or (eq rettype 'contuab)
(return (ncons (eval (cadr form)))))
(t (patom "Can't continue from this error")
((and (dtpr form) (eq 'retbrk (car form)))
(cond ((numberp (setq form (eval (cadr form))))
(t (return (sub1 break-level-count)))))
(t (setq form (eval form))
(return (cond ((eq rettype 'localcall)
((lessp retval break-level-count)
(setq tpl-errlist errlist)
(*throw 'break-catch retval))
(cond (val (setq ER%all 'debug-err-handler)
; the problem with this definition for break is that we are
; forced to put an errset around the break-err-handler. This means
; that we will never get break errors, since all errors will be
; caught by our errset (better ours than one higher up though).
; perhaps the solution is to automatically turn debugmode on.
(defmacro break (message &optional (pred t))
`(*break ,pred ',message))
(cond ((not (boundp 'break-level-count)) (setq break-level-count 1)))
(cond ((dtpr (setq form (errset (break-err-handler))))
(return (car form))))))))))
; this reset function is designed to work with the franz-top-level.
; When franz-top-level begins, it makes franz-reset be reset.
; when a reset occurs now, we set the global variable tpl-errlist to
; the current value of errlist and throw to top level. At top level,
; then tpl-errlist will be evaluated.
(setq tpl-errlist errlist)
(errset (*throw 'top-level-catch 'reset)
(declare (special $ldprint))
; search for a lisp init file. Look first in . then in $HOME
; look first for .o , then .l and then "",
; look for file bodies .lisprc and then lisprc
(setq break-level-count 0 ; do this in case break
debug-level-count 0) ; occurs during readin
(*catch '(break-catch top-level-catch)
(do ((dirs `("." ,(getenv 'HOME)) (cdr dirs))
($ldprint nil $ldprint)) ; prevent messages
(cond ((do ((name '(".lisprc" "lisprc") (cdr name)))
(cond ((do ((ext '(".o" ".l" "") (cdr ext))
(cond ((atom (errset (load file)))
"Error loading lisp init file ")
(putd 'top-level (getd 'franz-top-level))
; if this is the first time this file has been read in, then
; make franz-reset be the reset function, but remember the original
; reset function as old-reset-function. We need the old reset function
; if we are going to allow the user to change top-levels, for in
; order to do that we really have to jump all the way up to the top.
(cond ((null (getd 'old-reset-function))
(putd 'old-reset-function (getd 'reset))))
;---- autoloader functions
(setq funcnam (caddddr args))
(cond ((setq file (or (get funcnam 'autoload)
(get funcnam 'macro-autoload)))
(patom "[autoload ") (patom file)
(cond ((getd funcnam) (return (ncons funcnam)))
(t (patom "Autoload file " ) (print file)
(patom " does not contain function ")
(setq ER%undef 'undef-func-handler)
(declare (special $ldprint))
;--- autorunlisp :: check if this lisp is supposed to run a program right
(cond ((and (> (argv -1) 2) (equal (argv 1) '-f))
(let ((progname (argv 2))
(searchlist nil)) ; don't give fasl messages
(setq searchlist (cvtsearchpathtolist (getenv 'PATH)))
; give two args to load to insure that a fasl is done.
(errset (load-autorunobject progname searchlist)))
(defun cvtsearchpathtolist (path)
(do ((x (explodec path) (cdr x))
(cond ((or (eq ': (car x))
(and (null (cdr x)) (setq cur (cons (car x) cur))))
(cond (cur (setq names (cons (implode (nreverse cur))
(t (setq names (cons '|.| names)))))
(t (setq cur (cons (car x) cur))))))
(defun load-autorunobject (name search)
(cond ((memq (getchar name 1) '(/ |.|))
(cond ((probef name) (fasl name))
(t (error "From lisp autorun: can't find file to load"))))
(t (do ((xx search (cdr xx))
((null xx) (error "Can't find file to execute "))
(cond ((probef (setq fullname (concat (car xx) "/" name)))
(return (fasl-a-file fullname nil nil))))))))
;--- command-line-args :: return a list of the command line arguments
; The list does not include the name of the program being executed (argv 0).
; It also doesn't include the autorun flag and arg.
(defun command-line-args ()
(do ((res nil (cons (argv i) res))
(i (1- (argv -1)) (1- i)))
(if (and (eq '-f (car res))
(defun debug fexpr (args)
(load 'fix) ; load in fix package
(eval (cons 'debug args))) ; enter debug through eval
;-- default autoloader properties
(putprop 'trace (concat lisp-library-directory "/trace") 'autoload)
(putprop 'step (concat lisp-library-directory "/step") 'autoload)
(putprop 'editf (concat lisp-library-directory "/cmuedit") 'autoload)
(putprop 'editv (concat lisp-library-directory "/cmuedit") 'autoload)
(putprop 'editp (concat lisp-library-directory "/cmuedit") 'autoload)
(putprop 'edite (concat lisp-library-directory "/cmuedit") 'autoload)
(putprop 'defstruct (concat lisp-library-directory "/struct") 'macro-autoload)
(putprop 'defstruct-expand-ref-macro
(concat lisp-library-directory "/struct") 'autoload)
(putprop 'defstruct-expand-cons-macro
(concat lisp-library-directory "/struct") 'autoload)
(putprop 'loop (concat lisp-library-directory "/loop") 'macro-autoload)
(concat lisp-library-directory "/flavors") 'macro-autoload)
(concat lisp-library-directory "/flavors") 'autoload)
(putprop 'format (concat lisp-library-directory "/format") 'autoload)
(putprop 'ferror (concat lisp-library-directory "/format") 'autoload)
(putprop 'make-hash-table
(concat lisp-library-directory "/hash") 'autoload)
(putprop 'make-equal-hash-table
(concat lisp-library-directory "/hash") 'autoload)
(putprop 'describe (concat lisp-library-directory "/describe") 'autoload)
(putprop 'cgol (concat lisp-library-directory "/cgol") 'autoload)
; probably should be in franz so we don't have to autoload
(putprop 'displace (concat lisp-library-directory "/machacks") 'autoload)