|
|
1.1 root 1: (setq rcs-toplevel-
2: "$Header: toplevel.l,v 1.6 83/11/18 08:47:24 jkf Exp $")
3:
4: ;;
5: ;; toplevel.l -[Sun Oct 30 08:14:49 1983 by jkf]-
6: ;;
7: ;; toplevel read eval print loop
8: ;;
9:
10:
11: ; special atoms:
12: (declare (special debug-level-count break-level-count
13: errlist tpl-errlist user-top-level
14: franz-not-virgin piport ER%tpl ER%all
15: $ldprint evalhook funcallhook
16: franz-minor-version-number
17: top-level-init
18: top-level-prompt top-level-read
19: top-level-eval top-level-print
20: top-level-eof * ** *** + ++ +++ ^w)
21: (localf autorunlisp cvtsearchpathtolist)
22: (macros t))
23:
24: (setq top-level-eof (gensym 'Q)
25: tpl-errlist nil
26: errlist nil
27: user-top-level nil
28: top-level-init nil
29: top-level-prompt nil
30: top-level-read nil
31: top-level-eval nil
32: top-level-print nil)
33:
34: ;--- initialization, prompt, read, eval, and print functions are
35: ; user-selectable by just assigning another value to top-level-init,
36: ; top-level-prompt, top-level-read, top-level-eval, and top-level-print.
37: ;
38: (defmacro top-init nil
39: '(cond ((and top-level-init
40: (getd top-level-init))
41: (funcall top-level-init))
42: (t (cond ((not (autorunlisp))
43: (patom (status version))
44: ; franz-minor-version-number defined in version.l
45: (cond ((boundp 'franz-minor-version-number)
46: (patom franz-minor-version-number)))
47: (terpr)
48: (read-in-lisprc-file))))))
49:
50: (defmacro top-prompt nil
51: `(cond ((and top-level-prompt
52: (getd top-level-prompt))
53: (funcall top-level-prompt))
54: (t (patom "-> "))))
55:
56: (defmacro top-read (&rest args)
57: `(cond ((and top-level-read
58: (getd top-level-read))
59: (funcall top-level-read ,@args))
60: (t (read ,@args))))
61:
62: (defmacro top-eval (&rest args)
63: `(cond ((and top-level-eval
64: (getd top-level-eval))
65: (funcall top-level-eval ,@args))
66: (t (eval ,@args))))
67:
68: (defmacro top-print (&rest args)
69: `(cond ((and top-level-print
70: (getd top-level-print))
71: (funcall top-level-print ,@args))
72: (t (print ,@args))))
73:
74: ;------------------------------------------------------
75: ; Top level function for franz jkf, march 1980
76: ;
77: ; The following function contains the top-level read, eval, print
78: ; loop. With the help of the error handling functions,
79: ; break-err-handler and debug-err-handler, franz-top-level provides
80: ; a reasonable enviroment for working with franz lisp.
81: ;
82:
83: (def franz-top-level
84: (lambda nil
85: (putd 'reset (getd 'franz-reset))
86: (username-to-dir-flush-cache) ; clear tilde expansion knowledge
87: (cond ((or (not (boundp 'franz-not-virgin))
88: (null franz-not-virgin))
89: (setq franz-not-virgin t
90: + nil ++ nil +++ nil
91: * nil ** nil *** nil)
92: (setq ER%tpl 'break-err-handler)
93: (top-init)))
94:
95: ; loop forever
96: (do ((+*) (-) (retval))
97: (nil)
98: (setq retval
99: (*catch
100: '(top-level-catch break-catch)
101: ; begin or return to top level
102: (progn
103: (setq debug-level-count 0 break-level-count 0
104: evalhook nil funcallhook nil)
105: (cond (tpl-errlist (mapc 'eval tpl-errlist)))
106: (do ((^w nil nil))
107: (nil)
108: (cond (user-top-level (funcall user-top-level))
109: (t (top-prompt)
110: (cond ((eq top-level-eof
111: (setq -
112: (car (errset (top-read nil
113: top-level-eof)))))
114: (cond ((not (status isatty))
115: (exit)))
116: (cond ((null (status ignoreeof))
117: (terpr)
118: (print 'Goodbye)
119: (terpr)
120: (exit))
121: (t (terpr)
122: (setq - ''EOF)))))
123: (setq +* (top-eval -))
124: ; update list of old forms
125: (let ((val -))
126: (let ((o+ +) (o++ ++))
127: (setq + val
128: ++ o+
129: +++ o++)))
130: ; update list of old values
131: (let ((val +*))
132: (let ((o* *) (o** **))
133: (setq * val
134: ** o*
135: *** o**)))
136: (top-print +*)
137: (terpr)))))))
138: (terpr)
139: (patom "[Return to top level]")
140: (terpr)
141: (cond ((eq 'reset retval) (old-reset-function))))))
142:
143:
144:
145:
146:
147: ; debug-err-handler is the clb of ER%all when we are doing debugging
148: ; and we want to catch all errors.
149: ; It is just a read eval print loop with errset.
150: ; the only way to leave is:
151: ; (reset) just back to top level
152: ; (return x) return the value to the error checker.
153: ; if nil is returned then we will continue as if the error
154: ; didn't occur. Otherwise if the returned value is a list,
155: ; then if the error is continuable, the car of that list
156: ; will be returned to recontinue computation.
157: ; ^D continue as if this handler wasn't called.
158: ; the form of errmsgs is:
159: ; (error_type unique_id continuable message_string other_args ...)
160: ;
161: (def debug-err-handler
162: (lexpr (n)
163: ((lambda (message debug-level-count retval ^w piport)
164: (cond ((greaterp n 0)
165: (print 'Error:)
166: (mapc '(lambda (a) (patom " ") (patom a) )
167: (cdddr (arg 1)))
168: (terpr)))
169: (setq ER%all 'debug-err-handler)
170: (do ((retval)) (nil)
171: (cond ((dtpr
172: (setq retval
173: (errset
174: (do ((form)) (nil)
175: (patom "D<")
176: (patom debug-level-count)
177: (patom ">: ")
178: (cond ((eq top-level-eof
179: (setq form
180: (top-read nil
181: top-level-eof)))
182: (cond ((null (status isatty))
183: (exit)))
184: (return nil))
185: ((and (dtpr form)
186: (eq 'return
187: (car form)))
188: (return (eval (cadr form))))
189: (t (setq form (top-eval form))
190: (top-print form)
191: (terpr)))))))
192: (return (car retval))))))
193: nil
194: (add1 debug-level-count)
195: nil
196: nil
197: nil)))
198:
199: ; this is the break handler, it should be tied to
200: ; ER%tpl always.
201: ; it is entered if there is an error which no one wants to handle.
202: ; We loop forever, printing out our error level until someone
203: ; types a ^D which goes to the next break level above us (or the
204: ; top-level if there are no break levels above us.
205: ; a (return n) will return that value to the error message
206: ; which called us, if that is possible (that is if the error is
207: ; continuable)
208: ;
209: (def break-err-handler
210: (lexpr (n)
211: ((lambda (message break-level-count retval rettype ^w piport)
212: (cond ((greaterp n 0)
213: (print 'Error:)
214: (mapc '(lambda (a) (patom " ") (patom a) )
215: (cdddr (arg 1)))
216: (terpr)
217: (cond ((caddr (arg 1)) (setq rettype 'contuab))
218: (t (setq rettype nil))))
219: (t (setq rettype 'localcall)))
220:
221: (do nil (nil)
222: (cond ((dtpr
223: (setq retval
224: (*catch 'break-catch
225: (do ((form)) (nil)
226: (patom "<")
227: (patom break-level-count)
228: (patom ">: ")
229: (cond ((eq top-level-eof
230: (setq form
231: (top-read
232: nil
233: top-level-eof)))
234: (cond ((null (status isatty))
235: (exit)))
236: (eval 1) ; force interrupt check
237: (return (sub1 break-level-count)))
238: ((and (dtpr form)
239: (eq 'return (car form)))
240: (cond ((or (eq rettype 'contuab)
241: (eq rettype 'localcall))
242: (return (ncons (top-eval (cadr form)))))
243: (t (patom "Can't continue from this error")
244: (terpr))))
245: ((and (dtpr form) (eq 'retbrk (car form)))
246: (cond ((numberp (setq form (top-eval (cadr form))))
247: (return form))
248: (t (return (sub1 break-level-count)))))
249: (t (setq form (top-eval form))
250: (top-print form)
251: (terpr)))))))
252: (return (cond ((eq rettype 'localcall)
253: (car retval))
254: (t retval))))
255: ((lessp retval break-level-count)
256: (setq tpl-errlist errlist)
257: (*throw 'break-catch retval))
258: (t (terpr)))))
259: nil
260: (add1 break-level-count)
261: nil
262: nil
263: nil
264: nil)))
265:
266: (defvar debug-error-handler 'debug-err-handler) ; name of function to get
267: ; control on ER%all error
268: (def debugging
269: (lambda (val)
270: (cond (val (setq ER%all debug-error-handler)
271: (sstatus translink nil)
272: (*rset t))
273: (t (setq ER%all nil)))))
274:
275:
276: ; the problem with this definition for break is that we are
277: ; forced to put an errset around the break-err-handler. This means
278: ; that we will never get break errors, since all errors will be
279: ; caught by our errset (better ours than one higher up though).
280: ; perhaps the solution is to automatically turn debugmode on.
281: ;
282: (defmacro break (message &optional (pred t))
283: `(*break ,pred ',message))
284:
285: (def *break
286: (lambda (pred message)
287: (let ((^w nil))
288: (cond ((not (boundp 'break-level-count)) (setq break-level-count 1)))
289: (cond (pred (terpr)
290: (patom "Break ")
291: (patom message)
292: (terpr)
293: (do ((form))
294: (nil)
295: (cond ((dtpr (setq form (errset (break-err-handler))))
296: (return (car form))))))))))
297:
298:
299: ; this reset function is designed to work with the franz-top-level.
300: ; When franz-top-level begins, it makes franz-reset be reset.
301: ; when a reset occurs now, we set the global variable tpl-errlist to
302: ; the current value of errlist and throw to top level. At top level,
303: ; then tpl-errlist will be evaluated.
304: ;
305: (def franz-reset
306: (lambda nil
307: (setq tpl-errlist errlist)
308: (errset (*throw 'top-level-catch 'reset)
309: nil)
310: (old-reset-function)))
311:
312:
313: (declare (special $ldprint))
314:
315: ;--- read-in-lisprc-file
316: ; search for a lisp init file. Look first in . then in $HOME
317: ; look first for .o , then .l and then "",
318: ; look for file bodies .lisprc and then lisprc
319: ;
320: (def read-in-lisprc-file
321: (lambda nil
322: (setq break-level-count 0 ; do this in case break
323: debug-level-count 0) ; occurs during readin
324: (*catch '(break-catch top-level-catch)
325: (do ((dirs `("." ,(getenv 'HOME)) (cdr dirs))
326: ($ldprint nil $ldprint)) ; prevent messages
327: ((null dirs))
328: (cond ((do ((name '(".lisprc" "lisprc") (cdr name)))
329: ((null name))
330: (cond ((do ((ext '(".o" ".l" "") (cdr ext))
331: (file))
332: ((null ext))
333: (cond ((probef
334: (setq file
335: (concat (car dirs)
336: "/"
337: (car name)
338: (car ext))))
339: (cond ((atom (errset (load file)))
340: (patom
341: "Error loading lisp init file ")
342: (print file)
343: (terpr)
344: (return 'error)))
345: (return t))))
346: (return t))))
347: (return t)))))))
348:
349: (putd 'top-level (getd 'franz-top-level))
350:
351: ; if this is the first time this file has been read in, then
352: ; make franz-reset be the reset function, but remember the original
353: ; reset function as old-reset-function. We need the old reset function
354: ; if we are going to allow the user to change top-levels, for in
355: ; order to do that we really have to jump all the way up to the top.
356: (cond ((null (getd 'old-reset-function))
357: (putd 'old-reset-function (getd 'reset))))
358:
359:
360: ;---- autoloader functions
361:
362: (def undef-func-handler
363: (lambda (args)
364: (prog (funcnam file)
365: (setq funcnam (caddddr args))
366: (cond ((symbolp funcnam)
367: (cond ((setq file (or (get funcnam 'autoload)
368: (get funcnam 'macro-autoload)))
369: (cond ($ldprint
370: (patom "[autoload ") (patom file)
371: (patom "]")(terpr)))
372: (load file))
373: (t (return nil)))
374: (cond ((getd funcnam) (return (ncons funcnam)))
375: (t (patom "Autoload file " ) (print file)
376: (patom " does not contain function ")
377: (print funcnam)
378: (terpr)
379: (return nil))))))))
380:
381: (setq ER%undef 'undef-func-handler)
382:
383: (declare (special $ldprint))
384: ;--- autorunlisp :: check if this lisp is supposed to run a program right
385: ; away.
386: ;
387: (defun autorunlisp nil
388: (cond ((and (> (argv -1) 2) (equal (argv 1) '-f))
389: (let ((progname (argv 2))
390: ($ldprint nil)
391: (searchlist nil)) ; don't give fasl messages
392: (setq searchlist (cvtsearchpathtolist (getenv 'PATH)))
393: ; give two args to load to insure that a fasl is done.
394: (cond ((null
395: (errset (load-autorunobject progname searchlist)))
396: (exit 0))
397: (t t))))))
398:
399:
400: (defun cvtsearchpathtolist (path)
401: (do ((x (explodec path) (cdr x))
402: (names nil)
403: (cur nil))
404: ((null x)
405: (nreverse names))
406: (cond ((or (eq ': (car x))
407: (and (null (cdr x)) (setq cur (cons (car x) cur))))
408: (cond (cur (setq names (cons (implode (nreverse cur))
409: names))
410: (setq cur nil))
411: (t (setq names (cons '|.| names)))))
412: (t (setq cur (cons (car x) cur))))))
413:
414: (defun load-autorunobject (name search)
415: (cond ((memq (getchar name 1) '(/ |.|))
416: (cond ((probef name) (fasl name))
417: (t (error "From lisp autorun: can't find file to load"))))
418: (t (do ((xx search (cdr xx))
419: (fullname))
420: ((null xx) (error "Can't find file to execute "))
421: (cond ((probef (setq fullname (concat (car xx) "/" name)))
422: (return (fasl-a-file fullname nil nil))))))))
423:
424: ;--- command-line-args :: return a list of the command line arguments
425: ; The list does not include the name of the program being executed (argv 0).
426: ; It also doesn't include the autorun flag and arg.
427: ;
428: (defun command-line-args ()
429: (do ((res nil (cons (argv i) res))
430: (i (1- (argv -1)) (1- i)))
431: ((<& i 1)
432: (if (and (eq '-f (car res))
433: (cdr res))
434: then (cddr res)
435: else res))))
436:
437: (defun debug fexpr (args)
438: (load 'fix) ; load in fix package
439: (eval (cons 'debug args))) ; enter debug through eval
440:
441: ;-- default autoloader properties
442:
443: (putprop 'trace (concat lisp-library-directory "/trace") 'autoload)
444: (putprop 'untrace (concat lisp-library-directory "/trace") 'autoload)
445:
446: (putprop 'step (concat lisp-library-directory "/step") 'autoload)
447: (putprop 'editf (concat lisp-library-directory "/cmuedit") 'autoload)
448: (putprop 'editv (concat lisp-library-directory "/cmuedit") 'autoload)
449: (putprop 'editp (concat lisp-library-directory "/cmuedit") 'autoload)
450: (putprop 'edite (concat lisp-library-directory "/cmuedit") 'autoload)
451:
452: (putprop 'defstruct (concat lisp-library-directory "/struct") 'macro-autoload)
453: (putprop 'defstruct-expand-ref-macro
454: (concat lisp-library-directory "/struct") 'autoload)
455: (putprop 'defstruct-expand-cons-macro
456: (concat lisp-library-directory "/struct") 'autoload)
457: (putprop 'defstruct-expand-alter-macro
458: (concat lisp-library-directory "/struct") 'autoload)
459:
460: (putprop 'loop (concat lisp-library-directory "/loop") 'macro-autoload)
461: (putprop 'defflavor
462: (concat lisp-library-directory "/flavors") 'macro-autoload)
463: (putprop 'defflavor1
464: (concat lisp-library-directory "/flavors") 'autoload)
465:
466: (putprop 'format (concat lisp-library-directory "/format") 'autoload)
467: (putprop 'ferror (concat lisp-library-directory "/format") 'autoload)
468:
469: (putprop 'make-hash-table
470: (concat lisp-library-directory "/hash") 'autoload)
471: (putprop 'make-equal-hash-table
472: (concat lisp-library-directory "/hash") 'autoload)
473:
474: (putprop 'describe (concat lisp-library-directory "/describe") 'autoload)
475:
476: (putprop 'cgol (concat lisp-library-directory "/cgol/cgoll") 'autoload)
477: (putprop 'cgolprint (concat lisp-library-directory "/cgol/cgp") 'autoload)
478:
479: ; probably should be in franz so we don't have to autoload
480: (putprop 'displace (concat lisp-library-directory "/machacks") 'autoload)
481:
482: (putprop 'defrecord (concat lisp-library-directory "/record") 'macro-autoload)
483: (putprop 'record-pkg-construct
484: (concat lisp-library-directory "/record") 'autoload)
485: (putprop 'record-pkg-access
486: (concat lisp-library-directory "/record") 'autoload)
487: (putprop 'record-pkg-illegal-access
488: (concat lisp-library-directory "/record") 'autoload)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.