diff options
| author | Philipp Stephani | 2019-04-19 01:04:55 +0200 |
|---|---|---|
| committer | Philipp Stephani | 2019-04-19 01:04:55 +0200 |
| commit | 23a82cba12380b0905670c34395dc460a4bc9984 (patch) | |
| tree | df001ea84a8173dab9381a3ec75d36d25f6a3650 /src/eval.c | |
| parent | e712a8fe0929a18eaf3f4ec83b023f475afdc4d4 (diff) | |
| download | emacs-23a82cba12380b0905670c34395dc460a4bc9984.tar.gz emacs-23a82cba12380b0905670c34395dc460a4bc9984.zip | |
Refactoring: have CATCHER_ALL also catch signals.
In all cases where we use a CATCHER_ALL handler we also want to catch
signals. Therefore have 'signal' respect CATCHER_ALL. Adapt internal
interfaces so that handlers can distinguish among the two types of
nonlocal exits in CATCHER_ALL handlers.
* src/lisp.h (enum nonlocal_exit): New enum.
(struct handler): Add member 'nonlocal_exit' to hold the type of
nonlocal exit during stack unwinding.
* src/eval.c (signal_or_quit): Also respect CATCHER_ALL handlers.
(unwind_to_catch): Store nonlocal exit type in catch structure.
(Fthrow, signal_or_quit): Adapt callers.
(internal_catch_all): Install only one handler. Give handler a
nonlocal exit type argument.
(internal_catch_all_1): Remove, no longer needed.
* src/emacs-module.c (MODULE_SETJMP): Install only one handler.
(module_handle_nonlocal_exit): New function to handle all nonlocal
exits.
(MODULE_SETJMP_1): Pass nonlocal exit type to handler function.
(module_handle_signal, module_handle_throw): Remove, no longer needed.
* src/json.c (json_handle_nonlocal_exit): New helper function.
(json_insert_callback): Adapt to change in 'internal_catch_all'.
Diffstat (limited to 'src/eval.c')
| -rw-r--r-- | src/eval.c | 49 |
1 files changed, 17 insertions, 32 deletions
diff --git a/src/eval.c b/src/eval.c index c2e996a9474..23fd0efd54a 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -1134,13 +1134,15 @@ internal_catch (Lisp_Object tag, | |||
| 1134 | This is used for correct unwinding in Fthrow and Fsignal. */ | 1134 | This is used for correct unwinding in Fthrow and Fsignal. */ |
| 1135 | 1135 | ||
| 1136 | static AVOID | 1136 | static AVOID |
| 1137 | unwind_to_catch (struct handler *catch, Lisp_Object value) | 1137 | unwind_to_catch (struct handler *catch, enum nonlocal_exit type, |
| 1138 | Lisp_Object value) | ||
| 1138 | { | 1139 | { |
| 1139 | bool last_time; | 1140 | bool last_time; |
| 1140 | 1141 | ||
| 1141 | eassert (catch->next); | 1142 | eassert (catch->next); |
| 1142 | 1143 | ||
| 1143 | /* Save the value in the tag. */ | 1144 | /* Save the value in the tag. */ |
| 1145 | catch->nonlocal_exit = type; | ||
| 1144 | catch->val = value; | 1146 | catch->val = value; |
| 1145 | 1147 | ||
| 1146 | /* Restore certain special C variables. */ | 1148 | /* Restore certain special C variables. */ |
| @@ -1177,9 +1179,9 @@ Both TAG and VALUE are evalled. */ | |||
| 1177 | for (c = handlerlist; c; c = c->next) | 1179 | for (c = handlerlist; c; c = c->next) |
| 1178 | { | 1180 | { |
| 1179 | if (c->type == CATCHER_ALL) | 1181 | if (c->type == CATCHER_ALL) |
| 1180 | unwind_to_catch (c, Fcons (tag, value)); | 1182 | unwind_to_catch (c, NONLOCAL_EXIT_THROW, Fcons (tag, value)); |
| 1181 | if (c->type == CATCHER && EQ (c->tag_or_ch, tag)) | 1183 | if (c->type == CATCHER && EQ (c->tag_or_ch, tag)) |
| 1182 | unwind_to_catch (c, value); | 1184 | unwind_to_catch (c, NONLOCAL_EXIT_THROW, value); |
| 1183 | } | 1185 | } |
| 1184 | xsignal2 (Qno_catch, tag, value); | 1186 | xsignal2 (Qno_catch, tag, value); |
| 1185 | } | 1187 | } |
| @@ -1427,44 +1429,21 @@ internal_condition_case_n (Lisp_Object (*bfun) (ptrdiff_t, Lisp_Object *), | |||
| 1427 | } | 1429 | } |
| 1428 | } | 1430 | } |
| 1429 | 1431 | ||
| 1430 | static Lisp_Object | ||
| 1431 | internal_catch_all_1 (Lisp_Object (*function) (void *), void *argument) | ||
| 1432 | { | ||
| 1433 | struct handler *c = push_handler_nosignal (Qt, CATCHER_ALL); | ||
| 1434 | if (c == NULL) | ||
| 1435 | return Qcatch_all_memory_full; | ||
| 1436 | |||
| 1437 | if (sys_setjmp (c->jmp) == 0) | ||
| 1438 | { | ||
| 1439 | Lisp_Object val = function (argument); | ||
| 1440 | eassert (handlerlist == c); | ||
| 1441 | handlerlist = c->next; | ||
| 1442 | return val; | ||
| 1443 | } | ||
| 1444 | else | ||
| 1445 | { | ||
| 1446 | eassert (handlerlist == c); | ||
| 1447 | Lisp_Object val = c->val; | ||
| 1448 | handlerlist = c->next; | ||
| 1449 | Fsignal (Qno_catch, val); | ||
| 1450 | } | ||
| 1451 | } | ||
| 1452 | |||
| 1453 | /* Like a combination of internal_condition_case_1 and internal_catch. | 1432 | /* Like a combination of internal_condition_case_1 and internal_catch. |
| 1454 | Catches all signals and throws. Never exits nonlocally; returns | 1433 | Catches all signals and throws. Never exits nonlocally; returns |
| 1455 | Qcatch_all_memory_full if no handler could be allocated. */ | 1434 | Qcatch_all_memory_full if no handler could be allocated. */ |
| 1456 | 1435 | ||
| 1457 | Lisp_Object | 1436 | Lisp_Object |
| 1458 | internal_catch_all (Lisp_Object (*function) (void *), void *argument, | 1437 | internal_catch_all (Lisp_Object (*function) (void *), void *argument, |
| 1459 | Lisp_Object (*handler) (Lisp_Object)) | 1438 | Lisp_Object (*handler) (enum nonlocal_exit, Lisp_Object)) |
| 1460 | { | 1439 | { |
| 1461 | struct handler *c = push_handler_nosignal (Qt, CONDITION_CASE); | 1440 | struct handler *c = push_handler_nosignal (Qt, CATCHER_ALL); |
| 1462 | if (c == NULL) | 1441 | if (c == NULL) |
| 1463 | return Qcatch_all_memory_full; | 1442 | return Qcatch_all_memory_full; |
| 1464 | 1443 | ||
| 1465 | if (sys_setjmp (c->jmp) == 0) | 1444 | if (sys_setjmp (c->jmp) == 0) |
| 1466 | { | 1445 | { |
| 1467 | Lisp_Object val = internal_catch_all_1 (function, argument); | 1446 | Lisp_Object val = function (argument); |
| 1468 | eassert (handlerlist == c); | 1447 | eassert (handlerlist == c); |
| 1469 | handlerlist = c->next; | 1448 | handlerlist = c->next; |
| 1470 | return val; | 1449 | return val; |
| @@ -1472,9 +1451,10 @@ internal_catch_all (Lisp_Object (*function) (void *), void *argument, | |||
| 1472 | else | 1451 | else |
| 1473 | { | 1452 | { |
| 1474 | eassert (handlerlist == c); | 1453 | eassert (handlerlist == c); |
| 1454 | enum nonlocal_exit type = c->nonlocal_exit; | ||
| 1475 | Lisp_Object val = c->val; | 1455 | Lisp_Object val = c->val; |
| 1476 | handlerlist = c->next; | 1456 | handlerlist = c->next; |
| 1477 | return handler (val); | 1457 | return handler (type, val); |
| 1478 | } | 1458 | } |
| 1479 | } | 1459 | } |
| 1480 | 1460 | ||
| @@ -1645,6 +1625,11 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1645 | 1625 | ||
| 1646 | for (h = handlerlist; h; h = h->next) | 1626 | for (h = handlerlist; h; h = h->next) |
| 1647 | { | 1627 | { |
| 1628 | if (h->type == CATCHER_ALL) | ||
| 1629 | { | ||
| 1630 | clause = Qt; | ||
| 1631 | break; | ||
| 1632 | } | ||
| 1648 | if (h->type != CONDITION_CASE) | 1633 | if (h->type != CONDITION_CASE) |
| 1649 | continue; | 1634 | continue; |
| 1650 | clause = find_handler_clause (h->tag_or_ch, conditions); | 1635 | clause = find_handler_clause (h->tag_or_ch, conditions); |
| @@ -1678,7 +1663,7 @@ signal_or_quit (Lisp_Object error_symbol, Lisp_Object data, bool keyboard_quit) | |||
| 1678 | Lisp_Object unwind_data | 1663 | Lisp_Object unwind_data |
| 1679 | = (NILP (error_symbol) ? data : Fcons (error_symbol, data)); | 1664 | = (NILP (error_symbol) ? data : Fcons (error_symbol, data)); |
| 1680 | 1665 | ||
| 1681 | unwind_to_catch (h, unwind_data); | 1666 | unwind_to_catch (h, NONLOCAL_EXIT_SIGNAL, unwind_data); |
| 1682 | } | 1667 | } |
| 1683 | else | 1668 | else |
| 1684 | { | 1669 | { |