Mercurial > hg > xemacs-beta
comparison src/fns.c @ 5475:248176c74e6b
Merge with trunk.
author | Mats Lidell <matsl@xemacs.org> |
---|---|
date | Sat, 23 Apr 2011 23:47:13 +0200 |
parents | ac37a5f7e5be ccf7e84fe265 |
children | d3e0482c7899 |
comparison
equal
deleted
inserted
replaced
5474:4dee0387b9de | 5475:248176c74e6b |
---|---|
995 | 995 |
996 /* Our callers should have filtered out non-positive COUNT. */ | 996 /* Our callers should have filtered out non-positive COUNT. */ |
997 assert (counting >= 0); | 997 assert (counting >= 0); |
998 /* And we're not prepared to handle COUNT from any other caller at the | 998 /* And we're not prepared to handle COUNT from any other caller at the |
999 moment. */ | 999 moment. */ |
1000 assert (EQ (caller, QremoveX)); | 1000 assert (EQ (caller, QremoveX)|| EQ (caller, QdeleteX)); |
1001 } | 1001 } |
1002 | 1002 |
1003 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | 1003 check_test = get_check_test_function (item, &test, test_not, if_, if_not, |
1004 key, &test_not_unboundp); | 1004 key, &test_not_unboundp); |
1005 | 1005 |
1006 *tail_out = Qnil; | 1006 *tail_out = Qnil; |
1007 | 1007 |
1008 if (CONSP (sequence)) | 1008 if (CONSP (sequence)) |
1009 { | 1009 { |
1010 Lisp_Object elt, tail = Qnil; | |
1011 struct gcpro gcpro1; | |
1012 | |
1013 if (EQ (caller, Qcount) && !NILP (from_end) | 1010 if (EQ (caller, Qcount) && !NILP (from_end) |
1014 && (!EQ (key, Qnil) || | 1011 && (!EQ (key, Qnil) || |
1015 check_test == check_other_nokey || check_test == check_if_nokey)) | 1012 check_test == check_other_nokey || check_test == check_if_nokey)) |
1016 { | 1013 { |
1017 /* #'count, #'count-if, and #'count-if-not are documented to have | 1014 /* #'count, #'count-if, and #'count-if-not are documented to have |
1022 return list_count_from_end (item, sequence, check_test, | 1019 return list_count_from_end (item, sequence, check_test, |
1023 test_not_unboundp, test, key, | 1020 test_not_unboundp, test, key, |
1024 start, end); | 1021 start, end); |
1025 } | 1022 } |
1026 | 1023 |
1027 GCPRO1 (tail); | |
1028 | |
1029 /* If COUNT is non-nil and FROM-END is t, we can give the tail | 1024 /* If COUNT is non-nil and FROM-END is t, we can give the tail |
1030 containing the last match, since that's what #'remove* is | 1025 containing the last match, since that's what #'remove* is |
1031 interested in (a zero or negative COUNT won't ever reach | 1026 interested in (a zero or negative COUNT won't ever reach |
1032 count_with_tail(), our callers will return immediately on seeing | 1027 count_with_tail(), our callers will return immediately on seeing |
1033 it). */ | 1028 it). */ |
1035 { | 1030 { |
1036 counting = EMACS_INT_MAX; | 1031 counting = EMACS_INT_MAX; |
1037 } | 1032 } |
1038 | 1033 |
1039 { | 1034 { |
1040 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | 1035 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
1041 { | 1036 { |
1042 if (!(ii < ending)) | 1037 if (!(ii < ending)) |
1043 { | 1038 { |
1044 break; | 1039 break; |
1045 } | 1040 } |
1056 } | 1051 } |
1057 } | 1052 } |
1058 | 1053 |
1059 ii++; | 1054 ii++; |
1060 } | 1055 } |
1056 END_GC_EXTERNAL_LIST_LOOP (elt); | |
1061 } | 1057 } |
1062 | |
1063 UNGCPRO; | |
1064 | 1058 |
1065 if ((ii < starting || (ii < ending && !NILP (end))) && | 1059 if ((ii < starting || (ii < ending && !NILP (end))) && |
1066 encountered != counting) | 1060 encountered != counting) |
1067 { | 1061 { |
1068 check_sequence_range (args[1], start, end, Flength (args[1])); | 1062 check_sequence_range (args[1], start, end, Flength (args[1])); |
2618 Boolint test_not_unboundp, | 2612 Boolint test_not_unboundp, |
2619 Lisp_Object test, Lisp_Object key, | 2613 Lisp_Object test, Lisp_Object key, |
2620 Boolint reverse_test_order, | 2614 Boolint reverse_test_order, |
2621 Lisp_Object start, Lisp_Object end) | 2615 Lisp_Object start, Lisp_Object end) |
2622 { | 2616 { |
2623 struct gcpro gcpro1, gcpro2; | 2617 struct gcpro gcpro1; |
2624 Lisp_Object elt = Qnil, tail = list, tail_before = Qnil; | 2618 Lisp_Object tail_before = Qnil; |
2625 Elemcount len, ii = 0, starting = XINT (start); | 2619 Elemcount ii = 0, starting = XINT (start); |
2626 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end); | 2620 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end); |
2627 | 2621 |
2628 GCPRO2 (elt, tail); | 2622 GCPRO1 (tail_before); |
2629 | 2623 |
2630 if (check_test == check_eq_nokey) | 2624 if (check_test == check_eq_nokey) |
2631 { | 2625 { |
2632 /* TEST is #'eq, no need to call any C functions, and the test order | 2626 /* TEST is #'eq, no need to call any C functions, and the test order |
2633 won't be visible. */ | 2627 won't be visible. */ |
2634 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | 2628 EXTERNAL_LIST_LOOP_3 (elt, list, tail) |
2635 { | 2629 { |
2636 if (starting <= ii && ii < ending && | 2630 if (starting <= ii && ii < ending && |
2637 EQ (item, elt) == test_not_unboundp) | 2631 EQ (item, elt) == test_not_unboundp) |
2638 { | 2632 { |
2639 *cons_out = tail_before; | 2633 *cons_out = tail_before; |
2650 tail_before = tail; | 2644 tail_before = tail; |
2651 } | 2645 } |
2652 } | 2646 } |
2653 else | 2647 else |
2654 { | 2648 { |
2655 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | 2649 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail) |
2656 { | 2650 { |
2657 if (starting <= ii && ii < ending && | 2651 if (starting <= ii && ii < ending && |
2658 (reverse_test_order ? | 2652 (reverse_test_order ? |
2659 check_test (test, key, elt, item) : | 2653 check_test (test, key, elt, item) : |
2660 check_test (test, key, item, elt)) == test_not_unboundp) | 2654 check_test (test, key, item, elt)) == test_not_unboundp) |
2661 { | 2655 { |
2662 *cons_out = tail_before; | 2656 *cons_out = tail_before; |
2663 RETURN_UNGCPRO (make_integer (ii)); | 2657 XUNGCPRO (elt); |
2658 UNGCPRO; | |
2659 return make_integer (ii); | |
2664 } | 2660 } |
2665 else | 2661 else |
2666 { | 2662 { |
2667 if (ii >= ending) | 2663 if (ii >= ending) |
2668 { | 2664 { |
2670 } | 2666 } |
2671 } | 2667 } |
2672 ii++; | 2668 ii++; |
2673 tail_before = tail; | 2669 tail_before = tail; |
2674 } | 2670 } |
2671 END_GC_EXTERNAL_LIST_LOOP (elt); | |
2675 } | 2672 } |
2676 | 2673 |
2677 RETURN_UNGCPRO (Qnil); | 2674 RETURN_UNGCPRO (Qnil); |
2678 } | 2675 } |
2679 | 2676 |
2856 } | 2853 } |
2857 } | 2854 } |
2858 } | 2855 } |
2859 else | 2856 else |
2860 { | 2857 { |
2861 Lisp_Object tailed = alist; | 2858 GC_EXTERNAL_LIST_LOOP_2 (elt, alist) |
2862 struct gcpro gcpro1; | 2859 { |
2863 | 2860 if (CONSP (elt) && |
2864 GCPRO1 (tailed); | 2861 check_test (test, key, item, XCAR (elt)) == test_not_unboundp) |
2865 { | |
2866 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
2867 { | |
2868 tailed = tail; | |
2869 | |
2870 if (check_test (test, key, item, elt_car) == test_not_unboundp) | |
2871 { | 2862 { |
2872 RETURN_UNGCPRO (elt); | 2863 XUNGCPRO (elt); |
2864 return elt; | |
2873 } | 2865 } |
2874 } | 2866 } |
2875 } | 2867 END_GC_EXTERNAL_LIST_LOOP (elt); |
2876 UNGCPRO; | |
2877 } | 2868 } |
2878 | 2869 |
2879 return Qnil; | 2870 return Qnil; |
2880 } | 2871 } |
2881 | 2872 |
2965 } | 2956 } |
2966 } | 2957 } |
2967 } | 2958 } |
2968 else | 2959 else |
2969 { | 2960 { |
2970 struct gcpro gcpro1; | 2961 GC_EXTERNAL_LIST_LOOP_2 (elt, alist) |
2971 Lisp_Object tailed = alist; | 2962 { |
2972 | 2963 if (CONSP (elt) && |
2973 GCPRO1 (tailed); | 2964 check_test (test, key, item, XCDR (elt)) == test_not_unboundp) |
2974 { | 2965 { |
2975 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | 2966 XUNGCPRO (elt); |
2976 { | 2967 return elt; |
2977 tailed = tail; | 2968 } |
2978 | 2969 } |
2979 if (check_test (test, key, item, elt_cdr) == test_not_unboundp) | 2970 END_GC_EXTERNAL_LIST_LOOP (elt); |
2980 { | |
2981 RETURN_UNGCPRO (elt); | |
2982 } | |
2983 } | |
2984 } | |
2985 UNGCPRO; | |
2986 } | 2971 } |
2987 | 2972 |
2988 return Qnil; | 2973 return Qnil; |
2989 } | 2974 } |
2990 | 2975 |
3010 | 2995 |
3011 *object_out = default_; | 2996 *object_out = default_; |
3012 | 2997 |
3013 if (CONSP (sequence)) | 2998 if (CONSP (sequence)) |
3014 { | 2999 { |
3015 Lisp_Object elt, tail = Qnil; | |
3016 struct gcpro gcpro1; | |
3017 | |
3018 if (!(starting < ending)) | 3000 if (!(starting < ending)) |
3019 { | 3001 { |
3020 check_sequence_range (sequence, start, end, Flength (sequence)); | 3002 check_sequence_range (sequence, start, end, Flength (sequence)); |
3021 /* starting could be equal to ending, in which case nil is what | 3003 /* starting could be equal to ending, in which case nil is what |
3022 we want to return. */ | 3004 we want to return. */ |
3023 return Qnil; | 3005 return Qnil; |
3024 } | 3006 } |
3025 | 3007 |
3026 GCPRO1 (tail); | |
3027 | |
3028 { | 3008 { |
3029 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | 3009 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence) |
3030 { | 3010 { |
3031 if (starting <= ii && ii < ending | 3011 if (starting <= ii && ii < ending |
3032 && check_test (test, key, item, elt) == test_not_unboundp) | 3012 && check_test (test, key, item, elt) == test_not_unboundp) |
3033 { | 3013 { |
3034 result = make_integer (ii); | 3014 result = make_integer (ii); |
3035 *object_out = elt; | 3015 *object_out = elt; |
3036 | 3016 |
3037 if (NILP (from_end)) | 3017 if (NILP (from_end)) |
3038 { | 3018 { |
3039 UNGCPRO; | 3019 XUNGCPRO (elt); |
3040 return result; | 3020 return result; |
3041 } | 3021 } |
3042 } | 3022 } |
3043 else if (ii == ending) | 3023 else if (ii == ending) |
3044 { | 3024 { |
3045 break; | 3025 break; |
3046 } | 3026 } |
3047 | 3027 |
3048 ii++; | 3028 ii++; |
3049 } | 3029 } |
3030 END_GC_EXTERNAL_LIST_LOOP (elt); | |
3050 } | 3031 } |
3051 | |
3052 UNGCPRO; | |
3053 | 3032 |
3054 if (ii < starting || (ii < ending && !NILP (end))) | 3033 if (ii < starting || (ii < ending && !NILP (end))) |
3055 { | 3034 { |
3056 check_sequence_range (sequence, start, end, Flength (sequence)); | 3035 check_sequence_range (sequence, start, end, Flength (sequence)); |
3057 } | 3036 } |
3255 | 3234 |
3256 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) | 3235 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) |
3257 */ | 3236 */ |
3258 (int nargs, Lisp_Object *args)) | 3237 (int nargs, Lisp_Object *args)) |
3259 { | 3238 { |
3260 Lisp_Object item = args[0], sequence = args[1], tail = sequence; | 3239 Lisp_Object item = args[0], sequence = args[1]; |
3261 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; | 3240 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; |
3262 Elemcount len, ii = 0, encountered = 0, presenting = 0; | 3241 Elemcount len, ii = 0, encountered = 0, presenting = 0; |
3263 Boolint test_not_unboundp = 1; | 3242 Boolint test_not_unboundp = 1; |
3264 check_test_func_t check_test = NULL; | 3243 check_test_func_t check_test = NULL; |
3265 struct gcpro gcpro1; | |
3266 | 3244 |
3267 PARSE_KEYWORDS (FdeleteX, nargs, args, 9, | 3245 PARSE_KEYWORDS (FdeleteX, nargs, args, 9, |
3268 (test, if_not, if_, test_not, key, start, end, from_end, | 3246 (test, if_not, if_, test_not, key, start, end, from_end, |
3269 count), (start = Qzero, count = Qunbound)); | 3247 count), (start = Qzero, count = Qunbound)); |
3270 | 3248 |
3297 | 3275 |
3298 if (counting < 1) | 3276 if (counting < 1) |
3299 { | 3277 { |
3300 return sequence; | 3278 return sequence; |
3301 } | 3279 } |
3302 } | 3280 |
3281 if (!NILP (from_end)) | |
3282 { | |
3283 /* Sigh, this is inelegant. Force count_with_tail () to ignore | |
3284 the count keyword, so we get the actual number of matching | |
3285 elements, and can start removing from the beginning for the | |
3286 from-end case. */ | |
3287 for (ii = XSUBR (GET_DEFUN_LISP_OBJECT (FdeleteX))->min_args; | |
3288 ii < nargs; ii += 2) | |
3289 { | |
3290 if (EQ (args[ii], Q_count)) | |
3291 { | |
3292 args[ii + 1] = Qnil; | |
3293 break; | |
3294 } | |
3295 } | |
3296 ii = 0; | |
3297 } | |
3298 } | |
3303 } | 3299 } |
3304 | 3300 |
3305 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | 3301 check_test = get_check_test_function (item, &test, test_not, if_, if_not, |
3306 key, &test_not_unboundp); | 3302 key, &test_not_unboundp); |
3307 | 3303 |
3308 if (CONSP (sequence)) | 3304 if (CONSP (sequence)) |
3309 { | 3305 { |
3310 Lisp_Object prev_tail_list_elt = Qnil, list_elt = Qnil; | 3306 Lisp_Object prev_tail_list_elt = Qnil, ignore = Qnil; |
3311 Elemcount list_len = 0, deleted = 0; | 3307 Elemcount list_len = 0, deleted = 0; |
3308 struct gcpro gcpro1; | |
3312 | 3309 |
3313 if (!NILP (count) && !NILP (from_end)) | 3310 if (!NILP (count) && !NILP (from_end)) |
3314 { | 3311 { |
3315 /* Both COUNT and FROM-END were specified; we need to traverse the | 3312 /* Both COUNT and FROM-END were specified; we need to traverse the |
3316 list twice. */ | 3313 list twice. */ |
3317 Lisp_Object present = count_with_tail (&list_elt, nargs, args, | 3314 Lisp_Object present = count_with_tail (&ignore, nargs, args, |
3318 QdeleteX); | 3315 QdeleteX); |
3319 | 3316 |
3320 if (ZEROP (present)) | 3317 if (ZEROP (present)) |
3321 { | 3318 { |
3322 return sequence; | 3319 return sequence; |
3330 of matching items we need to ignore before we start to | 3327 of matching items we need to ignore before we start to |
3331 delete. */ | 3328 delete. */ |
3332 presenting = presenting <= counting ? 0 : presenting - counting; | 3329 presenting = presenting <= counting ? 0 : presenting - counting; |
3333 } | 3330 } |
3334 | 3331 |
3335 GCPRO1 (tail); | 3332 GCPRO1 (prev_tail_list_elt); |
3336 ii = -1; | 3333 ii = -1; |
3337 | 3334 |
3338 { | 3335 { |
3339 EXTERNAL_LIST_LOOP_4_NO_DECLARE (list_elt, sequence, tail, list_len) | 3336 GC_EXTERNAL_LIST_LOOP_4 (list_elt, sequence, tail, list_len) |
3340 { | 3337 { |
3341 ii++; | 3338 ii++; |
3342 | 3339 |
3343 if (starting <= ii && ii < ending && | 3340 if (starting <= ii && ii < ending && |
3344 (check_test (test, key, item, list_elt) == test_not_unboundp) | 3341 (check_test (test, key, item, list_elt) == test_not_unboundp) |
3365 { | 3362 { |
3366 break; | 3363 break; |
3367 } | 3364 } |
3368 } | 3365 } |
3369 } | 3366 } |
3367 END_GC_EXTERNAL_LIST_LOOP (list_elt); | |
3370 } | 3368 } |
3371 | 3369 |
3372 UNGCPRO; | 3370 UNGCPRO; |
3373 | 3371 |
3374 if ((ii < starting || (ii < ending && !NILP (end))) && | 3372 if ((ii < starting || (ii < ending && !NILP (end))) && |
3602 (int nargs, Lisp_Object *args)) | 3600 (int nargs, Lisp_Object *args)) |
3603 { | 3601 { |
3604 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil, | 3602 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil, |
3605 tail = Qnil; | 3603 tail = Qnil; |
3606 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; | 3604 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; |
3607 Elemcount len, ii = 0, encountered = 0, presenting = 0; | 3605 Elemcount ii = 0, encountered = 0, presenting = 0; |
3608 Boolint test_not_unboundp = 1; | 3606 Boolint test_not_unboundp = 1; |
3609 check_test_func_t check_test = NULL; | 3607 check_test_func_t check_test = NULL; |
3610 struct gcpro gcpro1; | |
3611 | 3608 |
3612 PARSE_KEYWORDS (FremoveX, nargs, args, 9, | 3609 PARSE_KEYWORDS (FremoveX, nargs, args, 9, |
3613 (test, if_not, if_, test_not, key, start, end, from_end, | 3610 (test, if_not, if_, test_not, key, start, end, from_end, |
3614 count), (start = Qzero)); | 3611 count), (start = Qzero)); |
3615 | 3612 |
3644 | 3641 |
3645 if (counting <= 0) | 3642 if (counting <= 0) |
3646 { | 3643 { |
3647 return sequence; | 3644 return sequence; |
3648 } | 3645 } |
3646 | |
3647 if (!NILP (from_end)) | |
3648 { | |
3649 /* Sigh, this is inelegant. Force count_with_tail () to ignore the | |
3650 count keyword, so we get the actual number of matching | |
3651 elements, and can start removing from the beginning for the | |
3652 from-end case. */ | |
3653 for (ii = XSUBR (GET_DEFUN_LISP_OBJECT (FremoveX))->min_args; | |
3654 ii < nargs; ii += 2) | |
3655 { | |
3656 if (EQ (args[ii], Q_count)) | |
3657 { | |
3658 args[ii + 1] = Qnil; | |
3659 break; | |
3660 } | |
3661 } | |
3662 ii = 0; | |
3663 } | |
3649 } | 3664 } |
3650 | 3665 |
3651 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | 3666 check_test = get_check_test_function (item, &test, test_not, if_, if_not, |
3652 key, &test_not_unboundp); | 3667 key, &test_not_unboundp); |
3653 | 3668 |
3654 matched_count = count_with_tail (&tail, nargs, args, QremoveX); | 3669 matched_count = count_with_tail (&tail, nargs, args, QremoveX); |
3655 | 3670 |
3656 if (!ZEROP (matched_count)) | 3671 if (!ZEROP (matched_count)) |
3657 { | 3672 { |
3658 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; | 3673 Lisp_Object result = Qnil, result_tail = Qnil; |
3659 GCPRO1 (tailing); | 3674 struct gcpro gcpro1, gcpro2; |
3660 | 3675 |
3661 if (!NILP (count) && !NILP (from_end)) | 3676 if (!NILP (count) && !NILP (from_end)) |
3662 { | 3677 { |
3663 presenting = XINT (matched_count); | 3678 presenting = XINT (matched_count); |
3664 | 3679 |
3668 is the number of matching items we need to ignore before we | 3683 is the number of matching items we need to ignore before we |
3669 start to delete. */ | 3684 start to delete. */ |
3670 presenting = presenting <= counting ? 0 : presenting - counting; | 3685 presenting = presenting <= counting ? 0 : presenting - counting; |
3671 } | 3686 } |
3672 | 3687 |
3688 GCPRO2 (result, tail); | |
3673 { | 3689 { |
3674 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) | 3690 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing) |
3675 { | 3691 { |
3676 if (EQ (tail, tailing)) | 3692 if (EQ (tail, tailing)) |
3677 { | 3693 { |
3694 XUNGCPRO (elt); | |
3695 UNGCPRO; | |
3696 | |
3678 if (NILP (result)) | 3697 if (NILP (result)) |
3679 { | 3698 { |
3680 RETURN_UNGCPRO (XCDR (tail)); | 3699 return XCDR (tail); |
3681 } | 3700 } |
3682 | 3701 |
3683 XSETCDR (result_tail, XCDR (tail)); | 3702 XSETCDR (result_tail, XCDR (tail)); |
3684 RETURN_UNGCPRO (result); | 3703 return result; |
3685 } | 3704 } |
3686 else if (starting <= ii && ii < ending && | 3705 else if (starting <= ii && ii < ending && |
3687 (check_test (test, key, item, elt) == test_not_unboundp) | 3706 (check_test (test, key, item, elt) == test_not_unboundp) |
3688 && (presenting ? encountered++ >= presenting | 3707 && (presenting ? encountered++ >= presenting |
3689 : encountered++ < counting)) | 3708 : encountered++ < counting)) |
3705 break; | 3724 break; |
3706 } | 3725 } |
3707 | 3726 |
3708 ii++; | 3727 ii++; |
3709 } | 3728 } |
3729 END_GC_EXTERNAL_LIST_LOOP (elt); | |
3710 } | 3730 } |
3711 | |
3712 UNGCPRO; | 3731 UNGCPRO; |
3713 | 3732 |
3714 if (ii < starting || (ii < ending && !NILP (end))) | 3733 if (ii < starting || (ii < ending && !NILP (end))) |
3715 { | 3734 { |
3716 check_sequence_range (args[0], start, end, Flength (args[0])); | 3735 check_sequence_range (args[0], start, end, Flength (args[0])); |
3825 Boolint test_not_unboundp, | 3844 Boolint test_not_unboundp, |
3826 Lisp_Object test, Lisp_Object key, | 3845 Lisp_Object test, Lisp_Object key, |
3827 Lisp_Object start, | 3846 Lisp_Object start, |
3828 Lisp_Object end, Boolint copy) | 3847 Lisp_Object end, Boolint copy) |
3829 { | 3848 { |
3830 Lisp_Object checking = Qnil, elt, tail, result = list; | 3849 Lisp_Object checking = Qnil, result = list; |
3831 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail; | 3850 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail; |
3832 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start); | 3851 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start); |
3833 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1; | 3852 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1; |
3834 Elemcount ii = 0; | 3853 Elemcount ii = 0; |
3835 struct gcpro gcpro1, gcpro2; | 3854 struct gcpro gcpro1; |
3836 | 3855 |
3837 /* We can't delete (or remove) as we go, because that breaks START and | 3856 /* We can't delete (or remove) as we go, because that breaks START and |
3838 END. We could if END were nil, and that would change an ON(N + 2) | 3857 END. We could if END were nil, and that would change an ON(N + 2) |
3839 algorithm to an ON^2 algorithm; list_position_cons_before() would need to | 3858 algorithm to an ON^2 algorithm; list_position_cons_before() would need to |
3840 be modified to return the cons *before* the one containing the item for | 3859 be modified to return the cons *before* the one containing the item for |
3850 | 3869 |
3851 deleting->size = len; | 3870 deleting->size = len; |
3852 memset (&(deleting->bits), 0, | 3871 memset (&(deleting->bits), 0, |
3853 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | 3872 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); |
3854 | 3873 |
3855 GCPRO2 (tail, keyed); | 3874 GCPRO1 (keyed); |
3856 | 3875 |
3857 { | 3876 { |
3858 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | 3877 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail) |
3859 { | 3878 { |
3860 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii)) | 3879 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii)) |
3861 { | 3880 { |
3862 ii++; | 3881 ii++; |
3863 continue; | 3882 continue; |
3880 XCDR (checking) : XCDR (XCDR (position_cons)); | 3899 XCDR (checking) : XCDR (XCDR (position_cons)); |
3881 pos += 1; | 3900 pos += 1; |
3882 } | 3901 } |
3883 ii++; | 3902 ii++; |
3884 } | 3903 } |
3904 END_GC_EXTERNAL_LIST_LOOP (elt); | |
3885 } | 3905 } |
3886 | 3906 |
3887 UNGCPRO; | 3907 UNGCPRO; |
3888 | 3908 |
3889 ii = 0; | 3909 ii = 0; |
3895 result = result_tail = Fcons (XCAR (list), Qnil); | 3915 result = result_tail = Fcons (XCAR (list), Qnil); |
3896 list = XCDR (list); | 3916 list = XCDR (list); |
3897 ii = 1; | 3917 ii = 1; |
3898 | 3918 |
3899 { | 3919 { |
3900 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | 3920 EXTERNAL_LIST_LOOP_3 (elt, list, tail) |
3901 { | 3921 { |
3902 if (ii == greatest_pos_seen) | 3922 if (ii == greatest_pos_seen) |
3903 { | 3923 { |
3904 XSETCDR (result_tail, XCDR (tail)); | 3924 XSETCDR (result_tail, XCDR (tail)); |
3905 break; | 3925 break; |
3913 } | 3933 } |
3914 } | 3934 } |
3915 } | 3935 } |
3916 else | 3936 else |
3917 { | 3937 { |
3918 EXTERNAL_LIST_LOOP_DELETE_IF (elt0, list, | 3938 EXTERNAL_LIST_LOOP_DELETE_IF (elt, list, |
3919 bit_vector_bit (deleting, ii++)); | 3939 bit_vector_bit (deleting, ii++)); |
3920 } | 3940 } |
3921 } | 3941 } |
3922 | 3942 |
3923 return result; | 3943 return result; |
3941 | 3961 |
3942 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | 3962 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) |
3943 */ | 3963 */ |
3944 (int nargs, Lisp_Object *args)) | 3964 (int nargs, Lisp_Object *args)) |
3945 { | 3965 { |
3946 Lisp_Object sequence = args[0], tail = sequence, keyed = Qnil, elt = Qnil; | 3966 Lisp_Object sequence = args[0], keyed = Qnil; |
3947 Lisp_Object elt0 = Qnil, positioned = Qnil, ignore = Qnil; | 3967 Lisp_Object positioned = Qnil, ignore = Qnil; |
3948 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0; | 3968 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0; |
3949 Boolint test_not_unboundp = 1; | 3969 Boolint test_not_unboundp = 1; |
3950 check_test_func_t check_test = NULL; | 3970 check_test_func_t check_test = NULL; |
3951 struct gcpro gcpro1, gcpro2; | 3971 struct gcpro gcpro1, gcpro2; |
3952 | 3972 |
3974 if (NILP (from_end)) | 3994 if (NILP (from_end)) |
3975 { | 3995 { |
3976 Lisp_Object prev_tail = Qnil; | 3996 Lisp_Object prev_tail = Qnil; |
3977 Elemcount deleted = 0; | 3997 Elemcount deleted = 0; |
3978 | 3998 |
3979 GCPRO2 (tail, keyed); | 3999 GCPRO2 (keyed, prev_tail); |
3980 | 4000 |
3981 { | 4001 { |
3982 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | 4002 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
3983 { | 4003 { |
3984 if (starting <= ii && ii < ending) | 4004 if (starting <= ii && ii < ending) |
3985 { | 4005 { |
3986 keyed = KEY (key, elt); | 4006 keyed = KEY (key, elt); |
3987 positioned | 4007 positioned |
4008 break; | 4028 break; |
4009 } | 4029 } |
4010 | 4030 |
4011 ii++; | 4031 ii++; |
4012 } | 4032 } |
4033 END_GC_EXTERNAL_LIST_LOOP (elt); | |
4013 } | 4034 } |
4014 { | 4035 { |
4015 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) | 4036 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
4016 { | 4037 { |
4017 if (!(starting <= ii && ii <= ending)) | 4038 if (!(starting <= ii && ii <= ending)) |
4018 { | 4039 { |
4019 prev_tail = tail; | 4040 prev_tail = tail; |
4020 ii++; | 4041 ii++; |
4021 continue; | 4042 continue; |
4022 } | 4043 } |
4023 | 4044 |
4024 keyed = KEY (key, elt0); | 4045 keyed = KEY (key, elt); |
4025 positioned | 4046 positioned |
4026 = list_position_cons_before (&ignore, keyed, XCDR (tail), | 4047 = list_position_cons_before (&ignore, keyed, XCDR (tail), |
4027 check_test, test_not_unboundp, | 4048 check_test, test_not_unboundp, |
4028 test, key, 0, | 4049 test, key, 0, |
4029 make_int (max (starting | 4050 make_int (max (starting |
4048 } | 4069 } |
4049 } | 4070 } |
4050 | 4071 |
4051 ii++; | 4072 ii++; |
4052 } | 4073 } |
4074 END_GC_EXTERNAL_LIST_LOOP (elt); | |
4053 } | 4075 } |
4076 | |
4054 UNGCPRO; | 4077 UNGCPRO; |
4055 | 4078 |
4056 if ((ii < starting || (ii < ending && !NILP (end)))) | 4079 if ((ii < starting || (ii < ending && !NILP (end)))) |
4057 { | 4080 { |
4058 check_sequence_range (args[0], start, end, | 4081 check_sequence_range (args[0], start, end, |
4068 0); | 4091 0); |
4069 } | 4092 } |
4070 } | 4093 } |
4071 else if (STRINGP (sequence)) | 4094 else if (STRINGP (sequence)) |
4072 { | 4095 { |
4096 Lisp_Object elt = Qnil; | |
4097 | |
4073 if (EQ (Qidentity, key)) | 4098 if (EQ (Qidentity, key)) |
4074 { | 4099 { |
4075 /* We know all the elements will be characters; set check_test to | 4100 /* We know all the elements will be characters; set check_test to |
4076 reflect that. This isn't useful if KEY is not #'identity, since | 4101 reflect that. This isn't useful if KEY is not #'identity, since |
4077 it may return non-characters for the elements. */ | 4102 it may return non-characters for the elements. */ |
4086 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | 4111 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; |
4087 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging; | 4112 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging; |
4088 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor; | 4113 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor; |
4089 Elemcount deleted = 0; | 4114 Elemcount deleted = 0; |
4090 | 4115 |
4091 elt = Qnil; | |
4092 GCPRO1 (elt); | 4116 GCPRO1 (elt); |
4093 | 4117 |
4094 while (cursor_offset < byte_len) | 4118 while (cursor_offset < byte_len) |
4095 { | 4119 { |
4096 if (starting <= ii && ii < ending) | 4120 if (starting <= ii && ii < ending) |
4241 else if (VECTORP (sequence)) | 4265 else if (VECTORP (sequence)) |
4242 { | 4266 { |
4243 Elemcount deleted = 0; | 4267 Elemcount deleted = 0; |
4244 Lisp_Object *content = XVECTOR_DATA (sequence); | 4268 Lisp_Object *content = XVECTOR_DATA (sequence); |
4245 struct Lisp_Bit_Vector *deleting; | 4269 struct Lisp_Bit_Vector *deleting; |
4270 Lisp_Object elt = Qnil; | |
4246 | 4271 |
4247 len = XVECTOR_LENGTH (sequence); | 4272 len = XVECTOR_LENGTH (sequence); |
4248 check_sequence_range (sequence, start, end, make_integer (len)); | 4273 check_sequence_range (sequence, start, end, make_integer (len)); |
4249 | 4274 |
4250 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | 4275 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) |
4324 that's the possible number of distinct elements if EQ is regarded | 4349 that's the possible number of distinct elements if EQ is regarded |
4325 as identity, which it should be). But to support arbitrary TEST | 4350 as identity, which it should be). But to support arbitrary TEST |
4326 and KEY arguments, which may be non-deterministic from our | 4351 and KEY arguments, which may be non-deterministic from our |
4327 perspective, we need the same algorithm as for vectors. */ | 4352 perspective, we need the same algorithm as for vectors. */ |
4328 struct Lisp_Bit_Vector *deleting; | 4353 struct Lisp_Bit_Vector *deleting; |
4354 Lisp_Object elt = Qnil; | |
4329 | 4355 |
4330 len = bit_vector_length (bv); | 4356 len = bit_vector_length (bv); |
4331 | 4357 |
4332 if (EQ (Qidentity, key)) | 4358 if (EQ (Qidentity, key)) |
4333 { | 4359 { |
4425 | 4451 |
4426 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | 4452 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) |
4427 */ | 4453 */ |
4428 (int nargs, Lisp_Object *args)) | 4454 (int nargs, Lisp_Object *args)) |
4429 { | 4455 { |
4430 Lisp_Object sequence = args[0], tail = sequence, keyed, positioned = Qnil; | 4456 Lisp_Object sequence = args[0], keyed, positioned = Qnil; |
4431 Lisp_Object result = sequence, result_tail = result, cursor = Qnil; | 4457 Lisp_Object result = sequence, result_tail = result, cursor = Qnil; |
4432 Lisp_Object cons_with_shared_tail = Qnil, elt, elt0; | 4458 Lisp_Object cons_with_shared_tail = Qnil; |
4433 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0; | 4459 Elemcount starting = 0, ending = EMACS_INT_MAX, ii = 0; |
4434 Boolint test_not_unboundp = 1; | 4460 Boolint test_not_unboundp = 1; |
4435 check_test_func_t check_test = NULL; | 4461 check_test_func_t check_test = NULL; |
4436 struct gcpro gcpro1, gcpro2, gcpro3; | 4462 struct gcpro gcpro1, gcpro2; |
4437 | 4463 |
4438 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6, | 4464 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6, |
4439 (test, key, test_not, start, end, from_end), | 4465 (test, key, test_not, start, end, from_end), |
4440 (start = Qzero)); | 4466 (start = Qzero)); |
4441 | 4467 |
4465 | 4491 |
4466 if (NILP (from_end)) | 4492 if (NILP (from_end)) |
4467 { | 4493 { |
4468 Lisp_Object ignore = Qnil; | 4494 Lisp_Object ignore = Qnil; |
4469 | 4495 |
4470 GCPRO3 (tail, keyed, result); | 4496 GCPRO2 (keyed, result); |
4471 | 4497 |
4472 { | 4498 { |
4473 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | 4499 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
4474 { | 4500 { |
4475 if (starting <= ii && ii <= ending) | 4501 if (starting <= ii && ii <= ending) |
4476 { | 4502 { |
4477 keyed = KEY (key, elt); | 4503 keyed = KEY (key, elt); |
4478 positioned | 4504 positioned |
4496 break; | 4522 break; |
4497 } | 4523 } |
4498 | 4524 |
4499 ii++; | 4525 ii++; |
4500 } | 4526 } |
4527 END_GC_EXTERNAL_LIST_LOOP (elt); | |
4501 } | 4528 } |
4502 | 4529 |
4503 { | 4530 { |
4504 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) | 4531 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
4505 { | 4532 { |
4506 if (!(starting <= ii && ii <= ending)) | 4533 if (!(starting <= ii && ii <= ending)) |
4507 { | 4534 { |
4508 ii++; | 4535 ii++; |
4509 continue; | 4536 continue; |
4512 /* For this algorithm, each time we encounter an object to be | 4539 /* For this algorithm, each time we encounter an object to be |
4513 removed, copy the output list from the tail beyond the last | 4540 removed, copy the output list from the tail beyond the last |
4514 removed cons to this one. Otherwise, the tail of the output list | 4541 removed cons to this one. Otherwise, the tail of the output list |
4515 is shared with the input list, which is OK. */ | 4542 is shared with the input list, which is OK. */ |
4516 | 4543 |
4517 keyed = KEY (key, elt0); | 4544 keyed = KEY (key, elt); |
4518 positioned | 4545 positioned |
4519 = list_position_cons_before (&ignore, keyed, XCDR (tail), | 4546 = list_position_cons_before (&ignore, keyed, XCDR (tail), |
4520 check_test, test_not_unboundp, | 4547 check_test, test_not_unboundp, |
4521 test, key, 0, | 4548 test, key, 0, |
4522 make_int (max (starting - (ii + 1), | 4549 make_int (max (starting - (ii + 1), |
4544 cons_with_shared_tail = result_tail; | 4571 cons_with_shared_tail = result_tail; |
4545 } | 4572 } |
4546 | 4573 |
4547 ii++; | 4574 ii++; |
4548 } | 4575 } |
4576 END_GC_EXTERNAL_LIST_LOOP (elt); | |
4549 } | 4577 } |
4578 | |
4550 UNGCPRO; | 4579 UNGCPRO; |
4551 | 4580 |
4552 if ((ii < starting || (ii < ending && !NILP (end)))) | 4581 if ((ii < starting || (ii < ending && !NILP (end)))) |
4553 { | 4582 { |
4554 check_sequence_range (args[0], start, end, Flength (args[0])); | 4583 check_sequence_range (args[0], start, end, Flength (args[0])); |
7928 } | 7957 } |
7929 else if (LISTP (sequence)) | 7958 else if (LISTP (sequence)) |
7930 { | 7959 { |
7931 if (NILP (from_end)) | 7960 if (NILP (from_end)) |
7932 { | 7961 { |
7933 struct gcpro gcpro1, gcpro2; | 7962 struct gcpro gcpro1; |
7934 Lisp_Object tailed = Qnil; | 7963 |
7935 | 7964 GCPRO1 (accum); |
7936 GCPRO2 (tailed, accum); | |
7937 | 7965 |
7938 if (!UNBOUNDP (initial_value)) | 7966 if (!UNBOUNDP (initial_value)) |
7939 { | 7967 { |
7940 accum = initial_value; | 7968 accum = initial_value; |
7941 } | 7969 } |
7942 else if (ending - starting) | 7970 else if (ending - starting) |
7943 { | 7971 { |
7944 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) | 7972 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence) |
7945 { | 7973 { |
7946 /* KEY may amputate the list behind us; make sure what | |
7947 remains to be processed is still reachable. */ | |
7948 tailed = tail; | |
7949 if (ii == starting) | 7974 if (ii == starting) |
7950 { | 7975 { |
7951 accum = KEY (key, elt); | 7976 accum = KEY (key, elt); |
7952 starting++; | 7977 starting++; |
7953 break; | 7978 break; |
7954 } | 7979 } |
7955 ++ii; | 7980 ++ii; |
7956 } | 7981 } |
7982 END_GC_EXTERNAL_LIST_LOOP (elt); | |
7957 } | 7983 } |
7958 | 7984 |
7959 ii = 0; | 7985 ii = 0; |
7960 | 7986 |
7961 if (ending - starting) | 7987 if (ending - starting) |
7962 { | 7988 { |
7963 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) | 7989 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence) |
7964 { | 7990 { |
7965 /* KEY or FUNCTION may amputate the list behind us; make | |
7966 sure what remains to be processed is still | |
7967 reachable. */ | |
7968 tailed = tail; | |
7969 if (ii >= starting) | 7991 if (ii >= starting) |
7970 { | 7992 { |
7971 if (ii < ending) | 7993 if (ii < ending) |
7972 { | 7994 { |
7973 accum = CALL2 (function, accum, KEY (key, elt)); | 7995 accum = CALL2 (function, accum, KEY (key, elt)); |
7977 break; | 7999 break; |
7978 } | 8000 } |
7979 } | 8001 } |
7980 ++ii; | 8002 ++ii; |
7981 } | 8003 } |
8004 END_GC_EXTERNAL_LIST_LOOP (elt); | |
7982 } | 8005 } |
7983 | 8006 |
7984 UNGCPRO; | 8007 UNGCPRO; |
7985 | 8008 |
7986 if (ii < starting || (ii < ending && !NILP (end))) | 8009 if (ii < starting || (ii < ending && !NILP (end))) |
8699 | 8722 |
8700 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT) | 8723 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT) |
8701 */ | 8724 */ |
8702 (int nargs, Lisp_Object *args)) | 8725 (int nargs, Lisp_Object *args)) |
8703 { | 8726 { |
8704 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; | 8727 Lisp_Object new_ = args[0], item = args[1], sequence = args[2]; |
8705 Lisp_Object object_, position0; | 8728 Lisp_Object object_, position0; |
8706 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | 8729 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; |
8707 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; | 8730 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; |
8708 Boolint test_not_unboundp = 1; | 8731 Boolint test_not_unboundp = 1; |
8709 check_test_func_t check_test = NULL; | 8732 check_test_func_t check_test = NULL; |
8710 struct gcpro gcpro1; | |
8711 | 8733 |
8712 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9, | 8734 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9, |
8713 (test, if_, if_not, test_not, key, start, end, count, | 8735 (test, if_, if_not, test_not, key, start, end, count, |
8714 from_end), (start = Qzero)); | 8736 from_end), (start = Qzero)); |
8715 | 8737 |
8747 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | 8769 check_test = get_check_test_function (item, &test, test_not, if_, if_not, |
8748 key, &test_not_unboundp); | 8770 key, &test_not_unboundp); |
8749 | 8771 |
8750 if (CONSP (sequence)) | 8772 if (CONSP (sequence)) |
8751 { | 8773 { |
8752 Lisp_Object elt; | |
8753 | |
8754 if (!NILP (count) && !NILP (from_end)) | 8774 if (!NILP (count) && !NILP (from_end)) |
8755 { | 8775 { |
8756 Lisp_Object present = count_with_tail (&elt, nargs - 1, args + 1, | 8776 Lisp_Object present = count_with_tail (&object_, nargs - 1, args + 1, |
8757 Qnsubstitute); | 8777 Qnsubstitute); |
8758 | 8778 |
8759 if (ZEROP (present)) | 8779 if (ZEROP (present)) |
8760 { | 8780 { |
8761 return sequence; | 8781 return sequence; |
8763 | 8783 |
8764 presenting = XINT (present); | 8784 presenting = XINT (present); |
8765 presenting = presenting <= counting ? 0 : presenting - counting; | 8785 presenting = presenting <= counting ? 0 : presenting - counting; |
8766 } | 8786 } |
8767 | 8787 |
8768 GCPRO1 (tail); | |
8769 { | 8788 { |
8770 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | 8789 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
8771 { | 8790 { |
8772 if (!(ii < ending)) | 8791 if (!(ii < ending)) |
8773 { | 8792 { |
8774 break; | 8793 break; |
8775 } | 8794 } |
8787 break; | 8806 break; |
8788 } | 8807 } |
8789 | 8808 |
8790 ii++; | 8809 ii++; |
8791 } | 8810 } |
8811 END_GC_EXTERNAL_LIST_LOOP (elt); | |
8792 } | 8812 } |
8793 UNGCPRO; | |
8794 | 8813 |
8795 if ((ii < starting || (ii < ending && !NILP (end))) | 8814 if ((ii < starting || (ii < ending && !NILP (end))) |
8796 && encountered < counting) | 8815 && encountered < counting) |
8797 { | 8816 { |
8798 check_sequence_range (args[0], start, end, Flength (args[0])); | 8817 check_sequence_range (args[0], start, end, Flength (args[0])); |
8960 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT) | 8979 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT) |
8961 */ | 8980 */ |
8962 (int nargs, Lisp_Object *args)) | 8981 (int nargs, Lisp_Object *args)) |
8963 { | 8982 { |
8964 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; | 8983 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; |
8965 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; | 8984 Lisp_Object result = Qnil, result_tail = Qnil; |
8966 Lisp_Object object, position0, matched_count; | 8985 Lisp_Object object, position0, matched_count; |
8967 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | 8986 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; |
8968 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; | 8987 Elemcount ii = 0, counting = EMACS_INT_MAX, presenting = 0; |
8969 Boolint test_not_unboundp = 1; | 8988 Boolint test_not_unboundp = 1; |
8970 check_test_func_t check_test = NULL; | 8989 check_test_func_t check_test = NULL; |
8971 struct gcpro gcpro1; | 8990 struct gcpro gcpro1; |
8972 | 8991 |
8973 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9, | 8992 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9, |
9040 { | 9059 { |
9041 presenting = XINT (matched_count); | 9060 presenting = XINT (matched_count); |
9042 presenting = presenting <= counting ? 0 : presenting - counting; | 9061 presenting = presenting <= counting ? 0 : presenting - counting; |
9043 } | 9062 } |
9044 | 9063 |
9045 GCPRO1 (tailing); | 9064 GCPRO1 (result); |
9046 { | 9065 { |
9047 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) | 9066 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing) |
9048 { | 9067 { |
9049 if (EQ (tail, tailing)) | 9068 if (EQ (tail, tailing)) |
9050 { | 9069 { |
9070 XUNGCPRO (elt); | |
9071 UNGCPRO; | |
9072 | |
9051 if (NILP (result)) | 9073 if (NILP (result)) |
9052 { | 9074 { |
9053 RETURN_UNGCPRO (XCDR (tail)); | 9075 return XCDR (tail); |
9054 } | 9076 } |
9055 | 9077 |
9056 XSETCDR (result_tail, XCDR (tail)); | 9078 XSETCDR (result_tail, XCDR (tail)); |
9057 RETURN_UNGCPRO (result); | 9079 return result; |
9058 } | 9080 } |
9059 else if (starting <= ii && ii < ending && | 9081 else if (starting <= ii && ii < ending && |
9060 (check_test (test, key, item, elt) == test_not_unboundp) | 9082 (check_test (test, key, item, elt) == test_not_unboundp) |
9061 && (presenting ? encountered++ >= presenting | 9083 && (presenting ? encountered++ >= presenting |
9062 : encountered++ < counting)) | 9084 : encountered++ < counting)) |
9086 break; | 9108 break; |
9087 } | 9109 } |
9088 | 9110 |
9089 ii++; | 9111 ii++; |
9090 } | 9112 } |
9113 END_GC_EXTERNAL_LIST_LOOP (elt); | |
9091 } | 9114 } |
9092 UNGCPRO; | 9115 UNGCPRO; |
9093 | 9116 |
9094 if (ii < starting || (ii < ending && !NILP (end))) | 9117 if (ii < starting || (ii < ending && !NILP (end))) |
9095 { | 9118 { |
9134 static Lisp_Object | 9157 static Lisp_Object |
9135 sublis (Lisp_Object alist, Lisp_Object tree, | 9158 sublis (Lisp_Object alist, Lisp_Object tree, |
9136 check_test_func_t check_test, Boolint test_not_unboundp, | 9159 check_test_func_t check_test, Boolint test_not_unboundp, |
9137 Lisp_Object test, Lisp_Object key, int depth) | 9160 Lisp_Object test, Lisp_Object key, int depth) |
9138 { | 9161 { |
9139 Lisp_Object keyed = KEY (key, tree), tailed = alist, aa, dd; | 9162 Lisp_Object keyed = KEY (key, tree), aa, dd; |
9140 struct gcpro gcpro1, gcpro2, gcpro3; | 9163 struct gcpro gcpro1; |
9141 | 9164 |
9142 if (depth + lisp_eval_depth > max_lisp_eval_depth) | 9165 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
9143 { | 9166 { |
9144 stack_overflow ("Stack overflow in sublis", tree); | 9167 stack_overflow ("Stack overflow in sublis", tree); |
9145 } | 9168 } |
9146 | 9169 |
9147 GCPRO3 (tailed, alist, tree); | |
9148 { | 9170 { |
9149 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | 9171 GC_EXTERNAL_LIST_LOOP_2 (elt, alist) |
9150 { | 9172 { |
9151 tailed = tail; | 9173 if (CONSP (elt) && |
9152 | 9174 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp) |
9153 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9154 { | 9175 { |
9155 /* Don't use elt_cdr, it is helpful to allow TEST or KEY to | 9176 XUNGCPRO (elt); |
9156 modify the alist while it executes. */ | 9177 return XCDR (elt); |
9157 RETURN_UNGCPRO (XCDR (elt)); | |
9158 } | 9178 } |
9159 } | 9179 } |
9180 END_GC_EXTERNAL_LIST_LOOP (elt); | |
9160 } | 9181 } |
9182 | |
9161 if (!CONSP (tree)) | 9183 if (!CONSP (tree)) |
9162 { | 9184 { |
9163 RETURN_UNGCPRO (tree); | 9185 return tree; |
9164 } | 9186 } |
9165 | 9187 |
9166 aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key, | 9188 aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key, |
9167 depth + 1); | 9189 depth + 1); |
9168 dd = sublis (alist, XCDR (tree), check_test, test_not_unboundp, test, key, | 9190 dd = sublis (alist, XCDR (tree), check_test, test_not_unboundp, test, key, |
9169 depth + 1); | 9191 depth + 1); |
9170 | 9192 |
9171 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree))) | 9193 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree))) |
9172 { | 9194 { |
9173 RETURN_UNGCPRO (tree); | 9195 return tree; |
9174 } | 9196 } |
9175 | 9197 |
9176 RETURN_UNGCPRO (Fcons (aa, dd)); | 9198 return Fcons (aa, dd); |
9177 } | 9199 } |
9178 | 9200 |
9179 DEFUN ("sublis", Fsublis, 2, MANY, 0, /* | 9201 DEFUN ("sublis", Fsublis, 2, MANY, 0, /* |
9180 Perform substitutions indicated by ALIST in TREE (non-destructively). | 9202 Perform substitutions indicated by ALIST in TREE (non-destructively). |
9181 Return a copy of TREE with all matching elements replaced. | 9203 Return a copy of TREE with all matching elements replaced. |
9221 nsublis (Lisp_Object alist, Lisp_Object tree, | 9243 nsublis (Lisp_Object alist, Lisp_Object tree, |
9222 check_test_func_t check_test, | 9244 check_test_func_t check_test, |
9223 Boolint test_not_unboundp, | 9245 Boolint test_not_unboundp, |
9224 Lisp_Object test, Lisp_Object key, int depth) | 9246 Lisp_Object test, Lisp_Object key, int depth) |
9225 { | 9247 { |
9226 Lisp_Object tree_saved = tree, tailed = alist, tortoise = tree, keyed = Qnil; | 9248 Lisp_Object tree_saved = tree, tortoise = tree, keyed = Qnil; |
9227 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 9249 struct gcpro gcpro1, gcpro2; |
9228 int count = 0; | 9250 int count = 0; |
9229 | 9251 |
9230 if (depth + lisp_eval_depth > max_lisp_eval_depth) | 9252 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
9231 { | 9253 { |
9232 stack_overflow ("Stack overflow in nsublis", tree); | 9254 stack_overflow ("Stack overflow in nsublis", tree); |
9233 } | 9255 } |
9234 | 9256 |
9235 GCPRO4 (tailed, alist, tree_saved, keyed); | 9257 GCPRO2 (tree_saved, keyed); |
9236 | 9258 |
9237 while (CONSP (tree)) | 9259 while (CONSP (tree)) |
9238 { | 9260 { |
9239 Boolint replaced = 0; | 9261 Boolint replaced = 0; |
9240 keyed = KEY (key, XCAR (tree)); | 9262 keyed = KEY (key, XCAR (tree)); |
9241 | 9263 |
9242 { | 9264 { |
9243 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | 9265 GC_EXTERNAL_LIST_LOOP_2 (elt, alist) |
9244 { | 9266 { |
9245 tailed = tail; | 9267 if (CONSP (elt) && |
9246 | 9268 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp) |
9247 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9248 { | 9269 { |
9249 CHECK_LISP_WRITEABLE (tree); | 9270 CHECK_LISP_WRITEABLE (tree); |
9250 /* See comment in sublis() on using elt_cdr. */ | 9271 /* See comment in sublis() on using elt_cdr. */ |
9251 XSETCAR (tree, XCDR (elt)); | 9272 XSETCAR (tree, XCDR (elt)); |
9252 replaced = 1; | 9273 replaced = 1; |
9253 break; | 9274 break; |
9254 } | 9275 } |
9255 } | 9276 } |
9277 END_GC_EXTERNAL_LIST_LOOP (elt); | |
9256 } | 9278 } |
9257 | 9279 |
9258 if (!replaced) | 9280 if (!replaced) |
9259 { | 9281 { |
9260 if (CONSP (XCAR (tree))) | 9282 if (CONSP (XCAR (tree))) |
9266 | 9288 |
9267 keyed = KEY (key, XCDR (tree)); | 9289 keyed = KEY (key, XCDR (tree)); |
9268 replaced = 0; | 9290 replaced = 0; |
9269 | 9291 |
9270 { | 9292 { |
9271 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | 9293 GC_EXTERNAL_LIST_LOOP_2 (elt, alist) |
9272 { | 9294 { |
9273 tailed = tail; | 9295 if (CONSP (elt) && |
9274 | 9296 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp) |
9275 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9276 { | 9297 { |
9277 CHECK_LISP_WRITEABLE (tree); | 9298 CHECK_LISP_WRITEABLE (tree); |
9278 /* See comment in sublis() on using elt_cdr. */ | |
9279 XSETCDR (tree, XCDR (elt)); | 9299 XSETCDR (tree, XCDR (elt)); |
9280 tree = Qnil; | 9300 tree = Qnil; |
9281 break; | 9301 break; |
9282 } | 9302 } |
9283 } | 9303 } |
9304 END_GC_EXTERNAL_LIST_LOOP (elt); | |
9284 } | 9305 } |
9285 | 9306 |
9286 if (!NILP (tree)) | 9307 if (!NILP (tree)) |
9287 { | 9308 { |
9288 tree = XCDR (tree); | 9309 tree = XCDR (tree); |
9339 keyed = KEY (key, tree); | 9360 keyed = KEY (key, tree); |
9340 | 9361 |
9341 { | 9362 { |
9342 /* nsublis() won't attempt to replace a cons handed to it, do that | 9363 /* nsublis() won't attempt to replace a cons handed to it, do that |
9343 ourselves. */ | 9364 ourselves. */ |
9344 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | 9365 GC_EXTERNAL_LIST_LOOP_2 (elt, alist) |
9345 { | 9366 { |
9346 tailed = tail; | 9367 if (CONSP (elt) && |
9347 | 9368 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp) |
9348 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9349 { | 9369 { |
9350 /* See comment in sublis() on using elt_cdr. */ | 9370 XUNGCPRO (elt); |
9351 RETURN_UNGCPRO (XCDR (elt)); | 9371 return XCDR (elt); |
9352 } | 9372 } |
9353 } | 9373 } |
9374 END_GC_EXTERNAL_LIST_LOOP (elt); | |
9354 } | 9375 } |
9355 | 9376 |
9356 UNGCPRO; | 9377 UNGCPRO; |
9357 | 9378 |
9358 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0); | 9379 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0); |
10519 /* These two functions do set operations, those that can be visualised with | 10540 /* These two functions do set operations, those that can be visualised with |
10520 Venn diagrams. */ | 10541 Venn diagrams. */ |
10521 static Lisp_Object | 10542 static Lisp_Object |
10522 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) | 10543 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) |
10523 { | 10544 { |
10524 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | 10545 Lisp_Object liszt1 = args[0], liszt2 = args[1]; |
10525 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil; | 10546 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil; |
10526 Lisp_Object keyed = Qnil, ignore = Qnil; | 10547 Lisp_Object keyed = Qnil, ignore = Qnil; |
10527 Elemcount len; | |
10528 Boolint test_not_unboundp = 1; | 10548 Boolint test_not_unboundp = 1; |
10529 check_test_func_t check_test = NULL; | 10549 check_test_func_t check_test = NULL; |
10530 struct gcpro gcpro1, gcpro2, gcpro3; | 10550 struct gcpro gcpro1, gcpro2; |
10531 | 10551 |
10532 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable), | 10552 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable), |
10533 NULL, 2, 0); | 10553 NULL, 2, 0); |
10534 | 10554 |
10535 CHECK_LIST (liszt1); | 10555 CHECK_LIST (liszt1); |
10548 } | 10568 } |
10549 | 10569 |
10550 get_check_match_function (&test, test_not, Qnil, Qnil, key, | 10570 get_check_match_function (&test, test_not, Qnil, Qnil, key, |
10551 &test_not_unboundp, &check_test); | 10571 &test_not_unboundp, &check_test); |
10552 | 10572 |
10553 GCPRO3 (tail, keyed, result); | 10573 GCPRO2 (keyed, result); |
10554 | 10574 |
10555 { | 10575 { |
10556 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | 10576 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1) |
10557 { | 10577 { |
10558 keyed = KEY (key, elt); | 10578 keyed = KEY (key, elt); |
10559 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | 10579 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, |
10560 check_test, test_not_unboundp, | 10580 check_test, test_not_unboundp, |
10561 test, key, 0, Qzero, Qnil)) | 10581 test, key, 0, Qzero, Qnil)) |
10579 XSETCDR (result_tail, Fcons (elt, Qnil)); | 10599 XSETCDR (result_tail, Fcons (elt, Qnil)); |
10580 result_tail = XCDR (result_tail); | 10600 result_tail = XCDR (result_tail); |
10581 } | 10601 } |
10582 } | 10602 } |
10583 } | 10603 } |
10604 END_GC_EXTERNAL_LIST_LOOP (elt); | |
10584 } | 10605 } |
10585 | 10606 |
10586 UNGCPRO; | 10607 UNGCPRO; |
10587 | 10608 |
10588 return result; | 10609 return result; |
10594 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil; | 10615 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil; |
10595 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil; | 10616 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil; |
10596 Elemcount count; | 10617 Elemcount count; |
10597 Boolint test_not_unboundp = 1; | 10618 Boolint test_not_unboundp = 1; |
10598 check_test_func_t check_test = NULL; | 10619 check_test_func_t check_test = NULL; |
10599 struct gcpro gcpro1, gcpro2, gcpro3; | 10620 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
10600 | 10621 |
10601 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not), | 10622 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not), |
10602 NULL, 2, 0); | 10623 NULL, 2, 0); |
10603 | 10624 |
10604 CHECK_LIST (liszt1); | 10625 CHECK_LIST (liszt1); |
10617 } | 10638 } |
10618 | 10639 |
10619 get_check_match_function (&test, test_not, Qnil, Qnil, key, | 10640 get_check_match_function (&test, test_not, Qnil, Qnil, key, |
10620 &test_not_unboundp, &check_test); | 10641 &test_not_unboundp, &check_test); |
10621 | 10642 |
10622 GCPRO3 (tail, keyed, liszt1); | 10643 tortoise_elt = tail = liszt1, count = 0; |
10623 | 10644 |
10624 tortoise_elt = tail = liszt1, count = 0; | 10645 GCPRO4 (tail, keyed, liszt1, tortoise_elt); |
10625 | 10646 |
10626 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | 10647 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : |
10627 (signal_malformed_list_error (liszt1), 0)) | 10648 (signal_malformed_list_error (liszt1), 0)) |
10628 { | 10649 { |
10629 keyed = KEY (key, elt); | 10650 keyed = KEY (key, elt); |
10791 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | 10812 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) |
10792 */ | 10813 */ |
10793 (int nargs, Lisp_Object *args)) | 10814 (int nargs, Lisp_Object *args)) |
10794 { | 10815 { |
10795 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil; | 10816 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil; |
10796 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, result, result_tail; | 10817 Lisp_Object keyed = Qnil, result, result_tail; |
10797 Elemcount len; | |
10798 Boolint test_not_unboundp = 1; | 10818 Boolint test_not_unboundp = 1; |
10799 check_test_func_t check_test = NULL, check_match = NULL; | 10819 check_test_func_t check_test = NULL, check_match = NULL; |
10800 struct gcpro gcpro1, gcpro2, gcpro3; | 10820 struct gcpro gcpro1, gcpro2; |
10801 | 10821 |
10802 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL); | 10822 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL); |
10803 | 10823 |
10804 CHECK_LIST (liszt1); | 10824 CHECK_LIST (liszt1); |
10805 CHECK_LIST (liszt2); | 10825 CHECK_LIST (liszt2); |
10817 } | 10837 } |
10818 | 10838 |
10819 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | 10839 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, |
10820 &test_not_unboundp, &check_test); | 10840 &test_not_unboundp, &check_test); |
10821 | 10841 |
10822 GCPRO3 (tail, keyed, result); | 10842 GCPRO2 (keyed, result); |
10823 | 10843 |
10824 if (NILP (stable)) | 10844 if (NILP (stable)) |
10825 { | 10845 { |
10826 result = liszt2; | 10846 result = liszt2; |
10827 { | 10847 { |
10828 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | 10848 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1) |
10829 { | 10849 { |
10830 keyed = KEY (key, elt); | 10850 keyed = KEY (key, elt); |
10831 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | 10851 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, |
10832 check_test, test_not_unboundp, | 10852 check_test, test_not_unboundp, |
10833 test, key, 0, Qzero, Qnil))) | 10853 test, key, 0, Qzero, Qnil))) |
10841 is called an awful lot more, so it's a space win but not | 10861 is called an awful lot more, so it's a space win but not |
10842 a time win. */ | 10862 a time win. */ |
10843 result = Fcons (elt, result); | 10863 result = Fcons (elt, result); |
10844 } | 10864 } |
10845 } | 10865 } |
10866 END_GC_EXTERNAL_LIST_LOOP (elt); | |
10846 } | 10867 } |
10847 } | 10868 } |
10848 else | 10869 else |
10849 { | 10870 { |
10850 result = result_tail = Qnil; | 10871 result = result_tail = Qnil; |
10854 the values in backwards order. According to the CLTL2 | 10875 the values in backwards order. According to the CLTL2 |
10855 documentation, `union' is not required to preserve the ordering of | 10876 documentation, `union' is not required to preserve the ordering of |
10856 elements in any fashion; providing the functionality for a stable | 10877 elements in any fashion; providing the functionality for a stable |
10857 union is an XEmacs extension. */ | 10878 union is an XEmacs extension. */ |
10858 { | 10879 { |
10859 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) | 10880 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2) |
10860 { | 10881 { |
10861 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | 10882 if (NILP (list_position_cons_before (&ignore, elt, liszt1, |
10862 check_match, test_not_unboundp, | 10883 check_match, test_not_unboundp, |
10863 test, key, 1, Qzero, Qnil))) | 10884 test, key, 1, Qzero, Qnil))) |
10864 { | 10885 { |
10871 XSETCDR (result_tail, Fcons (elt, Qnil)); | 10892 XSETCDR (result_tail, Fcons (elt, Qnil)); |
10872 result_tail = XCDR (result_tail); | 10893 result_tail = XCDR (result_tail); |
10873 } | 10894 } |
10874 } | 10895 } |
10875 } | 10896 } |
10897 END_GC_EXTERNAL_LIST_LOOP (elt); | |
10876 } | 10898 } |
10877 | 10899 |
10878 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result); | 10900 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result); |
10879 } | 10901 } |
10880 | 10902 |
10898 | 10920 |
10899 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | 10921 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) |
10900 */ | 10922 */ |
10901 (int nargs, Lisp_Object *args)) | 10923 (int nargs, Lisp_Object *args)) |
10902 { | 10924 { |
10903 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | 10925 Lisp_Object liszt1 = args[0], liszt2 = args[1]; |
10904 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil; | 10926 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil; |
10905 Elemcount len; | |
10906 Boolint test_not_unboundp = 1; | 10927 Boolint test_not_unboundp = 1; |
10907 check_test_func_t check_match = NULL, check_test = NULL; | 10928 check_test_func_t check_match = NULL, check_test = NULL; |
10908 struct gcpro gcpro1, gcpro2, gcpro3; | 10929 struct gcpro gcpro1, gcpro2; |
10909 | 10930 |
10910 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4, | 10931 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4, |
10911 (test, key, test_not, stable), NULL); | 10932 (test, key, test_not, stable), NULL); |
10912 | 10933 |
10913 CHECK_LIST (liszt1); | 10934 CHECK_LIST (liszt1); |
10921 } | 10942 } |
10922 | 10943 |
10923 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | 10944 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, |
10924 &test_not_unboundp, &check_test); | 10945 &test_not_unboundp, &check_test); |
10925 | 10946 |
10926 GCPRO3 (tail, keyed, result); | 10947 GCPRO2 (keyed, result); |
10927 { | 10948 { |
10928 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | 10949 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1) |
10929 { | 10950 { |
10930 keyed = KEY (key, elt); | 10951 keyed = KEY (key, elt); |
10931 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | 10952 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, |
10932 check_test, test_not_unboundp, | 10953 check_test, test_not_unboundp, |
10933 test, key, 0, Qzero, Qnil))) | 10954 test, key, 0, Qzero, Qnil))) |
10945 XSETCDR (result_tail, Fcons (elt, Qnil)); | 10966 XSETCDR (result_tail, Fcons (elt, Qnil)); |
10946 result_tail = XCDR (result_tail); | 10967 result_tail = XCDR (result_tail); |
10947 } | 10968 } |
10948 } | 10969 } |
10949 } | 10970 } |
10971 END_GC_EXTERNAL_LIST_LOOP (elt); | |
10950 } | 10972 } |
10951 | 10973 |
10952 { | 10974 { |
10953 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) | 10975 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2) |
10954 { | 10976 { |
10955 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | 10977 if (NILP (list_position_cons_before (&ignore, elt, liszt1, |
10956 check_match, test_not_unboundp, | 10978 check_match, test_not_unboundp, |
10957 test, key, 1, Qzero, Qnil))) | 10979 test, key, 1, Qzero, Qnil))) |
10958 { | 10980 { |
10969 XSETCDR (result_tail, Fcons (elt, Qnil)); | 10991 XSETCDR (result_tail, Fcons (elt, Qnil)); |
10970 result_tail = XCDR (result_tail); | 10992 result_tail = XCDR (result_tail); |
10971 } | 10993 } |
10972 } | 10994 } |
10973 } | 10995 } |
10996 END_GC_EXTERNAL_LIST_LOOP (elt); | |
10974 } | 10997 } |
10998 | |
10975 UNGCPRO; | 10999 UNGCPRO; |
10976 | 11000 |
10977 return result; | 11001 return result; |
10978 } | 11002 } |
10979 | 11003 |
10994 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap; | 11018 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap; |
10995 Lisp_Object prev_tail = Qnil, ignore = Qnil; | 11019 Lisp_Object prev_tail = Qnil, ignore = Qnil; |
10996 Elemcount count; | 11020 Elemcount count; |
10997 Boolint test_not_unboundp = 1; | 11021 Boolint test_not_unboundp = 1; |
10998 check_test_func_t check_match = NULL, check_test = NULL; | 11022 check_test_func_t check_match = NULL, check_test = NULL; |
10999 struct gcpro gcpro1, gcpro2, gcpro3; | 11023 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
11000 | 11024 |
11001 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4, | 11025 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4, |
11002 (test, key, test_not, stable), NULL); | 11026 (test, key, test_not, stable), NULL); |
11003 | 11027 |
11004 CHECK_LIST (liszt1); | 11028 CHECK_LIST (liszt1); |
11012 } | 11036 } |
11013 | 11037 |
11014 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | 11038 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, |
11015 &test_not_unboundp, &check_test); | 11039 &test_not_unboundp, &check_test); |
11016 | 11040 |
11017 GCPRO3 (tail, keyed, result); | |
11018 | |
11019 tortoise_elt = tail = liszt1, count = 0; | 11041 tortoise_elt = tail = liszt1, count = 0; |
11042 | |
11043 GCPRO4 (tail, keyed, result, tortoise_elt); | |
11020 | 11044 |
11021 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | 11045 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : |
11022 (signal_malformed_list_error (liszt1), 0)) | 11046 (signal_malformed_list_error (liszt1), 0)) |
11023 { | 11047 { |
11024 keyed = KEY (key, elt); | 11048 keyed = KEY (key, elt); |