comparison src/fns.c @ 5393:e99b473303e3

Use GC_EXTERNAL_LIST_LOOP_* where appropriate, fns.c src/ChangeLog addition: 2011-04-04 Aidan Kehoe <kehoea@parhasard.net> * lisp.h (GC_EXTERNAL_LIST_LOOP_3, GC_EXTERNAL_LIST_LOOP_4): New. * fns.c (count_with_tail, list_position_cons_before, FassocX): * fns.c (FrassocX, position, FdeleteX, FremoveX): * fns.c (list_delete_duplicates_from_end): * fns.c (Fdelete_duplicates, Fremove_duplicates, Freduce): * fns.c (Fnsubstitute, Fsubstitute, sublis, nsublis, Fnsublis): * fns.c (venn, nvenn, Funion, Fset_exclusive_or, Fnset_exclusive_or): Use GC_EXTERNAL_LIST_LOOP_* in the sequence functions in fns.c where appropriate, there were some corner cases where my old approach was unsafe (mainly if the circularity checking's tortoise lost GCPRO protection. Add GC_EXTERNAL_LIST_LOOP_{3,4}, analogous to GC_EXTERNAL_LIST_LOOP_2.
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 04 Apr 2011 00:20:09 +0100
parents d967d96ca043
children 484b437fc7b4
comparison
equal deleted inserted replaced
5392:25c10648ffba 5393:e99b473303e3
1007 1007
1008 *tail_out = Qnil; 1008 *tail_out = Qnil;
1009 1009
1010 if (CONSP (sequence)) 1010 if (CONSP (sequence))
1011 { 1011 {
1012 Lisp_Object elt, tail = Qnil;
1013 struct gcpro gcpro1;
1014
1015 if (EQ (caller, Qcount) && !NILP (from_end) 1012 if (EQ (caller, Qcount) && !NILP (from_end)
1016 && (!EQ (key, Qnil) || 1013 && (!EQ (key, Qnil) ||
1017 check_test == check_other_nokey || check_test == check_if_nokey)) 1014 check_test == check_other_nokey || check_test == check_if_nokey))
1018 { 1015 {
1019 /* #'count, #'count-if, and #'count-if-not are documented to have 1016 /* #'count, #'count-if, and #'count-if-not are documented to have
1024 return list_count_from_end (item, sequence, check_test, 1021 return list_count_from_end (item, sequence, check_test,
1025 test_not_unboundp, test, key, 1022 test_not_unboundp, test, key,
1026 start, end); 1023 start, end);
1027 } 1024 }
1028 1025
1029 GCPRO1 (tail);
1030
1031 /* If COUNT is non-nil and FROM-END is t, we can give the tail 1026 /* If COUNT is non-nil and FROM-END is t, we can give the tail
1032 containing the last match, since that's what #'remove* is 1027 containing the last match, since that's what #'remove* is
1033 interested in (a zero or negative COUNT won't ever reach 1028 interested in (a zero or negative COUNT won't ever reach
1034 count_with_tail(), our callers will return immediately on seeing 1029 count_with_tail(), our callers will return immediately on seeing
1035 it). */ 1030 it). */
1037 { 1032 {
1038 counting = EMACS_INT_MAX; 1033 counting = EMACS_INT_MAX;
1039 } 1034 }
1040 1035
1041 { 1036 {
1042 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) 1037 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
1043 { 1038 {
1044 if (!(ii < ending)) 1039 if (!(ii < ending))
1045 { 1040 {
1046 break; 1041 break;
1047 } 1042 }
1058 } 1053 }
1059 } 1054 }
1060 1055
1061 ii++; 1056 ii++;
1062 } 1057 }
1058 END_GC_EXTERNAL_LIST_LOOP (elt);
1063 } 1059 }
1064
1065 UNGCPRO;
1066 1060
1067 if ((ii < starting || (ii < ending && !NILP (end))) && 1061 if ((ii < starting || (ii < ending && !NILP (end))) &&
1068 encountered != counting) 1062 encountered != counting)
1069 { 1063 {
1070 check_sequence_range (args[1], start, end, Flength (args[1])); 1064 check_sequence_range (args[1], start, end, Flength (args[1]));
2620 Boolint test_not_unboundp, 2614 Boolint test_not_unboundp,
2621 Lisp_Object test, Lisp_Object key, 2615 Lisp_Object test, Lisp_Object key,
2622 Boolint reverse_test_order, 2616 Boolint reverse_test_order,
2623 Lisp_Object start, Lisp_Object end) 2617 Lisp_Object start, Lisp_Object end)
2624 { 2618 {
2625 struct gcpro gcpro1, gcpro2; 2619 struct gcpro gcpro1;
2626 Lisp_Object elt = Qnil, tail = list, tail_before = Qnil; 2620 Lisp_Object tail_before = Qnil;
2627 Elemcount len, ii = 0, starting = XINT (start); 2621 Elemcount ii = 0, starting = XINT (start);
2628 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end); 2622 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end);
2629 2623
2630 GCPRO2 (elt, tail); 2624 GCPRO1 (tail_before);
2631 2625
2632 if (check_test == check_eq_nokey) 2626 if (check_test == check_eq_nokey)
2633 { 2627 {
2634 /* TEST is #'eq, no need to call any C functions, and the test order 2628 /* TEST is #'eq, no need to call any C functions, and the test order
2635 won't be visible. */ 2629 won't be visible. */
2636 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) 2630 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
2637 { 2631 {
2638 if (starting <= ii && ii < ending && 2632 if (starting <= ii && ii < ending &&
2639 EQ (item, elt) == test_not_unboundp) 2633 EQ (item, elt) == test_not_unboundp)
2640 { 2634 {
2641 *cons_out = tail_before; 2635 *cons_out = tail_before;
2652 tail_before = tail; 2646 tail_before = tail;
2653 } 2647 }
2654 } 2648 }
2655 else 2649 else
2656 { 2650 {
2657 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) 2651 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
2658 { 2652 {
2659 if (starting <= ii && ii < ending && 2653 if (starting <= ii && ii < ending &&
2660 (reverse_test_order ? 2654 (reverse_test_order ?
2661 check_test (test, key, elt, item) : 2655 check_test (test, key, elt, item) :
2662 check_test (test, key, item, elt)) == test_not_unboundp) 2656 check_test (test, key, item, elt)) == test_not_unboundp)
2663 { 2657 {
2664 *cons_out = tail_before; 2658 *cons_out = tail_before;
2665 RETURN_UNGCPRO (make_integer (ii)); 2659 XUNGCPRO (elt);
2660 UNGCPRO;
2661 return make_integer (ii);
2666 } 2662 }
2667 else 2663 else
2668 { 2664 {
2669 if (ii >= ending) 2665 if (ii >= ending)
2670 { 2666 {
2672 } 2668 }
2673 } 2669 }
2674 ii++; 2670 ii++;
2675 tail_before = tail; 2671 tail_before = tail;
2676 } 2672 }
2673 END_GC_EXTERNAL_LIST_LOOP (elt);
2677 } 2674 }
2678 2675
2679 RETURN_UNGCPRO (Qnil); 2676 RETURN_UNGCPRO (Qnil);
2680 } 2677 }
2681 2678
2858 } 2855 }
2859 } 2856 }
2860 } 2857 }
2861 else 2858 else
2862 { 2859 {
2863 Lisp_Object tailed = alist; 2860 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
2864 struct gcpro gcpro1; 2861 {
2865 2862 if (CONSP (elt) &&
2866 GCPRO1 (tailed); 2863 check_test (test, key, item, XCAR (elt)) == test_not_unboundp)
2867 {
2868 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail)
2869 {
2870 tailed = tail;
2871
2872 if (check_test (test, key, item, elt_car) == test_not_unboundp)
2873 { 2864 {
2874 RETURN_UNGCPRO (elt); 2865 XUNGCPRO (elt);
2866 return elt;
2875 } 2867 }
2876 } 2868 }
2877 } 2869 END_GC_EXTERNAL_LIST_LOOP (elt);
2878 UNGCPRO;
2879 } 2870 }
2880 2871
2881 return Qnil; 2872 return Qnil;
2882 } 2873 }
2883 2874
2967 } 2958 }
2968 } 2959 }
2969 } 2960 }
2970 else 2961 else
2971 { 2962 {
2972 struct gcpro gcpro1; 2963 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
2973 Lisp_Object tailed = alist; 2964 {
2974 2965 if (CONSP (elt) &&
2975 GCPRO1 (tailed); 2966 check_test (test, key, item, XCDR (elt)) == test_not_unboundp)
2976 { 2967 {
2977 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) 2968 XUNGCPRO (elt);
2978 { 2969 return elt;
2979 tailed = tail; 2970 }
2980 2971 }
2981 if (check_test (test, key, item, elt_cdr) == test_not_unboundp) 2972 END_GC_EXTERNAL_LIST_LOOP (elt);
2982 {
2983 RETURN_UNGCPRO (elt);
2984 }
2985 }
2986 }
2987 UNGCPRO;
2988 } 2973 }
2989 2974
2990 return Qnil; 2975 return Qnil;
2991 } 2976 }
2992 2977
3012 2997
3013 *object_out = default_; 2998 *object_out = default_;
3014 2999
3015 if (CONSP (sequence)) 3000 if (CONSP (sequence))
3016 { 3001 {
3017 Lisp_Object elt, tail = Qnil;
3018 struct gcpro gcpro1;
3019
3020 if (!(starting < ending)) 3002 if (!(starting < ending))
3021 { 3003 {
3022 check_sequence_range (sequence, start, end, Flength (sequence)); 3004 check_sequence_range (sequence, start, end, Flength (sequence));
3023 /* starting could be equal to ending, in which case nil is what 3005 /* starting could be equal to ending, in which case nil is what
3024 we want to return. */ 3006 we want to return. */
3025 return Qnil; 3007 return Qnil;
3026 } 3008 }
3027 3009
3028 GCPRO1 (tail);
3029
3030 { 3010 {
3031 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) 3011 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
3032 { 3012 {
3033 if (starting <= ii && ii < ending 3013 if (starting <= ii && ii < ending
3034 && check_test (test, key, item, elt) == test_not_unboundp) 3014 && check_test (test, key, item, elt) == test_not_unboundp)
3035 { 3015 {
3036 result = make_integer (ii); 3016 result = make_integer (ii);
3037 *object_out = elt; 3017 *object_out = elt;
3038 3018
3039 if (NILP (from_end)) 3019 if (NILP (from_end))
3040 { 3020 {
3041 UNGCPRO; 3021 XUNGCPRO (elt);
3042 return result; 3022 return result;
3043 } 3023 }
3044 } 3024 }
3045 else if (ii == ending) 3025 else if (ii == ending)
3046 { 3026 {
3047 break; 3027 break;
3048 } 3028 }
3049 3029
3050 ii++; 3030 ii++;
3051 } 3031 }
3032 END_GC_EXTERNAL_LIST_LOOP (elt);
3052 } 3033 }
3053
3054 UNGCPRO;
3055 3034
3056 if (ii < starting || (ii < ending && !NILP (end))) 3035 if (ii < starting || (ii < ending && !NILP (end)))
3057 { 3036 {
3058 check_sequence_range (sequence, start, end, Flength (sequence)); 3037 check_sequence_range (sequence, start, end, Flength (sequence));
3059 } 3038 }
3257 3236
3258 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) 3237 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT)
3259 */ 3238 */
3260 (int nargs, Lisp_Object *args)) 3239 (int nargs, Lisp_Object *args))
3261 { 3240 {
3262 Lisp_Object item = args[0], sequence = args[1], tail = sequence; 3241 Lisp_Object item = args[0], sequence = args[1];
3263 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; 3242 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX;
3264 Elemcount len, ii = 0, encountered = 0, presenting = 0; 3243 Elemcount len, ii = 0, encountered = 0, presenting = 0;
3265 Boolint test_not_unboundp = 1; 3244 Boolint test_not_unboundp = 1;
3266 check_test_func_t check_test = NULL; 3245 check_test_func_t check_test = NULL;
3267 struct gcpro gcpro1;
3268 3246
3269 PARSE_KEYWORDS (FdeleteX, nargs, args, 9, 3247 PARSE_KEYWORDS (FdeleteX, nargs, args, 9,
3270 (test, if_not, if_, test_not, key, start, end, from_end, 3248 (test, if_not, if_, test_not, key, start, end, from_end,
3271 count), (start = Qzero, count = Qunbound)); 3249 count), (start = Qzero, count = Qunbound));
3272 3250
3307 check_test = get_check_test_function (item, &test, test_not, if_, if_not, 3285 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3308 key, &test_not_unboundp); 3286 key, &test_not_unboundp);
3309 3287
3310 if (CONSP (sequence)) 3288 if (CONSP (sequence))
3311 { 3289 {
3312 Lisp_Object prev_tail_list_elt = Qnil, list_elt = Qnil; 3290 Lisp_Object prev_tail_list_elt = Qnil, ignore = Qnil;
3313 Elemcount list_len = 0, deleted = 0; 3291 Elemcount list_len = 0, deleted = 0;
3292 struct gcpro gcpro1;
3314 3293
3315 if (!NILP (count) && !NILP (from_end)) 3294 if (!NILP (count) && !NILP (from_end))
3316 { 3295 {
3317 /* Both COUNT and FROM-END were specified; we need to traverse the 3296 /* Both COUNT and FROM-END were specified; we need to traverse the
3318 list twice. */ 3297 list twice. */
3319 Lisp_Object present = count_with_tail (&list_elt, nargs, args, 3298 Lisp_Object present = count_with_tail (&ignore, nargs, args,
3320 QdeleteX); 3299 QdeleteX);
3321 3300
3322 if (ZEROP (present)) 3301 if (ZEROP (present))
3323 { 3302 {
3324 return sequence; 3303 return sequence;
3332 of matching items we need to ignore before we start to 3311 of matching items we need to ignore before we start to
3333 delete. */ 3312 delete. */
3334 presenting = presenting <= counting ? 0 : presenting - counting; 3313 presenting = presenting <= counting ? 0 : presenting - counting;
3335 } 3314 }
3336 3315
3337 GCPRO1 (tail); 3316 GCPRO1 (prev_tail_list_elt);
3338 ii = -1; 3317 ii = -1;
3339 3318
3340 { 3319 {
3341 EXTERNAL_LIST_LOOP_4_NO_DECLARE (list_elt, sequence, tail, list_len) 3320 GC_EXTERNAL_LIST_LOOP_4 (list_elt, sequence, tail, list_len)
3342 { 3321 {
3343 ii++; 3322 ii++;
3344 3323
3345 if (starting <= ii && ii < ending && 3324 if (starting <= ii && ii < ending &&
3346 (check_test (test, key, item, list_elt) == test_not_unboundp) 3325 (check_test (test, key, item, list_elt) == test_not_unboundp)
3367 { 3346 {
3368 break; 3347 break;
3369 } 3348 }
3370 } 3349 }
3371 } 3350 }
3351 END_GC_EXTERNAL_LIST_LOOP (list_elt);
3372 } 3352 }
3373 3353
3374 UNGCPRO; 3354 UNGCPRO;
3375 3355
3376 if ((ii < starting || (ii < ending && !NILP (end))) && 3356 if ((ii < starting || (ii < ending && !NILP (end))) &&
3604 (int nargs, Lisp_Object *args)) 3584 (int nargs, Lisp_Object *args))
3605 { 3585 {
3606 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil, 3586 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil,
3607 tail = Qnil; 3587 tail = Qnil;
3608 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; 3588 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX;
3609 Elemcount len, ii = 0, encountered = 0, presenting = 0; 3589 Elemcount ii = 0, encountered = 0, presenting = 0;
3610 Boolint test_not_unboundp = 1; 3590 Boolint test_not_unboundp = 1;
3611 check_test_func_t check_test = NULL; 3591 check_test_func_t check_test = NULL;
3612 struct gcpro gcpro1;
3613 3592
3614 PARSE_KEYWORDS (FremoveX, nargs, args, 9, 3593 PARSE_KEYWORDS (FremoveX, nargs, args, 9,
3615 (test, if_not, if_, test_not, key, start, end, from_end, 3594 (test, if_not, if_, test_not, key, start, end, from_end,
3616 count), (start = Qzero)); 3595 count), (start = Qzero));
3617 3596
3655 3634
3656 matched_count = count_with_tail (&tail, nargs, args, QremoveX); 3635 matched_count = count_with_tail (&tail, nargs, args, QremoveX);
3657 3636
3658 if (!ZEROP (matched_count)) 3637 if (!ZEROP (matched_count))
3659 { 3638 {
3660 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; 3639 Lisp_Object result = Qnil, result_tail = Qnil;
3661 GCPRO1 (tailing); 3640 struct gcpro gcpro1, gcpro2;
3662 3641
3663 if (!NILP (count) && !NILP (from_end)) 3642 if (!NILP (count) && !NILP (from_end))
3664 { 3643 {
3665 presenting = XINT (matched_count); 3644 presenting = XINT (matched_count);
3666 3645
3670 is the number of matching items we need to ignore before we 3649 is the number of matching items we need to ignore before we
3671 start to delete. */ 3650 start to delete. */
3672 presenting = presenting <= counting ? 0 : presenting - counting; 3651 presenting = presenting <= counting ? 0 : presenting - counting;
3673 } 3652 }
3674 3653
3654 GCPRO2 (result, tail);
3675 { 3655 {
3676 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) 3656 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
3677 { 3657 {
3678 if (EQ (tail, tailing)) 3658 if (EQ (tail, tailing))
3679 { 3659 {
3660 XUNGCPRO (elt);
3661
3680 if (NILP (result)) 3662 if (NILP (result))
3681 { 3663 {
3682 RETURN_UNGCPRO (XCDR (tail)); 3664 return XCDR (tail);
3683 } 3665 }
3684 3666
3685 XSETCDR (result_tail, XCDR (tail)); 3667 XSETCDR (result_tail, XCDR (tail));
3686 RETURN_UNGCPRO (result); 3668 return result;
3687 } 3669 }
3688 else if (starting <= ii && ii < ending && 3670 else if (starting <= ii && ii < ending &&
3689 (check_test (test, key, item, elt) == test_not_unboundp) 3671 (check_test (test, key, item, elt) == test_not_unboundp)
3690 && (presenting ? encountered++ >= presenting 3672 && (presenting ? encountered++ >= presenting
3691 : encountered++ < counting)) 3673 : encountered++ < counting))
3707 break; 3689 break;
3708 } 3690 }
3709 3691
3710 ii++; 3692 ii++;
3711 } 3693 }
3694 END_GC_EXTERNAL_LIST_LOOP (elt);
3712 } 3695 }
3713
3714 UNGCPRO; 3696 UNGCPRO;
3715 3697
3716 if (ii < starting || (ii < ending && !NILP (end))) 3698 if (ii < starting || (ii < ending && !NILP (end)))
3717 { 3699 {
3718 check_sequence_range (args[0], start, end, Flength (args[0])); 3700 check_sequence_range (args[0], start, end, Flength (args[0]));
3827 Boolint test_not_unboundp, 3809 Boolint test_not_unboundp,
3828 Lisp_Object test, Lisp_Object key, 3810 Lisp_Object test, Lisp_Object key,
3829 Lisp_Object start, 3811 Lisp_Object start,
3830 Lisp_Object end, Boolint copy) 3812 Lisp_Object end, Boolint copy)
3831 { 3813 {
3832 Lisp_Object checking = Qnil, elt, tail, result = list; 3814 Lisp_Object checking = Qnil, result = list;
3833 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail; 3815 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail;
3834 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start); 3816 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start);
3835 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1; 3817 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1;
3836 Elemcount ii = 0; 3818 Elemcount ii = 0;
3837 struct gcpro gcpro1, gcpro2; 3819 struct gcpro gcpro1;
3838 3820
3839 /* We can't delete (or remove) as we go, because that breaks START and 3821 /* We can't delete (or remove) as we go, because that breaks START and
3840 END. We could if END were nil, and that would change an ON(N + 2) 3822 END. We could if END were nil, and that would change an ON(N + 2)
3841 algorithm to an ON^2 algorithm; list_position_cons_before() would need to 3823 algorithm to an ON^2 algorithm; list_position_cons_before() would need to
3842 be modified to return the cons *before* the one containing the item for 3824 be modified to return the cons *before* the one containing the item for
3852 3834
3853 deleting->size = len; 3835 deleting->size = len;
3854 memset (&(deleting->bits), 0, 3836 memset (&(deleting->bits), 0,
3855 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); 3837 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
3856 3838
3857 GCPRO2 (tail, keyed); 3839 GCPRO1 (keyed);
3858 3840
3859 { 3841 {
3860 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) 3842 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
3861 { 3843 {
3862 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii)) 3844 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii))
3863 { 3845 {
3864 ii++; 3846 ii++;
3865 continue; 3847 continue;
3882 XCDR (checking) : XCDR (XCDR (position_cons)); 3864 XCDR (checking) : XCDR (XCDR (position_cons));
3883 pos += 1; 3865 pos += 1;
3884 } 3866 }
3885 ii++; 3867 ii++;
3886 } 3868 }
3869 END_GC_EXTERNAL_LIST_LOOP (elt);
3887 } 3870 }
3888 3871
3889 UNGCPRO; 3872 UNGCPRO;
3890 3873
3891 ii = 0; 3874 ii = 0;
3897 result = result_tail = Fcons (XCAR (list), Qnil); 3880 result = result_tail = Fcons (XCAR (list), Qnil);
3898 list = XCDR (list); 3881 list = XCDR (list);
3899 ii = 1; 3882 ii = 1;
3900 3883
3901 { 3884 {
3902 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) 3885 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
3903 { 3886 {
3904 if (ii == greatest_pos_seen) 3887 if (ii == greatest_pos_seen)
3905 { 3888 {
3906 XSETCDR (result_tail, XCDR (tail)); 3889 XSETCDR (result_tail, XCDR (tail));
3907 break; 3890 break;
3915 } 3898 }
3916 } 3899 }
3917 } 3900 }
3918 else 3901 else
3919 { 3902 {
3920 EXTERNAL_LIST_LOOP_DELETE_IF (elt0, list, 3903 EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
3921 bit_vector_bit (deleting, ii++)); 3904 bit_vector_bit (deleting, ii++));
3922 } 3905 }
3923 } 3906 }
3924 3907
3925 return result; 3908 return result;
3943 3926
3944 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) 3927 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
3945 */ 3928 */
3946 (int nargs, Lisp_Object *args)) 3929 (int nargs, Lisp_Object *args))
3947 { 3930 {
3948 Lisp_Object sequence = args[0], tail = sequence, keyed = Qnil, elt = Qnil; 3931 Lisp_Object sequence = args[0], keyed = Qnil;
3949 Lisp_Object elt0 = Qnil, positioned = Qnil, ignore = Qnil; 3932 Lisp_Object positioned = Qnil, ignore = Qnil;
3950 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0; 3933 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0;
3951 Boolint test_not_unboundp = 1; 3934 Boolint test_not_unboundp = 1;
3952 check_test_func_t check_test = NULL; 3935 check_test_func_t check_test = NULL;
3953 struct gcpro gcpro1, gcpro2; 3936 struct gcpro gcpro1, gcpro2;
3954 3937
3976 if (NILP (from_end)) 3959 if (NILP (from_end))
3977 { 3960 {
3978 Lisp_Object prev_tail = Qnil; 3961 Lisp_Object prev_tail = Qnil;
3979 Elemcount deleted = 0; 3962 Elemcount deleted = 0;
3980 3963
3981 GCPRO2 (tail, keyed); 3964 GCPRO2 (keyed, prev_tail);
3982 3965
3983 { 3966 {
3984 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) 3967 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
3985 { 3968 {
3986 if (starting <= ii && ii < ending) 3969 if (starting <= ii && ii < ending)
3987 { 3970 {
3988 keyed = KEY (key, elt); 3971 keyed = KEY (key, elt);
3989 positioned 3972 positioned
4010 break; 3993 break;
4011 } 3994 }
4012 3995
4013 ii++; 3996 ii++;
4014 } 3997 }
3998 END_GC_EXTERNAL_LIST_LOOP (elt);
4015 } 3999 }
4016 { 4000 {
4017 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) 4001 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4018 { 4002 {
4019 if (!(starting <= ii && ii <= ending)) 4003 if (!(starting <= ii && ii <= ending))
4020 { 4004 {
4021 prev_tail = tail; 4005 prev_tail = tail;
4022 ii++; 4006 ii++;
4023 continue; 4007 continue;
4024 } 4008 }
4025 4009
4026 keyed = KEY (key, elt0); 4010 keyed = KEY (key, elt);
4027 positioned 4011 positioned
4028 = list_position_cons_before (&ignore, keyed, XCDR (tail), 4012 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4029 check_test, test_not_unboundp, 4013 check_test, test_not_unboundp,
4030 test, key, 0, 4014 test, key, 0,
4031 make_int (max (starting 4015 make_int (max (starting
4050 } 4034 }
4051 } 4035 }
4052 4036
4053 ii++; 4037 ii++;
4054 } 4038 }
4039 END_GC_EXTERNAL_LIST_LOOP (elt);
4055 } 4040 }
4041
4056 UNGCPRO; 4042 UNGCPRO;
4057 4043
4058 if ((ii < starting || (ii < ending && !NILP (end)))) 4044 if ((ii < starting || (ii < ending && !NILP (end))))
4059 { 4045 {
4060 check_sequence_range (args[0], start, end, 4046 check_sequence_range (args[0], start, end,
4070 0); 4056 0);
4071 } 4057 }
4072 } 4058 }
4073 else if (STRINGP (sequence)) 4059 else if (STRINGP (sequence))
4074 { 4060 {
4061 Lisp_Object elt = Qnil;
4062
4075 if (EQ (Qidentity, key)) 4063 if (EQ (Qidentity, key))
4076 { 4064 {
4077 /* We know all the elements will be characters; set check_test to 4065 /* We know all the elements will be characters; set check_test to
4078 reflect that. This isn't useful if KEY is not #'identity, since 4066 reflect that. This isn't useful if KEY is not #'identity, since
4079 it may return non-characters for the elements. */ 4067 it may return non-characters for the elements. */
4088 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; 4076 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
4089 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging; 4077 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging;
4090 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor; 4078 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor;
4091 Elemcount deleted = 0; 4079 Elemcount deleted = 0;
4092 4080
4093 elt = Qnil;
4094 GCPRO1 (elt); 4081 GCPRO1 (elt);
4095 4082
4096 while (cursor_offset < byte_len) 4083 while (cursor_offset < byte_len)
4097 { 4084 {
4098 if (starting <= ii && ii < ending) 4085 if (starting <= ii && ii < ending)
4243 else if (VECTORP (sequence)) 4230 else if (VECTORP (sequence))
4244 { 4231 {
4245 Elemcount deleted = 0; 4232 Elemcount deleted = 0;
4246 Lisp_Object *content = XVECTOR_DATA (sequence); 4233 Lisp_Object *content = XVECTOR_DATA (sequence);
4247 struct Lisp_Bit_Vector *deleting; 4234 struct Lisp_Bit_Vector *deleting;
4235 Lisp_Object elt = Qnil;
4248 4236
4249 len = XVECTOR_LENGTH (sequence); 4237 len = XVECTOR_LENGTH (sequence);
4250 check_sequence_range (sequence, start, end, make_integer (len)); 4238 check_sequence_range (sequence, start, end, make_integer (len));
4251 4239
4252 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) 4240 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4326 that's the possible number of distinct elements if EQ is regarded 4314 that's the possible number of distinct elements if EQ is regarded
4327 as identity, which it should be). But to support arbitrary TEST 4315 as identity, which it should be). But to support arbitrary TEST
4328 and KEY arguments, which may be non-deterministic from our 4316 and KEY arguments, which may be non-deterministic from our
4329 perspective, we need the same algorithm as for vectors. */ 4317 perspective, we need the same algorithm as for vectors. */
4330 struct Lisp_Bit_Vector *deleting; 4318 struct Lisp_Bit_Vector *deleting;
4319 Lisp_Object elt = Qnil;
4331 4320
4332 len = bit_vector_length (bv); 4321 len = bit_vector_length (bv);
4333 4322
4334 if (EQ (Qidentity, key)) 4323 if (EQ (Qidentity, key))
4335 { 4324 {
4427 4416
4428 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) 4417 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
4429 */ 4418 */
4430 (int nargs, Lisp_Object *args)) 4419 (int nargs, Lisp_Object *args))
4431 { 4420 {
4432 Lisp_Object sequence = args[0], tail = sequence, keyed, positioned = Qnil; 4421 Lisp_Object sequence = args[0], keyed, positioned = Qnil;
4433 Lisp_Object result = sequence, result_tail = result, cursor = Qnil; 4422 Lisp_Object result = sequence, result_tail = result, cursor = Qnil;
4434 Lisp_Object cons_with_shared_tail = Qnil, elt, elt0; 4423 Lisp_Object cons_with_shared_tail = Qnil;
4435 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0; 4424 Elemcount starting = 0, ending = EMACS_INT_MAX, ii = 0;
4436 Boolint test_not_unboundp = 1; 4425 Boolint test_not_unboundp = 1;
4437 check_test_func_t check_test = NULL; 4426 check_test_func_t check_test = NULL;
4438 struct gcpro gcpro1, gcpro2, gcpro3; 4427 struct gcpro gcpro1, gcpro2;
4439 4428
4440 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6, 4429 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6,
4441 (test, key, test_not, start, end, from_end), 4430 (test, key, test_not, start, end, from_end),
4442 (start = Qzero)); 4431 (start = Qzero));
4443 4432
4467 4456
4468 if (NILP (from_end)) 4457 if (NILP (from_end))
4469 { 4458 {
4470 Lisp_Object ignore = Qnil; 4459 Lisp_Object ignore = Qnil;
4471 4460
4472 GCPRO3 (tail, keyed, result); 4461 GCPRO2 (keyed, result);
4473 4462
4474 { 4463 {
4475 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) 4464 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4476 { 4465 {
4477 if (starting <= ii && ii <= ending) 4466 if (starting <= ii && ii <= ending)
4478 { 4467 {
4479 keyed = KEY (key, elt); 4468 keyed = KEY (key, elt);
4480 positioned 4469 positioned
4498 break; 4487 break;
4499 } 4488 }
4500 4489
4501 ii++; 4490 ii++;
4502 } 4491 }
4492 END_GC_EXTERNAL_LIST_LOOP (elt);
4503 } 4493 }
4504 4494
4505 { 4495 {
4506 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) 4496 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4507 { 4497 {
4508 if (!(starting <= ii && ii <= ending)) 4498 if (!(starting <= ii && ii <= ending))
4509 { 4499 {
4510 ii++; 4500 ii++;
4511 continue; 4501 continue;
4514 /* For this algorithm, each time we encounter an object to be 4504 /* For this algorithm, each time we encounter an object to be
4515 removed, copy the output list from the tail beyond the last 4505 removed, copy the output list from the tail beyond the last
4516 removed cons to this one. Otherwise, the tail of the output list 4506 removed cons to this one. Otherwise, the tail of the output list
4517 is shared with the input list, which is OK. */ 4507 is shared with the input list, which is OK. */
4518 4508
4519 keyed = KEY (key, elt0); 4509 keyed = KEY (key, elt);
4520 positioned 4510 positioned
4521 = list_position_cons_before (&ignore, keyed, XCDR (tail), 4511 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4522 check_test, test_not_unboundp, 4512 check_test, test_not_unboundp,
4523 test, key, 0, 4513 test, key, 0,
4524 make_int (max (starting - (ii + 1), 4514 make_int (max (starting - (ii + 1),
4546 cons_with_shared_tail = result_tail; 4536 cons_with_shared_tail = result_tail;
4547 } 4537 }
4548 4538
4549 ii++; 4539 ii++;
4550 } 4540 }
4541 END_GC_EXTERNAL_LIST_LOOP (elt);
4551 } 4542 }
4543
4552 UNGCPRO; 4544 UNGCPRO;
4553 4545
4554 if ((ii < starting || (ii < ending && !NILP (end)))) 4546 if ((ii < starting || (ii < ending && !NILP (end))))
4555 { 4547 {
4556 check_sequence_range (args[0], start, end, Flength (args[0])); 4548 check_sequence_range (args[0], start, end, Flength (args[0]));
7930 } 7922 }
7931 else if (LISTP (sequence)) 7923 else if (LISTP (sequence))
7932 { 7924 {
7933 if (NILP (from_end)) 7925 if (NILP (from_end))
7934 { 7926 {
7935 struct gcpro gcpro1, gcpro2; 7927 struct gcpro gcpro1;
7936 Lisp_Object tailed = Qnil; 7928
7937 7929 GCPRO1 (accum);
7938 GCPRO2 (tailed, accum);
7939 7930
7940 if (!UNBOUNDP (initial_value)) 7931 if (!UNBOUNDP (initial_value))
7941 { 7932 {
7942 accum = initial_value; 7933 accum = initial_value;
7943 } 7934 }
7944 else if (ending - starting) 7935 else if (ending - starting)
7945 { 7936 {
7946 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) 7937 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
7947 { 7938 {
7948 /* KEY may amputate the list behind us; make sure what
7949 remains to be processed is still reachable. */
7950 tailed = tail;
7951 if (ii == starting) 7939 if (ii == starting)
7952 { 7940 {
7953 accum = KEY (key, elt); 7941 accum = KEY (key, elt);
7954 starting++; 7942 starting++;
7955 break; 7943 break;
7956 } 7944 }
7957 ++ii; 7945 ++ii;
7958 } 7946 }
7947 END_GC_EXTERNAL_LIST_LOOP (elt);
7959 } 7948 }
7960 7949
7961 ii = 0; 7950 ii = 0;
7962 7951
7963 if (ending - starting) 7952 if (ending - starting)
7964 { 7953 {
7965 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) 7954 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
7966 { 7955 {
7967 /* KEY or FUNCTION may amputate the list behind us; make
7968 sure what remains to be processed is still
7969 reachable. */
7970 tailed = tail;
7971 if (ii >= starting) 7956 if (ii >= starting)
7972 { 7957 {
7973 if (ii < ending) 7958 if (ii < ending)
7974 { 7959 {
7975 accum = CALL2 (function, accum, KEY (key, elt)); 7960 accum = CALL2 (function, accum, KEY (key, elt));
7979 break; 7964 break;
7980 } 7965 }
7981 } 7966 }
7982 ++ii; 7967 ++ii;
7983 } 7968 }
7969 END_GC_EXTERNAL_LIST_LOOP (elt);
7984 } 7970 }
7985 7971
7986 UNGCPRO; 7972 UNGCPRO;
7987 7973
7988 if (ii < starting || (ii < ending && !NILP (end))) 7974 if (ii < starting || (ii < ending && !NILP (end)))
8701 8687
8702 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT) 8688 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT)
8703 */ 8689 */
8704 (int nargs, Lisp_Object *args)) 8690 (int nargs, Lisp_Object *args))
8705 { 8691 {
8706 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; 8692 Lisp_Object new_ = args[0], item = args[1], sequence = args[2];
8707 Lisp_Object object_, position0; 8693 Lisp_Object object_, position0;
8708 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; 8694 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
8709 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; 8695 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0;
8710 Boolint test_not_unboundp = 1; 8696 Boolint test_not_unboundp = 1;
8711 check_test_func_t check_test = NULL; 8697 check_test_func_t check_test = NULL;
8712 struct gcpro gcpro1;
8713 8698
8714 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9, 8699 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9,
8715 (test, if_, if_not, test_not, key, start, end, count, 8700 (test, if_, if_not, test_not, key, start, end, count,
8716 from_end), (start = Qzero)); 8701 from_end), (start = Qzero));
8717 8702
8749 check_test = get_check_test_function (item, &test, test_not, if_, if_not, 8734 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
8750 key, &test_not_unboundp); 8735 key, &test_not_unboundp);
8751 8736
8752 if (CONSP (sequence)) 8737 if (CONSP (sequence))
8753 { 8738 {
8754 Lisp_Object elt;
8755
8756 if (!NILP (count) && !NILP (from_end)) 8739 if (!NILP (count) && !NILP (from_end))
8757 { 8740 {
8758 Lisp_Object present = count_with_tail (&elt, nargs - 1, args + 1, 8741 Lisp_Object present = count_with_tail (&object_, nargs - 1, args + 1,
8759 Qnsubstitute); 8742 Qnsubstitute);
8760 8743
8761 if (ZEROP (present)) 8744 if (ZEROP (present))
8762 { 8745 {
8763 return sequence; 8746 return sequence;
8765 8748
8766 presenting = XINT (present); 8749 presenting = XINT (present);
8767 presenting = presenting <= counting ? 0 : presenting - counting; 8750 presenting = presenting <= counting ? 0 : presenting - counting;
8768 } 8751 }
8769 8752
8770 GCPRO1 (tail);
8771 { 8753 {
8772 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) 8754 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
8773 { 8755 {
8774 if (!(ii < ending)) 8756 if (!(ii < ending))
8775 { 8757 {
8776 break; 8758 break;
8777 } 8759 }
8789 break; 8771 break;
8790 } 8772 }
8791 8773
8792 ii++; 8774 ii++;
8793 } 8775 }
8776 END_GC_EXTERNAL_LIST_LOOP (elt);
8794 } 8777 }
8795 UNGCPRO;
8796 8778
8797 if ((ii < starting || (ii < ending && !NILP (end))) 8779 if ((ii < starting || (ii < ending && !NILP (end)))
8798 && encountered < counting) 8780 && encountered < counting)
8799 { 8781 {
8800 check_sequence_range (args[0], start, end, Flength (args[0])); 8782 check_sequence_range (args[0], start, end, Flength (args[0]));
8962 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT) 8944 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT)
8963 */ 8945 */
8964 (int nargs, Lisp_Object *args)) 8946 (int nargs, Lisp_Object *args))
8965 { 8947 {
8966 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; 8948 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil;
8967 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; 8949 Lisp_Object result = Qnil, result_tail = Qnil;
8968 Lisp_Object object, position0, matched_count; 8950 Lisp_Object object, position0, matched_count;
8969 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; 8951 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
8970 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; 8952 Elemcount ii = 0, counting = EMACS_INT_MAX, presenting = 0;
8971 Boolint test_not_unboundp = 1; 8953 Boolint test_not_unboundp = 1;
8972 check_test_func_t check_test = NULL; 8954 check_test_func_t check_test = NULL;
8973 struct gcpro gcpro1; 8955 struct gcpro gcpro1;
8974 8956
8975 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9, 8957 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9,
9042 { 9024 {
9043 presenting = XINT (matched_count); 9025 presenting = XINT (matched_count);
9044 presenting = presenting <= counting ? 0 : presenting - counting; 9026 presenting = presenting <= counting ? 0 : presenting - counting;
9045 } 9027 }
9046 9028
9047 GCPRO1 (tailing); 9029 GCPRO1 (result);
9048 { 9030 {
9049 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) 9031 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
9050 { 9032 {
9051 if (EQ (tail, tailing)) 9033 if (EQ (tail, tailing))
9052 { 9034 {
9035 XUNGCPRO (elt);
9036 UNGCPRO;
9037
9053 if (NILP (result)) 9038 if (NILP (result))
9054 { 9039 {
9055 RETURN_UNGCPRO (XCDR (tail)); 9040 return XCDR (tail);
9056 } 9041 }
9057 9042
9058 XSETCDR (result_tail, XCDR (tail)); 9043 XSETCDR (result_tail, XCDR (tail));
9059 RETURN_UNGCPRO (result); 9044 return result;
9060 } 9045 }
9061 else if (starting <= ii && ii < ending && 9046 else if (starting <= ii && ii < ending &&
9062 (check_test (test, key, item, elt) == test_not_unboundp) 9047 (check_test (test, key, item, elt) == test_not_unboundp)
9063 && (presenting ? encountered++ >= presenting 9048 && (presenting ? encountered++ >= presenting
9064 : encountered++ < counting)) 9049 : encountered++ < counting))
9088 break; 9073 break;
9089 } 9074 }
9090 9075
9091 ii++; 9076 ii++;
9092 } 9077 }
9078 END_GC_EXTERNAL_LIST_LOOP (elt);
9093 } 9079 }
9094 UNGCPRO; 9080 UNGCPRO;
9095 9081
9096 if (ii < starting || (ii < ending && !NILP (end))) 9082 if (ii < starting || (ii < ending && !NILP (end)))
9097 { 9083 {
9136 static Lisp_Object 9122 static Lisp_Object
9137 sublis (Lisp_Object alist, Lisp_Object tree, 9123 sublis (Lisp_Object alist, Lisp_Object tree,
9138 check_test_func_t check_test, Boolint test_not_unboundp, 9124 check_test_func_t check_test, Boolint test_not_unboundp,
9139 Lisp_Object test, Lisp_Object key, int depth) 9125 Lisp_Object test, Lisp_Object key, int depth)
9140 { 9126 {
9141 Lisp_Object keyed = KEY (key, tree), tailed = alist, aa, dd; 9127 Lisp_Object keyed = KEY (key, tree), aa, dd;
9142 struct gcpro gcpro1, gcpro2, gcpro3; 9128 struct gcpro gcpro1;
9143 9129
9144 if (depth + lisp_eval_depth > max_lisp_eval_depth) 9130 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9145 { 9131 {
9146 stack_overflow ("Stack overflow in sublis", tree); 9132 stack_overflow ("Stack overflow in sublis", tree);
9147 } 9133 }
9148 9134
9149 GCPRO3 (tailed, alist, tree);
9150 { 9135 {
9151 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) 9136 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9152 { 9137 {
9153 tailed = tail; 9138 if (CONSP (elt) &&
9154 9139 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9155 if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
9156 { 9140 {
9157 /* Don't use elt_cdr, it is helpful to allow TEST or KEY to 9141 XUNGCPRO (elt);
9158 modify the alist while it executes. */ 9142 return XCDR (elt);
9159 RETURN_UNGCPRO (XCDR (elt));
9160 } 9143 }
9161 } 9144 }
9145 END_GC_EXTERNAL_LIST_LOOP (elt);
9162 } 9146 }
9147
9163 if (!CONSP (tree)) 9148 if (!CONSP (tree))
9164 { 9149 {
9165 RETURN_UNGCPRO (tree); 9150 RETURN_UNGCPRO (tree);
9166 } 9151 }
9167 9152
9223 nsublis (Lisp_Object alist, Lisp_Object tree, 9208 nsublis (Lisp_Object alist, Lisp_Object tree,
9224 check_test_func_t check_test, 9209 check_test_func_t check_test,
9225 Boolint test_not_unboundp, 9210 Boolint test_not_unboundp,
9226 Lisp_Object test, Lisp_Object key, int depth) 9211 Lisp_Object test, Lisp_Object key, int depth)
9227 { 9212 {
9228 Lisp_Object tree_saved = tree, tailed = alist, tortoise = tree, keyed = Qnil; 9213 Lisp_Object tree_saved = tree, tortoise = tree, keyed = Qnil;
9229 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 9214 struct gcpro gcpro1, gcpro2;
9230 int count = 0; 9215 int count = 0;
9231 9216
9232 if (depth + lisp_eval_depth > max_lisp_eval_depth) 9217 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9233 { 9218 {
9234 stack_overflow ("Stack overflow in nsublis", tree); 9219 stack_overflow ("Stack overflow in nsublis", tree);
9235 } 9220 }
9236 9221
9237 GCPRO4 (tailed, alist, tree_saved, keyed); 9222 GCPRO2 (tree_saved, keyed);
9238 9223
9239 while (CONSP (tree)) 9224 while (CONSP (tree))
9240 { 9225 {
9241 Boolint replaced = 0; 9226 Boolint replaced = 0;
9242 keyed = KEY (key, XCAR (tree)); 9227 keyed = KEY (key, XCAR (tree));
9243 9228
9244 { 9229 {
9245 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) 9230 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9246 { 9231 {
9247 tailed = tail; 9232 if (CONSP (elt) &&
9248 9233 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9249 if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
9250 { 9234 {
9251 CHECK_LISP_WRITEABLE (tree); 9235 CHECK_LISP_WRITEABLE (tree);
9252 /* See comment in sublis() on using elt_cdr. */ 9236 /* See comment in sublis() on using elt_cdr. */
9253 XSETCAR (tree, XCDR (elt)); 9237 XSETCAR (tree, XCDR (elt));
9254 replaced = 1; 9238 replaced = 1;
9255 break; 9239 break;
9256 } 9240 }
9257 } 9241 }
9242 END_GC_EXTERNAL_LIST_LOOP (elt);
9258 } 9243 }
9259 9244
9260 if (!replaced) 9245 if (!replaced)
9261 { 9246 {
9262 if (CONSP (XCAR (tree))) 9247 if (CONSP (XCAR (tree)))
9268 9253
9269 keyed = KEY (key, XCDR (tree)); 9254 keyed = KEY (key, XCDR (tree));
9270 replaced = 0; 9255 replaced = 0;
9271 9256
9272 { 9257 {
9273 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) 9258 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9274 { 9259 {
9275 tailed = tail; 9260 if (CONSP (elt) &&
9276 9261 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9277 if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
9278 { 9262 {
9279 CHECK_LISP_WRITEABLE (tree); 9263 CHECK_LISP_WRITEABLE (tree);
9280 /* See comment in sublis() on using elt_cdr. */
9281 XSETCDR (tree, XCDR (elt)); 9264 XSETCDR (tree, XCDR (elt));
9282 tree = Qnil; 9265 tree = Qnil;
9283 break; 9266 break;
9284 } 9267 }
9285 } 9268 }
9269 END_GC_EXTERNAL_LIST_LOOP (elt);
9286 } 9270 }
9287 9271
9288 if (!NILP (tree)) 9272 if (!NILP (tree))
9289 { 9273 {
9290 tree = XCDR (tree); 9274 tree = XCDR (tree);
9341 keyed = KEY (key, tree); 9325 keyed = KEY (key, tree);
9342 9326
9343 { 9327 {
9344 /* nsublis() won't attempt to replace a cons handed to it, do that 9328 /* nsublis() won't attempt to replace a cons handed to it, do that
9345 ourselves. */ 9329 ourselves. */
9346 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) 9330 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9347 { 9331 {
9348 tailed = tail; 9332 if (CONSP (elt) &&
9349 9333 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9350 if (check_test (test, key, elt_car, keyed) == test_not_unboundp)
9351 { 9334 {
9352 /* See comment in sublis() on using elt_cdr. */ 9335 XUNGCPRO (elt);
9353 RETURN_UNGCPRO (XCDR (elt)); 9336 return XCDR (elt);
9354 } 9337 }
9355 } 9338 }
9339 END_GC_EXTERNAL_LIST_LOOP (elt);
9356 } 9340 }
9357 9341
9358 UNGCPRO; 9342 UNGCPRO;
9359 9343
9360 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0); 9344 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0);
10521 /* These two functions do set operations, those that can be visualised with 10505 /* These two functions do set operations, those that can be visualised with
10522 Venn diagrams. */ 10506 Venn diagrams. */
10523 static Lisp_Object 10507 static Lisp_Object
10524 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) 10508 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp)
10525 { 10509 {
10526 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; 10510 Lisp_Object liszt1 = args[0], liszt2 = args[1];
10527 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil; 10511 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil;
10528 Lisp_Object keyed = Qnil, ignore = Qnil; 10512 Lisp_Object keyed = Qnil, ignore = Qnil;
10529 Elemcount len;
10530 Boolint test_not_unboundp = 1; 10513 Boolint test_not_unboundp = 1;
10531 check_test_func_t check_test = NULL; 10514 check_test_func_t check_test = NULL;
10532 struct gcpro gcpro1, gcpro2, gcpro3; 10515 struct gcpro gcpro1, gcpro2;
10533 10516
10534 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable), 10517 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable),
10535 NULL, 2, 0); 10518 NULL, 2, 0);
10536 10519
10537 CHECK_LIST (liszt1); 10520 CHECK_LIST (liszt1);
10550 } 10533 }
10551 10534
10552 get_check_match_function (&test, test_not, Qnil, Qnil, key, 10535 get_check_match_function (&test, test_not, Qnil, Qnil, key,
10553 &test_not_unboundp, &check_test); 10536 &test_not_unboundp, &check_test);
10554 10537
10555 GCPRO3 (tail, keyed, result); 10538 GCPRO2 (keyed, result);
10556 10539
10557 { 10540 {
10558 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) 10541 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10559 { 10542 {
10560 keyed = KEY (key, elt); 10543 keyed = KEY (key, elt);
10561 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, 10544 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10562 check_test, test_not_unboundp, 10545 check_test, test_not_unboundp,
10563 test, key, 0, Qzero, Qnil)) 10546 test, key, 0, Qzero, Qnil))
10581 XSETCDR (result_tail, Fcons (elt, Qnil)); 10564 XSETCDR (result_tail, Fcons (elt, Qnil));
10582 result_tail = XCDR (result_tail); 10565 result_tail = XCDR (result_tail);
10583 } 10566 }
10584 } 10567 }
10585 } 10568 }
10569 END_GC_EXTERNAL_LIST_LOOP (elt);
10586 } 10570 }
10587 10571
10588 UNGCPRO; 10572 UNGCPRO;
10589 10573
10590 return result; 10574 return result;
10596 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil; 10580 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil;
10597 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil; 10581 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil;
10598 Elemcount count; 10582 Elemcount count;
10599 Boolint test_not_unboundp = 1; 10583 Boolint test_not_unboundp = 1;
10600 check_test_func_t check_test = NULL; 10584 check_test_func_t check_test = NULL;
10601 struct gcpro gcpro1, gcpro2, gcpro3; 10585 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10602 10586
10603 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not), 10587 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not),
10604 NULL, 2, 0); 10588 NULL, 2, 0);
10605 10589
10606 CHECK_LIST (liszt1); 10590 CHECK_LIST (liszt1);
10619 } 10603 }
10620 10604
10621 get_check_match_function (&test, test_not, Qnil, Qnil, key, 10605 get_check_match_function (&test, test_not, Qnil, Qnil, key,
10622 &test_not_unboundp, &check_test); 10606 &test_not_unboundp, &check_test);
10623 10607
10624 GCPRO3 (tail, keyed, liszt1); 10608 tortoise_elt = tail = liszt1, count = 0;
10625 10609
10626 tortoise_elt = tail = liszt1, count = 0; 10610 GCPRO4 (tail, keyed, liszt1, tortoise_elt);
10627 10611
10628 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : 10612 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
10629 (signal_malformed_list_error (liszt1), 0)) 10613 (signal_malformed_list_error (liszt1), 0))
10630 { 10614 {
10631 keyed = KEY (key, elt); 10615 keyed = KEY (key, elt);
10793 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) 10777 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10794 */ 10778 */
10795 (int nargs, Lisp_Object *args)) 10779 (int nargs, Lisp_Object *args))
10796 { 10780 {
10797 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil; 10781 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil;
10798 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, result, result_tail; 10782 Lisp_Object keyed = Qnil, result, result_tail;
10799 Elemcount len;
10800 Boolint test_not_unboundp = 1; 10783 Boolint test_not_unboundp = 1;
10801 check_test_func_t check_test = NULL, check_match = NULL; 10784 check_test_func_t check_test = NULL, check_match = NULL;
10802 struct gcpro gcpro1, gcpro2, gcpro3; 10785 struct gcpro gcpro1, gcpro2;
10803 10786
10804 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL); 10787 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL);
10805 10788
10806 CHECK_LIST (liszt1); 10789 CHECK_LIST (liszt1);
10807 CHECK_LIST (liszt2); 10790 CHECK_LIST (liszt2);
10819 } 10802 }
10820 10803
10821 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, 10804 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10822 &test_not_unboundp, &check_test); 10805 &test_not_unboundp, &check_test);
10823 10806
10824 GCPRO3 (tail, keyed, result); 10807 GCPRO2 (keyed, result);
10825 10808
10826 if (NILP (stable)) 10809 if (NILP (stable))
10827 { 10810 {
10828 result = liszt2; 10811 result = liszt2;
10829 { 10812 {
10830 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) 10813 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10831 { 10814 {
10832 keyed = KEY (key, elt); 10815 keyed = KEY (key, elt);
10833 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, 10816 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10834 check_test, test_not_unboundp, 10817 check_test, test_not_unboundp,
10835 test, key, 0, Qzero, Qnil))) 10818 test, key, 0, Qzero, Qnil)))
10843 is called an awful lot more, so it's a space win but not 10826 is called an awful lot more, so it's a space win but not
10844 a time win. */ 10827 a time win. */
10845 result = Fcons (elt, result); 10828 result = Fcons (elt, result);
10846 } 10829 }
10847 } 10830 }
10831 END_GC_EXTERNAL_LIST_LOOP (elt);
10848 } 10832 }
10849 } 10833 }
10850 else 10834 else
10851 { 10835 {
10852 result = result_tail = Qnil; 10836 result = result_tail = Qnil;
10856 the values in backwards order. According to the CLTL2 10840 the values in backwards order. According to the CLTL2
10857 documentation, `union' is not required to preserve the ordering of 10841 documentation, `union' is not required to preserve the ordering of
10858 elements in any fashion; providing the functionality for a stable 10842 elements in any fashion; providing the functionality for a stable
10859 union is an XEmacs extension. */ 10843 union is an XEmacs extension. */
10860 { 10844 {
10861 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) 10845 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
10862 { 10846 {
10863 if (NILP (list_position_cons_before (&ignore, elt, liszt1, 10847 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10864 check_match, test_not_unboundp, 10848 check_match, test_not_unboundp,
10865 test, key, 1, Qzero, Qnil))) 10849 test, key, 1, Qzero, Qnil)))
10866 { 10850 {
10873 XSETCDR (result_tail, Fcons (elt, Qnil)); 10857 XSETCDR (result_tail, Fcons (elt, Qnil));
10874 result_tail = XCDR (result_tail); 10858 result_tail = XCDR (result_tail);
10875 } 10859 }
10876 } 10860 }
10877 } 10861 }
10862 END_GC_EXTERNAL_LIST_LOOP (elt);
10878 } 10863 }
10879 10864
10880 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result); 10865 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result);
10881 } 10866 }
10882 10867
10900 10885
10901 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) 10886 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10902 */ 10887 */
10903 (int nargs, Lisp_Object *args)) 10888 (int nargs, Lisp_Object *args))
10904 { 10889 {
10905 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; 10890 Lisp_Object liszt1 = args[0], liszt2 = args[1];
10906 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil; 10891 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil;
10907 Elemcount len;
10908 Boolint test_not_unboundp = 1; 10892 Boolint test_not_unboundp = 1;
10909 check_test_func_t check_match = NULL, check_test = NULL; 10893 check_test_func_t check_match = NULL, check_test = NULL;
10910 struct gcpro gcpro1, gcpro2, gcpro3; 10894 struct gcpro gcpro1, gcpro2;
10911 10895
10912 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4, 10896 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4,
10913 (test, key, test_not, stable), NULL); 10897 (test, key, test_not, stable), NULL);
10914 10898
10915 CHECK_LIST (liszt1); 10899 CHECK_LIST (liszt1);
10923 } 10907 }
10924 10908
10925 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, 10909 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10926 &test_not_unboundp, &check_test); 10910 &test_not_unboundp, &check_test);
10927 10911
10928 GCPRO3 (tail, keyed, result); 10912 GCPRO2 (keyed, result);
10929 { 10913 {
10930 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) 10914 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10931 { 10915 {
10932 keyed = KEY (key, elt); 10916 keyed = KEY (key, elt);
10933 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, 10917 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10934 check_test, test_not_unboundp, 10918 check_test, test_not_unboundp,
10935 test, key, 0, Qzero, Qnil))) 10919 test, key, 0, Qzero, Qnil)))
10947 XSETCDR (result_tail, Fcons (elt, Qnil)); 10931 XSETCDR (result_tail, Fcons (elt, Qnil));
10948 result_tail = XCDR (result_tail); 10932 result_tail = XCDR (result_tail);
10949 } 10933 }
10950 } 10934 }
10951 } 10935 }
10936 END_GC_EXTERNAL_LIST_LOOP (elt);
10952 } 10937 }
10953 10938
10954 { 10939 {
10955 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) 10940 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
10956 { 10941 {
10957 if (NILP (list_position_cons_before (&ignore, elt, liszt1, 10942 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10958 check_match, test_not_unboundp, 10943 check_match, test_not_unboundp,
10959 test, key, 1, Qzero, Qnil))) 10944 test, key, 1, Qzero, Qnil)))
10960 { 10945 {
10971 XSETCDR (result_tail, Fcons (elt, Qnil)); 10956 XSETCDR (result_tail, Fcons (elt, Qnil));
10972 result_tail = XCDR (result_tail); 10957 result_tail = XCDR (result_tail);
10973 } 10958 }
10974 } 10959 }
10975 } 10960 }
10961 END_GC_EXTERNAL_LIST_LOOP (elt);
10976 } 10962 }
10963
10977 UNGCPRO; 10964 UNGCPRO;
10978 10965
10979 return result; 10966 return result;
10980 } 10967 }
10981 10968
10996 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap; 10983 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap;
10997 Lisp_Object prev_tail = Qnil, ignore = Qnil; 10984 Lisp_Object prev_tail = Qnil, ignore = Qnil;
10998 Elemcount count; 10985 Elemcount count;
10999 Boolint test_not_unboundp = 1; 10986 Boolint test_not_unboundp = 1;
11000 check_test_func_t check_match = NULL, check_test = NULL; 10987 check_test_func_t check_match = NULL, check_test = NULL;
11001 struct gcpro gcpro1, gcpro2, gcpro3; 10988 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
11002 10989
11003 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4, 10990 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4,
11004 (test, key, test_not, stable), NULL); 10991 (test, key, test_not, stable), NULL);
11005 10992
11006 CHECK_LIST (liszt1); 10993 CHECK_LIST (liszt1);
11014 } 11001 }
11015 11002
11016 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, 11003 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
11017 &test_not_unboundp, &check_test); 11004 &test_not_unboundp, &check_test);
11018 11005
11019 GCPRO3 (tail, keyed, result);
11020
11021 tortoise_elt = tail = liszt1, count = 0; 11006 tortoise_elt = tail = liszt1, count = 0;
11007
11008 GCPRO4 (tail, keyed, result, tortoise_elt);
11022 11009
11023 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : 11010 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
11024 (signal_malformed_list_error (liszt1), 0)) 11011 (signal_malformed_list_error (liszt1), 0))
11025 { 11012 {
11026 keyed = KEY (key, elt); 11013 keyed = KEY (key, elt);