aboutsummaryrefslogtreecommitdiffstats
path: root/src/eval.c
diff options
context:
space:
mode:
authorDmitry Gutov2022-08-15 02:22:59 +0300
committerDmitry Gutov2022-08-15 02:22:59 +0300
commitee3a674c7c9e39fe7ff296ce1f9830fc45520de8 (patch)
treee8ba1e7be54314f208454e80e3d31044c913f3eb /src/eval.c
parentfe0e53d963899a16e0dd1bbc1ba10a6b59f7989e (diff)
parent0a8e88fd83db5398d36064a7f87cff5b57da7284 (diff)
downloademacs-scratch/font_lock_large_files.tar.gz
emacs-scratch/font_lock_large_files.zip
Merge branch 'master' into scratch/font_lock_large_filesscratch/font_lock_large_files
Diffstat (limited to 'src/eval.c')
-rw-r--r--src/eval.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/src/eval.c b/src/eval.c
index d82d05797b2..56b42966623 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -57,6 +57,12 @@ Lisp_Object Vrun_hooks;
57/* FIXME: We should probably get rid of this! */ 57/* FIXME: We should probably get rid of this! */
58Lisp_Object Vsignaling_function; 58Lisp_Object Vsignaling_function;
59 59
60/* The handler structure which will catch errors in Lisp hooks called
61 from redisplay. We do not use it for this; we compare it with the
62 handler which is about to be used in signal_or_quit, and if it
63 matches, cause a backtrace to be generated. */
64static struct handler *redisplay_deep_handler;
65
60/* These would ordinarily be static, but they need to be visible to GDB. */ 66/* These would ordinarily be static, but they need to be visible to GDB. */
61bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE; 67bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
62Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE; 68Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
@@ -246,6 +252,7 @@ init_eval (void)
246 lisp_eval_depth = 0; 252 lisp_eval_depth = 0;
247 /* This is less than the initial value of num_nonmacro_input_events. */ 253 /* This is less than the initial value of num_nonmacro_input_events. */
248 when_entered_debugger = -1; 254 when_entered_debugger = -1;
255 redisplay_deep_handler = NULL;
249} 256}
250 257
251/* Ensure that *M is at least A + B if possible, or is its maximum 258/* Ensure that *M is at least A + B if possible, or is its maximum
@@ -333,7 +340,8 @@ call_debugger (Lisp_Object arg)
333 /* Interrupting redisplay and resuming it later is not safe under 340 /* Interrupting redisplay and resuming it later is not safe under
334 all circumstances. So, when the debugger returns, abort the 341 all circumstances. So, when the debugger returns, abort the
335 interrupted redisplay by going back to the top-level. */ 342 interrupted redisplay by going back to the top-level. */
336 if (debug_while_redisplaying) 343 if (debug_while_redisplaying
344 && !EQ (Vdebugger, Qdebug_early))
337 Ftop_level (); 345 Ftop_level ();
338 346
339 return unbind_to (count, val); 347 return unbind_to (count, val);
@@ -1556,12 +1564,16 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
1556 ptrdiff_t nargs, 1564 ptrdiff_t nargs,
1557 Lisp_Object *args)) 1565 Lisp_Object *args))
1558{ 1566{
1567 struct handler *old_deep = redisplay_deep_handler;
1559 struct handler *c = push_handler (handlers, CONDITION_CASE); 1568 struct handler *c = push_handler (handlers, CONDITION_CASE);
1569 if (redisplaying_p)
1570 redisplay_deep_handler = c;
1560 if (sys_setjmp (c->jmp)) 1571 if (sys_setjmp (c->jmp))
1561 { 1572 {
1562 Lisp_Object val = handlerlist->val; 1573 Lisp_Object val = handlerlist->val;
1563 clobbered_eassert (handlerlist == c); 1574 clobbered_eassert (handlerlist == c);
1564 handlerlist = handlerlist->next; 1575 handlerlist = handlerlist->next;
1576 redisplay_deep_handler = old_deep;
1565 return hfun (val, nargs, args); 1577 return hfun (val, nargs, args);
1566 } 1578 }
1567 else 1579 else
@@ -1569,6 +1581,7 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *),
1569 Lisp_Object val = bfun (nargs, args); 1581 Lisp_Object val = bfun (nargs, args);
1570 eassert (handlerlist == c); 1582 eassert (handlerlist == c);
1571 handlerlist = c->next; 1583 handlerlist = c->next;
1584 redisplay_deep_handler = old_deep;
1572 return val; 1585 return val;
1573 } 1586 }
1574} 1587}
@@ -1701,6 +1714,11 @@ quit (void)
1701 return signal_or_quit (Qquit, Qnil, true); 1714 return signal_or_quit (Qquit, Qnil, true);
1702} 1715}
1703 1716
1717/* Has an error in redisplay giving rise to a backtrace occurred as
1718 yet in the current command? This gets reset in the command
1719 loop. */
1720bool backtrace_yet = false;
1721
1704/* Signal an error, or quit. ERROR_SYMBOL and DATA are as with Fsignal. 1722/* Signal an error, or quit. ERROR_SYMBOL and DATA are as with Fsignal.
1705 If KEYBOARD_QUIT, this is a quit; ERROR_SYMBOL should be 1723 If KEYBOARD_QUIT, this is a quit; ERROR_SYMBOL should be
1706 Qquit and DATA should be Qnil, and this function may return. 1724 Qquit and DATA should be Qnil, and this function may return.
@@ -1816,6 +1834,40 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit)
1816 unbind_to (count, Qnil); 1834 unbind_to (count, Qnil);
1817 } 1835 }
1818 1836
1837 /* If an error is signalled during a Lisp hook in redisplay, write a
1838 backtrace into the buffer *Redisplay-trace*. */
1839 if (!debugger_called && !NILP (error_symbol)
1840 && backtrace_on_redisplay_error
1841 && (NILP (clause) || h == redisplay_deep_handler)
1842 && NILP (Vinhibit_debugger)
1843 && !NILP (Ffboundp (Qdebug_early)))
1844 {
1845 max_ensure_room (&max_lisp_eval_depth, lisp_eval_depth, 100);
1846 specpdl_ref count = SPECPDL_INDEX ();
1847 ptrdiff_t counti = specpdl_ref_to_count (count);
1848 AUTO_STRING (redisplay_trace, "*Redisplay_trace*");
1849 Lisp_Object redisplay_trace_buffer;
1850 AUTO_STRING (gap, "\n\n\n\n"); /* Separates things in *Redisplay-trace* */
1851 Lisp_Object delayed_warning;
1852 max_ensure_room (&max_specpdl_size, counti, 200);
1853 redisplay_trace_buffer = Fget_buffer_create (redisplay_trace, Qnil);
1854 current_buffer = XBUFFER (redisplay_trace_buffer);
1855 if (!backtrace_yet) /* Are we on the first backtrace of the command? */
1856 Ferase_buffer ();
1857 else
1858 Finsert (1, &gap);
1859 backtrace_yet = true;
1860 specbind (Qstandard_output, redisplay_trace_buffer);
1861 specbind (Qdebugger, Qdebug_early);
1862 call_debugger (list2 (Qerror, Fcons (error_symbol, data)));
1863 unbind_to (count, Qnil);
1864 delayed_warning = make_string
1865 ("Error in a redisplay Lisp hook. See buffer *Redisplay_trace*", 61);
1866
1867 Vdelayed_warnings_list = Fcons (list2 (Qerror, delayed_warning),
1868 Vdelayed_warnings_list);
1869 }
1870
1819 if (!NILP (clause)) 1871 if (!NILP (clause))
1820 { 1872 {
1821 Lisp_Object unwind_data 1873 Lisp_Object unwind_data
@@ -4278,6 +4330,11 @@ Does not apply if quit is handled by a `condition-case'. */);
4278 DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call, 4330 DEFVAR_BOOL ("debug-on-next-call", debug_on_next_call,
4279 doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */); 4331 doc: /* Non-nil means enter debugger before next `eval', `apply' or `funcall'. */);
4280 4332
4333 DEFVAR_BOOL ("backtrace-on-redisplay-error", backtrace_on_redisplay_error,
4334 doc: /* Non-nil means create a backtrace if a lisp error occurs in redisplay.
4335The backtrace is written to buffer *Redisplay-trace*. */);
4336 backtrace_on_redisplay_error = false;
4337
4281 DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue, 4338 DEFVAR_BOOL ("debugger-may-continue", debugger_may_continue,
4282 doc: /* Non-nil means debugger may continue execution. 4339 doc: /* Non-nil means debugger may continue execution.
4283This is nil when the debugger is called under circumstances where it 4340This is nil when the debugger is called under circumstances where it