| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 |
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 |
|
|---|
| 40 |
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
|
|---|
| 50 |
|
|---|
| 51 |
|
|---|
| 52 |
|
|---|
| 53 |
|
|---|
| 54 |
|
|---|
| 55 |
|
|---|
| 56 |
|
|---|
| 57 |
|
|---|
| 58 |
|
|---|
| 59 |
(defalias 'edebug-submit-bug-report 'report-emacs-bug) |
|---|
| 60 |
|
|---|
| 61 |
|
|---|
| 62 |
|
|---|
| 63 |
(defgroup edebug nil |
|---|
| 64 |
"A source-level debugger for Emacs Lisp." |
|---|
| 65 |
:group 'lisp) |
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 |
(defcustom edebug-setup-hook nil |
|---|
| 69 |
"*Functions to call before edebug is used. |
|---|
| 70 |
Each time it is set to a new value, Edebug will call those functions |
|---|
| 71 |
once and then `edebug-setup-hook' is reset to nil. You could use this |
|---|
| 72 |
to load up Edebug specifications associated with a package you are |
|---|
| 73 |
using but only when you also use Edebug." |
|---|
| 74 |
:type 'hook |
|---|
| 75 |
:group 'edebug) |
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
|
|---|
| 81 |
|
|---|
| 82 |
(defcustom edebug-all-defs nil |
|---|
| 83 |
"*If non-nil, evaluating defining forms instruments for Edebug. |
|---|
| 84 |
This applies to `eval-defun', `eval-region', `eval-buffer', and |
|---|
| 85 |
`eval-current-buffer'. `eval-region' is also called by |
|---|
| 86 |
`eval-last-sexp', and `eval-print-last-sexp'. |
|---|
| 87 |
|
|---|
| 88 |
You can use the command `edebug-all-defs' to toggle the value of this |
|---|
| 89 |
variable. You may wish to make it local to each buffer with |
|---|
| 90 |
\(make-local-variable 'edebug-all-defs) in your |
|---|
| 91 |
`emacs-lisp-mode-hook'." |
|---|
| 92 |
:type 'boolean |
|---|
| 93 |
:group 'edebug) |
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 |
|
|---|
| 100 |
(defcustom edebug-all-forms nil |
|---|
| 101 |
"*Non-nil evaluation of all forms will instrument for Edebug. |
|---|
| 102 |
This doesn't apply to loading or evaluations in the minibuffer. |
|---|
| 103 |
Use the command `edebug-all-forms' to toggle the value of this option." |
|---|
| 104 |
:type 'boolean |
|---|
| 105 |
:group 'edebug) |
|---|
| 106 |
|
|---|
| 107 |
(defcustom edebug-eval-macro-args nil |
|---|
| 108 |
"*Non-nil means all macro call arguments may be evaluated. |
|---|
| 109 |
If this variable is nil, the default, Edebug will *not* wrap |
|---|
| 110 |
macro call arguments as if they will be evaluated. |
|---|
| 111 |
For each macro, a `edebug-form-spec' overrides this option. |
|---|
| 112 |
So to specify exceptions for macros that have some arguments evaluated |
|---|
| 113 |
and some not, you should specify an `edebug-form-spec'." |
|---|
| 114 |
:type 'boolean |
|---|
| 115 |
:group 'edebug) |
|---|
| 116 |
|
|---|
| 117 |
(defcustom edebug-save-windows t |
|---|
| 118 |
"*If non-nil, Edebug saves and restores the window configuration. |
|---|
| 119 |
That takes some time, so if your program does not care what happens to |
|---|
| 120 |
the window configurations, it is better to set this variable to nil. |
|---|
| 121 |
|
|---|
| 122 |
If the value is a list, only the listed windows are saved and |
|---|
| 123 |
restored. |
|---|
| 124 |
|
|---|
| 125 |
`edebug-toggle-save-windows' may be used to change this variable." |
|---|
| 126 |
:type '(choice boolean (repeat string)) |
|---|
| 127 |
:group 'edebug) |
|---|
| 128 |
|
|---|
| 129 |
(defcustom edebug-save-displayed-buffer-points nil |
|---|
| 130 |
"*If non-nil, save and restore point in all displayed buffers. |
|---|
| 131 |
|
|---|
| 132 |
Saving and restoring point in other buffers is necessary if you are |
|---|
| 133 |
debugging code that changes the point of a buffer which is displayed |
|---|
| 134 |
in a non-selected window. If Edebug or the user then selects the |
|---|
| 135 |
window, the buffer's point will be changed to the window's point. |
|---|
| 136 |
|
|---|
| 137 |
Saving and restoring point in all buffers is expensive, since it |
|---|
| 138 |
requires selecting each window twice, so enable this only if you need |
|---|
| 139 |
it." |
|---|
| 140 |
:type 'boolean |
|---|
| 141 |
:group 'edebug) |
|---|
| 142 |
|
|---|
| 143 |
(defcustom edebug-initial-mode 'step |
|---|
| 144 |
"*Initial execution mode for Edebug, if non-nil. |
|---|
| 145 |
If this variable is non-nil, it specifies the initial execution mode |
|---|
| 146 |
for Edebug when it is first activated. Possible values are step, next, |
|---|
| 147 |
go, Go-nonstop, trace, Trace-fast, continue, and Continue-fast." |
|---|
| 148 |
:type '(choice (const step) (const next) (const go) |
|---|
| 149 |
(const Go-nonstop) (const trace) |
|---|
| 150 |
(const Trace-fast) (const continue) |
|---|
| 151 |
(const Continue-fast)) |
|---|
| 152 |
:group 'edebug) |
|---|
| 153 |
|
|---|
| 154 |
(defcustom edebug-trace nil |
|---|
| 155 |
"*Non-nil means display a trace of function entry and exit. |
|---|
| 156 |
Tracing output is displayed in a buffer named `*edebug-trace*', one |
|---|
| 157 |
function entry or exit per line, indented by the recursion level. |
|---|
| 158 |
|
|---|
| 159 |
You can customize by replacing functions `edebug-print-trace-before' |
|---|
| 160 |
and `edebug-print-trace-after'." |
|---|
| 161 |
:type 'boolean |
|---|
| 162 |
:group 'edebug) |
|---|
| 163 |
|
|---|
| 164 |
(defcustom edebug-test-coverage nil |
|---|
| 165 |
"*If non-nil, Edebug tests coverage of all expressions debugged. |
|---|
| 166 |
This is done by comparing the result of each expression |
|---|
| 167 |
with the previous result. Coverage is considered OK if two different |
|---|
| 168 |
results are found. |
|---|
| 169 |
|
|---|
| 170 |
Use `edebug-display-freq-count' to display the frequency count and |
|---|
| 171 |
coverage information for a definition." |
|---|
| 172 |
:type 'boolean |
|---|
| 173 |
:group 'edebug) |
|---|
| 174 |
|
|---|
| 175 |
(defcustom edebug-continue-kbd-macro nil |
|---|
| 176 |
"*If non-nil, continue defining or executing any keyboard macro. |
|---|
| 177 |
Use this with caution since it is not debugged." |
|---|
| 178 |
:type 'boolean |
|---|
| 179 |
:group 'edebug) |
|---|
| 180 |
|
|---|
| 181 |
|
|---|
| 182 |
(defcustom edebug-print-length 50 |
|---|
| 183 |
"*Default value of `print-length' for printing results in Edebug." |
|---|
| 184 |
:type 'integer |
|---|
| 185 |
:group 'edebug) |
|---|
| 186 |
(defcustom edebug-print-level 50 |
|---|
| 187 |
"*Default value of `print-level' for printing results in Edebug." |
|---|
| 188 |
:type 'integer |
|---|
| 189 |
:group 'edebug) |
|---|
| 190 |
(defcustom edebug-print-circle t |
|---|
| 191 |
"*Default value of `print-circle' for printing results in Edebug." |
|---|
| 192 |
:type 'boolean |
|---|
| 193 |
:group 'edebug) |
|---|
| 194 |
|
|---|
| 195 |
(defcustom edebug-unwrap-results nil |
|---|
| 196 |
"*Non-nil if Edebug should unwrap results of expressions. |
|---|
| 197 |
This is useful when debugging macros where the results of expressions |
|---|
| 198 |
are instrumented expressions. But don't do this when results might be |
|---|
| 199 |
circular or an infinite loop will result." |
|---|
| 200 |
:type 'boolean |
|---|
| 201 |
:group 'edebug) |
|---|
| 202 |
|
|---|
| 203 |
(defcustom edebug-on-error t |
|---|
| 204 |
"*Value bound to `debug-on-error' while Edebug is active. |
|---|
| 205 |
|
|---|
| 206 |
If `debug-on-error' is non-nil, that value is still used. |
|---|
| 207 |
|
|---|
| 208 |
If the value is a list of signal names, Edebug will stop when any of |
|---|
| 209 |
these errors are signaled from Lisp code whether or not the signal is |
|---|
| 210 |
handled by a `condition-case'. This option is useful for debugging |
|---|
| 211 |
signals that *are* handled since they would otherwise be missed. |
|---|
| 212 |
After execution is resumed, the error is signaled again." |
|---|
| 213 |
:type '(choice (const :tag "off") |
|---|
| 214 |
(repeat :menu-tag "When" |
|---|
| 215 |
:value (nil) |
|---|
| 216 |
(symbol :format "%v")) |
|---|
| 217 |
(const :tag "always" t)) |
|---|
| 218 |
:group 'edebug) |
|---|
| 219 |
|
|---|
| 220 |
(defcustom edebug-on-quit t |
|---|
| 221 |
"*Value bound to `debug-on-quit' while Edebug is active." |
|---|
| 222 |
:type 'boolean |
|---|
| 223 |
:group 'edebug) |
|---|
| 224 |
|
|---|
| 225 |
(defcustom edebug-global-break-condition nil |
|---|
| 226 |
"*If non-nil, an expression to test for at every stop point. |
|---|
| 227 |
If the result is non-nil, then break. Errors are ignored." |
|---|
| 228 |
:type 'sexp |
|---|
| 229 |
:group 'edebug) |
|---|
| 230 |
|
|---|
| 231 |
(defcustom edebug-sit-for-seconds 1 |
|---|
| 232 |
"*Number of seconds to pause when execution mode is `trace'." |
|---|
| 233 |
:type 'number |
|---|
| 234 |
:group 'edebug) |
|---|
| 235 |
|
|---|
| 236 |
|
|---|
| 237 |
|
|---|
| 238 |
(defmacro def-edebug-form-spec (symbol spec-form) |
|---|
| 239 |
"For compatibility with old version." |
|---|
| 240 |
(def-edebug-spec symbol (eval spec-form))) |
|---|
| 241 |
(make-obsolete 'def-edebug-form-spec 'def-edebug-spec "22.1") |
|---|
| 242 |
|
|---|
| 243 |
(defun get-edebug-spec (symbol) |
|---|
| 244 |
|
|---|
| 245 |
(let ((edebug-form-spec (get symbol 'edebug-form-spec)) |
|---|
| 246 |
indirect) |
|---|
| 247 |
(while (and (symbolp edebug-form-spec) |
|---|
| 248 |
(setq indirect (get edebug-form-spec 'edebug-form-spec))) |
|---|
| 249 |
|
|---|
| 250 |
(setq edebug-form-spec indirect)) |
|---|
| 251 |
edebug-form-spec |
|---|
| 252 |
)) |
|---|
| 253 |
|
|---|
| 254 |
|
|---|
| 255 |
(defun edebug-basic-spec (spec) |
|---|
| 256 |
"Return t if SPEC uses only extant spec symbols. |
|---|
| 257 |
An extant spec symbol is a symbol that is not a function and has a |
|---|
| 258 |
`edebug-form-spec' property." |
|---|
| 259 |
(cond ((listp spec) |
|---|
| 260 |
(catch 'basic |
|---|
| 261 |
(while spec |
|---|
| 262 |
(unless (edebug-basic-spec (car spec)) (throw 'basic nil)) |
|---|
| 263 |
(setq spec (cdr spec))) |
|---|
| 264 |
t)) |
|---|
| 265 |
((symbolp spec) |
|---|
| 266 |
(unless (functionp spec) (get spec 'edebug-form-spec))))) |
|---|
| 267 |
|
|---|
| 268 |
|
|---|
| 269 |
|
|---|
| 270 |
|
|---|
| 271 |
(defvar edebug-gensym-index 0 |
|---|
| 272 |
"Integer used by `edebug-gensym' to produce new names.") |
|---|
| 273 |
|
|---|
| 274 |
(defun edebug-gensym (&optional prefix) |
|---|
| 275 |
"Generate a fresh uninterned symbol. |
|---|
| 276 |
There is an optional argument, PREFIX. PREFIX is the |
|---|
| 277 |
string that begins the new name. Most people take just the default, |
|---|
| 278 |
except when debugging needs suggest otherwise." |
|---|
| 279 |
(if (null prefix) |
|---|
| 280 |
(setq prefix "G")) |
|---|
| 281 |
(let ((newsymbol nil) |
|---|
| 282 |
(newname "")) |
|---|
| 283 |
(while (not newsymbol) |
|---|
| 284 |
(setq newname (concat prefix (int-to-string edebug-gensym-index))) |
|---|
| 285 |
(setq edebug-gensym-index (+ edebug-gensym-index 1)) |
|---|
| 286 |
(if (not (intern-soft newname)) |
|---|
| 287 |
(setq newsymbol (make-symbol newname)))) |
|---|
| 288 |
newsymbol)) |
|---|
| 289 |
|
|---|
| 290 |
(defun edebug-lambda-list-keywordp (object) |
|---|
| 291 |
"Return t if OBJECT is a lambda list keyword. |
|---|
| 292 |
A lambda list keyword is a symbol that starts with `&'." |
|---|
| 293 |
(and (symbolp object) |
|---|
| 294 |
(= ?& (aref (symbol-name object) 0)))) |
|---|
| 295 |
|
|---|
| 296 |
|
|---|
| 297 |
(defun edebug-last-sexp () |
|---|
| 298 |
|
|---|
| 299 |
|
|---|
| 300 |
(car |
|---|
| 301 |
(read-from-string |
|---|
| 302 |
(buffer-substring |
|---|
| 303 |
(save-excursion |
|---|
| 304 |
(forward-sexp -1) |
|---|
| 305 |
(point)) |
|---|
| 306 |
(point))))) |
|---|
| 307 |
|
|---|
| 308 |
(defun edebug-window-list () |
|---|
| 309 |
"Return a list of windows, in order of `next-window'." |
|---|
| 310 |
|
|---|
| 311 |
(let (window-list) |
|---|
| 312 |
(walk-windows (lambda (w) (push w window-list))) |
|---|
| 313 |
(nreverse window-list))) |
|---|
| 314 |
|
|---|
| 315 |
|
|---|
| 316 |
'(defun edebug-two-window-p () |
|---|
| 317 |
"Return t if there are two windows." |
|---|
| 318 |
(and (not (one-window-p)) |
|---|
| 319 |
(eq (selected-window) |
|---|
| 320 |
(next-window (next-window (selected-window)))))) |
|---|
| 321 |
|
|---|
| 322 |
(defsubst edebug-lookup-function (object) |
|---|
| 323 |
(while (and (symbolp object) (fboundp object)) |
|---|
| 324 |
(setq object (symbol-function object))) |
|---|
| 325 |
object) |
|---|
| 326 |
|
|---|
| 327 |
(defun edebug-macrop (object) |
|---|
| 328 |
"Return the macro named by OBJECT, or nil if it is not a macro." |
|---|
| 329 |
(setq object (edebug-lookup-function object)) |
|---|
| 330 |
(if (and (listp object) |
|---|
| 331 |
(eq 'macro (car object)) |
|---|
| 332 |
(functionp (cdr object))) |
|---|
| 333 |
object)) |
|---|
| 334 |
|
|---|
| 335 |
(defun edebug-sort-alist (alist function) |
|---|
| 336 |
|
|---|
| 337 |
|
|---|
| 338 |
(sort alist (function |
|---|
| 339 |
(lambda (e1 e2) |
|---|
| 340 |
(funcall function (car e1) (car e2)))))) |
|---|
| 341 |
|
|---|
| 342 |
|
|---|
| 343 |
|
|---|
| 344 |
|
|---|
| 345 |
'(defmacro edebug-save-restriction (&rest body) |
|---|
| 346 |
"Evaluate BODY while saving the current buffers restriction. |
|---|
| 347 |
BODY may change buffer outside of current restriction, unlike |
|---|
| 348 |
save-restriction. BODY may change the current buffer, |
|---|
| 349 |
and the restriction will be restored to the original buffer, |
|---|
| 350 |
and the current buffer remains current. |
|---|
| 351 |
Return the result of the last expression in BODY." |
|---|
| 352 |
`(let ((edebug:s-r-beg (point-min-marker)) |
|---|
| 353 |
(edebug:s-r-end (point-max-marker))) |
|---|
| 354 |
(unwind-protect |
|---|
| 355 |
(progn ,@body) |
|---|
| 356 |
(save-excursion |
|---|
| 357 |
(set-buffer (marker-buffer edebug:s-r-beg)) |
|---|
| 358 |
(narrow-to-region edebug:s-r-beg edebug:s-r-end))))) |
|---|
| 359 |
|
|---|
| 360 |
|
|---|
| 361 |
|
|---|
| 362 |
(defconst edebug-trace-buffer "*edebug-trace*" |
|---|
| 363 |
"Name of the buffer to put trace info in.") |
|---|
| 364 |
|
|---|
| 365 |
(defun edebug-pop-to-buffer (buffer &optional window) |
|---|
| 366 |
|
|---|
| 367 |
|
|---|
| 368 |
|
|---|
| 369 |
|
|---|
| 370 |
(setq window |
|---|
| 371 |
(cond |
|---|
| 372 |
((and (windowp window) (edebug-window-live-p window) |
|---|
| 373 |
(eq (window-buffer window) buffer)) |
|---|
| 374 |
window) |
|---|
| 375 |
((eq (window-buffer (selected-window)) buffer) |
|---|
| 376 |
|
|---|
| 377 |
(selected-window)) |
|---|
| 378 |
((edebug-get-buffer-window buffer)) |
|---|
| 379 |
((one-window-p 'nomini) |
|---|
| 380 |
|
|---|
| 381 |
(split-window)) |
|---|
| 382 |
((let ((trace-window (get-buffer-window edebug-trace-buffer))) |
|---|
| 383 |
(catch 'found |
|---|
| 384 |
(dolist (elt (window-list nil 'nomini)) |
|---|
| 385 |
(unless (or (eq elt (selected-window)) (eq elt trace-window) |
|---|
| 386 |
(window-dedicated-p elt)) |
|---|
| 387 |
|
|---|
| 388 |
|
|---|
| 389 |
(throw 'found elt)))))) |
|---|
| 390 |
|
|---|
| 391 |
|
|---|
| 392 |
(t (split-window)))) |
|---|
| 393 |
(select-window window) |
|---|
| 394 |
(set-window-buffer window buffer) |
|---|
| 395 |
(set-window-hscroll window 0) |
|---|
| 396 |
|
|---|
| 397 |
|
|---|
| 398 |
) |
|---|
| 399 |
|
|---|
| 400 |
(defun edebug-get-displayed-buffer-points () |
|---|
| 401 |
|
|---|
| 402 |
(let (list) |
|---|
| 403 |
(walk-windows (lambda (w) |
|---|
| 404 |
(unless (eq w (selected-window)) |
|---|
| 405 |
(push (cons (window-buffer w) |
|---|
| 406 |
(window-point w)) |
|---|
| 407 |
list)))) |
|---|
| 408 |
list)) |
|---|
| 409 |
|
|---|
| 410 |
|
|---|
| 411 |
(defun edebug-set-buffer-points (buffer-points) |
|---|
| 412 |
|
|---|
| 413 |
(save-current-buffer |
|---|
| 414 |
(mapcar (lambda (buf-point) |
|---|
| 415 |
(when (buffer-live-p (car buf-point)) |
|---|
| 416 |
(set-buffer (car buf-point)) |
|---|
| 417 |
(goto-char (cdr buf-point)))) |
|---|
| 418 |
buffer-points))) |
|---|
| 419 |
|
|---|
| 420 |
(defun edebug-current-windows (which-windows) |
|---|
| 421 |
|
|---|
| 422 |
(if (listp which-windows) |
|---|
| 423 |
(mapcar (function (lambda (window) |
|---|
| 424 |
(if (edebug-window-live-p window) |
|---|
| 425 |
(list window |
|---|
| 426 |
(window-buffer window) |
|---|
| 427 |
(window-point window) |
|---|
| 428 |
(window-start window) |
|---|
| 429 |
(window-hscroll window))))) |
|---|
| 430 |
which-windows) |
|---|
| 431 |
(current-window-configuration))) |
|---|
| 432 |
|
|---|
| 433 |
(defun edebug-set-windows (window-info) |
|---|
| 434 |
|
|---|
| 435 |
(if (listp window-info) |
|---|
| 436 |
(mapcar (function |
|---|
| 437 |
(lambda (one-window-info) |
|---|
| 438 |
(if one-window-info |
|---|
| 439 |
(apply (function |
|---|
| 440 |
(lambda (window buffer point start hscroll) |
|---|
| 441 |
(if (edebug-window-live-p window) |
|---|
| 442 |
(progn |
|---|
| 443 |
(set-window-buffer window buffer) |
|---|
| 444 |
(set-window-point window point) |
|---|
| 445 |
(set-window-start window start) |
|---|
| 446 |
(set-window-hscroll window hscroll))))) |
|---|
| 447 |
one-window-info)))) |
|---|
| 448 |
window-info) |
|---|
| 449 |
(set-window-configuration window-info))) |
|---|
| 450 |
|
|---|
| 451 |
(defalias 'edebug-get-buffer-window 'get-buffer-window) |
|---|
| 452 |
(defalias 'edebug-sit-for 'sit-for) |
|---|
| 453 |
(defalias 'edebug-input-pending-p 'input-pending-p) |
|---|
| 454 |
|
|---|
| 455 |
|
|---|
| 456 |
|
|---|
| 457 |
|
|---|
| 458 |
|
|---|
| 459 |
|
|---|
| 460 |
|
|---|
| 461 |
(or (fboundp 'edebug-original-read) |
|---|
| 462 |
(defalias 'edebug-original-read (symbol-function 'read))) |
|---|
| 463 |
|
|---|
| 464 |
(defun edebug-read (&optional stream) |
|---|
| 465 |
"Read one Lisp expression as text from STREAM, return as Lisp object. |
|---|
| 466 |
If STREAM is nil, use the value of `standard-input' (which see). |
|---|
| 467 |
STREAM or the value of `standard-input' may be: |
|---|
| 468 |
a buffer (read from point and advance it) |
|---|
| 469 |
a marker (read from where it points and advance it) |
|---|
| 470 |
a function (call it with no arguments for each character, |
|---|
| 471 |
call it with a char as argument to push a char back) |
|---|
| 472 |
a string (takes text from string, starting at the beginning) |
|---|
| 473 |
t (read text line using minibuffer and use it). |
|---|
| 474 |
|
|---|
| 475 |
This version, from Edebug, maybe instruments the expression. But the |
|---|
| 476 |
STREAM must be the current buffer to do so. Whether it instruments is |
|---|
| 477 |
also dependent on the values of `edebug-all-defs' and |
|---|
| 478 |
`edebug-all-forms'." |
|---|
| 479 |
(or stream (setq stream standard-input)) |
|---|
| 480 |
(if (eq stream (current-buffer)) |
|---|
| 481 |
(edebug-read-and-maybe-wrap-form) |
|---|
| 482 |
(edebug-original-read stream))) |
|---|
| 483 |
|
|---|
| 484 |
(or (fboundp 'edebug-original-eval-defun) |
|---|
| 485 |
(defalias 'edebug-original-eval-defun (symbol-function 'eval-defun))) |
|---|
| 486 |
|
|---|
| 487 |
|
|---|
| 488 |
|
|---|
| 489 |
(defun edebug-eval-defun (edebug-it) |
|---|
| 490 |
"Evaluate the top-level form containing point, or after point. |
|---|
| 491 |
|
|---|
| 492 |
If the current defun is actually a call to `defvar', then reset the |
|---|
| 493 |
variable using its initial value expression even if the variable |
|---|
| 494 |
already has some other value. (Normally `defvar' does not change the |
|---|
| 495 |
variable's value if it already has a value.) Treat `defcustom' |
|---|
| 496 |
similarly. Reinitialize the face according to `defface' specification. |
|---|
| 497 |
|
|---|
| 498 |
With a prefix argument, instrument the code for Edebug. |
|---|
| 499 |
|
|---|
| 500 |
Setting `edebug-all-defs' to a non-nil value reverses the meaning of |
|---|
| 501 |
the prefix argument. Code is then instrumented when this function is |
|---|
| 502 |
invoked without a prefix argument |
|---|
| 503 |
|
|---|
| 504 |
If acting on a `defun' for FUNCTION, and the function was |
|---|
| 505 |
instrumented, `Edebug: FUNCTION' is printed in the minibuffer. If not |
|---|
| 506 |
instrumented, just FUNCTION is printed. |
|---|
| 507 |
|
|---|
| 508 |
If not acting on a `defun', the result of evaluation is displayed in |
|---|
| 509 |
the minibuffer." |
|---|
| 510 |
(interactive "P") |
|---|
| 511 |
(let* ((edebugging (not (eq (not edebug-it) (not edebug-all-defs)))) |
|---|
| 512 |
(edebug-result) |
|---|
| 513 |
(form |
|---|
| 514 |
(let ((edebug-all-forms edebugging) |
|---|
| 515 |
(edebug-all-defs (eq edebug-all-defs (not edebug-it)))) |
|---|
| 516 |
(edebug-read-top-level-form)))) |
|---|
| 517 |
|
|---|
| 518 |
|
|---|
| 519 |
(cond ((and (eq (car form) 'defvar) |
|---|
| 520 |
(cdr-safe (cdr-safe form))) |
|---|
| 521 |
|
|---|
| 522 |
(makunbound (nth 1 form))) |
|---|
| 523 |
((and (eq (car form) 'defcustom) |
|---|
| 524 |
(default-boundp (nth 1 form))) |
|---|
| 525 |
|
|---|
| 526 |
(set-default (nth 1 form) (eval (nth 2 form)))) |
|---|
| 527 |
((eq (car form) 'defface) |
|---|
| 528 |
|
|---|
| 529 |
(setq face-new-frame-defaults |
|---|
| 530 |
(assq-delete-all (nth 1 form) face-new-frame-defaults)) |
|---|
| 531 |
(put (nth 1 form) 'face-defface-spec nil) |
|---|
| 532 |
|
|---|
| 533 |
(setq form (prog1 `(prog1 ,form |
|---|
| 534 |
(put ',(nth 1 form) 'saved-face |
|---|
| 535 |
',(get (nth 1 form) 'saved-face)) |
|---|
| 536 |
(put ',(nth 1 form) 'customized-face |
|---|
| 537 |
,(nth 2 form))) |
|---|
| 538 |
(put (nth 1 form) 'saved-face nil))))) |
|---|
| 539 |
(setq edebug-result (eval form)) |
|---|
| 540 |
(if (not edebugging) |
|---|
| 541 |
(princ edebug-result) |
|---|
| 542 |
edebug-result))) |
|---|
| 543 |
|
|---|
| 544 |
|
|---|
| 545 |
|
|---|
| 546 |
(defalias 'edebug-defun 'edebug-eval-top-level-form) |
|---|
| 547 |
|
|---|
| 548 |
|
|---|
| 549 |
(defun edebug-eval-top-level-form () |
|---|
| 550 |
"Evaluate the top level form point is in, stepping through with Edebug. |
|---|
| 551 |
This is like `eval-defun' except that it steps the code for Edebug |
|---|
| 552 |
before evaluating it. It displays the value in the echo area |
|---|
| 553 |
using `eval-expression' (which see). |
|---|
| 554 |
|
|---|
| 555 |
If you do this on a function definition |
|---|
| 556 |
such as a defun or defmacro, it defines the function and instruments |
|---|
| 557 |
its definition for Edebug, so it will do Edebug stepping when called |
|---|
| 558 |
later. It displays `Edebug: FUNCTION' in the echo area to indicate |
|---|
| 559 |
that FUNCTION is now instrumented for Edebug. |
|---|
| 560 |
|
|---|
| 561 |
If the current defun is actually a call to `defvar' or `defcustom', |
|---|
| 562 |
evaluating it this way resets the variable using its initial value |
|---|
| 563 |
expression even if the variable already has some other value. |
|---|
| 564 |
\(Normally `defvar' and `defcustom' do not alter the value if there |
|---|
| 565 |
already is one.)" |
|---|
| 566 |
(interactive) |
|---|
| 567 |
(eval-expression |
|---|
| 568 |
|
|---|
| 569 |
|
|---|
| 570 |
(let ((edebug-all-forms t) |
|---|
| 571 |
(edebug-all-defs t)) |
|---|
| 572 |
(edebug-read-top-level-form)))) |
|---|
| 573 |
|
|---|
| 574 |
|
|---|
| 575 |
(defun edebug-read-top-level-form () |
|---|
| 576 |
(let ((starting-point (point))) |
|---|
| 577 |
(end-of-defun) |
|---|
| 578 |
(beginning-of-defun) |
|---|
| 579 |
(prog1 |
|---|
| 580 |
(edebug-read-and-maybe-wrap-form) |
|---|
| 581 |
|
|---|
| 582 |
(goto-char starting-point)))) |
|---|
| 583 |
|
|---|
| 584 |
|
|---|
| 585 |
|
|---|
| 586 |
(defalias 'edebug-all-defuns 'edebug-all-defs) |
|---|
| 587 |
|
|---|
| 588 |
|
|---|
| 589 |
(defun edebug-all-defs () |
|---|
| 590 |
"Toggle edebugging of all definitions." |
|---|
| 591 |
(interactive) |
|---|
| 592 |
(setq edebug-all-defs (not edebug-all-defs)) |
|---|
| 593 |
(message "Edebugging all definitions is %s." |
|---|
| 594 |
(if edebug-all-defs "on" "off"))) |
|---|
| 595 |
|
|---|
| 596 |
|
|---|
| 597 |
|
|---|
| 598 |
(defun edebug-all-forms () |
|---|
| 599 |
"Toggle edebugging of all forms." |
|---|
| 600 |
(interactive) |
|---|
| 601 |
(setq edebug-all-forms (not edebug-all-forms)) |
|---|
| 602 |
(message "Edebugging all forms is %s." |
|---|
| 603 |
(if edebug-all-forms "on" "off"))) |
|---|
| 604 |
|
|---|
| 605 |
|
|---|
| 606 |
(defun edebug-install-read-eval-functions () |
|---|
| 607 |
(interactive) |
|---|
| 608 |
|
|---|
| 609 |
(unless load-read-function |
|---|
| 610 |
(setq load-read-function 'edebug-read) |
|---|
| 611 |
(defalias 'eval-defun 'edebug-eval-defun))) |
|---|
| 612 |
|
|---|
| 613 |
(defun edebug-uninstall-read-eval-functions () |
|---|
| 614 |
(interactive) |
|---|
| 615 |
(setq load-read-function nil) |
|---|
| 616 |
(defalias 'eval-defun (symbol-function 'edebug-original-eval-defun))) |
|---|
| 617 |
|
|---|
| 618 |
|
|---|
| 619 |
|
|---|
| 620 |
|
|---|
| 621 |
|
|---|
| 622 |
|
|---|
| 623 |
|
|---|
| 624 |
(make-variable-buffer-local 'edebug-form-data) |
|---|
| 625 |
|
|---|
| 626 |
(defvar edebug-form-data nil) |
|---|
| 627 |
|
|---|
| 628 |
|
|---|
| 629 |
|
|---|
| 630 |
|
|---|
| 631 |
|
|---|
| 632 |
|
|---|
| 633 |
|
|---|
| 634 |
|
|---|
| 635 |
|
|---|
| 636 |
|
|---|
| 637 |
|
|---|
| 638 |
(defun edebug-make-form-data-entry (symbol begin end) |
|---|
| 639 |
(list symbol begin end)) |
|---|
| 640 |
|
|---|
| 641 |
(defsubst edebug-form-data-name (entry) |
|---|
| 642 |
(car entry)) |
|---|
| 643 |
|
|---|
| 644 |
(defsubst edebug-form-data-begin (entry) |
|---|
| 645 |
(nth 1 entry)) |
|---|
| 646 |
|
|---|
| 647 |
(defsubst edebug-form-data-end (entry) |
|---|
| 648 |
(nth 2 entry)) |
|---|
| 649 |
|
|---|
| 650 |
(defsubst edebug-set-form-data-entry (entry name begin end) |
|---|
| 651 |
(setcar entry name) |
|---|
| 652 |
(set-marker (nth 1 entry) begin) |
|---|
| 653 |
(set-marker (nth 2 entry) end)) |
|---|
| 654 |
|
|---|
| 655 |
(defun edebug-get-form-data-entry (pnt &optional end-point) |
|---|
| 656 |
|
|---|
| 657 |
|
|---|
| 658 |
|
|---|
| 659 |
(let ((rest edebug-form-data) |
|---|
| 660 |
closest-entry |
|---|
| 661 |
(closest-dist 999999)) |
|---|
| 662 |
(while (and rest (< 0 closest-dist)) |
|---|
| 663 |
(let* ((entry (car rest)) |
|---|
| 664 |
(begin (edebug-form-data-begin entry)) |
|---|
| 665 |
(dist (- pnt begin))) |
|---|
| 666 |
(setq rest (cdr rest)) |
|---|
| 667 |
(if (and (<= 0 dist) |
|---|
| 668 |
(< dist closest-dist) |
|---|
| 669 |
(or (not end-point) |
|---|
| 670 |
(= end-point (edebug-form-data-end entry))) |
|---|
| 671 |
(<= pnt (edebug-form-data-end entry))) |
|---|
| 672 |
(setq closest-dist dist |
|---|
| 673 |
closest-entry entry)))) |
|---|
| 674 |
closest-entry)) |
|---|
| 675 |
|
|---|
| 676 |
|
|---|
| 677 |
|
|---|
| 678 |
|
|---|
| 679 |
(defun edebug-form-data-symbol () |
|---|
| 680 |
|
|---|
| 681 |
|
|---|
| 682 |
(or (edebug-form-data-name (edebug-get-form-data-entry (point))) |
|---|
| 683 |
(error "Not inside instrumented form"))) |
|---|
| 684 |
|
|---|
| 685 |
(defun edebug-make-top-form-data-entry (new-entry) |
|---|
| 686 |
|
|---|
| 687 |
(edebug-clear-form-data-entry new-entry) |
|---|
| 688 |
(setq edebug-form-data (cons new-entry edebug-form-data))) |
|---|
| 689 |
|
|---|
| 690 |
(defun edebug-clear-form-data-entry (entry) |
|---|
| 691 |
|
|---|
| 692 |
|
|---|
| 693 |
(if entry |
|---|
| 694 |
(progn |
|---|
| 695 |
|
|---|
| 696 |
|
|---|
| 697 |
|
|---|
| 698 |
|
|---|
| 699 |
|
|---|
| 700 |
|
|---|
| 701 |
(setq edebug-form-data (delq entry edebug-form-data))))) |
|---|
| 702 |
|
|---|
| 703 |
|
|---|
| 704 |
|
|---|
| 705 |
(defun edebug-syntax-error (&rest args) |
|---|
| 706 |
|
|---|
| 707 |
(signal 'invalid-read-syntax args)) |
|---|
| 708 |
|
|---|
| 709 |
|
|---|
| 710 |
(defconst edebug-read-syntax-table |
|---|
| 711 |
|
|---|
| 712 |
|
|---|
| 713 |
(let ((table (make-char-table 'syntax-table 'symbol)) |
|---|
| 714 |
(i 0)) |
|---|
| 715 |
(while (< i ?!) |
|---|
| 716 |
(aset table i 'space) |
|---|
| 717 |
(setq i (1+ i))) |
|---|
| 718 |
(aset table ?\( 'lparen) |
|---|
| 719 |
(aset table ?\) 'rparen) |
|---|
| 720 |
(aset table ?\' 'quote) |
|---|
| 721 |
(aset table ?\` 'backquote) |
|---|
| 722 |
(aset table ?\, 'comma) |
|---|
| 723 |
(aset table ?\" 'string) |
|---|
| 724 |
(aset table ?\? 'char) |
|---|
| 725 |
(aset table ?\[ 'lbracket) |
|---|
| 726 |
(aset table ?\] 'rbracket) |
|---|
| 727 |
(aset table ?\. 'dot) |
|---|
| 728 |
(aset table ?\# 'hash) |
|---|
| 729 |
;; We treat numbers as symbols, because of confusion with -, -1, and 1-. |
|---|
| 730 |
;; We don't care about any other chars since they won't be seen. |
|---|
| 731 |
table)) |
|---|
| 732 |
|
|---|
| 733 |
(defun edebug-next-token-class () |
|---|
| 734 |
;; Move to the next token and return its class. We only care about |
|---|
| 735 |
;; lparen, rparen, dot, quote, backquote, comma, string, char, vector, |
|---|
| 736 |
;; or symbol. |
|---|
| 737 |
(edebug-skip-whitespace) |
|---|
| 738 |
(if (and (eq (following-char) ?.) |
|---|
| 739 |
(save-excursion |
|---|
| 740 |
(forward-char 1) |
|---|
| 741 |
(or (and (eq (aref edebug-read-syntax-table (following-char)) |
|---|
| 742 |
'symbol) |
|---|
| 743 |
(not (= (following-char) ?\;))) |
|---|
| 744 |
(memq (following-char) '(?\, ?\.))))) |
|---|
| 745 |
'symbol |
|---|
| 746 |
(aref edebug-read-syntax-table (following-char)))) |
|---|
| 747 |
|
|---|
| 748 |
|
|---|
| 749 |
(defun edebug-skip-whitespace () |
|---|
| 750 |
;; Leave point before the next token, skipping white space and comments. |
|---|
| 751 |
(skip-chars-forward " \t\r\n\f") |
|---|
| 752 |
(while (= (following-char) ?\;) |
|---|
| 753 |
(skip-chars-forward "^\n") ; skip the comment |
|---|
| 754 |
(skip-chars-forward " \t\r\n\f"))) |
|---|
| 755 |
|
|---|
| 756 |
|
|---|
| 757 |
;; Mostly obsolete reader; still used in one case. |
|---|
| 758 |
|
|---|
| 759 |
(defun edebug-read-sexp () |
|---|
| 760 |
;; Read one sexp from the current buffer starting at point. |
|---|
| 761 |
;; Leave point immediately after it. A sexp can be a list or atom. |
|---|
| 762 |
;; An atom is a symbol (or number), character, string, or vector. |
|---|
| 763 |
;; This works for reading anything legitimate, but it |
|---|
| 764 |
;; is gummed up by parser inconsistencies (bugs?) |
|---|
| 765 |
(let ((class (edebug-next-token-class))) |
|---|
| 766 |
(cond |
|---|
| 767 |
;; read goes one too far if a (possibly quoted) string or symbol |
|---|
| 768 |
;; is immediately followed by non-whitespace. |
|---|
| 769 |
((eq class 'symbol) (edebug-original-read (current-buffer))) |
|---|
| 770 |
((eq class 'string) (edebug-original-read (current-buffer))) |
|---|
| 771 |
((eq class 'quote) (forward-char 1) |
|---|
| 772 |
(list 'quote (edebug-read-sexp))) |
|---|
| 773 |
((eq class 'backquote) |
|---|
| 774 |
(list '\` (edebug-read-sexp))) |
|---|
| 775 |
((eq class 'comma) |
|---|
| 776 |
(list '\, (edebug-read-sexp))) |
|---|
| 777 |
(t ; anything else, just read it. |
|---|
| 778 |
(edebug-original-read (current-buffer)))))) |
|---|
| 779 |
|
|---|
| 780 |
;;; Offsets for reader |
|---|
| 781 |
|
|---|
| 782 |
;; Define a structure to represent offset positions of expressions. |
|---|
| 783 |
;; Each offset structure looks like: (before . after) for constituents, |
|---|
| 784 |
;; or for structures that have elements: (before <subexpressions> . after) |
|---|
| 785 |
;; where the <subexpressions> are the offset structures for subexpressions |
|---|
| 786 |
;; including the head of a list. |
|---|
| 787 |
(defvar edebug-offsets nil) |
|---|
| 788 |
|
|---|
| 789 |
;; Stack of offset structures in reverse order of the nesting. |
|---|
| 790 |
;; This is used to get back to previous levels. |
|---|
| 791 |
(defvar edebug-offsets-stack nil) |
|---|
| 792 |
(defvar edebug-current-offset nil) ; Top of the stack, for convenience. |
|---|
| 793 |
|
|---|
| 794 |
;; We must store whether we just read a list with a dotted form that |
|---|
| 795 |
;; is itself a list. This structure will be condensed, so the offsets |
|---|
| 796 |
;; must also be condensed. |
|---|
| 797 |
(defvar edebug-read-dotted-list nil) |
|---|
| 798 |
|
|---|
| 799 |
(defsubst edebug-initialize-offsets () |
|---|
| 800 |
;; Reinitialize offset recording. |
|---|
| 801 |
(setq edebug-current-offset nil)) |
|---|
| 802 |
|
|---|
| 803 |
(defun edebug-store-before-offset (point) |
|---|
| 804 |
;; Add a new offset pair with POINT as the before offset. |
|---|
| 805 |
(let ((new-offset (list point))) |
|---|
| 806 |
(if edebug-current-offset |
|---|
| 807 |
(setcdr edebug-current-offset |
|---|
| 808 |
(cons new-offset (cdr edebug-current-offset))) |
|---|
| 809 |
;; Otherwise, we are at the top level, so initialize. |
|---|
| 810 |
(setq edebug-offsets new-offset |
|---|
| 811 |
edebug-offsets-stack nil |
|---|
| 812 |
edebug-read-dotted-list nil)) |
|---|
| 813 |
;; Cons the new offset to the front of the stack. |
|---|
| 814 |
(setq edebug-offsets-stack (cons new-offset edebug-offsets-stack) |
|---|
| 815 |
edebug-current-offset new-offset) |
|---|
| 816 |
)) |
|---|
| 817 |
|
|---|
| 818 |
(defun edebug-store-after-offset (point) |
|---|
| 819 |
;; Finalize the current offset struct by reversing it and |
|---|
| 820 |
;; store POINT as the after offset. |
|---|
| 821 |
(if (not edebug-read-dotted-list) |
|---|
| 822 |
;; Just reverse the offsets of all subexpressions. |
|---|
| 823 |
(setcdr edebug-current-offset (nreverse (cdr edebug-current-offset))) |
|---|
| 824 |
|
|---|
| 825 |
;; We just read a list after a dot, which will be abbreviated out. |
|---|
| 826 |
(setq edebug-read-dotted-list nil) |
|---|
| 827 |
;; Drop the corresponding offset pair. |
|---|
| 828 |
;; That is, nconc the reverse of the rest of the offsets |
|---|
| 829 |
;; with the cdr of last offset. |
|---|
| 830 |
(setcdr edebug-current-offset |
|---|
| 831 |
(nconc (nreverse (cdr (cdr edebug-current-offset))) |
|---|
| 832 |
(cdr (car (cdr edebug-current-offset)))))) |
|---|
| 833 |
|
|---|
| 834 |
;; Now append the point using nconc. |
|---|
| 835 |
(setq edebug-current-offset (nconc edebug-current-offset point)) |
|---|
| 836 |
;; Pop the stack. |
|---|
| 837 |
(setq edebug-offsets-stack (cdr edebug-offsets-stack) |
|---|
| 838 |
edebug-current-offset (car edebug-offsets-stack))) |
|---|
| 839 |
|
|---|
| 840 |
(defun edebug-ignore-offset () |
|---|
| 841 |
;; Ignore the last created offset pair. |
|---|
| 842 |
(setcdr edebug-current-offset (cdr (cdr edebug-current-offset)))) |
|---|
| 843 |
|
|---|
| 844 |
(defmacro edebug-storing-offsets (point &rest body) |
|---|
| 845 |
(declare (debug (form body)) (indent 1)) |
|---|
| 846 |
`(unwind-protect |
|---|
| 847 |
(progn |
|---|
| 848 |
(edebug-store-before-offset ,point) |
|---|
| 849 |
,@body) |
|---|
| 850 |
(edebug-store-after-offset (point)))) |
|---|
| 851 |
|
|---|
| 852 |
|
|---|
| 853 |
;;; Reader for Emacs Lisp. |
|---|
| 854 |
|
|---|
| 855 |
;; Uses edebug-next-token-class (and edebug-skip-whitespace) above. |
|---|
| 856 |
|
|---|
| 857 |
(defconst edebug-read-alist |
|---|
| 858 |
'((symbol . edebug-read-symbol) |
|---|
| 859 |
(lparen . edebug-read-list) |
|---|
| 860 |
|---|