aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2018-08-21 02:05:07 -0700
committerPaul Eggert2018-08-21 02:05:31 -0700
commit77fc2725985b4e5ef977ae6930835c7f0771c61c (patch)
treec578f223cba18da66b1a7cb7a38ef7e8c29e1967 /src
parenteb83344fc7c08ec08b51e7700f1ac2632afa462c (diff)
downloademacs-77fc2725985b4e5ef977ae6930835c7f0771c61c.tar.gz
emacs-77fc2725985b4e5ef977ae6930835c7f0771c61c.zip
Fix glitches introduced by nthcdr changes
* src/fns.c (Fnthcdr): Fix recently-introduced bug when nthcdr is supposed to yield a non-nil non-cons. Reported by Glenn Morris and by Pip Cet here: https://lists.gnu.org/r/emacs-devel/2018-08/msg00699.html https://lists.gnu.org/r/emacs-devel/2018-08/msg00708.html Speed up nthcdr for small N, as suggested by Pip Cet here: https://lists.gnu.org/r/emacs-devel/2018-08/msg00707.html * test/src/fns-tests.el (test-nthcdr-simple): New test.
Diffstat (limited to 'src')
-rw-r--r--src/fns.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/src/fns.c b/src/fns.c
index 8cff6b1b6ca..9d681017c14 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1402,6 +1402,8 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1402 doc: /* Take cdr N times on LIST, return the result. */) 1402 doc: /* Take cdr N times on LIST, return the result. */)
1403 (Lisp_Object n, Lisp_Object list) 1403 (Lisp_Object n, Lisp_Object list)
1404{ 1404{
1405 Lisp_Object tail = list;
1406
1405 CHECK_INTEGER (n); 1407 CHECK_INTEGER (n);
1406 1408
1407 /* A huge but in-range EMACS_INT that can be substituted for a 1409 /* A huge but in-range EMACS_INT that can be substituted for a
@@ -1412,24 +1414,41 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
1412 1414
1413 EMACS_INT num; 1415 EMACS_INT num;
1414 if (FIXNUMP (n)) 1416 if (FIXNUMP (n))
1415 num = XFIXNUM (n); 1417 {
1418 num = XFIXNUM (n);
1419
1420 /* Speed up small lists by omitting circularity and quit checking. */
1421 if (num < 128)
1422 {
1423 for (; 0 < num; num--, tail = XCDR (tail))
1424 if (! CONSP (tail))
1425 {
1426 CHECK_LIST_END (tail, list);
1427 return Qnil;
1428 }
1429 return tail;
1430 }
1431 }
1416 else 1432 else
1417 { 1433 {
1418 num = mpz_sgn (XBIGNUM (n)->value); 1434 if (mpz_sgn (XBIGNUM (n)->value) < 0)
1419 if (0 < num) 1435 return tail;
1420 num = large_num; 1436 num = large_num;
1421 } 1437 }
1422 1438
1423 EMACS_INT tortoise_num = num; 1439 EMACS_INT tortoise_num = num;
1424 Lisp_Object tail = list, saved_tail = tail; 1440 Lisp_Object saved_tail = tail;
1425 FOR_EACH_TAIL_SAFE (tail) 1441 FOR_EACH_TAIL_SAFE (tail)
1426 { 1442 {
1427 if (num <= 0) 1443 /* If the tortoise just jumped (which is rare),
1428 return tail; 1444 update TORTOISE_NUM accordingly. */
1429 if (tail == li.tortoise) 1445 if (EQ (tail, li.tortoise))
1430 tortoise_num = num; 1446 tortoise_num = num;
1447
1431 saved_tail = XCDR (tail); 1448 saved_tail = XCDR (tail);
1432 num--; 1449 num--;
1450 if (num == 0)
1451 return saved_tail;
1433 rarely_quit (num); 1452 rarely_quit (num);
1434 } 1453 }
1435 1454