Mercurial > hg > xemacs-beta
comparison src/fns.c @ 5448:89331fa1c819
Merged with trunk.
author | Mats Lidell <matsl@xemacs.org> |
---|---|
date | Thu, 06 Jan 2011 00:35:22 +0100 |
parents | 771bf922ab2b 1dbc93b7ba19 |
children | a9094f28f9a9 |
comparison
equal
deleted
inserted
replaced
5447:4b08f375e2fb | 5448:89331fa1c819 |
---|---|
50 #include "opaque.h" | 50 #include "opaque.h" |
51 | 51 |
52 /* NOTE: This symbol is also used in lread.c */ | 52 /* NOTE: This symbol is also used in lread.c */ |
53 #define FEATUREP_SYNTAX | 53 #define FEATUREP_SYNTAX |
54 | 54 |
55 Lisp_Object Qstring_lessp, Qsort, Qmerge, Qfill, Qreplace; | 55 Lisp_Object Qstring_lessp, Qmerge, Qfill, Qreplace, QassocX, QrassocX; |
56 Lisp_Object Qidentity; | 56 Lisp_Object Qposition, Qfind, QdeleteX, QremoveX, Qidentity, Qadjoin; |
57 Lisp_Object Qvector, Qarray, Qbit_vector, QsortX, Q_from_end, Q_initial_value; | 57 Lisp_Object Qvector, Qarray, Qbit_vector, QsortX, Q_from_end, Q_initial_value; |
58 Lisp_Object Qmapconcat, QmapcarX, Qmapvector, Qmapcan, Qmapc, Qmap, Qmap_into; | 58 Lisp_Object Qmapconcat, QmapcarX, Qmapvector, Qmapcan, Qmapc, Qmap, Qmap_into; |
59 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce; | 59 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce, Qsubstitute; |
60 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2; | 60 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2, Q_if_, Q_if_not, Q_stable; |
61 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch; | |
62 | |
63 Lisp_Object Qintersection, Qset_difference, Qnset_difference; | |
64 Lisp_Object Qnunion, Qnintersection, Qsubsetp; | |
61 | 65 |
62 Lisp_Object Qbase64_conversion_error; | 66 Lisp_Object Qbase64_conversion_error; |
63 | 67 |
64 Lisp_Object Vpath_separator; | 68 Lisp_Object Vpath_separator; |
69 | |
70 extern Fixnum max_lisp_eval_depth; | |
71 extern int lisp_eval_depth; | |
65 | 72 |
66 static int internal_old_equal (Lisp_Object, Lisp_Object, int); | 73 static int internal_old_equal (Lisp_Object, Lisp_Object, int); |
67 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth); | 74 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth); |
68 | 75 |
69 static DOESNT_RETURN | 76 static DOESNT_RETURN |
195 bit_vector_equal, | 202 bit_vector_equal, |
196 bit_vector_hash, | 203 bit_vector_hash, |
197 bit_vector_description, | 204 bit_vector_description, |
198 size_bit_vector, | 205 size_bit_vector, |
199 Lisp_Bit_Vector); | 206 Lisp_Bit_Vector); |
207 | |
208 /* Various test functions for #'member*, #'assoc* and the other functions | |
209 that take both TEST and KEY arguments. */ | |
210 | |
211 typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key, | |
212 Lisp_Object item, Lisp_Object elt); | |
213 | |
214 static Boolint | |
215 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
216 Lisp_Object item, Lisp_Object elt) | |
217 { | |
218 return EQ (item, elt); | |
219 } | |
220 | |
221 static Boolint | |
222 check_eq_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item, | |
223 Lisp_Object elt) | |
224 { | |
225 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
226 return EQ (item, elt); | |
227 } | |
228 | |
229 /* The next two are not used by #'member* and #'assoc*, since we can decide | |
230 on #'eq vs. #'equal when we have the type of ITEM. */ | |
231 static Boolint | |
232 check_eql_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
233 Lisp_Object elt1, Lisp_Object elt2) | |
234 { | |
235 return EQ (elt1, elt2) | |
236 || (NON_FIXNUM_NUMBER_P (elt1) && internal_equal (elt1, elt2, 0)); | |
237 } | |
238 | |
239 static Boolint | |
240 check_eql_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item, | |
241 Lisp_Object elt) | |
242 { | |
243 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
244 return EQ (item, elt) | |
245 || (NON_FIXNUM_NUMBER_P (item) && internal_equal (item, elt, 0)); | |
246 } | |
247 | |
248 static Boolint | |
249 check_equal_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
250 Lisp_Object item, Lisp_Object elt) | |
251 { | |
252 return internal_equal (item, elt, 0); | |
253 } | |
254 | |
255 static Boolint | |
256 check_equal_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item, | |
257 Lisp_Object elt) | |
258 { | |
259 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
260 return internal_equal (item, elt, 0); | |
261 } | |
262 | |
263 static Boolint | |
264 check_equalp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
265 Lisp_Object item, Lisp_Object elt) | |
266 { | |
267 return internal_equalp (item, elt, 0); | |
268 } | |
269 | |
270 static Boolint | |
271 check_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
272 Lisp_Object item, Lisp_Object elt) | |
273 { | |
274 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
275 return internal_equalp (item, elt, 0); | |
276 } | |
277 | |
278 static Boolint | |
279 check_string_match_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
280 Lisp_Object item, Lisp_Object elt) | |
281 { | |
282 return !NILP (Fstring_match (item, elt, Qnil, Qnil)); | |
283 } | |
284 | |
285 static Boolint | |
286 check_string_match_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
287 Lisp_Object item, Lisp_Object elt) | |
288 { | |
289 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
290 return !NILP (Fstring_match (item, elt, Qnil, Qnil)); | |
291 } | |
292 | |
293 static Boolint | |
294 check_other_nokey (Lisp_Object test, Lisp_Object UNUSED (key), | |
295 Lisp_Object item, Lisp_Object elt) | |
296 { | |
297 Lisp_Object args[] = { test, item, elt }; | |
298 struct gcpro gcpro1; | |
299 | |
300 GCPRO1 (args[0]); | |
301 gcpro1.nvars = countof (args); | |
302 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
303 UNGCPRO; | |
304 | |
305 return !NILP (item); | |
306 } | |
307 | |
308 static Boolint | |
309 check_other_key (Lisp_Object test, Lisp_Object key, | |
310 Lisp_Object item, Lisp_Object elt) | |
311 { | |
312 Lisp_Object args[] = { item, key, elt }; | |
313 struct gcpro gcpro1; | |
314 | |
315 GCPRO1 (args[0]); | |
316 gcpro1.nvars = countof (args); | |
317 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args) - 1, args + 1)); | |
318 args[1] = item; | |
319 args[0] = test; | |
320 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
321 UNGCPRO; | |
322 | |
323 return !NILP (item); | |
324 } | |
325 | |
326 static Boolint | |
327 check_if_nokey (Lisp_Object test, Lisp_Object UNUSED (key), | |
328 Lisp_Object UNUSED (item), Lisp_Object elt) | |
329 { | |
330 elt = IGNORE_MULTIPLE_VALUES (call1 (test, elt)); | |
331 return !NILP (elt); | |
332 } | |
333 | |
334 static Boolint | |
335 check_if_key (Lisp_Object test, Lisp_Object key, | |
336 Lisp_Object UNUSED (item), Lisp_Object elt) | |
337 { | |
338 Lisp_Object args[] = { key, elt }; | |
339 struct gcpro gcpro1; | |
340 | |
341 GCPRO1 (args[0]); | |
342 gcpro1.nvars = countof (args); | |
343 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
344 args[0] = test; | |
345 elt = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
346 UNGCPRO; | |
347 | |
348 return !NILP (elt); | |
349 } | |
350 | |
351 static Boolint | |
352 check_match_eq_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
353 Lisp_Object elt1, Lisp_Object elt2) | |
354 { | |
355 Lisp_Object args[] = { key, elt1, elt2 }; | |
356 struct gcpro gcpro1; | |
357 | |
358 GCPRO1 (args[0]); | |
359 gcpro1.nvars = countof (args); | |
360 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
361 args[1] = key; | |
362 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
363 UNGCPRO; | |
364 | |
365 return EQ (args[0], args[1]); | |
366 } | |
367 | |
368 static Boolint | |
369 check_match_eql_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
370 Lisp_Object elt1, Lisp_Object elt2) | |
371 { | |
372 Lisp_Object args[] = { key, elt1, elt2 }; | |
373 struct gcpro gcpro1; | |
374 | |
375 GCPRO1 (args[0]); | |
376 gcpro1.nvars = countof (args); | |
377 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
378 args[1] = key; | |
379 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
380 UNGCPRO; | |
381 | |
382 return EQ (args[0], args[1]) || | |
383 (NON_FIXNUM_NUMBER_P (args[0]) && internal_equal (args[0], args[1], 0)); | |
384 } | |
385 | |
386 static Boolint | |
387 check_match_equal_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
388 Lisp_Object elt1, Lisp_Object elt2) | |
389 { | |
390 Lisp_Object args[] = { key, elt1, elt2 }; | |
391 struct gcpro gcpro1; | |
392 | |
393 GCPRO1 (args[0]); | |
394 gcpro1.nvars = countof (args); | |
395 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
396 args[1] = key; | |
397 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
398 UNGCPRO; | |
399 | |
400 return internal_equal (args[0], args[1], 0); | |
401 } | |
402 | |
403 static Boolint | |
404 check_match_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
405 Lisp_Object elt1, Lisp_Object elt2) | |
406 { | |
407 Lisp_Object args[] = { key, elt1, elt2 }; | |
408 struct gcpro gcpro1; | |
409 | |
410 GCPRO1 (args[0]); | |
411 gcpro1.nvars = countof (args); | |
412 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
413 args[1] = key; | |
414 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
415 UNGCPRO; | |
416 | |
417 return internal_equalp (args[0], args[1], 0); | |
418 } | |
419 | |
420 static Boolint | |
421 check_match_other_key (Lisp_Object test, Lisp_Object key, | |
422 Lisp_Object elt1, Lisp_Object elt2) | |
423 { | |
424 Lisp_Object args[] = { key, elt1, elt2 }; | |
425 struct gcpro gcpro1; | |
426 | |
427 GCPRO1 (args[0]); | |
428 gcpro1.nvars = countof (args); | |
429 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
430 args[1] = key; | |
431 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
432 args[1] = args[0]; | |
433 args[0] = test; | |
434 | |
435 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
436 UNGCPRO; | |
437 | |
438 return !NILP (elt1); | |
439 } | |
440 | |
441 static check_test_func_t | |
442 get_check_match_function_1 (Lisp_Object item, | |
443 Lisp_Object *test_inout, Lisp_Object test_not, | |
444 Lisp_Object if_, Lisp_Object if_not, | |
445 Lisp_Object key, Boolint *test_not_unboundp_out, | |
446 check_test_func_t *test_func_out) | |
447 { | |
448 Lisp_Object test = *test_inout; | |
449 check_test_func_t result = NULL, test_func = NULL; | |
450 Boolint force_if = 0; | |
451 | |
452 if (!NILP (if_)) | |
453 { | |
454 if (!(NILP (test) && NILP (test_not) && NILP (if_not))) | |
455 { | |
456 invalid_argument ("only one keyword among :test :test-not " | |
457 ":if :if-not allowed", if_); | |
458 } | |
459 | |
460 test = *test_inout = if_; | |
461 force_if = 1; | |
462 } | |
463 else if (!NILP (if_not)) | |
464 { | |
465 if (!(NILP (test) && NILP (test_not))) | |
466 { | |
467 invalid_argument ("only one keyword among :test :test-not " | |
468 ":if :if-not allowed", if_not); | |
469 } | |
470 | |
471 test_not = if_not; | |
472 force_if = 1; | |
473 } | |
474 | |
475 if (NILP (test)) | |
476 { | |
477 if (!NILP (test_not)) | |
478 { | |
479 test = *test_inout = test_not; | |
480 if (NULL != test_not_unboundp_out) | |
481 { | |
482 *test_not_unboundp_out = 0; | |
483 } | |
484 } | |
485 else | |
486 { | |
487 test = Qeql; | |
488 if (NULL != test_not_unboundp_out) | |
489 { | |
490 *test_not_unboundp_out = 1; | |
491 } | |
492 } | |
493 } | |
494 else if (!NILP (test_not)) | |
495 { | |
496 invalid_argument_2 ("conflicting :test and :test-not keyword arguments", | |
497 test, test_not); | |
498 } | |
499 | |
500 test = indirect_function (test, 1); | |
501 | |
502 if (NILP (key) || | |
503 EQ (indirect_function (key, 1), XSYMBOL_FUNCTION (Qidentity))) | |
504 { | |
505 key = Qidentity; | |
506 } | |
507 | |
508 if (force_if) | |
509 { | |
510 result = EQ (key, Qidentity) ? check_if_nokey : check_if_key; | |
511 | |
512 if (NULL != test_func_out) | |
513 { | |
514 *test_func_out = result; | |
515 } | |
516 | |
517 return result; | |
518 } | |
519 | |
520 if (!UNBOUNDP (item) && EQ (test, XSYMBOL_FUNCTION (Qeql))) | |
521 { | |
522 test = XSYMBOL_FUNCTION (NON_FIXNUM_NUMBER_P (item) ? Qequal : Qeq); | |
523 } | |
524 | |
525 #define FROB(known_test, eq_condition) \ | |
526 if (EQ (test, XSYMBOL_FUNCTION (Q##known_test))) do \ | |
527 { \ | |
528 if (eq_condition) \ | |
529 { \ | |
530 test = XSYMBOL_FUNCTION (Qeq); \ | |
531 goto force_eq_check; \ | |
532 } \ | |
533 \ | |
534 if (!EQ (Qidentity, key)) \ | |
535 { \ | |
536 test_func = check_##known_test##_key; \ | |
537 result = check_match_##known_test##_key; \ | |
538 } \ | |
539 else \ | |
540 { \ | |
541 result = test_func = check_##known_test##_nokey; \ | |
542 } \ | |
543 } while (0) | |
544 | |
545 FROB (eql, 0); | |
546 else if (SUBRP (test)) | |
547 { | |
548 force_eq_check: | |
549 FROB (eq, 0); | |
550 else FROB (equal, (SYMBOLP (item) || INTP (item) || CHARP (item))); | |
551 else FROB (equalp, (SYMBOLP (item))); | |
552 else if (EQ (test, XSYMBOL_FUNCTION (Qstring_match))) | |
553 { | |
554 if (EQ (Qidentity, key)) | |
555 { | |
556 test_func = result = check_string_match_nokey; | |
557 } | |
558 else | |
559 { | |
560 test_func = check_string_match_key; | |
561 result = check_other_key; | |
562 } | |
563 } | |
564 } | |
565 | |
566 if (NULL == result) | |
567 { | |
568 if (EQ (Qidentity, key)) | |
569 { | |
570 test_func = result = check_other_nokey; | |
571 } | |
572 else | |
573 { | |
574 test_func = check_other_key; | |
575 result = check_match_other_key; | |
576 } | |
577 } | |
578 | |
579 if (NULL != test_func_out) | |
580 { | |
581 *test_func_out = test_func; | |
582 } | |
583 | |
584 return result; | |
585 } | |
586 #undef FROB | |
587 | |
588 /* Given TEST, TEST_NOT, IF, IF_NOT, KEY, and ITEM, return a C function | |
589 pointer appropriate for use in deciding whether a given element of a | |
590 sequence satisfies TEST. | |
591 | |
592 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero | |
593 if it was bound, and set *test_inout to the value it was bound to. If | |
594 TEST was not bound, leave *test_inout alone; the value is not used by | |
595 check_eq_*key() or check_equal_*key(), which are the defaults, depending | |
596 on the type of ITEM. | |
597 | |
598 The returned function takes arguments (TEST, KEY, ITEM, ELT), where ITEM | |
599 is the item being searched for and ELT is the element of the sequence | |
600 being examined. | |
601 | |
602 Error if both TEST and TEST_NOT were specified, which Common Lisp says is | |
603 undefined behaviour. */ | |
604 | |
605 static check_test_func_t | |
606 get_check_test_function (Lisp_Object item, | |
607 Lisp_Object *test_inout, Lisp_Object test_not, | |
608 Lisp_Object if_, Lisp_Object if_not, | |
609 Lisp_Object key, Boolint *test_not_unboundp_out) | |
610 { | |
611 check_test_func_t result = NULL; | |
612 get_check_match_function_1 (item, test_inout, test_not, if_, if_not, | |
613 key, test_not_unboundp_out, &result); | |
614 return result; | |
615 } | |
616 | |
617 /* Given TEST, TEST_NOT, IF, IF_NOT and KEY, return a C function pointer | |
618 appropriate for use in deciding whether two given elements of a sequence | |
619 satisfy TEST. | |
620 | |
621 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero | |
622 if it was bound, and set *test_inout to the value it was bound to. If | |
623 TEST was not bound, leave *test_inout alone; the value is not used by | |
624 check_eql_*key(). | |
625 | |
626 The returned function takes arguments (TEST, KEY, ELT1, ELT2), where ELT1 | |
627 and ELT2 are elements of the sequence being examined. | |
628 | |
629 The value that would be given by get_check_test_function() is returned in | |
630 *TEST_FUNC_OUT, which allows calling functions to do their own key checks | |
631 if they're processing one element at a time. | |
632 | |
633 Error if both TEST and TEST_NOT were specified, which Common Lisp says is | |
634 undefined behaviour. */ | |
635 | |
636 static check_test_func_t | |
637 get_check_match_function (Lisp_Object *test_inout, Lisp_Object test_not, | |
638 Lisp_Object if_, Lisp_Object if_not, | |
639 Lisp_Object key, Boolint *test_not_unboundp_out, | |
640 check_test_func_t *test_func_out) | |
641 { | |
642 return get_check_match_function_1 (Qunbound, test_inout, test_not, | |
643 if_, if_not, key, | |
644 test_not_unboundp_out, test_func_out); | |
645 } | |
200 | 646 |
201 | 647 |
202 DEFUN ("identity", Fidentity, 1, 1, 0, /* | 648 DEFUN ("identity", Fidentity, 1, 1, 0, /* |
203 Return the argument unchanged. | 649 Return the argument unchanged. |
204 */ | 650 */ |
362 signal_malformed_list_error (list); | 808 signal_malformed_list_error (list); |
363 } | 809 } |
364 | 810 |
365 return EQ (hare, tortoise) && len != 0 ? Qnil : make_int (len); | 811 return EQ (hare, tortoise) && len != 0 ? Qnil : make_int (len); |
366 } | 812 } |
367 | 813 |
814 static Lisp_Object string_count_from_end (Lisp_Object, Lisp_Object , | |
815 check_test_func_t, Boolint, | |
816 Lisp_Object, Lisp_Object, | |
817 Lisp_Object, Lisp_Object); | |
818 | |
819 static Lisp_Object list_count_from_end (Lisp_Object, Lisp_Object, | |
820 check_test_func_t, Boolint, | |
821 Lisp_Object, Lisp_Object, | |
822 Lisp_Object, Lisp_Object); | |
823 | |
824 /* Count the number of occurrences of ITEM in SEQUENCE; if SEQUENCE is a | |
825 list, store the cons cell of which the car is the last ITEM in SEQUENCE, | |
826 at the address given by tail_out. */ | |
827 | |
828 static Lisp_Object | |
829 count_with_tail (Lisp_Object *tail_out, int nargs, Lisp_Object *args, | |
830 Lisp_Object caller) | |
831 { | |
832 Lisp_Object item = args[0], sequence = args[1]; | |
833 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | |
834 Elemcount len, ii = 0, counting = EMACS_INT_MAX; | |
835 Boolint test_not_unboundp = 1; | |
836 check_test_func_t check_test = NULL; | |
837 | |
838 PARSE_KEYWORDS_8 (caller, nargs, args, 9, | |
839 (test, key, start, end, from_end, test_not, count, | |
840 if_, if_not), (start = Qzero), 2, 0); | |
841 | |
842 CHECK_SEQUENCE (sequence); | |
843 CHECK_NATNUM (start); | |
844 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
845 | |
846 if (!NILP (end)) | |
847 { | |
848 CHECK_NATNUM (end); | |
849 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
850 } | |
851 | |
852 if (!NILP (count)) | |
853 { | |
854 CHECK_INTEGER (count); | |
855 counting = BIGNUMP (count) ? EMACS_INT_MAX + 1 : XINT (count); | |
856 | |
857 /* Our callers should have filtered out non-positive COUNT. */ | |
858 assert (counting >= 0); | |
859 /* And we're not prepared to handle COUNT from any other caller at the | |
860 moment. */ | |
861 assert (EQ (caller, QremoveX)); | |
862 } | |
863 | |
864 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
865 key, &test_not_unboundp); | |
866 | |
867 *tail_out = Qnil; | |
868 | |
869 if (CONSP (sequence)) | |
870 { | |
871 Lisp_Object elt, tail = Qnil; | |
872 struct gcpro gcpro1; | |
873 | |
874 if (EQ (caller, Qcount) && !NILP (from_end) | |
875 && (!EQ (key, Qnil) || | |
876 check_test == check_other_nokey || check_test == check_if_nokey)) | |
877 { | |
878 /* #'count, #'count-if, and #'count-if-not are documented to have | |
879 a given traversal order if :from-end t is passed in, even | |
880 though forward traversal of the sequence has the same result | |
881 and is algorithmically less expensive for lists and strings. | |
882 This order isn't necessary for other callers, though. */ | |
883 return list_count_from_end (item, sequence, check_test, | |
884 test_not_unboundp, test, key, | |
885 start, end); | |
886 } | |
887 | |
888 GCPRO1 (tail); | |
889 | |
890 /* If COUNT is non-nil and FROM-END is t, we can give the tail | |
891 containing the last match, since that's what #'remove* is | |
892 interested in (a zero or negative COUNT won't ever reach | |
893 count_with_tail(), our callers will return immediately on seeing | |
894 it). */ | |
895 if (!NILP (count) && !NILP (from_end)) | |
896 { | |
897 counting = EMACS_INT_MAX; | |
898 } | |
899 | |
900 { | |
901 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
902 { | |
903 if (!(ii < ending)) | |
904 { | |
905 break; | |
906 } | |
907 | |
908 if (starting <= ii && | |
909 check_test (test, key, item, elt) == test_not_unboundp) | |
910 { | |
911 encountered++; | |
912 *tail_out = tail; | |
913 | |
914 if (encountered == counting) | |
915 { | |
916 break; | |
917 } | |
918 } | |
919 | |
920 ii++; | |
921 } | |
922 } | |
923 | |
924 UNGCPRO; | |
925 | |
926 if ((ii < starting || (ii < ending && !NILP (end))) && | |
927 encountered != counting) | |
928 { | |
929 check_sequence_range (args[1], start, end, Flength (args[1])); | |
930 } | |
931 } | |
932 else if (STRINGP (sequence)) | |
933 { | |
934 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp; | |
935 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | |
936 Lisp_Object character = Qnil; | |
937 | |
938 if (EQ (caller, Qcount) && !NILP (from_end) | |
939 && (!EQ (key, Qnil) || | |
940 check_test == check_other_nokey || check_test == check_if_nokey)) | |
941 { | |
942 /* See comment above in the list code. */ | |
943 return string_count_from_end (item, sequence, | |
944 check_test, test_not_unboundp, | |
945 test, key, start, end); | |
946 } | |
947 | |
948 while (cursor_offset < byte_len && ii < ending && encountered < counting) | |
949 { | |
950 if (ii >= starting) | |
951 { | |
952 character = make_char (itext_ichar (cursor)); | |
953 | |
954 if (check_test (test, key, item, character) | |
955 == test_not_unboundp) | |
956 { | |
957 encountered++; | |
958 } | |
959 | |
960 startp = XSTRING_DATA (sequence); | |
961 cursor = startp + cursor_offset; | |
962 if (byte_len != XSTRING_LENGTH (sequence) | |
963 || !valid_ibyteptr_p (cursor)) | |
964 { | |
965 mapping_interaction_error (caller, sequence); | |
966 } | |
967 } | |
968 | |
969 INC_IBYTEPTR (cursor); | |
970 cursor_offset = cursor - startp; | |
971 ii++; | |
972 } | |
973 | |
974 if (ii < starting || (ii < ending && !NILP (end))) | |
975 { | |
976 check_sequence_range (sequence, start, end, Flength (sequence)); | |
977 } | |
978 } | |
979 else | |
980 { | |
981 Lisp_Object object = Qnil; | |
982 | |
983 len = XINT (Flength (sequence)); | |
984 check_sequence_range (sequence, start, end, make_int (len)); | |
985 | |
986 ending = min (ending, len); | |
987 if (0 == len) | |
988 { | |
989 /* Catches the case where we have nil. */ | |
990 return make_integer (encountered); | |
991 } | |
992 | |
993 if (NILP (from_end)) | |
994 { | |
995 for (ii = starting; ii < ending && encountered < counting; ii++) | |
996 { | |
997 object = Faref (sequence, make_int (ii)); | |
998 if (check_test (test, key, item, object) == test_not_unboundp) | |
999 { | |
1000 encountered++; | |
1001 } | |
1002 } | |
1003 } | |
1004 else | |
1005 { | |
1006 for (ii = ending - 1; ii >= starting && encountered < counting; ii--) | |
1007 { | |
1008 object = Faref (sequence, make_int (ii)); | |
1009 if (check_test (test, key, item, object) == test_not_unboundp) | |
1010 { | |
1011 encountered++; | |
1012 } | |
1013 } | |
1014 } | |
1015 } | |
1016 | |
1017 return make_integer (encountered); | |
1018 } | |
1019 | |
1020 static Lisp_Object | |
1021 list_count_from_end (Lisp_Object item, Lisp_Object sequence, | |
1022 check_test_func_t check_test, Boolint test_not_unboundp, | |
1023 Lisp_Object test, Lisp_Object key, | |
1024 Lisp_Object start, Lisp_Object end) | |
1025 { | |
1026 Elemcount length = XINT (Flength (sequence)), ii = 0, starting = XINT (start); | |
1027 Elemcount ending = NILP (end) ? length : XINT (end), encountered = 0; | |
1028 Lisp_Object *storage; | |
1029 struct gcpro gcpro1; | |
1030 | |
1031 check_sequence_range (sequence, start, end, make_integer (length)); | |
1032 | |
1033 storage = alloca_array (Lisp_Object, ending - starting); | |
1034 | |
1035 { | |
1036 EXTERNAL_LIST_LOOP_2 (elt, sequence) | |
1037 { | |
1038 if (starting <= ii && ii < ending) | |
1039 { | |
1040 storage[ii - starting] = elt; | |
1041 } | |
1042 ii++; | |
1043 } | |
1044 } | |
1045 | |
1046 GCPRO1 (storage[0]); | |
1047 gcpro1.nvars = ending - starting; | |
1048 | |
1049 for (ii = ending - 1; ii >= starting; ii--) | |
1050 { | |
1051 if (check_test (test, key, item, storage[ii - starting]) | |
1052 == test_not_unboundp) | |
1053 { | |
1054 encountered++; | |
1055 } | |
1056 } | |
1057 | |
1058 UNGCPRO; | |
1059 | |
1060 return make_integer (encountered); | |
1061 } | |
1062 | |
1063 static Lisp_Object | |
1064 string_count_from_end (Lisp_Object item, Lisp_Object sequence, | |
1065 check_test_func_t check_test, Boolint test_not_unboundp, | |
1066 Lisp_Object test, Lisp_Object key, | |
1067 Lisp_Object start, Lisp_Object end) | |
1068 { | |
1069 Elemcount length = string_char_length (sequence), ii = 0; | |
1070 Elemcount starting = XINT (start), ending = NILP (end) ? length : XINT (end); | |
1071 Elemcount encountered = 0; | |
1072 Ibyte *cursor = XSTRING_DATA (sequence); | |
1073 Ibyte *endp = cursor + XSTRING_LENGTH (sequence); | |
1074 Ichar *storage; | |
1075 | |
1076 check_sequence_range (sequence, start, end, make_integer (length)); | |
1077 | |
1078 storage = alloca_array (Ichar, ending - starting); | |
1079 | |
1080 while (cursor < endp && ii < ending) | |
1081 { | |
1082 if (starting <= ii && ii < ending) | |
1083 { | |
1084 storage [ii - starting] = itext_ichar (cursor); | |
1085 } | |
1086 | |
1087 ii++; | |
1088 INC_IBYTEPTR (cursor); | |
1089 } | |
1090 | |
1091 for (ii = ending - 1; ii >= starting; ii--) | |
1092 { | |
1093 if (check_test (test, key, item, make_char (storage [ii - starting])) | |
1094 == test_not_unboundp) | |
1095 { | |
1096 encountered++; | |
1097 } | |
1098 } | |
1099 | |
1100 return make_integer (encountered); | |
1101 } | |
1102 | |
1103 DEFUN ("count", Fcount, 2, MANY, 0, /* | |
1104 Count the number of occurrences of ITEM in SEQUENCE. | |
1105 | |
1106 See `remove*' for the meaning of the keywords. | |
1107 | |
1108 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | |
1109 */ | |
1110 (int nargs, Lisp_Object *args)) | |
1111 { | |
1112 Lisp_Object tail = Qnil; | |
1113 | |
1114 /* count_with_tail() accepts more keywords than we do, check those we've | |
1115 been given. */ | |
1116 PARSE_KEYWORDS (Fcount, nargs, args, 8, | |
1117 (test, test_not, if_, if_not, key, start, end, from_end), | |
1118 NULL); | |
1119 | |
1120 return count_with_tail (&tail, nargs, args, Qcount); | |
1121 } | |
1122 | |
368 /*** string functions. ***/ | 1123 /*** string functions. ***/ |
369 | 1124 |
370 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /* | 1125 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /* |
371 Return t if two strings have identical contents. | 1126 Return t if two strings have identical contents. |
372 Case is significant. Text properties are ignored. | 1127 Case is significant. Text properties are ignored. |
998 } | 1753 } |
999 | 1754 |
1000 Lisp_Object | 1755 Lisp_Object |
1001 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth) | 1756 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth) |
1002 { | 1757 { |
1003 if (depth > 200) | 1758 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
1004 stack_overflow ("Stack overflow in copy-tree", arg); | 1759 stack_overflow ("Stack overflow in copy-tree", arg); |
1005 | 1760 |
1006 if (CONSP (arg)) | 1761 if (CONSP (arg)) |
1007 { | 1762 { |
1008 Lisp_Object rest; | 1763 Lisp_Object rest; |
1738 return tail; | 2493 return tail; |
1739 } | 2494 } |
1740 return Qnil; | 2495 return Qnil; |
1741 } | 2496 } |
1742 | 2497 |
2498 /* Return the first index of ITEM in LIST. In CONS_OUT, return the cons cell | |
2499 before that containing the element. If the element is in the first cons | |
2500 cell, return Qnil in CONS_OUT. TEST, KEY, START, END are as in | |
2501 #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should have been initialized | |
2502 with get_check_match_function() or get_check_test_function(). A non-zero | |
2503 REVERSE_TEST_ORDER means call TEST with the element from LIST as its | |
2504 first argument and ITEM as its second. Error if LIST is ill-formed, or | |
2505 circular. */ | |
2506 static Lisp_Object | |
2507 list_position_cons_before (Lisp_Object *cons_out, | |
2508 Lisp_Object item, Lisp_Object list, | |
2509 check_test_func_t check_test, | |
2510 Boolint test_not_unboundp, | |
2511 Lisp_Object test, Lisp_Object key, | |
2512 Boolint reverse_test_order, | |
2513 Lisp_Object start, Lisp_Object end) | |
2514 { | |
2515 struct gcpro gcpro1, gcpro2; | |
2516 Lisp_Object elt = Qnil, tail = list, tail_before = Qnil; | |
2517 Elemcount len, ii = 0, starting = XINT (start); | |
2518 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end); | |
2519 | |
2520 GCPRO2 (elt, tail); | |
2521 | |
2522 if (check_test == check_eq_nokey) | |
2523 { | |
2524 /* TEST is #'eq, no need to call any C functions, and the test order | |
2525 won't be visible. */ | |
2526 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
2527 { | |
2528 if (starting <= ii && ii < ending && | |
2529 EQ (item, elt) == test_not_unboundp) | |
2530 { | |
2531 *cons_out = tail_before; | |
2532 RETURN_UNGCPRO (make_integer (ii)); | |
2533 } | |
2534 else | |
2535 { | |
2536 if (ii >= ending) | |
2537 { | |
2538 break; | |
2539 } | |
2540 } | |
2541 ii++; | |
2542 tail_before = tail; | |
2543 } | |
2544 } | |
2545 else | |
2546 { | |
2547 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
2548 { | |
2549 if (starting <= ii && ii < ending && | |
2550 (reverse_test_order ? | |
2551 check_test (test, key, elt, item) : | |
2552 check_test (test, key, item, elt)) == test_not_unboundp) | |
2553 { | |
2554 *cons_out = tail_before; | |
2555 RETURN_UNGCPRO (make_integer (ii)); | |
2556 } | |
2557 else | |
2558 { | |
2559 if (ii >= ending) | |
2560 { | |
2561 break; | |
2562 } | |
2563 } | |
2564 ii++; | |
2565 tail_before = tail; | |
2566 } | |
2567 } | |
2568 | |
2569 RETURN_UNGCPRO (Qnil); | |
2570 } | |
2571 | |
2572 DEFUN ("member*", FmemberX, 2, MANY, 0, /* | |
2573 Return the first sublist of LIST with car ITEM, or nil if no such sublist. | |
2574 | |
2575 The keyword :test specifies a two-argument function that is used to compare | |
2576 ITEM with elements in LIST; if omitted, it defaults to `eql'. | |
2577 | |
2578 The keyword :test-not is similar, but specifies a negated function. That | |
2579 is, ITEM is considered equal to an element in LIST if the given function | |
2580 returns nil. Common Lisp deprecates :test-not, and if both are specified, | |
2581 XEmacs signals an error. | |
2582 | |
2583 :key specifies a one-argument function that transforms elements of LIST into | |
2584 \"comparison keys\" before the test predicate is applied. For example, | |
2585 if :key is #'car, then ITEM is compared with the car of elements from LIST. | |
2586 The :key function, however, is not applied to ITEM, and does not affect the | |
2587 elements in the returned list, which are taken directly from the elements in | |
2588 LIST. | |
2589 | |
2590 arguments: (ITEM LIST &key (TEST #'eql) TEST-NOT (KEY #'identity)) | |
2591 */ | |
2592 (int nargs, Lisp_Object *args)) | |
2593 { | |
2594 Lisp_Object item = args[0], list = args[1], result = Qnil, position0; | |
2595 Boolint test_not_unboundp = 1; | |
2596 check_test_func_t check_test = NULL; | |
2597 | |
2598 PARSE_KEYWORDS (FmemberX, nargs, args, 5, (test, if_not, if_, test_not, key), | |
2599 NULL); | |
2600 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
2601 key, &test_not_unboundp); | |
2602 position0 | |
2603 = list_position_cons_before (&result, item, list, check_test, | |
2604 test_not_unboundp, test, key, 0, Qzero, Qnil); | |
2605 | |
2606 return CONSP (result) ? XCDR (result) : ZEROP (position0) ? list : Qnil; | |
2607 } | |
2608 | |
2609 /* This macro might eventually find a better home than here. */ | |
2610 | |
2611 #define CHECK_KEY_ARGUMENT(key) \ | |
2612 do { \ | |
2613 if (NILP (key)) \ | |
2614 { \ | |
2615 key = Qidentity; \ | |
2616 } \ | |
2617 \ | |
2618 if (!EQ (key, Qidentity)) \ | |
2619 { \ | |
2620 key = indirect_function (key, 1); \ | |
2621 if (EQ (key, XSYMBOL_FUNCTION (Qidentity))) \ | |
2622 { \ | |
2623 key = Qidentity; \ | |
2624 } \ | |
2625 } \ | |
2626 } while (0) | |
2627 | |
2628 #define KEY(key, item) (EQ (Qidentity, key) ? item : \ | |
2629 IGNORE_MULTIPLE_VALUES (call1 (key, item))) | |
2630 | |
2631 DEFUN ("adjoin", Fadjoin, 2, MANY, 0, /* | |
2632 Return ITEM consed onto the front of LIST, if not already in LIST. | |
2633 | |
2634 Otherwise, return LIST unmodified. | |
2635 | |
2636 See `member*' for the meaning of the keywords. | |
2637 | |
2638 arguments: (ITEM LIST &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
2639 */ | |
2640 (int nargs, Lisp_Object *args)) | |
2641 { | |
2642 Lisp_Object item = args[0], list = args[1], keyed = Qnil, ignore = Qnil; | |
2643 struct gcpro gcpro1; | |
2644 Boolint test_not_unboundp = 1; | |
2645 check_test_func_t check_test = NULL; | |
2646 | |
2647 PARSE_KEYWORDS (Fadjoin, nargs, args, 3, (test, key, test_not), | |
2648 NULL); | |
2649 | |
2650 CHECK_KEY_ARGUMENT (key); | |
2651 | |
2652 keyed = KEY (key, item); | |
2653 | |
2654 GCPRO1 (keyed); | |
2655 check_test = get_check_test_function (keyed, &test, test_not, Qnil, Qnil, | |
2656 key, &test_not_unboundp); | |
2657 if (NILP (list_position_cons_before (&ignore, keyed, list, check_test, | |
2658 test_not_unboundp, test, key, 0, Qzero, | |
2659 Qnil))) | |
2660 { | |
2661 RETURN_UNGCPRO (Fcons (item, list)); | |
2662 } | |
2663 | |
2664 RETURN_UNGCPRO (list); | |
2665 } | |
2666 | |
1743 DEFUN ("assoc", Fassoc, 2, 2, 0, /* | 2667 DEFUN ("assoc", Fassoc, 2, 2, 0, /* |
1744 Return non-nil if KEY is `equal' to the car of an element of ALIST. | 2668 Return non-nil if KEY is `equal' to the car of an element of ALIST. |
1745 The value is actually the element of ALIST whose car equals KEY. | 2669 The value is actually the element of ALIST whose car equals KEY. |
1746 */ | 2670 */ |
1747 (key, alist)) | 2671 (key, alist)) |
1824 return elt; | 2748 return elt; |
1825 } | 2749 } |
1826 return Qnil; | 2750 return Qnil; |
1827 } | 2751 } |
1828 | 2752 |
2753 DEFUN ("assoc*", FassocX, 2, MANY, 0, /* | |
2754 Find the first item whose car matches ITEM in ALIST. | |
2755 | |
2756 See `member*' for the meaning of :test, :test-not and :key. | |
2757 | |
2758 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
2759 */ | |
2760 (int nargs, Lisp_Object *args)) | |
2761 { | |
2762 Lisp_Object item = args[0], alist = args[1]; | |
2763 Boolint test_not_unboundp = 1; | |
2764 check_test_func_t check_test = NULL; | |
2765 | |
2766 PARSE_KEYWORDS (FassocX, nargs, args, 5, (test, if_, if_not, test_not, key), | |
2767 NULL); | |
2768 | |
2769 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
2770 key, &test_not_unboundp); | |
2771 | |
2772 if (check_test == check_eq_nokey) | |
2773 { | |
2774 /* TEST is #'eq, no need to call any C functions. */ | |
2775 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist) | |
2776 { | |
2777 if (EQ (item, elt_car) == test_not_unboundp) | |
2778 { | |
2779 return elt; | |
2780 } | |
2781 } | |
2782 } | |
2783 else | |
2784 { | |
2785 Lisp_Object tailed = alist; | |
2786 struct gcpro gcpro1; | |
2787 | |
2788 GCPRO1 (tailed); | |
2789 { | |
2790 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
2791 { | |
2792 tailed = tail; | |
2793 | |
2794 if (check_test (test, key, item, elt_car) == test_not_unboundp) | |
2795 { | |
2796 RETURN_UNGCPRO (elt); | |
2797 } | |
2798 } | |
2799 } | |
2800 UNGCPRO; | |
2801 } | |
2802 | |
2803 return Qnil; | |
2804 } | |
2805 | |
1829 DEFUN ("rassoc", Frassoc, 2, 2, 0, /* | 2806 DEFUN ("rassoc", Frassoc, 2, 2, 0, /* |
1830 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST. | 2807 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST. |
1831 The value is actually the element of ALIST whose cdr equals VALUE. | 2808 The value is actually the element of ALIST whose cdr equals VALUE. |
1832 */ | 2809 */ |
1833 (value, alist)) | 2810 (value, alist)) |
1894 return elt; | 2871 return elt; |
1895 } | 2872 } |
1896 return Qnil; | 2873 return Qnil; |
1897 } | 2874 } |
1898 | 2875 |
2876 DEFUN ("rassoc*", FrassocX, 2, MANY, 0, /* | |
2877 Find the first item whose cdr matches ITEM in ALIST. | |
2878 | |
2879 See `member*' for the meaning of :test, :test-not and :key. | |
2880 | |
2881 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
2882 */ | |
2883 (int nargs, Lisp_Object *args)) | |
2884 { | |
2885 Lisp_Object item = args[0], alist = args[1]; | |
2886 Boolint test_not_unboundp = 1; | |
2887 check_test_func_t check_test = NULL; | |
2888 | |
2889 PARSE_KEYWORDS (FrassocX, nargs, args, 5, (test, if_, if_not, test_not, key), | |
2890 NULL); | |
2891 | |
2892 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
2893 key, &test_not_unboundp); | |
2894 | |
2895 if (check_test == check_eq_nokey) | |
2896 { | |
2897 /* TEST is #'eq, no need to call any C functions. */ | |
2898 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist) | |
2899 { | |
2900 if (EQ (item, elt_cdr) == test_not_unboundp) | |
2901 { | |
2902 return elt; | |
2903 } | |
2904 } | |
2905 } | |
2906 else | |
2907 { | |
2908 struct gcpro gcpro1; | |
2909 Lisp_Object tailed = alist; | |
2910 | |
2911 GCPRO1 (tailed); | |
2912 { | |
2913 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
2914 { | |
2915 tailed = tail; | |
2916 | |
2917 if (check_test (test, key, item, elt_cdr) == test_not_unboundp) | |
2918 { | |
2919 RETURN_UNGCPRO (elt); | |
2920 } | |
2921 } | |
2922 } | |
2923 UNGCPRO; | |
2924 } | |
2925 | |
2926 return Qnil; | |
2927 } | |
2928 | |
2929 /* This is the implementation of both #'find and #'position. */ | |
2930 static Lisp_Object | |
2931 position (Lisp_Object *object_out, Lisp_Object item, Lisp_Object sequence, | |
2932 check_test_func_t check_test, Boolint test_not_unboundp, | |
2933 Lisp_Object test, Lisp_Object key, Lisp_Object start, Lisp_Object end, | |
2934 Lisp_Object from_end, Lisp_Object default_, Lisp_Object caller) | |
2935 { | |
2936 Lisp_Object result = Qnil; | |
2937 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0; | |
2938 | |
2939 CHECK_SEQUENCE (sequence); | |
2940 CHECK_NATNUM (start); | |
2941 starting = INTP (start) ? XINT (start) : 1 + EMACS_INT_MAX; | |
2942 | |
2943 if (!NILP (end)) | |
2944 { | |
2945 CHECK_NATNUM (end); | |
2946 ending = INTP (end) ? XINT (end) : 1 + EMACS_INT_MAX; | |
2947 } | |
2948 | |
2949 *object_out = default_; | |
2950 | |
2951 if (CONSP (sequence)) | |
2952 { | |
2953 Lisp_Object elt, tail = Qnil; | |
2954 struct gcpro gcpro1; | |
2955 | |
2956 if (!(starting < ending)) | |
2957 { | |
2958 check_sequence_range (sequence, start, end, Flength (sequence)); | |
2959 /* starting could be equal to ending, in which case nil is what | |
2960 we want to return. */ | |
2961 return Qnil; | |
2962 } | |
2963 | |
2964 GCPRO1 (tail); | |
2965 | |
2966 { | |
2967 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
2968 { | |
2969 if (starting <= ii && ii < ending | |
2970 && check_test (test, key, item, elt) == test_not_unboundp) | |
2971 { | |
2972 result = make_integer (ii); | |
2973 *object_out = elt; | |
2974 | |
2975 if (NILP (from_end)) | |
2976 { | |
2977 UNGCPRO; | |
2978 return result; | |
2979 } | |
2980 } | |
2981 else if (ii == ending) | |
2982 { | |
2983 break; | |
2984 } | |
2985 | |
2986 ii++; | |
2987 } | |
2988 } | |
2989 | |
2990 UNGCPRO; | |
2991 | |
2992 if (ii < starting || (ii < ending && !NILP (end))) | |
2993 { | |
2994 check_sequence_range (sequence, start, end, Flength (sequence)); | |
2995 } | |
2996 } | |
2997 else if (STRINGP (sequence)) | |
2998 { | |
2999 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp; | |
3000 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | |
3001 Lisp_Object character = Qnil; | |
3002 | |
3003 while (cursor_offset < byte_len && ii < ending) | |
3004 { | |
3005 if (ii >= starting) | |
3006 { | |
3007 character = make_char (itext_ichar (cursor)); | |
3008 | |
3009 if (check_test (test, key, item, character) == test_not_unboundp) | |
3010 { | |
3011 result = make_integer (ii); | |
3012 *object_out = character; | |
3013 | |
3014 if (NILP (from_end)) | |
3015 { | |
3016 return result; | |
3017 } | |
3018 } | |
3019 | |
3020 startp = XSTRING_DATA (sequence); | |
3021 cursor = startp + cursor_offset; | |
3022 if (byte_len != XSTRING_LENGTH (sequence) | |
3023 || !valid_ibyteptr_p (cursor)) | |
3024 { | |
3025 mapping_interaction_error (caller, sequence); | |
3026 } | |
3027 } | |
3028 | |
3029 INC_IBYTEPTR (cursor); | |
3030 cursor_offset = cursor - startp; | |
3031 ii++; | |
3032 } | |
3033 | |
3034 if (ii < starting || (ii < ending && !NILP (end))) | |
3035 { | |
3036 check_sequence_range (sequence, start, end, Flength (sequence)); | |
3037 } | |
3038 } | |
3039 else | |
3040 { | |
3041 Lisp_Object object = Qnil; | |
3042 len = XINT (Flength (sequence)); | |
3043 check_sequence_range (sequence, start, end, make_int (len)); | |
3044 | |
3045 ending = min (ending, len); | |
3046 if (0 == len) | |
3047 { | |
3048 /* Catches the case where we have nil. */ | |
3049 return result; | |
3050 } | |
3051 | |
3052 if (NILP (from_end)) | |
3053 { | |
3054 for (ii = starting; ii < ending; ii++) | |
3055 { | |
3056 object = Faref (sequence, make_int (ii)); | |
3057 if (check_test (test, key, item, object) == test_not_unboundp) | |
3058 { | |
3059 result = make_integer (ii); | |
3060 *object_out = object; | |
3061 return result; | |
3062 } | |
3063 } | |
3064 } | |
3065 else | |
3066 { | |
3067 for (ii = ending - 1; ii >= starting; ii--) | |
3068 { | |
3069 object = Faref (sequence, make_int (ii)); | |
3070 if (check_test (test, key, item, object) == test_not_unboundp) | |
3071 { | |
3072 result = make_integer (ii); | |
3073 *object_out = object; | |
3074 return result; | |
3075 } | |
3076 } | |
3077 } | |
3078 } | |
3079 | |
3080 return result; | |
3081 } | |
3082 | |
3083 DEFUN ("position", Fposition, 2, MANY, 0, /* | |
3084 Return the index of the first occurrence of ITEM in SEQUENCE. | |
3085 | |
3086 Return nil if not found. See `remove*' for the meaning of the keywords. | |
3087 | |
3088 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END TEST-NOT) | |
3089 */ | |
3090 (int nargs, Lisp_Object *args)) | |
3091 { | |
3092 Lisp_Object object = Qnil, item = args[0], sequence = args[1]; | |
3093 Boolint test_not_unboundp = 1; | |
3094 check_test_func_t check_test = NULL; | |
3095 | |
3096 PARSE_KEYWORDS (Fposition, nargs, args, 8, | |
3097 (test, if_, test_not, if_not, key, start, end, from_end), | |
3098 (start = Qzero)); | |
3099 | |
3100 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3101 key, &test_not_unboundp); | |
3102 | |
3103 return position (&object, item, sequence, check_test, test_not_unboundp, | |
3104 test, key, start, end, from_end, Qnil, Qposition); | |
3105 } | |
3106 | |
3107 DEFUN ("find", Ffind, 2, MANY, 0, /* | |
3108 Find the first occurrence of ITEM in SEQUENCE. | |
3109 | |
3110 Return the matching ITEM, or nil if not found. See `remove*' for the | |
3111 meaning of the keywords. | |
3112 | |
3113 The keyword :default, not specified by Common Lisp, designates an object to | |
3114 return instead of nil if ITEM is not found. | |
3115 | |
3116 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) DEFAULT FROM-END TEST-NOT) | |
3117 */ | |
3118 (int nargs, Lisp_Object *args)) | |
3119 { | |
3120 Lisp_Object object = Qnil, item = args[0], sequence = args[1]; | |
3121 Boolint test_not_unboundp = 1; | |
3122 check_test_func_t check_test = NULL; | |
3123 | |
3124 PARSE_KEYWORDS (Fposition, nargs, args, 9, | |
3125 (test, if_, test_not, if_not, key, start, end, from_end, | |
3126 default_), | |
3127 (start = Qzero)); | |
3128 | |
3129 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3130 key, &test_not_unboundp); | |
3131 | |
3132 position (&object, item, sequence, check_test, test_not_unboundp, | |
3133 test, key, start, end, from_end, Qnil, Qposition); | |
3134 | |
3135 return object; | |
3136 } | |
1899 | 3137 |
1900 DEFUN ("delete", Fdelete, 2, 2, 0, /* | 3138 DEFUN ("delete", Fdelete, 2, 2, 0, /* |
1901 Delete by side effect any occurrences of ELT as a member of LIST. | 3139 Delete by side effect any occurrences of ELT as a member of LIST. |
1902 The modified LIST is returned. Comparison is done with `equal'. | 3140 The modified LIST is returned. Comparison is done with `equal'. |
1903 If the first member of LIST is ELT, there is no way to remove it by side | 3141 If the first member of LIST is ELT, there is no way to remove it by side |
1998 } | 3236 } |
1999 } | 3237 } |
2000 return list; | 3238 return list; |
2001 } | 3239 } |
2002 | 3240 |
3241 DEFUN ("delete*", FdeleteX, 2, MANY, 0, /* | |
3242 Remove all occurrences of ITEM in SEQUENCE, destructively. | |
3243 | |
3244 If SEQUENCE is a non-nil list, this modifies the list directly. A non-list | |
3245 SEQUENCE will not be destructively modified, rather, if ITEM occurs in it, a | |
3246 new SEQUENCE of the same type without ITEM will be returned. | |
3247 | |
3248 See `remove*' for a non-destructive alternative, and for explanation of the | |
3249 keyword arguments. | |
3250 | |
3251 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) | |
3252 */ | |
3253 (int nargs, Lisp_Object *args)) | |
3254 { | |
3255 Lisp_Object item = args[0], sequence = args[1], tail = sequence; | |
3256 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; | |
3257 Elemcount len, ii = 0, encountered = 0, presenting = 0; | |
3258 Boolint test_not_unboundp = 1; | |
3259 check_test_func_t check_test = NULL; | |
3260 struct gcpro gcpro1; | |
3261 | |
3262 PARSE_KEYWORDS (FdeleteX, nargs, args, 9, | |
3263 (test, if_not, if_, test_not, key, start, end, from_end, | |
3264 count), (start = Qzero, count = Qunbound)); | |
3265 | |
3266 CHECK_SEQUENCE (sequence); | |
3267 CHECK_NATNUM (start); | |
3268 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
3269 | |
3270 if (!NILP (end)) | |
3271 { | |
3272 CHECK_NATNUM (end); | |
3273 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
3274 } | |
3275 | |
3276 if (!UNBOUNDP (count)) | |
3277 { | |
3278 if (!NILP (count)) | |
3279 { | |
3280 CHECK_INTEGER (count); | |
3281 if (INTP (count)) | |
3282 { | |
3283 counting = XINT (count); | |
3284 } | |
3285 #ifdef HAVE_BIGNUM | |
3286 else | |
3287 { | |
3288 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
3289 1 + EMACS_INT_MAX : EMACS_INT_MIN - 1; | |
3290 } | |
3291 #endif | |
3292 | |
3293 if (counting < 1) | |
3294 { | |
3295 return sequence; | |
3296 } | |
3297 } | |
3298 } | |
3299 | |
3300 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3301 key, &test_not_unboundp); | |
3302 | |
3303 if (CONSP (sequence)) | |
3304 { | |
3305 Lisp_Object prev_tail_list_elt = Qnil, list_elt = Qnil; | |
3306 Elemcount list_len = 0, deleted = 0; | |
3307 | |
3308 if (!NILP (count) && !NILP (from_end)) | |
3309 { | |
3310 /* Both COUNT and FROM-END were specified; we need to traverse the | |
3311 list twice. */ | |
3312 Lisp_Object present = count_with_tail (&list_elt, nargs, args, | |
3313 QdeleteX); | |
3314 | |
3315 if (ZEROP (present)) | |
3316 { | |
3317 return sequence; | |
3318 } | |
3319 | |
3320 presenting = XINT (present); | |
3321 | |
3322 /* If there are fewer items in the list than we have permission to | |
3323 delete, we don't need to differentiate between the :from-end | |
3324 nil and :from-end t cases. Otherwise, presenting is the number | |
3325 of matching items we need to ignore before we start to | |
3326 delete. */ | |
3327 presenting = presenting <= counting ? 0 : presenting - counting; | |
3328 } | |
3329 | |
3330 GCPRO1 (tail); | |
3331 ii = -1; | |
3332 | |
3333 { | |
3334 EXTERNAL_LIST_LOOP_4_NO_DECLARE (list_elt, sequence, tail, list_len) | |
3335 { | |
3336 ii++; | |
3337 | |
3338 if (starting <= ii && ii < ending && | |
3339 (check_test (test, key, item, list_elt) == test_not_unboundp) | |
3340 && (presenting ? encountered++ >= presenting | |
3341 : encountered++ < counting)) | |
3342 { | |
3343 if (NILP (prev_tail_list_elt)) | |
3344 { | |
3345 sequence = XCDR (tail); | |
3346 } | |
3347 else | |
3348 { | |
3349 XSETCDR (prev_tail_list_elt, XCDR (tail)); | |
3350 } | |
3351 | |
3352 /* Keep tortoise from ever passing hare. */ | |
3353 list_len = 0; | |
3354 deleted++; | |
3355 } | |
3356 else | |
3357 { | |
3358 prev_tail_list_elt = tail; | |
3359 if (ii >= ending || (!presenting && encountered > counting)) | |
3360 { | |
3361 break; | |
3362 } | |
3363 } | |
3364 } | |
3365 } | |
3366 | |
3367 UNGCPRO; | |
3368 | |
3369 if ((ii < starting || (ii < ending && !NILP (end))) && | |
3370 !(presenting ? encountered == presenting : encountered == counting)) | |
3371 { | |
3372 check_sequence_range (args[1], start, end, | |
3373 make_int (deleted + XINT (Flength (args[1])))); | |
3374 } | |
3375 | |
3376 return sequence; | |
3377 } | |
3378 else if (STRINGP (sequence)) | |
3379 { | |
3380 Ibyte *staging = alloca_ibytes (XSTRING_LENGTH (sequence)); | |
3381 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence); | |
3382 Ibyte *cursor = startp; | |
3383 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence); | |
3384 Lisp_Object character, result = sequence; | |
3385 | |
3386 if (!NILP (count) && !NILP (from_end)) | |
3387 { | |
3388 Lisp_Object present = count_with_tail (&character, nargs, args, | |
3389 QdeleteX); | |
3390 | |
3391 if (ZEROP (present)) | |
3392 { | |
3393 return sequence; | |
3394 } | |
3395 | |
3396 presenting = XINT (present); | |
3397 | |
3398 /* If there are fewer items in the list than we have permission to | |
3399 delete, we don't need to differentiate between the :from-end | |
3400 nil and :from-end t cases. Otherwise, presenting is the number | |
3401 of matching items we need to ignore before we start to | |
3402 delete. */ | |
3403 presenting = presenting <= counting ? 0 : presenting - counting; | |
3404 } | |
3405 | |
3406 ii = 0; | |
3407 while (cursor_offset < byte_len) | |
3408 { | |
3409 if (ii >= starting && ii < ending) | |
3410 { | |
3411 character = make_char (itext_ichar (cursor)); | |
3412 | |
3413 if ((check_test (test, key, item, character) | |
3414 == test_not_unboundp) | |
3415 && (presenting ? encountered++ >= presenting : | |
3416 encountered++ < counting)) | |
3417 { | |
3418 DO_NOTHING; | |
3419 } | |
3420 else | |
3421 { | |
3422 staging_cursor | |
3423 += set_itext_ichar (staging_cursor, XCHAR (character)); | |
3424 } | |
3425 | |
3426 startp = XSTRING_DATA (sequence); | |
3427 cursor = startp + cursor_offset; | |
3428 if (byte_len != XSTRING_LENGTH (sequence) | |
3429 || !valid_ibyteptr_p (cursor)) | |
3430 { | |
3431 mapping_interaction_error (QdeleteX, sequence); | |
3432 } | |
3433 } | |
3434 else | |
3435 { | |
3436 staging_cursor += itext_copy_ichar (cursor, staging_cursor); | |
3437 } | |
3438 | |
3439 INC_IBYTEPTR (cursor); | |
3440 cursor_offset = cursor - startp; | |
3441 ii++; | |
3442 } | |
3443 | |
3444 if (ii < starting || (ii < ending && !NILP (end))) | |
3445 { | |
3446 check_sequence_range (sequence, start, end, Flength (sequence)); | |
3447 } | |
3448 | |
3449 if (0 != encountered) | |
3450 { | |
3451 result = make_string (staging, staging_cursor - staging); | |
3452 copy_string_extents (result, sequence, 0, 0, | |
3453 staging_cursor - staging); | |
3454 sequence = result; | |
3455 } | |
3456 | |
3457 return sequence; | |
3458 } | |
3459 else | |
3460 { | |
3461 Lisp_Object position0 = Qnil, object = Qnil; | |
3462 Lisp_Object *staging = NULL, *staging_cursor, *staging_limit; | |
3463 Elemcount positioning; | |
3464 | |
3465 len = XINT (Flength (sequence)); | |
3466 | |
3467 check_sequence_range (sequence, start, end, make_int (len)); | |
3468 | |
3469 position0 = position (&object, item, sequence, check_test, | |
3470 test_not_unboundp, test, key, start, end, | |
3471 from_end, Qnil, QdeleteX); | |
3472 if (NILP (position0)) | |
3473 { | |
3474 return sequence; | |
3475 } | |
3476 | |
3477 ending = min (ending, len); | |
3478 positioning = XINT (position0); | |
3479 encountered = 1; | |
3480 | |
3481 if (NILP (from_end)) | |
3482 { | |
3483 staging = alloca_array (Lisp_Object, len - 1); | |
3484 staging_cursor = staging; | |
3485 | |
3486 ii = 0; | |
3487 while (ii < positioning) | |
3488 { | |
3489 *staging_cursor++ = Faref (sequence, make_int (ii)); | |
3490 ii++; | |
3491 } | |
3492 | |
3493 ii = positioning + 1; | |
3494 while (ii < ending) | |
3495 { | |
3496 object = Faref (sequence, make_int (ii)); | |
3497 if (encountered < counting | |
3498 && (check_test (test, key, item, object) | |
3499 == test_not_unboundp)) | |
3500 { | |
3501 encountered++; | |
3502 } | |
3503 else | |
3504 { | |
3505 *staging_cursor++ = object; | |
3506 } | |
3507 ii++; | |
3508 } | |
3509 | |
3510 while (ii < len) | |
3511 { | |
3512 *staging_cursor++ = Faref (sequence, make_int (ii)); | |
3513 ii++; | |
3514 } | |
3515 } | |
3516 else | |
3517 { | |
3518 staging = alloca_array (Lisp_Object, len - 1); | |
3519 staging_cursor = staging_limit = staging + len - 1; | |
3520 | |
3521 ii = len - 1; | |
3522 while (ii > positioning) | |
3523 { | |
3524 *--staging_cursor = Faref (sequence, make_int (ii)); | |
3525 ii--; | |
3526 } | |
3527 | |
3528 ii = positioning - 1; | |
3529 while (ii >= starting) | |
3530 { | |
3531 object = Faref (sequence, make_int (ii)); | |
3532 if (encountered < counting | |
3533 && (check_test (test, key, item, object) == | |
3534 test_not_unboundp)) | |
3535 { | |
3536 encountered++; | |
3537 } | |
3538 else | |
3539 { | |
3540 *--staging_cursor = object; | |
3541 } | |
3542 | |
3543 ii--; | |
3544 } | |
3545 | |
3546 while (ii >= 0) | |
3547 { | |
3548 *--staging_cursor = Faref (sequence, make_int (ii)); | |
3549 ii--; | |
3550 } | |
3551 | |
3552 staging = staging_cursor; | |
3553 staging_cursor = staging_limit; | |
3554 } | |
3555 | |
3556 if (VECTORP (sequence)) | |
3557 { | |
3558 return Fvector (staging_cursor - staging, staging); | |
3559 } | |
3560 else if (BIT_VECTORP (sequence)) | |
3561 { | |
3562 return Fbit_vector (staging_cursor - staging, staging); | |
3563 } | |
3564 | |
3565 /* A nil sequence will have given us a nil #'position, | |
3566 above. */ | |
3567 ABORT (); | |
3568 | |
3569 return Qnil; | |
3570 } | |
3571 } | |
3572 | |
3573 DEFUN ("remove*", FremoveX, 2, MANY, 0, /* | |
3574 Remove all occurrences of ITEM in SEQUENCE, non-destructively. | |
3575 | |
3576 If SEQUENCE is a list, `remove*' makes a copy if that is necessary to avoid | |
3577 corrupting the original SEQUENCE. | |
3578 | |
3579 The keywords :test and :test-not specify two-argument test and negated-test | |
3580 predicates, respectively; :test defaults to `eql'. :key specifies a | |
3581 one-argument function that transforms elements of SEQUENCE into \"comparison | |
3582 keys\" before the test predicate is applied. See `member*' for more | |
3583 information on these keywords. | |
3584 | |
3585 :start and :end, if given, specify indices of a subsequence of SEQUENCE to | |
3586 be processed. Indices are 0-based and processing involves the subsequence | |
3587 starting at the index given by :start and ending just before the index given | |
3588 by :end. | |
3589 | |
3590 :count, if given, limits the number of items removed to the number | |
3591 specified. :from-end, if given, causes processing to proceed starting from | |
3592 the end instead of the beginning; in this case, this matters only if :count | |
3593 is given. | |
3594 | |
3595 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) | |
3596 */ | |
3597 (int nargs, Lisp_Object *args)) | |
3598 { | |
3599 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil, | |
3600 tail = Qnil; | |
3601 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; | |
3602 Elemcount len, ii = 0, encountered = 0, presenting = 0; | |
3603 Boolint test_not_unboundp = 1; | |
3604 check_test_func_t check_test = NULL; | |
3605 struct gcpro gcpro1; | |
3606 | |
3607 PARSE_KEYWORDS (FremoveX, nargs, args, 9, | |
3608 (test, if_not, if_, test_not, key, start, end, from_end, | |
3609 count), (start = Qzero)); | |
3610 | |
3611 if (!CONSP (sequence)) | |
3612 { | |
3613 return FdeleteX (nargs, args); | |
3614 } | |
3615 | |
3616 CHECK_NATNUM (start); | |
3617 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
3618 | |
3619 if (!NILP (end)) | |
3620 { | |
3621 CHECK_NATNUM (end); | |
3622 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
3623 } | |
3624 | |
3625 if (!NILP (count)) | |
3626 { | |
3627 CHECK_INTEGER (count); | |
3628 if (INTP (count)) | |
3629 { | |
3630 counting = XINT (count); | |
3631 } | |
3632 #ifdef HAVE_BIGNUM | |
3633 else | |
3634 { | |
3635 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
3636 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN; | |
3637 } | |
3638 #endif | |
3639 | |
3640 if (counting <= 0) | |
3641 { | |
3642 return sequence; | |
3643 } | |
3644 } | |
3645 | |
3646 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3647 key, &test_not_unboundp); | |
3648 | |
3649 matched_count = count_with_tail (&tail, nargs, args, QremoveX); | |
3650 | |
3651 if (!ZEROP (matched_count)) | |
3652 { | |
3653 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; | |
3654 GCPRO1 (tailing); | |
3655 | |
3656 if (!NILP (count) && !NILP (from_end)) | |
3657 { | |
3658 presenting = XINT (matched_count); | |
3659 | |
3660 /* If there are fewer matching elements in the list than we have | |
3661 permission to delete, we don't need to differentiate between | |
3662 the :from-end nil and :from-end t cases. Otherwise, presenting | |
3663 is the number of matching items we need to ignore before we | |
3664 start to delete. */ | |
3665 presenting = presenting <= counting ? 0 : presenting - counting; | |
3666 } | |
3667 | |
3668 { | |
3669 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) | |
3670 { | |
3671 if (EQ (tail, tailing)) | |
3672 { | |
3673 if (NILP (result)) | |
3674 { | |
3675 RETURN_UNGCPRO (XCDR (tail)); | |
3676 } | |
3677 | |
3678 XSETCDR (result_tail, XCDR (tail)); | |
3679 RETURN_UNGCPRO (result); | |
3680 } | |
3681 else if (starting <= ii && ii < ending && | |
3682 (check_test (test, key, item, elt) == test_not_unboundp) | |
3683 && (presenting ? encountered++ >= presenting | |
3684 : encountered++ < counting)) | |
3685 { | |
3686 DO_NOTHING; | |
3687 } | |
3688 else if (NILP (result)) | |
3689 { | |
3690 result = result_tail = Fcons (elt, Qnil); | |
3691 } | |
3692 else | |
3693 { | |
3694 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
3695 result_tail = XCDR (result_tail); | |
3696 } | |
3697 | |
3698 if (ii == ending) | |
3699 { | |
3700 break; | |
3701 } | |
3702 | |
3703 ii++; | |
3704 } | |
3705 } | |
3706 | |
3707 UNGCPRO; | |
3708 | |
3709 if (ii < starting || (ii < ending && !NILP (end))) | |
3710 { | |
3711 check_sequence_range (args[0], start, end, Flength (args[0])); | |
3712 } | |
3713 | |
3714 return result; | |
3715 } | |
3716 | |
3717 return sequence; | |
3718 } | |
3719 | |
2003 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /* | 3720 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /* |
2004 Delete by side effect any elements of ALIST whose car is `equal' to KEY. | 3721 Delete by side effect any elements of ALIST whose car is `equal' to KEY. |
2005 The modified ALIST is returned. If the first member of ALIST has a car | 3722 The modified ALIST is returned. If the first member of ALIST has a car |
2006 that is `equal' to KEY, there is no way to remove it by side effect; | 3723 that is `equal' to KEY, there is no way to remove it by side effect; |
2007 therefore, write `(setq foo (remassoc key foo))' to be sure of changing | 3724 therefore, write `(setq foo (remassoc key foo))' to be sure of changing |
2086 LIST_LOOP_DELETE_IF (elt, alist, | 3803 LIST_LOOP_DELETE_IF (elt, alist, |
2087 (CONSP (elt) && | 3804 (CONSP (elt) && |
2088 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); | 3805 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); |
2089 return alist; | 3806 return alist; |
2090 } | 3807 } |
2091 | 3808 |
3809 /* Remove duplicate elements between START and END from LIST, a non-nil | |
3810 list; if COPY is zero, do so destructively. Items to delete are selected | |
3811 according to the algorithm used when :from-end t is passed to | |
3812 #'delete-duplicates. Error if LIST is ill-formed or circular. | |
3813 | |
3814 TEST and KEY are as in #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should | |
3815 reflect them, having been initialised with get_check_match_function() or | |
3816 get_check_test_function(). */ | |
3817 static Lisp_Object | |
3818 list_delete_duplicates_from_end (Lisp_Object list, | |
3819 check_test_func_t check_test, | |
3820 Boolint test_not_unboundp, | |
3821 Lisp_Object test, Lisp_Object key, | |
3822 Lisp_Object start, | |
3823 Lisp_Object end, Boolint copy) | |
3824 { | |
3825 Lisp_Object checking = Qnil, elt, tail, result = list; | |
3826 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail; | |
3827 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start); | |
3828 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1; | |
3829 Elemcount ii = 0; | |
3830 struct gcpro gcpro1, gcpro2; | |
3831 | |
3832 /* We can't delete (or remove) as we go, because that breaks START and | |
3833 END. We could if END were nil, and that would change an ON(N + 2) | |
3834 algorithm to an ON^2 algorithm; list_position_cons_before() would need to | |
3835 be modified to return the cons *before* the one containing the item for | |
3836 that. Here and now it doesn't matter, though, #'delete-duplicates is | |
3837 relatively expensive no matter what. */ | |
3838 struct Lisp_Bit_Vector *deleting | |
3839 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
3840 + (sizeof (long) | |
3841 * (BIT_VECTOR_LONG_STORAGE (len) | |
3842 - 1))); | |
3843 | |
3844 check_sequence_range (list, start, end, make_integer (len)); | |
3845 | |
3846 deleting->size = len; | |
3847 memset (&(deleting->bits), 0, | |
3848 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
3849 | |
3850 GCPRO2 (tail, keyed); | |
3851 | |
3852 { | |
3853 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
3854 { | |
3855 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii)) | |
3856 { | |
3857 ii++; | |
3858 continue; | |
3859 } | |
3860 | |
3861 keyed = KEY (key, elt); | |
3862 checking = XCDR (tail); | |
3863 pos = ii + 1; | |
3864 | |
3865 while (!NILP ((positioned = list_position_cons_before | |
3866 (&position_cons, keyed, checking, check_test, | |
3867 test_not_unboundp, test, key, 0, | |
3868 make_int (max (starting - pos, 0)), | |
3869 make_int (ending - pos))))) | |
3870 { | |
3871 pos = XINT (positioned) + pos; | |
3872 set_bit_vector_bit (deleting, pos, 1); | |
3873 greatest_pos_seen = max (greatest_pos_seen, pos); | |
3874 checking = NILP (position_cons) ? | |
3875 XCDR (checking) : XCDR (XCDR (position_cons)); | |
3876 pos += 1; | |
3877 } | |
3878 ii++; | |
3879 } | |
3880 } | |
3881 | |
3882 UNGCPRO; | |
3883 | |
3884 ii = 0; | |
3885 | |
3886 if (greatest_pos_seen > -1) | |
3887 { | |
3888 if (copy) | |
3889 { | |
3890 result = result_tail = Fcons (XCAR (list), Qnil); | |
3891 list = XCDR (list); | |
3892 ii = 1; | |
3893 | |
3894 { | |
3895 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
3896 { | |
3897 if (ii == greatest_pos_seen) | |
3898 { | |
3899 XSETCDR (result_tail, XCDR (tail)); | |
3900 break; | |
3901 } | |
3902 else if (!bit_vector_bit (deleting, ii)) | |
3903 { | |
3904 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
3905 result_tail = XCDR (result_tail); | |
3906 } | |
3907 ii++; | |
3908 } | |
3909 } | |
3910 } | |
3911 else | |
3912 { | |
3913 EXTERNAL_LIST_LOOP_DELETE_IF (elt0, list, | |
3914 bit_vector_bit (deleting, ii++)); | |
3915 } | |
3916 } | |
3917 | |
3918 return result; | |
3919 } | |
3920 | |
3921 DEFUN ("delete-duplicates", Fdelete_duplicates, 1, MANY, 0, /* | |
3922 Remove all duplicate elements from SEQUENCE, destructively. | |
3923 | |
3924 If SEQUENCE is a list and has duplicates, modify and return it. Note that | |
3925 SEQUENCE may start with an element to be deleted; because of this, if | |
3926 modifying a variable, be sure to write `(setq VARIABLE (delete-duplicates | |
3927 VARIABLE))' to be certain to have a list without duplicate elements. | |
3928 | |
3929 If SEQUENCE is an array and has duplicates, return a newly-allocated array | |
3930 of the same type comprising all unique elements of SEQUENCE. | |
3931 | |
3932 If there are no duplicate elements in SEQUENCE, return it unmodified. | |
3933 | |
3934 See `remove*' for the meaning of the keywords. See `remove-duplicates' for | |
3935 a non-destructive version of this function. | |
3936 | |
3937 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | |
3938 */ | |
3939 (int nargs, Lisp_Object *args)) | |
3940 { | |
3941 Lisp_Object sequence = args[0], tail = sequence, keyed = Qnil, elt = Qnil; | |
3942 Lisp_Object elt0 = Qnil, positioned = Qnil, ignore = Qnil; | |
3943 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0; | |
3944 Boolint test_not_unboundp = 1; | |
3945 check_test_func_t check_test = NULL; | |
3946 struct gcpro gcpro1, gcpro2; | |
3947 | |
3948 PARSE_KEYWORDS (Fdelete_duplicates, nargs, args, 6, | |
3949 (test, key, test_not, start, end, from_end), | |
3950 (start = Qzero)); | |
3951 | |
3952 CHECK_SEQUENCE (sequence); | |
3953 CHECK_NATNUM (start); | |
3954 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
3955 | |
3956 if (!NILP (end)) | |
3957 { | |
3958 CHECK_NATNUM (end); | |
3959 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
3960 } | |
3961 | |
3962 CHECK_KEY_ARGUMENT (key); | |
3963 | |
3964 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
3965 &test_not_unboundp, &check_test); | |
3966 | |
3967 if (CONSP (sequence)) | |
3968 { | |
3969 if (NILP (from_end)) | |
3970 { | |
3971 Lisp_Object prev_tail = Qnil; | |
3972 Elemcount deleted = 0; | |
3973 | |
3974 GCPRO2 (tail, keyed); | |
3975 | |
3976 { | |
3977 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
3978 { | |
3979 if (starting <= ii && ii < ending) | |
3980 { | |
3981 keyed = KEY (key, elt); | |
3982 positioned | |
3983 = list_position_cons_before (&ignore, keyed, | |
3984 XCDR (tail), check_test, | |
3985 test_not_unboundp, test, key, | |
3986 0, make_int (max (starting | |
3987 - (ii + 1), | |
3988 0)), | |
3989 make_int (ending | |
3990 - (ii + 1))); | |
3991 if (!NILP (positioned)) | |
3992 { | |
3993 sequence = XCDR (tail); | |
3994 deleted++; | |
3995 } | |
3996 else | |
3997 { | |
3998 break; | |
3999 } | |
4000 } | |
4001 else | |
4002 { | |
4003 break; | |
4004 } | |
4005 | |
4006 ii++; | |
4007 } | |
4008 } | |
4009 { | |
4010 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) | |
4011 { | |
4012 if (!(starting <= ii && ii <= ending)) | |
4013 { | |
4014 prev_tail = tail; | |
4015 ii++; | |
4016 continue; | |
4017 } | |
4018 | |
4019 keyed = KEY (key, elt0); | |
4020 positioned | |
4021 = list_position_cons_before (&ignore, keyed, XCDR (tail), | |
4022 check_test, test_not_unboundp, | |
4023 test, key, 0, | |
4024 make_int (max (starting | |
4025 - (ii + 1), 0)), | |
4026 make_int (ending - (ii + 1))); | |
4027 if (!NILP (positioned)) | |
4028 { | |
4029 /* We know this isn't the first iteration of the loop, | |
4030 because we advanced above to the point where we have at | |
4031 least one non-duplicate entry at the head of the | |
4032 list. */ | |
4033 XSETCDR (prev_tail, XCDR (tail)); | |
4034 len = 0; | |
4035 deleted++; | |
4036 } | |
4037 else | |
4038 { | |
4039 prev_tail = tail; | |
4040 if (ii >= ending) | |
4041 { | |
4042 break; | |
4043 } | |
4044 } | |
4045 | |
4046 ii++; | |
4047 } | |
4048 } | |
4049 UNGCPRO; | |
4050 | |
4051 if ((ii < starting || (ii < ending && !NILP (end)))) | |
4052 { | |
4053 check_sequence_range (args[0], start, end, | |
4054 make_int (deleted | |
4055 + XINT (Flength (args[0])))); | |
4056 } | |
4057 } | |
4058 else | |
4059 { | |
4060 sequence = list_delete_duplicates_from_end (sequence, check_test, | |
4061 test_not_unboundp, | |
4062 test, key, start, end, | |
4063 0); | |
4064 } | |
4065 } | |
4066 else if (STRINGP (sequence)) | |
4067 { | |
4068 if (EQ (Qidentity, key)) | |
4069 { | |
4070 /* We know all the elements will be characters; set check_test to | |
4071 reflect that. This isn't useful if KEY is not #'identity, since | |
4072 it may return non-characters for the elements. */ | |
4073 check_test = get_check_test_function (make_char ('a'), | |
4074 &test, test_not, | |
4075 Qnil, Qnil, key, | |
4076 &test_not_unboundp); | |
4077 } | |
4078 | |
4079 if (NILP (from_end)) | |
4080 { | |
4081 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | |
4082 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging; | |
4083 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor; | |
4084 Elemcount deleted = 0; | |
4085 | |
4086 elt = Qnil; | |
4087 GCPRO1 (elt); | |
4088 | |
4089 while (cursor_offset < byte_len) | |
4090 { | |
4091 if (starting <= ii && ii < ending) | |
4092 { | |
4093 Ibyte *cursor0 = cursor; | |
4094 Bytecount cursor0_offset; | |
4095 Boolint delete_this = 0; | |
4096 | |
4097 elt = KEY (key, make_char (itext_ichar (cursor))); | |
4098 INC_IBYTEPTR (cursor0); | |
4099 cursor0_offset = cursor0 - startp; | |
4100 | |
4101 for (jj = ii + 1; jj < ending && cursor0_offset < byte_len; | |
4102 jj++) | |
4103 { | |
4104 if (check_test (test, key, elt, | |
4105 make_char (itext_ichar (cursor0))) | |
4106 == test_not_unboundp) | |
4107 { | |
4108 delete_this = 1; | |
4109 deleted++; | |
4110 break; | |
4111 } | |
4112 | |
4113 startp = XSTRING_DATA (sequence); | |
4114 cursor0 = startp + cursor0_offset; | |
4115 if (byte_len != XSTRING_LENGTH (sequence) | |
4116 || !valid_ibyteptr_p (cursor0)) | |
4117 { | |
4118 mapping_interaction_error (Qdelete_duplicates, | |
4119 sequence); | |
4120 } | |
4121 | |
4122 INC_IBYTEPTR (cursor0); | |
4123 cursor0_offset = cursor0 - startp; | |
4124 } | |
4125 | |
4126 startp = XSTRING_DATA (sequence); | |
4127 cursor = startp + cursor_offset; | |
4128 | |
4129 if (byte_len != XSTRING_LENGTH (sequence) | |
4130 || !valid_ibyteptr_p (cursor)) | |
4131 { | |
4132 mapping_interaction_error (Qdelete_duplicates, sequence); | |
4133 } | |
4134 | |
4135 if (!delete_this) | |
4136 { | |
4137 staging_cursor | |
4138 += itext_copy_ichar (cursor, staging_cursor); | |
4139 | |
4140 } | |
4141 } | |
4142 else | |
4143 { | |
4144 staging_cursor += itext_copy_ichar (cursor, staging_cursor); | |
4145 } | |
4146 | |
4147 INC_IBYTEPTR (cursor); | |
4148 cursor_offset = cursor - startp; | |
4149 ii++; | |
4150 } | |
4151 | |
4152 UNGCPRO; | |
4153 | |
4154 if (ii < starting || (ii < ending && !NILP (end))) | |
4155 { | |
4156 check_sequence_range (sequence, start, end, Flength (sequence)); | |
4157 } | |
4158 | |
4159 if (0 != deleted) | |
4160 { | |
4161 sequence = make_string (staging, staging_cursor - staging); | |
4162 } | |
4163 } | |
4164 else | |
4165 { | |
4166 Elemcount deleted = 0; | |
4167 Ibyte *staging = alloca_ibytes ((len = string_char_length (sequence)) | |
4168 * MAX_ICHAR_LEN); | |
4169 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence); | |
4170 Ibyte *endp = startp + XSTRING_LENGTH (sequence); | |
4171 struct Lisp_Bit_Vector *deleting | |
4172 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
4173 + (sizeof (long) | |
4174 * (BIT_VECTOR_LONG_STORAGE (len) | |
4175 - 1))); | |
4176 | |
4177 check_sequence_range (sequence, start, end, make_integer (len)); | |
4178 | |
4179 /* For the from_end t case; transform contents to an array with | |
4180 elements addressable in constant time, use the same algorithm | |
4181 as for vectors. */ | |
4182 deleting->size = len; | |
4183 memset (&(deleting->bits), 0, | |
4184 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
4185 | |
4186 while (startp < endp) | |
4187 { | |
4188 itext_copy_ichar (startp, staging + (ii * MAX_ICHAR_LEN)); | |
4189 INC_IBYTEPTR (startp); | |
4190 ii++; | |
4191 } | |
4192 | |
4193 GCPRO1 (elt); | |
4194 | |
4195 ending = min (ending, len); | |
4196 | |
4197 for (ii = ending - 1; ii >= starting; ii--) | |
4198 { | |
4199 elt = KEY (key, make_char (itext_ichar (staging + | |
4200 (ii * MAX_ICHAR_LEN)))); | |
4201 for (jj = ii - 1; jj >= starting; jj--) | |
4202 { | |
4203 if (check_test (test, key, elt, | |
4204 make_char (itext_ichar | |
4205 (staging + (jj * MAX_ICHAR_LEN)))) | |
4206 == test_not_unboundp) | |
4207 { | |
4208 set_bit_vector_bit (deleting, ii, 1); | |
4209 deleted++; | |
4210 break; | |
4211 } | |
4212 } | |
4213 } | |
4214 | |
4215 UNGCPRO; | |
4216 | |
4217 if (0 != deleted) | |
4218 { | |
4219 startp = XSTRING_DATA (sequence); | |
4220 | |
4221 for (ii = 0; ii < len; ii++) | |
4222 { | |
4223 if (!bit_vector_bit (deleting, ii)) | |
4224 { | |
4225 staging_cursor | |
4226 += itext_copy_ichar (startp, staging_cursor); | |
4227 } | |
4228 | |
4229 INC_IBYTEPTR (startp); | |
4230 } | |
4231 | |
4232 sequence = make_string (staging, staging_cursor - staging); | |
4233 } | |
4234 } | |
4235 } | |
4236 else if (VECTORP (sequence)) | |
4237 { | |
4238 Elemcount deleted = 0; | |
4239 Lisp_Object *content = XVECTOR_DATA (sequence); | |
4240 struct Lisp_Bit_Vector *deleting; | |
4241 | |
4242 len = XVECTOR_LENGTH (sequence); | |
4243 check_sequence_range (sequence, start, end, make_integer (len)); | |
4244 | |
4245 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
4246 + (sizeof (long) | |
4247 * (BIT_VECTOR_LONG_STORAGE (len) | |
4248 - 1))); | |
4249 deleting->size = len; | |
4250 memset (&(deleting->bits), 0, | |
4251 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
4252 | |
4253 GCPRO1 (elt); | |
4254 | |
4255 ending = min (ending, len); | |
4256 | |
4257 if (NILP (from_end)) | |
4258 { | |
4259 for (ii = starting; ii < ending; ii++) | |
4260 { | |
4261 elt = KEY (key, content[ii]); | |
4262 | |
4263 for (jj = ii + 1; jj < ending; jj++) | |
4264 { | |
4265 if (check_test (test, key, elt, content[jj]) | |
4266 == test_not_unboundp) | |
4267 { | |
4268 set_bit_vector_bit (deleting, ii, 1); | |
4269 deleted++; | |
4270 break; | |
4271 } | |
4272 } | |
4273 } | |
4274 } | |
4275 else | |
4276 { | |
4277 for (ii = ending - 1; ii >= starting; ii--) | |
4278 { | |
4279 elt = KEY (key, content[ii]); | |
4280 | |
4281 for (jj = ii - 1; jj >= starting; jj--) | |
4282 { | |
4283 if (check_test (test, key, elt, content[jj]) | |
4284 == test_not_unboundp) | |
4285 { | |
4286 set_bit_vector_bit (deleting, ii, 1); | |
4287 deleted++; | |
4288 break; | |
4289 } | |
4290 } | |
4291 } | |
4292 } | |
4293 | |
4294 UNGCPRO; | |
4295 | |
4296 if (deleted) | |
4297 { | |
4298 Lisp_Object res = make_vector (len - deleted, Qnil), | |
4299 *res_content = XVECTOR_DATA (res); | |
4300 | |
4301 for (ii = jj = 0; ii < len; ii++) | |
4302 { | |
4303 if (!bit_vector_bit (deleting, ii)) | |
4304 { | |
4305 res_content[jj++] = content[ii]; | |
4306 } | |
4307 } | |
4308 | |
4309 sequence = res; | |
4310 } | |
4311 } | |
4312 else if (BIT_VECTORP (sequence)) | |
4313 { | |
4314 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence); | |
4315 Elemcount deleted = 0; | |
4316 /* I'm a little irritated at this. Basically, the only reasonable | |
4317 thing delete-duplicates should do if handed a bit vector is return | |
4318 something of maximum length two and minimum length 0 (because | |
4319 that's the possible number of distinct elements if EQ is regarded | |
4320 as identity, which it should be). But to support arbitrary TEST | |
4321 and KEY arguments, which may be non-deterministic from our | |
4322 perspective, we need the same algorithm as for vectors. */ | |
4323 struct Lisp_Bit_Vector *deleting; | |
4324 | |
4325 len = bit_vector_length (bv); | |
4326 | |
4327 if (EQ (Qidentity, key)) | |
4328 { | |
4329 /* We know all the elements will be bits; set check_test to | |
4330 reflect that. This isn't useful if KEY is not #'identity, since | |
4331 it may return non-bits for the elements. */ | |
4332 check_test = get_check_test_function (Qzero, &test, test_not, | |
4333 Qnil, Qnil, key, | |
4334 &test_not_unboundp); | |
4335 } | |
4336 | |
4337 check_sequence_range (sequence, start, end, make_integer (len)); | |
4338 | |
4339 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
4340 + (sizeof (long) | |
4341 * (BIT_VECTOR_LONG_STORAGE (len) | |
4342 - 1))); | |
4343 deleting->size = len; | |
4344 memset (&(deleting->bits), 0, | |
4345 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
4346 | |
4347 ending = min (ending, len); | |
4348 | |
4349 GCPRO1 (elt); | |
4350 | |
4351 if (NILP (from_end)) | |
4352 { | |
4353 for (ii = starting; ii < ending; ii++) | |
4354 { | |
4355 elt = KEY (key, make_int (bit_vector_bit (bv, ii))); | |
4356 | |
4357 for (jj = ii + 1; jj < ending; jj++) | |
4358 { | |
4359 if (check_test (test, key, elt, | |
4360 make_int (bit_vector_bit (bv, jj))) | |
4361 == test_not_unboundp) | |
4362 { | |
4363 set_bit_vector_bit (deleting, ii, 1); | |
4364 deleted++; | |
4365 break; | |
4366 } | |
4367 } | |
4368 } | |
4369 } | |
4370 else | |
4371 { | |
4372 for (ii = ending - 1; ii >= starting; ii--) | |
4373 { | |
4374 elt = KEY (key, make_int (bit_vector_bit (bv, ii))); | |
4375 | |
4376 for (jj = ii - 1; jj >= starting; jj--) | |
4377 { | |
4378 if (check_test (test, key, elt, | |
4379 make_int (bit_vector_bit (bv, jj))) | |
4380 == test_not_unboundp) | |
4381 { | |
4382 set_bit_vector_bit (deleting, ii, 1); | |
4383 deleted++; | |
4384 break; | |
4385 } | |
4386 } | |
4387 } | |
4388 } | |
4389 | |
4390 UNGCPRO; | |
4391 | |
4392 if (deleted) | |
4393 { | |
4394 Lisp_Object res = make_bit_vector (len - deleted, Qzero); | |
4395 Lisp_Bit_Vector *resbv = XBIT_VECTOR (res); | |
4396 | |
4397 for (ii = jj = 0; ii < len; ii++) | |
4398 { | |
4399 if (!bit_vector_bit (deleting, ii)) | |
4400 { | |
4401 set_bit_vector_bit (resbv, jj++, bit_vector_bit (bv, ii)); | |
4402 } | |
4403 } | |
4404 | |
4405 sequence = res; | |
4406 } | |
4407 } | |
4408 | |
4409 return sequence; | |
4410 } | |
4411 | |
4412 DEFUN ("remove-duplicates", Fremove_duplicates, 1, MANY, 0, /* | |
4413 Remove duplicate elements from SEQUENCE, non-destructively. | |
4414 | |
4415 If there are no duplicate elements in SEQUENCE, return it unmodified; | |
4416 otherwise, return a new object. If SEQUENCE is a list, the new object may | |
4417 share list structure with SEQUENCE. | |
4418 | |
4419 See `remove*' for the meaning of the keywords. | |
4420 | |
4421 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | |
4422 */ | |
4423 (int nargs, Lisp_Object *args)) | |
4424 { | |
4425 Lisp_Object sequence = args[0], tail = sequence, keyed, positioned = Qnil; | |
4426 Lisp_Object result = sequence, result_tail = result, cursor = Qnil; | |
4427 Lisp_Object cons_with_shared_tail = Qnil, elt, elt0; | |
4428 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0; | |
4429 Boolint test_not_unboundp = 1; | |
4430 check_test_func_t check_test = NULL; | |
4431 struct gcpro gcpro1, gcpro2, gcpro3; | |
4432 | |
4433 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6, | |
4434 (test, key, test_not, start, end, from_end), | |
4435 (start = Qzero)); | |
4436 | |
4437 CHECK_SEQUENCE (sequence); | |
4438 | |
4439 if (!CONSP (sequence)) | |
4440 { | |
4441 return Fdelete_duplicates (nargs, args); | |
4442 } | |
4443 | |
4444 CHECK_NATNUM (start); | |
4445 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
4446 | |
4447 if (!NILP (end)) | |
4448 { | |
4449 CHECK_NATNUM (end); | |
4450 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
4451 } | |
4452 | |
4453 if (NILP (key)) | |
4454 { | |
4455 key = Qidentity; | |
4456 } | |
4457 | |
4458 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
4459 &test_not_unboundp, &check_test); | |
4460 | |
4461 if (NILP (from_end)) | |
4462 { | |
4463 Lisp_Object ignore = Qnil; | |
4464 | |
4465 GCPRO3 (tail, keyed, result); | |
4466 | |
4467 { | |
4468 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
4469 { | |
4470 if (starting <= ii && ii <= ending) | |
4471 { | |
4472 keyed = KEY (key, elt); | |
4473 positioned | |
4474 = list_position_cons_before (&ignore, keyed, XCDR (tail), | |
4475 check_test, test_not_unboundp, | |
4476 test, key, 0, | |
4477 make_int (max (starting | |
4478 - (ii + 1), 0)), | |
4479 make_int (ending - (ii + 1))); | |
4480 if (!NILP (positioned)) | |
4481 { | |
4482 sequence = result = result_tail = XCDR (tail); | |
4483 } | |
4484 else | |
4485 { | |
4486 break; | |
4487 } | |
4488 } | |
4489 else | |
4490 { | |
4491 break; | |
4492 } | |
4493 | |
4494 ii++; | |
4495 } | |
4496 } | |
4497 | |
4498 { | |
4499 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) | |
4500 { | |
4501 if (!(starting <= ii && ii <= ending)) | |
4502 { | |
4503 ii++; | |
4504 continue; | |
4505 } | |
4506 | |
4507 /* For this algorithm, each time we encounter an object to be | |
4508 removed, copy the output list from the tail beyond the last | |
4509 removed cons to this one. Otherwise, the tail of the output list | |
4510 is shared with the input list, which is OK. */ | |
4511 | |
4512 keyed = KEY (key, elt0); | |
4513 positioned | |
4514 = list_position_cons_before (&ignore, keyed, XCDR (tail), | |
4515 check_test, test_not_unboundp, | |
4516 test, key, 0, | |
4517 make_int (max (starting - (ii + 1), | |
4518 0)), | |
4519 make_int (ending - (ii + 1))); | |
4520 if (!NILP (positioned)) | |
4521 { | |
4522 if (EQ (result, sequence)) | |
4523 { | |
4524 result = cons_with_shared_tail | |
4525 = Fcons (XCAR (sequence), XCDR (sequence)); | |
4526 } | |
4527 | |
4528 result_tail = cons_with_shared_tail; | |
4529 cursor = XCDR (cons_with_shared_tail); | |
4530 | |
4531 while (!EQ (cursor, tail) && !NILP (cursor)) | |
4532 { | |
4533 XSETCDR (result_tail, Fcons (XCAR (cursor), Qnil)); | |
4534 result_tail = XCDR (result_tail); | |
4535 cursor = XCDR (cursor); | |
4536 } | |
4537 | |
4538 XSETCDR (result_tail, XCDR (tail)); | |
4539 cons_with_shared_tail = result_tail; | |
4540 } | |
4541 | |
4542 ii++; | |
4543 } | |
4544 } | |
4545 UNGCPRO; | |
4546 | |
4547 if ((ii < starting || (ii < ending && !NILP (end)))) | |
4548 { | |
4549 check_sequence_range (args[0], start, end, Flength (args[0])); | |
4550 } | |
4551 } | |
4552 else | |
4553 { | |
4554 result = list_delete_duplicates_from_end (sequence, check_test, | |
4555 test_not_unboundp, test, key, | |
4556 start, end, 1); | |
4557 } | |
4558 | |
4559 return result; | |
4560 } | |
4561 #undef KEY | |
4562 | |
2092 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* | 4563 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* |
2093 Reverse SEQUENCE, destructively. | 4564 Reverse SEQUENCE, destructively. |
2094 | 4565 |
2095 Return the beginning of the reversed sequence, which will be a distinct Lisp | 4566 Return the beginning of the reversed sequence, which will be a distinct Lisp |
2096 object if SEQUENCE is a list with length greater than one. See also | 4567 object if SEQUENCE is a list with length greater than one. See also |
2710 for (counter = 0; counter < len; ++counter) \ | 5181 for (counter = 0; counter < len; ++counter) \ |
2711 { \ | 5182 { \ |
2712 c_array[counter] = make_int (bit_vector_bit (v, counter)); \ | 5183 c_array[counter] = make_int (bit_vector_bit (v, counter)); \ |
2713 } \ | 5184 } \ |
2714 } while (0) | 5185 } while (0) |
2715 | |
2716 /* This macro might eventually find a better home than here. */ | |
2717 | |
2718 #define CHECK_KEY_ARGUMENT(key) \ | |
2719 do { \ | |
2720 if (NILP (key)) \ | |
2721 { \ | |
2722 key = Qidentity; \ | |
2723 } \ | |
2724 \ | |
2725 if (!EQ (key, Qidentity)) \ | |
2726 { \ | |
2727 key = indirect_function (key, 1); \ | |
2728 } \ | |
2729 } while (0) | |
2730 | 5186 |
2731 DEFUN ("merge", Fmerge, 4, MANY, 0, /* | 5187 DEFUN ("merge", Fmerge, 4, MANY, 0, /* |
2732 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence. | 5188 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence. |
2733 | 5189 |
2734 TYPE is the type of sequence to return. PREDICATE is a `less-than' | 5190 TYPE is the type of sequence to return. PREDICATE is a `less-than' |
3940 } | 6396 } |
3941 | 6397 |
3942 int | 6398 int |
3943 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 6399 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
3944 { | 6400 { |
3945 if (depth > 200) | 6401 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
3946 stack_overflow ("Stack overflow in equal", Qunbound); | 6402 stack_overflow ("Stack overflow in equal", Qunbound); |
3947 QUIT; | 6403 QUIT; |
3948 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2)) | 6404 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2)) |
3949 return 1; | 6405 return 1; |
3950 /* Note that (equal 20 20.0) should be nil */ | 6406 /* Note that (equal 20 20.0) should be nil */ |
3985 } | 6441 } |
3986 | 6442 |
3987 int | 6443 int |
3988 internal_equalp (Lisp_Object obj1, Lisp_Object obj2, int depth) | 6444 internal_equalp (Lisp_Object obj1, Lisp_Object obj2, int depth) |
3989 { | 6445 { |
3990 if (depth > 200) | 6446 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
3991 stack_overflow ("Stack overflow in equalp", Qunbound); | 6447 stack_overflow ("Stack overflow in equalp", Qunbound); |
3992 QUIT; | 6448 QUIT; |
3993 | 6449 |
3994 /* 1. Objects that are `eq' are equal. This will catch the common case | 6450 /* 1. Objects that are `eq' are equal. This will catch the common case |
3995 of two equal fixnums or the same object seen twice. */ | 6451 of two equal fixnums or the same object seen twice. */ |
4061 but that seems unlikely. */ | 6517 but that seems unlikely. */ |
4062 | 6518 |
4063 static int | 6519 static int |
4064 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 6520 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
4065 { | 6521 { |
4066 if (depth > 200) | 6522 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
4067 stack_overflow ("Stack overflow in equal", Qunbound); | 6523 stack_overflow ("Stack overflow in equal", Qunbound); |
4068 QUIT; | 6524 QUIT; |
4069 if (HACKEQ_UNSAFE (obj1, obj2)) | 6525 if (HACKEQ_UNSAFE (obj1, obj2)) |
4070 return 1; | 6526 return 1; |
4071 /* Note that (equal 20 20.0) should be nil */ | 6527 /* Note that (equal 20 20.0) should be nil */ |
4227 } | 6683 } |
4228 else if (LISTP (sequence)) | 6684 else if (LISTP (sequence)) |
4229 { | 6685 { |
4230 Elemcount counting = 0; | 6686 Elemcount counting = 0; |
4231 | 6687 |
4232 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) | 6688 { |
4233 { | 6689 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
4234 if (counting >= starting) | 6690 { |
4235 { | 6691 if (counting >= starting) |
4236 if (counting < ending) | 6692 { |
4237 { | 6693 if (counting < ending) |
4238 XSETCAR (tail, item); | 6694 { |
4239 } | 6695 XSETCAR (tail, item); |
4240 else if (counting == ending) | 6696 } |
4241 { | 6697 else if (counting == ending) |
4242 break; | 6698 { |
4243 } | 6699 break; |
4244 } | 6700 } |
4245 ++counting; | 6701 } |
4246 } | 6702 ++counting; |
6703 } | |
6704 } | |
4247 | 6705 |
4248 if (counting < starting || (counting != ending && !NILP (end))) | 6706 if (counting < starting || (counting != ending && !NILP (end))) |
4249 { | 6707 { |
4250 check_sequence_range (args[0], start, end, Flength (args[0])); | 6708 check_sequence_range (args[0], start, end, Flength (args[0])); |
4251 } | 6709 } |
6075 { | 8533 { |
6076 Ibyte *p2 = XSTRING_DATA (sequence2), | 8534 Ibyte *p2 = XSTRING_DATA (sequence2), |
6077 *p2end = p2 + XSTRING_LENGTH (sequence2), *p2cursor; | 8535 *p2end = p2 + XSTRING_LENGTH (sequence2), *p2cursor; |
6078 Charcount ii = 0, len1 = string_char_length (sequence1); | 8536 Charcount ii = 0, len1 = string_char_length (sequence1); |
6079 | 8537 |
8538 check_sequence_range (sequence1, start1, end1, make_int (len1)); | |
8539 | |
6080 while (ii < starting2 && p2 < p2end) | 8540 while (ii < starting2 && p2 < p2end) |
6081 { | 8541 { |
6082 INC_IBYTEPTR (p2); | 8542 INC_IBYTEPTR (p2); |
6083 ii++; | 8543 ii++; |
6084 } | 8544 } |
6184 } | 8644 } |
6185 | 8645 |
6186 return result; | 8646 return result; |
6187 } | 8647 } |
6188 | 8648 |
8649 DEFUN ("nsubstitute", Fnsubstitute, 3, MANY, 0, /* | |
8650 Substitute NEW for OLD in SEQUENCE. | |
8651 | |
8652 This is a destructive function; it reuses the storage of SEQUENCE whenever | |
8653 possible. See `remove*' for the meaning of the keywords. | |
8654 | |
8655 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT) | |
8656 */ | |
8657 (int nargs, Lisp_Object *args)) | |
8658 { | |
8659 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; | |
8660 Lisp_Object object_, position0; | |
8661 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | |
8662 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; | |
8663 Boolint test_not_unboundp = 1; | |
8664 check_test_func_t check_test = NULL; | |
8665 struct gcpro gcpro1; | |
8666 | |
8667 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9, | |
8668 (test, if_, if_not, test_not, key, start, end, count, | |
8669 from_end), (start = Qzero)); | |
8670 | |
8671 CHECK_SEQUENCE (sequence); | |
8672 CHECK_NATNUM (start); | |
8673 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
8674 | |
8675 if (!NILP (end)) | |
8676 { | |
8677 CHECK_NATNUM (end); | |
8678 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
8679 } | |
8680 | |
8681 if (!NILP (count)) | |
8682 { | |
8683 CHECK_INTEGER (count); | |
8684 if (INTP (count)) | |
8685 { | |
8686 counting = XINT (count); | |
8687 } | |
8688 #ifdef HAVE_BIGNUM | |
8689 else | |
8690 { | |
8691 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
8692 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN; | |
8693 } | |
8694 #endif | |
8695 | |
8696 if (counting <= 0) | |
8697 { | |
8698 return sequence; | |
8699 } | |
8700 } | |
8701 | |
8702 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
8703 key, &test_not_unboundp); | |
8704 | |
8705 if (CONSP (sequence)) | |
8706 { | |
8707 Lisp_Object elt; | |
8708 | |
8709 if (!NILP (count) && !NILP (from_end)) | |
8710 { | |
8711 Lisp_Object present = count_with_tail (&elt, nargs - 1, args + 1, | |
8712 Qnsubstitute); | |
8713 | |
8714 if (ZEROP (present)) | |
8715 { | |
8716 return sequence; | |
8717 } | |
8718 | |
8719 presenting = XINT (present); | |
8720 presenting = presenting <= counting ? 0 : presenting - counting; | |
8721 } | |
8722 | |
8723 GCPRO1 (tail); | |
8724 { | |
8725 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
8726 { | |
8727 if (!(ii < ending)) | |
8728 { | |
8729 break; | |
8730 } | |
8731 | |
8732 if (starting <= ii && | |
8733 check_test (test, key, item, elt) == test_not_unboundp | |
8734 && (presenting ? encountered++ >= presenting | |
8735 : encountered++ < counting)) | |
8736 { | |
8737 CHECK_LISP_WRITEABLE (tail); | |
8738 XSETCAR (tail, new_); | |
8739 } | |
8740 else if (!presenting && encountered >= counting) | |
8741 { | |
8742 break; | |
8743 } | |
8744 | |
8745 ii++; | |
8746 } | |
8747 } | |
8748 UNGCPRO; | |
8749 | |
8750 if ((ii < starting || (ii < ending && !NILP (end))) | |
8751 && encountered < counting) | |
8752 { | |
8753 check_sequence_range (args[0], start, end, Flength (args[0])); | |
8754 } | |
8755 } | |
8756 else if (STRINGP (sequence)) | |
8757 { | |
8758 Ibyte *staging, new_bytes[MAX_ICHAR_LEN], *staging_cursor; | |
8759 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp; | |
8760 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence); | |
8761 Bytecount new_len; | |
8762 Lisp_Object character; | |
8763 | |
8764 CHECK_CHAR_COERCE_INT (new_); | |
8765 | |
8766 new_len = set_itext_ichar (new_bytes, XCHAR (new_)); | |
8767 | |
8768 /* Worst case scenario; new char is four octets long, all the old ones | |
8769 were one octet long, all the old ones match. */ | |
8770 staging = alloca_ibytes (XSTRING_LENGTH (sequence) * new_len); | |
8771 staging_cursor = staging; | |
8772 | |
8773 if (!NILP (count) && !NILP (from_end)) | |
8774 { | |
8775 Lisp_Object present = count_with_tail (&character, nargs - 1, | |
8776 args + 1, Qnsubstitute); | |
8777 | |
8778 if (ZEROP (present)) | |
8779 { | |
8780 return sequence; | |
8781 } | |
8782 | |
8783 presenting = XINT (present); | |
8784 | |
8785 /* If there are fewer items in the string than we have | |
8786 permission to change, we don't need to differentiate | |
8787 between the :from-end nil and :from-end t | |
8788 cases. Otherwise, presenting is the number of matching | |
8789 items we need to ignore before we start to change. */ | |
8790 presenting = presenting <= counting ? 0 : presenting - counting; | |
8791 } | |
8792 | |
8793 ii = 0; | |
8794 while (cursor_offset < byte_len && ii < ending) | |
8795 { | |
8796 if (ii >= starting) | |
8797 { | |
8798 character = make_char (itext_ichar (cursor)); | |
8799 | |
8800 if ((check_test (test, key, item, character) | |
8801 == test_not_unboundp) | |
8802 && (presenting ? encountered++ >= presenting : | |
8803 encountered++ < counting)) | |
8804 { | |
8805 staging_cursor | |
8806 += itext_copy_ichar (new_bytes, staging_cursor); | |
8807 } | |
8808 else | |
8809 { | |
8810 staging_cursor | |
8811 += itext_copy_ichar (cursor, staging_cursor); | |
8812 } | |
8813 | |
8814 startp = XSTRING_DATA (sequence); | |
8815 cursor = startp + cursor_offset; | |
8816 | |
8817 if (byte_len != XSTRING_LENGTH (sequence) | |
8818 || !valid_ibyteptr_p (cursor)) | |
8819 { | |
8820 mapping_interaction_error (Qnsubstitute, sequence); | |
8821 } | |
8822 } | |
8823 else | |
8824 { | |
8825 staging_cursor += itext_copy_ichar (cursor, staging_cursor); | |
8826 } | |
8827 | |
8828 INC_IBYTEPTR (cursor); | |
8829 cursor_offset = cursor - startp; | |
8830 ii++; | |
8831 } | |
8832 | |
8833 if (ii < starting || (ii < ending && !NILP (end))) | |
8834 { | |
8835 check_sequence_range (sequence, start, end, Flength (sequence)); | |
8836 } | |
8837 | |
8838 if (0 != encountered) | |
8839 { | |
8840 CHECK_LISP_WRITEABLE (sequence); | |
8841 replace_string_range (sequence, Qzero, make_int (ii), | |
8842 staging, staging_cursor); | |
8843 } | |
8844 } | |
8845 else | |
8846 { | |
8847 Elemcount positioning; | |
8848 Lisp_Object object = Qnil; | |
8849 | |
8850 len = XINT (Flength (sequence)); | |
8851 check_sequence_range (sequence, start, end, make_int (len)); | |
8852 | |
8853 position0 = position (&object, item, sequence, check_test, | |
8854 test_not_unboundp, test, key, start, end, from_end, | |
8855 Qnil, Qnsubstitute); | |
8856 | |
8857 if (NILP (position0)) | |
8858 { | |
8859 return sequence; | |
8860 } | |
8861 | |
8862 positioning = XINT (position0); | |
8863 ending = min (len, ending); | |
8864 | |
8865 Faset (sequence, position0, new_); | |
8866 encountered = 1; | |
8867 | |
8868 if (NILP (from_end)) | |
8869 { | |
8870 for (ii = positioning + 1; ii < ending; ii++) | |
8871 { | |
8872 object_ = Faref (sequence, make_int (ii)); | |
8873 | |
8874 if (check_test (test, key, item, object_) == test_not_unboundp | |
8875 && encountered++ < counting) | |
8876 { | |
8877 Faset (sequence, make_int (ii), new_); | |
8878 } | |
8879 else if (encountered == counting) | |
8880 { | |
8881 break; | |
8882 } | |
8883 } | |
8884 } | |
8885 else | |
8886 { | |
8887 for (ii = positioning - 1; ii >= starting; ii--) | |
8888 { | |
8889 object_ = Faref (sequence, make_int (ii)); | |
8890 | |
8891 if (check_test (test, key, item, object_) == test_not_unboundp | |
8892 && encountered++ < counting) | |
8893 { | |
8894 Faset (sequence, make_int (ii), new_); | |
8895 } | |
8896 else if (encountered == counting) | |
8897 { | |
8898 break; | |
8899 } | |
8900 } | |
8901 } | |
8902 } | |
8903 | |
8904 return sequence; | |
8905 } | |
8906 | |
8907 DEFUN ("substitute", Fsubstitute, 3, MANY, 0, /* | |
8908 Substitute NEW for OLD in SEQUENCE. | |
8909 | |
8910 This is a non-destructive function; it makes a copy of SEQUENCE if necessary | |
8911 to avoid corrupting the original SEQUENCE. | |
8912 | |
8913 See `remove*' for the meaning of the keywords. | |
8914 | |
8915 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT) | |
8916 */ | |
8917 (int nargs, Lisp_Object *args)) | |
8918 { | |
8919 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; | |
8920 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; | |
8921 Lisp_Object object, position0, matched_count; | |
8922 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | |
8923 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; | |
8924 Boolint test_not_unboundp = 1; | |
8925 check_test_func_t check_test = NULL; | |
8926 struct gcpro gcpro1; | |
8927 | |
8928 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9, | |
8929 (test, if_, if_not, test_not, key, start, end, count, | |
8930 from_end), (start = Qzero, count = Qunbound)); | |
8931 | |
8932 CHECK_SEQUENCE (sequence); | |
8933 | |
8934 CHECK_NATNUM (start); | |
8935 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
8936 | |
8937 if (!NILP (end)) | |
8938 { | |
8939 CHECK_NATNUM (end); | |
8940 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
8941 } | |
8942 | |
8943 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
8944 key, &test_not_unboundp); | |
8945 | |
8946 if (!UNBOUNDP (count)) | |
8947 { | |
8948 if (!NILP (count)) | |
8949 { | |
8950 CHECK_INTEGER (count); | |
8951 if (INTP (count)) | |
8952 { | |
8953 counting = XINT (count); | |
8954 } | |
8955 #ifdef HAVE_BIGNUM | |
8956 else | |
8957 { | |
8958 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
8959 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN; | |
8960 } | |
8961 #endif | |
8962 | |
8963 if (counting <= 0) | |
8964 { | |
8965 return sequence; | |
8966 } | |
8967 } | |
8968 } | |
8969 | |
8970 if (!CONSP (sequence)) | |
8971 { | |
8972 position0 = position (&object, item, sequence, check_test, | |
8973 test_not_unboundp, test, key, start, end, from_end, | |
8974 Qnil, Qsubstitute); | |
8975 | |
8976 if (NILP (position0)) | |
8977 { | |
8978 return sequence; | |
8979 } | |
8980 else | |
8981 { | |
8982 args[2] = Fcopy_sequence (sequence); | |
8983 return Fnsubstitute (nargs, args); | |
8984 } | |
8985 } | |
8986 | |
8987 matched_count = count_with_tail (&tail, nargs - 1, args + 1, Qsubstitute); | |
8988 | |
8989 if (ZEROP (matched_count)) | |
8990 { | |
8991 return sequence; | |
8992 } | |
8993 | |
8994 if (!NILP (count) && !NILP (from_end)) | |
8995 { | |
8996 presenting = XINT (matched_count); | |
8997 presenting = presenting <= counting ? 0 : presenting - counting; | |
8998 } | |
8999 | |
9000 GCPRO1 (tailing); | |
9001 { | |
9002 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) | |
9003 { | |
9004 if (EQ (tail, tailing)) | |
9005 { | |
9006 if (NILP (result)) | |
9007 { | |
9008 RETURN_UNGCPRO (XCDR (tail)); | |
9009 } | |
9010 | |
9011 XSETCDR (result_tail, XCDR (tail)); | |
9012 RETURN_UNGCPRO (result); | |
9013 } | |
9014 else if (starting <= ii && ii < ending && | |
9015 (check_test (test, key, item, elt) == test_not_unboundp) | |
9016 && (presenting ? encountered++ >= presenting | |
9017 : encountered++ < counting)) | |
9018 { | |
9019 if (NILP (result)) | |
9020 { | |
9021 result = result_tail = Fcons (new_, Qnil); | |
9022 } | |
9023 else | |
9024 { | |
9025 XSETCDR (result_tail, Fcons (new_, Qnil)); | |
9026 result_tail = XCDR (result_tail); | |
9027 } | |
9028 } | |
9029 else if (NILP (result)) | |
9030 { | |
9031 result = result_tail = Fcons (elt, Qnil); | |
9032 } | |
9033 else | |
9034 { | |
9035 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
9036 result_tail = XCDR (result_tail); | |
9037 } | |
9038 | |
9039 if (ii == ending) | |
9040 { | |
9041 break; | |
9042 } | |
9043 | |
9044 ii++; | |
9045 } | |
9046 } | |
9047 UNGCPRO; | |
9048 | |
9049 if (ii < starting || (ii < ending && !NILP (end))) | |
9050 { | |
9051 check_sequence_range (args[0], start, end, Flength (args[0])); | |
9052 } | |
9053 | |
9054 return result; | |
9055 } | |
9056 | |
9057 static Lisp_Object | |
9058 subst (Lisp_Object new_, Lisp_Object old, Lisp_Object tree, int depth) | |
9059 { | |
9060 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9061 { | |
9062 stack_overflow ("Stack overflow in subst", tree); | |
9063 } | |
9064 | |
9065 if (EQ (tree, old)) | |
9066 { | |
9067 return new_; | |
9068 } | |
9069 else if (CONSP (tree)) | |
9070 { | |
9071 Lisp_Object aa = subst (new_, old, XCAR (tree), depth + 1); | |
9072 Lisp_Object dd = subst (new_, old, XCDR (tree), depth + 1); | |
9073 | |
9074 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree))) | |
9075 { | |
9076 return tree; | |
9077 } | |
9078 else | |
9079 { | |
9080 return Fcons (aa, dd); | |
9081 } | |
9082 } | |
9083 else | |
9084 { | |
9085 return tree; | |
9086 } | |
9087 } | |
9088 | |
9089 static Lisp_Object | |
9090 sublis (Lisp_Object alist, Lisp_Object tree, | |
9091 check_test_func_t check_test, Boolint test_not_unboundp, | |
9092 Lisp_Object test, Lisp_Object key, int depth) | |
9093 { | |
9094 Lisp_Object keyed = KEY (key, tree), tailed = alist, aa, dd; | |
9095 struct gcpro gcpro1, gcpro2, gcpro3; | |
9096 | |
9097 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9098 { | |
9099 stack_overflow ("Stack overflow in sublis", tree); | |
9100 } | |
9101 | |
9102 GCPRO3 (tailed, alist, tree); | |
9103 { | |
9104 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9105 { | |
9106 tailed = tail; | |
9107 | |
9108 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9109 { | |
9110 /* Don't use elt_cdr, it is helpful to allow TEST or KEY to | |
9111 modify the alist while it executes. */ | |
9112 RETURN_UNGCPRO (XCDR (elt)); | |
9113 } | |
9114 } | |
9115 } | |
9116 if (!CONSP (tree)) | |
9117 { | |
9118 RETURN_UNGCPRO (tree); | |
9119 } | |
9120 | |
9121 aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key, | |
9122 depth + 1); | |
9123 dd = sublis (alist, XCDR (tree), check_test, test_not_unboundp, test, key, | |
9124 depth + 1); | |
9125 | |
9126 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree))) | |
9127 { | |
9128 RETURN_UNGCPRO (tree); | |
9129 } | |
9130 | |
9131 RETURN_UNGCPRO (Fcons (aa, dd)); | |
9132 } | |
9133 | |
9134 DEFUN ("sublis", Fsublis, 2, MANY, 0, /* | |
9135 Perform substitutions indicated by ALIST in TREE (non-destructively). | |
9136 Return a copy of TREE with all matching elements replaced. | |
9137 | |
9138 See `member*' for the meaning of :test, :test-not and :key. | |
9139 | |
9140 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9141 */ | |
9142 (int nargs, Lisp_Object *args)) | |
9143 { | |
9144 Lisp_Object alist = args[0], tree = args[1]; | |
9145 Boolint test_not_unboundp = 1; | |
9146 check_test_func_t check_test = NULL; | |
9147 | |
9148 PARSE_KEYWORDS (Fsublis, nargs, args, 5, (test, if_, test_not, if_not, key), | |
9149 (key = Qidentity)); | |
9150 | |
9151 if (NILP (key)) | |
9152 { | |
9153 key = Qidentity; | |
9154 } | |
9155 | |
9156 get_check_match_function (&test, test_not, if_, if_not, | |
9157 /* sublis() is going to apply the key, don't ask | |
9158 for a match function that will do it for | |
9159 us. */ | |
9160 Qidentity, &test_not_unboundp, &check_test); | |
9161 | |
9162 if (CONSP (alist) && NILP (XCDR (alist)) && CONSP (XCAR (alist)) | |
9163 && EQ (key, Qidentity) && 1 == test_not_unboundp | |
9164 && (check_eq_nokey == check_test || | |
9165 (check_eql_nokey == check_test && | |
9166 !NON_FIXNUM_NUMBER_P (XCAR (XCAR (alist)))))) | |
9167 { | |
9168 /* #'subst with #'eq is very cheap indeed; call it. */ | |
9169 return subst (XCDR (XCAR (alist)), XCAR (XCAR (alist)), tree, 0); | |
9170 } | |
9171 | |
9172 return sublis (alist, tree, check_test, test_not_unboundp, test, key, 0); | |
9173 } | |
9174 | |
9175 static Lisp_Object | |
9176 nsublis (Lisp_Object alist, Lisp_Object tree, | |
9177 check_test_func_t check_test, | |
9178 Boolint test_not_unboundp, | |
9179 Lisp_Object test, Lisp_Object key, int depth) | |
9180 { | |
9181 Lisp_Object tree_saved = tree, tailed = alist, tortoise = tree, keyed = Qnil; | |
9182 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
9183 int count = 0; | |
9184 | |
9185 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9186 { | |
9187 stack_overflow ("Stack overflow in nsublis", tree); | |
9188 } | |
9189 | |
9190 GCPRO4 (tailed, alist, tree_saved, keyed); | |
9191 | |
9192 while (CONSP (tree)) | |
9193 { | |
9194 Boolint replaced = 0; | |
9195 keyed = KEY (key, XCAR (tree)); | |
9196 | |
9197 { | |
9198 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9199 { | |
9200 tailed = tail; | |
9201 | |
9202 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9203 { | |
9204 CHECK_LISP_WRITEABLE (tree); | |
9205 /* See comment in sublis() on using elt_cdr. */ | |
9206 XSETCAR (tree, XCDR (elt)); | |
9207 replaced = 1; | |
9208 break; | |
9209 } | |
9210 } | |
9211 } | |
9212 | |
9213 if (!replaced) | |
9214 { | |
9215 if (CONSP (XCAR (tree))) | |
9216 { | |
9217 nsublis (alist, XCAR (tree), check_test, test_not_unboundp, | |
9218 test, key, depth + 1); | |
9219 } | |
9220 } | |
9221 | |
9222 keyed = KEY (key, XCDR (tree)); | |
9223 replaced = 0; | |
9224 | |
9225 { | |
9226 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9227 { | |
9228 tailed = tail; | |
9229 | |
9230 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9231 { | |
9232 CHECK_LISP_WRITEABLE (tree); | |
9233 /* See comment in sublis() on using elt_cdr. */ | |
9234 XSETCDR (tree, XCDR (elt)); | |
9235 tree = Qnil; | |
9236 break; | |
9237 } | |
9238 } | |
9239 } | |
9240 | |
9241 if (!NILP (tree)) | |
9242 { | |
9243 tree = XCDR (tree); | |
9244 } | |
9245 | |
9246 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH) | |
9247 { | |
9248 if (count & 1) | |
9249 { | |
9250 tortoise = XCDR (tortoise); | |
9251 } | |
9252 | |
9253 if (EQ (tortoise, tree)) | |
9254 { | |
9255 signal_circular_list_error (tree); | |
9256 } | |
9257 } | |
9258 } | |
9259 | |
9260 RETURN_UNGCPRO (tree_saved); | |
9261 } | |
9262 | |
9263 DEFUN ("nsublis", Fnsublis, 2, MANY, 0, /* | |
9264 Perform substitutions indicated by ALIST in TREE (destructively). | |
9265 Any matching element of TREE is changed via a call to `setcar'. | |
9266 | |
9267 See `member*' for the meaning of :test, :test-not and :key. | |
9268 | |
9269 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9270 */ | |
9271 (int nargs, Lisp_Object *args)) | |
9272 { | |
9273 Lisp_Object alist = args[0], tree = args[1], tailed = Qnil, keyed = Qnil; | |
9274 Boolint test_not_unboundp = 1; | |
9275 check_test_func_t check_test = NULL; | |
9276 struct gcpro gcpro1, gcpro2; | |
9277 | |
9278 PARSE_KEYWORDS (Fnsublis, nargs, args, 5, (test, if_, test_not, if_not, key), | |
9279 (key = Qidentity)); | |
9280 | |
9281 if (NILP (key)) | |
9282 { | |
9283 key = Qidentity; | |
9284 } | |
9285 | |
9286 get_check_match_function (&test, test_not, if_, if_not, | |
9287 /* nsublis() is going to apply the key, don't ask | |
9288 for a match function that will do it for | |
9289 us. */ | |
9290 Qidentity, &test_not_unboundp, &check_test); | |
9291 | |
9292 GCPRO2 (tailed, keyed); | |
9293 | |
9294 keyed = KEY (key, tree); | |
9295 | |
9296 { | |
9297 /* nsublis() won't attempt to replace a cons handed to it, do that | |
9298 ourselves. */ | |
9299 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9300 { | |
9301 tailed = tail; | |
9302 | |
9303 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9304 { | |
9305 /* See comment in sublis() on using elt_cdr. */ | |
9306 RETURN_UNGCPRO (XCDR (elt)); | |
9307 } | |
9308 } | |
9309 } | |
9310 | |
9311 UNGCPRO; | |
9312 | |
9313 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0); | |
9314 } | |
9315 | |
9316 DEFUN ("subst", Fsubst, 3, MANY, 0, /* | |
9317 Substitute NEW for OLD everywhere in TREE (non-destructively). | |
9318 | |
9319 Return a copy of TREE with all elements `eql' to OLD replaced by NEW. | |
9320 | |
9321 See `member*' for the meaning of :test, :test-not and :key. | |
9322 | |
9323 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9324 */ | |
9325 (int nargs, Lisp_Object *args)) | |
9326 { | |
9327 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]), | |
9328 Qnil); | |
9329 args[1] = alist; | |
9330 result = Fsublis (nargs - 1, args + 1); | |
9331 free_cons (XCAR (alist)); | |
9332 free_cons (alist); | |
9333 | |
9334 return result; | |
9335 } | |
9336 | |
9337 DEFUN ("nsubst", Fnsubst, 3, MANY, 0, /* | |
9338 Substitute NEW for OLD everywhere in TREE (destructively). | |
9339 | |
9340 Any element of TREE which is `eql' to OLD is changed to NEW (via a call to | |
9341 `setcar'). | |
9342 | |
9343 See `member*' for the meaning of the keywords. | |
9344 | |
9345 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9346 */ | |
9347 (int nargs, Lisp_Object *args)) | |
9348 { | |
9349 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]), | |
9350 Qnil); | |
9351 args[1] = alist; | |
9352 result = Fnsublis (nargs - 1, args + 1); | |
9353 free_cons (XCAR (alist)); | |
9354 free_cons (alist); | |
9355 | |
9356 return result; | |
9357 } | |
9358 | |
9359 static Boolint | |
9360 tree_equal (Lisp_Object tree1, Lisp_Object tree2, | |
9361 check_test_func_t check_test, Boolint test_not_unboundp, | |
9362 Lisp_Object test, Lisp_Object key, int depth) | |
9363 { | |
9364 Lisp_Object tortoise1 = tree1, tortoise2 = tree2; | |
9365 struct gcpro gcpro1, gcpro2; | |
9366 int count = 0; | |
9367 Boolint result; | |
9368 | |
9369 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9370 { | |
9371 stack_overflow ("Stack overflow in tree-equal", tree1); | |
9372 } | |
9373 | |
9374 GCPRO2 (tree1, tree2); | |
9375 | |
9376 while (CONSP (tree1) && CONSP (tree2) | |
9377 && tree_equal (XCAR (tree1), XCAR (tree2), check_test, | |
9378 test_not_unboundp, test, key, depth + 1)) | |
9379 { | |
9380 tree1 = XCDR (tree1); | |
9381 tree2 = XCDR (tree2); | |
9382 | |
9383 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH) | |
9384 { | |
9385 if (count & 1) | |
9386 { | |
9387 tortoise1 = XCDR (tortoise1); | |
9388 tortoise2 = XCDR (tortoise2); | |
9389 } | |
9390 | |
9391 if (EQ (tortoise1, tree1)) | |
9392 { | |
9393 signal_circular_list_error (tree1); | |
9394 } | |
9395 | |
9396 if (EQ (tortoise2, tree2)) | |
9397 { | |
9398 signal_circular_list_error (tree2); | |
9399 } | |
9400 } | |
9401 } | |
9402 | |
9403 if (CONSP (tree1) || CONSP (tree2)) | |
9404 { | |
9405 UNGCPRO; | |
9406 return 0; | |
9407 } | |
9408 | |
9409 result = check_test (test, key, tree1, tree2) == test_not_unboundp; | |
9410 UNGCPRO; | |
9411 | |
9412 return result; | |
9413 } | |
9414 | |
9415 DEFUN ("tree-equal", Ftree_equal, 2, MANY, 0, /* | |
9416 Return t if TREE1 and TREE2 have `eql' leaves. | |
9417 | |
9418 Atoms are compared by `eql', unless another test is specified using | |
9419 :test; cons cells are compared recursively. | |
9420 | |
9421 See `union' for the meaning of :test, :test-not and :key. | |
9422 | |
9423 arguments: (TREE1 TREE2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9424 */ | |
9425 (int nargs, Lisp_Object *args)) | |
9426 { | |
9427 Lisp_Object tree1 = args[0], tree2 = args[1]; | |
9428 Boolint test_not_unboundp = 1; | |
9429 check_test_func_t check_test = NULL; | |
9430 | |
9431 PARSE_KEYWORDS (Ftree_equal, nargs, args, 3, (test, key, test_not), | |
9432 (key = Qidentity)); | |
9433 | |
9434 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
9435 &test_not_unboundp, &check_test); | |
9436 | |
9437 return tree_equal (tree1, tree2, check_test, test_not_unboundp, test, key, | |
9438 0) ? Qt : Qnil; | |
9439 } | |
9440 | |
9441 static Lisp_Object | |
9442 mismatch_from_end (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1, | |
9443 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2, | |
9444 check_test_func_t check_match, Boolint test_not_unboundp, | |
9445 Lisp_Object test, Lisp_Object key, | |
9446 Boolint UNUSED (return_sequence1_index)) | |
9447 { | |
9448 Elemcount sequence1_len = XINT (Flength (sequence1)); | |
9449 Elemcount sequence2_len = XINT (Flength (sequence2)), ii = 0; | |
9450 Elemcount starting1, ending1, starting2, ending2; | |
9451 Lisp_Object *sequence1_storage = NULL, *sequence2_storage = NULL; | |
9452 struct gcpro gcpro1, gcpro2; | |
9453 | |
9454 check_sequence_range (sequence1, start1, end1, make_int (sequence1_len)); | |
9455 starting1 = XINT (start1); | |
9456 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX; | |
9457 ending1 = min (ending1, sequence1_len); | |
9458 | |
9459 check_sequence_range (sequence2, start2, end2, make_int (sequence2_len)); | |
9460 starting2 = XINT (start2); | |
9461 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX; | |
9462 ending2 = min (ending2, sequence2_len); | |
9463 | |
9464 if (LISTP (sequence1)) | |
9465 { | |
9466 Lisp_Object *saving; | |
9467 sequence1_storage = saving | |
9468 = alloca_array (Lisp_Object, ending1 - starting1); | |
9469 | |
9470 { | |
9471 EXTERNAL_LIST_LOOP_2 (elt, sequence1) | |
9472 { | |
9473 if (starting1 <= ii && ii < ending1) | |
9474 { | |
9475 *saving++ = elt; | |
9476 } | |
9477 else if (ii == ending1) | |
9478 { | |
9479 break; | |
9480 } | |
9481 | |
9482 ++ii; | |
9483 } | |
9484 } | |
9485 } | |
9486 else if (STRINGP (sequence1)) | |
9487 { | |
9488 const Ibyte *cursor = string_char_addr (sequence1, starting1); | |
9489 | |
9490 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence1_storage, ii, | |
9491 ending1 - starting1); | |
9492 | |
9493 } | |
9494 else if (BIT_VECTORP (sequence1)) | |
9495 { | |
9496 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence1); | |
9497 sequence1_storage = alloca_array (Lisp_Object, ending1 - starting1); | |
9498 for (ii = starting1; ii < ending1; ++ii) | |
9499 { | |
9500 sequence1_storage[ii - starting1] | |
9501 = make_int (bit_vector_bit (vv, ii)); | |
9502 } | |
9503 } | |
9504 else | |
9505 { | |
9506 sequence1_storage = XVECTOR_DATA (sequence1) + starting1; | |
9507 } | |
9508 | |
9509 ii = 0; | |
9510 | |
9511 if (LISTP (sequence2)) | |
9512 { | |
9513 Lisp_Object *saving; | |
9514 sequence2_storage = saving | |
9515 = alloca_array (Lisp_Object, ending2 - starting2); | |
9516 | |
9517 { | |
9518 EXTERNAL_LIST_LOOP_2 (elt, sequence2) | |
9519 { | |
9520 if (starting2 <= ii && ii < ending2) | |
9521 { | |
9522 *saving++ = elt; | |
9523 } | |
9524 else if (ii == ending2) | |
9525 { | |
9526 break; | |
9527 } | |
9528 | |
9529 ++ii; | |
9530 } | |
9531 } | |
9532 } | |
9533 else if (STRINGP (sequence2)) | |
9534 { | |
9535 const Ibyte *cursor = string_char_addr (sequence2, starting2); | |
9536 | |
9537 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence2_storage, ii, | |
9538 ending2 - starting2); | |
9539 | |
9540 } | |
9541 else if (BIT_VECTORP (sequence2)) | |
9542 { | |
9543 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence2); | |
9544 sequence2_storage = alloca_array (Lisp_Object, ending2 - starting2); | |
9545 for (ii = starting2; ii < ending2; ++ii) | |
9546 { | |
9547 sequence2_storage[ii - starting2] | |
9548 = make_int (bit_vector_bit (vv, ii)); | |
9549 } | |
9550 } | |
9551 else | |
9552 { | |
9553 sequence2_storage = XVECTOR_DATA (sequence2) + starting2; | |
9554 } | |
9555 | |
9556 GCPRO2 (sequence1_storage[0], sequence2_storage[0]); | |
9557 gcpro1.nvars = ending1 - starting1; | |
9558 gcpro2.nvars = ending2 - starting2; | |
9559 | |
9560 while (ending1 > starting1 && ending2 > starting2) | |
9561 { | |
9562 --ending1; | |
9563 --ending2; | |
9564 | |
9565 if (check_match (test, key, sequence1_storage[ending1 - starting1], | |
9566 sequence2_storage[ending2 - starting2]) | |
9567 != test_not_unboundp) | |
9568 { | |
9569 UNGCPRO; | |
9570 return make_integer (ending1 + 1); | |
9571 } | |
9572 } | |
9573 | |
9574 UNGCPRO; | |
9575 | |
9576 if (ending1 > starting1 || ending2 > starting2) | |
9577 { | |
9578 return make_integer (ending1); | |
9579 } | |
9580 | |
9581 return Qnil; | |
9582 } | |
9583 | |
9584 static Lisp_Object | |
9585 mismatch_list_list (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1, | |
9586 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2, | |
9587 check_test_func_t check_match, Boolint test_not_unboundp, | |
9588 Lisp_Object test, Lisp_Object key, | |
9589 Boolint UNUSED (return_list_index)) | |
9590 { | |
9591 Lisp_Object sequence1_tortoise = sequence1, sequence2_tortoise = sequence2; | |
9592 Lisp_Object orig_sequence1 = sequence1, orig_sequence2 = sequence2; | |
9593 Elemcount ending1 = EMACS_INT_MAX, ending2 = EMACS_INT_MAX; | |
9594 Elemcount starting1, starting2, counting, startcounting; | |
9595 Elemcount shortest_len = 0; | |
9596 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
9597 | |
9598 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX; | |
9599 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX; | |
9600 | |
9601 if (!NILP (end1)) | |
9602 { | |
9603 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX; | |
9604 } | |
9605 | |
9606 if (!NILP (end2)) | |
9607 { | |
9608 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX; | |
9609 } | |
9610 | |
9611 if (!ZEROP (start1)) | |
9612 { | |
9613 sequence1 = Fnthcdr (start1, sequence1); | |
9614 | |
9615 if (NILP (sequence1)) | |
9616 { | |
9617 check_sequence_range (sequence1_tortoise, start1, end1, | |
9618 Flength (sequence1_tortoise)); | |
9619 /* Give up early here. */ | |
9620 return Qnil; | |
9621 } | |
9622 | |
9623 ending1 -= starting1; | |
9624 starting1 = 0; | |
9625 sequence1_tortoise = sequence1; | |
9626 } | |
9627 | |
9628 if (!ZEROP (start2)) | |
9629 { | |
9630 sequence2 = Fnthcdr (start2, sequence2); | |
9631 | |
9632 if (NILP (sequence2)) | |
9633 { | |
9634 check_sequence_range (sequence2_tortoise, start2, end2, | |
9635 Flength (sequence2_tortoise)); | |
9636 return Qnil; | |
9637 } | |
9638 | |
9639 ending2 -= starting2; | |
9640 starting2 = 0; | |
9641 sequence2_tortoise = sequence2; | |
9642 } | |
9643 | |
9644 GCPRO4 (sequence1, sequence2, sequence1_tortoise, sequence2_tortoise); | |
9645 | |
9646 counting = startcounting = min (ending1, ending2); | |
9647 | |
9648 while (counting-- > 0 && !NILP (sequence1) && !NILP (sequence2)) | |
9649 { | |
9650 if (check_match (test, key, | |
9651 CONSP (sequence1) ? XCAR (sequence1) | |
9652 : Fcar (sequence1), | |
9653 CONSP (sequence2) ? XCAR (sequence2) | |
9654 : Fcar (sequence2) ) != test_not_unboundp) | |
9655 { | |
9656 UNGCPRO; | |
9657 return make_integer (XINT (start1) + shortest_len); | |
9658 } | |
9659 | |
9660 sequence1 = CONSP (sequence1) ? XCDR (sequence1) : Fcdr (sequence1); | |
9661 sequence2 = CONSP (sequence2) ? XCDR (sequence2) : Fcdr (sequence2); | |
9662 | |
9663 shortest_len++; | |
9664 | |
9665 if (startcounting - counting > CIRCULAR_LIST_SUSPICION_LENGTH) | |
9666 { | |
9667 if (counting & 1) | |
9668 { | |
9669 sequence1_tortoise = XCDR (sequence1_tortoise); | |
9670 sequence2_tortoise = XCDR (sequence2_tortoise); | |
9671 } | |
9672 | |
9673 if (EQ (sequence1, sequence1_tortoise)) | |
9674 { | |
9675 signal_circular_list_error (sequence1); | |
9676 } | |
9677 | |
9678 if (EQ (sequence2, sequence2_tortoise)) | |
9679 { | |
9680 signal_circular_list_error (sequence2); | |
9681 } | |
9682 } | |
9683 } | |
9684 | |
9685 UNGCPRO; | |
9686 | |
9687 if (NILP (sequence1)) | |
9688 { | |
9689 Lisp_Object args[] = { start1, make_int (shortest_len) }; | |
9690 check_sequence_range (orig_sequence1, start1, end1, | |
9691 Fplus (countof (args), args)); | |
9692 } | |
9693 | |
9694 if (NILP (sequence2)) | |
9695 { | |
9696 Lisp_Object args[] = { start2, make_int (shortest_len) }; | |
9697 check_sequence_range (orig_sequence2, start2, end2, | |
9698 Fplus (countof (args), args)); | |
9699 } | |
9700 | |
9701 if ((!NILP (end1) && shortest_len != ending1 - starting1) || | |
9702 (!NILP (end2) && shortest_len != ending2 - starting2)) | |
9703 { | |
9704 return make_integer (XINT (start1) + shortest_len); | |
9705 } | |
9706 | |
9707 if ((NILP (end1) && CONSP (sequence1)) || (NILP (end2) && CONSP (sequence2))) | |
9708 { | |
9709 return make_integer (XINT (start1) + shortest_len); | |
9710 } | |
9711 | |
9712 return Qnil; | |
9713 } | |
9714 | |
9715 static Lisp_Object | |
9716 mismatch_list_string (Lisp_Object list, Lisp_Object list_start, | |
9717 Lisp_Object list_end, | |
9718 Lisp_Object string, Lisp_Object string_start, | |
9719 Lisp_Object string_end, | |
9720 check_test_func_t check_match, | |
9721 Boolint test_not_unboundp, | |
9722 Lisp_Object test, Lisp_Object key, | |
9723 Boolint return_list_index) | |
9724 { | |
9725 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data; | |
9726 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string); | |
9727 Elemcount char_count = 0, list_starting, list_ending; | |
9728 Elemcount string_starting, string_ending; | |
9729 Lisp_Object character, orig_list = list; | |
9730 struct gcpro gcpro1; | |
9731 | |
9732 list_ending = INTP (list_end) ? XINT (list_end) : 1 + EMACS_INT_MAX; | |
9733 list_starting = INTP (list_start) ? XINT (list_start) : 1 + EMACS_INT_MAX; | |
9734 | |
9735 string_ending = INTP (string_end) ? XINT (string_end) : 1 + EMACS_INT_MAX; | |
9736 string_starting | |
9737 = INTP (string_start) ? XINT (string_start) : 1 + EMACS_INT_MAX; | |
9738 | |
9739 while (char_count < string_starting && string_offset < string_len) | |
9740 { | |
9741 INC_IBYTEPTR (string_data); | |
9742 string_offset = string_data - startp; | |
9743 char_count++; | |
9744 } | |
9745 | |
9746 if (!ZEROP (list_start)) | |
9747 { | |
9748 list = Fnthcdr (list_start, list); | |
9749 if (NILP (list)) | |
9750 { | |
9751 check_sequence_range (orig_list, list_start, list_end, | |
9752 Flength (orig_list)); | |
9753 return Qnil; | |
9754 } | |
9755 | |
9756 list_ending -= list_starting; | |
9757 list_starting = 0; | |
9758 } | |
9759 | |
9760 GCPRO1 (list); | |
9761 | |
9762 while (list_starting < list_ending && string_starting < string_ending | |
9763 && string_offset < string_len && !NILP (list)) | |
9764 { | |
9765 character = make_char (itext_ichar (string_data)); | |
9766 | |
9767 if (return_list_index) | |
9768 { | |
9769 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list), | |
9770 character) | |
9771 != test_not_unboundp) | |
9772 { | |
9773 UNGCPRO; | |
9774 return make_integer (XINT (list_start) + char_count); | |
9775 } | |
9776 } | |
9777 else | |
9778 { | |
9779 if (check_match (test, key, character, | |
9780 CONSP (list) ? XCAR (list) : Fcar (list)) | |
9781 != test_not_unboundp) | |
9782 { | |
9783 UNGCPRO; | |
9784 return make_integer (char_count); | |
9785 } | |
9786 } | |
9787 | |
9788 list = CONSP (list) ? XCDR (list) : Fcdr (list); | |
9789 | |
9790 startp = XSTRING_DATA (string); | |
9791 string_data = startp + string_offset; | |
9792 if (string_len != XSTRING_LENGTH (string) | |
9793 || !valid_ibyteptr_p (string_data)) | |
9794 { | |
9795 mapping_interaction_error (Qmismatch, string); | |
9796 } | |
9797 | |
9798 list_starting++; | |
9799 string_starting++; | |
9800 char_count++; | |
9801 INC_IBYTEPTR (string_data); | |
9802 string_offset = string_data - startp; | |
9803 } | |
9804 | |
9805 UNGCPRO; | |
9806 | |
9807 if (NILP (list)) | |
9808 { | |
9809 Lisp_Object args[] = { list_start, make_int (char_count) }; | |
9810 check_sequence_range (orig_list, list_start, list_end, | |
9811 Fplus (countof (args), args)); | |
9812 } | |
9813 | |
9814 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string)) | |
9815 { | |
9816 check_sequence_range (string, string_start, string_end, | |
9817 make_int (char_count)); | |
9818 } | |
9819 | |
9820 if ((NILP (string_end) ? | |
9821 string_offset < string_len : string_starting < string_ending) || | |
9822 (NILP (list_end) ? !NILP (list) : list_starting < list_ending)) | |
9823 { | |
9824 return make_integer (return_list_index ? XINT (list_start) + char_count : | |
9825 char_count); | |
9826 } | |
9827 | |
9828 return Qnil; | |
9829 } | |
9830 | |
9831 static Lisp_Object | |
9832 mismatch_list_array (Lisp_Object list, Lisp_Object list_start, | |
9833 Lisp_Object list_end, | |
9834 Lisp_Object array, Lisp_Object array_start, | |
9835 Lisp_Object array_end, | |
9836 check_test_func_t check_match, | |
9837 Boolint test_not_unboundp, | |
9838 Lisp_Object test, Lisp_Object key, | |
9839 Boolint return_list_index) | |
9840 { | |
9841 Elemcount ii = 0, list_starting, list_ending; | |
9842 Elemcount array_starting, array_ending, array_len; | |
9843 Lisp_Object orig_list = list; | |
9844 struct gcpro gcpro1; | |
9845 | |
9846 list_ending = INTP (list_end) ? XINT (list_end) : 1 + EMACS_INT_MAX; | |
9847 list_starting = INTP (list_start) ? XINT (list_start) : 1 + EMACS_INT_MAX; | |
9848 | |
9849 array_ending = INTP (array_end) ? XINT (array_end) : 1 + EMACS_INT_MAX; | |
9850 array_starting = INTP (array_start) ? XINT (array_start) : 1 + EMACS_INT_MAX; | |
9851 array_len = XINT (Flength (array)); | |
9852 | |
9853 array_ending = min (array_ending, array_len); | |
9854 | |
9855 check_sequence_range (array, array_start, array_end, make_int (array_len)); | |
9856 | |
9857 if (!ZEROP (list_start)) | |
9858 { | |
9859 list = Fnthcdr (list_start, list); | |
9860 if (NILP (list)) | |
9861 { | |
9862 check_sequence_range (orig_list, list_start, list_end, | |
9863 Flength (orig_list)); | |
9864 return Qnil; | |
9865 } | |
9866 | |
9867 list_ending -= list_starting; | |
9868 list_starting = 0; | |
9869 } | |
9870 | |
9871 GCPRO1 (list); | |
9872 | |
9873 while (list_starting < list_ending && array_starting < array_ending | |
9874 && !NILP (list)) | |
9875 { | |
9876 if (return_list_index) | |
9877 { | |
9878 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list), | |
9879 Faref (array, make_int (array_starting))) | |
9880 != test_not_unboundp) | |
9881 { | |
9882 UNGCPRO; | |
9883 return make_integer (XINT (list_start) + ii); | |
9884 } | |
9885 } | |
9886 else | |
9887 { | |
9888 if (check_match (test, key, Faref (array, make_int (array_starting)), | |
9889 CONSP (list) ? XCAR (list) : Fcar (list)) | |
9890 != test_not_unboundp) | |
9891 { | |
9892 UNGCPRO; | |
9893 return make_integer (array_starting); | |
9894 } | |
9895 } | |
9896 | |
9897 list = CONSP (list) ? XCDR (list) : Fcdr (list); | |
9898 list_starting++; | |
9899 array_starting++; | |
9900 ii++; | |
9901 } | |
9902 | |
9903 UNGCPRO; | |
9904 | |
9905 if (NILP (list)) | |
9906 { | |
9907 Lisp_Object args[] = { list_start, make_int (ii) }; | |
9908 check_sequence_range (orig_list, list_start, list_end, | |
9909 Fplus (countof (args), args)); | |
9910 } | |
9911 | |
9912 if (array_starting < array_ending || | |
9913 (NILP (list_end) ? !NILP (list) : list_starting < list_ending)) | |
9914 { | |
9915 return make_integer (return_list_index ? XINT (list_start) + ii : | |
9916 array_starting); | |
9917 } | |
9918 | |
9919 return Qnil; | |
9920 } | |
9921 | |
9922 static Lisp_Object | |
9923 mismatch_string_array (Lisp_Object string, Lisp_Object string_start, | |
9924 Lisp_Object string_end, | |
9925 Lisp_Object array, Lisp_Object array_start, | |
9926 Lisp_Object array_end, | |
9927 check_test_func_t check_match, Boolint test_not_unboundp, | |
9928 Lisp_Object test, Lisp_Object key, | |
9929 Boolint return_string_index) | |
9930 { | |
9931 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data; | |
9932 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string); | |
9933 Elemcount char_count = 0, array_starting, array_ending, array_length; | |
9934 Elemcount string_starting, string_ending; | |
9935 Lisp_Object character; | |
9936 | |
9937 array_starting = INTP (array_start) ? XINT (array_start) : 1 + EMACS_INT_MAX; | |
9938 array_ending = INTP (array_end) ? XINT (array_end) : 1 + EMACS_INT_MAX; | |
9939 array_length = XINT (Flength (array)); | |
9940 check_sequence_range (array, array_start, array_end, make_int (array_length)); | |
9941 array_ending = min (array_ending, array_length); | |
9942 | |
9943 string_ending = INTP (string_end) ? XINT (string_end) : 1 + EMACS_INT_MAX; | |
9944 string_starting | |
9945 = INTP (string_start) ? XINT (string_start) : 1 + EMACS_INT_MAX; | |
9946 | |
9947 while (char_count < string_starting && string_offset < string_len) | |
9948 { | |
9949 INC_IBYTEPTR (string_data); | |
9950 string_offset = string_data - startp; | |
9951 char_count++; | |
9952 } | |
9953 | |
9954 while (array_starting < array_ending && string_starting < string_ending | |
9955 && string_offset < string_len) | |
9956 { | |
9957 character = make_char (itext_ichar (string_data)); | |
9958 | |
9959 if (return_string_index) | |
9960 { | |
9961 if (check_match (test, key, character, | |
9962 Faref (array, make_int (array_starting))) | |
9963 != test_not_unboundp) | |
9964 { | |
9965 return make_integer (char_count); | |
9966 } | |
9967 } | |
9968 else | |
9969 { | |
9970 if (check_match (test, key, | |
9971 Faref (array, make_int (array_starting)), | |
9972 character) | |
9973 != test_not_unboundp) | |
9974 { | |
9975 return make_integer (XINT (array_start) + char_count); | |
9976 } | |
9977 } | |
9978 | |
9979 startp = XSTRING_DATA (string); | |
9980 string_data = startp + string_offset; | |
9981 if (string_len != XSTRING_LENGTH (string) | |
9982 || !valid_ibyteptr_p (string_data)) | |
9983 { | |
9984 mapping_interaction_error (Qmismatch, string); | |
9985 } | |
9986 | |
9987 array_starting++; | |
9988 string_starting++; | |
9989 char_count++; | |
9990 INC_IBYTEPTR (string_data); | |
9991 string_offset = string_data - startp; | |
9992 } | |
9993 | |
9994 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string)) | |
9995 { | |
9996 check_sequence_range (string, string_start, string_end, | |
9997 make_int (char_count)); | |
9998 } | |
9999 | |
10000 if ((NILP (string_end) ? | |
10001 string_offset < string_len : string_starting < string_ending) || | |
10002 (NILP (array_end) ? !NILP (array) : array_starting < array_ending)) | |
10003 { | |
10004 return make_integer (return_string_index ? char_count : | |
10005 XINT (array_start) + char_count); | |
10006 } | |
10007 | |
10008 return Qnil; | |
10009 } | |
10010 | |
10011 static Lisp_Object | |
10012 mismatch_string_string (Lisp_Object string1, | |
10013 Lisp_Object string1_start, Lisp_Object string1_end, | |
10014 Lisp_Object string2, Lisp_Object string2_start, | |
10015 Lisp_Object string2_end, | |
10016 check_test_func_t check_match, | |
10017 Boolint test_not_unboundp, | |
10018 Lisp_Object test, Lisp_Object key, | |
10019 Boolint UNUSED (return_string1_index)) | |
10020 { | |
10021 Ibyte *string1_data = XSTRING_DATA (string1), *startp1 = string1_data; | |
10022 Bytecount string1_offset = 0, string1_len = XSTRING_LENGTH (string1); | |
10023 Ibyte *string2_data = XSTRING_DATA (string2), *startp2 = string2_data; | |
10024 Bytecount string2_offset = 0, string2_len = XSTRING_LENGTH (string2); | |
10025 Elemcount char_count1 = 0, string1_starting, string1_ending; | |
10026 Elemcount char_count2 = 0, string2_starting, string2_ending; | |
10027 Lisp_Object character1, character2; | |
10028 | |
10029 string1_ending = INTP (string1_end) ? XINT (string1_end) : 1 + EMACS_INT_MAX; | |
10030 string1_starting | |
10031 = INTP (string1_start) ? XINT (string1_start) : 1 + EMACS_INT_MAX; | |
10032 | |
10033 string2_starting | |
10034 = INTP (string2_start) ? XINT (string2_start) : 1 + EMACS_INT_MAX; | |
10035 string2_ending = INTP (string2_end) ? XINT (string2_end) : 1 + EMACS_INT_MAX; | |
10036 | |
10037 while (char_count1 < string1_starting && string1_offset < string1_len) | |
10038 { | |
10039 INC_IBYTEPTR (string1_data); | |
10040 string1_offset = string1_data - startp1; | |
10041 char_count1++; | |
10042 } | |
10043 | |
10044 while (char_count2 < string2_starting && string2_offset < string2_len) | |
10045 { | |
10046 INC_IBYTEPTR (string2_data); | |
10047 string2_offset = string2_data - startp2; | |
10048 char_count2++; | |
10049 } | |
10050 | |
10051 while (string2_starting < string2_ending && string1_starting < string1_ending | |
10052 && string1_offset < string1_len && string2_offset < string2_len) | |
10053 { | |
10054 character1 = make_char (itext_ichar (string1_data)); | |
10055 character2 = make_char (itext_ichar (string2_data)); | |
10056 | |
10057 if (check_match (test, key, character1, character2) | |
10058 != test_not_unboundp) | |
10059 { | |
10060 return make_integer (char_count1); | |
10061 } | |
10062 | |
10063 startp1 = XSTRING_DATA (string1); | |
10064 string1_data = startp1 + string1_offset; | |
10065 if (string1_len != XSTRING_LENGTH (string1) | |
10066 || !valid_ibyteptr_p (string1_data)) | |
10067 { | |
10068 mapping_interaction_error (Qmismatch, string1); | |
10069 } | |
10070 | |
10071 startp2 = XSTRING_DATA (string2); | |
10072 string2_data = startp2 + string2_offset; | |
10073 if (string2_len != XSTRING_LENGTH (string2) | |
10074 || !valid_ibyteptr_p (string2_data)) | |
10075 { | |
10076 mapping_interaction_error (Qmismatch, string2); | |
10077 } | |
10078 | |
10079 string2_starting++; | |
10080 string1_starting++; | |
10081 char_count1++; | |
10082 char_count2++; | |
10083 INC_IBYTEPTR (string1_data); | |
10084 string1_offset = string1_data - startp1; | |
10085 INC_IBYTEPTR (string2_data); | |
10086 string2_offset = string2_data - startp2; | |
10087 } | |
10088 | |
10089 if (string1_data == XSTRING_DATA (string1) + XSTRING_LENGTH (string1)) | |
10090 { | |
10091 check_sequence_range (string1, string1_start, string1_end, | |
10092 make_int (char_count1)); | |
10093 } | |
10094 | |
10095 if (string2_data == XSTRING_DATA (string2) + XSTRING_LENGTH (string2)) | |
10096 { | |
10097 check_sequence_range (string2, string2_start, string2_end, | |
10098 make_int (char_count2)); | |
10099 } | |
10100 | |
10101 if ((!NILP (string1_end) && string1_starting < string1_ending) || | |
10102 (!NILP (string2_end) && string2_starting < string2_ending)) | |
10103 { | |
10104 return make_integer (char_count1); | |
10105 } | |
10106 | |
10107 if ((NILP (string1_end) && string1_data | |
10108 < (XSTRING_DATA (string1) + XSTRING_LENGTH (string1))) || | |
10109 (NILP (string2_end) && string2_data | |
10110 < (XSTRING_DATA (string2) + XSTRING_LENGTH (string2)))) | |
10111 { | |
10112 return make_integer (char_count1); | |
10113 } | |
10114 | |
10115 return Qnil; | |
10116 } | |
10117 | |
10118 static Lisp_Object | |
10119 mismatch_array_array (Lisp_Object array1, Lisp_Object start1, Lisp_Object end1, | |
10120 Lisp_Object array2, Lisp_Object start2, Lisp_Object end2, | |
10121 check_test_func_t check_match, Boolint test_not_unboundp, | |
10122 Lisp_Object test, Lisp_Object key, | |
10123 Boolint UNUSED (return_array1_index)) | |
10124 { | |
10125 Elemcount len1 = XINT (Flength (array1)), len2 = XINT (Flength (array2)); | |
10126 Elemcount ending1 = EMACS_INT_MAX, ending2 = EMACS_INT_MAX; | |
10127 Elemcount starting1, starting2; | |
10128 | |
10129 check_sequence_range (array1, start1, end1, make_int (len1)); | |
10130 check_sequence_range (array2, start2, end2, make_int (len2)); | |
10131 | |
10132 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX; | |
10133 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX; | |
10134 | |
10135 if (!NILP (end1)) | |
10136 { | |
10137 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX; | |
10138 } | |
10139 | |
10140 if (!NILP (end2)) | |
10141 { | |
10142 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX; | |
10143 } | |
10144 | |
10145 ending1 = min (ending1, len1); | |
10146 ending2 = min (ending2, len2); | |
10147 | |
10148 while (starting1 < ending1 && starting2 < ending2) | |
10149 { | |
10150 if (check_match (test, key, Faref (array1, make_int (starting1)), | |
10151 Faref (array2, make_int (starting2))) | |
10152 != test_not_unboundp) | |
10153 { | |
10154 return make_integer (starting1); | |
10155 } | |
10156 starting1++; | |
10157 starting2++; | |
10158 } | |
10159 | |
10160 if (starting1 < ending1 || starting2 < ending2) | |
10161 { | |
10162 return make_integer (starting1); | |
10163 } | |
10164 | |
10165 return Qnil; | |
10166 } | |
10167 | |
10168 typedef Lisp_Object | |
10169 (*mismatch_func_t) (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1, | |
10170 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2, | |
10171 check_test_func_t check_match, Boolint test_not_unboundp, | |
10172 Lisp_Object test, Lisp_Object key, | |
10173 Boolint return_list_index); | |
10174 | |
10175 static mismatch_func_t | |
10176 get_mismatch_func (Lisp_Object sequence1, Lisp_Object sequence2, | |
10177 Lisp_Object from_end, Boolint *return_sequence1_index_out) | |
10178 { | |
10179 CHECK_SEQUENCE (sequence1); | |
10180 CHECK_SEQUENCE (sequence2); | |
10181 | |
10182 if (!NILP (from_end)) | |
10183 { | |
10184 *return_sequence1_index_out = 1; | |
10185 return mismatch_from_end; | |
10186 } | |
10187 | |
10188 if (LISTP (sequence1)) | |
10189 { | |
10190 if (LISTP (sequence2)) | |
10191 { | |
10192 *return_sequence1_index_out = 1; | |
10193 return mismatch_list_list; | |
10194 } | |
10195 | |
10196 if (STRINGP (sequence2)) | |
10197 { | |
10198 *return_sequence1_index_out = 1; | |
10199 return mismatch_list_string; | |
10200 } | |
10201 | |
10202 *return_sequence1_index_out = 1; | |
10203 return mismatch_list_array; | |
10204 } | |
10205 | |
10206 if (STRINGP (sequence1)) | |
10207 { | |
10208 if (STRINGP (sequence2)) | |
10209 { | |
10210 *return_sequence1_index_out = 1; | |
10211 return mismatch_string_string; | |
10212 } | |
10213 | |
10214 if (LISTP (sequence2)) | |
10215 { | |
10216 *return_sequence1_index_out = 0; | |
10217 return mismatch_list_string; | |
10218 } | |
10219 | |
10220 *return_sequence1_index_out = 1; | |
10221 return mismatch_string_array; | |
10222 } | |
10223 | |
10224 if (ARRAYP (sequence1)) | |
10225 { | |
10226 if (STRINGP (sequence2)) | |
10227 { | |
10228 *return_sequence1_index_out = 0; | |
10229 return mismatch_string_array; | |
10230 } | |
10231 | |
10232 if (LISTP (sequence2)) | |
10233 { | |
10234 *return_sequence1_index_out = 0; | |
10235 return mismatch_list_array; | |
10236 } | |
10237 | |
10238 *return_sequence1_index_out = 1; | |
10239 return mismatch_array_array; | |
10240 } | |
10241 | |
10242 RETURN_NOT_REACHED (NULL); | |
10243 return NULL; | |
10244 } | |
10245 | |
10246 DEFUN ("mismatch", Fmismatch, 2, MANY, 0, /* | |
10247 Compare SEQUENCE1 with SEQUENCE2, return index of first mismatching element. | |
10248 | |
10249 Return nil if the sequences match. If one sequence is a prefix of the | |
10250 other, the return value indicates the end of the shorter sequence. A | |
10251 non-nil return value always reflects an index into SEQUENCE1. | |
10252 | |
10253 See `search' for the meaning of the keywords." | |
10254 | |
10255 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT) | |
10256 */ | |
10257 (int nargs, Lisp_Object *args)) | |
10258 { | |
10259 Lisp_Object sequence1 = args[0], sequence2 = args[1]; | |
10260 Boolint test_not_unboundp = 1, return_first_index = 0; | |
10261 check_test_func_t check_match = NULL; | |
10262 mismatch_func_t mismatch = NULL; | |
10263 | |
10264 PARSE_KEYWORDS (Fmismatch, nargs, args, 8, | |
10265 (test, key, from_end, start1, end1, start2, end2, test_not), | |
10266 (start1 = start2 = Qzero)); | |
10267 | |
10268 CHECK_SEQUENCE (sequence1); | |
10269 CHECK_SEQUENCE (sequence2); | |
10270 | |
10271 CHECK_NATNUM (start1); | |
10272 CHECK_NATNUM (start2); | |
10273 | |
10274 if (!NILP (end1)) | |
10275 { | |
10276 CHECK_NATNUM (end1); | |
10277 } | |
10278 | |
10279 if (!NILP (end2)) | |
10280 { | |
10281 CHECK_NATNUM (end2); | |
10282 } | |
10283 | |
10284 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10285 &test_not_unboundp, NULL); | |
10286 mismatch = get_mismatch_func (sequence1, sequence2, from_end, | |
10287 &return_first_index); | |
10288 | |
10289 if (return_first_index) | |
10290 { | |
10291 return mismatch (sequence1, start1, end1, sequence2, start2, end2, | |
10292 check_match, test_not_unboundp, test, key, 1); | |
10293 } | |
10294 | |
10295 return mismatch (sequence2, start2, end2, sequence1, start1, end1, | |
10296 check_match, test_not_unboundp, test, key, 0); | |
10297 } | |
10298 | |
10299 DEFUN ("search", Fsearch, 2, MANY, 0, /* | |
10300 Search for SEQUENCE1 as a subsequence of SEQUENCE2. | |
10301 | |
10302 Return the index of the leftmost element of the first match found; return | |
10303 nil if there are no matches. | |
10304 | |
10305 In this function, :start1 and :end1 specify a subsequence of SEQUENCE1, and | |
10306 :start2 and :end2 specify a subsequence of SEQUENCE2. See `remove*' for | |
10307 details of the other keywords. | |
10308 | |
10309 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT) | |
10310 */ | |
10311 (int nargs, Lisp_Object *args)) | |
10312 { | |
10313 Lisp_Object sequence1 = args[0], sequence2 = args[1], position0 = Qnil; | |
10314 Boolint test_not_unboundp = 1, return_first = 0; | |
10315 check_test_func_t check_test = NULL, check_match = NULL; | |
10316 mismatch_func_t mismatch = NULL; | |
10317 Elemcount starting1 = 0, ending1 = 1 + EMACS_INT_MAX, starting2 = 0; | |
10318 Elemcount ending2 = 1 + EMACS_INT_MAX, ii = 0; | |
10319 Elemcount length1; | |
10320 Lisp_Object object = Qnil; | |
10321 struct gcpro gcpro1, gcpro2; | |
10322 | |
10323 PARSE_KEYWORDS (Fsearch, nargs, args, 8, | |
10324 (test, key, from_end, start1, end1, start2, end2, test_not), | |
10325 (start1 = start2 = Qzero)); | |
10326 | |
10327 CHECK_SEQUENCE (sequence1); | |
10328 CHECK_SEQUENCE (sequence2); | |
10329 CHECK_KEY_ARGUMENT (key); | |
10330 | |
10331 CHECK_NATNUM (start1); | |
10332 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX; | |
10333 CHECK_NATNUM (start2); | |
10334 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX; | |
10335 | |
10336 if (!NILP (end1)) | |
10337 { | |
10338 Lisp_Object len1 = Flength (sequence1); | |
10339 | |
10340 CHECK_NATNUM (end1); | |
10341 check_sequence_range (sequence1, start1, end1, len1); | |
10342 ending1 = min (XINT (end1), XINT (len1)); | |
10343 } | |
10344 else | |
10345 { | |
10346 end1 = Flength (sequence1); | |
10347 check_sequence_range (sequence1, start1, end1, end1); | |
10348 ending1 = XINT (end1); | |
10349 } | |
10350 | |
10351 length1 = ending1 - starting1; | |
10352 | |
10353 if (!NILP (end2)) | |
10354 { | |
10355 Lisp_Object len2 = Flength (sequence2); | |
10356 | |
10357 CHECK_NATNUM (end2); | |
10358 check_sequence_range (sequence2, start2, end2, len2); | |
10359 ending2 = min (XINT (end2), XINT (len2)); | |
10360 } | |
10361 else | |
10362 { | |
10363 end2 = Flength (sequence2); | |
10364 check_sequence_range (sequence2, start2, end2, end2); | |
10365 ending2 = XINT (end2); | |
10366 } | |
10367 | |
10368 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10369 &test_not_unboundp, &check_test); | |
10370 mismatch = get_mismatch_func (sequence1, sequence2, from_end, &return_first); | |
10371 | |
10372 if (bytecode_arithcompare (start1, make_integer (ending1)) >= 0) | |
10373 { | |
10374 if (NILP (from_end)) | |
10375 { | |
10376 return start2; | |
10377 } | |
10378 | |
10379 if (NILP (end2)) | |
10380 { | |
10381 return Flength (sequence2); | |
10382 } | |
10383 | |
10384 return end2; | |
10385 } | |
10386 | |
10387 if (NILP (from_end)) | |
10388 { | |
10389 Lisp_Object mismatch_start1 = Fadd1 (start1); | |
10390 Lisp_Object first = KEY (key, Felt (sequence1, start1)); | |
10391 GCPRO2 (first, mismatch_start1); | |
10392 | |
10393 ii = starting2; | |
10394 while (ii < ending2) | |
10395 { | |
10396 position0 = position (&object, first, sequence2, check_test, | |
10397 test_not_unboundp, test, key, make_int (ii), | |
10398 end2, Qnil, Qnil, Qsearch); | |
10399 if (NILP (position0)) | |
10400 { | |
10401 UNGCPRO; | |
10402 return Qnil; | |
10403 } | |
10404 | |
10405 if (length1 + XINT (position0) <= ending2 && | |
10406 (return_first ? | |
10407 NILP (mismatch (sequence1, mismatch_start1, end1, | |
10408 sequence2, | |
10409 make_int (1 + XINT (position0)), | |
10410 make_int (length1 + XINT (position0)), | |
10411 check_match, test_not_unboundp, test, key, 1)) : | |
10412 NILP (mismatch (sequence2, | |
10413 make_int (1 + XINT (position0)), | |
10414 make_int (length1 + XINT (position0)), | |
10415 sequence1, mismatch_start1, end1, | |
10416 check_match, test_not_unboundp, test, key, 0)))) | |
10417 | |
10418 | |
10419 { | |
10420 UNGCPRO; | |
10421 return position0; | |
10422 } | |
10423 | |
10424 ii = XINT (position0) + 1; | |
10425 } | |
10426 | |
10427 UNGCPRO; | |
10428 } | |
10429 else | |
10430 { | |
10431 Lisp_Object mismatch_end1 = make_integer (ending1 - 1); | |
10432 Lisp_Object last = KEY (key, Felt (sequence1, mismatch_end1)); | |
10433 GCPRO2 (last, mismatch_end1); | |
10434 | |
10435 ii = ending2; | |
10436 while (ii > starting2) | |
10437 { | |
10438 position0 = position (&object, last, sequence2, check_test, | |
10439 test_not_unboundp, test, key, start2, | |
10440 make_int (ii), Qt, Qnil, Qsearch); | |
10441 | |
10442 if (NILP (position0)) | |
10443 { | |
10444 UNGCPRO; | |
10445 return Qnil; | |
10446 } | |
10447 | |
10448 if (XINT (position0) - length1 + 1 >= starting2 && | |
10449 (return_first ? | |
10450 NILP (mismatch (sequence1, start1, mismatch_end1, | |
10451 sequence2, | |
10452 make_int (XINT (position0) - length1 + 1), | |
10453 make_int (XINT (position0)), | |
10454 check_match, test_not_unboundp, test, key, 1)) : | |
10455 NILP (mismatch (sequence2, | |
10456 make_int (XINT (position0) - length1 + 1), | |
10457 make_int (XINT (position0)), | |
10458 sequence1, start1, mismatch_end1, | |
10459 check_match, test_not_unboundp, test, key, 0)))) | |
10460 { | |
10461 UNGCPRO; | |
10462 return make_int (XINT (position0) - length1 + 1); | |
10463 } | |
10464 | |
10465 ii = XINT (position0); | |
10466 } | |
10467 | |
10468 UNGCPRO; | |
10469 } | |
10470 | |
10471 return Qnil; | |
10472 } | |
10473 | |
10474 /* These two functions do set operations, those that can be visualised with | |
10475 Venn diagrams. */ | |
10476 static Lisp_Object | |
10477 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) | |
10478 { | |
10479 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | |
10480 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil; | |
10481 Lisp_Object keyed = Qnil, ignore = Qnil; | |
10482 Elemcount len; | |
10483 Boolint test_not_unboundp = 1; | |
10484 check_test_func_t check_test = NULL; | |
10485 struct gcpro gcpro1, gcpro2, gcpro3; | |
10486 | |
10487 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable), | |
10488 NULL, 2, 0); | |
10489 | |
10490 CHECK_LIST (liszt1); | |
10491 CHECK_LIST (liszt2); | |
10492 | |
10493 CHECK_KEY_ARGUMENT (key); | |
10494 | |
10495 if (NILP (liszt1) && intersectionp) | |
10496 { | |
10497 return Qnil; | |
10498 } | |
10499 | |
10500 if (NILP (liszt2)) | |
10501 { | |
10502 return intersectionp ? Qnil : liszt1; | |
10503 } | |
10504 | |
10505 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10506 &test_not_unboundp, &check_test); | |
10507 | |
10508 GCPRO3 (tail, keyed, result); | |
10509 | |
10510 { | |
10511 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | |
10512 { | |
10513 keyed = KEY (key, elt); | |
10514 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10515 check_test, test_not_unboundp, | |
10516 test, key, 0, Qzero, Qnil)) | |
10517 != intersectionp) | |
10518 { | |
10519 if (EQ (Qsubsetp, caller)) | |
10520 { | |
10521 result = Qnil; | |
10522 break; | |
10523 } | |
10524 else if (NILP (stable)) | |
10525 { | |
10526 result = Fcons (elt, result); | |
10527 } | |
10528 else if (NILP (result)) | |
10529 { | |
10530 result = result_tail = Fcons (elt, Qnil); | |
10531 } | |
10532 else | |
10533 { | |
10534 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10535 result_tail = XCDR (result_tail); | |
10536 } | |
10537 } | |
10538 } | |
10539 } | |
10540 | |
10541 UNGCPRO; | |
10542 | |
10543 return result; | |
10544 } | |
10545 | |
10546 static Lisp_Object | |
10547 nvenn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) | |
10548 { | |
10549 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil; | |
10550 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil; | |
10551 Elemcount count; | |
10552 Boolint test_not_unboundp = 1; | |
10553 check_test_func_t check_test = NULL; | |
10554 struct gcpro gcpro1, gcpro2, gcpro3; | |
10555 | |
10556 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not), | |
10557 NULL, 2, 0); | |
10558 | |
10559 CHECK_LIST (liszt1); | |
10560 CHECK_LIST (liszt2); | |
10561 | |
10562 CHECK_KEY_ARGUMENT (key); | |
10563 | |
10564 if (NILP (liszt1) && intersectionp) | |
10565 { | |
10566 return Qnil; | |
10567 } | |
10568 | |
10569 if (NILP (liszt2)) | |
10570 { | |
10571 return intersectionp ? Qnil : liszt1; | |
10572 } | |
10573 | |
10574 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10575 &test_not_unboundp, &check_test); | |
10576 | |
10577 GCPRO3 (tail, keyed, liszt1); | |
10578 | |
10579 tortoise_elt = tail = liszt1, count = 0; | |
10580 | |
10581 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | |
10582 (signal_malformed_list_error (liszt1), 0)) | |
10583 { | |
10584 keyed = KEY (key, elt); | |
10585 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10586 check_test, test_not_unboundp, | |
10587 test, key, 0, Qzero, Qnil)) | |
10588 == intersectionp) | |
10589 { | |
10590 if (NILP (prev_tail)) | |
10591 { | |
10592 liszt1 = XCDR (tail); | |
10593 } | |
10594 else | |
10595 { | |
10596 XSETCDR (prev_tail, XCDR (tail)); | |
10597 } | |
10598 | |
10599 tail = XCDR (tail); | |
10600 /* List is definitely not circular now! */ | |
10601 count = 0; | |
10602 } | |
10603 else | |
10604 { | |
10605 prev_tail = tail; | |
10606 tail = XCDR (tail); | |
10607 } | |
10608 | |
10609 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
10610 | |
10611 if (count & 1) | |
10612 { | |
10613 tortoise_elt = XCDR (tortoise_elt); | |
10614 } | |
10615 | |
10616 if (EQ (elt, tortoise_elt)) | |
10617 { | |
10618 signal_circular_list_error (liszt1); | |
10619 } | |
10620 } | |
10621 | |
10622 UNGCPRO; | |
10623 | |
10624 return liszt1; | |
10625 } | |
10626 | |
10627 DEFUN ("intersection", Fintersection, 2, MANY, 0, /* | |
10628 Combine LIST1 and LIST2 using a set-intersection operation. | |
10629 | |
10630 The result list contains all items that appear in both LIST1 and LIST2. | |
10631 This is a non-destructive function; it makes a copy of the data if necessary | |
10632 to avoid corrupting the original LIST1 and LIST2. | |
10633 | |
10634 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10635 return the items in the order they appear in LIST1. | |
10636 | |
10637 See `union' for the meaning of :test, :test-not and :key." | |
10638 | |
10639 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | |
10640 */ | |
10641 (int nargs, Lisp_Object *args)) | |
10642 { | |
10643 return venn (Qintersection, nargs, args, 1); | |
10644 } | |
10645 | |
10646 DEFUN ("nintersection", Fnintersection, 2, MANY, 0, /* | |
10647 Combine LIST1 and LIST2 using a set-intersection operation. | |
10648 | |
10649 The result list contains all items that appear in both LIST1 and LIST2. | |
10650 This is a destructive function; it reuses the storage of LIST1 whenever | |
10651 possible. | |
10652 | |
10653 See `union' for the meaning of :test, :test-not and :key." | |
10654 | |
10655 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10656 */ | |
10657 (int nargs, Lisp_Object *args)) | |
10658 { | |
10659 return nvenn (Qnintersection, nargs, args, 1); | |
10660 } | |
10661 | |
10662 DEFUN ("subsetp", Fsubsetp, 2, MANY, 0, /* | |
10663 Return non-nil if every element of LIST1 also appears in LIST2. | |
10664 | |
10665 See `union' for the meaning of the keyword arguments. | |
10666 | |
10667 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10668 */ | |
10669 (int nargs, Lisp_Object *args)) | |
10670 { | |
10671 return venn (Qsubsetp, nargs, args, 0); | |
10672 } | |
10673 | |
10674 DEFUN ("set-difference", Fset_difference, 2, MANY, 0, /* | |
10675 Combine LIST1 and LIST2 using a set-difference operation. | |
10676 | |
10677 The result list contains all items that appear in LIST1 but not LIST2. This | |
10678 is a non-destructive function; it makes a copy of the data if necessary to | |
10679 avoid corrupting the original LIST1 and LIST2. | |
10680 | |
10681 See `union' for the meaning of :test, :test-not and :key. | |
10682 | |
10683 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10684 return the items in the order they appear in LIST1. | |
10685 | |
10686 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | |
10687 */ | |
10688 (int nargs, Lisp_Object *args)) | |
10689 { | |
10690 return venn (Qset_difference, nargs, args, 0); | |
10691 } | |
10692 | |
10693 DEFUN ("nset-difference", Fnset_difference, 2, MANY, 0, /* | |
10694 Combine LIST1 and LIST2 using a set-difference operation. | |
10695 | |
10696 The result list contains all items that appear in LIST1 but not LIST2. This | |
10697 is a destructive function; it reuses the storage of LIST1 whenever possible. | |
10698 | |
10699 See `union' for the meaning of :test, :test-not and :key." | |
10700 | |
10701 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10702 */ | |
10703 (int nargs, Lisp_Object *args)) | |
10704 { | |
10705 return nvenn (Qnset_difference, nargs, args, 0); | |
10706 } | |
10707 | |
10708 DEFUN ("nunion", Fnunion, 2, MANY, 0, /* | |
10709 Combine LIST1 and LIST2 using a set-union operation. | |
10710 The result list contains all items that appear in either LIST1 or LIST2. | |
10711 | |
10712 This is a destructive function, it reuses the storage of LIST1 whenever | |
10713 possible. | |
10714 | |
10715 See `union' for the meaning of :test, :test-not and :key. | |
10716 | |
10717 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10718 */ | |
10719 (int nargs, Lisp_Object *args)) | |
10720 { | |
10721 args[0] = nvenn (Qnunion, nargs, args, 0); | |
10722 return bytecode_nconc2 (args); | |
10723 } | |
10724 | |
10725 DEFUN ("union", Funion, 2, MANY, 0, /* | |
10726 Combine LIST1 and LIST2 using a set-union operation. | |
10727 The result list contains all items that appear in either LIST1 or LIST2. | |
10728 This is a non-destructive function; it makes a copy of the data if necessary | |
10729 to avoid corrupting the original LIST1 and LIST2. | |
10730 | |
10731 The keywords :test and :test-not specify two-argument test and negated-test | |
10732 predicates, respectively; :test defaults to `eql'. See `member*' for more | |
10733 information. | |
10734 | |
10735 :key specifies a one-argument function that transforms elements of LIST1 | |
10736 and LIST2 into \"comparison keys\" before the test predicate is applied. | |
10737 For example, if :key is #'car, then the car of elements from LIST1 is | |
10738 compared with the car of elements from LIST2. The :key function, however, | |
10739 does not affect the elements in the returned list, which are taken directly | |
10740 from the elements in LIST1 and LIST2. | |
10741 | |
10742 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10743 return the items of LIST1 in order, followed by the remaining items of LIST2 | |
10744 in the order they occur in LIST2. | |
10745 | |
10746 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | |
10747 */ | |
10748 (int nargs, Lisp_Object *args)) | |
10749 { | |
10750 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil; | |
10751 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, result, result_tail; | |
10752 Elemcount len; | |
10753 Boolint test_not_unboundp = 1; | |
10754 check_test_func_t check_test = NULL, check_match = NULL; | |
10755 struct gcpro gcpro1, gcpro2, gcpro3; | |
10756 | |
10757 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL); | |
10758 | |
10759 CHECK_LIST (liszt1); | |
10760 CHECK_LIST (liszt2); | |
10761 | |
10762 CHECK_KEY_ARGUMENT (key); | |
10763 | |
10764 if (NILP (liszt1)) | |
10765 { | |
10766 return liszt2; | |
10767 } | |
10768 | |
10769 if (NILP (liszt2)) | |
10770 { | |
10771 return liszt1; | |
10772 } | |
10773 | |
10774 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10775 &test_not_unboundp, &check_test); | |
10776 | |
10777 GCPRO3 (tail, keyed, result); | |
10778 | |
10779 if (NILP (stable)) | |
10780 { | |
10781 result = liszt2; | |
10782 { | |
10783 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | |
10784 { | |
10785 keyed = KEY (key, elt); | |
10786 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10787 check_test, test_not_unboundp, | |
10788 test, key, 0, Qzero, Qnil))) | |
10789 { | |
10790 /* The Lisp version of #'union used to check which list was | |
10791 longer, and use that as the tail of the constructed | |
10792 list. That fails when the order of arguments to TEST is | |
10793 specified, as is the case for these functions. We could | |
10794 pass the reverse_check argument to | |
10795 list_position_cons_before, but that means any key argument | |
10796 is called an awful lot more, so it's a space win but not | |
10797 a time win. */ | |
10798 result = Fcons (elt, result); | |
10799 } | |
10800 } | |
10801 } | |
10802 } | |
10803 else | |
10804 { | |
10805 result = result_tail = Qnil; | |
10806 | |
10807 /* The standard `union' doesn't produce a "stable" union -- it | |
10808 iterates over the second list instead of the first one, and returns | |
10809 the values in backwards order. According to the CLTL2 | |
10810 documentation, `union' is not required to preserve the ordering of | |
10811 elements in any fashion; providing the functionality for a stable | |
10812 union is an XEmacs extension. */ | |
10813 { | |
10814 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) | |
10815 { | |
10816 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | |
10817 check_match, test_not_unboundp, | |
10818 test, key, 1, Qzero, Qnil))) | |
10819 { | |
10820 if (NILP (result)) | |
10821 { | |
10822 result = result_tail = Fcons (elt, Qnil); | |
10823 } | |
10824 else | |
10825 { | |
10826 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10827 result_tail = XCDR (result_tail); | |
10828 } | |
10829 } | |
10830 } | |
10831 } | |
10832 | |
10833 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result); | |
10834 } | |
10835 | |
10836 UNGCPRO; | |
10837 | |
10838 return result; | |
10839 } | |
10840 | |
10841 DEFUN ("set-exclusive-or", Fset_exclusive_or, 2, MANY, 0, /* | |
10842 Combine LIST1 and LIST2 using a set-exclusive-or operation. | |
10843 | |
10844 The result list contains all items that appear in exactly one of LIST1, LIST2. | |
10845 This is a non-destructive function; it makes a copy of the data if necessary | |
10846 to avoid corrupting the original LIST1 and LIST2. | |
10847 | |
10848 See `union' for the meaning of :test, :test-not and :key. | |
10849 | |
10850 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10851 return the items in the order they appear in LIST1, followed by the | |
10852 remaining items in the order they appear in LIST2. | |
10853 | |
10854 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10855 */ | |
10856 (int nargs, Lisp_Object *args)) | |
10857 { | |
10858 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | |
10859 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil; | |
10860 Elemcount len; | |
10861 Boolint test_not_unboundp = 1; | |
10862 check_test_func_t check_match = NULL, check_test = NULL; | |
10863 struct gcpro gcpro1, gcpro2, gcpro3; | |
10864 | |
10865 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4, | |
10866 (test, key, test_not, stable), NULL); | |
10867 | |
10868 CHECK_LIST (liszt1); | |
10869 CHECK_LIST (liszt2); | |
10870 | |
10871 CHECK_KEY_ARGUMENT (key); | |
10872 | |
10873 if (NILP (liszt2)) | |
10874 { | |
10875 return liszt1; | |
10876 } | |
10877 | |
10878 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10879 &test_not_unboundp, &check_test); | |
10880 | |
10881 GCPRO3 (tail, keyed, result); | |
10882 { | |
10883 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | |
10884 { | |
10885 keyed = KEY (key, elt); | |
10886 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10887 check_test, test_not_unboundp, | |
10888 test, key, 0, Qzero, Qnil))) | |
10889 { | |
10890 if (NILP (stable)) | |
10891 { | |
10892 result = Fcons (elt, result); | |
10893 } | |
10894 else if (NILP (result)) | |
10895 { | |
10896 result = result_tail = Fcons (elt, Qnil); | |
10897 } | |
10898 else | |
10899 { | |
10900 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10901 result_tail = XCDR (result_tail); | |
10902 } | |
10903 } | |
10904 } | |
10905 } | |
10906 | |
10907 { | |
10908 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) | |
10909 { | |
10910 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | |
10911 check_match, test_not_unboundp, | |
10912 test, key, 1, Qzero, Qnil))) | |
10913 { | |
10914 if (NILP (stable)) | |
10915 { | |
10916 result = Fcons (elt, result); | |
10917 } | |
10918 else if (NILP (result)) | |
10919 { | |
10920 result = result_tail = Fcons (elt, Qnil); | |
10921 } | |
10922 else | |
10923 { | |
10924 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10925 result_tail = XCDR (result_tail); | |
10926 } | |
10927 } | |
10928 } | |
10929 } | |
10930 UNGCPRO; | |
10931 | |
10932 return result; | |
10933 } | |
10934 | |
10935 DEFUN ("nset-exclusive-or", Fnset_exclusive_or, 2, MANY, 0, /* | |
10936 Combine LIST1 and LIST2 using a set-exclusive-or operation. | |
10937 | |
10938 The result list contains all items that appear in exactly one of LIST1 and | |
10939 LIST2. This is a destructive function; it reuses the storage of LIST1 and | |
10940 LIST2 whenever possible. | |
10941 | |
10942 See `union' for the meaning of :test, :test-not and :key. | |
10943 | |
10944 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10945 */ | |
10946 (int nargs, Lisp_Object *args)) | |
10947 { | |
10948 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | |
10949 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap; | |
10950 Lisp_Object prev_tail = Qnil, ignore = Qnil; | |
10951 Elemcount count; | |
10952 Boolint test_not_unboundp = 1; | |
10953 check_test_func_t check_match = NULL, check_test = NULL; | |
10954 struct gcpro gcpro1, gcpro2, gcpro3; | |
10955 | |
10956 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4, | |
10957 (test, key, test_not, stable), NULL); | |
10958 | |
10959 CHECK_LIST (liszt1); | |
10960 CHECK_LIST (liszt2); | |
10961 | |
10962 CHECK_KEY_ARGUMENT (key); | |
10963 | |
10964 if (NILP (liszt2)) | |
10965 { | |
10966 return liszt1; | |
10967 } | |
10968 | |
10969 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10970 &test_not_unboundp, &check_test); | |
10971 | |
10972 GCPRO3 (tail, keyed, result); | |
10973 | |
10974 tortoise_elt = tail = liszt1, count = 0; | |
10975 | |
10976 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | |
10977 (signal_malformed_list_error (liszt1), 0)) | |
10978 { | |
10979 keyed = KEY (key, elt); | |
10980 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10981 check_test, test_not_unboundp, | |
10982 test, key, 0, Qzero, Qnil))) | |
10983 { | |
10984 swap = XCDR (tail); | |
10985 | |
10986 if (NILP (prev_tail)) | |
10987 { | |
10988 liszt1 = XCDR (tail); | |
10989 } | |
10990 else | |
10991 { | |
10992 XSETCDR (prev_tail, swap); | |
10993 } | |
10994 | |
10995 XSETCDR (tail, result); | |
10996 result = tail; | |
10997 tail = swap; | |
10998 | |
10999 /* List is definitely not circular now! */ | |
11000 count = 0; | |
11001 } | |
11002 else | |
11003 { | |
11004 prev_tail = tail; | |
11005 tail = XCDR (tail); | |
11006 } | |
11007 | |
11008 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
11009 | |
11010 if (count & 1) | |
11011 { | |
11012 tortoise_elt = XCDR (tortoise_elt); | |
11013 } | |
11014 | |
11015 if (EQ (elt, tortoise_elt)) | |
11016 { | |
11017 signal_circular_list_error (liszt1); | |
11018 } | |
11019 } | |
11020 | |
11021 tortoise_elt = tail = liszt2, count = 0; | |
11022 | |
11023 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | |
11024 (signal_malformed_list_error (liszt2), 0)) | |
11025 { | |
11026 /* Need to leave the key calculation to list_position_cons_before(). */ | |
11027 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | |
11028 check_match, test_not_unboundp, | |
11029 test, key, 1, Qzero, Qnil))) | |
11030 { | |
11031 swap = XCDR (tail); | |
11032 XSETCDR (tail, result); | |
11033 result = tail; | |
11034 tail = swap; | |
11035 count = 0; | |
11036 } | |
11037 else | |
11038 { | |
11039 tail = XCDR (tail); | |
11040 } | |
11041 | |
11042 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
11043 | |
11044 if (count & 1) | |
11045 { | |
11046 tortoise_elt = XCDR (tortoise_elt); | |
11047 } | |
11048 | |
11049 if (EQ (elt, tortoise_elt)) | |
11050 { | |
11051 signal_circular_list_error (liszt1); | |
11052 } | |
11053 } | |
11054 | |
11055 UNGCPRO; | |
11056 | |
11057 return result; | |
11058 } | |
11059 | |
11060 | |
6189 Lisp_Object | 11061 Lisp_Object |
6190 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) | 11062 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) |
6191 { | 11063 { |
6192 return Fintern (concat2 (Fsymbol_name (symbol), | 11064 return Fintern (concat2 (Fsymbol_name (symbol), |
6193 build_ascstring (ascii_string)), | 11065 build_ascstring (ascii_string)), |
6199 { | 11071 { |
6200 return Fintern (concat2 (build_ascstring (ascii_string), | 11072 return Fintern (concat2 (build_ascstring (ascii_string), |
6201 Fsymbol_name (symbol)), | 11073 Fsymbol_name (symbol)), |
6202 Qnil); | 11074 Qnil); |
6203 } | 11075 } |
6204 | |
6205 | 11076 |
6206 /* #### this function doesn't belong in this file! */ | 11077 /* #### this function doesn't belong in this file! */ |
6207 | 11078 |
6208 #ifdef HAVE_GETLOADAVG | 11079 #ifdef HAVE_GETLOADAVG |
6209 #ifdef HAVE_SYS_LOADAVG_H | 11080 #ifdef HAVE_SYS_LOADAVG_H |
6817 syms_of_fns (void) | 11688 syms_of_fns (void) |
6818 { | 11689 { |
6819 INIT_LISP_OBJECT (bit_vector); | 11690 INIT_LISP_OBJECT (bit_vector); |
6820 | 11691 |
6821 DEFSYMBOL (Qstring_lessp); | 11692 DEFSYMBOL (Qstring_lessp); |
6822 DEFSYMBOL (Qsort); | |
6823 DEFSYMBOL (Qmerge); | 11693 DEFSYMBOL (Qmerge); |
6824 DEFSYMBOL (Qfill); | 11694 DEFSYMBOL (Qfill); |
6825 DEFSYMBOL (Qidentity); | 11695 DEFSYMBOL (Qidentity); |
6826 DEFSYMBOL (Qvector); | 11696 DEFSYMBOL (Qvector); |
6827 DEFSYMBOL (Qarray); | 11697 DEFSYMBOL (Qarray); |
6829 DEFSYMBOL (Qlist); | 11699 DEFSYMBOL (Qlist); |
6830 DEFSYMBOL (Qbit_vector); | 11700 DEFSYMBOL (Qbit_vector); |
6831 defsymbol (&QsortX, "sort*"); | 11701 defsymbol (&QsortX, "sort*"); |
6832 DEFSYMBOL (Qreduce); | 11702 DEFSYMBOL (Qreduce); |
6833 DEFSYMBOL (Qreplace); | 11703 DEFSYMBOL (Qreplace); |
11704 DEFSYMBOL (Qposition); | |
11705 DEFSYMBOL (Qfind); | |
11706 defsymbol (&QdeleteX, "delete*"); | |
11707 defsymbol (&QremoveX, "remove*"); | |
6834 | 11708 |
6835 DEFSYMBOL (Qmapconcat); | 11709 DEFSYMBOL (Qmapconcat); |
6836 defsymbol (&QmapcarX, "mapcar*"); | 11710 defsymbol (&QmapcarX, "mapcar*"); |
6837 DEFSYMBOL (Qmapvector); | 11711 DEFSYMBOL (Qmapvector); |
6838 DEFSYMBOL (Qmapcan); | 11712 DEFSYMBOL (Qmapcan); |
6842 DEFSYMBOL (Qsome); | 11716 DEFSYMBOL (Qsome); |
6843 DEFSYMBOL (Qevery); | 11717 DEFSYMBOL (Qevery); |
6844 DEFSYMBOL (Qmaplist); | 11718 DEFSYMBOL (Qmaplist); |
6845 DEFSYMBOL (Qmapl); | 11719 DEFSYMBOL (Qmapl); |
6846 DEFSYMBOL (Qmapcon); | 11720 DEFSYMBOL (Qmapcon); |
11721 DEFSYMBOL (Qnsubstitute); | |
11722 DEFSYMBOL (Qdelete_duplicates); | |
11723 DEFSYMBOL (Qsubstitute); | |
11724 DEFSYMBOL (Qmismatch); | |
11725 DEFSYMBOL (Qintersection); | |
11726 DEFSYMBOL (Qnintersection); | |
11727 DEFSYMBOL (Qsubsetp); | |
11728 DEFSYMBOL (Qset_difference); | |
11729 DEFSYMBOL (Qnset_difference); | |
11730 DEFSYMBOL (Qnunion); | |
6847 | 11731 |
6848 DEFKEYWORD (Q_from_end); | 11732 DEFKEYWORD (Q_from_end); |
6849 DEFKEYWORD (Q_initial_value); | 11733 DEFKEYWORD (Q_initial_value); |
6850 DEFKEYWORD (Q_start1); | 11734 DEFKEYWORD (Q_start1); |
6851 DEFKEYWORD (Q_start2); | 11735 DEFKEYWORD (Q_start2); |
6852 DEFKEYWORD (Q_end1); | 11736 DEFKEYWORD (Q_end1); |
6853 DEFKEYWORD (Q_end2); | 11737 DEFKEYWORD (Q_end2); |
11738 defkeyword (&Q_if_, ":if"); | |
11739 DEFKEYWORD (Q_if_not); | |
11740 DEFKEYWORD (Q_test_not); | |
11741 DEFKEYWORD (Q_count); | |
11742 DEFKEYWORD (Q_stable); | |
6854 | 11743 |
6855 DEFSYMBOL (Qyes_or_no_p); | 11744 DEFSYMBOL (Qyes_or_no_p); |
6856 | 11745 |
6857 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); | 11746 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); |
6858 | 11747 |
6859 DEFSUBR (Fidentity); | 11748 DEFSUBR (Fidentity); |
6860 DEFSUBR (Frandom); | 11749 DEFSUBR (Frandom); |
6861 DEFSUBR (Flength); | 11750 DEFSUBR (Flength); |
6862 DEFSUBR (Fsafe_length); | 11751 DEFSUBR (Fsafe_length); |
6863 DEFSUBR (Flist_length); | 11752 DEFSUBR (Flist_length); |
11753 DEFSUBR (Fcount); | |
6864 DEFSUBR (Fstring_equal); | 11754 DEFSUBR (Fstring_equal); |
6865 DEFSUBR (Fcompare_strings); | 11755 DEFSUBR (Fcompare_strings); |
6866 DEFSUBR (Fstring_lessp); | 11756 DEFSUBR (Fstring_lessp); |
6867 DEFSUBR (Fstring_modified_tick); | 11757 DEFSUBR (Fstring_modified_tick); |
6868 DEFSUBR (Fappend); | 11758 DEFSUBR (Fappend); |
6882 DEFSUBR (Fnbutlast); | 11772 DEFSUBR (Fnbutlast); |
6883 DEFSUBR (Fmember); | 11773 DEFSUBR (Fmember); |
6884 DEFSUBR (Fold_member); | 11774 DEFSUBR (Fold_member); |
6885 DEFSUBR (Fmemq); | 11775 DEFSUBR (Fmemq); |
6886 DEFSUBR (Fold_memq); | 11776 DEFSUBR (Fold_memq); |
11777 DEFSUBR (FmemberX); | |
11778 DEFSUBR (Fadjoin); | |
6887 DEFSUBR (Fassoc); | 11779 DEFSUBR (Fassoc); |
6888 DEFSUBR (Fold_assoc); | 11780 DEFSUBR (Fold_assoc); |
6889 DEFSUBR (Fassq); | 11781 DEFSUBR (Fassq); |
6890 DEFSUBR (Fold_assq); | 11782 DEFSUBR (Fold_assq); |
6891 DEFSUBR (Frassoc); | 11783 DEFSUBR (Frassoc); |
6892 DEFSUBR (Fold_rassoc); | 11784 DEFSUBR (Fold_rassoc); |
6893 DEFSUBR (Frassq); | 11785 DEFSUBR (Frassq); |
6894 DEFSUBR (Fold_rassq); | 11786 DEFSUBR (Fold_rassq); |
11787 | |
11788 DEFSUBR (Fposition); | |
11789 DEFSUBR (Ffind); | |
11790 | |
6895 DEFSUBR (Fdelete); | 11791 DEFSUBR (Fdelete); |
6896 DEFSUBR (Fold_delete); | 11792 DEFSUBR (Fold_delete); |
6897 DEFSUBR (Fdelq); | 11793 DEFSUBR (Fdelq); |
6898 DEFSUBR (Fold_delq); | 11794 DEFSUBR (Fold_delq); |
11795 DEFSUBR (FdeleteX); | |
11796 DEFSUBR (FremoveX); | |
6899 DEFSUBR (Fremassoc); | 11797 DEFSUBR (Fremassoc); |
6900 DEFSUBR (Fremassq); | 11798 DEFSUBR (Fremassq); |
6901 DEFSUBR (Fremrassoc); | 11799 DEFSUBR (Fremrassoc); |
6902 DEFSUBR (Fremrassq); | 11800 DEFSUBR (Fremrassq); |
11801 DEFSUBR (Fdelete_duplicates); | |
11802 DEFSUBR (Fremove_duplicates); | |
6903 DEFSUBR (Fnreverse); | 11803 DEFSUBR (Fnreverse); |
6904 DEFSUBR (Freverse); | 11804 DEFSUBR (Freverse); |
6905 DEFSUBR (FsortX); | 11805 DEFSUBR (FsortX); |
6906 Ffset (intern ("sort"), QsortX); | |
6907 DEFSUBR (Fmerge); | 11806 DEFSUBR (Fmerge); |
6908 DEFSUBR (Fplists_eq); | 11807 DEFSUBR (Fplists_eq); |
6909 DEFSUBR (Fplists_equal); | 11808 DEFSUBR (Fplists_equal); |
6910 DEFSUBR (Flax_plists_eq); | 11809 DEFSUBR (Flax_plists_eq); |
6911 DEFSUBR (Flax_plists_equal); | 11810 DEFSUBR (Flax_plists_equal); |
6929 DEFSUBR (Fobject_setplist); | 11828 DEFSUBR (Fobject_setplist); |
6930 DEFSUBR (Fequal); | 11829 DEFSUBR (Fequal); |
6931 DEFSUBR (Fequalp); | 11830 DEFSUBR (Fequalp); |
6932 DEFSUBR (Fold_equal); | 11831 DEFSUBR (Fold_equal); |
6933 DEFSUBR (Ffill); | 11832 DEFSUBR (Ffill); |
6934 Ffset (intern ("fillarray"), Qfill); | 11833 |
11834 DEFSUBR (FassocX); | |
11835 DEFSUBR (FrassocX); | |
6935 | 11836 |
6936 DEFSUBR (Fnconc); | 11837 DEFSUBR (Fnconc); |
6937 DEFSUBR (FmapcarX); | 11838 DEFSUBR (FmapcarX); |
6938 DEFSUBR (Fmapvector); | 11839 DEFSUBR (Fmapvector); |
6939 DEFSUBR (Fmapcan); | 11840 DEFSUBR (Fmapcan); |
6941 DEFSUBR (Fmapconcat); | 11842 DEFSUBR (Fmapconcat); |
6942 DEFSUBR (Fmap); | 11843 DEFSUBR (Fmap); |
6943 DEFSUBR (Fmap_into); | 11844 DEFSUBR (Fmap_into); |
6944 DEFSUBR (Fsome); | 11845 DEFSUBR (Fsome); |
6945 DEFSUBR (Fevery); | 11846 DEFSUBR (Fevery); |
6946 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc"))); | 11847 Ffset (intern ("mapc-internal"), Qmapc); |
6947 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*"))); | 11848 Ffset (intern ("mapcar"), QmapcarX); |
6948 DEFSUBR (Fmaplist); | 11849 DEFSUBR (Fmaplist); |
6949 DEFSUBR (Fmapl); | 11850 DEFSUBR (Fmapl); |
6950 DEFSUBR (Fmapcon); | 11851 DEFSUBR (Fmapcon); |
6951 | 11852 |
6952 DEFSUBR (Freduce); | 11853 DEFSUBR (Freduce); |
6953 DEFSUBR (Freplace_list); | 11854 DEFSUBR (Freplace_list); |
6954 DEFSUBR (Freplace); | 11855 DEFSUBR (Freplace); |
11856 DEFSUBR (Fsubsetp); | |
11857 DEFSUBR (Fnsubstitute); | |
11858 DEFSUBR (Fsubstitute); | |
11859 DEFSUBR (Fsublis); | |
11860 DEFSUBR (Fnsublis); | |
11861 DEFSUBR (Fsubst); | |
11862 DEFSUBR (Fnsubst); | |
11863 DEFSUBR (Ftree_equal); | |
11864 DEFSUBR (Fmismatch); | |
11865 DEFSUBR (Fsearch); | |
11866 DEFSUBR (Funion); | |
11867 DEFSUBR (Fnunion); | |
11868 DEFSUBR (Fintersection); | |
11869 DEFSUBR (Fnintersection); | |
11870 DEFSUBR (Fset_difference); | |
11871 DEFSUBR (Fnset_difference); | |
11872 DEFSUBR (Fset_exclusive_or); | |
11873 DEFSUBR (Fnset_exclusive_or); | |
11874 | |
6955 DEFSUBR (Fload_average); | 11875 DEFSUBR (Fload_average); |
6956 DEFSUBR (Ffeaturep); | 11876 DEFSUBR (Ffeaturep); |
6957 DEFSUBR (Frequire); | 11877 DEFSUBR (Frequire); |
6958 DEFSUBR (Fprovide); | 11878 DEFSUBR (Fprovide); |
6959 DEFSUBR (Fbase64_encode_region); | 11879 DEFSUBR (Fbase64_encode_region); |