BSD 4_1_snap release
[unix-history] / usr / lib / lisp / toplevel.l
CommitLineData
4b9ccde7
C
1(setq SCCS-toplevel "@(#)toplevel.l 1.5 7/9/81")
2; vi: set lisp :
31cef89c
BJ
3
4; special atoms:
5(declare (special debug-level-count break-level-count
6 errlist tpl-errlist user-top-level
7 franz-not-virgin piport ER%tpl ER%all
4b9ccde7 8 $ldprint evalhook funcallhook
31cef89c
BJ
9 top-level-eof * ** *** + ++ +++ ^w)
10 (macros t))
11
12(setq top-level-eof (gensym 'Q)
13 tpl-errlist nil
14 errlist nil
15 user-top-level nil )
16
17;------------------------------------------------------
18; Top level function for franz jkf, march 1980
19;
20; The following function contains the top-level read, eval, print
21; loop. With the help of the error handling functions,
22; break-err-handler and debug-err-handler, franz-top-level provides
23; a reasonable enviroment for working with franz lisp.
24;
25
26(def franz-top-level
27 (lambda nil
28 (cond ((or (not (boundp 'franz-not-virgin))
29 (null franz-not-virgin))
31cef89c
BJ
30 (setq franz-not-virgin t
31 + nil ++ nil +++ nil
32 * nil ** nil *** nil)
33 (setq ER%tpl 'break-err-handler)
34 (putd 'reset (getd 'franz-reset))
4b9ccde7
C
35 (cond ((not (autorunlisp))
36 (patom (status version))
37 (terpr)
38 (read-in-lisprc-file)))))
31cef89c
BJ
39
40 ; loop forever
41 (do ((+*) (-) (retval))
42 (nil)
43 (setq retval
44 (*catch
45 '(top-level-catch break-catch)
46 ; begin or return to top level
47 (progn
4b9ccde7
C
48 (setq debug-level-count 0 break-level-count 0
49 evalhook nil funcallhook nil)
31cef89c
BJ
50 (cond (tpl-errlist (mapc 'eval tpl-errlist)))
51 (do ((^w nil nil))
52 (nil)
53 (cond (user-top-level (funcall user-top-level))
54 (t (patom "-> ")
55 (cond ((eq top-level-eof
56 (setq -
57 (car (errset (read nil
58 top-level-eof)))))
59 (cond ((not (status isatty))
60 (exit)))
61 (cond ((null (status ignoreeof))
62 (terpr)
63 (print 'Goodbye)
64 (terpr)
65 (exit))
66 (t (terpr)
67 (setq - ''EOF)))))
68 (setq +* (eval -))
4b9ccde7
C
69 ; update list of old forms
70 (let ((val -))
71 (let ((o+ +) (o++ ++))
72 (setq + val
73 ++ o+
74 +++ o++)))
75 ; update list of old values
76 (let ((val +*))
77 (let ((o* *) (o** **))
78 (setq * val
79 ** o*
80 *** o**)))
31cef89c
BJ
81 (print +*)
82 (terpr)))))))
83 (terpr)
84 (patom "[Return to top level]")
85 (terpr)
86 (cond ((eq 'reset retval) (old-reset-function))))))
87
31cef89c
BJ
88
89
90
91\f
92; debug-err-handler is the clb of ER%all when we are doing debugging
93; and we want to catch all errors.
94; It is just a read eval print loop with errset.
95; the only way to leave is:
96; (reset) just back to top level
97; (return x) return the value to the error checker.
98; if nil is returned then we will continue as if the error
99; didn't occur. Otherwise if the returned value is a list,
100; then if the error is continuable, the car of that list
101; will be returned to recontinue computation.
102; ^D continue as if this handler wasn't called.
103; the form of errmsgs is:
104; (error_type unique_id continuable message_string other_args ...)
105;
106(def debug-err-handler
107 (lexpr (n)
4b9ccde7
C
108 ((lambda (message debug-level-count retval ^w piport
109 evalhook funcallhook)
31cef89c
BJ
110 (cond ((greaterp n 0)
111 (print 'Error:)
112 (mapc '(lambda (a) (patom " ") (patom a) )
113 (cdddr (arg 1)))
114 (terpr)))
115 (setq ER%all 'debug-err-handler)
116 (do (retval) (nil)
117 (cond ((dtpr
118 (setq retval
119 (errset
120 (do ((form)) (nil)
121 (patom "D<")
122 (patom debug-level-count)
123 (patom ">: ")
124 (cond ((eq top-level-eof
125 (setq form
126 (read nil top-level-eof)))
127 (cond ((null (status isatty))
128 (exit)))
129 (return nil))
130 ((and (dtpr form)
131 (eq 'return (car form)))
132 (return (eval (cadr form))))
133 (t (print (eval form))
134 (terpr)))))))
135 (return (car retval))))))
136 nil
137 (add1 debug-level-count)
138 nil
4b9ccde7
C
139 nil
140 nil
141 nil
31cef89c
BJ
142 nil)))
143\f
144; this is the break handler, it should be tied to
145; ER%tpl always.
146; it is entered if there is an error which no one wants to handle.
147; We loop forever, printing out our error level until someone
148; types a ^D which goes to the next break level above us (or the
149; top-level if there are no break levels above us.
150; a (return n) will return that value to the error message
151; which called us, if that is possible (that is if the error is
152; continuable)
153;
154(def break-err-handler
155 (lexpr (n)
4b9ccde7
C
156 ((lambda (message break-level-count retval rettype ^w piport
157 evalhook funcallhook)
31cef89c
BJ
158 (cond ((greaterp n 0)
159 (print 'Error:)
160 (mapc '(lambda (a) (patom " ") (patom a) )
161 (cdddr (arg 1)))
162 (terpr)
163 (cond ((caddr (arg 1)) (setq rettype 'contuab))
164 (t (setq rettype nil))))
165 (t (setq rettype 'localcall)))
166
167 (do nil (nil)
168 (cond ((dtpr
169 (setq retval
170 (*catch 'break-catch
171 (do ((form)) (nil)
172 (patom "<")
173 (patom break-level-count)
174 (patom ">: ")
175 (cond ((eq top-level-eof
176 (setq form (read nil top-level-eof)))
177 (cond ((null (status isatty))
178 (exit)))
179 (eval 1) ; force interrupt check
180 (return (sub1 break-level-count)))
181 ((and (dtpr form) (eq 'return (car form)))
182 (cond ((or (eq rettype 'contuab)
183 (eq rettype 'localcall))
184 (return (ncons (eval (cadr form)))))
185 (t (patom "Can't continue from this error")
186 (terpr))))
187 ((and (dtpr form) (eq 'retbrk (car form)))
188 (cond ((numberp (setq form (eval (cadr form))))
189 (return form))
190 (t (return (sub1 break-level-count)))))
191 (t (print (eval form))
192 (terpr)))))))
193 (return (cond ((eq rettype 'localcall)
194 (car retval))
195 (t retval))))
196 ((lessp retval break-level-count)
197 (setq tpl-errlist errlist)
198 (*throw 'break-catch retval))
199 (t (terpr)))))
200 nil
201 (add1 break-level-count)
202 nil
203 nil
4b9ccde7
C
204 nil
205 nil
206 nil
31cef89c
BJ
207 nil)))
208\f
209(def debugging
210 (lambda (val)
4b9ccde7
C
211 (cond (val (setq ER%all 'debug-err-handler)
212 (*rset t))
31cef89c
BJ
213 (t (setq ER%all nil)))))
214
215
216; the problem with this definition for break is that we are
217; forced to put an errset around the break-err-handler. This means
218; that we will never get break errors, since all errors will be
219; caught by our errset (better ours than one higher up though).
220; perhaps the solution is to automatically turn debugmode on.
221;
222(defmacro break (message &optional (pred t))
223 `(*break ,pred ',message))
224
225(def *break
226 (lambda (pred message)
227 (let ((^w nil))
228 (cond ((not (boundp 'break-level-count)) (setq break-level-count 1)))
229 (cond (pred (terpr)
230 (patom "Break ")
231 (patom message)
232 (terpr)
233 (do ((form))
234 (nil)
235 (cond ((dtpr (setq form (errset (break-err-handler))))
236 (return (car form))))))))))
237
238
239; this reset function is designed to work with the franz-top-level.
240; When franz-top-level begins, it makes franz-reset be reset.
241; when a reset occurs now, we set the global variable tpl-errlist to
242; the current value of errlist and throw to top level. At top level,
243; then tpl-errlist will be evaluated.
244;
245(def franz-reset
246 (lambda nil
247 (setq tpl-errlist errlist)
248 (errset (*throw 'top-level-catch 'reset)
249 nil)
250 (old-reset-function)))
251
252
253; this definition will have to do until we have the ability to
254; cause and error on any channel in franz
255(def error
256 (lexpr (n)
257 (cond ((greaterp n 0)
258 (patom (arg 1))
259
260 (cond ((greaterp n 1)
261 (patom " ")
262 (patom (arg 2))))
263 (terpr)))
264 (err)))
265
266
267; this file is read in just before dumplisping if you want .lisprc
268; from your home directory read in before the lisp begins.
269(def read-in-lisprc-file
270 (lambda nil
271 ((lambda (hom prt)
272 (setq break-level-count 0 ; do this in case break
273 debug-level-count 0) ; occurs during readin
274 (*catch '(break-catch top-level-catch)
275 (cond (hom
276 (cond ((and
277 (errset
278 (progn
279 (setq prt (infile (concat hom '"/.lisprc")))
280 (close prt))
281 nil)
282 (null (errset
283 (load (concat hom '"/.lisprc")))))
284 (patom '"Error in .lisprc file detected")
285 (terpr)))))))
286 (getenv 'HOME) nil)))
287
288(putd 'top-level (getd 'franz-top-level))
289
290; if this is the first time this file has been read in, then
291; make franz-reset be the reset function, but remember the original
292; reset function as old-reset-function. We need the old reset function
293; if we are going to allow the user to change top-levels, for in
294; order to do that we really have to jump all the way up to the top.
295(cond ((null (getd 'old-reset-function))
296 (putd 'old-reset-function (getd 'reset))))
297
298
299;---- autoloader functions
300
301(def undef-func-handler
302 (lambda (args)
303 (prog (funcnam file)
304 (setq funcnam (caddddr args))
305 (cond ((symbolp funcnam)
306 (cond ((setq file (get funcnam 'autoload))
4b9ccde7
C
307 (cond ($ldprint
308 (patom "[autoload ") (patom file)
309 (patom "]")(terpr)))
31cef89c
BJ
310 (load file))
311 (t (return nil)))
312 (cond ((getd funcnam) (return (ncons funcnam)))
313 (t (patom "Autoload file does not contain func ")
314 (return nil))))))))
315
316(setq ER%undef 'undef-func-handler)
317
4b9ccde7
C
318(declare (special $ldprint))
319;--- autorunlisp :: check if this lisp is supposed to run a program right
320; away.
321;
322(defun autorunlisp nil
323 (cond ((and (> (argv -1) 2) (equal (argv 1) '-f))
324 (let ((progname (argv 2))
325 ($ldprint nil)
326 (searchlist nil)) ; don't give fasl messages
327 (setq searchlist (cvtsearchpathtolist (getenv 'PATH)))
328 ; give two args to load to insure that a fasl is done.
329 (cond ((null
330 (errset (load-autorunobject progname searchlist)))
331 (exit 0))
332 (t t))))))
333
334
335(defun cvtsearchpathtolist (path)
336 (do ((x (explodec path) (cdr x))
337 (names nil)
338 (cur nil))
339 ((null x)
340 (nreverse names))
341 (cond ((or (eq ': (car x))
342 (and (null (cdr x)) (setq cur (cons (car x) cur))))
343 (cond (cur (setq names (cons (implode (nreverse cur))
344 names))
345 (setq cur nil))
346 (t (setq names (cons '|.| names)))))
347 (t (setq cur (cons (car x) cur))))))
348
349(defun load-autorunobject (name search)
350 (cond ((memq (getchar name 1) '(/ |.|))
351 (cond ((probef name) (fasl name))
352 (t (error "From lisp autorun: can't find file to load"))))
353 (t (do ((xx search (cdr xx))
354 (fullname))
355 ((null xx) (error "Can't find file to execute "))
356 (cond ((probef (setq fullname (concat (car xx) "/" name)))
357 (return (fasl fullname))))))))
358
359(defun debug fexpr (args)
360 (load 'fix) ; load in fix package
361 (eval (cons 'debug args))) ; enter debug through eval
362
31cef89c
BJ
363;-- default autoloader properties
364
365(putprop 'trace '/usr/lib/lisp/trace 'autoload)
4b9ccde7 366(putprop 'step '/usr/lib/lisp/step 'autoload)