diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 109 |
1 files changed, 47 insertions, 62 deletions
diff --git a/src/eval.c b/src/eval.c index b4103acd28f..ce7b08e894a 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -31,15 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 31 | #include "pdumper.h" | 31 | #include "pdumper.h" |
| 32 | #include "atimer.h" | 32 | #include "atimer.h" |
| 33 | 33 | ||
| 34 | /* CACHEABLE is ordinarily nothing, except it is 'volatile' if | ||
| 35 | necessary to cajole GCC into not warning incorrectly that a | ||
| 36 | variable should be volatile. */ | ||
| 37 | #if defined GCC_LINT || defined lint | ||
| 38 | # define CACHEABLE volatile | ||
| 39 | #else | ||
| 40 | # define CACHEABLE /* empty */ | ||
| 41 | #endif | ||
| 42 | |||
| 43 | /* Non-nil means record all fset's and provide's, to be undone | 34 | /* Non-nil means record all fset's and provide's, to be undone |
| 44 | if the file being autoloaded is not fully loaded. | 35 | if the file being autoloaded is not fully loaded. |
| 45 | They are recorded by being consed onto the front of Vautoload_queue: | 36 | They are recorded by being consed onto the front of Vautoload_queue: |
| @@ -430,7 +421,7 @@ DEFUN ("progn", Fprogn, Sprogn, 0, UNEVALLED, 0, | |||
| 430 | usage: (progn BODY...) */) | 421 | usage: (progn BODY...) */) |
| 431 | (Lisp_Object body) | 422 | (Lisp_Object body) |
| 432 | { | 423 | { |
| 433 | Lisp_Object CACHEABLE val = Qnil; | 424 | Lisp_Object val = Qnil; |
| 434 | 425 | ||
| 435 | while (CONSP (body)) | 426 | while (CONSP (body)) |
| 436 | { | 427 | { |
| @@ -1257,12 +1248,6 @@ usage: (catch TAG BODY...) */) | |||
| 1257 | return internal_catch (tag, Fprogn, XCDR (args)); | 1248 | return internal_catch (tag, Fprogn, XCDR (args)); |
| 1258 | } | 1249 | } |
| 1259 | 1250 | ||
| 1260 | /* Work around GCC bug 61118 | ||
| 1261 | <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61118>. */ | ||
| 1262 | #if GNUC_PREREQ (4, 9, 0) | ||
| 1263 | # pragma GCC diagnostic ignored "-Wclobbered" | ||
| 1264 | #endif | ||
| 1265 | |||
| 1266 | /* Assert that E is true, but do not evaluate E. Use this instead of | 1251 | /* Assert that E is true, but do not evaluate E. Use this instead of |
| 1267 | eassert (E) when E contains variables that might be clobbered by a | 1252 | eassert (E) when E contains variables that might be clobbered by a |
| 1268 | longjmp. */ | 1253 | longjmp. */ |
| @@ -1488,8 +1473,10 @@ Lisp_Object | |||
| 1488 | internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, | 1473 | internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, |
| 1489 | Lisp_Object handlers) | 1474 | Lisp_Object handlers) |
| 1490 | { | 1475 | { |
| 1491 | struct handler *oldhandlerlist = handlerlist; | 1476 | struct handler *volatile oldhandlerlist = handlerlist; |
| 1492 | ptrdiff_t CACHEABLE clausenb = 0; | 1477 | |
| 1478 | /* The number of non-success handlers, plus 1 for a sentinel. */ | ||
| 1479 | ptrdiff_t clausenb = 1; | ||
| 1493 | 1480 | ||
| 1494 | var = maybe_remove_pos_from_symbol (var); | 1481 | var = maybe_remove_pos_from_symbol (var); |
| 1495 | CHECK_TYPE (BARE_SYMBOL_P (var), Qsymbolp, var); | 1482 | CHECK_TYPE (BARE_SYMBOL_P (var), Qsymbolp, var); |
| @@ -1521,69 +1508,67 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform, | |||
| 1521 | memory_full (SIZE_MAX); | 1508 | memory_full (SIZE_MAX); |
| 1522 | Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses); | 1509 | Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses); |
| 1523 | clauses += clausenb; | 1510 | clauses += clausenb; |
| 1511 | *--clauses = make_fixnum (0); | ||
| 1524 | for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail)) | 1512 | for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail)) |
| 1525 | { | 1513 | { |
| 1526 | Lisp_Object tem = XCAR (tail); | 1514 | Lisp_Object tem = XCAR (tail); |
| 1527 | if (!(CONSP (tem) && EQ (XCAR (tem), QCsuccess))) | 1515 | if (!(CONSP (tem) && EQ (XCAR (tem), QCsuccess))) |
| 1528 | *--clauses = tem; | 1516 | *--clauses = tem; |
| 1529 | } | 1517 | } |
| 1530 | for (ptrdiff_t i = 0; i < clausenb; i++) | 1518 | Lisp_Object volatile var_volatile = var; |
| 1519 | Lisp_Object val, handler_body; | ||
| 1520 | for (Lisp_Object volatile *pcl = clauses; ; pcl++) | ||
| 1531 | { | 1521 | { |
| 1532 | Lisp_Object clause = clauses[i]; | 1522 | if (BASE_EQ (*pcl, make_fixnum (0))) |
| 1523 | { | ||
| 1524 | val = eval_sub (bodyform); | ||
| 1525 | handlerlist = oldhandlerlist; | ||
| 1526 | if (NILP (success_handler)) | ||
| 1527 | return val; | ||
| 1528 | #if GCC_LINT && __GNUC__ && !__clang__ | ||
| 1529 | /* This useless assignment pacifies GCC 14.2.1 x86-64 | ||
| 1530 | <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=21161>. */ | ||
| 1531 | var = var_volatile; | ||
| 1532 | #endif | ||
| 1533 | handler_body = XCDR (success_handler); | ||
| 1534 | break; | ||
| 1535 | } | ||
| 1536 | Lisp_Object clause = *pcl; | ||
| 1533 | Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil; | 1537 | Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil; |
| 1534 | if (!CONSP (condition)) | 1538 | if (!CONSP (condition)) |
| 1535 | condition = list1 (condition); | 1539 | condition = list1 (condition); |
| 1536 | struct handler *c = push_handler (condition, CONDITION_CASE); | 1540 | struct handler *c = push_handler (condition, CONDITION_CASE); |
| 1541 | Lisp_Object volatile *clauses_volatile = clauses; | ||
| 1537 | if (sys_setjmp (c->jmp)) | 1542 | if (sys_setjmp (c->jmp)) |
| 1538 | { | 1543 | { |
| 1539 | Lisp_Object val = handlerlist->val; | 1544 | var = var_volatile; |
| 1540 | Lisp_Object volatile *chosen_clause = clauses; | 1545 | val = handlerlist->val; |
| 1541 | for (struct handler *h = handlerlist->next; h != oldhandlerlist; | 1546 | Lisp_Object volatile *chosen_clause = clauses_volatile; |
| 1542 | h = h->next) | 1547 | struct handler *oldh = oldhandlerlist; |
| 1548 | for (struct handler *h = handlerlist->next; h != oldh; h = h->next) | ||
| 1543 | chosen_clause++; | 1549 | chosen_clause++; |
| 1544 | Lisp_Object handler_body = XCDR (*chosen_clause); | 1550 | handler_body = XCDR (*chosen_clause); |
| 1545 | handlerlist = oldhandlerlist; | 1551 | handlerlist = oldh; |
| 1546 | |||
| 1547 | if (NILP (var)) | ||
| 1548 | return Fprogn (handler_body); | ||
| 1549 | 1552 | ||
| 1550 | Lisp_Object handler_var = var; | 1553 | /* Whoever longjumped to us unwound the stack to C->pdlcount before |
| 1551 | if (!NILP (Vinternal_interpreter_environment)) | 1554 | throwing, so the unbind_to will undo just this binding. */ |
| 1552 | { | 1555 | break; |
| 1553 | val = Fcons (Fcons (var, val), | ||
| 1554 | Vinternal_interpreter_environment); | ||
| 1555 | handler_var = Qinternal_interpreter_environment; | ||
| 1556 | } | ||
| 1557 | |||
| 1558 | /* Bind HANDLER_VAR to VAL while evaluating HANDLER_BODY. | ||
| 1559 | The unbind_to undoes just this binding; whoever longjumped | ||
| 1560 | to us unwound the stack to C->pdlcount before throwing. */ | ||
| 1561 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 1562 | specbind (handler_var, val); | ||
| 1563 | return unbind_to (count, Fprogn (handler_body)); | ||
| 1564 | } | 1556 | } |
| 1565 | } | 1557 | } |
| 1566 | 1558 | ||
| 1567 | Lisp_Object CACHEABLE result = eval_sub (bodyform); | 1559 | if (NILP (var)) |
| 1568 | handlerlist = oldhandlerlist; | 1560 | return Fprogn (handler_body); |
| 1569 | if (!NILP (success_handler)) | ||
| 1570 | { | ||
| 1571 | if (NILP (var)) | ||
| 1572 | return Fprogn (XCDR (success_handler)); | ||
| 1573 | 1561 | ||
| 1574 | Lisp_Object handler_var = var; | 1562 | if (!NILP (Vinternal_interpreter_environment)) |
| 1575 | if (!NILP (Vinternal_interpreter_environment)) | 1563 | { |
| 1576 | { | 1564 | val = Fcons (Fcons (var, val), |
| 1577 | result = Fcons (Fcons (var, result), | 1565 | Vinternal_interpreter_environment); |
| 1578 | Vinternal_interpreter_environment); | 1566 | var = Qinternal_interpreter_environment; |
| 1579 | handler_var = Qinternal_interpreter_environment; | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 1583 | specbind (handler_var, result); | ||
| 1584 | return unbind_to (count, Fprogn (XCDR (success_handler))); | ||
| 1585 | } | 1567 | } |
| 1586 | return result; | 1568 | |
| 1569 | specpdl_ref count = SPECPDL_INDEX (); | ||
| 1570 | specbind (var, val); | ||
| 1571 | return unbind_to (count, Fprogn (handler_body)); | ||
| 1587 | } | 1572 | } |
| 1588 | 1573 | ||
| 1589 | /* Call the function BFUN with no arguments, catching errors within it | 1574 | /* Call the function BFUN with no arguments, catching errors within it |
| @@ -1740,7 +1725,7 @@ push_handler (Lisp_Object tag_ch_val, enum handlertype handlertype) | |||
| 1740 | struct handler * | 1725 | struct handler * |
| 1741 | push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) | 1726 | push_handler_nosignal (Lisp_Object tag_ch_val, enum handlertype handlertype) |
| 1742 | { | 1727 | { |
| 1743 | struct handler *CACHEABLE c = handlerlist->nextfree; | 1728 | struct handler *c = handlerlist->nextfree; |
| 1744 | if (!c) | 1729 | if (!c) |
| 1745 | { | 1730 | { |
| 1746 | c = malloc (sizeof *c); | 1731 | c = malloc (sizeof *c); |