comparison src/fns.c @ 5307:c096d8051f89

Have NATNUMP give t for positive bignums; check limits appropriately. src/ChangeLog addition: 2010-11-20 Aidan Kehoe <kehoea@parhasard.net> * abbrev.c (Fexpand_abbrev): * alloc.c: * alloc.c (Fmake_list): * alloc.c (Fmake_vector): * alloc.c (Fmake_bit_vector): * alloc.c (Fmake_byte_code): * alloc.c (Fmake_string): * alloc.c (vars_of_alloc): * bytecode.c (UNUSED): * bytecode.c (Fbyte_code): * chartab.c (decode_char_table_range): * cmds.c (Fself_insert_command): * data.c (check_integer_range): * data.c (Fnatnump): * data.c (Fnonnegativep): * data.c (Fstring_to_number): * elhash.c (hash_table_size_validate): * elhash.c (decode_hash_table_size): * eval.c (Fbacktrace_frame): * event-stream.c (lisp_number_to_milliseconds): * event-stream.c (Faccept_process_output): * event-stream.c (Frecent_keys): * event-stream.c (Fdispatch_event): * events.c (Fmake_event): * events.c (Fevent_timestamp): * events.c (Fevent_timestamp_lessp): * events.h: * events.h (struct command_builder): * file-coding.c (gzip_putprop): * fns.c: * fns.c (check_sequence_range): * fns.c (Frandom): * fns.c (Fnthcdr): * fns.c (Flast): * fns.c (Fnbutlast): * fns.c (Fbutlast): * fns.c (Fmember): * fns.c (Ffill): * fns.c (Freduce): * fns.c (replace_string_range_1): * fns.c (Freplace): * font-mgr.c (Ffc_pattern_get): * frame-msw.c (msprinter_set_frame_properties): * glyphs.c (check_valid_xbm_inline): * indent.c (Fmove_to_column): * intl-win32.c (mswindows_multibyte_to_unicode_putprop): * lisp.h: * lisp.h (ARRAY_DIMENSION_LIMIT): * lread.c (decode_mode_1): * mule-ccl.c (ccl_get_compiled_code): * number.h: * process-unix.c (unix_open_multicast_group): * process.c (Fset_process_window_size): * profile.c (Fstart_profiling): * unicode.c (Funicode_to_char): Change NATNUMP to return 1 for positive bignums; changes uses of it and of CHECK_NATNUM appropriately, usually by checking for an integer in an appropriate range. Add array-dimension-limit and use it in #'make-vector, #'make-string. Add array-total-size-limit, array-rank-limit while we're at it, for the sake of any Common Lisp-oriented code that uses these limits. Rename check_int_range to check_integer_range, have it take Lisp_Objects (and thus bignums) instead. Remove bignum_butlast(), just set int_n to an appropriately large integer if N is a bignum. Accept bignums in check_sequence_range(), change the functions that use check_sequence_range() appropriately. Move the definition of NATNUMP() to number.h; document why it's a reasonable name, contradicting an old comment. tests/ChangeLog addition: 2010-11-20 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el: * automated/lisp-tests.el (featurep): * automated/lisp-tests.el (wrong-type-argument): * automated/mule-tests.el (featurep): Check for args-out-of-range errors instead of wrong-type-argument errors in various places when code is handed a large bignum instead of a fixnum. Also check for the wrong-type-argument errors when giving the same code a non-integer value.
author Aidan Kehoe <kehoea@parhasard.net>
date Sat, 20 Nov 2010 16:49:11 +0000
parents cde1608596d0
children c290121b0c3f 8d29f1c4bb98
comparison
equal deleted inserted replaced
5306:cde1608596d0 5307:c096d8051f89
76 76
77 static void 77 static void
78 check_sequence_range (Lisp_Object sequence, Lisp_Object start, 78 check_sequence_range (Lisp_Object sequence, Lisp_Object start,
79 Lisp_Object end, Lisp_Object length) 79 Lisp_Object end, Lisp_Object length)
80 { 80 {
81 Elemcount starting = XINT (start), ending, len = XINT (length); 81 Lisp_Object args[] = { Qzero, start, NILP (end) ? length : end, length };
82 82
83 ending = NILP (end) ? XINT (length) : XINT (end); 83 if (NILP (Fleq (countof (args), args)))
84 84 {
85 if (!(0 <= starting && starting <= ending && ending <= len)) 85 args_out_of_range_3 (sequence, start, end);
86 {
87 args_out_of_range_3 (sequence, start, make_int (ending));
88 } 86 }
89 } 87 }
90 88
91 static Lisp_Object 89 static Lisp_Object
92 mark_bit_vector (Lisp_Object UNUSED (obj)) 90 mark_bit_vector (Lisp_Object UNUSED (obj))
226 224
227 if (EQ (limit, Qt)) 225 if (EQ (limit, Qt))
228 seed_random (qxe_getpid () + time (NULL)); 226 seed_random (qxe_getpid () + time (NULL));
229 if (NATNUMP (limit) && !ZEROP (limit)) 227 if (NATNUMP (limit) && !ZEROP (limit))
230 { 228 {
229 #ifdef HAVE_BIGNUM
230 if (BIGNUMP (limit))
231 {
232 bignum_random (scratch_bignum, XBIGNUM_DATA (limit));
233 return Fcanonicalize_number (make_bignum_bg (scratch_bignum));
234 }
235 #endif
231 /* Try to take our random number from the higher bits of VAL, 236 /* Try to take our random number from the higher bits of VAL,
232 not the lower, since (says Gentzel) the low bits of `random' 237 not the lower, since (says Gentzel) the low bits of `random'
233 are less random than the higher ones. We do this by using the 238 are less random than the higher ones. We do this by using the
234 quotient rather than the remainder. At the high end of the RNG 239 quotient rather than the remainder. At the high end of the RNG
235 it's possible to get a quotient larger than limit; discarding 240 it's possible to get a quotient larger than limit; discarding
238 denominator = ((unsigned long)1 << INT_VALBITS) / XINT (limit); 243 denominator = ((unsigned long)1 << INT_VALBITS) / XINT (limit);
239 do 244 do
240 val = get_random () / denominator; 245 val = get_random () / denominator;
241 while (val >= XINT (limit)); 246 while (val >= XINT (limit));
242 } 247 }
243 #ifdef HAVE_BIGNUM
244 else if (BIGNUMP (limit))
245 {
246 bignum_random (scratch_bignum, XBIGNUM_DATA (limit));
247 return Fcanonicalize_number (make_bignum_bg (scratch_bignum));
248 }
249 #endif
250 else 248 else
251 val = get_random (); 249 val = get_random ();
252 250
253 return make_int (val); 251 return make_int (val);
254 } 252 }
1434 { 1432 {
1435 /* This function can GC */ 1433 /* This function can GC */
1436 REGISTER EMACS_INT i; 1434 REGISTER EMACS_INT i;
1437 REGISTER Lisp_Object tail = list; 1435 REGISTER Lisp_Object tail = list;
1438 CHECK_NATNUM (n); 1436 CHECK_NATNUM (n);
1439 for (i = XINT (n); i; i--) 1437 for (i = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n); i; i--)
1440 { 1438 {
1441 if (CONSP (tail)) 1439 if (CONSP (tail))
1442 tail = XCDR (tail); 1440 tail = XCDR (tail);
1443 else if (NILP (tail)) 1441 else if (NILP (tail))
1444 return Qnil; 1442 return Qnil;
1554 if (NILP (n)) 1552 if (NILP (n))
1555 int_n = 1; 1553 int_n = 1;
1556 else 1554 else
1557 { 1555 {
1558 CHECK_NATNUM (n); 1556 CHECK_NATNUM (n);
1559 int_n = XINT (n); 1557 int_n = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n);
1560 } 1558 }
1561 1559
1562 for (retval = tortoise = hare = list, count = 0; 1560 for (retval = tortoise = hare = list, count = 0;
1563 CONSP (hare); 1561 CONSP (hare);
1564 hare = XCDR (hare), 1562 hare = XCDR (hare),
1574 } 1572 }
1575 1573
1576 return retval; 1574 return retval;
1577 } 1575 }
1578 1576
1579 static Lisp_Object bignum_butlast (Lisp_Object list, Lisp_Object number,
1580 Boolint copy);
1581
1582 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /* 1577 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /*
1583 Modify LIST to remove the last N (default 1) elements. 1578 Modify LIST to remove the last N (default 1) elements.
1584 1579
1585 If LIST has N or fewer elements, nil is returned and LIST is unmodified. 1580 If LIST has N or fewer elements, nil is returned and LIST is unmodified.
1586 Otherwise, LIST may be dotted, but not circular. 1581 Otherwise, LIST may be dotted, but not circular.
1591 1586
1592 CHECK_LIST (list); 1587 CHECK_LIST (list);
1593 1588
1594 if (!NILP (n)) 1589 if (!NILP (n))
1595 { 1590 {
1596 if (BIGNUMP (n))
1597 {
1598 return bignum_butlast (list, n, 0);
1599 }
1600
1601 CHECK_NATNUM (n); 1591 CHECK_NATNUM (n);
1602 int_n = XINT (n); 1592 int_n = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n);
1603 } 1593 }
1604 1594
1605 if (CONSP (list)) 1595 if (CONSP (list))
1606 { 1596 {
1607 Lisp_Object last_cons = list; 1597 Lisp_Object last_cons = list;
1644 1634
1645 CHECK_LIST (list); 1635 CHECK_LIST (list);
1646 1636
1647 if (!NILP (n)) 1637 if (!NILP (n))
1648 { 1638 {
1649 if (BIGNUMP (n))
1650 {
1651 return bignum_butlast (list, n, 1);
1652 }
1653
1654 CHECK_NATNUM (n); 1639 CHECK_NATNUM (n);
1655 int_n = XINT (n); 1640 int_n = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n);
1656 } 1641 }
1657 1642
1658 if (CONSP (list)) 1643 if (CONSP (list))
1659 { 1644 {
1660 Lisp_Object tail = list; 1645 Lisp_Object tail = list;
1682 } 1667 }
1683 } 1668 }
1684 } 1669 }
1685 1670
1686 return retval; 1671 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;
1723 } 1672 }
1724 1673
1725 DEFUN ("member", Fmember, 2, 2, 0, /* 1674 DEFUN ("member", Fmember, 2, 2, 0, /*
1726 Return non-nil if ELT is an element of LIST. Comparison done with `equal'. 1675 Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
1727 The value is actually the tail of LIST whose car is ELT. 1676 The value is actually the tail of LIST whose car is ELT.
4222 */ 4171 */
4223 (int nargs, Lisp_Object *args)) 4172 (int nargs, Lisp_Object *args))
4224 { 4173 {
4225 Lisp_Object sequence = args[0]; 4174 Lisp_Object sequence = args[0];
4226 Lisp_Object item = args[1]; 4175 Lisp_Object item = args[1];
4227 Elemcount starting = 0, ending = EMACS_INT_MAX, ii, len; 4176 Elemcount starting = 0, ending = EMACS_INT_MAX + 1, ii, len;
4228 4177
4229 PARSE_KEYWORDS (Ffill, nargs, args, 2, (start, end), (start = Qzero)); 4178 PARSE_KEYWORDS (Ffill, nargs, args, 2, (start, end), (start = Qzero));
4230 4179
4231 CHECK_NATNUM (start); 4180 CHECK_NATNUM (start);
4232 starting = XINT (start);
4233
4234 if (!NILP (end)) 4181 if (!NILP (end))
4235 { 4182 {
4236 CHECK_NATNUM (end); 4183 CHECK_NATNUM (end);
4237 ending = XINT (end); 4184 ending = BIGNUMP (end) ? EMACS_INT_MAX + 1 : XINT (end);
4238 } 4185 }
4239 4186
4240 retry: 4187 retry:
4241 if (STRINGP (sequence)) 4188 if (STRINGP (sequence))
4242 { 4189 {
4252 CHECK_LISP_WRITEABLE (sequence); 4199 CHECK_LISP_WRITEABLE (sequence);
4253 len = XVECTOR_LENGTH (sequence); 4200 len = XVECTOR_LENGTH (sequence);
4254 4201
4255 check_sequence_range (sequence, start, end, make_int (len)); 4202 check_sequence_range (sequence, start, end, make_int (len));
4256 ending = min (ending, len); 4203 ending = min (ending, len);
4204 starting = XINT (start);
4257 4205
4258 for (ii = starting; ii < ending; ++ii) 4206 for (ii = starting; ii < ending; ++ii)
4259 { 4207 {
4260 p[ii] = item; 4208 p[ii] = item;
4261 } 4209 }
4270 CHECK_LISP_WRITEABLE (sequence); 4218 CHECK_LISP_WRITEABLE (sequence);
4271 len = bit_vector_length (v); 4219 len = bit_vector_length (v);
4272 4220
4273 check_sequence_range (sequence, start, end, make_int (len)); 4221 check_sequence_range (sequence, start, end, make_int (len));
4274 ending = min (ending, len); 4222 ending = min (ending, len);
4223 starting = XINT (start);
4275 4224
4276 for (ii = starting; ii < ending; ++ii) 4225 for (ii = starting; ii < ending; ++ii)
4277 { 4226 {
4278 set_bit_vector_bit (v, ii, bit); 4227 set_bit_vector_bit (v, ii, bit);
4279 } 4228 }
4280 } 4229 }
4281 else if (LISTP (sequence)) 4230 else if (LISTP (sequence))
4282 { 4231 {
4283 Elemcount counting = 0; 4232 Elemcount counting = 0;
4233 starting = BIGNUMP (start) ? EMACS_INT_MAX + 1 : XINT (start);
4284 4234
4285 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) 4235 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4286 { 4236 {
4287 if (counting >= starting) 4237 if (counting >= starting)
4288 { 4238 {
5233 arguments: (FUNCTION SEQUENCE &key (START 0) (END (length SEQUENCE)) FROM-END INITIAL-VALUE (KEY #'identity)) 5183 arguments: (FUNCTION SEQUENCE &key (START 0) (END (length SEQUENCE)) FROM-END INITIAL-VALUE (KEY #'identity))
5234 */ 5184 */
5235 (int nargs, Lisp_Object *args)) 5185 (int nargs, Lisp_Object *args))
5236 { 5186 {
5237 Lisp_Object function = args[0], sequence = args[1], accum = Qunbound; 5187 Lisp_Object function = args[0], sequence = args[1], accum = Qunbound;
5238 Elemcount starting, ending = EMACS_INT_MAX, ii = 0; 5188 Elemcount starting, ending = EMACS_INT_MAX + 1, ii = 0;
5239 5189
5240 PARSE_KEYWORDS (Freduce, nargs, args, 5, 5190 PARSE_KEYWORDS (Freduce, nargs, args, 5,
5241 (start, end, from_end, initial_value, key), 5191 (start, end, from_end, initial_value, key),
5242 (start = Qzero, initial_value = Qunbound)); 5192 (start = Qzero, initial_value = Qunbound));
5243 5193
5244 CHECK_SEQUENCE (sequence); 5194 CHECK_SEQUENCE (sequence);
5245 CHECK_NATNUM (start); 5195 CHECK_NATNUM (start);
5246 5196 starting = BIGNUMP (start) ? EMACS_INT_MAX + 1 : XINT (start);
5247 CHECK_KEY_ARGUMENT (key); 5197 CHECK_KEY_ARGUMENT (key);
5248 5198
5249 #define KEY(key, item) (EQ (Qidentity, key) ? item : \ 5199 #define KEY(key, item) (EQ (Qidentity, key) ? item : \
5250 IGNORE_MULTIPLE_VALUES (call1 (key, item))) 5200 IGNORE_MULTIPLE_VALUES (call1 (key, item)))
5251 #define CALL2(function, accum, item) \ 5201 #define CALL2(function, accum, item) \
5252 IGNORE_MULTIPLE_VALUES (call2 (function, accum, item)) 5202 IGNORE_MULTIPLE_VALUES (call2 (function, accum, item))
5253 5203
5254 starting = XINT (start);
5255 if (!NILP (end)) 5204 if (!NILP (end))
5256 { 5205 {
5257 CHECK_NATNUM (end); 5206 CHECK_NATNUM (end);
5258 ending = XINT (end); 5207 ending = BIGNUMP (end) ? EMACS_INT_MAX + 1 : XINT (end);
5259 }
5260
5261 if (!(starting <= ending))
5262 {
5263 check_sequence_range (sequence, start, end, Flength (sequence));
5264 } 5208 }
5265 5209
5266 if (VECTORP (sequence)) 5210 if (VECTORP (sequence))
5267 { 5211 {
5268 Lisp_Vector *vv = XVECTOR (sequence); 5212 Lisp_Vector *vv = XVECTOR (sequence);
5430 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence); 5374 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence);
5431 const Ibyte *cursor; 5375 const Ibyte *cursor;
5432 5376
5433 check_sequence_range (sequence, start, end, make_int (len)); 5377 check_sequence_range (sequence, start, end, make_int (len));
5434 ending = min (ending, len); 5378 ending = min (ending, len);
5379 starting = XINT (start);
5380
5435 cursor = string_char_addr (sequence, ending - 1); 5381 cursor = string_char_addr (sequence, ending - 1);
5436 cursor_offset = cursor - XSTRING_DATA (sequence); 5382 cursor_offset = cursor - XSTRING_DATA (sequence);
5437 5383
5438 if (!UNBOUNDP (initial_value)) 5384 if (!UNBOUNDP (initial_value))
5439 { 5385 {
5677 Lisp_Object item) 5623 Lisp_Object item)
5678 { 5624 {
5679 Ibyte *destp = XSTRING_DATA (dest), *p = destp, 5625 Ibyte *destp = XSTRING_DATA (dest), *p = destp,
5680 *pend = p + XSTRING_LENGTH (dest), *pcursor, item_buf[MAX_ICHAR_LEN]; 5626 *pend = p + XSTRING_LENGTH (dest), *pcursor, item_buf[MAX_ICHAR_LEN];
5681 Bytecount prefix_bytecount, source_len = source_limit - source; 5627 Bytecount prefix_bytecount, source_len = source_limit - source;
5682 Charcount ii = 0, starting = XINT (start), ending, len; 5628 Charcount ii = 0, ending, len;
5629 Charcount starting = BIGNUMP (start) ? EMACS_INT_MAX + 1 : XINT (start);
5683 Elemcount delta; 5630 Elemcount delta;
5684 5631
5685 while (ii < starting && p < pend) 5632 while (ii < starting && p < pend)
5686 { 5633 {
5687 INC_IBYTEPTR (p); 5634 INC_IBYTEPTR (p);
5700 5647
5701 ending = len = ii; 5648 ending = len = ii;
5702 } 5649 }
5703 else 5650 else
5704 { 5651 {
5705 ending = XINT (end); 5652 ending = BIGNUMP (end) ? EMACS_INT_MAX + 1 : XINT (end);
5706 while (ii < ending && pcursor < pend) 5653 while (ii < ending && pcursor < pend)
5707 { 5654 {
5708 INC_IBYTEPTR (pcursor); 5655 INC_IBYTEPTR (pcursor);
5709 ii++; 5656 ii++;
5710 } 5657 }
5780 */ 5727 */
5781 (int nargs, Lisp_Object *args)) 5728 (int nargs, Lisp_Object *args))
5782 { 5729 {
5783 Lisp_Object sequence1 = args[0], sequence2 = args[1], 5730 Lisp_Object sequence1 = args[0], sequence2 = args[1],
5784 result = sequence1; 5731 result = sequence1;
5785 Elemcount starting1, ending1 = EMACS_INT_MAX, starting2; 5732 Elemcount starting1, ending1 = EMACS_INT_MAX + 1, starting2;
5786 Elemcount ending2 = EMACS_INT_MAX, counting = 0, startcounting; 5733 Elemcount ending2 = EMACS_INT_MAX + 1, counting = 0, startcounting;
5787 Boolint sequence1_listp, sequence2_listp, 5734 Boolint sequence1_listp, sequence2_listp,
5788 overwriting = EQ (sequence1, sequence2); 5735 overwriting = EQ (sequence1, sequence2);
5789 5736
5790 PARSE_KEYWORDS (Freplace, nargs, args, 4, (start1, end1, start2, end2), 5737 PARSE_KEYWORDS (Freplace, nargs, args, 4, (start1, end1, start2, end2),
5791 (start1 = start2 = Qzero)); 5738 (start1 = start2 = Qzero));
5794 CHECK_LISP_WRITEABLE (sequence1); 5741 CHECK_LISP_WRITEABLE (sequence1);
5795 5742
5796 CHECK_SEQUENCE (sequence2); 5743 CHECK_SEQUENCE (sequence2);
5797 5744
5798 CHECK_NATNUM (start1); 5745 CHECK_NATNUM (start1);
5799 starting1 = XINT (start1); 5746 starting1 = BIGNUMP (start1) ? EMACS_INT_MAX + 1 : XINT (start1);
5800 CHECK_NATNUM (start2); 5747 CHECK_NATNUM (start2);
5801 starting2 = XINT (start2); 5748 starting2 = BIGNUMP (start2) ? EMACS_INT_MAX + 1 : XINT (start2);
5802 5749
5803 if (!NILP (end1)) 5750 if (!NILP (end1))
5804 { 5751 {
5805 CHECK_NATNUM (end1); 5752 CHECK_NATNUM (end1);
5806 ending1 = XINT (end1); 5753 ending1 = BIGNUMP (end1) ? EMACS_INT_MAX + 1 : XINT (end1);
5807
5808 if (!(starting1 <= ending1))
5809 {
5810 args_out_of_range_3 (sequence1, start1, end1);
5811 }
5812 } 5754 }
5813 5755
5814 if (!NILP (end2)) 5756 if (!NILP (end2))
5815 { 5757 {
5816 CHECK_NATNUM (end2); 5758 CHECK_NATNUM (end2);
5817 ending2 = XINT (end2); 5759 ending2 = BIGNUMP (end2) ? EMACS_INT_MAX + 1 : XINT (end2);
5818
5819 if (!(starting2 <= ending2))
5820 {
5821 args_out_of_range_3 (sequence1, start2, end2);
5822 }
5823 } 5760 }
5824 5761
5825 sequence1_listp = LISTP (sequence1); 5762 sequence1_listp = LISTP (sequence1);
5826 sequence2_listp = LISTP (sequence2); 5763 sequence2_listp = LISTP (sequence2);
5827 5764