Mercurial > hg > xemacs-beta
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); |