comparison src/fns.c @ 5327:d1b17a33450b

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