aboutsummaryrefslogtreecommitdiffstats
path: root/src/fns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fns.c')
-rw-r--r--src/fns.c377
1 files changed, 157 insertions, 220 deletions
diff --git a/src/fns.c b/src/fns.c
index 00fa65886f0..ac7c1f265a4 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
34#include "buffer.h" 34#include "buffer.h"
35#include "intervals.h" 35#include "intervals.h"
36#include "window.h" 36#include "window.h"
37#include "puresize.h"
37 38
38static void sort_vector_copy (Lisp_Object, ptrdiff_t, 39static void sort_vector_copy (Lisp_Object, ptrdiff_t,
39 Lisp_Object *restrict, Lisp_Object *restrict); 40 Lisp_Object *restrict, Lisp_Object *restrict);
@@ -83,18 +84,8 @@ See Info node `(elisp)Random Numbers' for more details. */)
83 return make_number (val); 84 return make_number (val);
84} 85}
85 86
86/* Heuristic on how many iterations of a tight loop can be safely done
87 before it's time to do a QUIT. This must be a power of 2. */
88enum { QUIT_COUNT_HEURISTIC = 1 << 16 };
89
90/* Random data-structure functions. */ 87/* Random data-structure functions. */
91 88
92static void
93CHECK_LIST_END (Lisp_Object x, Lisp_Object y)
94{
95 CHECK_TYPE (NILP (x), Qlistp, y);
96}
97
98DEFUN ("length", Flength, Slength, 1, 1, 0, 89DEFUN ("length", Flength, Slength, 1, 1, 0,
99 doc: /* Return the length of vector, list or string SEQUENCE. 90 doc: /* Return the length of vector, list or string SEQUENCE.
100A byte-code function object is also allowed. 91A byte-code function object is also allowed.
@@ -126,7 +117,7 @@ To get the number of bytes, use `string-bytes'. */)
126 { 117 {
127 if (MOST_POSITIVE_FIXNUM < i) 118 if (MOST_POSITIVE_FIXNUM < i)
128 error ("List too long"); 119 error ("List too long");
129 QUIT; 120 maybe_quit ();
130 } 121 }
131 sequence = XCDR (sequence); 122 sequence = XCDR (sequence);
132 } 123 }
@@ -172,7 +163,7 @@ which is at least the number of distinct elements. */)
172 halftail = XCDR (halftail); 163 halftail = XCDR (halftail);
173 if ((lolen & (QUIT_COUNT_HEURISTIC - 1)) == 0) 164 if ((lolen & (QUIT_COUNT_HEURISTIC - 1)) == 0)
174 { 165 {
175 QUIT; 166 maybe_quit ();
176 if (lolen == 0) 167 if (lolen == 0)
177 hilen += UINTMAX_MAX + 1.0; 168 hilen += UINTMAX_MAX + 1.0;
178 } 169 }
@@ -1202,17 +1193,12 @@ are shared, however.
1202Elements of ALIST that are not conses are also shared. */) 1193Elements of ALIST that are not conses are also shared. */)
1203 (Lisp_Object alist) 1194 (Lisp_Object alist)
1204{ 1195{
1205 register Lisp_Object tem;
1206
1207 CHECK_LIST (alist);
1208 if (NILP (alist)) 1196 if (NILP (alist))
1209 return alist; 1197 return alist;
1210 alist = concat (1, &alist, Lisp_Cons, 0); 1198 alist = concat (1, &alist, Lisp_Cons, false);
1211 for (tem = alist; CONSP (tem); tem = XCDR (tem)) 1199 for (Lisp_Object tem = alist; !NILP (tem); tem = XCDR (tem))
1212 { 1200 {
1213 register Lisp_Object car; 1201 Lisp_Object car = XCAR (tem);
1214 car = XCAR (tem);
1215
1216 if (CONSP (car)) 1202 if (CONSP (car))
1217 XSETCAR (tem, Fcons (XCAR (car), XCDR (car))); 1203 XSETCAR (tem, Fcons (XCAR (car), XCDR (car)));
1218 } 1204 }
@@ -1356,16 +1342,19 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1356 doc: /* Take cdr N times on LIST, return the result. */) 1342 doc: /* Take cdr N times on LIST, return the result. */)
1357 (Lisp_Object n, Lisp_Object list) 1343 (Lisp_Object n, Lisp_Object list)
1358{ 1344{
1359 EMACS_INT i, num;
1360 CHECK_NUMBER (n); 1345 CHECK_NUMBER (n);
1361 num = XINT (n); 1346 Lisp_Object tail = list;
1362 for (i = 0; i < num && !NILP (list); i++) 1347 for (EMACS_INT num = XINT (n); 0 < num; num--)
1363 { 1348 {
1364 QUIT; 1349 if (! CONSP (tail))
1365 CHECK_LIST_CONS (list, list); 1350 {
1366 list = XCDR (list); 1351 CHECK_LIST_END (tail, list);
1352 return Qnil;
1353 }
1354 tail = XCDR (tail);
1355 rarely_quit (num);
1367 } 1356 }
1368 return list; 1357 return tail;
1369} 1358}
1370 1359
1371DEFUN ("nth", Fnth, Snth, 2, 2, 0, 1360DEFUN ("nth", Fnth, Snth, 2, 2, 0,
@@ -1392,66 +1381,55 @@ DEFUN ("elt", Felt, Selt, 2, 2, 0,
1392DEFUN ("member", Fmember, Smember, 2, 2, 0, 1381DEFUN ("member", Fmember, Smember, 2, 2, 0,
1393 doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `equal'. 1382 doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
1394The value is actually the tail of LIST whose car is ELT. */) 1383The value is actually the tail of LIST whose car is ELT. */)
1395 (register Lisp_Object elt, Lisp_Object list) 1384 (Lisp_Object elt, Lisp_Object list)
1396{ 1385{
1397 register Lisp_Object tail; 1386 unsigned short int quit_count = 0;
1398 for (tail = list; !NILP (tail); tail = XCDR (tail)) 1387 Lisp_Object tail;
1388 for (tail = list; CONSP (tail); tail = XCDR (tail))
1399 { 1389 {
1400 register Lisp_Object tem; 1390 if (! NILP (Fequal (elt, XCAR (tail))))
1401 CHECK_LIST_CONS (tail, list);
1402 tem = XCAR (tail);
1403 if (! NILP (Fequal (elt, tem)))
1404 return tail; 1391 return tail;
1405 QUIT; 1392 rarely_quit (++quit_count);
1406 } 1393 }
1394 CHECK_LIST_END (tail, list);
1407 return Qnil; 1395 return Qnil;
1408} 1396}
1409 1397
1410DEFUN ("memq", Fmemq, Smemq, 2, 2, 0, 1398DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1411 doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `eq'. 1399 doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `eq'.
1412The value is actually the tail of LIST whose car is ELT. */) 1400The value is actually the tail of LIST whose car is ELT. */)
1413 (register Lisp_Object elt, Lisp_Object list) 1401 (Lisp_Object elt, Lisp_Object list)
1414{ 1402{
1415 while (1) 1403 unsigned short int quit_count = 0;
1404 Lisp_Object tail;
1405 for (tail = list; CONSP (tail); tail = XCDR (tail))
1416 { 1406 {
1417 if (!CONSP (list) || EQ (XCAR (list), elt)) 1407 if (EQ (XCAR (tail), elt))
1418 break; 1408 return tail;
1419 1409 rarely_quit (++quit_count);
1420 list = XCDR (list);
1421 if (!CONSP (list) || EQ (XCAR (list), elt))
1422 break;
1423
1424 list = XCDR (list);
1425 if (!CONSP (list) || EQ (XCAR (list), elt))
1426 break;
1427
1428 list = XCDR (list);
1429 QUIT;
1430 } 1410 }
1431 1411 CHECK_LIST_END (tail, list);
1432 CHECK_LIST (list); 1412 return Qnil;
1433 return list;
1434} 1413}
1435 1414
1436DEFUN ("memql", Fmemql, Smemql, 2, 2, 0, 1415DEFUN ("memql", Fmemql, Smemql, 2, 2, 0,
1437 doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `eql'. 1416 doc: /* Return non-nil if ELT is an element of LIST. Comparison done with `eql'.
1438The value is actually the tail of LIST whose car is ELT. */) 1417The value is actually the tail of LIST whose car is ELT. */)
1439 (register Lisp_Object elt, Lisp_Object list) 1418 (Lisp_Object elt, Lisp_Object list)
1440{ 1419{
1441 register Lisp_Object tail;
1442
1443 if (!FLOATP (elt)) 1420 if (!FLOATP (elt))
1444 return Fmemq (elt, list); 1421 return Fmemq (elt, list);
1445 1422
1446 for (tail = list; !NILP (tail); tail = XCDR (tail)) 1423 unsigned short int quit_count = 0;
1424 Lisp_Object tail;
1425 for (tail = list; CONSP (tail); tail = XCDR (tail))
1447 { 1426 {
1448 register Lisp_Object tem; 1427 Lisp_Object tem = XCAR (tail);
1449 CHECK_LIST_CONS (tail, list);
1450 tem = XCAR (tail);
1451 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil)) 1428 if (FLOATP (tem) && internal_equal (elt, tem, 0, 0, Qnil))
1452 return tail; 1429 return tail;
1453 QUIT; 1430 rarely_quit (++quit_count);
1454 } 1431 }
1432 CHECK_LIST_END (tail, list);
1455 return Qnil; 1433 return Qnil;
1456} 1434}
1457 1435
@@ -1461,44 +1439,28 @@ The value is actually the first element of LIST whose car is KEY.
1461Elements of LIST that are not conses are ignored. */) 1439Elements of LIST that are not conses are ignored. */)
1462 (Lisp_Object key, Lisp_Object list) 1440 (Lisp_Object key, Lisp_Object list)
1463{ 1441{
1464 while (1) 1442 unsigned short int quit_count = 0;
1443 Lisp_Object tail;
1444 for (tail = list; CONSP (tail); tail = XCDR (tail))
1465 { 1445 {
1466 if (!CONSP (list) 1446 if (CONSP (XCAR (tail)) && EQ (XCAR (XCAR (tail)), key))
1467 || (CONSP (XCAR (list)) 1447 return XCAR (tail);
1468 && EQ (XCAR (XCAR (list)), key))) 1448 rarely_quit (++quit_count);
1469 break;
1470
1471 list = XCDR (list);
1472 if (!CONSP (list)
1473 || (CONSP (XCAR (list))
1474 && EQ (XCAR (XCAR (list)), key)))
1475 break;
1476
1477 list = XCDR (list);
1478 if (!CONSP (list)
1479 || (CONSP (XCAR (list))
1480 && EQ (XCAR (XCAR (list)), key)))
1481 break;
1482
1483 list = XCDR (list);
1484 QUIT;
1485 } 1449 }
1486 1450 CHECK_LIST_END (tail, list);
1487 return CAR (list); 1451 return Qnil;
1488} 1452}
1489 1453
1490/* Like Fassq but never report an error and do not allow quits. 1454/* Like Fassq but never report an error and do not allow quits.
1491 Use only on lists known never to be circular. */ 1455 Use only on objects known to be non-circular lists. */
1492 1456
1493Lisp_Object 1457Lisp_Object
1494assq_no_quit (Lisp_Object key, Lisp_Object list) 1458assq_no_quit (Lisp_Object key, Lisp_Object list)
1495{ 1459{
1496 while (CONSP (list) 1460 for (; ! NILP (list); list = XCDR (list))
1497 && (!CONSP (XCAR (list)) 1461 if (CONSP (XCAR (list)) && EQ (XCAR (XCAR (list)), key))
1498 || !EQ (XCAR (XCAR (list)), key))) 1462 return XCAR (list);
1499 list = XCDR (list); 1463 return Qnil;
1500
1501 return CAR_SAFE (list);
1502} 1464}
1503 1465
1504DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0, 1466DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
@@ -1506,81 +1468,51 @@ DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
1506The value is actually the first element of LIST whose car equals KEY. */) 1468The value is actually the first element of LIST whose car equals KEY. */)
1507 (Lisp_Object key, Lisp_Object list) 1469 (Lisp_Object key, Lisp_Object list)
1508{ 1470{
1509 Lisp_Object car; 1471 unsigned short int quit_count = 0;
1510 1472 Lisp_Object tail;
1511 while (1) 1473 for (tail = list; CONSP (tail); tail = XCDR (tail))
1512 { 1474 {
1513 if (!CONSP (list) 1475 Lisp_Object car = XCAR (tail);
1514 || (CONSP (XCAR (list)) 1476 if (CONSP (car)
1515 && (car = XCAR (XCAR (list)), 1477 && (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key))))
1516 EQ (car, key) || !NILP (Fequal (car, key))))) 1478 return car;
1517 break; 1479 rarely_quit (++quit_count);
1518
1519 list = XCDR (list);
1520 if (!CONSP (list)
1521 || (CONSP (XCAR (list))
1522 && (car = XCAR (XCAR (list)),
1523 EQ (car, key) || !NILP (Fequal (car, key)))))
1524 break;
1525
1526 list = XCDR (list);
1527 if (!CONSP (list)
1528 || (CONSP (XCAR (list))
1529 && (car = XCAR (XCAR (list)),
1530 EQ (car, key) || !NILP (Fequal (car, key)))))
1531 break;
1532
1533 list = XCDR (list);
1534 QUIT;
1535 } 1480 }
1536 1481 CHECK_LIST_END (tail, list);
1537 return CAR (list); 1482 return Qnil;
1538} 1483}
1539 1484
1540/* Like Fassoc but never report an error and do not allow quits. 1485/* Like Fassoc but never report an error and do not allow quits.
1541 Use only on lists known never to be circular. */ 1486 Use only on objects known to be non-circular lists. */
1542 1487
1543Lisp_Object 1488Lisp_Object
1544assoc_no_quit (Lisp_Object key, Lisp_Object list) 1489assoc_no_quit (Lisp_Object key, Lisp_Object list)
1545{ 1490{
1546 while (CONSP (list) 1491 for (; ! NILP (list); list = XCDR (list))
1547 && (!CONSP (XCAR (list)) 1492 {
1548 || (!EQ (XCAR (XCAR (list)), key) 1493 Lisp_Object car = XCAR (list);
1549 && NILP (Fequal (XCAR (XCAR (list)), key))))) 1494 if (CONSP (car)
1550 list = XCDR (list); 1495 && (EQ (XCAR (car), key) || !NILP (Fequal (XCAR (car), key))))
1551 1496 return car;
1552 return CONSP (list) ? XCAR (list) : Qnil; 1497 }
1498 return Qnil;
1553} 1499}
1554 1500
1555DEFUN ("rassq", Frassq, Srassq, 2, 2, 0, 1501DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1556 doc: /* Return non-nil if KEY is `eq' to the cdr of an element of LIST. 1502 doc: /* Return non-nil if KEY is `eq' to the cdr of an element of LIST.
1557The value is actually the first element of LIST whose cdr is KEY. */) 1503The value is actually the first element of LIST whose cdr is KEY. */)
1558 (register Lisp_Object key, Lisp_Object list) 1504 (Lisp_Object key, Lisp_Object list)
1559{ 1505{
1560 while (1) 1506 unsigned short int quit_count = 0;
1507 Lisp_Object tail;
1508 for (tail = list; CONSP (tail); tail = XCDR (tail))
1561 { 1509 {
1562 if (!CONSP (list) 1510 if (CONSP (XCAR (tail)) && EQ (XCDR (XCAR (tail)), key))
1563 || (CONSP (XCAR (list)) 1511 return XCAR (tail);
1564 && EQ (XCDR (XCAR (list)), key))) 1512 rarely_quit (++quit_count);
1565 break;
1566
1567 list = XCDR (list);
1568 if (!CONSP (list)
1569 || (CONSP (XCAR (list))
1570 && EQ (XCDR (XCAR (list)), key)))
1571 break;
1572
1573 list = XCDR (list);
1574 if (!CONSP (list)
1575 || (CONSP (XCAR (list))
1576 && EQ (XCDR (XCAR (list)), key)))
1577 break;
1578
1579 list = XCDR (list);
1580 QUIT;
1581 } 1513 }
1582 1514 CHECK_LIST_END (tail, list);
1583 return CAR (list); 1515 return Qnil;
1584} 1516}
1585 1517
1586DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0, 1518DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
@@ -1588,35 +1520,18 @@ DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1588The value is actually the first element of LIST whose cdr equals KEY. */) 1520The value is actually the first element of LIST whose cdr equals KEY. */)
1589 (Lisp_Object key, Lisp_Object list) 1521 (Lisp_Object key, Lisp_Object list)
1590{ 1522{
1591 Lisp_Object cdr; 1523 unsigned short int quit_count = 0;
1592 1524 Lisp_Object tail;
1593 while (1) 1525 for (tail = list; CONSP (tail); tail = XCDR (tail))
1594 { 1526 {
1595 if (!CONSP (list) 1527 Lisp_Object car = XCAR (tail);
1596 || (CONSP (XCAR (list)) 1528 if (CONSP (car)
1597 && (cdr = XCDR (XCAR (list)), 1529 && (EQ (XCDR (car), key) || !NILP (Fequal (XCDR (car), key))))
1598 EQ (cdr, key) || !NILP (Fequal (cdr, key))))) 1530 return car;
1599 break; 1531 rarely_quit (++quit_count);
1600
1601 list = XCDR (list);
1602 if (!CONSP (list)
1603 || (CONSP (XCAR (list))
1604 && (cdr = XCDR (XCAR (list)),
1605 EQ (cdr, key) || !NILP (Fequal (cdr, key)))))
1606 break;
1607
1608 list = XCDR (list);
1609 if (!CONSP (list)
1610 || (CONSP (XCAR (list))
1611 && (cdr = XCDR (XCAR (list)),
1612 EQ (cdr, key) || !NILP (Fequal (cdr, key)))))
1613 break;
1614
1615 list = XCDR (list);
1616 QUIT;
1617 } 1532 }
1618 1533 CHECK_LIST_END (tail, list);
1619 return CAR (list); 1534 return Qnil;
1620} 1535}
1621 1536
1622DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0, 1537DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
@@ -1647,6 +1562,7 @@ argument. */)
1647 else 1562 else
1648 prev = tail; 1563 prev = tail;
1649 } 1564 }
1565 CHECK_LIST_END (tail, list);
1650 return list; 1566 return list;
1651} 1567}
1652 1568
@@ -1754,12 +1670,11 @@ changing the value of a sequence `foo'. */)
1754 } 1670 }
1755 else 1671 else
1756 { 1672 {
1673 unsigned short int quit_count = 0;
1757 Lisp_Object tail, prev; 1674 Lisp_Object tail, prev;
1758 1675
1759 for (tail = seq, prev = Qnil; !NILP (tail); tail = XCDR (tail)) 1676 for (tail = seq, prev = Qnil; CONSP (tail); tail = XCDR (tail))
1760 { 1677 {
1761 CHECK_LIST_CONS (tail, seq);
1762
1763 if (!NILP (Fequal (elt, XCAR (tail)))) 1678 if (!NILP (Fequal (elt, XCAR (tail))))
1764 { 1679 {
1765 if (NILP (prev)) 1680 if (NILP (prev))
@@ -1769,8 +1684,9 @@ changing the value of a sequence `foo'. */)
1769 } 1684 }
1770 else 1685 else
1771 prev = tail; 1686 prev = tail;
1772 QUIT; 1687 rarely_quit (++quit_count);
1773 } 1688 }
1689 CHECK_LIST_END (tail, seq);
1774 } 1690 }
1775 1691
1776 return seq; 1692 return seq;
@@ -1788,16 +1704,17 @@ This function may destructively modify SEQ to produce the value. */)
1788 return Freverse (seq); 1704 return Freverse (seq);
1789 else if (CONSP (seq)) 1705 else if (CONSP (seq))
1790 { 1706 {
1707 unsigned short int quit_count = 0;
1791 Lisp_Object prev, tail, next; 1708 Lisp_Object prev, tail, next;
1792 1709
1793 for (prev = Qnil, tail = seq; !NILP (tail); tail = next) 1710 for (prev = Qnil, tail = seq; CONSP (tail); tail = next)
1794 { 1711 {
1795 QUIT;
1796 CHECK_LIST_CONS (tail, tail);
1797 next = XCDR (tail); 1712 next = XCDR (tail);
1798 Fsetcdr (tail, prev); 1713 Fsetcdr (tail, prev);
1799 prev = tail; 1714 prev = tail;
1715 rarely_quit (++quit_count);
1800 } 1716 }
1717 CHECK_LIST_END (tail, seq);
1801 seq = prev; 1718 seq = prev;
1802 } 1719 }
1803 else if (VECTORP (seq)) 1720 else if (VECTORP (seq))
@@ -1838,10 +1755,11 @@ See also the function `nreverse', which is used more often. */)
1838 return Qnil; 1755 return Qnil;
1839 else if (CONSP (seq)) 1756 else if (CONSP (seq))
1840 { 1757 {
1758 unsigned short int quit_count = 0;
1841 for (new = Qnil; CONSP (seq); seq = XCDR (seq)) 1759 for (new = Qnil; CONSP (seq); seq = XCDR (seq))
1842 { 1760 {
1843 QUIT;
1844 new = Fcons (XCAR (seq), new); 1761 new = Fcons (XCAR (seq), new);
1762 rarely_quit (++quit_count);
1845 } 1763 }
1846 CHECK_LIST_END (seq, seq); 1764 CHECK_LIST_END (seq, seq);
1847 } 1765 }
@@ -2130,12 +2048,11 @@ If PROP is already a property on the list, its value is set to VAL,
2130otherwise the new PROP VAL pair is added. The new plist is returned; 2048otherwise the new PROP VAL pair is added. The new plist is returned;
2131use `(setq x (plist-put x prop val))' to be sure to use the new value. 2049use `(setq x (plist-put x prop val))' to be sure to use the new value.
2132The PLIST is modified by side effects. */) 2050The PLIST is modified by side effects. */)
2133 (Lisp_Object plist, register Lisp_Object prop, Lisp_Object val) 2051 (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
2134{ 2052{
2135 register Lisp_Object tail, prev; 2053 unsigned short int quit_count = 0;
2136 Lisp_Object newcell; 2054 Lisp_Object prev = Qnil;
2137 prev = Qnil; 2055 for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2138 for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2139 tail = XCDR (XCDR (tail))) 2056 tail = XCDR (XCDR (tail)))
2140 { 2057 {
2141 if (EQ (prop, XCAR (tail))) 2058 if (EQ (prop, XCAR (tail)))
@@ -2145,13 +2062,13 @@ The PLIST is modified by side effects. */)
2145 } 2062 }
2146 2063
2147 prev = tail; 2064 prev = tail;
2148 QUIT; 2065 rarely_quit (++quit_count);
2149 } 2066 }
2150 newcell = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev)))); 2067 Lisp_Object newcell
2068 = Fcons (prop, Fcons (val, NILP (prev) ? plist : XCDR (XCDR (prev))));
2151 if (NILP (prev)) 2069 if (NILP (prev))
2152 return newcell; 2070 return newcell;
2153 else 2071 Fsetcdr (XCDR (prev), newcell);
2154 Fsetcdr (XCDR (prev), newcell);
2155 return plist; 2072 return plist;
2156} 2073}
2157 2074
@@ -2174,6 +2091,7 @@ corresponding to the given PROP, or nil if PROP is not
2174one of the properties on the list. */) 2091one of the properties on the list. */)
2175 (Lisp_Object plist, Lisp_Object prop) 2092 (Lisp_Object plist, Lisp_Object prop)
2176{ 2093{
2094 unsigned short int quit_count = 0;
2177 Lisp_Object tail; 2095 Lisp_Object tail;
2178 2096
2179 for (tail = plist; 2097 for (tail = plist;
@@ -2182,8 +2100,7 @@ one of the properties on the list. */)
2182 { 2100 {
2183 if (! NILP (Fequal (prop, XCAR (tail)))) 2101 if (! NILP (Fequal (prop, XCAR (tail))))
2184 return XCAR (XCDR (tail)); 2102 return XCAR (XCDR (tail));
2185 2103 rarely_quit (++quit_count);
2186 QUIT;
2187 } 2104 }
2188 2105
2189 CHECK_LIST_END (tail, prop); 2106 CHECK_LIST_END (tail, prop);
@@ -2199,12 +2116,11 @@ If PROP is already a property on the list, its value is set to VAL,
2199otherwise the new PROP VAL pair is added. The new plist is returned; 2116otherwise the new PROP VAL pair is added. The new plist is returned;
2200use `(setq x (lax-plist-put x prop val))' to be sure to use the new value. 2117use `(setq x (lax-plist-put x prop val))' to be sure to use the new value.
2201The PLIST is modified by side effects. */) 2118The PLIST is modified by side effects. */)
2202 (Lisp_Object plist, register Lisp_Object prop, Lisp_Object val) 2119 (Lisp_Object plist, Lisp_Object prop, Lisp_Object val)
2203{ 2120{
2204 register Lisp_Object tail, prev; 2121 unsigned short int quit_count = 0;
2205 Lisp_Object newcell; 2122 Lisp_Object prev = Qnil;
2206 prev = Qnil; 2123 for (Lisp_Object tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2207 for (tail = plist; CONSP (tail) && CONSP (XCDR (tail));
2208 tail = XCDR (XCDR (tail))) 2124 tail = XCDR (XCDR (tail)))
2209 { 2125 {
2210 if (! NILP (Fequal (prop, XCAR (tail)))) 2126 if (! NILP (Fequal (prop, XCAR (tail))))
@@ -2214,13 +2130,12 @@ The PLIST is modified by side effects. */)
2214 } 2130 }
2215 2131
2216 prev = tail; 2132 prev = tail;
2217 QUIT; 2133 rarely_quit (++quit_count);
2218 } 2134 }
2219 newcell = list2 (prop, val); 2135 Lisp_Object newcell = list2 (prop, val);
2220 if (NILP (prev)) 2136 if (NILP (prev))
2221 return newcell; 2137 return newcell;
2222 else 2138 Fsetcdr (XCDR (prev), newcell);
2223 Fsetcdr (XCDR (prev), newcell);
2224 return plist; 2139 return plist;
2225} 2140}
2226 2141
@@ -2293,8 +2208,9 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props,
2293 } 2208 }
2294 } 2209 }
2295 2210
2211 unsigned short int quit_count = 0;
2296 tail_recurse: 2212 tail_recurse:
2297 QUIT; 2213 rarely_quit (++quit_count);
2298 if (EQ (o1, o2)) 2214 if (EQ (o1, o2))
2299 return 1; 2215 return 1;
2300 if (XTYPE (o1) != XTYPE (o2)) 2216 if (XTYPE (o1) != XTYPE (o2))
@@ -2483,14 +2399,12 @@ Only the last argument is not altered, and need not be a list.
2483usage: (nconc &rest LISTS) */) 2399usage: (nconc &rest LISTS) */)
2484 (ptrdiff_t nargs, Lisp_Object *args) 2400 (ptrdiff_t nargs, Lisp_Object *args)
2485{ 2401{
2486 ptrdiff_t argnum; 2402 unsigned short int quit_count = 0;
2487 register Lisp_Object tail, tem, val; 2403 Lisp_Object val = Qnil;
2488
2489 val = tail = Qnil;
2490 2404
2491 for (argnum = 0; argnum < nargs; argnum++) 2405 for (ptrdiff_t argnum = 0; argnum < nargs; argnum++)
2492 { 2406 {
2493 tem = args[argnum]; 2407 Lisp_Object tem = args[argnum];
2494 if (NILP (tem)) continue; 2408 if (NILP (tem)) continue;
2495 2409
2496 if (NILP (val)) 2410 if (NILP (val))
@@ -2498,14 +2412,16 @@ usage: (nconc &rest LISTS) */)
2498 2412
2499 if (argnum + 1 == nargs) break; 2413 if (argnum + 1 == nargs) break;
2500 2414
2501 CHECK_LIST_CONS (tem, tem); 2415 CHECK_CONS (tem);
2502 2416
2503 while (CONSP (tem)) 2417 Lisp_Object tail;
2418 do
2504 { 2419 {
2505 tail = tem; 2420 tail = tem;
2506 tem = XCDR (tail); 2421 tem = XCDR (tail);
2507 QUIT; 2422 rarely_quit (++quit_count);
2508 } 2423 }
2424 while (CONSP (tem));
2509 2425
2510 tem = args[argnum + 1]; 2426 tem = args[argnum + 1];
2511 Fsetcdr (tail, tem); 2427 Fsetcdr (tail, tem);
@@ -2927,11 +2843,12 @@ property and a property with the value nil.
2927The value is actually the tail of PLIST whose car is PROP. */) 2843The value is actually the tail of PLIST whose car is PROP. */)
2928 (Lisp_Object plist, Lisp_Object prop) 2844 (Lisp_Object plist, Lisp_Object prop)
2929{ 2845{
2846 unsigned short int quit_count = 0;
2930 while (CONSP (plist) && !EQ (XCAR (plist), prop)) 2847 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2931 { 2848 {
2932 plist = XCDR (plist); 2849 plist = XCDR (plist);
2933 plist = CDR (plist); 2850 plist = CDR (plist);
2934 QUIT; 2851 rarely_quit (++quit_count);
2935 } 2852 }
2936 return plist; 2853 return plist;
2937} 2854}
@@ -3804,12 +3721,17 @@ allocate_hash_table (void)
3804 (table size) is >= REHASH_THRESHOLD. 3721 (table size) is >= REHASH_THRESHOLD.
3805 3722
3806 WEAK specifies the weakness of the table. If non-nil, it must be 3723 WEAK specifies the weakness of the table. If non-nil, it must be
3807 one of the symbols `key', `value', `key-or-value', or `key-and-value'. */ 3724 one of the symbols `key', `value', `key-or-value', or `key-and-value'.
3725
3726 If PURECOPY is non-nil, the table can be copied to pure storage via
3727 `purecopy' when Emacs is being dumped. Such tables can no longer be
3728 changed after purecopy. */
3808 3729
3809Lisp_Object 3730Lisp_Object
3810make_hash_table (struct hash_table_test test, 3731make_hash_table (struct hash_table_test test,
3811 Lisp_Object size, Lisp_Object rehash_size, 3732 Lisp_Object size, Lisp_Object rehash_size,
3812 Lisp_Object rehash_threshold, Lisp_Object weak) 3733 Lisp_Object rehash_threshold, Lisp_Object weak,
3734 Lisp_Object pure)
3813{ 3735{
3814 struct Lisp_Hash_Table *h; 3736 struct Lisp_Hash_Table *h;
3815 Lisp_Object table; 3737 Lisp_Object table;
@@ -3850,6 +3772,7 @@ make_hash_table (struct hash_table_test test,
3850 h->hash = Fmake_vector (size, Qnil); 3772 h->hash = Fmake_vector (size, Qnil);
3851 h->next = Fmake_vector (size, Qnil); 3773 h->next = Fmake_vector (size, Qnil);
3852 h->index = Fmake_vector (make_number (index_size), Qnil); 3774 h->index = Fmake_vector (make_number (index_size), Qnil);
3775 h->pure = pure;
3853 3776
3854 /* Set up the free list. */ 3777 /* Set up the free list. */
3855 for (i = 0; i < sz - 1; ++i) 3778 for (i = 0; i < sz - 1; ++i)
@@ -4514,10 +4437,15 @@ key, value, one of key or value, or both key and value, depending on
4514WEAK. WEAK t is equivalent to `key-and-value'. Default value of WEAK 4437WEAK. WEAK t is equivalent to `key-and-value'. Default value of WEAK
4515is nil. 4438is nil.
4516 4439
4440:purecopy PURECOPY -- If PURECOPY is non-nil, the table can be copied
4441to pure storage when Emacs is being dumped, making the contents of the
4442table read only. Any further changes to purified tables will result
4443in an error.
4444
4517usage: (make-hash-table &rest KEYWORD-ARGS) */) 4445usage: (make-hash-table &rest KEYWORD-ARGS) */)
4518 (ptrdiff_t nargs, Lisp_Object *args) 4446 (ptrdiff_t nargs, Lisp_Object *args)
4519{ 4447{
4520 Lisp_Object test, size, rehash_size, rehash_threshold, weak; 4448 Lisp_Object test, size, rehash_size, rehash_threshold, weak, pure;
4521 struct hash_table_test testdesc; 4449 struct hash_table_test testdesc;
4522 ptrdiff_t i; 4450 ptrdiff_t i;
4523 USE_SAFE_ALLOCA; 4451 USE_SAFE_ALLOCA;
@@ -4551,6 +4479,9 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
4551 testdesc.cmpfn = cmpfn_user_defined; 4479 testdesc.cmpfn = cmpfn_user_defined;
4552 } 4480 }
4553 4481
4482 /* See if there's a `:purecopy PURECOPY' argument. */
4483 i = get_key_arg (QCpurecopy, nargs, args, used);
4484 pure = i ? args[i] : Qnil;
4554 /* See if there's a `:size SIZE' argument. */ 4485 /* See if there's a `:size SIZE' argument. */
4555 i = get_key_arg (QCsize, nargs, args, used); 4486 i = get_key_arg (QCsize, nargs, args, used);
4556 size = i ? args[i] : Qnil; 4487 size = i ? args[i] : Qnil;
@@ -4592,7 +4523,8 @@ usage: (make-hash-table &rest KEYWORD-ARGS) */)
4592 signal_error ("Invalid argument list", args[i]); 4523 signal_error ("Invalid argument list", args[i]);
4593 4524
4594 SAFE_FREE (); 4525 SAFE_FREE ();
4595 return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak); 4526 return make_hash_table (testdesc, size, rehash_size, rehash_threshold, weak,
4527 pure);
4596} 4528}
4597 4529
4598 4530
@@ -4671,7 +4603,9 @@ DEFUN ("clrhash", Fclrhash, Sclrhash, 1, 1, 0,
4671 doc: /* Clear hash table TABLE and return it. */) 4603 doc: /* Clear hash table TABLE and return it. */)
4672 (Lisp_Object table) 4604 (Lisp_Object table)
4673{ 4605{
4674 hash_clear (check_hash_table (table)); 4606 struct Lisp_Hash_Table *h = check_hash_table (table);
4607 CHECK_IMPURE (table, h);
4608 hash_clear (h);
4675 /* Be compatible with XEmacs. */ 4609 /* Be compatible with XEmacs. */
4676 return table; 4610 return table;
4677} 4611}
@@ -4695,9 +4629,10 @@ VALUE. In any case, return VALUE. */)
4695 (Lisp_Object key, Lisp_Object value, Lisp_Object table) 4629 (Lisp_Object key, Lisp_Object value, Lisp_Object table)
4696{ 4630{
4697 struct Lisp_Hash_Table *h = check_hash_table (table); 4631 struct Lisp_Hash_Table *h = check_hash_table (table);
4632 CHECK_IMPURE (table, h);
4633
4698 ptrdiff_t i; 4634 ptrdiff_t i;
4699 EMACS_UINT hash; 4635 EMACS_UINT hash;
4700
4701 i = hash_lookup (h, key, &hash); 4636 i = hash_lookup (h, key, &hash);
4702 if (i >= 0) 4637 if (i >= 0)
4703 set_hash_value_slot (h, i, value); 4638 set_hash_value_slot (h, i, value);
@@ -4713,6 +4648,7 @@ DEFUN ("remhash", Fremhash, Sremhash, 2, 2, 0,
4713 (Lisp_Object key, Lisp_Object table) 4648 (Lisp_Object key, Lisp_Object table)
4714{ 4649{
4715 struct Lisp_Hash_Table *h = check_hash_table (table); 4650 struct Lisp_Hash_Table *h = check_hash_table (table);
4651 CHECK_IMPURE (table, h);
4716 hash_remove_from_table (h, key); 4652 hash_remove_from_table (h, key);
4717 return Qnil; 4653 return Qnil;
4718} 4654}
@@ -5083,6 +5019,7 @@ syms_of_fns (void)
5083 DEFSYM (Qequal, "equal"); 5019 DEFSYM (Qequal, "equal");
5084 DEFSYM (QCtest, ":test"); 5020 DEFSYM (QCtest, ":test");
5085 DEFSYM (QCsize, ":size"); 5021 DEFSYM (QCsize, ":size");
5022 DEFSYM (QCpurecopy, ":purecopy");
5086 DEFSYM (QCrehash_size, ":rehash-size"); 5023 DEFSYM (QCrehash_size, ":rehash-size");
5087 DEFSYM (QCrehash_threshold, ":rehash-threshold"); 5024 DEFSYM (QCrehash_threshold, ":rehash-threshold");
5088 DEFSYM (QCweakness, ":weakness"); 5025 DEFSYM (QCweakness, ":weakness");