* Problems with debug-on-entry in the Lisp debugger. @ 2005-03-07 11:05 Lute Kamstra 2005-03-07 13:31 ` Stefan Monnier ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Lute Kamstra @ 2005-03-07 11:05 UTC (permalink / raw) Debug-on-entry currently changes the definition of functions by adding code that enters the debugger. This code needs be hidden from the user of the debugger, which can be hard. Redefining the function also removes this code and thus cancels debug-on-entry, which is inconvenient. I'll give some more details on these problems below and propose an new implementation of debug-on-entry that (hopefully) solves these problems. I'm currently working on three bugs in the debugger that have to do with debug-on-entry: 1. When using `d' in the debugger to step through code, you can encounter the code added by debug-on-entry. For example: you have two functions, f-outer and f-inner, and f-outer calls f-inner, and you set both to debug-on-entry. If a call to f-outer puts you in the debugger and you decide to step through the function with `d', then you will encounter the code added by debug-on-entry. This is not only bad because it shows the debugger's internals and can thus cause confusion, but it also bad because it effectively stops you from stepping into f-inner since you will just step into the debugger. The only solution (within the current implementation) that I can think of, is to temporarily remove all debug-on-entry code while stepping with `d'. This could change the definition of the function currently being debugged, which is rather tricky. 2. The debugger keeps a list of functions, debug-function-list, that are set to debug-on-entry. Redefining a function set to debug-on-entry effectively disables debug-on-entry but doesn't remove it from debug-function-list. Richard proposed to change defun, defmacro, defsubst or defalias to let them put in debug-on-entry code when a function is in debug-function-list. Stefan suggested to use advice to cause functions to debug-on-entry. 3. Debug-on-entry for macros is currently broken: debug-on-entry just strips the car (i.e. `macro') of the macro definition and treats it as if it was a function. This not only makes debug-on-entry for macros useless, but it also breaks the macro definition itself; even a subsequent cancel-debug-on-entry will not put `macro' back. I can think of two points in a macro to set a break for the debugger: just before macro expansion and just after it, right before the evaluation of the resulting sexp. In both cases, hiding the debug-on-entry code from the user of the debugger seems not possible. When I was thinking about these three problems, it seemed to me that the easiest and simplest thing to do, is to move support for debug-on-entry into the C implementation of the Lisp interpreter. To mark a function for debug-on-entry, you could set the debug-on-entry property of the function's symbol and the Lisp interpreter would then call the debugger. This doesn't change the definition of functions so it hides the debuggers internals much better. So it solves problem 1. Redefining a function does not effect the debug-on-entry property on the symbol so problem 2 is solved as well. From the lisp interpreter it would also be easy to call the debugger before and/or after macro expansion, thus solving 3 as well. The big disadvantage is that the Lisp interpreter has to check the properties of every functions it evaluates. This slows down the overall speed of the interpreter. This could be mostly solved by using a `debug-on-entry' variable that defaults to nil. The Lisp interpreter will only consider the debug-on-entry property of functions if the debug-on-entry variable is non-nil. The debugger would then only set this variable to a non-nil value if the debug-function-list is not empty. So the overhead of moving debug-on-entry support into the Lisp interpreter would then be one variable check per function call. This seems acceptable to me. Shall I go ahead and try to implement this, or do people think this is a bad idea? Lute. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 11:05 Problems with debug-on-entry in the Lisp debugger Lute Kamstra @ 2005-03-07 13:31 ` Stefan Monnier 2005-03-07 15:20 ` Lute Kamstra 2005-03-07 13:40 ` Kim F. Storm 2005-03-08 2:53 ` Richard Stallman 2 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier @ 2005-03-07 13:31 UTC (permalink / raw) Cc: emacs-devel > I can think of two points in a macro to set a break for the > debugger: just before macro expansion and just after it, right > before the evaluation of the resulting sexp. In both cases, hiding > the debug-on-entry code from the user of the debugger seems not > possible. To me "entry of a macro" is very clearly "just before expansion". Especially if you think of macro-expansion occurring because of explicit calls to macroexpand (e.g. in the byte-compiler) rather than as a direct part of interpretation. > Shall I go ahead and try to implement this, or do people think this is > a bad idea? I think it's a bad idea. The interpreter is already way too slow, I'd rather not make it worse. Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 13:31 ` Stefan Monnier @ 2005-03-07 15:20 ` Lute Kamstra 2005-03-07 16:32 ` Stefan Monnier 0 siblings, 1 reply; 19+ messages in thread From: Lute Kamstra @ 2005-03-07 15:20 UTC (permalink / raw) Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> I can think of two points in a macro to set a break for the >> debugger: just before macro expansion and just after it, right >> before the evaluation of the resulting sexp. In both cases, >> hiding the debug-on-entry code from the user of the debugger >> seems not possible. > > To me "entry of a macro" is very clearly "just before expansion". > Especially if you think of macro-expansion occurring because of > explicit calls to macroexpand (e.g. in the byte-compiler) rather > than as a direct part of interpretation. I see you implemented this. This makes debug-on-entry for macros a lot better, of course. Thanks. But the problem I mentioned remains: the debug-entry-code is visible. For example: (defmacro inc (var) (list 'setq var (list '1+ var))) (debug-on-entry 'inc) (progn (setq x 0) (inc x)) gives a backtrace like this: ------ Buffer: *Backtrace* ------ Debugger entered--entering a function: * (lambda (var) (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)) (list (quote setq) var (list ... var)))(x) (inc x) (progn (setq x 0) (inc x)) eval((progn (setq x 0) (inc x))) eval-last-sexp-1(nil) eval-last-sexp(nil) call-interactively(eval-last-sexp) ------ Buffer: *Backtrace* ------ >> Shall I go ahead and try to implement this, or do people think this >> is a bad idea? > > I think it's a bad idea. The interpreter is already way too slow, > I'd rather not make it worse. I think the effect on performance will be very minimal. Do you know of a good way to test the performance of the interpreter so that I can measure the impact of my proposed change? Can you indicate how much performance loss would be acceptable for you? Lute. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 15:20 ` Lute Kamstra @ 2005-03-07 16:32 ` Stefan Monnier 2005-03-08 18:57 ` Lute Kamstra 0 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier @ 2005-03-07 16:32 UTC (permalink / raw) Cc: emacs-devel > I see you implemented this. This makes debug-on-entry for macros a > lot better, of course. Thanks. But the problem I mentioned remains: > the debug-entry-code is visible. [...] > Debugger entered--entering a function: > * (lambda (var) (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)) (list (quote setq) var (list ... var)))(x) > (inc x) [...] Other than the aesthetic aspect (which we can fix by just removing the offending line in an ad-hoc way), does it have any real impact? > I think the effect on performance will be very minimal. But I see no compelling reason to pay this price. After all, we've live for many years with this elisp implementation without nearly any complaint. If the aesthetic aspect is just more serious now that we replace (debug 'debug) with (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug 'debug)), we can define a function named e.g. `debug-entering' that will do the checking of inhibit-debug-on-entry and debugger-jumping-flag. Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 16:32 ` Stefan Monnier @ 2005-03-08 18:57 ` Lute Kamstra 2005-03-09 16:58 ` Richard Stallman 0 siblings, 1 reply; 19+ messages in thread From: Lute Kamstra @ 2005-03-08 18:57 UTC (permalink / raw) Cc: emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> I see you implemented this. This makes debug-on-entry for macros a >> lot better, of course. Thanks. But the problem I mentioned remains: >> the debug-entry-code is visible. > [...] >> Debugger entered--entering a function: >> * (lambda (var) (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)) (list (quote setq) var (list ... var)))(x) >> (inc x) > [...] > > Other than the aesthetic aspect (which we can fix by just removing the > offending line in an ad-hoc way), Actually, I'd like to see the line, but not the "(if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...))". > does it have any real impact? It can be confusing for new users of the debugger: Hey, what's that doing in my function? Did I put that there? >> I think the effect on performance will be very minimal. > > But I see no compelling reason to pay this price. > > After all, we've live for many years with this elisp implementation > without nearly any complaint. That's not really a valid argument. The macro handling bug was in there for years without any complaint too. Yet you fixed it. ;-) > If the aesthetic aspect is just more serious now that we replace > (debug 'debug) with (if (or inhibit-debug-on-entry > debugger-jumping-flag) nil (debug 'debug)), we can define a function > named e.g. `debug-entering' that will do the checking of > inhibit-debug-on-entry and debugger-jumping-flag. That would be somewhat better. However, I still feel that moving debug-on-entry to the lisp interpreter is "the right thing". It makes the hole thing better a lot simpler. Lute. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-08 18:57 ` Lute Kamstra @ 2005-03-09 16:58 ` Richard Stallman 2005-03-09 17:30 ` Lute Kamstra 0 siblings, 1 reply; 19+ messages in thread From: Richard Stallman @ 2005-03-09 16:58 UTC (permalink / raw) Cc: monnier, emacs-devel > does it have any real impact? It can be confusing for new users of the debugger: Hey, what's that doing in my function? Did I put that there? The user probably rembemers having set "debug on entry" for the function, and has just been reminded by entering the debugger, so that ought to help him understand. > If the aesthetic aspect is just more serious now that we replace > (debug 'debug) with (if (or inhibit-debug-on-entry > debugger-jumping-flag) nil (debug 'debug)), we can define a function > named e.g. `debug-entering' that will do the checking of > inhibit-debug-on-entry and debugger-jumping-flag. That would be somewhat better. Using the name implement-debug-on-entry will help the user figure out why it is there. the user to understand. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-09 16:58 ` Richard Stallman @ 2005-03-09 17:30 ` Lute Kamstra 0 siblings, 0 replies; 19+ messages in thread From: Lute Kamstra @ 2005-03-09 17:30 UTC (permalink / raw) Cc: monnier, emacs-devel Richard Stallman <rms@gnu.org> writes: > > does it have any real impact? > > It can be confusing for new users of the debugger: Hey, what's > that doing in my function? Did I put that there? > > The user probably rembemers having set "debug on entry" for the > function, and has just been reminded by entering the debugger, so > that ought to help him understand. True. > > If the aesthetic aspect is just more serious now that we > > replace (debug 'debug) with (if (or inhibit-debug-on-entry > > debugger-jumping-flag) nil (debug 'debug)), we can define a > > function named e.g. `debug-entering' that will do the checking > > of inhibit-debug-on-entry and debugger-jumping-flag. > > That would be somewhat better. > > Using the name implement-debug-on-entry will help the user figure > out why it is there. Ok, I'll implement this. Lute. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 11:05 Problems with debug-on-entry in the Lisp debugger Lute Kamstra 2005-03-07 13:31 ` Stefan Monnier @ 2005-03-07 13:40 ` Kim F. Storm 2005-03-07 14:20 ` drkm 2005-03-08 2:53 ` Richard Stallman 2 siblings, 1 reply; 19+ messages in thread From: Kim F. Storm @ 2005-03-07 13:40 UTC (permalink / raw) Cc: emacs-devel Lute Kamstra <Lute.Kamstra.lists@xs4all.nl> writes: > When I was thinking about these three problems, it seemed to me that > the easiest and simplest thing to do, is to move support for > debug-on-entry into the C implementation of the Lisp interpreter. To > mark a function for debug-on-entry, you could set the debug-on-entry > property of the function's symbol and the Lisp interpreter would then > call the debugger. You could define a bit in the Lisp_Symbol, like this: struct Lisp_Symbol { unsigned gcmarkbit : 1; /* Non-zero means symbol serves as a variable alias. The symbol holding the real value is found in the value slot. */ unsigned indirect_variable : 1; /* Non-zero means call debugger on entry. */ unsigned debug_on_entry; ... }; Then you would define debug-on-entry and cancel-debug-on-entry in C as well, which simply set or clear that bit. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 13:40 ` Kim F. Storm @ 2005-03-07 14:20 ` drkm 2005-03-07 14:45 ` Kim F. Storm 0 siblings, 1 reply; 19+ messages in thread From: drkm @ 2005-03-07 14:20 UTC (permalink / raw) storm@cua.dk (Kim F. Storm) writes: > You could define a bit in the Lisp_Symbol, like this: > struct Lisp_Symbol > { [...] > unsigned debug_on_entry; ^^^ Really?-) --drkm ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 14:20 ` drkm @ 2005-03-07 14:45 ` Kim F. Storm 0 siblings, 0 replies; 19+ messages in thread From: Kim F. Storm @ 2005-03-07 14:45 UTC (permalink / raw) Cc: emacs-devel drkm <darkman_spam@yahoo.fr> writes: > Really?-) Ouch. That should have been: unsigned debug_on_entry : 1; -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-07 11:05 Problems with debug-on-entry in the Lisp debugger Lute Kamstra 2005-03-07 13:31 ` Stefan Monnier 2005-03-07 13:40 ` Kim F. Storm @ 2005-03-08 2:53 ` Richard Stallman 2005-03-08 18:02 ` Lute Kamstra 2 siblings, 1 reply; 19+ messages in thread From: Richard Stallman @ 2005-03-08 2:53 UTC (permalink / raw) Cc: emacs-devel The only solution (within the current implementation) that I can think of, is to temporarily remove all debug-on-entry code while stepping with `d'. Would setting inhibit-debug-on-entry temporarily do the job? I can think of two points in a macro to set a break for the debugger: just before macro expansion and just after it, right before the evaluation of the resulting sexp. The correct place to do it is before macro expansion. This is a very evident bug, so please just fix it if you can. In both cases, hiding the debug-on-entry code from the user of the debugger seems not possible. I am not sure what that means. When I was thinking about these three problems, it seemed to me that the easiest and simplest thing to do, is to move support for debug-on-entry into the C implementation of the Lisp interpreter. To mark a function for debug-on-entry, you could set the debug-on-entry property of the function's symbol and the Lisp interpreter would then call the debugger. I agree this is undesirable due to slowness. I don't see a need for this big a change. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-08 2:53 ` Richard Stallman @ 2005-03-08 18:02 ` Lute Kamstra 2005-03-08 18:59 ` Stefan Monnier ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Lute Kamstra @ 2005-03-08 18:02 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > The only solution (within the current implementation) that I can > think of, is to temporarily remove all debug-on-entry code while > stepping with `d'. > > Would setting inhibit-debug-on-entry temporarily do the job? inhibit-debug-on-entry cannot be set from within the debugger because it is shadowed by a let binding. That's what I introduced debugger-jumping-flag for. Temporary setting debugger-jumping-flag would solve the problem of stepping into the code of the debugger. (I'll implement this fix.) The debug-entry-code would still be visible in the backtrace however. > I can think of two points in a macro to set a break for the > debugger: just before macro expansion and just after it, right > before the evaluation of the resulting sexp. > > The correct place to do it is before macro expansion. > This is a very evident bug, so please just fix it if you can. Stefan already did this. > In both cases, hiding > the debug-on-entry code from the user of the debugger seems not > possible. > > I am not sure what that means. Consider this example (with Stefan's fix for macro's installed): (defmacro inc (var) (list 'setq var (list '1+ var))) (debug-on-entry 'inc) (progn (setq x 0) (inc x)) This gives a backtrace like this: ------ Buffer: *Backtrace* ------ Debugger entered--entering a function: * (lambda (var) (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)) (list (quote setq) var (list ... var)))(x) (inc x) (progn (setq x 0) (inc x)) eval((progn (setq x 0) (inc x))) eval-last-sexp-1(nil) eval-last-sexp(nil) call-interactively(eval-last-sexp) ------ Buffer: *Backtrace* ------ where you can see the debug-entry-code (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)). I would prefer to hide the internals of the debugger from its users. Moving support for debug-on-entry into the lisp interpreter (just like support for stepping is in the lisp interpreter) would make this possible (and easy). > When I was thinking about these three problems, it seemed to me that > the easiest and simplest thing to do, is to move support for > debug-on-entry into the C implementation of the Lisp interpreter. To > mark a function for debug-on-entry, you could set the debug-on-entry > property of the function's symbol and the Lisp interpreter would then > call the debugger. > > I agree this is undesirable due to slowness. My proposed change would add one test like if (debug_on_entry) ... to Feval and Ffuncall. And when no functions are set to break on entry (i.e., the normal situation), debug_on_entry will be zero. Do you think that this will have a significant impact on performance? > I don't see a need for this big a change. You proposed to change defun, defsubst, defalias and defmacro to add debug-entry-code when their argument was in debug-function-list. That is a similarly big change. Below is a quick "proof-of-concept" patch for src/eval.c and lisp/emacs-lisp/debug.el to get a better idea of what I mean. As you can see, the change to eval.c isn't that big. The change in debug.el is more substantial, but the code becomes a lot simpler. I also did a quick-and-dirty test to measure the performance impact of the patch but I did not see any effect on speed; so I suppose it is negligible. Lute. Index: src/eval.c =================================================================== RCS file: /cvsroot/emacs/emacs/src/eval.c,v retrieving revision 1.234 diff -u -r1.234 eval.c --- src/eval.c 6 Mar 2005 16:02:47 -0000 1.234 +++ src/eval.c 8 Mar 2005 14:58:49 -0000 @@ -1,6 +1,6 @@ /* Evaluator for GNU Emacs Lisp interpreter. - Copyright (C) 1985, 86, 87, 93, 94, 95, 99, 2000, 2001, 02, 2004 - Free Software Foundation, Inc. + Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1999, 2000, 2001, + 2002, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -91,6 +91,7 @@ Lisp_Object Qautoload, Qmacro, Qexit, Qinteractive, Qcommandp, Qdefun; Lisp_Object Qinhibit_quit, Vinhibit_quit, Vquit_flag; Lisp_Object Qand_rest, Qand_optional; +Lisp_Object Qdebug_on_entry, Qdebug; Lisp_Object Qdebug_on_error; Lisp_Object Qdeclare; @@ -135,6 +136,14 @@ int debug_on_next_call; +/* Nonzero means check the debug-on-entry property of functions. */ + +int debug_on_entry; + +/* Nonzero means dont't check the debug-on-entry property of functions. */ + +int suspend_debug_on_entry; + /* Non-zero means debugger may continue. This is zero when the debugger is called during redisplay, where it might not be safe to continue the interrupted redisplay. */ @@ -206,6 +215,8 @@ specpdl_ptr = specpdl; max_specpdl_size = 1000; max_lisp_eval_depth = 300; + debug_on_entry = 0; + suspend_debug_on_entry = 0; Vrun_hooks = Qnil; } @@ -2051,6 +2062,11 @@ if (debug_on_next_call) do_debug_on_call (Qt); + else if (debug_on_entry && + ! suspend_debug_on_entry && + SYMBOLP (original_fun) && + ! NILP (Fget (original_fun, Qdebug_on_entry))) + do_debug_on_call (Qdebug); /* At this point, only original_fun and original_args have values that will be used below */ @@ -2741,6 +2757,11 @@ if (debug_on_next_call) do_debug_on_call (Qlambda); + else if (debug_on_entry && + ! suspend_debug_on_entry && + SYMBOLP (args[0]) && + ! NILP (Fget (args[0], Qdebug_on_entry))) + do_debug_on_call (Qdebug); retry: @@ -3379,6 +3400,12 @@ Qexit = intern ("exit"); staticpro (&Qexit); + Qdebug_on_entry = intern ("debug-on-entry"); + staticpro (&Qdebug_on_entry); + + Qdebug = intern ("debug"); + staticpro (&Qdebug); + Qinteractive = intern ("interactive"); staticpro (&Qinteractive); @@ -3432,6 +3459,18 @@ DEFVAR_BOOL ("debug-on-next-call", &debug_on_next_call, doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */); + DEFVAR_BOOL ("debug-on-entry", &debug_on_entry, + doc: /* Non-nil means debug-on-entry is enabled. +When debug-on-entry is enabled, the debugger in entered when functions +are called that have the debug-on-entry property set. */); + + DEFVAR_BOOL ("suspend-debug-on-entry", &suspend_debug_on_entry, + doc: /* Non-nil means debug-on-entry is disabled. +When this variable is nil, the variable `debug-on-entry' determines +whether debug-on-entry is enabled. When debug-on-entry is enabled, +the debugger in entered when functions are called that have the +debug-on-entry property set. */); + DEFVAR_BOOL ("debugger-may-continue", &debugger_may_continue, doc: /* Non-nil means debugger may continue execution. This is nil when the debugger is called under circumstances where it Index: lisp/emacs-lisp/debug.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/emacs-lisp/debug.el,v retrieving revision 1.73 diff -u -r1.73 debug.el --- lisp/emacs-lisp/debug.el 7 Mar 2005 14:12:26 -0000 1.73 +++ lisp/emacs-lisp/debug.el 8 Mar 2005 14:58:50 -0000 @@ -89,21 +89,6 @@ (defvar debugger-outer-inhibit-redisplay) (defvar debugger-outer-cursor-in-echo-area) -(defvar inhibit-debug-on-entry nil - "Non-nil means that debug-on-entry is disabled.") - -(defvar debugger-jumping-flag nil - "Non-nil means that debug-on-entry is disabled. -This variable is used by `debugger-jump' and `debugger-reenable'.") - -;; When you change this, you may also need to change the number of -;; frames that the debugger skips. -(defconst debug-entry-code - '(if (or inhibit-debug-on-entry debugger-jumping-flag) - nil - (debug 'debug)) - "Code added to a function to cause it to call the debugger upon entry.") - ;;;###autoload (setq debugger 'debug) ;;;###autoload @@ -124,6 +109,7 @@ (let (debugger-value (debug-on-error nil) (debug-on-quit nil) + (debug-on-entry nil) (debugger-buffer (let ((default-major-mode 'fundamental-mode)) (get-buffer-create "*Backtrace*"))) (debugger-old-buffer (current-buffer)) @@ -159,7 +145,6 @@ ;; Don't let these magic variables affect the debugger itself. (let ((last-command nil) this-command track-mouse (inhibit-trace t) - (inhibit-debug-on-entry t) unread-command-events unread-post-input-method-events last-input-event last-command-event last-nonmenu-event @@ -198,9 +183,8 @@ (message "%s" (buffer-string)) (kill-emacs)) (if (eq (car debugger-args) 'debug) - ;; Skip the frames for backtrace-debug, byte-code, - ;; and debug-entry-code. - (backtrace-debug 4 t)) + ;; Skip the frames for backtrace-debug and byte-code. + (backtrace-debug 3 t)) (message "") (let ((standard-output nil) (buffer-read-only t)) @@ -262,9 +246,7 @@ (delete-region (point) (progn (search-forward "\n debug(") - (forward-line (if (eq (car debugger-args) 'debug) - 2 ; Remove debug-entry-code frame. - 1)) + (forward-line 1) (point))) (insert "Debugger entered") ;; lambda is for debug-on-call when a function call is next. @@ -409,7 +391,7 @@ "Continue to exit from this frame, with all debug-on-entry suspended." (interactive) (debugger-frame) - (setq debugger-jumping-flag t) + (setq suspend-debug-on-entry t) (add-hook 'post-command-hook 'debugger-reenable) (message "Continuing through this frame") (exit-recursive-edit)) @@ -418,7 +400,7 @@ "Turn all debug-on-entry functions back on. This function is put on `post-command-hook' by `debugger-jump' and removes itself from that hook." - (setq debugger-jumping-flag nil) + (setq suspend-debug-on-entry nil) (remove-hook 'post-command-hook 'debugger-reenable)) (defun debugger-frame-number () @@ -429,9 +411,6 @@ (count 0)) (while (not (eq (cadr (backtrace-frame count)) 'debug)) (setq count (1+ count))) - ;; Skip debug-entry-code frame. - (when (member '(debug (quote debug)) (cdr (backtrace-frame (1+ count)))) - (setq count (1+ count))) (goto-char (point-min)) (when (looking-at "Debugger entered--\\(Lisp error\\|returning value\\):") (goto-char (match-end 0)) @@ -624,29 +603,16 @@ (defun debug-on-entry (function) "Request FUNCTION to invoke debugger each time it is called. If you tell the debugger to continue, FUNCTION's execution proceeds. -This works by modifying the definition of FUNCTION, -which must be written in Lisp, not predefined. -Use \\[cancel-debug-on-entry] to cancel the effect of this command. -Redefining FUNCTION also cancels it." +This works by setting the debug-on-entry property of FUNCTION. +Use \\[cancel-debug-on-entry] to cancel the effect of this command." (interactive "aDebug on entry (to function): ") ;; Handle a function that has been aliased to some other function. (if (and (subrp (symbol-function function)) (eq (cdr (subr-arity (symbol-function function))) 'unevalled)) (error "Function %s is a special form" function)) - (if (or (symbolp (symbol-function function)) - (subrp (symbol-function function))) - ;; Create a wrapper in which we can then add the necessary debug call. - (fset function `(lambda (&rest debug-on-entry-args) - ,(interactive-form (symbol-function function)) - (apply ',(symbol-function function) - debug-on-entry-args)))) - (or (consp (symbol-function function)) - (debug-convert-byte-code function)) - (or (consp (symbol-function function)) - (error "Definition of %s is not a list" function)) - (fset function (debug-on-entry-1 function (symbol-function function) t)) - (or (memq function debug-function-list) - (push function debug-function-list)) + (put function 'debug-on-entry t) + (add-to-list 'debug-function-list function) + (setq debug-on-entry t) function) ;;;###autoload @@ -661,56 +627,14 @@ (if name (intern name))))) (if (and function (not (string= function ""))) (progn - (let ((f (debug-on-entry-1 function (symbol-function function) nil))) - (condition-case nil - (if (and (equal (nth 1 f) '(&rest debug-on-entry-args)) - (eq (car (nth 3 f)) 'apply)) - ;; `f' is a wrapper introduced in debug-on-entry. - ;; Get rid of it since we don't need it any more. - (setq f (nth 1 (nth 1 (nth 3 f))))) - (error nil)) - (fset function f)) + (put function 'debug-on-entry nil) (setq debug-function-list (delq function debug-function-list)) + (unless debug-function-list + (setq debug-on-entry nil)) function) (message "Cancelling debug-on-entry for all functions") - (mapcar 'cancel-debug-on-entry debug-function-list))) - -(defun debug-convert-byte-code (function) - (let ((defn (symbol-function function))) - (if (not (consp defn)) - ;; Assume a compiled code object. - (let* ((contents (append defn nil)) - (body - (list (list 'byte-code (nth 1 contents) - (nth 2 contents) (nth 3 contents))))) - (if (nthcdr 5 contents) - (setq body (cons (list 'interactive (nth 5 contents)) body))) - (if (nth 4 contents) - ;; Use `documentation' here, to get the actual string, - ;; in case the compiled function has a reference - ;; to the .elc file. - (setq body (cons (documentation function) body))) - (fset function (cons 'lambda (cons (car contents) body))))))) - -(defun debug-on-entry-1 (function defn flag) - (let ((tail defn)) - (if (subrp tail) - (error "%s is a built-in function" function) - (if (eq (car tail) 'macro) (setq tail (cdr tail))) - (if (eq (car tail) 'lambda) (setq tail (cdr tail)) - (error "%s not user-defined Lisp function" function)) - ;; Skip the docstring. - (when (and (stringp (cadr tail)) (cddr tail)) - (setq tail (cdr tail))) - ;; Skip the interactive form. - (when (eq 'interactive (car-safe (cadr tail))) - (setq tail (cdr tail))) - (unless (eq flag (equal (cadr tail) debug-entry-code)) - ;; Add/remove debug statement as needed. - (if flag - (setcdr tail (cons debug-entry-code (cdr tail))) - (setcdr tail (cddr tail)))) - defn))) + (setq debug-function-list nil) + (setq debug-on-entry nil))) (defun debugger-list-functions () "Display a list of all the functions now set to debug on entry." @@ -726,10 +650,7 @@ (make-text-button (point) (progn (prin1 fun) (point)) 'type 'help-function 'help-args (list fun)) - (terpri)) - (terpri) - (princ "Note: if you have redefined a function, then it may no longer\n") - (princ "be set to debug on entry, even if it is in the list."))))) + (terpri)))))) (provide 'debug) ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-08 18:02 ` Lute Kamstra @ 2005-03-08 18:59 ` Stefan Monnier 2005-03-09 10:14 ` Lute Kamstra 2005-03-09 16:58 ` Richard Stallman 2005-03-09 16:58 ` Richard Stallman 2 siblings, 1 reply; 19+ messages in thread From: Stefan Monnier @ 2005-03-08 18:59 UTC (permalink / raw) Cc: rms, emacs-devel > This gives a backtrace like this: > ------ Buffer: *Backtrace* ------ > Debugger entered--entering a function: > * (lambda (var) (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)) (list (quote setq) var (list ... var)))(x) > (inc x) > (progn (setq x 0) (inc x)) > eval((progn (setq x 0) (inc x))) > eval-last-sexp-1(nil) > eval-last-sexp(nil) > call-interactively(eval-last-sexp) > ------ Buffer: *Backtrace* ------ > where you can see the debug-entry-code (if (or inhibit-debug-on-entry > debugger-jumping-flag) nil (debug ...)). I would prefer to hide the > internals of the debugger from its users. debug.el already hides its internals. See debugger-setup-buffer. It just has to be updated to hide this part of the internals. > You proposed to change defun, defsubst, defalias and defmacro to add > debug-entry-code when their argument was in debug-function-list. That > is a similarly big change. There's no need to do that. The hooks are already present for defadvice, so we should simply use them. Better yet, we should use defadvice directly: (defadvice <FOO> (before debug-on-entry activate) (if inhibit-debug-on-entry nil (debug 'debug))) This will properly survive function redefinitions. Stefan ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-08 18:59 ` Stefan Monnier @ 2005-03-09 10:14 ` Lute Kamstra 0 siblings, 0 replies; 19+ messages in thread From: Lute Kamstra @ 2005-03-09 10:14 UTC (permalink / raw) Cc: rms, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> This gives a backtrace like this: > >> ------ Buffer: *Backtrace* ------ >> Debugger entered--entering a function: >> * (lambda (var) (if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...)) (list (quote setq) var (list ... var)))(x) >> (inc x) >> (progn (setq x 0) (inc x)) >> eval((progn (setq x 0) (inc x))) >> eval-last-sexp-1(nil) >> eval-last-sexp(nil) >> call-interactively(eval-last-sexp) >> ------ Buffer: *Backtrace* ------ > >> where you can see the debug-entry-code (if (or inhibit-debug-on-entry >> debugger-jumping-flag) nil (debug ...)). I would prefer to hide the >> internals of the debugger from its users. > > debug.el already hides its internals. See debugger-setup-buffer. > It just has to be updated to hide this part of the internals. In this case, hiding the internals is possible. It will be clumsy though. You have to search for debug-entry-code as text, which can be abbreviated like in "(if (or inhibit-debug-on-entry debugger-jumping-flag) nil (debug ...))". You probably can only do that easily for a specific example of debug-entry-code. So the next time debug-entry-code is changed, debug.el breaks in yet another place. (Remember that when you introduced the (if ...) test in debug-entry-code, debug.el already had to be changed in 3 defuns to compensate for this?) So debug.el will become more difficult to maintain. In the other case I mentioned, hiding the debugger's internals is not possible. When you encounter debug-entry-code while stepping with `d', it will not be possible to hide this. You could hide the code visually by deleting it from the backtrace buffer, but then the user would still have to press `d' a couple of times (seemingly without any effect) to step through the debug-entry-code. >> You proposed to change defun, defsubst, defalias and defmacro to >> add debug-entry-code when their argument was in >> debug-function-list. That is a similarly big change. > > There's no need to do that. The hooks are already present for > defadvice, so we should simply use them. Hmm, I'm don't see how you can use these hooks except by using defadvice: they seem to be designed to handle only advice. I'd have to change Ffset to deal with debug-on-entry. Am I missing something? > Better yet, we should use defadvice directly: > > (defadvice <FOO> (before debug-on-entry activate) > (if inhibit-debug-on-entry nil (debug 'debug))) > > This will properly survive function redefinitions. It does survive function redefinition. I think this solution is worse than the problem it tries to solve, however. The defadvice changes a function definition quite a bit. The hapless debugger user might not recognize his own function anymore: (defun fun () "Return one." 1) (symbol-function 'fun) => (lambda nil "Return one." 1) (defadvice fun (before debug-on-entry activate) (if inhibit-debug-on-entry nil (debug 'debug))) (symbol-function 'fun) => (lambda nil "$ad-doc: fun$" (let (ad-return-value) (if inhibit-debug-on-entry nil (debug (quote debug))) (setq ad-return-value (ad-Orig-fun)) ad-return-value)) Stepping through this will cause some confusion, I think. Can you think of an easy way to hide the debugger's internals when you use advice like this? Lute. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-08 18:02 ` Lute Kamstra 2005-03-08 18:59 ` Stefan Monnier @ 2005-03-09 16:58 ` Richard Stallman 2005-03-09 16:58 ` Richard Stallman 2 siblings, 0 replies; 19+ messages in thread From: Richard Stallman @ 2005-03-09 16:58 UTC (permalink / raw) Cc: emacs-devel Temporary setting debugger-jumping-flag would solve the problem of stepping into the code of the debugger. (I'll implement this fix.) Thanks. The debug-entry-code would still be visible in the backtrace however. That is not a problem. It might even help users learn to understand that programs are data. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-08 18:02 ` Lute Kamstra 2005-03-08 18:59 ` Stefan Monnier 2005-03-09 16:58 ` Richard Stallman @ 2005-03-09 16:58 ` Richard Stallman 2005-03-09 17:38 ` Lute Kamstra 2005-03-10 0:26 ` Kevin Rodgers 2 siblings, 2 replies; 19+ messages in thread From: Richard Stallman @ 2005-03-09 16:58 UTC (permalink / raw) Cc: emacs-devel Below is a quick "proof-of-concept" patch for src/eval.c and lisp/emacs-lisp/debug.el to get a better idea of what I mean. As you can see, the change to eval.c isn't that big. The code is not unclean, but I don't think it is a real problem that the debug-on-entry code is visible. So I'd rather not go in this direction. This is not the part of Emacs that is important to improve. Hackers tend to focus their attention on the parts of Emacs that make it seem more elegant in programmers' terms, but this doesn't make Emacs more powerful or a better editor. Could you possibly look at implementing something listed in etc/TODO? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-09 16:58 ` Richard Stallman @ 2005-03-09 17:38 ` Lute Kamstra 2005-03-10 0:26 ` Kevin Rodgers 1 sibling, 0 replies; 19+ messages in thread From: Lute Kamstra @ 2005-03-09 17:38 UTC (permalink / raw) Cc: emacs-devel Richard Stallman <rms@gnu.org> writes: > Below is a quick "proof-of-concept" patch for src/eval.c and > lisp/emacs-lisp/debug.el to get a better idea of what I mean. > As you can see, the change to eval.c isn't that big. > > The code is not unclean, but I don't think it is a real problem > that the debug-on-entry code is visible. So I'd rather not > go in this direction. Ok, I'll cease my efforts to convince you then. ;-) > This is not the part of Emacs that is important to improve. > Hackers tend to focus their attention on the parts of Emacs > that make it seem more elegant in programmers' terms, > but this doesn't make Emacs more powerful or a better editor. > > Could you possibly look at implementing something listed in etc/TODO? I'll take a look to see if there's anything that strikes my fancy. Lute. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-09 16:58 ` Richard Stallman 2005-03-09 17:38 ` Lute Kamstra @ 2005-03-10 0:26 ` Kevin Rodgers 2005-03-11 1:47 ` Richard Stallman 1 sibling, 1 reply; 19+ messages in thread From: Kevin Rodgers @ 2005-03-10 0:26 UTC (permalink / raw) Richard Stallman wrote: > This is not the part of Emacs that is important to improve. > Hackers tend to focus their attention on the parts of Emacs > that make it seem more elegant in programmers' terms, > but this doesn't make Emacs more powerful or a better editor. Maybe not now, but an elegant rewrite may enable changes to make Emacs more powerful and better in the future. -- Kevin Rodgers ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Problems with debug-on-entry in the Lisp debugger. 2005-03-10 0:26 ` Kevin Rodgers @ 2005-03-11 1:47 ` Richard Stallman 0 siblings, 0 replies; 19+ messages in thread From: Richard Stallman @ 2005-03-11 1:47 UTC (permalink / raw) Cc: emacs-devel Maybe not now, but an elegant rewrite may enable changes to make Emacs more powerful and better in the future. I am not saying these are useless, I am saying that people focus too much on making Emacs "more powerful", disregarding other kinds of improvements that we need. Most of the TODO list items are not of that kind. The fact is that very few of the TODO list entries have ever been done. ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2005-03-11 1:47 UTC | newest] Thread overview: 19+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-03-07 11:05 Problems with debug-on-entry in the Lisp debugger Lute Kamstra 2005-03-07 13:31 ` Stefan Monnier 2005-03-07 15:20 ` Lute Kamstra 2005-03-07 16:32 ` Stefan Monnier 2005-03-08 18:57 ` Lute Kamstra 2005-03-09 16:58 ` Richard Stallman 2005-03-09 17:30 ` Lute Kamstra 2005-03-07 13:40 ` Kim F. Storm 2005-03-07 14:20 ` drkm 2005-03-07 14:45 ` Kim F. Storm 2005-03-08 2:53 ` Richard Stallman 2005-03-08 18:02 ` Lute Kamstra 2005-03-08 18:59 ` Stefan Monnier 2005-03-09 10:14 ` Lute Kamstra 2005-03-09 16:58 ` Richard Stallman 2005-03-09 16:58 ` Richard Stallman 2005-03-09 17:38 ` Lute Kamstra 2005-03-10 0:26 ` Kevin Rodgers 2005-03-11 1:47 ` Richard Stallman
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).