comparison src/fns.c @ 5306:cde1608596d0

Handle bignum N correctly, #'butlast, #'nbutlast. 2010-11-17 Aidan Kehoe <kehoea@parhasard.net> * fns.c (bignum_butlast): New. (Fnbutlast, Fbutlast): Use it. In #'butlast and #'nbutlast, if N is a bignum, we should always return nil. Bug revealed by Paul Dietz' test suite, thank you Paul.
author Aidan Kehoe <kehoea@parhasard.net>
date Wed, 17 Nov 2010 14:37:26 +0000
parents 4c4085177ca5
children c096d8051f89
comparison
equal deleted inserted replaced
5305:09fed7053634 5306:cde1608596d0
1574 } 1574 }
1575 1575
1576 return retval; 1576 return retval;
1577 } 1577 }
1578 1578
1579 static Lisp_Object bignum_butlast (Lisp_Object list, Lisp_Object number,
1580 Boolint copy);
1581
1579 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /* 1582 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /*
1580 Modify LIST to remove the last N (default 1) elements. 1583 Modify LIST to remove the last N (default 1) elements.
1581 1584
1582 If LIST has N or fewer elements, nil is returned and LIST is unmodified. 1585 If LIST has N or fewer elements, nil is returned and LIST is unmodified.
1583 Otherwise, LIST may be dotted, but not circular. 1586 Otherwise, LIST may be dotted, but not circular.
1588 1591
1589 CHECK_LIST (list); 1592 CHECK_LIST (list);
1590 1593
1591 if (!NILP (n)) 1594 if (!NILP (n))
1592 { 1595 {
1596 if (BIGNUMP (n))
1597 {
1598 return bignum_butlast (list, n, 0);
1599 }
1600
1593 CHECK_NATNUM (n); 1601 CHECK_NATNUM (n);
1594 int_n = XINT (n); 1602 int_n = XINT (n);
1595 } 1603 }
1596 1604
1597 if (CONSP (list)) 1605 if (CONSP (list))
1636 1644
1637 CHECK_LIST (list); 1645 CHECK_LIST (list);
1638 1646
1639 if (!NILP (n)) 1647 if (!NILP (n))
1640 { 1648 {
1649 if (BIGNUMP (n))
1650 {
1651 return bignum_butlast (list, n, 1);
1652 }
1653
1641 CHECK_NATNUM (n); 1654 CHECK_NATNUM (n);
1642 int_n = XINT (n); 1655 int_n = XINT (n);
1643 } 1656 }
1644 1657
1645 if (CONSP (list)) 1658 if (CONSP (list))
1669 } 1682 }
1670 } 1683 }
1671 } 1684 }
1672 1685
1673 return retval; 1686 return retval;
1687 }
1688
1689 /* This is sufficient to implement #'butlast and #'nbutlast with bignum N
1690 under XEmacs, because #'list-length and #'safe-length can never return a
1691 bignum. This means that #'nbutlast never has to modify and #'butlast
1692 never has to copy. */
1693 static Lisp_Object
1694 bignum_butlast (Lisp_Object list, Lisp_Object number, Boolint copy)
1695 {
1696 Boolint malformed = EQ (Fsafe_length (list), Qzero);
1697 Boolint circular = !malformed && EQ (Flist_length (list), Qnil);
1698
1699 assert (BIGNUMP (number));
1700
1701 #ifdef HAVE_BIGNUM
1702
1703 if (bignum_sign (XBIGNUM_DATA (number)) < 0)
1704 {
1705 dead_wrong_type_argument (Qnatnump, number);
1706 }
1707
1708 number = Fcanonicalize_number (number);
1709
1710 if (INTP (number))
1711 {
1712 return copy ? Fbutlast (list, number) : Fnbutlast (list, number);
1713 }
1714
1715 #endif
1716
1717 if (circular)
1718 {
1719 signal_circular_list_error (list);
1720 }
1721
1722 return Qnil;
1674 } 1723 }
1675 1724
1676 DEFUN ("member", Fmember, 2, 2, 0, /* 1725 DEFUN ("member", Fmember, 2, 2, 0, /*
1677 Return non-nil if ELT is an element of LIST. Comparison done with `equal'. 1726 Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
1678 The value is actually the tail of LIST whose car is ELT. 1727 The value is actually the tail of LIST whose car is ELT.