|
|
1.1 ! root 1: (setq rcs-trace- ! 2: "$Header: /usr/lib/lisp/RCS/trace.l,v 1.2 83/08/15 22:30:36 jkf Exp $") ! 3: ! 4: ;---- The Joseph Lister Trace Package, v1 ! 5: ; John Foderaro, Sept 1979 ! 6: ;------------------------------------------------------------------; ! 7: ; Copyright (c) 1979 The Regents of the University of California ; ! 8: ; All rights reserved. ; ! 9: ;------------------------------------------------------------------; ! 10: (eval-when (eval) ! 11: (setq old-read-table-trace readtable) ! 12: (setq readtable (makereadtable t)) ! 13: (setq old-uctolc-value (status uctolc)) ! 14: (sstatus uctolc nil) ; turn off case conversion ! 15: (load 'charmac) ! 16: (setsyntax '\; 'macro 'zapline) ! 17: ) ! 18: ! 19: ! 20: ! 21: ;---- ! 22: ; trace uses these properties on the property list: ! 23: ; trace-orig-fcn: original occupant of the function cell ! 24: ; trace-trace-fcn: the value trace puts in the function cell ! 25: ; (used to check if the trace function has be overwritten). ! 26: ; trace-trace-args: the arguments when function was traced. ! 27: ; trace-printargs: function to print argument to function ! 28: ; trace-printres: function to print result of function ! 29: ! 30: (declare (nlambda T-status T-sstatus) ! 31: (special piport ! 32: if ifnot evalin evalout ! 33: printargs printres evfcn ! 34: traceenter traceexit ! 35: prinlevel prinlength ! 36: $$traced-functions$$ ; all functions being traced ! 37: $$functions-in-trace$$ ; active functions ! 38: $$funcargs-in-trace$$ ; arguments to active functions. ! 39: $tracemute ; if t, then enters and exits ! 40: ; are quiet, but info is still ! 41: ; kept so (tracedump) will work ! 42: trace-prinlevel ; default values ! 43: trace-prinlength ! 44: trace-printer ; function trace uses to print ! 45: )) ! 46: ! 47: ! 48: ! 49: (cond ((null (boundp '$$traced-functions$$)) (setq $$traced-functions$$ nil))) ! 50: (cond ((null (boundp '$$functions-in-trace$$)) (setq $$functions-in-trace$$ nil))) ! 51: (cond ((null (boundp '$$funcargs-in-trace$$)) (setq $$funcargs-in-trace$$ nil))) ! 52: (cond ((null (boundp '$tracemute)) (setq $tracemute nil))) ! 53: (cond ((null (boundp 'trace-prinlevel)) (setq trace-prinlevel 4))) ! 54: (cond ((null (boundp 'trace-prinlength)) (setq trace-prinlength 5))) ! 55: (cond ((null (boundp 'trace-printer)) (setq trace-printer 'Trace-print))) ! 56: ! 57: ;----> It is important that the trace package not use traced functions ! 58: ; thus we give the functions the trace package uses different ! 59: ; names and make them equivalent at this time to their ! 60: ; traceable counterparts. ! 61: (defun trace-startup-func nil ! 62: (do ((i '( (add1 T-add1)(append T-append) ! 63: (and T-and) (apply T-apply) ! 64: (cond T-cond) (cons T-cons) (delq T-delq) ! 65: (def T-def) (do T-do) (drain T-drain) ! 66: (dtpr T-dtpr) (eval T-eval)(funcall T-funcall) ! 67: (get T-get) (getd T-getd)(getdisc T-getdisc) ! 68: (greaterp T-greaterp)(lessp T-lessp) ! 69: (mapc T-mapc) (not T-not)(nreverse T-nreverse) ! 70: (patom T-patom) (print T-print) (prog T-prog) ! 71: (patom T-patom)(putd T-putd) ! 72: (putprop T-putprop) ! 73: (read T-read)(remprop T-remprop) (reverse T-reverse) ! 74: (return T-return) ! 75: (set T-set) (setq T-setq) ! 76: (status T-status) (sstatus T-sstatus) ! 77: (sub1 T-sub1) (terpr T-terpr) ! 78: (zerop T-zerop)) ! 79: (cdr i))) ! 80: ((null i)) ! 81: (putd (cadar i) (getd (caar i))) ! 82: (putprop (cadar i) t 'Untraceable))) ! 83: ! 84: (trace-startup-func) ! 85: ! 86: ! 87: (putprop 'quote t 'Untraceable) ; this prevents the common error ! 88: ; of (trace 'foo) from causing big ! 89: ; problems. ! 90: ! 91: ;--- trace - arg1,arg2, ... names of functions to trace ! 92: ; This is the main user callable trace routine. ! 93: ; work in progress, documentation incomplete since im not sure exactly ! 94: ; where this is going. ! 95: ; ! 96: (def trace ! 97: (nlambda (argl) ! 98: (prog (if ifnot evalin evalout funnm typ ! 99: funcd did break printargs printres evfcn traceenter traceexit ! 100: traceargs) ! 101: ! 102: ; turn off transfer table linkages if they are on ! 103: (cond ((T-status translink) (T-sstatus translink nil))) ! 104: ! 105: ; process each argument ! 106: ! 107: (do ((ll argl (cdr ll)) ! 108: (funnm) ! 109: (funcd)) ! 110: ((null ll)) ! 111: (setq funnm (car ll) ! 112: if t ! 113: break nil ! 114: ifnot nil ! 115: evalin nil ! 116: evalout nil ! 117: printargs nil ! 118: printres nil ! 119: evfcn nil ! 120: traceenter 'T-traceenter ! 121: traceexit 'T-traceexit ! 122: traceargs nil) ! 123: ! 124: ; a list as an argument means that the user is specifying ! 125: ; conditions on the trace ! 126: (cond ((not (atom funnm)) ! 127: (cond ((not (atom (setq funnm (car funnm)))) ! 128: (T-print (car funnm)) ! 129: (T-patom '" is non an function name") ! 130: (go botloop))) ! 131: ; remember the arguments in case a retrace is requested ! 132: (setq traceargs (cdar ll)) ! 133: ; scan the arguments ! 134: (do ((rr (cdar ll) (cdr rr))) ! 135: ((null rr)) ! 136: (cond ((memq (car rr) '(if ifnot evalin evalout ! 137: printargs printres evfcn ! 138: traceenter traceexit)) ! 139: (T-set (car rr) (cadr rr)) ! 140: (setq rr (cdr rr))) ! 141: ((eq (car rr) 'evalinout) ! 142: (setq evalin (setq evalout (cadr rr)) ! 143: rr (cdr rr))) ! 144: ((eq (car rr) 'break) ! 145: (setq break t)) ! 146: ((eq (car rr) 'lprint) ! 147: (setq printargs 'T-levprint ! 148: printres 'T-levprint)) ! 149: (t (T-patom '"bad request: ") ! 150: (T-print (car rr)) ! 151: (T-terpr))))) ! 152: (t (setq traceargs nil) ;no args given ! 153: )) ! 154: ! 155: ; if function is untraceable, print error message and skip ! 156: (cond ((get funnm 'Untraceable) ! 157: (setq did (cons `(,funnm untraceable) did)) ! 158: (go botloop))) ! 159: ! 160: ! 161: ; Untrace before tracing ! 162: (let ((res (funcall 'untrace (list funnm)))) ! 163: (cond (res (setq did (cons `(,funnm untraced) did))))) ! 164: ! 165: ; store the names of the arg printing routines if they are ! 166: ; different than print ! 167: ! 168: (cond (printargs (T-putprop funnm printargs 'trace-printargs))) ! 169: (cond (printres (T-putprop funnm printres 'trace-printres))) ! 170: (T-putprop funnm traceargs 'trace-trace-args) ! 171: ! 172: ; we must determine the type of function being traced ! 173: ; in order to create the correct replacement function ! 174: ! 175: (cond ((setq funcd (T-getd funnm)) ! 176: (cond ((bcdp funcd) ; machine code ! 177: (cond ((or (eq 'lambda (T-getdisc funcd)) ! 178: (eq 'nlambda (T-getdisc funcd)) ! 179: (eq 'macro (T-getdisc funcd))) ! 180: (setq typ (T-getdisc funcd))) ! 181: ((stringp (T-getdisc funcd)) ; foreign func ! 182: (setq typ 'lambda)) ; close enough ! 183: (t (T-patom '"Unknown type of compiled function") ! 184: (T-print funnm) ! 185: (setq typ nil)))) ! 186: ! 187: ((dtpr funcd) ; lisp coded ! 188: (cond ((or (eq 'lambda (car funcd)) ! 189: (eq 'lexpr (car funcd))) ! 190: (setq typ 'lambda)) ! 191: ((or (eq 'nlambda (car funcd)) ! 192: (eq 'macro (car funcd))) ! 193: (setq typ (car funcd))) ! 194: (t (T-patom '"Bad function definition: ") ! 195: (T-print funnm) ! 196: (setq typ nil)))) ! 197: ((arrayp funcd) ; array ! 198: (setq typ 'lambda)) ! 199: (t (T-patom '"Bad function defintion: ") ! 200: (T-print funnm))) ! 201: ! 202: ; now that the arguments have been examined for this ! 203: ; function, do the tracing stuff. ! 204: ; First save the old function on the property list ! 205: ! 206: (T-putprop funnm funcd 'trace-orig-fcn) ! 207: ! 208: ; now build a replacement ! 209: ! 210: (cond ! 211: ((eq typ 'lambda) ! 212: (T-eval ! 213: `(T-def ! 214: ,funnm ! 215: (lexpr (T-nargs) ! 216: ((lambda (T-arglst T-res T-rslt ! 217: $$functions-in-trace$$ ! 218: $$funcargs-in-trace$$) ! 219: (T-do ((i T-nargs (T-sub1 i))) ! 220: ((T-zerop i)) ! 221: (T-setq T-arglst ! 222: (T-cons (arg i) T-arglst))) ! 223: (T-setq $$funcargs-in-trace$$ ! 224: (T-cons T-arglst ! 225: $$funcargs-in-trace$$)) ! 226: (T-cond ((T-setq T-res ! 227: (T-and ,if ! 228: (T-not ,ifnot))) ! 229: (,traceenter ',funnm T-arglst) ! 230: ,@(cond (evalin ! 231: `((T-patom ,'":in: ") ! 232: ,evalin ! 233: (T-terpr)))) ! 234: (T-cond (,break ! 235: (trace-break))))) ! 236: (T-setq T-rslt ! 237: ,(cond ! 238: (evfcn) ! 239: (t `(T-apply ! 240: ',funcd ! 241: T-arglst)))) ! 242: (T-cond (T-res ! 243: ,@(cond (evalout ! 244: `((T-patom ,'":out: ") ! 245: ,evalout ! 246: (T-terpr)))) ! 247: (,traceexit ',funnm T-rslt))) ! 248: T-rslt) ! 249: nil nil nil ! 250: (T-cons ',funnm $$functions-in-trace$$) ! 251: $$funcargs-in-trace$$)))) ! 252: (T-putprop funnm (T-getd funnm) 'trace-trace-fcn) ! 253: (setq did (cons funnm did) ! 254: $$traced-functions$$ (cons funnm ! 255: $$traced-functions$$))) ! 256: ! 257: ((or (eq typ 'nlambda) ! 258: (eq typ 'macro)) ! 259: (T-eval ! 260: `(T-def ,funnm ! 261: (,typ (T-arglst) ! 262: ((lambda (T-res T-rslt ! 263: $$functions-in-trace$$ ! 264: $$funcargs-in-trace$$) ! 265: (T-setq $$funcargs-in-trace$$ ! 266: (T-cons ! 267: T-arglst ! 268: $$funcargs-in-trace$$)) ! 269: (T-cond ((T-setq ! 270: T-res ! 271: (T-and ,if ! 272: (not ,ifnot))) ! 273: (,traceenter ! 274: ',funnm ! 275: T-arglst) ! 276: ,evalin ! 277: (T-cond (,break ! 278: (trace-break))))) ! 279: (T-setq T-rslt ! 280: ,(cond ! 281: (evfcn `(,evfcn ! 282: ',funcd ! 283: T-arglst)) ! 284: (t `(T-apply ',funcd ! 285: T-arglst)))) ! 286: (T-cond (T-res ! 287: ,evalout ! 288: (,traceexit ',funnm T-rslt))) ! 289: T-rslt) ! 290: nil nil ! 291: (cons ',funnm $$functions-in-trace$$) ! 292: $$funcargs-in-trace$$)))) ! 293: (T-putprop funnm (T-getd funnm) 'trace-trace-fcn) ! 294: (setq did (cons funnm did) ! 295: $$traced-functions$$ (cons funnm ! 296: $$traced-functions$$))) ! 297: ! 298: (t (T-patom '"No such function as: ") ! 299: (T-print funnm) ! 300: (T-terpr))))) ! 301: botloop ) ! 302: ; if given no args, just return the function currently being traced ! 303: (return (cond ((null argl) $$traced-functions$$) ! 304: (t (T-nreverse did))))))) ! 305: ! 306: ;--- untrace ! 307: ; (untrace foo bar baz) ! 308: ; untraces foo, bar and baz. ! 309: ; (untrace) ! 310: ; untraces all functions being traced. ! 311: ; ! 312: ! 313: (def untrace ! 314: (nlambda (argl) ! 315: (cond ((null argl) (setq argl $$traced-functions$$))) ! 316: ! 317: (do ((i argl (cdr i)) ! 318: (tmp) ! 319: (curf) ! 320: (res)) ! 321: ((null i) ! 322: (cond ((null $$traced-functions$$) ! 323: (setq $$functions-in-trace$$ nil) ! 324: (setq $$funcargs-in-trace$$ nil))) ! 325: res) ! 326: (cond ((and (T-getd (setq curf (car i))) ! 327: (eq (T-getd (car i)) ! 328: (get (car i) 'trace-trace-fcn))) ! 329: ; we only want to restore the original definition ! 330: ; if this function has not been redefined! ! 331: ; we test this by checking to be sure that the ! 332: ; trace-trace-property is the same as the function ! 333: ; definition. ! 334: (T-putd curf (get curf 'trace-orig-fcn)) ! 335: (T-remprop curf 'trace-orig-fcn) ! 336: (T-remprop curf 'trace-trace-fcn) ! 337: (T-remprop curf 'trace-trace-args) ! 338: (T-remprop curf 'entercount) ! 339: (setq $$traced-functions$$ ! 340: (T-delq curf $$traced-functions$$)) ! 341: (setq res (cons curf res))))))) ! 342: ! 343: ! 344: ;--- retrace :: trace again all function thought to be traced. ! 345: ; ! 346: (def retrace ! 347: (nlambda (args) ! 348: (cond ((null args) (setq args $$traced-functions$$))) ! 349: (mapcan '(lambda (fcn) ! 350: (cond ((and (symbolp fcn) ! 351: (not (eq (T-getd fcn) ! 352: (get fcn 'trace-trace-fcn)))) ! 353: ! 354: (funcall 'trace ! 355: `((,fcn ,@(get fcn 'trace-trace-args))))))) ! 356: args))) ! 357: ! 358: ;--- tracedump :: dump the currently active trace frames ! 359: ; ! 360: (def tracedump ! 361: (lambda nil ! 362: (let (($tracemute nil)) ! 363: (T-tracedump-recursive $$functions-in-trace$$ ! 364: $$funcargs-in-trace$$)))) ! 365: ! 366: ! 367: ;--- traceargs :: return list of args to currently entered traced functions ! 368: ; call is: ! 369: ; (traceargs foo) returns first call to foo starting at most current ! 370: ; (traceargs foo 3) returns args to third call to foo, starting at ! 371: ; most current ! 372: ; ! 373: (def traceargs ! 374: (nlambda (args) ! 375: (cond ((and args $$functions-in-trace$$) ! 376: (let ((name (car args)) ! 377: (amt (cond ((numberp (cadr args)) (cadr args)) ! 378: (t 1)))) ! 379: (do ((fit $$functions-in-trace$$ (cdr fit)) ! 380: (fat $$funcargs-in-trace$$ (cdr fat))) ! 381: ((null fit)) ! 382: (cond ((eq name (car fit)) ! 383: (cond ((zerop (setq amt (1- amt))) ! 384: (return (car fat)))))))))))) ! 385: ! 386: ;--- T-tracedump-recursive ! 387: ; since the lists of functions being traced and arguments are in the reverse ! 388: ; of the order we want to print them, we recurse down the lists and on the ! 389: ; way back we print the information. ! 390: ; ! 391: (def T-tracedump-recursive ! 392: (lambda ($$functions-in-trace$$ $$funcargs-in-trace$$) ! 393: (cond ((null $$functions-in-trace$$)) ! 394: (t (T-tracedump-recursive (cdr $$functions-in-trace$$) ! 395: (cdr $$funcargs-in-trace$$)) ! 396: (T-traceenter (car $$functions-in-trace$$) ! 397: (car $$funcargs-in-trace$$)))))) ! 398: ! 399: ! 400: ! 401: ;--- T-traceenter - funnm : name of function just entered ! 402: ; - count : count to print out ! 403: ; This routine is called to print the entry banner for a ! 404: ; traced function. ! 405: ; ! 406: (def T-traceenter ! 407: (lambda (name args) ! 408: (prog (count indent) ! 409: (cond ((not $tracemute) ! 410: (setq count 0 indent 0) ! 411: (do ((ll $$functions-in-trace$$ (cdr ll))) ! 412: ((null ll)) ! 413: (cond ((eq (car ll) name) (setq count (1+ count)))) ! 414: (setq indent (1+ indent))) ! 415: ! 416: (T-traceindent indent) ! 417: (T-print count) ! 418: (T-patom '" <Enter> ") ! 419: (T-print name) ! 420: (T-patom '" ") ! 421: (cond ((setq count (T-get name 'trace-printargs)) ! 422: (funcall count args)) ! 423: (t (funcall trace-printer args))) ! 424: (T-terpr)))))) ! 425: ! 426: (def T-traceexit ! 427: (lambda (name res) ! 428: (prog (count indent) ! 429: (cond ((not $tracemute) ! 430: (setq count 0 indent 0) ! 431: (do ((ll $$functions-in-trace$$ (cdr ll))) ! 432: ((null ll)) ! 433: (cond ((eq (car ll) name) (setq count (1+ count)))) ! 434: (setq indent (1+ indent))) ! 435: ! 436: ! 437: (T-traceindent indent) ! 438: (T-print count) ! 439: (T-patom " <EXIT> ") ! 440: (T-print name) ! 441: (T-patom " ") ! 442: ! 443: (cond ((setq count (T-get name 'trace-printres)) ! 444: (funcall count res)) ! 445: (t (funcall trace-printer res))) ! 446: ! 447: (T-terpr)))))) ! 448: ! 449: ! 450: ;--- Trace-printer ! 451: ; this is the default value of trace-printer. It prints a form after ! 452: ; binding prinlevel and prinlength. ! 453: ; ! 454: (def Trace-print ! 455: (lambda (form) ! 456: (let ((prinlevel trace-prinlevel) ! 457: (prinlength trace-prinlength)) ! 458: (T-print form)))) ! 459: ! 460: ; T-traceindent ! 461: ; - n : indent to column n ! 462: ! 463: (def T-traceindent ! 464: (lambda (col) ! 465: (do ((i col (1- i)) ! 466: (char '| |)) ! 467: ((< i 2)) ! 468: (T-patom (cond ((eq char '| |) (setq char '\|)) ! 469: (t (setq char '| |))))))) ! 470: ; from toplevel.l: ! 471: ; ! 472: ;--- read and print functions are user-selectable by just ! 473: ; assigning another value to top-level-print and top-level-read ! 474: ; ! 475: (declare (special top-level-read top-level-print)) ! 476: ! 477: (defmacro top-print (&rest args) ! 478: `(cond (top-level-print (funcall top-level-print ,@args)) ! 479: (t (T-print ,@args)))) ! 480: ! 481: (defmacro top-read (&rest args) ! 482: `(cond ((and top-level-read ! 483: (T-getd top-level-read)) ! 484: (funcall top-level-read ,@args)) ! 485: (t (T-read ,@args)))) ! 486: ! 487: ! 488: ; trace-break - this is the trace break loop ! 489: (def trace-break ! 490: (lambda nil ! 491: (prog (tracevalread piport) ! 492: (T-terpr) (T-patom '"[tracebreak]") ! 493: loop (T-terpr) ! 494: (T-patom '"T>") ! 495: (T-drain) ! 496: (cond ((or (eq nil (setq tracevalread ! 497: (car ! 498: (errset (top-read nil nil))))) ! 499: (and (dtpr tracevalread) ! 500: (eq 'tracereturn (car tracevalread)))) ! 501: (T-terpr) ! 502: (return nil))) ! 503: (top-print (car (errset (T-eval tracevalread)))) ! 504: (go loop)))) ! 505: ! 506: ! 507: (def T-levprint ! 508: (lambda (x) ! 509: ((lambda (prinlevel prinlength) ! 510: (T-print x)) ! 511: 3 10))) ! 512: ! 513: ! 514: (eval-when (eval) ! 515: (apply 'sstatus `(uctolc ,old-uctolc-value)) ! 516: (setq readtable old-read-table-trace) ! 517: )
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.