aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPhilipp Stephani2019-04-19 01:04:55 +0200
committerPhilipp Stephani2019-04-19 01:04:55 +0200
commit23a82cba12380b0905670c34395dc460a4bc9984 (patch)
treedf001ea84a8173dab9381a3ec75d36d25f6a3650 /src
parente712a8fe0929a18eaf3f4ec83b023f475afdc4d4 (diff)
downloademacs-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')
-rw-r--r--src/emacs-module.c37
-rw-r--r--src/eval.c49
-rw-r--r--src/json.c15
-rw-r--r--src/lisp.h18
4 files changed, 64 insertions, 55 deletions
diff --git a/src/emacs-module.c b/src/emacs-module.c
index fd033e8044f..393a4354b88 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -201,8 +201,8 @@ static emacs_env *initialize_environment (emacs_env *,
201static void finalize_environment (emacs_env *); 201static void finalize_environment (emacs_env *);
202static void finalize_environment_unwind (void *); 202static void finalize_environment_unwind (void *);
203static void finalize_runtime_unwind (void *); 203static void finalize_runtime_unwind (void *);
204static void module_handle_signal (emacs_env *, Lisp_Object); 204static void module_handle_nonlocal_exit (emacs_env *, enum nonlocal_exit,
205static void module_handle_throw (emacs_env *, Lisp_Object); 205 Lisp_Object);
206static void module_non_local_exit_signal_1 (emacs_env *, 206static void module_non_local_exit_signal_1 (emacs_env *,
207 Lisp_Object, Lisp_Object); 207 Lisp_Object, Lisp_Object);
208static void module_non_local_exit_throw_1 (emacs_env *, 208static void module_non_local_exit_throw_1 (emacs_env *,
@@ -231,11 +231,8 @@ static bool module_assertions = false;
231 or a pointer to handle non-local exits. The function must have an 231 or a pointer to handle non-local exits. The function must have an
232 ENV parameter. The function will return the specified value if a 232 ENV parameter. The function will return the specified value if a
233 signal or throw is caught. */ 233 signal or throw is caught. */
234/* TODO: Have Fsignal check for CATCHER_ALL so we only have to install
235 one handler. */
236#define MODULE_HANDLE_NONLOCAL_EXIT(retval) \ 234#define MODULE_HANDLE_NONLOCAL_EXIT(retval) \
237 MODULE_SETJMP (CONDITION_CASE, module_handle_signal, retval); \ 235 MODULE_SETJMP (CATCHER_ALL, module_handle_nonlocal_exit, retval)
238 MODULE_SETJMP (CATCHER_ALL, module_handle_throw, retval)
239 236
240#define MODULE_SETJMP(handlertype, handlerfunc, retval) \ 237#define MODULE_SETJMP(handlertype, handlerfunc, retval) \
241 MODULE_SETJMP_1 (handlertype, handlerfunc, retval, \ 238 MODULE_SETJMP_1 (handlertype, handlerfunc, retval, \
@@ -271,7 +268,7 @@ static bool module_assertions = false;
271 = c0; \ 268 = c0; \
272 if (sys_setjmp (c->jmp)) \ 269 if (sys_setjmp (c->jmp)) \
273 { \ 270 { \
274 (handlerfunc) (env, c->val); \ 271 (handlerfunc) (env, c->nonlocal_exit, c->val); \
275 return retval; \ 272 return retval; \
276 } \ 273 } \
277 do { } while (false) 274 do { } while (false)
@@ -1183,20 +1180,22 @@ module_reset_handlerlist (struct handler **phandlerlist)
1183 handlerlist = handlerlist->next; 1180 handlerlist = handlerlist->next;
1184} 1181}
1185 1182
1186/* Called on `signal'. ERR is a pair (SYMBOL . DATA), which gets 1183/* Called on `signal' and `throw'. DATA is a pair
1187 stored in the environment. Set the pending non-local exit flag. */ 1184 (ERROR-SYMBOL . ERROR-DATA) or (TAG . VALUE), which gets stored in
1185 the environment. Set the pending non-local exit flag. */
1188static void 1186static void
1189module_handle_signal (emacs_env *env, Lisp_Object err) 1187module_handle_nonlocal_exit (emacs_env *env, enum nonlocal_exit type,
1188 Lisp_Object data)
1190{ 1189{
1191 module_non_local_exit_signal_1 (env, XCAR (err), XCDR (err)); 1190 switch (type)
1192} 1191 {
1193 1192 case NONLOCAL_EXIT_SIGNAL:
1194/* Called on `throw'. TAG_VAL is a pair (TAG . VALUE), which gets 1193 module_non_local_exit_signal_1 (env, XCAR (data), XCDR (data));
1195 stored in the environment. Set the pending non-local exit flag. */ 1194 break;
1196static void 1195 case NONLOCAL_EXIT_THROW:
1197module_handle_throw (emacs_env *env, Lisp_Object tag_val) 1196 module_non_local_exit_throw_1 (env, XCAR (data), XCDR (data));
1198{ 1197 break;
1199 module_non_local_exit_throw_1 (env, XCAR (tag_val), XCDR (tag_val)); 1198 }
1200} 1199}
1201 1200
1202 1201
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
1136static AVOID 1136static AVOID
1137unwind_to_catch (struct handler *catch, Lisp_Object value) 1137unwind_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
1430static Lisp_Object
1431internal_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
1457Lisp_Object 1436Lisp_Object
1458internal_catch_all (Lisp_Object (*function) (void *), void *argument, 1437internal_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 {
diff --git a/src/json.c b/src/json.c
index 5917212899e..014ac3e3168 100644
--- a/src/json.c
+++ b/src/json.c
@@ -665,6 +665,18 @@ json_insert (void *data)
665 return Qnil; 665 return Qnil;
666} 666}
667 667
668static Lisp_Object
669json_handle_nonlocal_exit (enum nonlocal_exit type, Lisp_Object data)
670{
671 switch (type)
672 {
673 case NONLOCAL_EXIT_SIGNAL:
674 return data;
675 case NONLOCAL_EXIT_THROW:
676 return Fcons (Qno_catch, data);
677 }
678}
679
668struct json_insert_data 680struct json_insert_data
669{ 681{
670 /* This tracks how many bytes were inserted by the callback since 682 /* This tracks how many bytes were inserted by the callback since
@@ -687,7 +699,8 @@ json_insert_callback (const char *buffer, size_t size, void *data)
687 struct json_insert_data *d = data; 699 struct json_insert_data *d = data;
688 struct json_buffer_and_size buffer_and_size 700 struct json_buffer_and_size buffer_and_size
689 = {.buffer = buffer, .size = size, .inserted_bytes = d->inserted_bytes}; 701 = {.buffer = buffer, .size = size, .inserted_bytes = d->inserted_bytes};
690 d->error = internal_catch_all (json_insert, &buffer_and_size, Fidentity); 702 d->error = internal_catch_all (json_insert, &buffer_and_size,
703 json_handle_nonlocal_exit);
691 d->inserted_bytes = buffer_and_size.inserted_bytes; 704 d->inserted_bytes = buffer_and_size.inserted_bytes;
692 return NILP (d->error) ? 0 : -1; 705 return NILP (d->error) ? 0 : -1;
693} 706}
diff --git a/src/lisp.h b/src/lisp.h
index 0da20375228..2aa767b86c2 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3262,8 +3262,10 @@ SPECPDL_INDEX (void)
3262 member is TAG, and then unbinds to it. The `val' member is used to 3262 member is TAG, and then unbinds to it. The `val' member is used to
3263 hold VAL while the stack is unwound; `val' is returned as the value 3263 hold VAL while the stack is unwound; `val' is returned as the value
3264 of the catch form. If there is a handler of type CATCHER_ALL, it will 3264 of the catch form. If there is a handler of type CATCHER_ALL, it will
3265 be treated as a handler for all invocations of `throw'; in this case 3265 be treated as a handler for all invocations of `signal' and `throw';
3266 `val' will be set to (TAG . VAL). 3266 in this case `val' will be set to (ERROR-SYMBOL . DATA) or (TAG . VAL),
3267 respectively. During stack unwinding, `nonlocal_exit' is set to
3268 specify the type of nonlocal exit that caused the stack unwinding.
3267 3269
3268 All the other members are concerned with restoring the interpreter 3270 All the other members are concerned with restoring the interpreter
3269 state. 3271 state.
@@ -3273,11 +3275,21 @@ SPECPDL_INDEX (void)
3273 3275
3274enum handlertype { CATCHER, CONDITION_CASE, CATCHER_ALL }; 3276enum handlertype { CATCHER, CONDITION_CASE, CATCHER_ALL };
3275 3277
3278enum nonlocal_exit
3279{
3280 NONLOCAL_EXIT_SIGNAL,
3281 NONLOCAL_EXIT_THROW,
3282};
3283
3276struct handler 3284struct handler
3277{ 3285{
3278 enum handlertype type; 3286 enum handlertype type;
3279 Lisp_Object tag_or_ch; 3287 Lisp_Object tag_or_ch;
3288
3289 /* The next two are set by unwind_to_catch. */
3290 enum nonlocal_exit nonlocal_exit;
3280 Lisp_Object val; 3291 Lisp_Object val;
3292
3281 struct handler *next; 3293 struct handler *next;
3282 struct handler *nextfree; 3294 struct handler *nextfree;
3283 3295
@@ -4129,7 +4141,7 @@ extern Lisp_Object internal_condition_case_2 (Lisp_Object (*) (Lisp_Object, Lisp
4129extern Lisp_Object internal_condition_case_n 4141extern Lisp_Object internal_condition_case_n
4130 (Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *, 4142 (Lisp_Object (*) (ptrdiff_t, Lisp_Object *), ptrdiff_t, Lisp_Object *,
4131 Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *)); 4143 Lisp_Object, Lisp_Object (*) (Lisp_Object, ptrdiff_t, Lisp_Object *));
4132extern Lisp_Object internal_catch_all (Lisp_Object (*) (void *), void *, Lisp_Object (*) (Lisp_Object)); 4144extern Lisp_Object internal_catch_all (Lisp_Object (*) (void *), void *, Lisp_Object (*) (enum nonlocal_exit, Lisp_Object));
4133extern struct handler *push_handler (Lisp_Object, enum handlertype); 4145extern struct handler *push_handler (Lisp_Object, enum handlertype);
4134extern struct handler *push_handler_nosignal (Lisp_Object, enum handlertype); 4146extern struct handler *push_handler_nosignal (Lisp_Object, enum handlertype);
4135extern void specbind (Lisp_Object, Lisp_Object); 4147extern void specbind (Lisp_Object, Lisp_Object);