|
|
1.1 root 1: (setq rcs-tpl-
2: "$Header: tpl.l,v 1.4 83/09/04 10:20:03 jkf Exp $")
3:
4: ; -[Sun Sep 4 10:18:42 1983 by jkf]-
5: ;
6:
7: ; to do
8: ; ?state : display status translink, *rset, displace-macros.
9: ; current error, prinlevel and prinlength
10: ; add a way of modifying the values
11: ; ?bk [n] : do a baktrace (default 10 frames from bottom)
12: ; ?zo [n] : add an optional number of frames to zoom
13: ; ?retf : return value from 'current' frame
14: ; ?retry : retry expr in 'current' frame (required mod to lisp).
15: ;
16: ; the frame re-eval question is not asked when it should.
17: ; interact with tracebreaks correctly
18: ;
19: ; add stepper.
20: ; get 'debugging' to work ok.
21:
22: ;--- state
23: ;
24: (declare (special tpl-debug-on tpl-step-on
25: tpl-top-framelist tpl-bot-framelist
26: tpl-eval-flush tpl-trace-flush
27: tpl-prinlength tpl-prinlevel
28: prinlevel prinlength
29: tpl-commands tpl-break-level
30: tpl-spec-char
31: tpl-last-loaded
32: tpl-level
33: tpl-fcn-in-eval
34: tpl-contuab
35: ER%tpl ER%all given-history res-history
36: tpl-stack-bad tpl-stack-ok
37: tpl-history-count
38: tpl-history-show
39: tpl-dontshow-tpl
40: tpl-step-enable ;; if stepping is on
41: tpl-step-print ;; if should print step forms
42: tpl-step-triggers ;; list of fcns to enable step
43: tpl-step-countdown ;; if positive, then don't break
44: tpl-step-reclevel ;; recursion level
45: evalhook funcallhook
46: *rset % piport
47: debug-error-handler
48: ))
49:
50: (putd 'tpl-eval (getd 'eval))
51: (putd 'tpl-funcall (getd 'funcall))
52: (putd 'tpl-evalhook (getd 'evalhook))
53: (putd 'tpl-funcallhook (getd 'funcallhook))
54:
55:
56: ;--- macros which should be in the system
57: ;
58: (defmacro evalframe-type (evf) `(car ,evf))
59: (defmacro evalframe-pdl (evf) `(cadr ,evf))
60: (defmacro evalframe-expr (evf) `(caddr ,evf))
61: (defmacro evalframe-bind (evf) `(cadddr ,evf))
62: (defmacro evalframe-np (evf) `(caddddr ,evf))
63: (defmacro evalframe-lbot (evf) `(cadddddr ,evf))
64:
65:
66: ;; messages are passed between break levels by means of catch and
67: ;; throw:
68: (defmacro tpl-throw (value) `(*throw 'tpl-break-catch ,value))
69: (defmacro tpl-catch (form) `(*catch 'tpl-break-catch ,form))
70:
71: ; A tpl-catch is placed around the prompting and evaluation of forms.
72: ; if something abnormal happens in the evaluation, a tpl-throw is done
73: ; which then tells the break look that something special should be
74: ; done.
75: ;
76: ; messages:
77: ; contbreak - this tells the break level to print out the message
78: ; it prints when it is entered (such as the error message).
79: ; [see poplevel message].
80: ; poplevel - tells the break level to jump up to the next higher
81: ; break level and continue there. It sends contbreak
82: ; message to that break level so that it will remind the
83: ; user what the state is. [see cmd: ?pop ]
84: ; reset - This tells the break level to send a reset to the next
85: ; higher break level. Thus a reset is done by successive
86: ; small pops. This isn't totally necessary, but it is
87: ; clean.
88: ; (retbreak v) - return from the break level, returning the value v.
89: ; If this an error break, then we return (list v) since
90: ; that is required to indicate that an error has been
91: ; handled.
92: ; (retry v) - instead of asking for a new value, retry the given one.
93: ; popretry - take the expression that caused the current break and
94: ; send a (retry expr) message to the break level above us
95: ; so that it can be tried again.
96:
97: (setq tpl-eval-flush nil tpl-trace-flush nil
98: tpl-prinlevel 3 tpl-prinlength 4
99: tpl-spec-char #/?)
100:
101: (or (boundp 'tpl-last-loaded) (setq tpl-last-loaded nil))
102:
103: (defun tpl nil
104: (let ((debug-error-handler 'tpl-err-all-fcn))
105: (setq ER%tpl 'tpl-err-tpl-fcn)
106: (putd '*break (getd 'tpl-*break))
107: (setq given-history nil
108: res-history nil
109: tpl-debug-on nil
110: tpl-step-on nil
111: tpl-top-framelist nil
112: tpl-bot-framelist nil
113: tpl-stack-bad t
114: tpl-stack-ok nil
115: tpl-fcn-in-eval nil
116: tpl-level nil
117: tpl-history-count 0
118: tpl-break-level -1
119: tpl-dontshow-tpl t
120: tpl-history-show 10
121: tpl-step-enable nil
122: tpl-step-countdown 0
123: tpl-step-reclevel 0)
124: (do ((retv))
125: (nil)
126: (setq retv
127: (tpl-catch
128: (tpl-break-function nil))))))
129:
130:
131: ;--- do-one-transaction
132: ; do a single read-eval-print transaction
133: ; If eof-form is given, then we provide a prompt and read the input,
134: ; otherwise given is what we use, but we print the prompt and the
135: ; given input before evaling it again.
136: ; (given must be in the form (sys|user ..)
137: ;
138: (defun do-one-transaction (given prompt eof-form)
139: (let (retv)
140: (patom prompt)
141: (If eof-form
142: then (setq given
143: (car (errset (ntpl-read nil eof-form))))
144: (If (eq eof-form given)
145: then (If (status isatty)
146: then (msg "EOF" N)
147: (setq given '(sys <eof>))
148: else (exit)))
149: else (tpl-history-form-print given)
150: (terpr))
151: (add-to-given-history given)
152: (If (eq 'user (car given))
153: then (setq tpl-stack-bad t)
154: (setq retv
155: (if tpl-step-enable
156: then (tpl-evalhook (cdr given)
157: 'tpl-do-evalhook
158: 'tpl-do-funcallhook)
159: else (tpl-eval (cdr given))))
160: (setq tpl-stack-bad t)
161: else (setq retv (process-fcn (cdr given)))
162: (setq tpl-stack-bad (not tpl-stack-ok)))
163: (add-to-res-history retv)
164: (ntpl-print retv)
165: (terpr)
166: ))
167:
168:
169: ;; reader
170: ; if sees a rpar as the first non space char, it just reads all chars
171: ; return (sys . form) where form is a list, e.g
172: ; )foo bar baz rets (sys foo bar baz)
173: ; or
174: ; (user . form)
175: ; note: if nothing is typed, (sys) is returned
176: ;
177: (defun ntpl-read (port eof-form)
178: (let (ch)
179: ; skip all spaces
180: (do ()
181: ((and (not (eq (setq ch (tyipeek port)) #\space))
182: (not (eq ch #\newline))))
183: (setq ch (tyi)))
184: (If (eq ch #\eof)
185: then eof-form
186: else (setq ch (tyi port))
187: (If (eq ch tpl-spec-char)
188: then (do ((xx (list #\lpar) (cons (tyi) xx)))
189: ((or (eq #\eof (car xx))
190: (eq #\newline (car xx)))
191: (cons 'sys
192: (car (errset
193: (readlist
194: (nreverse
195: (cons #\rpar (cdr xx)))))))))
196: else (untyi ch)
197: (cons 'user (read port eof-form))))))
198:
199: ;--- tpl-history-form-print :: the inverse of tpl-read
200: ; this takes the history form of an expression and prints it out
201: ; just as the user would have typed it.
202: ;
203: (defun tpl-history-form-print (form)
204: (If (eq 'user (car form))
205: then (print (cdr form))
206: else (patom "?")
207: (mapc '(lambda (x) (print x) (patom " ")) (cdr form))))
208:
209: (defun ntpl-print (form)
210: (print form))
211:
212: (setq tpl-commands
213: '( ((help h) tpl-command-help
214: " [cmd] - print general or specific info "
215: " '?help' - print a short description of all commands "
216: " '?help cmd' - print extended information on the given command ")
217: ( ? tpl-command-redo
218: " [args] - redo last or previous command "
219: " '??' - redo last user command "
220: " '?? n' - (for n>0) redo command #n (as printed by ?history)"
221: " '?? -n' - (for n>0) redo n'th previous command (?? -1 == ??)"
222: " '?? symb' - redo last with car == symb"
223: " '?? symb *' - redo last with car == symb*")
224: ( (his history) tpl-command-history
225: " [r] - print history list "
226: " ?history, ?his - print list of commands previously executed"
227: " '?his r' - print results too")
228: ( (re reset) tpl-command-reset
229: " - pop up to the top level"
230: " '?re, ?reset', pop up to the top level ")
231: ( tr tpl-command-trace
232: " [fn ..] - trace"
233: " '?tr' - print list of traced functions"
234: " '?tr fn ...' - trace given functions, can be fn or (fn cmd ...)"
235: " where cmds are trace commands")
236: ( step tpl-command-step
237: " [t] [funa funb ...] step always or when specific function hit"
238: " '?step t' - step starting right away "
239: " '?step funa funb' - step when either funa or funb to be called ")
240: ( soff tpl-command-stepoff
241: " - turn off stepping "
242: " '?soff' - turn off stepping ")
243: ( sc tpl-command-sc
244: " [n] - continue stepping [don't break for n steps] "
245: " '?sc' - do one step then break "
246: " '?sc n' - step for n steps before breaking "
247: " if n is a non integer (e.g. inf) then "
248: " step forever without breaking ")
249: ( state tpl-command-state
250: " [vals] - print or change state "
251: " 'state' - print current state in short form "
252: " 'state l' - print state in long form"
253: " 'state sym val ... ...' - set values of state "
254: " symbols are those given in 'state l' list")
255: ( prt tpl-command-prt
256: " - pop up a level and retry the command which caused this break"
257: " ?prt - do a ?pop followed by a retry of the command which"
258: " caused this break to be entered")
259: ( ld tpl-command-load
260: " [file ...] - load given or last files"
261: " 'ld' - loads the last files loaded with ?ld"
262: " 'ld file ...' - loads the given files")
263: ( debug tpl-command-debug
264: " [off] - toggle debug state "
265: " 'debug' Turns on debugging. When debug is on then"
266: " enough information is kept around for viewing"
267: " and quering evaluation stack"
268: " 'debug off' - Turns off debuging" )
269: ( pop tpl-command-pop
270: " - pop up to previous break level"
271: " 'pop' - if not at top level, pop up to the break level"
272: " above this one")
273: ( ret tpl-command-ret
274: " [val] - return value from this break loop "
275: " 'ret [val]' if this is a break look due to a break command "
276: " or a continuable error, evaluate val (default nil)"
277: " and return it to the function that found an error,"
278: " allowing it to continue")
279:
280: ( zo tpl-command-zoom
281: " - view a portion of evaluation stack"
282: " 'zo' - show a portion above and below the 'current' stack"
283: " frame. Use )up and )dn or alter current stack frame")
284: ( dn tpl-command-down
285: " [n] - go down stack frames "
286: " 'dn' - move the current stack frame down one. Down refers to"
287: " older stack frames"
288: " 'dn n' - n is a fixnum telling how many stack frames to go down"
289: " 'dn n z' - after going down, do a zoom"
290: " After dn is done, a limited zoom will be done")
291: ( up tpl-command-up
292: " [n] - go up stack frames "
293: " 'up' - move the current stack frame up one. Up refers to"
294: " younger stack frames"
295: " 'up n' - n is a fixnum telling how many stack frames to go up")
296: ( ev tpl-command-ev
297: " symbol - eval the given symbol wrt the current frame "
298: " 'ev symbol' - determine the value of the given symbol"
299: " after restoring the bindings to the way they were"
300: " when the current frame was current. see ?zo,?up,?dn")
301: ( pp tpl-command-pp
302: " - pretty print the current frame "
303: " 'pp' - pretty print the current frame (see ?zo, ?up, ?dn)")
304: ( <eof> tpl-command-pop
305: " - pop one break level up "
306: " '^D' - if connect to tty, pops up one break level,"
307: " otherwise, exits doesn't exit unless "))
308: )
309:
310: ;--- process-fcn :: do a user command
311: ;
312: (defun process-fcn (form)
313: (let ((sel (car form)))
314: (setq tpl-stack-ok nil)
315: (do ((xx tpl-commands (cdr xx))
316: (this))
317: ((null xx)
318: (msg "Illegal command, type ?help for list of commands" N))
319: (If (or (and (symbolp (setq this (caar xx)))
320: (eq sel this))
321: (and (dtpr this)
322: (memq sel this)))
323: then (return (tpl-funcall (cadar xx) form))))))
324:
325:
326:
327: ;--- tpl commands
328: ;
329:
330: ;--- tpl-command-help
331: (defun tpl-command-help (x)
332: (setq tpl-stack-ok t)
333: (If (cdr x)
334: then (do ((xx tpl-commands (cdr xx))
335: (sel (cadr x))
336: (this))
337: ((null xx)
338: (msg "I don't know that command" N))
339: ; look for command in tpl-commands list
340: (If (or (and (symbolp (setq this (caar xx)))
341: (eq sel this))
342: (and (dtpr this)
343: (memq sel this)))
344: then (return (do ((yy (cdddar xx) (cdr yy)))
345: ((null yy))
346: ; print all extended documentation
347: (patom (car yy))
348: (terpr)))))
349: else ; print short info on all commands
350: (mapc #'(lambda (x)
351: (let ((sel (car x)))
352: ; first print selector or selectors
353: (If (dtpr sel)
354: then (patom (car sel))
355: (mapc #'(lambda (y) (patom ",") (patom y))
356: (cdr sel))
357: else (patom sel))
358: ; next print documentation
359: (patom (caddr x))
360: (terpr)))
361: tpl-commands))
362: nil)
363:
364: (defun tpl-command-load (args)
365: (setq args (cdr args))
366: (If args
367: then (setq tpl-last-loaded args)
368: (mapc 'load args)
369: elseif tpl-last-loaded
370: then (mapc 'load tpl-last-loaded)
371: else (msg "Nothing to load" N)))
372:
373:
374: (defun tpl-command-trace (args)
375: (setq args (cdr args))
376: (apply 'trace args))
377:
378:
379:
380: ;--- tpl-command-state
381: ;
382: (defun tpl-command-state (x)
383: (msg " State: debug " tpl-debug-on ", step " tpl-step-enable N))
384:
385: ;--- tpl-command-debug
386: ;
387: (defun tpl-command-debug (x)
388: (If (memq 'off (cdr x))
389: then (*rset nil)
390: (msg "Debug is off" N)
391: (setq tpl-debug-on nil)
392: else (*rset t)
393: (sstatus translink nil)
394: (msg "Debug is on" N)
395: (setq tpl-debug-on t)))
396:
397: ;--- tpl-command-zoom
398: ;
399: (defun tpl-command-zoom (x)
400: (tpl-update-stack)
401: (setq tpl-stack-ok t)
402: (tpl-zoom))
403:
404: (defun tpl-command-down (args)
405: ;; go down the evaluation stack and zoom
406: ;; down means towards older frames
407: (setq tpl-stack-ok t)
408: (let ((count 1))
409: (If (and (fixp (cadr args)) (> (cadr args) 0))
410: then (setq count (cadr args)))
411: (do ((xx count (1- xx)))
412: ((= 0 xx))
413: (If tpl-bot-framelist
414: then (setq tpl-top-framelist (cons (car tpl-bot-framelist)
415: tpl-top-framelist)
416: tpl-bot-framelist (cdr tpl-bot-framelist))))
417: (tpl-command-zoom nil)))
418:
419: (defun tpl-command-up (args)
420: ;; go up the stack and zoom
421: ;; up is towards more recent stuff
422: ;;
423: (setq tpl-stack-ok t)
424: (let ((count 1))
425: (If (and (fixp (cadr args)) (> (cadr args) 0))
426: then (setq count (cadr args)))
427: (do ((xx count (1- xx)))
428: ((= 0 xx))
429: (If tpl-top-framelist
430: then (setq tpl-bot-framelist (cons (car tpl-top-framelist)
431: tpl-bot-framelist)
432: tpl-top-framelist (cdr tpl-top-framelist))))
433: (tpl-command-zoom nil)))
434:
435: (defun tpl-command-ev (args)
436: ;; ?ev foo
437: ;; determine the value of variable foo with respect to the current
438: ;; evaluation frame.
439: ;;
440: (let ((sym (cadr args)))
441: (If (not (symbolp sym))
442: then (msg "ev must be given a symbol" N)
443: elseif (null tpl-bot-framelist)
444: then (msg "there is no evaluation stack, is debug on?")
445: else (prog1 (car
446: (errset
447: (eval sym
448: (evalframe-bind (car tpl-bot-framelist)))))
449: (setq tpl-stack-ok t)))))
450:
451:
452: (defun tpl-command-pp (args)
453: (pp-form (evalframe-expr (car tpl-bot-framelist)))
454: (terpr)
455: nil)
456:
457: ;;-- history list maintainers
458: ;
459: ; history lists are just lists of forms
460: ; one for the given, and one for the returned
461: ;
462: (defun most-recent-given () (car given-history))
463:
464: (defun add-to-given-history (form)
465: (setq given-history (cons form given-history))
466: (setq res-history (cons nil res-history))
467: (If (not (eq (car form) 'history))
468: then (setq tpl-history-count (1+ tpl-history-count))))
469:
470: (defun add-to-res-history (form)
471: (setq res-history (cons form (cdr res-history)))
472: (setq % form))
473:
474:
475: ;--- evalframe generation
476: ;
477:
478: (defun tpl-update-stack nil
479: (If tpl-stack-bad
480: then (If (tpl-yorn "Should I re-calc the stack(y/n):")
481: then (tpl-gentrace)
482: else (msg "[not re-calc'ed]" N)
483: (setq tpl-stack-bad nil))))
484:
485: ;--- tpl-gentrace
486: ; this is called before an function which references the
487: ; frame list. it needn't be called unless one knows that
488: ; the frame status has changed
489: ;
490: (defun tpl-gentrace ()
491: (let ((templist (tpl-getframelist)))
492: ; templist contains the frame from bottom (oldest) to top
493:
494: (setq templist (nreverse templist)) ; now youngest to oldest
495:
496:
497: ; determine a new framelist and put it on the bottom list
498: ; the top list is empty. the first thing in the
499: ; bottom framelist is the 'current' frame.
500:
501: ; go though frames, based on flags, flush trace calls
502: ; or eval calls
503: (do ((xx templist (cdr xx))
504: (remember (If tpl-dontshow-tpl then nil else t))
505: (forget-this nil nil)
506: (res)
507: (exp)
508: (flushpoint))
509: ((null xx) (setq tpl-bot-framelist (nreverse res)))
510: (setq exp (evalframe-expr (car xx)))
511: (If (dtpr exp)
512: then (If (and tpl-dontshow-tpl
513: (memq (car exp) '(tpl-eval tpl-funcall
514: tpl-evalhook
515: tpl-funcallhook)))
516: then (setq remember nil)))
517: (If (dtpr exp)
518: then (If (and tpl-dontshow-tpl (memq (car exp)
519: '(tpl-err-tpl-fcn
520: tpl-funcall-evalhook
521: tpl-do-funcallhook)))
522: then (setq forget-this t)))
523: (If (and remember (not forget-this))
524: then (setq res (cons (car xx) res)))
525: (If (dtpr exp)
526: then (If (and tpl-dontshow-tpl
527: (eq (car exp) 'tpl-break-function))
528: then (setq remember t))))
529:
530: (setq tpl-top-framelist nil)))
531:
532: (defun tpl-getframelist nil
533: (let ((frames)
534: temp)
535: (If *rset
536: then ; Getting the first few frames is tricky because
537: ; the frames disappear quickly.
538: (setq temp (evalframe nil)) ; call to setq
539: (setq temp (evalframe (evalframe-pdl temp)))
540: (do ((xx (list (evalframe (evalframe-pdl temp)))
541: (cons (evalframe (evalframe-pdl (car xx))) xx)))
542: ((null (car xx))
543: (cdr xx))))))
544:
545:
546: (defun tpl-printframelist (printdown vals count)
547: (If (null vals)
548: then (If printdown
549: then (msg "*** bottom ***" N)
550: else (msg "*** top ***" N))
551: elseif (= 0 count)
552: then (msg "... " (length vals) " more ..." N)
553: else (If (not printdown)
554: then (tpl-printframelist printdown (cdr vals) (1- count)))
555: (let ((prinlevel tpl-prinlevel)
556: (prinlength tpl-prinlength))
557: ; tag apply type forms with 'a:'
558: (if (eq 'apply (evalframe-type (car vals)))
559: then (msg "a:"))
560: (print (evalframe-expr (car vals)))
561: (terpr))
562: (If printdown
563: then (tpl-printframelist printdown (cdr vals) (1- count)))))
564:
565:
566: (defun tpl-zoom nil
567: (tpl-printframelist nil tpl-top-framelist 4)
568: (msg "// current \\\\" N)
569: (tpl-printframelist t tpl-bot-framelist 4))
570:
571:
572:
573: (defmacro errdesc-class (err) `(car ,err))
574: (defmacro errdesc-id (err) `(cadr ,err))
575: (defmacro errdesc-contp (err) `(caddr ,err))
576: (defmacro errdesc-descr (err) `(cdddr ,err))
577:
578: ;--- error handler
579: ;
580:
581: (defun tpl-break-function (reason)
582: (do ((tpl-fcn-in-eval (most-recent-given))
583: (tpl-level reason)
584: (tpl-continuab)
585: (tpl-break-level (1+ tpl-break-level))
586: ;(tpl-step-enable)
587: (prompt)
588: (do-retry nil nil)
589: (retry-value)
590: (retv 'contbreak)
591: (piport nil)
592: (eof-form (ncons nil)))
593: (nil)
594: (If (eq retv 'contbreak)
595: then
596: (If (memq (car reason) '(error derror))
597: then (if (eq (car reason) 'error)
598: then (msg "Error: ")
599: else (msg "DError: "))
600: (patom (car (errdesc-descr (cdr reason))))
601: (mapc #'(lambda (x) (patom " ") (print x))
602: (cdr (errdesc-descr (cdr reason))))
603: (terpr)
604: (msg "Form: " (cdr tpl-fcn-in-eval))
605: elseif (eq 'break (car reason))
606: then (msg "Break: ")
607: (patom (cadr reason))
608: (mapc #'(lambda (x) (patom " ") (print x))
609: (cddr reason)))
610: (terpr)
611: (setq tpl-contuab (or (memq (car reason) '(break derror step))
612: (errdesc-contp (cdr reason))))
613: (setq prompt (If reason
614: then (concat (if (eq (car reason) 'derror)
615: then "d"
616: elseif (eq (car reason) 'step)
617: then "s"
618: else "")
619: (If tpl-contuab then "c" else "")
620: "{"
621: tpl-break-level
622: "} ")
623: else "=> "))
624: elseif (eq retv 'reset)
625: then (tpl-throw 'reset)
626: elseif (eq retv 'poplevel)
627: then (tpl-throw 'contbreak)
628: elseif (eq retv 'popretry)
629: then (tpl-throw `(retry ,tpl-fcn-in-eval))
630: elseif (dtpr retv)
631: then (If (eq 'retbreak (car retv))
632: then (If (eq 'error (car reason))
633: then (return (cdr retv)) ; return from error
634: else (return (cadr retv)))
635: else (If (eq 'retry (car retv))
636: then (setq do-retry t
637: retry-value (cadr retv)))))
638: (setq retv
639: (tpl-catch
640: (do ()
641: (nil)
642: (If (null do-retry)
643: then (do-one-transaction nil prompt eof-form)
644: else (do-one-transaction retry-value prompt nil))
645: (setq do-retry nil)
646: nil)))))
647:
648: ;--- tpl-err-tpl-fcn
649: ; attached to ER%tpl, the error will return to top level
650: ; generic error handler
651: ;
652: (defun tpl-err-tpl-fcn (err)
653: (tpl-break-function (cons 'error err)))
654:
655: ;--- tpl-err-all-fcn
656: ; attached to ER%all if (debugging t) is done.
657: ;
658: (defun tpl-err-all-fcn (err)
659: (setq ER%all 'tpl-err-all-fcn)
660: (tpl-break-function (cons 'derror err)))
661:
662: ;-- tpl-command-pop
663: ; pop a break level
664: ;
665: (defun tpl-command-pop (x)
666: (If (= 0 tpl-break-level)
667: then (msg "Already at top level " N)
668: else (tpl-throw 'poplevel)))
669:
670:
671:
672: (defun tpl-command-ret (x)
673: (If tpl-contuab
674: then (tpl-throw (list 'retbreak (eval (cadr x))))
675: else (msg "Can't return at this point" N)))
676:
677: ;--- tpl-command-redo
678: ; see documentatio above for a list of the various things this accepts
679: ;
680: (defun tpl-command-redo (x)
681: (setq x (cdr x))
682: (If (null x)
683: then (tpl-redo-by-count 1)
684: elseif (fixp (car x))
685: then (If (< (car x) 0)
686: then (tpl-redo-by-count (- (car x)))
687: else (If (not (< (car x) tpl-history-count))
688: then (msg "There aren't that many commands " N)
689: else (tpl-redo-by-count (- tpl-history-count (car x)))))
690: else (tpl-redo-by-car x)))
691:
692:
693: ;--- tpl-redo-by-car :: locate command to do by the car of the command
694: ;
695: (defun tpl-redo-by-car (x)
696: (let ((command (car x))
697: (substringp (If (eq (cadr x) '*) thenret)))
698: (If substringp
699: then (If (not (symbolp command))
700: then (msg "must give a symbol before *" N)
701: else (let* ((string (get_pname command))
702: (len (pntlen string)))
703: (do ((xx (tpl-next-user-in-history given-history)
704: (tpl-next-user-in-history (cdr xx)))
705: (pos))
706: ((null xx)
707: (msg "Can't find a match" N))
708: (If (and (dtpr (cdar xx))
709: (symbolp (setq pos (cadar xx))))
710: then (If (equal (substring pos 1 len)
711: string)
712: then (tpl-throw
713: `(retry ,(car xx))))))))
714: else (do ((xx (tpl-next-user-in-history given-history)
715: (tpl-next-user-in-history (cdr xx)))
716: (pos))
717: ((null xx)
718: (msg "Can't find a match" N))
719: (If (and (dtpr (cdar xx))
720: (symbolp (setq pos (cadar xx))))
721: then (If (eq pos command)
722: then (tpl-throw
723: `(retry ,(car xx)))))))))
724:
725: ;--- tpl-redo-by-count :: redo n'th previous input
726: ; n>=0. if n=0, then redo last.
727: ;
728: (defun tpl-redo-by-count (n)
729: (do ((xx n (1- xx))
730: (list (tpl-next-user-in-history given-history)
731: (tpl-next-user-in-history (cdr list))))
732: ((or (not (> xx 0)) (null list))
733: (If (null list)
734: then (msg "There aren't that many commands " N)
735: else (tpl-throw `(retry ,(car list)))))))
736:
737:
738: '(defun tpl-next-user-in-history (hlist)
739: (do ((histlist hlist (cdr histlist)))
740: ((or (null histlist)
741: (eq 'user (caar histlist)))
742: histlist)))
743:
744: (defun tpl-next-user-in-history (hlist)
745: hlist)
746:
747: ;--- tpl-command-prt
748: ; pop and retry command which failed this time
749: ;
750: (defun tpl-command-prt (x)
751: (tpl-throw 'popretry))
752:
753:
754: ;--- tpl-command-history
755: ;
756: (defun tpl-command-history (x)
757: (let (show-res)
758: (If (memq 'r (cdr x))
759: then (setq show-res t))
760: (tpl-command-his-rec tpl-history-show tpl-history-count show-res
761: given-history res-history)))
762:
763: (defun tpl-command-his-rec (count current show-res hlist rhlist)
764: (If (and hlist (> count 0))
765: then (tpl-command-his-rec (1- count) (1- current) show-res
766: (cdr hlist) (cdr rhlist)))
767: (If hlist
768: then
769: (let ((prinlevel tpl-prinlevel)
770: (prinlength tpl-prinlength))
771: (msg current ": ") (tpl-history-form-print (car hlist))
772: (terpr)
773: (If show-res
774: then (msg "% " current ": " (car rhlist) N)))))
775:
776:
777: (defun tpl-command-reset (x)
778: (tpl-throw 'reset))
779:
780: (defun tpl-yorn (message)
781: (drain piport)
782: (msg message)
783: (let ((ch (tyi)))
784: (drain piport)
785: (eq #/y ch)))
786:
787:
788: ;--- tpl-*break :: handle breaks
789: ; when tpl starts, this is put on *break's function cell
790: ;
791: (defun tpl-*break (pred message)
792: (let ((^w nil))
793: (cond (pred (tpl-break-function (list 'break message))))))
794:
795:
796:
797: ;; stepping code
798: (defun tpl-command-step (args)
799: (setq tpl-step-enable t
800: tpl-step-print nil
801: tpl-step-triggers nil
802: tpl-step-countdown 0)
803: (if (memq t args)
804: then (setq tpl-step-print t)
805: else (setq tpl-step-triggers args))
806: (*rset t)
807: (setq evalhook nil funcallhook nil)
808: (sstatus translink nil)
809: (sstatus evalhook t))
810:
811:
812: (defun tpl-command-stepoff (args)
813: ;; we don't turn off status evalhook because then an
814: ;; evalhook would cause an error (this probably should be fixed)
815: (sstatus evalhook nil)
816: (setq tpl-step-enable nil
817: tpl-step-print nil))
818:
819: (defun tpl-command-sc (args)
820: ;; continue after step
821: (if (cdr args)
822: then (if (fixp (cadr args))
823: then (setq tpl-step-countdown (cadr args))
824: else (setq tpl-step-countdown 100000)))
825: (tpl-throw `(retbreak ,tpl-step-enable)))
826:
827: (defun tpl-do-evalhook (arg)
828: ;; arg is the form to eval
829: (tpl-funcall-evalhook arg 'eval))
830:
831: (defun tpl-do-funcallhook (&rest args)
832: ;; this is called with n args.
833: ;; args 0 to n-2 are the actual arguments.
834: ;; arg n-1 is the function to call (notice that it comes at the end)
835: ; the list in 'args' is a fresh list, we can clobber it
836: (let (name)
837: ; strip the last cons cells from the args list
838: ; there will be at least one element in the list,
839: ; namely the function being called
840: (if (cdr args)
841: then ; case of at least one argument
842: (do ((xx args (cdr xx)))
843: ((null (cddr xx))
844: (setq name (cadr xx))
845: (setf (cdr xx) nil)))
846: else ; case of zero arguments
847: (setq name (car args) args nil))
848:
849: (tpl-funcall-evalhook (cons name args) 'funcall)))
850:
851:
852: (defun tpl-funcall-evalhook (fform type)
853: ;; function called after an evalhook or funclalhook is triggered
854: ;; The form is an s-expression to be evaluated
855: ;; The type is either 'eval' or 'funcall',
856: ;; eval meaning that the form is something to be eval'ed
857: ;; funcall meaning that the car of the form is the function to
858: ;; be applied to the list which is the cdr [actually the cdr
859: ;; is spread out on the stack and a 'funcall' is done, but this
860: ;; is what apply does anyway.
861: ;; Upon entry we optionally print, optionally break, optionally continue
862: ;; stepping, and then optionally print the value
863: ;; We print if tpl-step-print is t
864: ;; We break if tpl-step-print is t and tpl-step-countdown is <= 0
865: ;; We continue stepping if tpl-step-enable is t
866: ;; We print the result if we continued stepping.
867: ;;
868: ;; note: if it were possible to call evalhook and funcallhook if
869: ;; (status evalhook) were nil, then we could make ?soff turn off
870: ;; (status evalhook), making things run faster [as it is now, stepping
871: ;; continues until we reach top-level again. We just don't print
872: ;; things out]
873: ;;
874: (let ((tpl-step-reclevel (1+ tpl-step-reclevel)))
875: (if (and (not tpl-step-print)
876: (dtpr fform)
877: (memq (car fform) tpl-step-triggers))
878: then (setq tpl-step-print t))
879: (if tpl-step-print
880: then (tpl-step-printform tpl-step-reclevel type fform)
881: (if (<& tpl-step-countdown 1)
882: then (setq tpl-step-enable (tpl-break-function '(step)))
883: else (setq tpl-step-countdown (1- tpl-step-countdown))))
884: (if tpl-step-enable
885: then (let ((newval))
886: (setq newval (if (eq type 'eval)
887: then (tpl-evalhook fform
888: 'tpl-do-evalhook
889: 'tpl-do-funcallhook)
890: else (tpl-funcallhook fform
891: 'tpl-do-funcallhook
892: 'tpl-do-evalhook)))
893: (if tpl-step-print
894: then (tpl-step-printform tpl-step-reclevel 'r newval))
895: newval)
896: else (if (eq type 'eval)
897: then (tpl-evalhook fform nil nil)
898: else (tpl-funcallhook fform nil nil)))))
899:
900:
901: (defun tpl-step-printform (indent key form)
902: (printblanks indent nil)
903: (let ((prinlevel 4) (prinlength 4))
904: (msg (if (eq key 'r)
905: then '"=="
906: elseif (eq key 'funcall)
907: then 'f:
908: elseif (eq key 'eval)
909: then 'e:
910: else key)
911: form N)))
912:
913: ; in order to use this: (setq user-top-level 'tpl)
914:
915:
916: (putprop 'tpl t 'version)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.