Mercurial > hg > xemacs-beta
comparison src/fns.c @ 5470:0af042a0c116
Merge with trunk.
author | Mats Lidell <matsl@xemacs.org> |
---|---|
date | Mon, 07 Feb 2011 21:22:17 +0100 |
parents | a9094f28f9a9 94bbd4792049 |
children | 00e79bbbe48f |
comparison
equal
deleted
inserted
replaced
5469:2a8a04f73c15 | 5470:0af042a0c116 |
---|---|
59 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce, Qsubstitute; | 59 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce, Qsubstitute; |
60 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2, Q_if_, Q_if_not, Q_stable; | 60 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2, Q_if_, Q_if_not, Q_stable; |
61 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch; | 61 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch; |
62 | 62 |
63 Lisp_Object Qintersection, Qset_difference, Qnset_difference; | 63 Lisp_Object Qintersection, Qset_difference, Qnset_difference; |
64 Lisp_Object Qnunion, Qnintersection, Qsubsetp; | 64 Lisp_Object Qnunion, Qnintersection, Qsubsetp, Qcar_less_than_car; |
65 | 65 |
66 Lisp_Object Qbase64_conversion_error; | 66 Lisp_Object Qbase64_conversion_error; |
67 | 67 |
68 Lisp_Object Vpath_separator; | 68 Lisp_Object Vpath_separator; |
69 | 69 |
206 Lisp_Bit_Vector); | 206 Lisp_Bit_Vector); |
207 | 207 |
208 /* Various test functions for #'member*, #'assoc* and the other functions | 208 /* Various test functions for #'member*, #'assoc* and the other functions |
209 that take both TEST and KEY arguments. */ | 209 that take both TEST and KEY arguments. */ |
210 | 210 |
211 typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key, | |
212 Lisp_Object item, Lisp_Object elt); | |
213 | |
214 static Boolint | 211 static Boolint |
215 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | 212 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), |
216 Lisp_Object item, Lisp_Object elt) | 213 Lisp_Object item, Lisp_Object elt) |
217 { | 214 { |
218 return EQ (item, elt); | 215 return EQ (item, elt); |
435 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | 432 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); |
436 UNGCPRO; | 433 UNGCPRO; |
437 | 434 |
438 return !NILP (elt1); | 435 return !NILP (elt1); |
439 } | 436 } |
440 | 437 |
438 static Boolint | |
439 check_lss_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
440 Lisp_Object elt1, Lisp_Object elt2) | |
441 { | |
442 return bytecode_arithcompare (elt1, elt2) < 0; | |
443 } | |
444 | |
445 static Boolint | |
446 check_lss_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
447 Lisp_Object elt1, Lisp_Object elt2) | |
448 { | |
449 Lisp_Object args[] = { key, elt1, elt2 }; | |
450 struct gcpro gcpro1; | |
451 | |
452 GCPRO1 (args[0]); | |
453 gcpro1.nvars = countof (args); | |
454 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
455 args[1] = key; | |
456 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
457 UNGCPRO; | |
458 | |
459 return bytecode_arithcompare (args[0], args[1]) < 0; | |
460 } | |
461 | |
462 Boolint | |
463 check_lss_key_car (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
464 Lisp_Object elt1, Lisp_Object elt2) | |
465 { | |
466 struct gcpro gcpro1, gcpro2; | |
467 | |
468 GCPRO2 (elt1, elt2); | |
469 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1); | |
470 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2); | |
471 UNGCPRO; | |
472 | |
473 return bytecode_arithcompare (elt1, elt2) < 0; | |
474 } | |
475 | |
476 Boolint | |
477 check_string_lessp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
478 Lisp_Object elt1, Lisp_Object elt2) | |
479 { | |
480 return !NILP (Fstring_lessp (elt1, elt2)); | |
481 } | |
482 | |
483 static Boolint | |
484 check_string_lessp_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
485 Lisp_Object elt1, Lisp_Object elt2) | |
486 { | |
487 Lisp_Object args[] = { key, elt1, elt2 }; | |
488 struct gcpro gcpro1; | |
489 | |
490 GCPRO1 (args[0]); | |
491 gcpro1.nvars = countof (args); | |
492 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
493 args[1] = key; | |
494 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
495 UNGCPRO; | |
496 | |
497 return !NILP (Fstring_lessp (args[0], args[1])); | |
498 } | |
499 | |
500 static Boolint | |
501 check_string_lessp_key_car (Lisp_Object UNUSED (test), | |
502 Lisp_Object UNUSED (key), | |
503 Lisp_Object elt1, Lisp_Object elt2) | |
504 { | |
505 struct gcpro gcpro1, gcpro2; | |
506 | |
507 GCPRO2 (elt1, elt2); | |
508 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1); | |
509 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2); | |
510 UNGCPRO; | |
511 | |
512 return !NILP (Fstring_lessp (elt1, elt2)); | |
513 } | |
514 | |
441 static check_test_func_t | 515 static check_test_func_t |
442 get_check_match_function_1 (Lisp_Object item, | 516 get_check_match_function_1 (Lisp_Object item, |
443 Lisp_Object *test_inout, Lisp_Object test_not, | 517 Lisp_Object *test_inout, Lisp_Object test_not, |
444 Lisp_Object if_, Lisp_Object if_not, | 518 Lisp_Object if_, Lisp_Object if_not, |
445 Lisp_Object key, Boolint *test_not_unboundp_out, | 519 Lisp_Object key, Boolint *test_not_unboundp_out, |
642 return get_check_match_function_1 (Qunbound, test_inout, test_not, | 716 return get_check_match_function_1 (Qunbound, test_inout, test_not, |
643 if_, if_not, key, | 717 if_, if_not, key, |
644 test_not_unboundp_out, test_func_out); | 718 test_not_unboundp_out, test_func_out); |
645 } | 719 } |
646 | 720 |
721 /* Given PREDICATE and KEY, return a C function pointer appropriate for use | |
722 in deciding whether one given elements of a sequence is less than | |
723 another. */ | |
724 | |
725 static check_test_func_t | |
726 get_merge_predicate (Lisp_Object predicate, Lisp_Object key) | |
727 { | |
728 predicate = indirect_function (predicate, 1); | |
729 | |
730 if (NILP (key)) | |
731 { | |
732 key = Qidentity; | |
733 } | |
734 else | |
735 { | |
736 key = indirect_function (key, 1); | |
737 if (EQ (key, XSYMBOL_FUNCTION (Qidentity))) | |
738 { | |
739 key = Qidentity; | |
740 } | |
741 } | |
742 | |
743 if (EQ (key, Qidentity) && EQ (predicate, | |
744 XSYMBOL_FUNCTION (Qcar_less_than_car))) | |
745 { | |
746 key = XSYMBOL_FUNCTION (Qcar); | |
747 predicate = XSYMBOL_FUNCTION (Qlss); | |
748 } | |
749 | |
750 if (EQ (predicate, XSYMBOL_FUNCTION (Qlss))) | |
751 { | |
752 if (EQ (key, Qidentity)) | |
753 { | |
754 return check_lss_nokey; | |
755 } | |
756 | |
757 if (EQ (key, XSYMBOL_FUNCTION (Qcar))) | |
758 { | |
759 return check_lss_key_car; | |
760 } | |
761 | |
762 return check_lss_key; | |
763 } | |
764 | |
765 if (EQ (predicate, XSYMBOL_FUNCTION (Qstring_lessp))) | |
766 { | |
767 if (EQ (key, Qidentity)) | |
768 { | |
769 return check_string_lessp_nokey; | |
770 } | |
771 | |
772 if (EQ (key, XSYMBOL_FUNCTION (Qcar))) | |
773 { | |
774 return check_string_lessp_key_car; | |
775 } | |
776 | |
777 return check_string_lessp_key; | |
778 } | |
779 | |
780 if (EQ (key, Qidentity)) | |
781 { | |
782 return check_other_nokey; | |
783 } | |
784 | |
785 return check_match_other_key; | |
786 } | |
647 | 787 |
648 DEFUN ("identity", Fidentity, 1, 1, 0, /* | 788 DEFUN ("identity", Fidentity, 1, 1, 0, /* |
649 Return the argument unchanged. | 789 Return the argument unchanged. |
650 */ | 790 */ |
651 (arg)) | 791 (arg)) |
4690 } | 4830 } |
4691 | 4831 |
4692 return result; | 4832 return result; |
4693 } | 4833 } |
4694 | 4834 |
4695 static Lisp_Object | |
4696 c_merge_predicate_key (Lisp_Object obj1, Lisp_Object obj2, | |
4697 Lisp_Object pred, Lisp_Object key_func) | |
4698 { | |
4699 struct gcpro gcpro1; | |
4700 Lisp_Object args[3]; | |
4701 | |
4702 /* We could use call2() and call3() here, but we're called O(nlogn) times | |
4703 for a sequence of length n, it make some sense to inline them. */ | |
4704 args[0] = key_func; | |
4705 args[1] = obj1; | |
4706 args[2] = Qnil; | |
4707 | |
4708 GCPRO1 (args[0]); | |
4709 gcpro1.nvars = countof (args); | |
4710 | |
4711 obj1 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
4712 | |
4713 args[1] = obj2; | |
4714 obj2 = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
4715 | |
4716 args[0] = pred; | |
4717 args[1] = obj1; | |
4718 args[2] = obj2; | |
4719 | |
4720 RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args))); | |
4721 } | |
4722 | |
4723 static Lisp_Object | |
4724 c_merge_predicate_nokey (Lisp_Object obj1, Lisp_Object obj2, | |
4725 Lisp_Object pred, Lisp_Object UNUSED (key_func)) | |
4726 { | |
4727 struct gcpro gcpro1; | |
4728 Lisp_Object args[3]; | |
4729 | |
4730 /* This is (almost) the implementation of call2, it makes some sense to | |
4731 inline it here. */ | |
4732 args[0] = pred; | |
4733 args[1] = obj1; | |
4734 args[2] = obj2; | |
4735 | |
4736 GCPRO1 (args[0]); | |
4737 gcpro1.nvars = countof (args); | |
4738 | |
4739 RETURN_UNGCPRO (IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args))); | |
4740 } | |
4741 | |
4742 Lisp_Object | 4835 Lisp_Object |
4743 list_merge (Lisp_Object org_l1, Lisp_Object org_l2, | 4836 list_merge (Lisp_Object org_l1, Lisp_Object org_l2, |
4744 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, | 4837 check_test_func_t check_merge, |
4745 Lisp_Object, Lisp_Object), | 4838 Lisp_Object predicate, Lisp_Object key) |
4746 Lisp_Object predicate, Lisp_Object key_func) | |
4747 { | 4839 { |
4748 Lisp_Object value; | 4840 Lisp_Object value; |
4749 Lisp_Object tail; | 4841 Lisp_Object tail; |
4750 Lisp_Object tem; | 4842 Lisp_Object tem; |
4751 Lisp_Object l1, l2; | 4843 Lisp_Object l1, l2; |
4758 tail = Qnil; | 4850 tail = Qnil; |
4759 value = Qnil; | 4851 value = Qnil; |
4760 tortoises[0] = org_l1; | 4852 tortoises[0] = org_l1; |
4761 tortoises[1] = org_l2; | 4853 tortoises[1] = org_l2; |
4762 | 4854 |
4763 if (NULL == c_predicate) | 4855 /* It is sufficient to protect org_l1 and org_l2. When l1 and l2 are |
4764 { | 4856 updated, we copy the new values back into the org_ vars. */ |
4765 c_predicate = EQ (key_func, Qidentity) ? | |
4766 c_merge_predicate_nokey : c_merge_predicate_key; | |
4767 } | |
4768 | |
4769 /* It is sufficient to protect org_l1 and org_l2. | |
4770 When l1 and l2 are updated, we copy the new values | |
4771 back into the org_ vars. */ | |
4772 | 4857 |
4773 GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]); | 4858 GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]); |
4774 gcpro5.nvars = 2; | 4859 gcpro5.nvars = 2; |
4775 | 4860 |
4776 while (1) | 4861 while (1) |
4790 return l1; | 4875 return l1; |
4791 Fsetcdr (tail, l1); | 4876 Fsetcdr (tail, l1); |
4792 return value; | 4877 return value; |
4793 } | 4878 } |
4794 | 4879 |
4795 if (NILP (c_predicate (Fcar (l2), Fcar (l1), predicate, key_func))) | 4880 if (check_merge (predicate, key, Fcar (l2), Fcar (l1)) == 0) |
4796 { | 4881 { |
4797 tem = l1; | 4882 tem = l1; |
4798 l1 = Fcdr (l1); | 4883 l1 = Fcdr (l1); |
4799 org_l1 = l1; | 4884 org_l1 = l1; |
4800 | 4885 |
4852 | 4937 |
4853 static void | 4938 static void |
4854 array_merge (Lisp_Object *dest, Elemcount dest_len, | 4939 array_merge (Lisp_Object *dest, Elemcount dest_len, |
4855 Lisp_Object *front, Elemcount front_len, | 4940 Lisp_Object *front, Elemcount front_len, |
4856 Lisp_Object *back, Elemcount back_len, | 4941 Lisp_Object *back, Elemcount back_len, |
4857 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, | 4942 check_test_func_t check_merge, |
4858 Lisp_Object, Lisp_Object), | 4943 Lisp_Object predicate, Lisp_Object key) |
4859 Lisp_Object predicate, Lisp_Object key_func) | |
4860 { | 4944 { |
4861 Elemcount ii, fronting, backing; | 4945 Elemcount ii, fronting, backing; |
4862 Lisp_Object *front_staging = front; | 4946 Lisp_Object *front_staging = front; |
4863 Lisp_Object *back_staging = back; | 4947 Lisp_Object *back_staging = back; |
4864 struct gcpro gcpro1, gcpro2; | 4948 struct gcpro gcpro1, gcpro2; |
4916 } | 5000 } |
4917 UNGCPRO; | 5001 UNGCPRO; |
4918 return; | 5002 return; |
4919 } | 5003 } |
4920 | 5004 |
4921 if (NILP (c_predicate (back_staging[backing], front_staging[fronting], | 5005 if (check_merge (predicate, key, back_staging[backing], |
4922 predicate, key_func))) | 5006 front_staging[fronting]) == 0) |
4923 { | 5007 { |
4924 dest[ii] = front_staging[fronting]; | 5008 dest[ii] = front_staging[fronting]; |
4925 ++fronting; | 5009 ++fronting; |
4926 } | 5010 } |
4927 else | 5011 else |
4935 } | 5019 } |
4936 | 5020 |
4937 static Lisp_Object | 5021 static Lisp_Object |
4938 list_array_merge_into_list (Lisp_Object list, | 5022 list_array_merge_into_list (Lisp_Object list, |
4939 Lisp_Object *array, Elemcount array_len, | 5023 Lisp_Object *array, Elemcount array_len, |
4940 Lisp_Object (*c_predicate) (Lisp_Object, | 5024 check_test_func_t check_merge, |
4941 Lisp_Object, | 5025 Lisp_Object predicate, Lisp_Object key, |
4942 Lisp_Object, | |
4943 Lisp_Object), | |
4944 Lisp_Object predicate, Lisp_Object key_func, | |
4945 Boolint reverse_order) | 5026 Boolint reverse_order) |
4946 { | 5027 { |
4947 Lisp_Object tail = Qnil, value = Qnil, tortoise = list; | 5028 Lisp_Object tail = Qnil, value = Qnil, tortoise = list; |
4948 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 5029 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
4949 Elemcount array_index = 0; | 5030 Elemcount array_index = 0; |
4978 return value; | 5059 return value; |
4979 } | 5060 } |
4980 | 5061 |
4981 | 5062 |
4982 if (reverse_order ? | 5063 if (reverse_order ? |
4983 !NILP (c_predicate (Fcar (list), array [array_index], predicate, | 5064 check_merge (predicate, key, Fcar (list), array [array_index]) |
4984 key_func)) : | 5065 : !check_merge (predicate, key, array [array_index], Fcar (list))) |
4985 NILP (c_predicate (array [array_index], Fcar (list), predicate, | |
4986 key_func))) | |
4987 { | 5066 { |
4988 if (NILP (tail)) | 5067 if (NILP (tail)) |
4989 { | 5068 { |
4990 value = tail = list; | 5069 value = tail = list; |
4991 } | 5070 } |
5027 } | 5106 } |
5028 | 5107 |
5029 static void | 5108 static void |
5030 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len, | 5109 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len, |
5031 Lisp_Object list_one, Lisp_Object list_two, | 5110 Lisp_Object list_one, Lisp_Object list_two, |
5032 Lisp_Object (*c_predicate) (Lisp_Object, | 5111 check_test_func_t check_merge, |
5033 Lisp_Object, | 5112 Lisp_Object predicate, Lisp_Object key) |
5034 Lisp_Object, | |
5035 Lisp_Object), | |
5036 Lisp_Object predicate, Lisp_Object key_func) | |
5037 { | 5113 { |
5038 Elemcount output_index = 0; | 5114 Elemcount output_index = 0; |
5039 | 5115 |
5040 while (output_index < output_len) | 5116 while (output_index < output_len) |
5041 { | 5117 { |
5057 list_one = Fcdr (list_one), ++output_index; | 5133 list_one = Fcdr (list_one), ++output_index; |
5058 } | 5134 } |
5059 return; | 5135 return; |
5060 } | 5136 } |
5061 | 5137 |
5062 if (NILP (c_predicate (Fcar (list_two), Fcar (list_one), predicate, | 5138 if (check_merge (predicate, key, Fcar (list_two), Fcar (list_one)) |
5063 key_func))) | 5139 == 0) |
5064 { | 5140 { |
5065 output [output_index] = XCAR (list_one); | 5141 output [output_index] = XCAR (list_one); |
5066 list_one = XCDR (list_one); | 5142 list_one = XCDR (list_one); |
5067 } | 5143 } |
5068 else | 5144 else |
5079 | 5155 |
5080 static void | 5156 static void |
5081 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len, | 5157 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len, |
5082 Lisp_Object list, | 5158 Lisp_Object list, |
5083 Lisp_Object *array, Elemcount array_len, | 5159 Lisp_Object *array, Elemcount array_len, |
5084 Lisp_Object (*c_predicate) (Lisp_Object, | 5160 check_test_func_t check_merge, |
5085 Lisp_Object, | 5161 Lisp_Object predicate, Lisp_Object key, |
5086 Lisp_Object, | |
5087 Lisp_Object), | |
5088 Lisp_Object predicate, Lisp_Object key_func, | |
5089 Boolint reverse_order) | 5162 Boolint reverse_order) |
5090 { | 5163 { |
5091 Elemcount output_index = 0, array_index = 0; | 5164 Elemcount output_index = 0, array_index = 0; |
5092 | 5165 |
5093 while (output_index < output_len) | 5166 while (output_index < output_len) |
5117 | 5190 |
5118 return; | 5191 return; |
5119 } | 5192 } |
5120 | 5193 |
5121 if (reverse_order ? | 5194 if (reverse_order ? |
5122 !NILP (c_predicate (Fcar (list), array [array_index], predicate, | 5195 check_merge (predicate, key, Fcar (list), array [array_index]) : |
5123 key_func)) : | 5196 !check_merge (predicate, key, array [array_index], Fcar (list))) |
5124 NILP (c_predicate (array [array_index], Fcar (list), predicate, | |
5125 key_func))) | |
5126 { | 5197 { |
5127 output [output_index] = XCAR (list); | 5198 output [output_index] = XCAR (list); |
5128 list = XCDR (list); | 5199 list = XCDR (list); |
5129 } | 5200 } |
5130 else | 5201 else |
5168 */ | 5239 */ |
5169 (int nargs, Lisp_Object *args)) | 5240 (int nargs, Lisp_Object *args)) |
5170 { | 5241 { |
5171 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2], | 5242 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2], |
5172 predicate = args[3], result = Qnil; | 5243 predicate = args[3], result = Qnil; |
5173 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object, | 5244 check_test_func_t check_merge = NULL; |
5174 Lisp_Object); | |
5175 | 5245 |
5176 PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL); | 5246 PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL); |
5177 | 5247 |
5178 CHECK_SEQUENCE (sequence_one); | 5248 CHECK_SEQUENCE (sequence_one); |
5179 CHECK_SEQUENCE (sequence_two); | 5249 CHECK_SEQUENCE (sequence_two); |
5180 | 5250 |
5181 CHECK_KEY_ARGUMENT (key); | 5251 CHECK_KEY_ARGUMENT (key); |
5182 | 5252 |
5183 c_predicate = EQ (key, Qidentity) ? | 5253 check_merge = get_merge_predicate (predicate, key); |
5184 c_merge_predicate_nokey : c_merge_predicate_key; | |
5185 | 5254 |
5186 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two))) | 5255 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two))) |
5187 { | 5256 { |
5188 if (NILP (sequence_two)) | 5257 if (NILP (sequence_two)) |
5189 { | 5258 { |
5195 protection, but that doesn't matter. */ | 5264 protection, but that doesn't matter. */ |
5196 result = Fappend (2, args + 2); | 5265 result = Fappend (2, args + 2); |
5197 } | 5266 } |
5198 else if (CONSP (sequence_one) && CONSP (sequence_two)) | 5267 else if (CONSP (sequence_one) && CONSP (sequence_two)) |
5199 { | 5268 { |
5200 result = list_merge (sequence_one, sequence_two, c_predicate, | 5269 result = list_merge (sequence_one, sequence_two, check_merge, |
5201 predicate, key); | 5270 predicate, key); |
5202 } | 5271 } |
5203 else | 5272 else |
5204 { | 5273 { |
5205 Lisp_Object *array_storage, swap; | 5274 Lisp_Object *array_storage, swap; |
5237 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length); | 5306 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length); |
5238 } | 5307 } |
5239 | 5308 |
5240 result = list_array_merge_into_list (sequence_one, | 5309 result = list_array_merge_into_list (sequence_one, |
5241 array_storage, array_length, | 5310 array_storage, array_length, |
5242 c_predicate, | 5311 check_merge, predicate, key, |
5243 predicate, key, | |
5244 reverse_order); | 5312 reverse_order); |
5245 } | 5313 } |
5246 } | 5314 } |
5247 else | 5315 else |
5248 { | 5316 { |
5302 | 5370 |
5303 if (LISTP (sequence_one) && LISTP (sequence_two)) | 5371 if (LISTP (sequence_one) && LISTP (sequence_two)) |
5304 { | 5372 { |
5305 list_list_merge_into_array (output + 1, output_len - 1, | 5373 list_list_merge_into_array (output + 1, output_len - 1, |
5306 sequence_one, sequence_two, | 5374 sequence_one, sequence_two, |
5307 c_predicate, predicate, | 5375 check_merge, predicate, key); |
5308 key); | |
5309 } | 5376 } |
5310 else if (LISTP (sequence_one)) | 5377 else if (LISTP (sequence_one)) |
5311 { | 5378 { |
5312 list_array_merge_into_array (output + 1, output_len - 1, | 5379 list_array_merge_into_array (output + 1, output_len - 1, |
5313 sequence_one, | 5380 sequence_one, |
5314 sequence_two_storage, | 5381 sequence_two_storage, |
5315 sequence_two_len, | 5382 sequence_two_len, |
5316 c_predicate, predicate, | 5383 check_merge, predicate, key, 0); |
5317 key, 0); | |
5318 } | 5384 } |
5319 else if (LISTP (sequence_two)) | 5385 else if (LISTP (sequence_two)) |
5320 { | 5386 { |
5321 list_array_merge_into_array (output + 1, output_len - 1, | 5387 list_array_merge_into_array (output + 1, output_len - 1, |
5322 sequence_two, | 5388 sequence_two, |
5323 sequence_one_storage, | 5389 sequence_one_storage, |
5324 sequence_one_len, | 5390 sequence_one_len, |
5325 c_predicate, predicate, | 5391 check_merge, predicate, key, 1); |
5326 key, 1); | |
5327 } | 5392 } |
5328 else | 5393 else |
5329 { | 5394 { |
5330 array_merge (output + 1, output_len - 1, | 5395 array_merge (output + 1, output_len - 1, |
5331 sequence_one_storage, sequence_one_len, | 5396 sequence_one_storage, sequence_one_len, |
5332 sequence_two_storage, sequence_two_len, | 5397 sequence_two_storage, sequence_two_len, |
5333 c_predicate, predicate, | 5398 check_merge, predicate, |
5334 key); | 5399 key); |
5335 } | 5400 } |
5336 | 5401 |
5337 result = Ffuncall (output_len, output); | 5402 result = Ffuncall (output_len, output); |
5338 | 5403 |
5345 } | 5410 } |
5346 | 5411 |
5347 return result; | 5412 return result; |
5348 } | 5413 } |
5349 | 5414 |
5350 /* The sort function should return non-nil if OBJ1 < OBJ2, nil otherwise. | |
5351 NOTE: This is backwards from the way qsort() works. */ | |
5352 Lisp_Object | 5415 Lisp_Object |
5353 list_sort (Lisp_Object list, | 5416 list_sort (Lisp_Object list, check_test_func_t check_merge, |
5354 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, | 5417 Lisp_Object predicate, Lisp_Object key) |
5355 Lisp_Object, Lisp_Object), | |
5356 Lisp_Object predicate, Lisp_Object key_func) | |
5357 { | 5418 { |
5358 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | 5419 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; |
5359 Lisp_Object back, tem; | 5420 Lisp_Object back, tem; |
5360 Lisp_Object front = list; | 5421 Lisp_Object front = list; |
5361 Lisp_Object len = Flength (list); | 5422 Lisp_Object len = Flength (list); |
5362 | 5423 |
5363 if (XINT (len) < 2) | 5424 if (XINT (len) < 2) |
5364 return list; | 5425 return list; |
5365 | 5426 |
5366 if (NULL == c_predicate) | |
5367 { | |
5368 c_predicate = EQ (key_func, Qidentity) ? c_merge_predicate_nokey : | |
5369 c_merge_predicate_key; | |
5370 } | |
5371 | |
5372 len = make_int (XINT (len) / 2 - 1); | 5427 len = make_int (XINT (len) / 2 - 1); |
5373 tem = Fnthcdr (len, list); | 5428 tem = Fnthcdr (len, list); |
5374 back = Fcdr (tem); | 5429 back = Fcdr (tem); |
5375 Fsetcdr (tem, Qnil); | 5430 Fsetcdr (tem, Qnil); |
5376 | 5431 |
5377 GCPRO4 (front, back, predicate, key_func); | 5432 GCPRO4 (front, back, predicate, key); |
5378 front = list_sort (front, c_predicate, predicate, key_func); | 5433 front = list_sort (front, check_merge, predicate, key); |
5379 back = list_sort (back, c_predicate, predicate, key_func); | 5434 back = list_sort (back, check_merge, predicate, key); |
5380 | 5435 |
5381 RETURN_UNGCPRO (list_merge (front, back, c_predicate, predicate, key_func)); | 5436 RETURN_UNGCPRO (list_merge (front, back, check_merge, predicate, key)); |
5382 } | 5437 } |
5383 | 5438 |
5384 static void | 5439 static void |
5385 array_sort (Lisp_Object *array, Elemcount array_len, | 5440 array_sort (Lisp_Object *array, Elemcount array_len, |
5386 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, | 5441 check_test_func_t check_merge, |
5387 Lisp_Object, Lisp_Object), | 5442 Lisp_Object predicate, Lisp_Object key) |
5388 Lisp_Object predicate, Lisp_Object key_func) | |
5389 { | 5443 { |
5390 Elemcount split; | 5444 Elemcount split; |
5391 | 5445 |
5392 if (array_len < 2) | 5446 if (array_len < 2) |
5393 return; | 5447 return; |
5394 | 5448 |
5395 split = array_len / 2; | 5449 split = array_len / 2; |
5396 | 5450 |
5397 array_sort (array, split, c_predicate, predicate, key_func); | 5451 array_sort (array, split, check_merge, predicate, key); |
5398 array_sort (array + split, array_len - split, c_predicate, predicate, | 5452 array_sort (array + split, array_len - split, check_merge, predicate, |
5399 key_func); | 5453 key); |
5400 array_merge (array, array_len, array, split, array + split, | 5454 array_merge (array, array_len, array, split, array + split, |
5401 array_len - split, c_predicate, predicate, key_func); | 5455 array_len - split, check_merge, predicate, key); |
5402 } | 5456 } |
5403 | 5457 |
5404 DEFUN ("sort*", FsortX, 2, MANY, 0, /* | 5458 DEFUN ("sort*", FsortX, 2, MANY, 0, /* |
5405 Sort SEQUENCE, comparing elements using PREDICATE. | 5459 Sort SEQUENCE, comparing elements using PREDICATE. |
5406 Returns the sorted sequence. SEQUENCE is modified by side effect. | 5460 Returns the sorted sequence. SEQUENCE is modified by side effect. |
5419 */ | 5473 */ |
5420 (int nargs, Lisp_Object *args)) | 5474 (int nargs, Lisp_Object *args)) |
5421 { | 5475 { |
5422 Lisp_Object sequence = args[0], predicate = args[1]; | 5476 Lisp_Object sequence = args[0], predicate = args[1]; |
5423 Lisp_Object *sequence_carray; | 5477 Lisp_Object *sequence_carray; |
5424 Lisp_Object (*c_predicate) (Lisp_Object, Lisp_Object, Lisp_Object, | 5478 check_test_func_t check_merge = NULL; |
5425 Lisp_Object); | |
5426 Elemcount sequence_len, i; | 5479 Elemcount sequence_len, i; |
5427 | 5480 |
5428 PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL); | 5481 PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL); |
5429 | 5482 |
5430 CHECK_SEQUENCE (sequence); | 5483 CHECK_SEQUENCE (sequence); |
5431 | 5484 |
5432 CHECK_KEY_ARGUMENT (key); | 5485 CHECK_KEY_ARGUMENT (key); |
5433 | 5486 |
5434 c_predicate = EQ (key, Qidentity) ? | 5487 check_merge = get_merge_predicate (predicate, key); |
5435 c_merge_predicate_nokey : c_merge_predicate_key; | |
5436 | 5488 |
5437 if (LISTP (sequence)) | 5489 if (LISTP (sequence)) |
5438 { | 5490 { |
5439 sequence = list_sort (sequence, c_predicate, predicate, key); | 5491 sequence = list_sort (sequence, check_merge, predicate, key); |
5440 } | 5492 } |
5441 else if (VECTORP (sequence)) | 5493 else if (VECTORP (sequence)) |
5442 { | 5494 { |
5443 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence), | 5495 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence), |
5444 c_predicate, predicate, key); | 5496 check_merge, predicate, key); |
5445 } | 5497 } |
5446 else if (STRINGP (sequence)) | 5498 else if (STRINGP (sequence)) |
5447 { | 5499 { |
5448 Ibyte *strdata = XSTRING_DATA (sequence); | 5500 Ibyte *strdata = XSTRING_DATA (sequence); |
5449 | 5501 |
5450 sequence_len = string_char_length (sequence); | 5502 sequence_len = string_char_length (sequence); |
5451 | 5503 |
5452 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len); | 5504 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len); |
5453 | 5505 |
5454 /* No GCPRO necessary, characters are immediate. */ | 5506 /* No GCPRO necessary, characters are immediate. */ |
5455 array_sort (sequence_carray, sequence_len, c_predicate, predicate, key); | 5507 array_sort (sequence_carray, sequence_len, check_merge, predicate, key); |
5456 | 5508 |
5457 strdata = XSTRING_DATA (sequence); | 5509 strdata = XSTRING_DATA (sequence); |
5458 | 5510 |
5459 CHECK_LISP_WRITEABLE (sequence); | 5511 CHECK_LISP_WRITEABLE (sequence); |
5460 for (i = 0; i < sequence_len; ++i) | 5512 for (i = 0; i < sequence_len; ++i) |
5472 sequence_len = bit_vector_length (v); | 5524 sequence_len = bit_vector_length (v); |
5473 | 5525 |
5474 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len); | 5526 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len); |
5475 | 5527 |
5476 /* No GCPRO necessary, bits are immediate. */ | 5528 /* No GCPRO necessary, bits are immediate. */ |
5477 array_sort (sequence_carray, sequence_len, c_predicate, predicate, key); | 5529 array_sort (sequence_carray, sequence_len, check_merge, predicate, key); |
5478 | 5530 |
5479 for (i = 0; i < sequence_len; ++i) | 5531 for (i = 0; i < sequence_len; ++i) |
5480 { | 5532 { |
5481 set_bit_vector_bit (v, i, XINT (sequence_carray [i])); | 5533 set_bit_vector_bit (v, i, XINT (sequence_carray [i])); |
5482 } | 5534 } |
11694 DEFSYMBOL (Qsubstitute); | 11746 DEFSYMBOL (Qsubstitute); |
11695 DEFSYMBOL (Qmismatch); | 11747 DEFSYMBOL (Qmismatch); |
11696 DEFSYMBOL (Qintersection); | 11748 DEFSYMBOL (Qintersection); |
11697 DEFSYMBOL (Qnintersection); | 11749 DEFSYMBOL (Qnintersection); |
11698 DEFSYMBOL (Qsubsetp); | 11750 DEFSYMBOL (Qsubsetp); |
11751 DEFSYMBOL (Qcar_less_than_car); | |
11699 DEFSYMBOL (Qset_difference); | 11752 DEFSYMBOL (Qset_difference); |
11700 DEFSYMBOL (Qnset_difference); | 11753 DEFSYMBOL (Qnset_difference); |
11701 DEFSYMBOL (Qnunion); | 11754 DEFSYMBOL (Qnunion); |
11702 | 11755 |
11703 DEFKEYWORD (Q_from_end); | 11756 DEFKEYWORD (Q_from_end); |