comparison src/fns.c @ 5303:4c4085177ca5

Fix some bugs in fns.c, discovered in passing while doing other work. 2010-11-14 Aidan Kehoe <kehoea@parhasard.net> * fns.c (Fnreverse): Check that non-list sequences are writable from Lisp before modifying them. (There's an argument that we should do this for list sequences too, but for the moment other code (e.g. #'setcar) doesn't.) (mapcarX): Initialise lisp_vals_staging, lisp_vals_type explicitly, for the sake of compile warnings. Check if lisp_vals_staging is non-NULL when deciding whether to replace a string's range. (Fsome): Cross-reference to #'find-if in the doc string for this function. (Freduce): GCPRO accum in this function, when a key argument is specicified it can be silently garbage-collected. When deciding whether to iterate across a string, check whether the cursor exceeds the byte len; while iterating, increment an integer counter. Don't ABORT() if check_sequence_range() returns when handed a suspicious sequence; it is legal to supply the length of SEQUENCE as the :end keyword value, and this will provoke our suspicions, legitimately enough. (Problems with this function revealed by Paul Dietz' ANSI test suite, thank you Paul Dietz.) (Freplace): Check list sequence lengths using the arguments, not the conses we're currently looking at, thank you Paul Dietz.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 14 Nov 2010 14:54:09 +0000
parents 6468cf6f0b9d
children cde1608596d0 002cb5224e4f
comparison
equal deleted inserted replaced
5302:6468cf6f0b9d 5303:4c4085177ca5
1106 if (0 != ss) 1106 if (0 != ss)
1107 { 1107 {
1108 sequence = Fnthcdr (make_int (ss), sequence); 1108 sequence = Fnthcdr (make_int (ss), sequence);
1109 } 1109 }
1110 1110
1111 ii = ss + 1;
1112
1111 if (ss < ee && !NILP (sequence)) 1113 if (ss < ee && !NILP (sequence))
1112 { 1114 {
1113 result = result_tail = Fcons (Fcar (sequence), Qnil); 1115 result = result_tail = Fcons (Fcar (sequence), Qnil);
1114 sequence = Fcdr (sequence); 1116 sequence = Fcdr (sequence);
1115 ii = ss + 1;
1116 1117
1117 { 1118 {
1118 EXTERNAL_LIST_LOOP_2 (elt, sequence) 1119 EXTERNAL_LIST_LOOP_2 (elt, sequence)
1119 { 1120 {
1120 if (!(ii < ee)) 1121 if (!(ii < ee))
2126 else if (VECTORP (sequence)) 2127 else if (VECTORP (sequence))
2127 { 2128 {
2128 Elemcount length = XVECTOR_LENGTH (sequence), ii = length; 2129 Elemcount length = XVECTOR_LENGTH (sequence), ii = length;
2129 Elemcount half = length / 2; 2130 Elemcount half = length / 2;
2130 Lisp_Object swap = Qnil; 2131 Lisp_Object swap = Qnil;
2132 CHECK_LISP_WRITEABLE (sequence);
2131 2133
2132 while (ii > half) 2134 while (ii > half)
2133 { 2135 {
2134 swap = XVECTOR_DATA (sequence) [length - ii]; 2136 swap = XVECTOR_DATA (sequence) [length - ii];
2135 XVECTOR_DATA (sequence) [length - ii] 2137 XVECTOR_DATA (sequence) [length - ii]
2142 { 2144 {
2143 Elemcount length = XSTRING_LENGTH (sequence); 2145 Elemcount length = XSTRING_LENGTH (sequence);
2144 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length; 2146 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length;
2145 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length; 2147 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length;
2146 2148
2149 CHECK_LISP_WRITEABLE (sequence);
2147 while (cursor < endp) 2150 while (cursor < endp)
2148 { 2151 {
2149 staging_end -= itext_ichar_len (cursor); 2152 staging_end -= itext_ichar_len (cursor);
2150 itext_copy_ichar (cursor, staging_end); 2153 itext_copy_ichar (cursor, staging_end);
2151 INC_IBYTEPTR (cursor); 2154 INC_IBYTEPTR (cursor);
2163 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence); 2166 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
2164 Elemcount length = bit_vector_length (bv), ii = length; 2167 Elemcount length = bit_vector_length (bv), ii = length;
2165 Elemcount half = length / 2; 2168 Elemcount half = length / 2;
2166 int swap = 0; 2169 int swap = 0;
2167 2170
2171 CHECK_LISP_WRITEABLE (sequence);
2168 while (ii > half) 2172 while (ii > half)
2169 { 2173 {
2170 swap = bit_vector_bit (bv, length - ii); 2174 swap = bit_vector_bit (bv, length - ii);
2171 set_bit_vector_bit (bv, length - ii, bit_vector_bit (bv, ii - 1)); 2175 set_bit_vector_bit (bv, length - ii, bit_vector_bit (bv, ii - 1));
2172 set_bit_vector_bit (bv, ii - 1, swap); 2176 set_bit_vector_bit (bv, ii - 1, swap);
4448 Lisp_Object function, int nsequences, Lisp_Object *sequences, 4452 Lisp_Object function, int nsequences, Lisp_Object *sequences,
4449 Lisp_Object caller) 4453 Lisp_Object caller)
4450 { 4454 {
4451 Lisp_Object called, *args; 4455 Lisp_Object called, *args;
4452 struct gcpro gcpro1, gcpro2; 4456 struct gcpro gcpro1, gcpro2;
4453 Ibyte *lisp_vals_staging, *cursor; 4457 Ibyte *lisp_vals_staging = NULL, *cursor = NULL;
4454 int i, j; 4458 int i, j;
4455 4459
4456 assert ((EQ (caller, Qsome) || EQ (caller, Qevery)) ? vals == NULL : 1); 4460 assert ((EQ (caller, Qsome) || EQ (caller, Qevery)) ? vals == NULL : 1);
4457 4461
4458 args = alloca_array (Lisp_Object, nsequences + 1); 4462 args = alloca_array (Lisp_Object, nsequences + 1);
4495 vals[i] = IGNORE_MULTIPLE_VALUES (Ffuncall (nsequences + 1, args)); 4499 vals[i] = IGNORE_MULTIPLE_VALUES (Ffuncall (nsequences + 1, args));
4496 } 4500 }
4497 } 4501 }
4498 else 4502 else
4499 { 4503 {
4500 enum lrecord_type lisp_vals_type; 4504 enum lrecord_type lisp_vals_type = lrecord_type_symbol;
4501 Binbyte *sequence_types = alloca_array (Binbyte, nsequences); 4505 Binbyte *sequence_types = alloca_array (Binbyte, nsequences);
4502 for (j = 0; j < nsequences; ++j) 4506 for (j = 0; j < nsequences; ++j)
4503 { 4507 {
4504 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type; 4508 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type;
4505 } 4509 }
4514 if (lrecord_type_string == lisp_vals_type) 4518 if (lrecord_type_string == lisp_vals_type)
4515 { 4519 {
4516 lisp_vals_staging = cursor 4520 lisp_vals_staging = cursor
4517 = alloca_ibytes (call_count * MAX_ICHAR_LEN); 4521 = alloca_ibytes (call_count * MAX_ICHAR_LEN);
4518 } 4522 }
4523 else if (ARRAYP (lisp_vals))
4524 {
4525 CHECK_LISP_WRITEABLE (lisp_vals);
4526 }
4519 } 4527 }
4520 4528
4521 for (i = 0; i < call_count; ++i) 4529 for (i = 0; i < call_count; ++i)
4522 { 4530 {
4523 for (j = 0; j < nsequences; ++j) 4531 for (j = 0; j < nsequences; ++j)
4639 } 4647 }
4640 } 4648 }
4641 } 4649 }
4642 } 4650 }
4643 4651
4644 if (!EQ (caller, Qsome) && !EQ (caller, Qevery) && 4652 if (lisp_vals_staging != NULL)
4645 lrecord_type_string == lisp_vals_type) 4653 {
4646 { 4654 CHECK_LISP_WRITEABLE (lisp_vals);
4647 replace_string_range (lisp_vals, Qzero, make_int (call_count), 4655 replace_string_range (lisp_vals, Qzero, make_int (call_count),
4648 lisp_vals_staging, cursor); 4656 lisp_vals_staging, cursor);
4649 } 4657 }
4650 } 4658 }
4651 4659
4657 one of them is not a sequence. */ 4665 one of them is not a sequence. */
4658 static Elemcount 4666 static Elemcount
4659 shortest_length_among_sequences (int nsequences, Lisp_Object *sequences) 4667 shortest_length_among_sequences (int nsequences, Lisp_Object *sequences)
4660 { 4668 {
4661 Elemcount len = EMACS_INT_MAX; 4669 Elemcount len = EMACS_INT_MAX;
4662 Lisp_Object length; 4670 Lisp_Object length = Qnil;
4663 int i; 4671 int i;
4664 4672
4665 for (i = 0; i < nsequences; ++i) 4673 for (i = 0; i < nsequences; ++i)
4666 { 4674 {
4667 if (CONSP (sequences[i])) 4675 if (CONSP (sequences[i]))
4950 4958
4951 If so, return the value (possibly multiple) given by PREDICATE. 4959 If so, return the value (possibly multiple) given by PREDICATE.
4952 4960
4953 With optional SEQUENCES, call PREDICATE each time with as many arguments as 4961 With optional SEQUENCES, call PREDICATE each time with as many arguments as
4954 there are SEQUENCES (plus one for the element from SEQUENCE). 4962 there are SEQUENCES (plus one for the element from SEQUENCE).
4963
4964 See also `find-if', which returns the corresponding element of SEQUENCE,
4965 rather than the value given by PREDICATE, and accepts bounding index
4966 keywords.
4955 4967
4956 arguments: (PREDICATE SEQUENCE &rest SEQUENCES) 4968 arguments: (PREDICATE SEQUENCE &rest SEQUENCES)
4957 */ 4969 */
4958 (int nargs, Lisp_Object *args)) 4970 (int nargs, Lisp_Object *args))
4959 { 4971 {
5203 } 5215 }
5204 5216
5205 if (VECTORP (sequence)) 5217 if (VECTORP (sequence))
5206 { 5218 {
5207 Lisp_Vector *vv = XVECTOR (sequence); 5219 Lisp_Vector *vv = XVECTOR (sequence);
5220 struct gcpro gcpro1;
5208 5221
5209 check_sequence_range (sequence, start, end, make_int (vv->size)); 5222 check_sequence_range (sequence, start, end, make_int (vv->size));
5210 5223
5211 ending = min (ending, vv->size); 5224 ending = min (ending, vv->size);
5225
5226 GCPRO1 (accum);
5212 5227
5213 if (!UNBOUNDP (initial_value)) 5228 if (!UNBOUNDP (initial_value))
5214 { 5229 {
5215 accum = initial_value; 5230 accum = initial_value;
5216 } 5231 }
5240 for (ii = ending - 1; ii >= starting; --ii) 5255 for (ii = ending - 1; ii >= starting; --ii)
5241 { 5256 {
5242 accum = CALL2 (function, KEY (key, vv->contents[ii]), accum); 5257 accum = CALL2 (function, KEY (key, vv->contents[ii]), accum);
5243 } 5258 }
5244 } 5259 }
5260
5261 UNGCPRO;
5245 } 5262 }
5246 else if (BIT_VECTORP (sequence)) 5263 else if (BIT_VECTORP (sequence))
5247 { 5264 {
5248 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence); 5265 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
5266 struct gcpro gcpro1;
5249 5267
5250 check_sequence_range (sequence, start, end, make_int (bv->size)); 5268 check_sequence_range (sequence, start, end, make_int (bv->size));
5251
5252 ending = min (ending, bv->size); 5269 ending = min (ending, bv->size);
5270
5271 GCPRO1 (accum);
5253 5272
5254 if (!UNBOUNDP (initial_value)) 5273 if (!UNBOUNDP (initial_value))
5255 { 5274 {
5256 accum = initial_value; 5275 accum = initial_value;
5257 } 5276 }
5285 make_int (bit_vector_bit (bv, 5304 make_int (bit_vector_bit (bv,
5286 ii))), 5305 ii))),
5287 accum); 5306 accum);
5288 } 5307 }
5289 } 5308 }
5309
5310 UNGCPRO;
5311
5290 } 5312 }
5291 else if (STRINGP (sequence)) 5313 else if (STRINGP (sequence))
5292 { 5314 {
5315 struct gcpro gcpro1;
5316
5317 GCPRO1 (accum);
5318
5293 if (NILP (from_end)) 5319 if (NILP (from_end))
5294 { 5320 {
5295 Bytecount byte_len = XSTRING_LENGTH (sequence); 5321 Bytecount byte_len = XSTRING_LENGTH (sequence);
5296 Bytecount cursor_offset = 0; 5322 Bytecount cursor_offset = 0;
5297 const Ibyte *startp = XSTRING_DATA (sequence); 5323 const Ibyte *startp = XSTRING_DATA (sequence);
5305 5331
5306 if (!UNBOUNDP (initial_value)) 5332 if (!UNBOUNDP (initial_value))
5307 { 5333 {
5308 accum = initial_value; 5334 accum = initial_value;
5309 } 5335 }
5310 else if (ending - starting) 5336 else if (ending - starting && cursor_offset < byte_len)
5311 { 5337 {
5312 accum = KEY (key, make_char (itext_ichar (cursor))); 5338 accum = KEY (key, make_char (itext_ichar (cursor)));
5313 starting++; 5339 starting++;
5314 startp = XSTRING_DATA (sequence); 5340 startp = XSTRING_DATA (sequence);
5315 cursor = startp + cursor_offset; 5341 cursor = startp + cursor_offset;
5320 mapping_interaction_error (Qreduce, sequence); 5346 mapping_interaction_error (Qreduce, sequence);
5321 } 5347 }
5322 5348
5323 INC_IBYTEPTR (cursor); 5349 INC_IBYTEPTR (cursor);
5324 cursor_offset = cursor - startp; 5350 cursor_offset = cursor - startp;
5351 ii++;
5325 } 5352 }
5326 5353
5327 while (cursor_offset < byte_len && ii < ending) 5354 while (cursor_offset < byte_len && ii < ending)
5328 { 5355 {
5329 accum = CALL2 (function, accum, 5356 accum = CALL2 (function, accum,
5344 } 5371 }
5345 5372
5346 if (ii < starting || (ii < ending && !NILP (end))) 5373 if (ii < starting || (ii < ending && !NILP (end)))
5347 { 5374 {
5348 check_sequence_range (sequence, start, end, Flength (sequence)); 5375 check_sequence_range (sequence, start, end, Flength (sequence));
5349 ABORT ();
5350 } 5376 }
5351 } 5377 }
5352 else 5378 else
5353 { 5379 {
5354 Elemcount len = string_char_length (sequence); 5380 Elemcount len = string_char_length (sequence);
5355 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence); 5381 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence);
5356 const Ibyte *cursor; 5382 const Ibyte *cursor;
5357 5383
5358 check_sequence_range (sequence, start, end, make_int (len)); 5384 check_sequence_range (sequence, start, end, make_int (len));
5359
5360 ending = min (ending, len); 5385 ending = min (ending, len);
5361 cursor = string_char_addr (sequence, ending - 1); 5386 cursor = string_char_addr (sequence, ending - 1);
5362 cursor_offset = cursor - XSTRING_DATA (sequence); 5387 cursor_offset = cursor - XSTRING_DATA (sequence);
5363 5388
5364 if (!UNBOUNDP (initial_value)) 5389 if (!UNBOUNDP (initial_value))
5401 DEC_IBYTEPTR (cursor); 5426 DEC_IBYTEPTR (cursor);
5402 cursor_offset = cursor - XSTRING_DATA (sequence); 5427 cursor_offset = cursor - XSTRING_DATA (sequence);
5403 } 5428 }
5404 } 5429 }
5405 } 5430 }
5431
5432 UNGCPRO;
5406 } 5433 }
5407 else if (LISTP (sequence)) 5434 else if (LISTP (sequence))
5408 { 5435 {
5409 if (NILP (from_end)) 5436 if (NILP (from_end))
5410 { 5437 {
5411 struct gcpro gcpro1; 5438 struct gcpro gcpro1, gcpro2;
5412 Lisp_Object tailed = Qnil; 5439 Lisp_Object tailed = Qnil;
5413 5440
5414 GCPRO1 (tailed); 5441 GCPRO2 (tailed, accum);
5415 5442
5416 if (!UNBOUNDP (initial_value)) 5443 if (!UNBOUNDP (initial_value))
5417 { 5444 {
5418 accum = initial_value; 5445 accum = initial_value;
5419 } 5446 }
5462 UNGCPRO; 5489 UNGCPRO;
5463 5490
5464 if (ii < starting || (ii < ending && !NILP (end))) 5491 if (ii < starting || (ii < ending && !NILP (end)))
5465 { 5492 {
5466 check_sequence_range (sequence, start, end, Flength (sequence)); 5493 check_sequence_range (sequence, start, end, Flength (sequence));
5467 ABORT ();
5468 } 5494 }
5469 } 5495 }
5470 else 5496 else
5471 { 5497 {
5472 Boolint need_accum = 0; 5498 Boolint need_accum = 0;
5928 } 5954 }
5929 } 5955 }
5930 5956
5931 if (NILP (sequence1)) 5957 if (NILP (sequence1))
5932 { 5958 {
5933 check_sequence_range (sequence1, start1, end1, 5959 check_sequence_range (args[0], start1, end1,
5934 make_int (XINT (start1) + shortest_len)); 5960 make_int (XINT (start1) + shortest_len));
5935 } 5961 }
5936 else if (NILP (sequence2)) 5962 else if (NILP (sequence2))
5937 { 5963 {
5938 check_sequence_range (sequence2, start2, end2, 5964 check_sequence_range (args[1], start2, end2,
5939 make_int (XINT (start2) + shortest_len)); 5965 make_int (XINT (start2) + shortest_len));
5940 } 5966 }
5941 } 5967 }
5942 else if (sequence1_listp) 5968 else if (sequence1_listp)
5943 { 5969 {
5996 starting2++; 6022 starting2++;
5997 } 6023 }
5998 6024
5999 if (NILP (sequence1)) 6025 if (NILP (sequence1))
6000 { 6026 {
6001 check_sequence_range (sequence1, start1, end1, 6027 check_sequence_range (args[0], start1, end1,
6002 make_int (XINT (start1) + starting1)); 6028 make_int (XINT (start1) + starting1));
6003 } 6029 }
6004 } 6030 }
6005 } 6031 }
6006 else if (sequence2_listp) 6032 else if (sequence2_listp)
6053 starting2++; 6079 starting2++;
6054 } 6080 }
6055 6081
6056 if (NILP (sequence2)) 6082 if (NILP (sequence2))
6057 { 6083 {
6058 check_sequence_range (sequence2, start2, end2, 6084 check_sequence_range (args[1], start2, end2,
6059 make_int (XINT (start2) + starting2)); 6085 make_int (XINT (start2) + starting2));
6060 } 6086 }
6061 } 6087 }
6062 } 6088 }
6063 else 6089 else