home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / gnu / emacs / sources / 867 < prev    next >
Encoding:
Text File  |  1992-12-16  |  9.2 KB  |  280 lines

  1. Path: sparky!uunet!elroy.jpl.nasa.gov!swrinde!news.dell.com!natinst.com!cs.utexas.edu!qt.cs.utexas.edu!yale.edu!spool.mu.edu!umn.edu!cs.widener.edu!dsinc!ub!acsu.buffalo.edu!hans
  2. From: hans@acsu.buffalo.edu (Hans Chalupsky)
  3. Newsgroups: gnu.emacs.sources
  4. Subject: trace.el - a trace package for Emacs-Lisp functions
  5. Message-ID: <BzC5DD.HKB@acsu.buffalo.edu>
  6. Date: 16 Dec 92 04:48:49 GMT
  7. Sender: nntp@acsu.buffalo.edu
  8. Distribution: gnu
  9. Organization: State University of New York at Buffalo/Comp Sci
  10. Lines: 267
  11. Nntp-Posting-Host: hadar.cs.buffalo.edu
  12.  
  13. Here is a simple trace package that gives you Lisp-style trace output for
  14. Emacs-Lisp functions. The package is based on advice.el previously posted
  15. here. 
  16.  
  17. The latest versions of trace.el and advice.el are also available via anonymous
  18. ftp from ftp.cs.buffalo.edu (128.205.32.9) in directory /pub/Emacs/.
  19.  
  20. Enjoy,
  21.  
  22. Hans
  23.  
  24. hans@cs.buffalo.edu
  25. Hans Chalupsky, Dept. of CS, 226 Bell Hall, SUNY@Buffalo, NY 14260.
  26.  
  27. ------------------------ cut here ------------------------
  28. ;; -*-Emacs-Lisp-*-
  29. ;;
  30. ;; Tracing facility for Emacs-Lisp functions
  31. ;;
  32. ;; Copyright (C) 1992 Hans Chalupsky
  33. ;;
  34. ;; File:     trace.el
  35. ;; Revision: $Revision: 1.1 $
  36. ;; Author:   Hans Chalupsky (hans@cs.buffalo.edu)
  37. ;; Created:   Date: 92/12/09 19:18:06
  38. ;; Modified: $Date: 92/12/15 22:45:15 $
  39. ;;
  40. ;;
  41. ;; This program is free software; you can redistribute it and/or modify
  42. ;; it under the terms of the GNU General Public License as published by
  43. ;; the Free Software Foundation; either version 1, or (at your option)
  44. ;; any later version.
  45. ;;
  46. ;; This program is distributed in the hope that it will be useful,
  47. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  48. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  49. ;; GNU General Public License for more details.
  50. ;;
  51. ;; A copy of the GNU General Public License can be obtained from this
  52. ;; program's author (send electronic mail to hans@cs.buffalo.edu) or from
  53. ;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
  54. ;; 02139, USA.
  55. ;;
  56. ;;
  57. ;; Description:
  58. ;; ============
  59. ;; A simple trace package that utilizes advice.el. It generates trace 
  60. ;; information in a Lisp-style fashion and inserts it into a trace output
  61. ;; buffer. Tracing can be done in the background (or silently) so that
  62. ;; generation of trace output won't interfere with what you are currently
  63. ;; doing.
  64. ;;
  65. ;; How to get the latest trace.el:
  66. ;; ===============================
  67. ;; You can get the latest version of this file either via anonymous ftp from 
  68. ;; ftp.cs.buffalo.edu (128.205.32.9) with pathname /pub/Emacs/trace.el,
  69. ;; or send email to hans@cs.buffalo.edu and I'll mail it to you.
  70. ;;
  71. ;; Restrictions:
  72. ;; =============
  73. ;; - Traced subrs when called interactively will always show nil as the
  74. ;;   value of ad-subr-args.
  75. ;; - Subrs called from other subrs/C-code won't generate any trace output.
  76. ;; - All the restrictions that apply to advice.el
  77. ;;
  78. ;; Installation:
  79. ;; =============
  80. ;; Put this file together with advice.el (which you can get from the same
  81. ;; ftp directory mentioned above) somewhere into your Emacs load-path, 
  82. ;; byte-compile it/them for efficiency, and put the following autoload 
  83. ;; declaration into your .emacs
  84. ;;
  85. ;;    (autoload 'trace-function "trace" "Trace a function" t nil)
  86. ;;
  87. ;; or explicitly load it with (require 'trace) or (load "trace").
  88. ;;
  89. ;; Comments, suggestions, bug reports
  90. ;; ==================================
  91. ;; are strongly appreciated, please email them to hans@cs.buffalo.edu.
  92. ;; Also feel free to mail me any questions you might have about trace.el.
  93. ;;
  94. ;; Usage:
  95. ;; ======
  96. ;; - To trace a function say M-x trace-function which will ask you for the name
  97. ;;   of the function/subr/macro you want to trace, as well as for the buffer
  98. ;;   into which trace output should go. With a prefix argument the tracing
  99. ;;   will be done silently in the background. 
  100. ;; - To untrace a function say M-x untrace-function and supply the function 
  101. ;;   you want to have untraced as an argument. 
  102. ;; - To untrace all currently traced functions say M-x untrace-all.
  103. ;;
  104. ;;
  105. ;; Examples:
  106. ;; =========
  107. ;;
  108. ;;  (defun fact (n)
  109. ;;    (if (= n 0) 1
  110. ;;      (* n (fact (1- n)))))
  111. ;;  fact
  112. ;;  
  113. ;;  (trace-function 'fact)
  114. ;;  fact
  115. ;;
  116. ;;  ;; Now, evaluating this...
  117. ;;  (fact 4)
  118. ;;  24
  119. ;;
  120. ;;  ;; ...will generate the following in *trace-buffer*:  
  121. ;;  1 -> fact: n=4
  122. ;;  | 2 -> fact: n=3
  123. ;;  | | 3 -> fact: n=2
  124. ;;  | | | 4 -> fact: n=1
  125. ;;  | | | | 5 -> fact: n=0
  126. ;;  | | | | 5 <- fact: 1
  127. ;;  | | | 4 <- fact: 1
  128. ;;  | | 3 <- fact: 2
  129. ;;  | 2 <- fact: 6
  130. ;;  1 <- fact: 24
  131. ;;
  132. ;;
  133. ;;  (defun ack (x y z)
  134. ;;    (if (= x 0) 
  135. ;;        (+ y z)
  136. ;;      (if (and (<= x 2) (= z 0)) 
  137. ;;          (1- x)
  138. ;;        (if (and (> x 2) (= z 0)) 
  139. ;;            y
  140. ;;          (ack (1- x) y (ack x y (1- z)))))))
  141. ;;  ack
  142. ;;
  143. ;;  (trace-function 'ack)
  144. ;;  ack
  145. ;;
  146. ;;  ;; Try this for some interesting trace output:
  147. ;;  (ack 3 3 1)
  148. ;;  27
  149. ;;
  150. ;; 
  151. ;;  ;; The following does something similar to the functionality of the
  152. ;;  ;; package log-message.el by Robert Potter (rpotter@grip.cis.upenn.edu),
  153. ;;  ;; which is giving you a chance to look at messages that might have
  154. ;;  ;; whizzed by too quickly (you won't see subr generated messages though):
  155. ;;
  156. ;;  (trace-function 'message "*Message Log*" t)
  157. ;;
  158.  
  159.  
  160. (require 'advice)
  161. (require 'backquote)
  162.  
  163. (defconst trace-version (substring "$Revision: 1.1 $" 11 -2))
  164.  
  165. (defvar trace-buffer "*trace-output*"
  166.   "Trace output will by default go to that buffer")
  167.  
  168. (defvar traced-functions nil
  169.   "List of functions that are currently traced")
  170.  
  171. (defvar trace-level 0
  172.   "Current level of traced function invocation")
  173.  
  174. (defvar trace-in-background nil
  175.   "If non-NIL all trace ouput will silently go to trace-buffer, otherwise
  176. the execution of a traced function will pop to the trace-buffer.")
  177.  
  178. (defvar trace-separator (format "%s\n" (make-string 70 ?=))
  179.   "Used to separate new trace output from previous traced runs")
  180.  
  181.  
  182. (defun trace-entry-message (function level argument-bindings)
  183.   "Generates a string that describes that FUNCTION has been entered at
  184. trace LEVEL with ARGUMENT-BINDINGS."
  185.   (format "%s%s%d -> %s: %s\n"
  186.       (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
  187.       (if (> level 1) " " "")
  188.       level
  189.       function
  190.       (mapconcat (function
  191.               (lambda (binding)
  192.                (format "%s=%s"
  193.                    (ad-arg-binding-field binding 'name)
  194.                    (ad-arg-binding-field binding 'value))))
  195.              argument-bindings
  196.              " ")))
  197.  
  198. (defun trace-exit-message (function level value)
  199.   "Generates a string that describes that FUNCTION has been exited at
  200. trace LEVEL and that it returned VALUE."
  201.   (format "%s%s%d <- %s: %s\n"
  202.       (mapconcat 'char-to-string (make-string (1- level) ?|) " ")
  203.       (if (> level 1) " " "")
  204.       level
  205.       function
  206.       value))
  207.  
  208. (defun trace-function (function &optional buffer background)
  209.   "Generates the trace advice for FUNCTION and activates it (and all other
  210. advice there might be!!) Trace output will go to BUFFER. If BACKGROUND is
  211. non-NIL (or when called with a prefix argument) trace output will be
  212. generated in the background, otherwise a traced FUNCTION will popup its
  213. trace BUFFER whenever it is called."
  214.   (interactive
  215.    (call-interactively
  216.     (progn
  217.       ;; This seems to be the only way to influence the default used by the
  218.       ;; B specifier in interactive. Messes with buffer list but is much less
  219.       ;; work than doing the correct thing by hand:
  220.       (save-excursion
  221.     (switch-to-buffer (get-buffer-create trace-buffer)))
  222.       '(lambda (function &optional buffer background)
  223.     (interactive "aFunction to trace: \nBOutput to buffer: \nP")
  224.     (list function buffer background)))))
  225.   (ad-add-advice
  226.    function
  227.    (ad-make-advice
  228.     'trace nil
  229.     (` ((let ((trace-level (1+ trace-level))
  230.           (trace-buffer (get-buffer-create (, (or buffer trace-buffer))))
  231.           (trace-in-background (, (and background t))))
  232.       (if (and (= trace-level 1)
  233.            (not trace-in-background))
  234.           (pop-to-buffer trace-buffer))
  235.       (save-excursion
  236.         (set-buffer trace-buffer)
  237.         (goto-char (point-max))
  238.         ;; Insert a separator from previous trace output:
  239.            (if (= trace-level 1) (insert trace-separator))
  240.         (insert
  241.          (trace-entry-message
  242.           '(, function) trace-level ad-arg-bindings)))
  243.       (if (not trace-in-background) (goto-char (point-max)))
  244.       ad-do-it
  245.       (save-excursion
  246.         (set-buffer trace-buffer)
  247.         (goto-char (point-max))
  248.         (insert
  249.          (trace-exit-message
  250.           '(, function) trace-level ad-return-value)))
  251.       (if (not trace-in-background) (goto-char (point-max)))
  252.       ))))
  253.    'around 'last)
  254.   (if (ad-has-proper-definition function)
  255.       (ad-activate function nil))
  256.   (if (not (memq function traced-functions))
  257.       (setq traced-functions (cons function traced-functions)))
  258.   function)
  259.  
  260. (defun untrace-function (function)
  261.   "Untraces FUNCTION and activates all remaining advice information. If 
  262. FUNCTION was not traced this is a noop."
  263.   (interactive "aFunction to untrace: ")
  264.   (cond ((memq function traced-functions)
  265.      (ad-remove-advice function 'around 'trace)
  266.      (if (ad-has-proper-definition function)
  267.          (ad-activate function nil))
  268.      (setq traced-functions (delq function traced-functions))
  269.      function)))
  270.  
  271. (defun untrace-all ()
  272.   "Untraces all currently traced functions"
  273.   (interactive)
  274.   (ad-dolist (traced-fn (copy-alist traced-functions))
  275.      (untrace-function traced-fn)))
  276.  
  277. (provide 'trace)
  278.  
  279. ;; eof
  280.