(setq SCCS-toplevel "@(#)toplevel.l 1.5 7/9/81")
(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
top-level-eof * ** *** + ++ +++ ^w)
(setq top-level-eof (gensym 'Q)
;------------------------------------------------------
; 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.
(cond ((or (not (boundp 'franz-not-virgin))
(setq ER%tpl 'break-err-handler)
(putd 'reset (getd 'franz-reset))
(cond ((not (autorunlisp))
(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))
(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)
(read nil top-level-eof)))
(cond ((null (status isatty))
(return (eval (cadr 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)
(setq form (read nil top-level-eof)))
(cond ((null (status isatty))
(eval 1) ; force interrupt check
(return (sub1 break-level-count)))
((and (dtpr form) (eq 'return (car form)))
(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)))))
(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)
; this definition will have to do until we have the ability to
; cause and error on any channel in franz
; this file is read in just before dumplisping if you want .lisprc
; from your home directory read in before the lisp begins.
(setq break-level-count 0 ; do this in case break
debug-level-count 0) ; occurs during readin
(*catch '(break-catch top-level-catch)
(setq prt (infile (concat hom '"/.lisprc")))
(load (concat hom '"/.lisprc")))))
(patom '"Error in .lisprc file detected")
(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 (get funcnam 'autoload))
(patom "[autoload ") (patom file)
(cond ((getd funcnam) (return (ncons funcnam)))
(t (patom "Autoload file does not contain func ")
(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 fullname))))))))
(defun debug fexpr (args)
(load 'fix) ; load in fix package
(eval (cons 'debug args))) ; enter debug through eval
;-- default autoloader properties
(putprop 'trace '/usr/lib/lisp/trace 'autoload)
(putprop 'step '/usr/lib/lisp/step 'autoload)