comparison src/eval.c @ 2532:989a7680c221

[xemacs-hg @ 2005-01-29 09:15:55 by ben] Add backtrace when throwing past call_trapping_problems() alloc.c, backtrace.h, bytecode.c, cmdloop.c, eval.c, lisp.h, macros.c: Also include a backtrace when we catch an attempt to throw outside of a function where call_trapping_problems() has been used.
author ben
date Sat, 29 Jan 2005 09:16:00 +0000
parents 3d8143fc88e1
children 9f70af3ac939
comparison
equal deleted inserted replaced
2531:7de8d9ab7bbd 2532:989a7680c221
402 /* Used for error catching purposes by throw_or_bomb_out */ 402 /* Used for error catching purposes by throw_or_bomb_out */
403 static int throw_level; 403 static int throw_level;
404 #endif 404 #endif
405 405
406 static int warning_will_be_discarded (Lisp_Object level); 406 static int warning_will_be_discarded (Lisp_Object level);
407 static Lisp_Object maybe_get_trapping_problems_backtrace (void);
407 408
408 409
409 /************************************************************************/ 410 /************************************************************************/
410 /* The subr object type */ 411 /* The subr object type */
411 /************************************************************************/ 412 /************************************************************************/
524 max_lisp_eval_depth = lisp_eval_depth + 20; 525 max_lisp_eval_depth = lisp_eval_depth + 20;
525 if (specpdl_size + 40 > max_specpdl_size) 526 if (specpdl_size + 40 > max_specpdl_size)
526 max_specpdl_size = specpdl_size + 40; 527 max_specpdl_size = specpdl_size + 40;
527 528
528 speccount = internal_bind_int (&entering_debugger, 1); 529 speccount = internal_bind_int (&entering_debugger, 1);
529 val = internal_catch (Qdebugger, call_debugger_259, arg, &threw, 0); 530 val = internal_catch (Qdebugger, call_debugger_259, arg, &threw, 0, 0);
530 531
531 return unbind_to_1 (speccount, ((threw) 532 return unbind_to_1 (speccount, ((threw)
532 ? Qunbound /* Not returning a value */ 533 ? Qunbound /* Not returning a value */
533 : val)); 534 : val));
534 } 535 }
1478 (args)) 1479 (args))
1479 { 1480 {
1480 /* This function can GC */ 1481 /* This function can GC */
1481 Lisp_Object tag = Feval (XCAR (args)); 1482 Lisp_Object tag = Feval (XCAR (args));
1482 Lisp_Object body = XCDR (args); 1483 Lisp_Object body = XCDR (args);
1483 return internal_catch (tag, Fprogn, body, 0, 0); 1484 return internal_catch (tag, Fprogn, body, 0, 0, 0);
1484 } 1485 }
1485 1486
1486 /* Set up a catch, then call C function FUNC on argument ARG. 1487 /* Set up a catch, then call C function FUNC on argument ARG.
1487 FUNC should return a Lisp_Object. 1488 FUNC should return a Lisp_Object.
1488 This is how catches are done from within C code. */ 1489 This is how catches are done from within C code. */
1490 Lisp_Object 1491 Lisp_Object
1491 internal_catch (Lisp_Object tag, 1492 internal_catch (Lisp_Object tag,
1492 Lisp_Object (*func) (Lisp_Object arg), 1493 Lisp_Object (*func) (Lisp_Object arg),
1493 Lisp_Object arg, 1494 Lisp_Object arg,
1494 int * volatile threw, 1495 int * volatile threw,
1495 Lisp_Object * volatile thrown_tag) 1496 Lisp_Object * volatile thrown_tag,
1497 Lisp_Object * volatile backtrace_before_throw)
1496 { 1498 {
1497 /* This structure is made part of the chain `catchlist'. */ 1499 /* This structure is made part of the chain `catchlist'. */
1498 struct catchtag c; 1500 struct catchtag c;
1499 1501
1500 /* Fill in the components of c, and put it on the list. */ 1502 /* Fill in the components of c, and put it on the list. */
1501 c.next = catchlist; 1503 c.next = catchlist;
1502 c.tag = tag; 1504 c.tag = tag;
1503 c.actual_tag = Qnil; 1505 c.actual_tag = Qnil;
1506 c.backtrace = Qnil;
1504 c.val = Qnil; 1507 c.val = Qnil;
1505 c.backlist = backtrace_list; 1508 c.backlist = backtrace_list;
1506 #if 0 /* FSFmacs */ 1509 #if 0 /* FSFmacs */
1507 /* #### */ 1510 /* #### */
1508 c.handlerlist = handlerlist; 1511 c.handlerlist = handlerlist;
1519 if (SETJMP (c.jmp)) 1522 if (SETJMP (c.jmp))
1520 { 1523 {
1521 /* Throw works by a longjmp that comes right here. */ 1524 /* Throw works by a longjmp that comes right here. */
1522 if (threw) *threw = 1; 1525 if (threw) *threw = 1;
1523 if (thrown_tag) *thrown_tag = c.actual_tag; 1526 if (thrown_tag) *thrown_tag = c.actual_tag;
1527 if (backtrace_before_throw) *backtrace_before_throw = c.backtrace;
1524 return c.val; 1528 return c.val;
1525 } 1529 }
1526 c.val = (*func) (arg); 1530 c.val = (*func) (arg);
1527 if (threw) *threw = 0; 1531 if (threw) *threw = 0;
1528 if (thrown_tag) *thrown_tag = Qnil; 1532 if (thrown_tag) *thrown_tag = Qnil;
1675 #if 0 /* FSFmacs */ 1679 #if 0 /* FSFmacs */
1676 if (!NILP (tag)) /* #### */ 1680 if (!NILP (tag)) /* #### */
1677 #endif 1681 #endif
1678 for (c = catchlist; c; c = c->next) 1682 for (c = catchlist; c; c = c->next)
1679 { 1683 {
1684 if (EQ (c->tag, Vcatch_everything_tag))
1685 c->backtrace = maybe_get_trapping_problems_backtrace ();
1680 if (EQ (c->tag, tag) || EQ (c->tag, Vcatch_everything_tag)) 1686 if (EQ (c->tag, tag) || EQ (c->tag, Vcatch_everything_tag))
1681 unwind_to_catch (c, val, tag); 1687 unwind_to_catch (c, val, tag);
1682 } 1688 }
1683 if (!bomb_out_p) 1689 if (!bomb_out_p)
1684 tag = Fsignal (Qno_catch, list2 (tag, val)); 1690 tag = Fsignal (Qno_catch, list2 (tag, val));
1879 c.tag = noseeum_cons (noseeum_cons (Qunbound, handlers), 1885 c.tag = noseeum_cons (noseeum_cons (Qunbound, handlers),
1880 Vcondition_handlers); 1886 Vcondition_handlers);
1881 #endif 1887 #endif
1882 c.val = Qnil; 1888 c.val = Qnil;
1883 c.actual_tag = Qnil; 1889 c.actual_tag = Qnil;
1890 c.backtrace = Qnil;
1884 c.backlist = backtrace_list; 1891 c.backlist = backtrace_list;
1885 #if 0 /* FSFmacs */ 1892 #if 0 /* FSFmacs */
1886 /* #### */ 1893 /* #### */
1887 c.handlerlist = handlerlist; 1894 c.handlerlist = handlerlist;
1888 #endif 1895 #endif
4811 const CIbyte *warning_string; 4818 const CIbyte *warning_string;
4812 Lisp_Object (*fun) (void *); 4819 Lisp_Object (*fun) (void *);
4813 void *arg; 4820 void *arg;
4814 }; 4821 };
4815 4822
4816 static DECLARE_DOESNT_RETURN_TYPE 4823 static Lisp_Object
4817 (Lisp_Object, flagged_a_squirmer (Lisp_Object, Lisp_Object, Lisp_Object)); 4824 maybe_get_trapping_problems_backtrace (void)
4818 4825 {
4819 static DOESNT_RETURN_TYPE (Lisp_Object) 4826 Lisp_Object backtrace;
4820 flagged_a_squirmer (Lisp_Object error_conditions, Lisp_Object data,
4821 Lisp_Object opaque)
4822 {
4823 struct call_trapping_problems *p =
4824 (struct call_trapping_problems *) get_opaque_ptr (opaque);
4825 4827
4826 if (!(inhibit_flags & INHIBIT_WARNING_ISSUE) 4828 if (!(inhibit_flags & INHIBIT_WARNING_ISSUE)
4827 && !warning_will_be_discarded (current_warning_level ()) 4829 && !warning_will_be_discarded (current_warning_level ()))
4828 && !EQ (error_conditions, Qquit))
4829 { 4830 {
4830 struct gcpro gcpro1; 4831 struct gcpro gcpro1;
4831 Lisp_Object lstream = Qnil; 4832 Lisp_Object lstream = Qnil;
4832 int speccount = specpdl_depth (); 4833 int speccount = specpdl_depth ();
4833 4834
4840 4841
4841 GCPRO1 (lstream); 4842 GCPRO1 (lstream);
4842 lstream = make_resizing_buffer_output_stream (); 4843 lstream = make_resizing_buffer_output_stream ();
4843 Fbacktrace (lstream, Qt); 4844 Fbacktrace (lstream, Qt);
4844 Lstream_flush (XLSTREAM (lstream)); 4845 Lstream_flush (XLSTREAM (lstream));
4845 p->backtrace = resizing_buffer_to_lisp_string (XLSTREAM (lstream)); 4846 backtrace = resizing_buffer_to_lisp_string (XLSTREAM (lstream));
4846 Lstream_delete (XLSTREAM (lstream)); 4847 Lstream_delete (XLSTREAM (lstream));
4847 UNGCPRO; 4848 UNGCPRO;
4848 4849
4849 unbind_to (speccount); 4850 unbind_to (speccount);
4850 } 4851 }
4851 else 4852 else
4853 backtrace = Qnil;
4854
4855 return backtrace;
4856 }
4857
4858 static DECLARE_DOESNT_RETURN_TYPE
4859 (Lisp_Object, flagged_a_squirmer (Lisp_Object, Lisp_Object, Lisp_Object));
4860
4861 static DOESNT_RETURN_TYPE (Lisp_Object)
4862 flagged_a_squirmer (Lisp_Object error_conditions, Lisp_Object data,
4863 Lisp_Object opaque)
4864 {
4865 struct call_trapping_problems *p =
4866 (struct call_trapping_problems *) get_opaque_ptr (opaque);
4867
4868 if (!EQ (error_conditions, Qquit))
4869 p->backtrace = maybe_get_trapping_problems_backtrace ();
4870 else
4852 p->backtrace = Qnil; 4871 p->backtrace = Qnil;
4853
4854 p->error_conditions = error_conditions; 4872 p->error_conditions = error_conditions;
4855 p->data = data; 4873 p->data = data;
4856 4874
4857 Fthrow (p->catchtag, Qnil); 4875 Fthrow (p->catchtag, Qnil);
4858 RETURN_NOT_REACHED (Qnil); 4876 RETURN_NOT_REACHED (Qnil);
4889 4907
4890 if (p->caught_throw) 4908 if (p->caught_throw)
4891 { 4909 {
4892 Lisp_Object errstr = 4910 Lisp_Object errstr =
4893 emacs_sprintf_string_lisp 4911 emacs_sprintf_string_lisp
4894 ("%s: Attempt to throw outside of function " 4912 ("%s: Attempt to throw outside of function:"
4895 "to catch `%s' with value `%s'", 4913 "To catch `%s' with value `%s'\n\nBacktrace follows:\n\n%s",
4896 Qnil, 3, 4914 Qnil, 3,
4897 build_msg_string (warning_string ? warning_string : "error"), 4915 build_msg_string (warning_string ? warning_string : "error"),
4898 p->thrown_tag, p->thrown_value); 4916 p->thrown_tag, p->thrown_value, p->backtrace);
4899 warn_when_safe_lispobj (Qerror, current_warning_level (), errstr); 4917 warn_when_safe_lispobj (Qerror, current_warning_level (), errstr);
4900 } 4918 }
4901 else if (p->caught_error && !EQ (p->error_conditions, Qquit)) 4919 else if (p->caught_error && !EQ (p->error_conditions, Qquit))
4902 { 4920 {
4903 Lisp_Object errstr; 4921 Lisp_Object errstr;
5107 { 5125 {
5108 int speccount = specpdl_depth (); 5126 int speccount = specpdl_depth ();
5109 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 5127 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
5110 struct call_trapping_problems package; 5128 struct call_trapping_problems package;
5111 struct call_trapping_problems_result real_problem; 5129 struct call_trapping_problems_result real_problem;
5112 Lisp_Object opaque, thrown_tag, tem; 5130 Lisp_Object opaque, thrown_tag, tem, thrown_backtrace;
5113 int thrown = 0; 5131 int thrown = 0;
5114 5132
5115 assert (SYMBOLP (warning_class)); /* sanity-check */ 5133 assert (SYMBOLP (warning_class)); /* sanity-check */
5116 assert (!NILP (warning_class)); 5134 assert (!NILP (warning_class));
5117 5135
5142 if (flags & INTERNAL_INHIBIT_ERRORS) 5160 if (flags & INTERNAL_INHIBIT_ERRORS)
5143 /* We need a catch so that our condition-handler can throw back here 5161 /* We need a catch so that our condition-handler can throw back here
5144 after printing the warning. (We print the warning in the stack 5162 after printing the warning. (We print the warning in the stack
5145 context of the error, so we can get a backtrace.) */ 5163 context of the error, so we can get a backtrace.) */
5146 tem = internal_catch (package.catchtag, call_trapping_problems_1, opaque, 5164 tem = internal_catch (package.catchtag, call_trapping_problems_1, opaque,
5147 &thrown, &thrown_tag); 5165 &thrown, &thrown_tag, &thrown_backtrace);
5148 else if (flags & INTERNAL_INHIBIT_THROWS) 5166 else if (flags & INTERNAL_INHIBIT_THROWS)
5149 /* We skip over the first wrapper, which traps errors. */ 5167 /* We skip over the first wrapper, which traps errors. */
5150 tem = internal_catch (package.catchtag, call_trapping_problems_2, opaque, 5168 tem = internal_catch (package.catchtag, call_trapping_problems_2, opaque,
5151 &thrown, &thrown_tag); 5169 &thrown, &thrown_tag, &thrown_backtrace);
5152 else 5170 else
5153 /* Nothing special. */ 5171 /* Nothing special. */
5154 tem = (fun) (arg); 5172 tem = (fun) (arg);
5155 5173
5156 if (!problem) 5174 if (!problem)
5180 { 5198 {
5181 problem->caught_error = 0; 5199 problem->caught_error = 0;
5182 problem->caught_throw = 1; 5200 problem->caught_throw = 1;
5183 problem->error_conditions = Qnil; 5201 problem->error_conditions = Qnil;
5184 problem->data = Qnil; 5202 problem->data = Qnil;
5185 problem->backtrace = Qnil; 5203 problem->backtrace = thrown_backtrace;
5186 problem->thrown_tag = thrown_tag; 5204 problem->thrown_tag = thrown_tag;
5187 problem->thrown_value = tem; 5205 problem->thrown_value = tem;
5188 } 5206 }
5189 5207
5190 if (!(flags & INHIBIT_WARNING_ISSUE) && !(flags & POSTPONE_WARNING_ISSUE)) 5208 if (!(flags & INHIBIT_WARNING_ISSUE) && !(flags & POSTPONE_WARNING_ISSUE))