diff options
| author | Po Lu | 2024-07-22 09:56:08 +0800 |
|---|---|---|
| committer | Po Lu | 2024-07-22 09:56:08 +0800 |
| commit | da0165a01e01dcb4334feee03b462ac09ceb0f8c (patch) | |
| tree | c707b09510f6c41d636e59c7fbbf4f9d81d37b86 /src/data.c | |
| parent | 4868a17396b6796b77285a3608b383aac32aee4f (diff) | |
| download | emacs-da0165a01e01dcb4334feee03b462ac09ceb0f8c.tar.gz emacs-da0165a01e01dcb4334feee03b462ac09ceb0f8c.zip | |
Prohibit unbinding of built-in variables
* src/data.c (set_internal): Signal error if a BLV with a
redirect or a forwarded symbol is being unbound.
* test/src/data-tests.el (binding-test-makunbound-built-in): New
test.
Diffstat (limited to 'src/data.c')
| -rw-r--r-- | src/data.c | 45 |
1 files changed, 22 insertions, 23 deletions
diff --git a/src/data.c b/src/data.c index 3490d4985c9..752856abf09 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -1642,7 +1642,7 @@ void | |||
| 1642 | set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | 1642 | set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, |
| 1643 | enum Set_Internal_Bind bindflag) | 1643 | enum Set_Internal_Bind bindflag) |
| 1644 | { | 1644 | { |
| 1645 | bool voide = BASE_EQ (newval, Qunbound); | 1645 | bool unbinding_p = BASE_EQ (newval, Qunbound); |
| 1646 | 1646 | ||
| 1647 | /* If restoring in a dead buffer, do nothing. */ | 1647 | /* If restoring in a dead buffer, do nothing. */ |
| 1648 | 1648 | ||
| @@ -1661,10 +1661,13 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | |||
| 1661 | case SYMBOL_TRAPPED_WRITE: | 1661 | case SYMBOL_TRAPPED_WRITE: |
| 1662 | /* Setting due to thread-switching doesn't count. */ | 1662 | /* Setting due to thread-switching doesn't count. */ |
| 1663 | if (bindflag != SET_INTERNAL_THREAD_SWITCH) | 1663 | if (bindflag != SET_INTERNAL_THREAD_SWITCH) |
| 1664 | notify_variable_watchers (symbol, voide? Qnil : newval, | 1664 | notify_variable_watchers (symbol, (unbinding_p ? Qnil : newval), |
| 1665 | (bindflag == SET_INTERNAL_BIND? Qlet : | 1665 | (bindflag == SET_INTERNAL_BIND |
| 1666 | bindflag == SET_INTERNAL_UNBIND? Qunlet : | 1666 | ? Qlet |
| 1667 | voide? Qmakunbound : Qset), | 1667 | : (bindflag == SET_INTERNAL_UNBIND |
| 1668 | ? Qunlet | ||
| 1669 | : (unbinding_p | ||
| 1670 | ? Qmakunbound : Qset))), | ||
| 1668 | where); | 1671 | where); |
| 1669 | break; | 1672 | break; |
| 1670 | 1673 | ||
| @@ -1682,6 +1685,11 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | |||
| 1682 | case SYMBOL_LOCALIZED: | 1685 | case SYMBOL_LOCALIZED: |
| 1683 | { | 1686 | { |
| 1684 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); | 1687 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); |
| 1688 | |||
| 1689 | if (unbinding_p && blv->fwd.fwdptr) | ||
| 1690 | /* Forbid unbinding built-in variables. */ | ||
| 1691 | error ("Built-in variables may not be unbound"); | ||
| 1692 | |||
| 1685 | if (NILP (where)) | 1693 | if (NILP (where)) |
| 1686 | XSETBUFFER (where, current_buffer); | 1694 | XSETBUFFER (where, current_buffer); |
| 1687 | 1695 | ||
| @@ -1746,16 +1754,9 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | |||
| 1746 | set_blv_value (blv, newval); | 1754 | set_blv_value (blv, newval); |
| 1747 | 1755 | ||
| 1748 | if (blv->fwd.fwdptr) | 1756 | if (blv->fwd.fwdptr) |
| 1749 | { | 1757 | store_symval_forwarding (blv->fwd, newval, (BUFFERP (where) |
| 1750 | if (voide) | 1758 | ? XBUFFER (where) |
| 1751 | /* If storing void (making the symbol void), forward only through | 1759 | : current_buffer)); |
| 1752 | buffer-local indicator, not through Lisp_Objfwd, etc. */ | ||
| 1753 | blv->fwd.fwdptr = NULL; | ||
| 1754 | else | ||
| 1755 | store_symval_forwarding (blv->fwd, newval, | ||
| 1756 | BUFFERP (where) | ||
| 1757 | ? XBUFFER (where) : current_buffer); | ||
| 1758 | } | ||
| 1759 | break; | 1760 | break; |
| 1760 | } | 1761 | } |
| 1761 | case SYMBOL_FORWARDED: | 1762 | case SYMBOL_FORWARDED: |
| @@ -1763,6 +1764,11 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | |||
| 1763 | struct buffer *buf | 1764 | struct buffer *buf |
| 1764 | = BUFFERP (where) ? XBUFFER (where) : current_buffer; | 1765 | = BUFFERP (where) ? XBUFFER (where) : current_buffer; |
| 1765 | lispfwd innercontents = SYMBOL_FWD (sym); | 1766 | lispfwd innercontents = SYMBOL_FWD (sym); |
| 1767 | |||
| 1768 | if (unbinding_p) | ||
| 1769 | /* Forbid unbinding built-in variables. */ | ||
| 1770 | error ("Built-in variables may not be unbound"); | ||
| 1771 | |||
| 1766 | if (BUFFER_OBJFWDP (innercontents)) | 1772 | if (BUFFER_OBJFWDP (innercontents)) |
| 1767 | { | 1773 | { |
| 1768 | int offset = XBUFFER_OBJFWD (innercontents)->offset; | 1774 | int offset = XBUFFER_OBJFWD (innercontents)->offset; |
| @@ -1778,14 +1784,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where, | |||
| 1778 | } | 1784 | } |
| 1779 | } | 1785 | } |
| 1780 | 1786 | ||
| 1781 | if (voide) | 1787 | store_symval_forwarding (/* sym, */ innercontents, newval, buf); |
| 1782 | { /* If storing void (making the symbol void), forward only through | ||
| 1783 | buffer-local indicator, not through Lisp_Objfwd, etc. */ | ||
| 1784 | sym->u.s.redirect = SYMBOL_PLAINVAL; | ||
| 1785 | SET_SYMBOL_VAL (sym, newval); | ||
| 1786 | } | ||
| 1787 | else | ||
| 1788 | store_symval_forwarding (/* sym, */ innercontents, newval, buf); | ||
| 1789 | break; | 1788 | break; |
| 1790 | } | 1789 | } |
| 1791 | default: emacs_abort (); | 1790 | default: emacs_abort (); |