Commit | Line | Data |
---|---|---|
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) |