comparison src/fns.c @ 5495:1f0b15040456

Merge.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 01 May 2011 18:44:03 +0100
parents 248176c74e6b
children d3e0482c7899
comparison
equal deleted inserted replaced
5494:861f2601a38b 5495:1f0b15040456
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. 2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
3 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2010 Ben Wing. 3 Copyright (C) 1995, 1996, 2000, 2001, 2002, 2003, 2010 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any 9 Free Software Foundation, either version 3 of the License, or (at your
10 later version. 10 option) any later version.
11 11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details. 15 for more details.
16 16
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to 18 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21 19
22 /* Synched up with: Mule 2.0, FSF 19.30. */ 20 /* Synched up with: Mule 2.0, FSF 19.30. */
23 21
24 /* This file has been Mule-ized. */ 22 /* This file has been Mule-ized. */
25 23
52 #include "opaque.h" 50 #include "opaque.h"
53 51
54 /* NOTE: This symbol is also used in lread.c */ 52 /* NOTE: This symbol is also used in lread.c */
55 #define FEATUREP_SYNTAX 53 #define FEATUREP_SYNTAX
56 54
57 Lisp_Object Qstring_lessp; 55 Lisp_Object Qstring_lessp, Qmerge, Qfill, Qreplace, QassocX, QrassocX;
58 Lisp_Object Qidentity; 56 Lisp_Object Qposition, Qfind, QdeleteX, QremoveX, Qidentity, Qadjoin;
59 Lisp_Object Qvector, Qarray, Qbit_vector; 57 Lisp_Object Qvector, Qarray, Qbit_vector, QsortX, Q_from_end, Q_initial_value;
58 Lisp_Object Qmapconcat, QmapcarX, Qmapvector, Qmapcan, Qmapc, Qmap, Qmap_into;
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;
61 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch;
62
63 Lisp_Object Qintersection, Qset_difference, Qnset_difference;
64 Lisp_Object Qnunion, Qnintersection, Qsubsetp, Qcar_less_than_car;
60 65
61 Lisp_Object Qbase64_conversion_error; 66 Lisp_Object Qbase64_conversion_error;
62 67
63 Lisp_Object Vpath_separator; 68 Lisp_Object Vpath_separator;
64 69
65 static int internal_old_equal (Lisp_Object, Lisp_Object, int); 70 extern Fixnum max_lisp_eval_depth;
71 extern int lisp_eval_depth;
72
66 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth); 73 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth);
74
75 static DOESNT_RETURN
76 mapping_interaction_error (Lisp_Object func, Lisp_Object object)
77 {
78 invalid_state_2 ("object modified while traversing it", func, object);
79 }
80
81 static void
82 check_sequence_range (Lisp_Object sequence, Lisp_Object start,
83 Lisp_Object end, Lisp_Object length)
84 {
85 Lisp_Object args[] = { Qzero, start, NILP (end) ? length : end, length };
86
87 if (NILP (Fleq (countof (args), args)))
88 {
89 args_out_of_range_3 (sequence, start, end);
90 }
91 }
67 92
68 static Lisp_Object 93 static Lisp_Object
69 mark_bit_vector (Lisp_Object UNUSED (obj)) 94 mark_bit_vector (Lisp_Object UNUSED (obj))
70 { 95 {
71 return Qnil; 96 return Qnil;
106 !memcmp (v1->bits, v2->bits, 131 !memcmp (v1->bits, v2->bits,
107 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) * 132 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) *
108 sizeof (long))); 133 sizeof (long)));
109 } 134 }
110 135
136 /* This needs to be algorithmically identical to internal_array_hash in
137 elhash.c when equalp is one, so arrays and bit vectors with the same
138 contents hash the same. It would be possible to enforce this by giving
139 internal_ARRAYLIKE_hash its own file and including it twice, but right
140 now that doesn't seem worth it. */
111 static Hashcode 141 static Hashcode
112 bit_vector_hash (Lisp_Object obj, int UNUSED (depth)) 142 internal_bit_vector_equalp_hash (Lisp_Bit_Vector *v)
143 {
144 int ii, size = bit_vector_length (v);
145 Hashcode hash = 0;
146
147 if (size <= 5)
148 {
149 for (ii = 0; ii < size; ii++)
150 {
151 hash = HASH2
152 (hash,
153 FLOAT_HASHCODE_FROM_DOUBLE ((double) (bit_vector_bit (v, ii))));
154 }
155 return hash;
156 }
157
158 /* just pick five elements scattered throughout the array.
159 A slightly better approach would be to offset by some
160 noise factor from the points chosen below. */
161 for (ii = 0; ii < 5; ii++)
162 hash = HASH2 (hash,
163 FLOAT_HASHCODE_FROM_DOUBLE
164 ((double) (bit_vector_bit (v, ii * size / 5))));
165
166 return hash;
167 }
168
169 static Hashcode
170 bit_vector_hash (Lisp_Object obj, int UNUSED (depth), Boolint equalp)
113 { 171 {
114 Lisp_Bit_Vector *v = XBIT_VECTOR (obj); 172 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
173 if (equalp)
174 {
175 return HASH2 (bit_vector_length (v),
176 internal_bit_vector_equalp_hash (v));
177 }
178
115 return HASH2 (bit_vector_length (v), 179 return HASH2 (bit_vector_length (v),
116 memory_hash (v->bits, 180 memory_hash (v->bits,
117 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) * 181 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) *
118 sizeof (long))); 182 sizeof (long)));
119 } 183 }
120 184
121 static Bytecount 185 static Bytecount
122 size_bit_vector (const void *lheader) 186 size_bit_vector (Lisp_Object obj)
123 { 187 {
124 Lisp_Bit_Vector *v = (Lisp_Bit_Vector *) lheader; 188 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
125 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, unsigned long, bits, 189 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, unsigned long, bits,
126 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v))); 190 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)));
127 } 191 }
128 192
129 static const struct memory_description bit_vector_description[] = { 193 static const struct memory_description bit_vector_description[] = {
130 { XD_END } 194 { XD_END }
131 }; 195 };
132 196
133 197
134 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("bit-vector", bit_vector, 198 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("bit-vector", bit_vector,
135 1, /*dumpable-flag*/ 199 mark_bit_vector,
136 mark_bit_vector, 200 print_bit_vector, 0,
137 print_bit_vector, 0, 201 bit_vector_equal,
138 bit_vector_equal, 202 bit_vector_hash,
139 bit_vector_hash, 203 bit_vector_description,
140 bit_vector_description, 204 size_bit_vector,
141 size_bit_vector, 205 Lisp_Bit_Vector);
142 Lisp_Bit_Vector); 206
143 207 /* Various test functions for #'member*, #'assoc* and the other functions
208 that take both TEST and KEY arguments. */
209
210 static Boolint
211 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
212 Lisp_Object item, Lisp_Object elt)
213 {
214 return EQ (item, elt);
215 }
216
217 static Boolint
218 check_eq_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item,
219 Lisp_Object elt)
220 {
221 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
222 return EQ (item, elt);
223 }
224
225 /* The next two are not used by #'member* and #'assoc*, since we can decide
226 on #'eq vs. #'equal when we have the type of ITEM. */
227 static Boolint
228 check_eql_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
229 Lisp_Object elt1, Lisp_Object elt2)
230 {
231 return EQ (elt1, elt2)
232 || (NON_FIXNUM_NUMBER_P (elt1) && internal_equal (elt1, elt2, 0));
233 }
234
235 static Boolint
236 check_eql_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item,
237 Lisp_Object elt)
238 {
239 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
240 return EQ (item, elt)
241 || (NON_FIXNUM_NUMBER_P (item) && internal_equal (item, elt, 0));
242 }
243
244 static Boolint
245 check_equal_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
246 Lisp_Object item, Lisp_Object elt)
247 {
248 return internal_equal (item, elt, 0);
249 }
250
251 static Boolint
252 check_equal_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item,
253 Lisp_Object elt)
254 {
255 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
256 return internal_equal (item, elt, 0);
257 }
258
259 static Boolint
260 check_equalp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
261 Lisp_Object item, Lisp_Object elt)
262 {
263 return internal_equalp (item, elt, 0);
264 }
265
266 static Boolint
267 check_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key,
268 Lisp_Object item, Lisp_Object elt)
269 {
270 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
271 return internal_equalp (item, elt, 0);
272 }
273
274 static Boolint
275 check_string_match_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
276 Lisp_Object item, Lisp_Object elt)
277 {
278 return !NILP (Fstring_match (item, elt, Qnil, Qnil));
279 }
280
281 static Boolint
282 check_string_match_key (Lisp_Object UNUSED (test), Lisp_Object key,
283 Lisp_Object item, Lisp_Object elt)
284 {
285 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
286 return !NILP (Fstring_match (item, elt, Qnil, Qnil));
287 }
288
289 static Boolint
290 check_other_nokey (Lisp_Object test, Lisp_Object UNUSED (key),
291 Lisp_Object item, Lisp_Object elt)
292 {
293 Lisp_Object args[] = { test, item, elt };
294 struct gcpro gcpro1;
295
296 GCPRO1 (args[0]);
297 gcpro1.nvars = countof (args);
298 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
299 UNGCPRO;
300
301 return !NILP (item);
302 }
303
304 static Boolint
305 check_other_key (Lisp_Object test, Lisp_Object key,
306 Lisp_Object item, Lisp_Object elt)
307 {
308 Lisp_Object args[] = { item, key, elt };
309 struct gcpro gcpro1;
310
311 GCPRO1 (args[0]);
312 gcpro1.nvars = countof (args);
313 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args) - 1, args + 1));
314 args[1] = item;
315 args[0] = test;
316 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
317 UNGCPRO;
318
319 return !NILP (item);
320 }
321
322 static Boolint
323 check_if_nokey (Lisp_Object test, Lisp_Object UNUSED (key),
324 Lisp_Object UNUSED (item), Lisp_Object elt)
325 {
326 elt = IGNORE_MULTIPLE_VALUES (call1 (test, elt));
327 return !NILP (elt);
328 }
329
330 static Boolint
331 check_if_key (Lisp_Object test, Lisp_Object key,
332 Lisp_Object UNUSED (item), Lisp_Object elt)
333 {
334 Lisp_Object args[] = { key, elt };
335 struct gcpro gcpro1;
336
337 GCPRO1 (args[0]);
338 gcpro1.nvars = countof (args);
339 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
340 args[0] = test;
341 elt = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
342 UNGCPRO;
343
344 return !NILP (elt);
345 }
346
347 static Boolint
348 check_match_eq_key (Lisp_Object UNUSED (test), Lisp_Object key,
349 Lisp_Object elt1, Lisp_Object elt2)
350 {
351 Lisp_Object args[] = { key, elt1, elt2 };
352 struct gcpro gcpro1;
353
354 GCPRO1 (args[0]);
355 gcpro1.nvars = countof (args);
356 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
357 args[1] = key;
358 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
359 UNGCPRO;
360
361 return EQ (args[0], args[1]);
362 }
363
364 static Boolint
365 check_match_eql_key (Lisp_Object UNUSED (test), Lisp_Object key,
366 Lisp_Object elt1, Lisp_Object elt2)
367 {
368 Lisp_Object args[] = { key, elt1, elt2 };
369 struct gcpro gcpro1;
370
371 GCPRO1 (args[0]);
372 gcpro1.nvars = countof (args);
373 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
374 args[1] = key;
375 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
376 UNGCPRO;
377
378 return EQ (args[0], args[1]) ||
379 (NON_FIXNUM_NUMBER_P (args[0]) && internal_equal (args[0], args[1], 0));
380 }
381
382 static Boolint
383 check_match_equal_key (Lisp_Object UNUSED (test), Lisp_Object key,
384 Lisp_Object elt1, Lisp_Object elt2)
385 {
386 Lisp_Object args[] = { key, elt1, elt2 };
387 struct gcpro gcpro1;
388
389 GCPRO1 (args[0]);
390 gcpro1.nvars = countof (args);
391 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
392 args[1] = key;
393 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
394 UNGCPRO;
395
396 return internal_equal (args[0], args[1], 0);
397 }
398
399 static Boolint
400 check_match_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key,
401 Lisp_Object elt1, Lisp_Object elt2)
402 {
403 Lisp_Object args[] = { key, elt1, elt2 };
404 struct gcpro gcpro1;
405
406 GCPRO1 (args[0]);
407 gcpro1.nvars = countof (args);
408 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
409 args[1] = key;
410 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
411 UNGCPRO;
412
413 return internal_equalp (args[0], args[1], 0);
414 }
415
416 static Boolint
417 check_match_other_key (Lisp_Object test, Lisp_Object key,
418 Lisp_Object elt1, Lisp_Object elt2)
419 {
420 Lisp_Object args[] = { key, elt1, elt2 };
421 struct gcpro gcpro1;
422
423 GCPRO1 (args[0]);
424 gcpro1.nvars = countof (args);
425 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
426 args[1] = key;
427 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
428 args[1] = args[0];
429 args[0] = test;
430
431 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
432 UNGCPRO;
433
434 return !NILP (elt1);
435 }
436
437 static Boolint
438 check_lss_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
439 Lisp_Object elt1, Lisp_Object elt2)
440 {
441 return bytecode_arithcompare (elt1, elt2) < 0;
442 }
443
444 static Boolint
445 check_lss_key (Lisp_Object UNUSED (test), Lisp_Object key,
446 Lisp_Object elt1, Lisp_Object elt2)
447 {
448 Lisp_Object args[] = { key, elt1, elt2 };
449 struct gcpro gcpro1;
450
451 GCPRO1 (args[0]);
452 gcpro1.nvars = countof (args);
453 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
454 args[1] = key;
455 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
456 UNGCPRO;
457
458 return bytecode_arithcompare (args[0], args[1]) < 0;
459 }
460
461 Boolint
462 check_lss_key_car (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
463 Lisp_Object elt1, Lisp_Object elt2)
464 {
465 struct gcpro gcpro1, gcpro2;
466
467 GCPRO2 (elt1, elt2);
468 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
469 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
470 UNGCPRO;
471
472 return bytecode_arithcompare (elt1, elt2) < 0;
473 }
474
475 Boolint
476 check_string_lessp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
477 Lisp_Object elt1, Lisp_Object elt2)
478 {
479 return !NILP (Fstring_lessp (elt1, elt2));
480 }
481
482 static Boolint
483 check_string_lessp_key (Lisp_Object UNUSED (test), Lisp_Object key,
484 Lisp_Object elt1, Lisp_Object elt2)
485 {
486 Lisp_Object args[] = { key, elt1, elt2 };
487 struct gcpro gcpro1;
488
489 GCPRO1 (args[0]);
490 gcpro1.nvars = countof (args);
491 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
492 args[1] = key;
493 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
494 UNGCPRO;
495
496 return !NILP (Fstring_lessp (args[0], args[1]));
497 }
498
499 static Boolint
500 check_string_lessp_key_car (Lisp_Object UNUSED (test),
501 Lisp_Object UNUSED (key),
502 Lisp_Object elt1, Lisp_Object elt2)
503 {
504 struct gcpro gcpro1, gcpro2;
505
506 GCPRO2 (elt1, elt2);
507 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
508 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
509 UNGCPRO;
510
511 return !NILP (Fstring_lessp (elt1, elt2));
512 }
513
514 static check_test_func_t
515 get_check_match_function_1 (Lisp_Object item,
516 Lisp_Object *test_inout, Lisp_Object test_not,
517 Lisp_Object if_, Lisp_Object if_not,
518 Lisp_Object key, Boolint *test_not_unboundp_out,
519 check_test_func_t *test_func_out)
520 {
521 Lisp_Object test = *test_inout;
522 check_test_func_t result = NULL, test_func = NULL;
523 Boolint force_if = 0;
524
525 if (!NILP (if_))
526 {
527 if (!(NILP (test) && NILP (test_not) && NILP (if_not)))
528 {
529 invalid_argument ("only one keyword among :test :test-not "
530 ":if :if-not allowed", if_);
531 }
532
533 test = *test_inout = if_;
534 force_if = 1;
535 }
536 else if (!NILP (if_not))
537 {
538 if (!(NILP (test) && NILP (test_not)))
539 {
540 invalid_argument ("only one keyword among :test :test-not "
541 ":if :if-not allowed", if_not);
542 }
543
544 test_not = if_not;
545 force_if = 1;
546 }
547
548 if (NILP (test))
549 {
550 if (!NILP (test_not))
551 {
552 test = *test_inout = test_not;
553 if (NULL != test_not_unboundp_out)
554 {
555 *test_not_unboundp_out = 0;
556 }
557 }
558 else
559 {
560 test = Qeql;
561 if (NULL != test_not_unboundp_out)
562 {
563 *test_not_unboundp_out = 1;
564 }
565 }
566 }
567 else if (!NILP (test_not))
568 {
569 invalid_argument_2 ("conflicting :test and :test-not keyword arguments",
570 test, test_not);
571 }
572
573 test = indirect_function (test, 1);
574
575 if (NILP (key) ||
576 EQ (indirect_function (key, 1), XSYMBOL_FUNCTION (Qidentity)))
577 {
578 key = Qidentity;
579 }
580
581 if (force_if)
582 {
583 result = EQ (key, Qidentity) ? check_if_nokey : check_if_key;
584
585 if (NULL != test_func_out)
586 {
587 *test_func_out = result;
588 }
589
590 return result;
591 }
592
593 if (!UNBOUNDP (item) && EQ (test, XSYMBOL_FUNCTION (Qeql)))
594 {
595 test = XSYMBOL_FUNCTION (NON_FIXNUM_NUMBER_P (item) ? Qequal : Qeq);
596 }
597
598 #define FROB(known_test, eq_condition) \
599 if (EQ (test, XSYMBOL_FUNCTION (Q##known_test))) do \
600 { \
601 if (eq_condition) \
602 { \
603 test = XSYMBOL_FUNCTION (Qeq); \
604 goto force_eq_check; \
605 } \
606 \
607 if (!EQ (Qidentity, key)) \
608 { \
609 test_func = check_##known_test##_key; \
610 result = check_match_##known_test##_key; \
611 } \
612 else \
613 { \
614 result = test_func = check_##known_test##_nokey; \
615 } \
616 } while (0)
617
618 FROB (eql, 0);
619 else if (SUBRP (test))
620 {
621 force_eq_check:
622 FROB (eq, 0);
623 else FROB (equal, (SYMBOLP (item) || INTP (item) || CHARP (item)));
624 else FROB (equalp, (SYMBOLP (item)));
625 else if (EQ (test, XSYMBOL_FUNCTION (Qstring_match)))
626 {
627 if (EQ (Qidentity, key))
628 {
629 test_func = result = check_string_match_nokey;
630 }
631 else
632 {
633 test_func = check_string_match_key;
634 result = check_other_key;
635 }
636 }
637 }
638
639 if (NULL == result)
640 {
641 if (EQ (Qidentity, key))
642 {
643 test_func = result = check_other_nokey;
644 }
645 else
646 {
647 test_func = check_other_key;
648 result = check_match_other_key;
649 }
650 }
651
652 if (NULL != test_func_out)
653 {
654 *test_func_out = test_func;
655 }
656
657 return result;
658 }
659 #undef FROB
660
661 /* Given TEST, TEST_NOT, IF, IF_NOT, KEY, and ITEM, return a C function
662 pointer appropriate for use in deciding whether a given element of a
663 sequence satisfies TEST.
664
665 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero
666 if it was bound, and set *test_inout to the value it was bound to. If
667 TEST was not bound, leave *test_inout alone; the value is not used by
668 check_eq_*key() or check_equal_*key(), which are the defaults, depending
669 on the type of ITEM.
670
671 The returned function takes arguments (TEST, KEY, ITEM, ELT), where ITEM
672 is the item being searched for and ELT is the element of the sequence
673 being examined.
674
675 Error if both TEST and TEST_NOT were specified, which Common Lisp says is
676 undefined behaviour. */
677
678 static check_test_func_t
679 get_check_test_function (Lisp_Object item,
680 Lisp_Object *test_inout, Lisp_Object test_not,
681 Lisp_Object if_, Lisp_Object if_not,
682 Lisp_Object key, Boolint *test_not_unboundp_out)
683 {
684 check_test_func_t result = NULL;
685 get_check_match_function_1 (item, test_inout, test_not, if_, if_not,
686 key, test_not_unboundp_out, &result);
687 return result;
688 }
689
690 /* Given TEST, TEST_NOT, IF, IF_NOT and KEY, return a C function pointer
691 appropriate for use in deciding whether two given elements of a sequence
692 satisfy TEST.
693
694 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero
695 if it was bound, and set *test_inout to the value it was bound to. If
696 TEST was not bound, leave *test_inout alone; the value is not used by
697 check_eql_*key().
698
699 The returned function takes arguments (TEST, KEY, ELT1, ELT2), where ELT1
700 and ELT2 are elements of the sequence being examined.
701
702 The value that would be given by get_check_test_function() is returned in
703 *TEST_FUNC_OUT, which allows calling functions to do their own key checks
704 if they're processing one element at a time.
705
706 Error if both TEST and TEST_NOT were specified, which Common Lisp says is
707 undefined behaviour. */
708
709 static check_test_func_t
710 get_check_match_function (Lisp_Object *test_inout, Lisp_Object test_not,
711 Lisp_Object if_, Lisp_Object if_not,
712 Lisp_Object key, Boolint *test_not_unboundp_out,
713 check_test_func_t *test_func_out)
714 {
715 return get_check_match_function_1 (Qunbound, test_inout, test_not,
716 if_, if_not, key,
717 test_not_unboundp_out, test_func_out);
718 }
719
720 /* Given PREDICATE and KEY, return a C function pointer appropriate for use
721 in deciding whether one given elements of a sequence is less than
722 another. */
723
724 static check_test_func_t
725 get_merge_predicate (Lisp_Object predicate, Lisp_Object key)
726 {
727 predicate = indirect_function (predicate, 1);
728
729 if (NILP (key))
730 {
731 key = Qidentity;
732 }
733 else
734 {
735 key = indirect_function (key, 1);
736 if (EQ (key, XSYMBOL_FUNCTION (Qidentity)))
737 {
738 key = Qidentity;
739 }
740 }
741
742 if (EQ (key, Qidentity) && EQ (predicate,
743 XSYMBOL_FUNCTION (Qcar_less_than_car)))
744 {
745 key = XSYMBOL_FUNCTION (Qcar);
746 predicate = XSYMBOL_FUNCTION (Qlss);
747 }
748
749 if (EQ (predicate, XSYMBOL_FUNCTION (Qlss)))
750 {
751 if (EQ (key, Qidentity))
752 {
753 return check_lss_nokey;
754 }
755
756 if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
757 {
758 return check_lss_key_car;
759 }
760
761 return check_lss_key;
762 }
763
764 if (EQ (predicate, XSYMBOL_FUNCTION (Qstring_lessp)))
765 {
766 if (EQ (key, Qidentity))
767 {
768 return check_string_lessp_nokey;
769 }
770
771 if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
772 {
773 return check_string_lessp_key_car;
774 }
775
776 return check_string_lessp_key;
777 }
778
779 if (EQ (key, Qidentity))
780 {
781 return check_other_nokey;
782 }
783
784 return check_match_other_key;
785 }
144 786
145 DEFUN ("identity", Fidentity, 1, 1, 0, /* 787 DEFUN ("identity", Fidentity, 1, 1, 0, /*
146 Return the argument unchanged. 788 Return the argument unchanged.
147 */ 789 */
148 (arg)) 790 (arg))
151 } 793 }
152 794
153 DEFUN ("random", Frandom, 0, 1, 0, /* 795 DEFUN ("random", Frandom, 0, 1, 0, /*
154 Return a pseudo-random number. 796 Return a pseudo-random number.
155 All fixnums are equally likely. On most systems, this is 31 bits' worth. 797 All fixnums are equally likely. On most systems, this is 31 bits' worth.
156 With positive integer argument N, return random number in interval [0,N). 798 With positive integer argument LIMIT, return random number in interval [0,
157 N can be a bignum, in which case the range of possible values is extended. 799 LIMIT). LIMIT can be a bignum, in which case the range of possible values
158 With argument t, set the random number seed from the current time and pid. 800 is extended. With argument t, set the random number seed from the current
801 time and pid.
159 */ 802 */
160 (limit)) 803 (limit))
161 { 804 {
162 EMACS_INT val; 805 EMACS_INT val;
163 unsigned long denominator; 806 unsigned long denominator;
164 807
165 if (EQ (limit, Qt)) 808 if (EQ (limit, Qt))
166 seed_random (qxe_getpid () + time (NULL)); 809 seed_random (qxe_getpid () + time (NULL));
167 if (NATNUMP (limit) && !ZEROP (limit)) 810 if (NATNUMP (limit) && !ZEROP (limit))
168 { 811 {
812 #ifdef HAVE_BIGNUM
813 if (BIGNUMP (limit))
814 {
815 bignum_random (scratch_bignum, XBIGNUM_DATA (limit));
816 return Fcanonicalize_number (make_bignum_bg (scratch_bignum));
817 }
818 #endif
169 /* Try to take our random number from the higher bits of VAL, 819 /* Try to take our random number from the higher bits of VAL,
170 not the lower, since (says Gentzel) the low bits of `random' 820 not the lower, since (says Gentzel) the low bits of `random'
171 are less random than the higher ones. We do this by using the 821 are less random than the higher ones. We do this by using the
172 quotient rather than the remainder. At the high end of the RNG 822 quotient rather than the remainder. At the high end of the RNG
173 it's possible to get a quotient larger than limit; discarding 823 it's possible to get a quotient larger than limit; discarding
176 denominator = ((unsigned long)1 << INT_VALBITS) / XINT (limit); 826 denominator = ((unsigned long)1 << INT_VALBITS) / XINT (limit);
177 do 827 do
178 val = get_random () / denominator; 828 val = get_random () / denominator;
179 while (val >= XINT (limit)); 829 while (val >= XINT (limit));
180 } 830 }
181 #ifdef HAVE_BIGNUM
182 else if (BIGNUMP (limit))
183 {
184 bignum_random (scratch_bignum, XBIGNUM_DATA (limit));
185 return Fcanonicalize_number (make_bignum_bg (scratch_bignum));
186 }
187 #endif
188 else 831 else
189 val = get_random (); 832 val = get_random ();
190 833
191 return make_int (val); 834 return make_int (val);
192 } 835 }
276 } 919 }
277 920
278 return make_int (len); 921 return make_int (len);
279 } 922 }
280 923
924 /* This is almost the above, but is defined by Common Lisp. We need it in C
925 for shortest_length_among_sequences(), below, for the various sequence
926 functions that can usefully operate on circular lists. */
927
928 DEFUN ("list-length", Flist_length, 1, 1, 0, /*
929 Return the length of LIST. Return nil if LIST is circular.
930 Error if LIST is dotted.
931 */
932 (list))
933 {
934 Lisp_Object hare, tortoise;
935 Elemcount len;
936
937 for (hare = tortoise = list, len = 0;
938 CONSP (hare) && (! EQ (hare, tortoise) || len == 0);
939 hare = XCDR (hare), len++)
940 {
941 if (len & 1)
942 tortoise = XCDR (tortoise);
943 }
944
945 if (!LISTP (hare))
946 {
947 signal_malformed_list_error (list);
948 }
949
950 return EQ (hare, tortoise) && len != 0 ? Qnil : make_int (len);
951 }
952
953 static Lisp_Object string_count_from_end (Lisp_Object, Lisp_Object ,
954 check_test_func_t, Boolint,
955 Lisp_Object, Lisp_Object,
956 Lisp_Object, Lisp_Object);
957
958 static Lisp_Object list_count_from_end (Lisp_Object, Lisp_Object,
959 check_test_func_t, Boolint,
960 Lisp_Object, Lisp_Object,
961 Lisp_Object, Lisp_Object);
962
963 /* Count the number of occurrences of ITEM in SEQUENCE; if SEQUENCE is a
964 list, store the cons cell of which the car is the last ITEM in SEQUENCE,
965 at the address given by tail_out. */
966
967 static Lisp_Object
968 count_with_tail (Lisp_Object *tail_out, int nargs, Lisp_Object *args,
969 Lisp_Object caller)
970 {
971 Lisp_Object item = args[0], sequence = args[1];
972 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
973 Elemcount len, ii = 0, counting = EMACS_INT_MAX;
974 Boolint test_not_unboundp = 1;
975 check_test_func_t check_test = NULL;
976
977 PARSE_KEYWORDS_8 (caller, nargs, args, 9,
978 (test, key, start, end, from_end, test_not, count,
979 if_, if_not), (start = Qzero), 2, 0);
980
981 CHECK_SEQUENCE (sequence);
982 CHECK_NATNUM (start);
983 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
984
985 if (!NILP (end))
986 {
987 CHECK_NATNUM (end);
988 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
989 }
990
991 if (!NILP (count))
992 {
993 CHECK_INTEGER (count);
994 counting = BIGNUMP (count) ? EMACS_INT_MAX + 1 : XINT (count);
995
996 /* Our callers should have filtered out non-positive COUNT. */
997 assert (counting >= 0);
998 /* And we're not prepared to handle COUNT from any other caller at the
999 moment. */
1000 assert (EQ (caller, QremoveX)|| EQ (caller, QdeleteX));
1001 }
1002
1003 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
1004 key, &test_not_unboundp);
1005
1006 *tail_out = Qnil;
1007
1008 if (CONSP (sequence))
1009 {
1010 if (EQ (caller, Qcount) && !NILP (from_end)
1011 && (!EQ (key, Qnil) ||
1012 check_test == check_other_nokey || check_test == check_if_nokey))
1013 {
1014 /* #'count, #'count-if, and #'count-if-not are documented to have
1015 a given traversal order if :from-end t is passed in, even
1016 though forward traversal of the sequence has the same result
1017 and is algorithmically less expensive for lists and strings.
1018 This order isn't necessary for other callers, though. */
1019 return list_count_from_end (item, sequence, check_test,
1020 test_not_unboundp, test, key,
1021 start, end);
1022 }
1023
1024 /* If COUNT is non-nil and FROM-END is t, we can give the tail
1025 containing the last match, since that's what #'remove* is
1026 interested in (a zero or negative COUNT won't ever reach
1027 count_with_tail(), our callers will return immediately on seeing
1028 it). */
1029 if (!NILP (count) && !NILP (from_end))
1030 {
1031 counting = EMACS_INT_MAX;
1032 }
1033
1034 {
1035 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
1036 {
1037 if (!(ii < ending))
1038 {
1039 break;
1040 }
1041
1042 if (starting <= ii &&
1043 check_test (test, key, item, elt) == test_not_unboundp)
1044 {
1045 encountered++;
1046 *tail_out = tail;
1047
1048 if (encountered == counting)
1049 {
1050 break;
1051 }
1052 }
1053
1054 ii++;
1055 }
1056 END_GC_EXTERNAL_LIST_LOOP (elt);
1057 }
1058
1059 if ((ii < starting || (ii < ending && !NILP (end))) &&
1060 encountered != counting)
1061 {
1062 check_sequence_range (args[1], start, end, Flength (args[1]));
1063 }
1064 }
1065 else if (STRINGP (sequence))
1066 {
1067 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp;
1068 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
1069 Lisp_Object character = Qnil;
1070
1071 if (EQ (caller, Qcount) && !NILP (from_end)
1072 && (!EQ (key, Qnil) ||
1073 check_test == check_other_nokey || check_test == check_if_nokey))
1074 {
1075 /* See comment above in the list code. */
1076 return string_count_from_end (item, sequence,
1077 check_test, test_not_unboundp,
1078 test, key, start, end);
1079 }
1080
1081 while (cursor_offset < byte_len && ii < ending && encountered < counting)
1082 {
1083 if (ii >= starting)
1084 {
1085 character = make_char (itext_ichar (cursor));
1086
1087 if (check_test (test, key, item, character)
1088 == test_not_unboundp)
1089 {
1090 encountered++;
1091 }
1092
1093 startp = XSTRING_DATA (sequence);
1094 cursor = startp + cursor_offset;
1095 if (byte_len != XSTRING_LENGTH (sequence)
1096 || !valid_ibyteptr_p (cursor))
1097 {
1098 mapping_interaction_error (caller, sequence);
1099 }
1100 }
1101
1102 INC_IBYTEPTR (cursor);
1103 cursor_offset = cursor - startp;
1104 ii++;
1105 }
1106
1107 if (ii < starting || (ii < ending && !NILP (end)))
1108 {
1109 check_sequence_range (sequence, start, end, Flength (sequence));
1110 }
1111 }
1112 else
1113 {
1114 Lisp_Object object = Qnil;
1115
1116 len = XINT (Flength (sequence));
1117 check_sequence_range (sequence, start, end, make_int (len));
1118
1119 ending = min (ending, len);
1120 if (0 == len)
1121 {
1122 /* Catches the case where we have nil. */
1123 return make_integer (encountered);
1124 }
1125
1126 if (NILP (from_end))
1127 {
1128 for (ii = starting; ii < ending && encountered < counting; ii++)
1129 {
1130 object = Faref (sequence, make_int (ii));
1131 if (check_test (test, key, item, object) == test_not_unboundp)
1132 {
1133 encountered++;
1134 }
1135 }
1136 }
1137 else
1138 {
1139 for (ii = ending - 1; ii >= starting && encountered < counting; ii--)
1140 {
1141 object = Faref (sequence, make_int (ii));
1142 if (check_test (test, key, item, object) == test_not_unboundp)
1143 {
1144 encountered++;
1145 }
1146 }
1147 }
1148 }
1149
1150 return make_integer (encountered);
1151 }
1152
1153 static Lisp_Object
1154 list_count_from_end (Lisp_Object item, Lisp_Object sequence,
1155 check_test_func_t check_test, Boolint test_not_unboundp,
1156 Lisp_Object test, Lisp_Object key,
1157 Lisp_Object start, Lisp_Object end)
1158 {
1159 Elemcount length = XINT (Flength (sequence)), ii = 0, starting = XINT (start);
1160 Elemcount ending = NILP (end) ? length : XINT (end), encountered = 0;
1161 Lisp_Object *storage;
1162 struct gcpro gcpro1;
1163
1164 check_sequence_range (sequence, start, end, make_integer (length));
1165
1166 storage = alloca_array (Lisp_Object, ending - starting);
1167
1168 {
1169 EXTERNAL_LIST_LOOP_2 (elt, sequence)
1170 {
1171 if (starting <= ii && ii < ending)
1172 {
1173 storage[ii - starting] = elt;
1174 }
1175 ii++;
1176 }
1177 }
1178
1179 GCPRO1 (storage[0]);
1180 gcpro1.nvars = ending - starting;
1181
1182 for (ii = ending - 1; ii >= starting; ii--)
1183 {
1184 if (check_test (test, key, item, storage[ii - starting])
1185 == test_not_unboundp)
1186 {
1187 encountered++;
1188 }
1189 }
1190
1191 UNGCPRO;
1192
1193 return make_integer (encountered);
1194 }
1195
1196 static Lisp_Object
1197 string_count_from_end (Lisp_Object item, Lisp_Object sequence,
1198 check_test_func_t check_test, Boolint test_not_unboundp,
1199 Lisp_Object test, Lisp_Object key,
1200 Lisp_Object start, Lisp_Object end)
1201 {
1202 Elemcount length = string_char_length (sequence), ii = 0;
1203 Elemcount starting = XINT (start), ending = NILP (end) ? length : XINT (end);
1204 Elemcount encountered = 0;
1205 Ibyte *cursor = XSTRING_DATA (sequence);
1206 Ibyte *endp = cursor + XSTRING_LENGTH (sequence);
1207 Ichar *storage;
1208
1209 check_sequence_range (sequence, start, end, make_integer (length));
1210
1211 storage = alloca_array (Ichar, ending - starting);
1212
1213 while (cursor < endp && ii < ending)
1214 {
1215 if (starting <= ii && ii < ending)
1216 {
1217 storage [ii - starting] = itext_ichar (cursor);
1218 }
1219
1220 ii++;
1221 INC_IBYTEPTR (cursor);
1222 }
1223
1224 for (ii = ending - 1; ii >= starting; ii--)
1225 {
1226 if (check_test (test, key, item, make_char (storage [ii - starting]))
1227 == test_not_unboundp)
1228 {
1229 encountered++;
1230 }
1231 }
1232
1233 return make_integer (encountered);
1234 }
1235
1236 DEFUN ("count", Fcount, 2, MANY, 0, /*
1237 Count the number of occurrences of ITEM in SEQUENCE.
1238
1239 See `remove*' for the meaning of the keywords.
1240
1241 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
1242 */
1243 (int nargs, Lisp_Object *args))
1244 {
1245 Lisp_Object tail = Qnil;
1246
1247 /* count_with_tail() accepts more keywords than we do, check those we've
1248 been given. */
1249 PARSE_KEYWORDS (Fcount, nargs, args, 8,
1250 (test, test_not, if_, if_not, key, start, end, from_end),
1251 NULL);
1252
1253 return count_with_tail (&tail, nargs, args, Qcount);
1254 }
1255
281 /*** string functions. ***/ 1256 /*** string functions. ***/
282 1257
283 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /* 1258 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /*
284 Return t if two strings have identical contents. 1259 Return t if two strings have identical contents.
285 Case is significant. Text properties are ignored. 1260 Case is significant. Text properties are ignored.
837 } 1812 }
838 else 1813 else
839 { 1814 {
840 CHECK_CHAR_COERCE_INT (elt); 1815 CHECK_CHAR_COERCE_INT (elt);
841 string_result_ptr += set_itext_ichar (string_result_ptr, 1816 string_result_ptr += set_itext_ichar (string_result_ptr,
842 XCHAR (elt)); 1817 XCHAR (elt));
843 } 1818 }
844 } 1819 }
845 if (args_mse) 1820 if (args_mse)
846 { 1821 {
847 args_mse[argnum].entry_offset = 1822 args_mse[argnum].entry_offset =
911 } 1886 }
912 1887
913 Lisp_Object 1888 Lisp_Object
914 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth) 1889 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth)
915 { 1890 {
916 if (depth > 200) 1891 if (depth + lisp_eval_depth > max_lisp_eval_depth)
917 stack_overflow ("Stack overflow in copy-tree", arg); 1892 stack_overflow ("Stack overflow in copy-tree", arg);
918 1893
919 if (CONSP (arg)) 1894 if (CONSP (arg))
920 { 1895 {
921 Lisp_Object rest; 1896 Lisp_Object rest;
945 } 1920 }
946 } 1921 }
947 return arg; 1922 return arg;
948 } 1923 }
949 1924
950 DEFUN ("substring", Fsubstring, 2, 3, 0, /* 1925 DEFUN ("subseq", Fsubseq, 2, 3, 0, /*
951 Return the substring of STRING starting at START and ending before END. 1926 Return the subsequence of SEQUENCE starting at START and ending before END.
1927 END may be omitted; then the subsequence runs to the end of SEQUENCE.
1928
1929 If START or END is negative, it counts from the end, in contravention of
1930 Common Lisp.
1931 The returned subsequence is always of the same type as SEQUENCE.
1932 If SEQUENCE is a string, relevant parts of the string-extent-data
1933 are copied to the new string.
1934
1935 See also `substring-no-properties', which only operates on strings, and does
1936 not copy extent data.
1937 */
1938 (sequence, start, end))
1939 {
1940 Elemcount len, ss, ee = EMACS_INT_MAX, ii;
1941 Lisp_Object result = Qnil;
1942
1943 CHECK_SEQUENCE (sequence);
1944 CHECK_INT (start);
1945 ss = XINT (start);
1946
1947 if (!NILP (end))
1948 {
1949 CHECK_INT (end);
1950 ee = XINT (end);
1951 }
1952
1953 if (STRINGP (sequence))
1954 {
1955 Bytecount bstart, blen;
1956
1957 get_string_range_char (sequence, start, end, &ss, &ee,
1958 GB_HISTORICAL_STRING_BEHAVIOR);
1959 bstart = string_index_char_to_byte (sequence, ss);
1960 blen = string_offset_char_to_byte_len (sequence, bstart, ee - ss);
1961
1962 result = make_string (XSTRING_DATA (sequence) + bstart, blen);
1963 /* Copy any applicable extent information into the new string. */
1964 copy_string_extents (result, sequence, 0, bstart, blen);
1965 }
1966 else if (CONSP (sequence))
1967 {
1968 Lisp_Object result_tail, saved = sequence;
1969
1970 if (ss < 0 || ee < 0)
1971 {
1972 len = XINT (Flength (sequence));
1973 if (ss < 0)
1974 {
1975 ss = len + ss;
1976 start = make_integer (ss);
1977 }
1978
1979 if (ee < 0)
1980 {
1981 ee = len + ee;
1982 end = make_integer (ee);
1983 }
1984 else
1985 {
1986 ee = min (ee, len);
1987 }
1988 }
1989
1990 if (0 != ss)
1991 {
1992 sequence = Fnthcdr (make_int (ss), sequence);
1993 }
1994
1995 ii = ss + 1;
1996
1997 if (ss < ee && !NILP (sequence))
1998 {
1999 result = result_tail = Fcons (Fcar (sequence), Qnil);
2000 sequence = Fcdr (sequence);
2001
2002 {
2003 EXTERNAL_LIST_LOOP_2 (elt, sequence)
2004 {
2005 if (!(ii < ee))
2006 {
2007 break;
2008 }
2009
2010 XSETCDR (result_tail, Fcons (elt, Qnil));
2011 result_tail = XCDR (result_tail);
2012 ii++;
2013 }
2014 }
2015 }
2016
2017 if (NILP (result) || (ii < ee && !NILP (end)))
2018 {
2019 /* We were handed a cons, which definitely has elements. nil
2020 result means either ss >= ee or SEQUENCE was nil after the
2021 nthcdr; in both cases that means START and END were incorrectly
2022 specified for this sequence. ii < ee with a non-nil end means
2023 the user handed us a bogus end value. */
2024 check_sequence_range (saved, start, end, Flength (saved));
2025 }
2026 }
2027 else
2028 {
2029 len = XINT (Flength (sequence));
2030 if (ss < 0)
2031 {
2032 ss = len + ss;
2033 start = make_integer (ss);
2034 }
2035
2036 if (ee < 0)
2037 {
2038 ee = len + ee;
2039 end = make_integer (ee);
2040 }
2041 else
2042 {
2043 ee = min (len, ee);
2044 }
2045
2046 check_sequence_range (sequence, start, end, make_int (len));
2047
2048 if (VECTORP (sequence))
2049 {
2050 result = Fvector (ee - ss, XVECTOR_DATA (sequence) + ss);
2051 }
2052 else if (BIT_VECTORP (sequence))
2053 {
2054 result = make_bit_vector (ee - ss, Qzero);
2055
2056 for (ii = ss; ii < ee; ii++)
2057 {
2058 set_bit_vector_bit (XBIT_VECTOR (result), ii - ss,
2059 bit_vector_bit (XBIT_VECTOR (sequence), ii));
2060 }
2061 }
2062 else if (NILP (sequence))
2063 {
2064 DO_NOTHING;
2065 }
2066 else
2067 {
2068 /* Won't happen, since CHECK_SEQUENCE didn't error. */
2069 ABORT ();
2070 }
2071 }
2072
2073 return result;
2074 }
2075
2076 DEFUN ("substring-no-properties", Fsubstring_no_properties, 1, 3, 0, /*
2077 Return a substring of STRING, without copying the extents.
952 END may be nil or omitted; then the substring runs to the end of STRING. 2078 END may be nil or omitted; then the substring runs to the end of STRING.
953 If START or END is negative, it counts from the end. 2079 If START or END is negative, it counts from the end.
954 Relevant parts of the string-extent-data are copied to the new string. 2080
2081 With one argument, copy STRING without its properties.
955 */ 2082 */
956 (string, start, end)) 2083 (string, start, end))
957 { 2084 {
958 Charcount ccstart, ccend; 2085 Charcount ccstart, ccend;
959 Bytecount bstart, blen; 2086 Bytecount bstart, blen;
960 Lisp_Object val; 2087 Lisp_Object val;
961 2088
962 CHECK_STRING (string); 2089 CHECK_STRING (string);
963 CHECK_INT (start);
964 get_string_range_char (string, start, end, &ccstart, &ccend, 2090 get_string_range_char (string, start, end, &ccstart, &ccend,
965 GB_HISTORICAL_STRING_BEHAVIOR); 2091 GB_HISTORICAL_STRING_BEHAVIOR);
966 bstart = string_index_char_to_byte (string, ccstart); 2092 bstart = string_index_char_to_byte (string, ccstart);
967 blen = string_offset_char_to_byte_len (string, bstart, ccend - ccstart); 2093 blen = string_offset_char_to_byte_len (string, bstart, ccend - ccstart);
968 val = make_string (XSTRING_DATA (string) + bstart, blen); 2094 val = make_string (XSTRING_DATA (string) + bstart, blen);
969 /* Copy any applicable extent information into the new string. */ 2095
970 copy_string_extents (val, string, 0, bstart, blen);
971 return val; 2096 return val;
972 } 2097 }
973 2098
974 DEFUN ("subseq", Fsubseq, 2, 3, 0, /*
975 Return the subsequence of SEQUENCE starting at START and ending before END.
976 END may be omitted; then the subsequence runs to the end of SEQUENCE.
977 If START or END is negative, it counts from the end.
978 The returned subsequence is always of the same type as SEQUENCE.
979 If SEQUENCE is a string, relevant parts of the string-extent-data
980 are copied to the new string.
981 */
982 (sequence, start, end))
983 {
984 EMACS_INT len, s, e;
985
986 CHECK_SEQUENCE (sequence);
987
988 if (STRINGP (sequence))
989 return Fsubstring (sequence, start, end);
990
991 len = XINT (Flength (sequence));
992
993 CHECK_INT (start);
994 s = XINT (start);
995 if (s < 0)
996 s = len + s;
997
998 if (NILP (end))
999 e = len;
1000 else
1001 {
1002 CHECK_INT (end);
1003 e = XINT (end);
1004 if (e < 0)
1005 e = len + e;
1006 }
1007
1008 if (!(0 <= s && s <= e && e <= len))
1009 args_out_of_range_3 (sequence, make_int (s), make_int (e));
1010
1011 if (VECTORP (sequence))
1012 {
1013 Lisp_Object result = make_vector (e - s, Qnil);
1014 EMACS_INT i;
1015 Lisp_Object *in_elts = XVECTOR_DATA (sequence);
1016 Lisp_Object *out_elts = XVECTOR_DATA (result);
1017
1018 for (i = s; i < e; i++)
1019 out_elts[i - s] = in_elts[i];
1020 return result;
1021 }
1022 else if (LISTP (sequence))
1023 {
1024 Lisp_Object result = Qnil;
1025 EMACS_INT i;
1026
1027 sequence = Fnthcdr (make_int (s), sequence);
1028
1029 for (i = s; i < e; i++)
1030 {
1031 result = Fcons (Fcar (sequence), result);
1032 sequence = Fcdr (sequence);
1033 }
1034
1035 return Fnreverse (result);
1036 }
1037 else if (BIT_VECTORP (sequence))
1038 {
1039 Lisp_Object result = make_bit_vector (e - s, Qzero);
1040 EMACS_INT i;
1041
1042 for (i = s; i < e; i++)
1043 set_bit_vector_bit (XBIT_VECTOR (result), i - s,
1044 bit_vector_bit (XBIT_VECTOR (sequence), i));
1045 return result;
1046 }
1047 else
1048 {
1049 ABORT (); /* unreachable, since CHECK_SEQUENCE (sequence) did not
1050 error */
1051 return Qnil;
1052 }
1053 }
1054
1055 /* Split STRING into a list of substrings. The substrings are the 2099 /* Split STRING into a list of substrings. The substrings are the
1056 parts of original STRING separated by SEPCHAR. */ 2100 parts of original STRING separated by SEPCHAR.
2101
2102 If UNESCAPE is non-zero, ESCAPECHAR specifies a character that will quote
2103 SEPCHAR, and cause it not to split STRING. A double ESCAPECHAR is
2104 necessary for ESCAPECHAR to appear once in a substring. */
2105
1057 static Lisp_Object 2106 static Lisp_Object
1058 split_string_by_ichar_1 (const Ibyte *string, Bytecount size, 2107 split_string_by_ichar_1 (const Ibyte *string, Bytecount size,
1059 Ichar sepchar) 2108 Ichar sepchar, int unescape, Ichar escapechar)
1060 { 2109 {
1061 Lisp_Object result = Qnil; 2110 Lisp_Object result = Qnil;
1062 const Ibyte *end = string + size; 2111 const Ibyte *end = string + size;
1063 2112
1064 while (1) 2113 if (unescape)
1065 { 2114 {
1066 const Ibyte *p = string; 2115 Ibyte unescape_buffer[64], *unescape_buffer_ptr = unescape_buffer,
1067 while (p < end) 2116 escaped[MAX_ICHAR_LEN], *unescape_cursor;
1068 { 2117 Bytecount unescape_buffer_size = countof (unescape_buffer),
1069 if (itext_ichar (p) == sepchar) 2118 escaped_len = set_itext_ichar (escaped, escapechar);
1070 break; 2119 Boolint deleting_escapes, previous_escaped;
1071 INC_IBYTEPTR (p); 2120 Ichar pchar;
1072 } 2121
1073 result = Fcons (make_string (string, p - string), result); 2122 while (1)
1074 if (p < end) 2123 {
1075 { 2124 const Ibyte *p = string, *cursor;
1076 string = p; 2125 deleting_escapes = 0;
1077 INC_IBYTEPTR (string); /* skip sepchar */ 2126 previous_escaped = 0;
1078 } 2127
1079 else 2128 while (p < end)
1080 break; 2129 {
2130 pchar = itext_ichar (p);
2131
2132 if (pchar == sepchar)
2133 {
2134 if (!previous_escaped)
2135 {
2136 break;
2137 }
2138 }
2139 else if (pchar == escapechar
2140 /* Doubled escapes don't escape: */
2141 && !previous_escaped)
2142 {
2143 ++deleting_escapes;
2144 previous_escaped = 1;
2145 }
2146 else
2147 {
2148 previous_escaped = 0;
2149 }
2150
2151 INC_IBYTEPTR (p);
2152 }
2153
2154 if (deleting_escapes)
2155 {
2156 if (((p - string) - (escaped_len * deleting_escapes))
2157 > unescape_buffer_size)
2158 {
2159 unescape_buffer_size =
2160 ((p - string) - (escaped_len * deleting_escapes)) * 1.5;
2161 unescape_buffer_ptr = alloca_ibytes (unescape_buffer_size);
2162 }
2163
2164 cursor = string;
2165 unescape_cursor = unescape_buffer_ptr;
2166 previous_escaped = 0;
2167
2168 while (cursor < p)
2169 {
2170 pchar = itext_ichar (cursor);
2171
2172 if (pchar != escapechar || previous_escaped)
2173 {
2174 memcpy (unescape_cursor, cursor,
2175 itext_ichar_len (cursor));
2176 INC_IBYTEPTR (unescape_cursor);
2177 }
2178
2179 previous_escaped = !previous_escaped
2180 && (pchar == escapechar);
2181
2182 INC_IBYTEPTR (cursor);
2183 }
2184
2185 result = Fcons (make_string (unescape_buffer_ptr,
2186 unescape_cursor
2187 - unescape_buffer_ptr),
2188 result);
2189 }
2190 else
2191 {
2192 result = Fcons (make_string (string, p - string), result);
2193 }
2194 if (p < end)
2195 {
2196 string = p;
2197 INC_IBYTEPTR (string); /* skip sepchar */
2198 }
2199 else
2200 break;
2201 }
2202 }
2203 else
2204 {
2205 while (1)
2206 {
2207 const Ibyte *p = string;
2208 while (p < end)
2209 {
2210 if (itext_ichar (p) == sepchar)
2211 break;
2212 INC_IBYTEPTR (p);
2213 }
2214 result = Fcons (make_string (string, p - string), result);
2215 if (p < end)
2216 {
2217 string = p;
2218 INC_IBYTEPTR (string); /* skip sepchar */
2219 }
2220 else
2221 break;
2222 }
1081 } 2223 }
1082 return Fnreverse (result); 2224 return Fnreverse (result);
1083 } 2225 }
1084 2226
1085 /* The same as the above, except PATH is an external C string (it is 2227 /* The same as the above, except PATH is an external C string (it is
1100 depend on split_external_path("") returning nil instead of an empty 2242 depend on split_external_path("") returning nil instead of an empty
1101 string? */ 2243 string? */
1102 if (!newlen) 2244 if (!newlen)
1103 return Qnil; 2245 return Qnil;
1104 2246
1105 return split_string_by_ichar_1 (newpath, newlen, SEPCHAR); 2247 return split_string_by_ichar_1 (newpath, newlen, SEPCHAR, 0, 0);
1106 } 2248 }
1107 2249
1108 Lisp_Object 2250 Lisp_Object
1109 split_env_path (const CIbyte *evarname, const Ibyte *default_) 2251 split_env_path (const CIbyte *evarname, const Ibyte *default_)
1110 { 2252 {
1113 path = egetenv (evarname); 2255 path = egetenv (evarname);
1114 if (!path) 2256 if (!path)
1115 path = default_; 2257 path = default_;
1116 if (!path) 2258 if (!path)
1117 return Qnil; 2259 return Qnil;
1118 return split_string_by_ichar_1 (path, qxestrlen (path), SEPCHAR); 2260 return split_string_by_ichar_1 (path, qxestrlen (path), SEPCHAR, 0, 0);
1119 } 2261 }
1120 2262
1121 /* Ben thinks this function should not exist or be exported to Lisp. 2263 /* Ben thinks this function should not exist or be exported to Lisp.
1122 We use it to define split-path-string in subr.el (not!). */ 2264 We use it to define split-path-string in subr.el (not!). */
1123 2265
1124 DEFUN ("split-string-by-char", Fsplit_string_by_char, 2, 2, 0, /* 2266 DEFUN ("split-string-by-char", Fsplit_string_by_char, 2, 3, 0, /*
1125 Split STRING into a list of substrings originally separated by SEPCHAR. 2267 Split STRING into a list of substrings originally separated by SEPCHAR.
1126 */ 2268
1127 (string, sepchar)) 2269 With optional ESCAPE-CHAR, any instances of SEPCHAR preceded by that
1128 { 2270 character will not split the string, and a double instance of ESCAPE-CHAR
2271 will be necessary for a single ESCAPE-CHAR to appear in the output string.
2272 */
2273 (string, sepchar, escape_char))
2274 {
2275 Ichar escape_ichar = 0;
2276
1129 CHECK_STRING (string); 2277 CHECK_STRING (string);
1130 CHECK_CHAR (sepchar); 2278 CHECK_CHAR (sepchar);
2279 if (!NILP (escape_char))
2280 {
2281 CHECK_CHAR (escape_char);
2282 escape_ichar = XCHAR (escape_char);
2283 }
1131 return split_string_by_ichar_1 (XSTRING_DATA (string), 2284 return split_string_by_ichar_1 (XSTRING_DATA (string),
1132 XSTRING_LENGTH (string), 2285 XSTRING_LENGTH (string),
1133 XCHAR (sepchar)); 2286 XCHAR (sepchar),
2287 !NILP (escape_char), escape_ichar);
1134 } 2288 }
1135 2289
1136 /* #### This was supposed to be in subr.el, but is used VERY early in 2290 /* #### This was supposed to be in subr.el, but is used VERY early in
1137 the bootstrap process, so it goes here. Damn. */ 2291 the bootstrap process, so it goes here. Damn. */
1138 2292
1152 "`path-separator' should be set to a single-character string", 2306 "`path-separator' should be set to a single-character string",
1153 Vpath_separator); 2307 Vpath_separator);
1154 2308
1155 return (split_string_by_ichar_1 2309 return (split_string_by_ichar_1
1156 (XSTRING_DATA (path), XSTRING_LENGTH (path), 2310 (XSTRING_DATA (path), XSTRING_LENGTH (path),
1157 itext_ichar (XSTRING_DATA (Vpath_separator)))); 2311 itext_ichar (XSTRING_DATA (Vpath_separator)), 0, 0));
1158 } 2312 }
1159 2313
1160 2314
1161 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /* 2315 DEFUN ("nthcdr", Fnthcdr, 2, 2, 0, /*
1162 Take cdr N times on LIST, and return the result. 2316 Take cdr N times on LIST, and return the result.
1165 { 2319 {
1166 /* This function can GC */ 2320 /* This function can GC */
1167 REGISTER EMACS_INT i; 2321 REGISTER EMACS_INT i;
1168 REGISTER Lisp_Object tail = list; 2322 REGISTER Lisp_Object tail = list;
1169 CHECK_NATNUM (n); 2323 CHECK_NATNUM (n);
1170 for (i = XINT (n); i; i--) 2324 for (i = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n); i; i--)
1171 { 2325 {
1172 if (CONSP (tail)) 2326 if (CONSP (tail))
1173 tail = XCDR (tail); 2327 tail = XCDR (tail);
1174 else if (NILP (tail)) 2328 else if (NILP (tail))
1175 return Qnil; 2329 return Qnil;
1285 if (NILP (n)) 2439 if (NILP (n))
1286 int_n = 1; 2440 int_n = 1;
1287 else 2441 else
1288 { 2442 {
1289 CHECK_NATNUM (n); 2443 CHECK_NATNUM (n);
1290 int_n = XINT (n); 2444 int_n = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n);
1291 } 2445 }
1292 2446
1293 for (retval = tortoise = hare = list, count = 0; 2447 for (retval = tortoise = hare = list, count = 0;
1294 CONSP (hare); 2448 CONSP (hare);
1295 hare = XCDR (hare), 2449 hare = XCDR (hare),
1307 return retval; 2461 return retval;
1308 } 2462 }
1309 2463
1310 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /* 2464 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /*
1311 Modify LIST to remove the last N (default 1) elements. 2465 Modify LIST to remove the last N (default 1) elements.
2466
1312 If LIST has N or fewer elements, nil is returned and LIST is unmodified. 2467 If LIST has N or fewer elements, nil is returned and LIST is unmodified.
2468 Otherwise, LIST may be dotted, but not circular.
1313 */ 2469 */
1314 (list, n)) 2470 (list, n))
1315 { 2471 {
1316 EMACS_INT int_n; 2472 Elemcount int_n = 1;
1317 2473
1318 CHECK_LIST (list); 2474 CHECK_LIST (list);
1319 2475
1320 if (NILP (n)) 2476 if (!NILP (n))
1321 int_n = 1;
1322 else
1323 { 2477 {
1324 CHECK_NATNUM (n); 2478 CHECK_NATNUM (n);
1325 int_n = XINT (n); 2479 int_n = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n);
1326 } 2480 }
1327 2481
1328 { 2482 if (CONSP (list))
1329 Lisp_Object last_cons = list; 2483 {
1330 2484 Lisp_Object last_cons = list;
1331 EXTERNAL_LIST_LOOP_1 (list) 2485
1332 { 2486 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
1333 if (int_n-- < 0) 2487 {
1334 last_cons = XCDR (last_cons); 2488 if (int_n-- < 0)
1335 } 2489 {
1336 2490 last_cons = XCDR (last_cons);
1337 if (int_n >= 0) 2491 }
1338 return Qnil; 2492
1339 2493 if (!CONSP (XCDR (tail)))
1340 XCDR (last_cons) = Qnil; 2494 {
1341 return list; 2495 break;
1342 } 2496 }
2497 }
2498
2499 if (int_n >= 0)
2500 {
2501 return Qnil;
2502 }
2503
2504 XCDR (last_cons) = Qnil;
2505 }
2506
2507 return list;
1343 } 2508 }
1344 2509
1345 DEFUN ("butlast", Fbutlast, 1, 2, 0, /* 2510 DEFUN ("butlast", Fbutlast, 1, 2, 0, /*
1346 Return a copy of LIST with the last N (default 1) elements removed. 2511 Return a copy of LIST with the last N (default 1) elements removed.
2512
1347 If LIST has N or fewer elements, nil is returned. 2513 If LIST has N or fewer elements, nil is returned.
2514 Otherwise, LIST may be dotted, but not circular, and `(butlast LIST 0)'
2515 converts a dotted into a true list.
1348 */ 2516 */
1349 (list, n)) 2517 (list, n))
1350 { 2518 {
1351 EMACS_INT int_n; 2519 Lisp_Object retval = Qnil, retval_tail = Qnil;
2520 Elemcount int_n = 1;
1352 2521
1353 CHECK_LIST (list); 2522 CHECK_LIST (list);
1354 2523
1355 if (NILP (n)) 2524 if (!NILP (n))
1356 int_n = 1;
1357 else
1358 { 2525 {
1359 CHECK_NATNUM (n); 2526 CHECK_NATNUM (n);
1360 int_n = XINT (n); 2527 int_n = BIGNUMP (n) ? 1 + EMACS_INT_MAX : XINT (n);
1361 } 2528 }
1362 2529
1363 { 2530 if (CONSP (list))
1364 Lisp_Object retval = Qnil; 2531 {
1365 Lisp_Object tail = list; 2532 Lisp_Object tail = list;
1366 2533
1367 EXTERNAL_LIST_LOOP_1 (list) 2534 EXTERNAL_LIST_LOOP_3 (elt, list, list_tail)
1368 { 2535 {
1369 if (--int_n < 0) 2536 if (--int_n < 0)
1370 { 2537 {
1371 retval = Fcons (XCAR (tail), retval); 2538 if (NILP (retval_tail))
1372 tail = XCDR (tail); 2539 {
1373 } 2540 retval = retval_tail = Fcons (XCAR (tail), Qnil);
1374 } 2541 }
1375 2542 else
1376 return Fnreverse (retval); 2543 {
1377 } 2544 XSETCDR (retval_tail, Fcons (XCAR (tail), Qnil));
2545 retval_tail = XCDR (retval_tail);
2546 }
2547
2548 tail = XCDR (tail);
2549 }
2550
2551 if (!CONSP (XCDR (list_tail)))
2552 {
2553 break;
2554 }
2555 }
2556 }
2557
2558 return retval;
1378 } 2559 }
1379 2560
1380 DEFUN ("member", Fmember, 2, 2, 0, /* 2561 DEFUN ("member", Fmember, 2, 2, 0, /*
1381 Return non-nil if ELT is an element of LIST. Comparison done with `equal'. 2562 Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
1382 The value is actually the tail of LIST whose car is ELT. 2563 The value is actually the tail of LIST whose car is ELT.
1389 return tail; 2570 return tail;
1390 } 2571 }
1391 return Qnil; 2572 return Qnil;
1392 } 2573 }
1393 2574
1394 DEFUN ("old-member", Fold_member, 2, 2, 0, /*
1395 Return non-nil if ELT is an element of LIST. Comparison done with `old-equal'.
1396 The value is actually the tail of LIST whose car is ELT.
1397 This function is provided only for byte-code compatibility with v19.
1398 Do not use it.
1399 */
1400 (elt, list))
1401 {
1402 EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
1403 {
1404 if (internal_old_equal (elt, list_elt, 0))
1405 return tail;
1406 }
1407 return Qnil;
1408 }
1409
1410 DEFUN ("memq", Fmemq, 2, 2, 0, /* 2575 DEFUN ("memq", Fmemq, 2, 2, 0, /*
1411 Return non-nil if ELT is an element of LIST. Comparison done with `eq'. 2576 Return non-nil if ELT is an element of LIST. Comparison done with `eq'.
1412 The value is actually the tail of LIST whose car is ELT. 2577 The value is actually the tail of LIST whose car is ELT.
1413 */ 2578 */
1414 (elt, list)) 2579 (elt, list))
1419 return tail; 2584 return tail;
1420 } 2585 }
1421 return Qnil; 2586 return Qnil;
1422 } 2587 }
1423 2588
1424 DEFUN ("old-memq", Fold_memq, 2, 2, 0, /*
1425 Return non-nil if ELT is an element of LIST. Comparison done with `old-eq'.
1426 The value is actually the tail of LIST whose car is ELT.
1427 This function is provided only for byte-code compatibility with v19.
1428 Do not use it.
1429 */
1430 (elt, list))
1431 {
1432 EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
1433 {
1434 if (HACKEQ_UNSAFE (elt, list_elt))
1435 return tail;
1436 }
1437 return Qnil;
1438 }
1439
1440 Lisp_Object 2589 Lisp_Object
1441 memq_no_quit (Lisp_Object elt, Lisp_Object list) 2590 memq_no_quit (Lisp_Object elt, Lisp_Object list)
1442 { 2591 {
1443 LIST_LOOP_3 (list_elt, list, tail) 2592 LIST_LOOP_3 (list_elt, list, tail)
1444 { 2593 {
1445 if (EQ_WITH_EBOLA_NOTICE (elt, list_elt)) 2594 if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
1446 return tail; 2595 return tail;
1447 } 2596 }
1448 return Qnil; 2597 return Qnil;
2598 }
2599
2600 /* Return the first index of ITEM in LIST. In CONS_OUT, return the cons cell
2601 before that containing the element. If the element is in the first cons
2602 cell, return Qnil in CONS_OUT. TEST, KEY, START, END are as in
2603 #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should have been initialized
2604 with get_check_match_function() or get_check_test_function(). A non-zero
2605 REVERSE_TEST_ORDER means call TEST with the element from LIST as its
2606 first argument and ITEM as its second. Error if LIST is ill-formed, or
2607 circular. */
2608 static Lisp_Object
2609 list_position_cons_before (Lisp_Object *cons_out,
2610 Lisp_Object item, Lisp_Object list,
2611 check_test_func_t check_test,
2612 Boolint test_not_unboundp,
2613 Lisp_Object test, Lisp_Object key,
2614 Boolint reverse_test_order,
2615 Lisp_Object start, Lisp_Object end)
2616 {
2617 struct gcpro gcpro1;
2618 Lisp_Object tail_before = Qnil;
2619 Elemcount ii = 0, starting = XINT (start);
2620 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end);
2621
2622 GCPRO1 (tail_before);
2623
2624 if (check_test == check_eq_nokey)
2625 {
2626 /* TEST is #'eq, no need to call any C functions, and the test order
2627 won't be visible. */
2628 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
2629 {
2630 if (starting <= ii && ii < ending &&
2631 EQ (item, elt) == test_not_unboundp)
2632 {
2633 *cons_out = tail_before;
2634 RETURN_UNGCPRO (make_integer (ii));
2635 }
2636 else
2637 {
2638 if (ii >= ending)
2639 {
2640 break;
2641 }
2642 }
2643 ii++;
2644 tail_before = tail;
2645 }
2646 }
2647 else
2648 {
2649 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
2650 {
2651 if (starting <= ii && ii < ending &&
2652 (reverse_test_order ?
2653 check_test (test, key, elt, item) :
2654 check_test (test, key, item, elt)) == test_not_unboundp)
2655 {
2656 *cons_out = tail_before;
2657 XUNGCPRO (elt);
2658 UNGCPRO;
2659 return make_integer (ii);
2660 }
2661 else
2662 {
2663 if (ii >= ending)
2664 {
2665 break;
2666 }
2667 }
2668 ii++;
2669 tail_before = tail;
2670 }
2671 END_GC_EXTERNAL_LIST_LOOP (elt);
2672 }
2673
2674 RETURN_UNGCPRO (Qnil);
2675 }
2676
2677 DEFUN ("member*", FmemberX, 2, MANY, 0, /*
2678 Return the first sublist of LIST with car ITEM, or nil if no such sublist.
2679
2680 The keyword :test specifies a two-argument function that is used to compare
2681 ITEM with elements in LIST; if omitted, it defaults to `eql'.
2682
2683 The keyword :test-not is similar, but specifies a negated function. That
2684 is, ITEM is considered equal to an element in LIST if the given function
2685 returns nil. Common Lisp deprecates :test-not, and if both are specified,
2686 XEmacs signals an error.
2687
2688 :key specifies a one-argument function that transforms elements of LIST into
2689 \"comparison keys\" before the test predicate is applied. For example,
2690 if :key is #'car, then ITEM is compared with the car of elements from LIST.
2691 The :key function, however, is not applied to ITEM, and does not affect the
2692 elements in the returned list, which are taken directly from the elements in
2693 LIST.
2694
2695 arguments: (ITEM LIST &key (TEST #'eql) TEST-NOT (KEY #'identity))
2696 */
2697 (int nargs, Lisp_Object *args))
2698 {
2699 Lisp_Object item = args[0], list = args[1], result = Qnil, position0;
2700 Boolint test_not_unboundp = 1;
2701 check_test_func_t check_test = NULL;
2702
2703 PARSE_KEYWORDS (FmemberX, nargs, args, 5, (test, if_not, if_, test_not, key),
2704 NULL);
2705 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
2706 key, &test_not_unboundp);
2707 position0
2708 = list_position_cons_before (&result, item, list, check_test,
2709 test_not_unboundp, test, key, 0, Qzero, Qnil);
2710
2711 return CONSP (result) ? XCDR (result) : ZEROP (position0) ? list : Qnil;
2712 }
2713
2714 /* This macro might eventually find a better home than here. */
2715
2716 #define CHECK_KEY_ARGUMENT(key) \
2717 do { \
2718 if (NILP (key)) \
2719 { \
2720 key = Qidentity; \
2721 } \
2722 \
2723 if (!EQ (key, Qidentity)) \
2724 { \
2725 key = indirect_function (key, 1); \
2726 if (EQ (key, XSYMBOL_FUNCTION (Qidentity))) \
2727 { \
2728 key = Qidentity; \
2729 } \
2730 } \
2731 } while (0)
2732
2733 #define KEY(key, item) (EQ (Qidentity, key) ? item : \
2734 IGNORE_MULTIPLE_VALUES (call1 (key, item)))
2735
2736 DEFUN ("adjoin", Fadjoin, 2, MANY, 0, /*
2737 Return ITEM consed onto the front of LIST, if not already in LIST.
2738
2739 Otherwise, return LIST unmodified.
2740
2741 See `member*' for the meaning of the keywords.
2742
2743 arguments: (ITEM LIST &key (TEST #'eql) (KEY #'identity) TEST-NOT)
2744 */
2745 (int nargs, Lisp_Object *args))
2746 {
2747 Lisp_Object item = args[0], list = args[1], keyed = Qnil, ignore = Qnil;
2748 struct gcpro gcpro1;
2749 Boolint test_not_unboundp = 1;
2750 check_test_func_t check_test = NULL;
2751
2752 PARSE_KEYWORDS (Fadjoin, nargs, args, 3, (test, key, test_not),
2753 NULL);
2754
2755 CHECK_KEY_ARGUMENT (key);
2756
2757 keyed = KEY (key, item);
2758
2759 GCPRO1 (keyed);
2760 check_test = get_check_test_function (keyed, &test, test_not, Qnil, Qnil,
2761 key, &test_not_unboundp);
2762 if (NILP (list_position_cons_before (&ignore, keyed, list, check_test,
2763 test_not_unboundp, test, key, 0, Qzero,
2764 Qnil)))
2765 {
2766 RETURN_UNGCPRO (Fcons (item, list));
2767 }
2768
2769 RETURN_UNGCPRO (list);
1449 } 2770 }
1450 2771
1451 DEFUN ("assoc", Fassoc, 2, 2, 0, /* 2772 DEFUN ("assoc", Fassoc, 2, 2, 0, /*
1452 Return non-nil if KEY is `equal' to the car of an element of ALIST. 2773 Return non-nil if KEY is `equal' to the car of an element of ALIST.
1453 The value is actually the element of ALIST whose car equals KEY. 2774 The value is actually the element of ALIST whose car equals KEY.
1456 { 2777 {
1457 /* This function can GC. */ 2778 /* This function can GC. */
1458 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist) 2779 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
1459 { 2780 {
1460 if (internal_equal (key, elt_car, 0)) 2781 if (internal_equal (key, elt_car, 0))
1461 return elt;
1462 }
1463 return Qnil;
1464 }
1465
1466 DEFUN ("old-assoc", Fold_assoc, 2, 2, 0, /*
1467 Return non-nil if KEY is `old-equal' to the car of an element of ALIST.
1468 The value is actually the element of ALIST whose car equals KEY.
1469 */
1470 (key, alist))
1471 {
1472 /* This function can GC. */
1473 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
1474 {
1475 if (internal_old_equal (key, elt_car, 0))
1476 return elt; 2782 return elt;
1477 } 2783 }
1478 return Qnil; 2784 return Qnil;
1479 } 2785 }
1480 2786
1499 return elt; 2805 return elt;
1500 } 2806 }
1501 return Qnil; 2807 return Qnil;
1502 } 2808 }
1503 2809
1504 DEFUN ("old-assq", Fold_assq, 2, 2, 0, /*
1505 Return non-nil if KEY is `old-eq' to the car of an element of ALIST.
1506 The value is actually the element of ALIST whose car is KEY.
1507 Elements of ALIST that are not conses are ignored.
1508 This function is provided only for byte-code compatibility with v19.
1509 Do not use it.
1510 */
1511 (key, alist))
1512 {
1513 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
1514 {
1515 if (HACKEQ_UNSAFE (key, elt_car))
1516 return elt;
1517 }
1518 return Qnil;
1519 }
1520
1521 /* Like Fassq but never report an error and do not allow quits. 2810 /* Like Fassq but never report an error and do not allow quits.
1522 Use only on lists known never to be circular. */ 2811 Use only on lists known never to be circular. */
1523 2812
1524 Lisp_Object 2813 Lisp_Object
1525 assq_no_quit (Lisp_Object key, Lisp_Object alist) 2814 assq_no_quit (Lisp_Object key, Lisp_Object alist)
1532 return elt; 2821 return elt;
1533 } 2822 }
1534 return Qnil; 2823 return Qnil;
1535 } 2824 }
1536 2825
2826 DEFUN ("assoc*", FassocX, 2, MANY, 0, /*
2827 Find the first item whose car matches ITEM in ALIST.
2828
2829 See `member*' for the meaning of :test, :test-not and :key.
2830
2831 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT)
2832 */
2833 (int nargs, Lisp_Object *args))
2834 {
2835 Lisp_Object item = args[0], alist = args[1];
2836 Boolint test_not_unboundp = 1;
2837 check_test_func_t check_test = NULL;
2838
2839 PARSE_KEYWORDS (FassocX, nargs, args, 5, (test, if_, if_not, test_not, key),
2840 NULL);
2841
2842 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
2843 key, &test_not_unboundp);
2844
2845 if (check_test == check_eq_nokey)
2846 {
2847 /* TEST is #'eq, no need to call any C functions. */
2848 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2849 {
2850 if (EQ (item, elt_car) == test_not_unboundp)
2851 {
2852 return elt;
2853 }
2854 }
2855 }
2856 else
2857 {
2858 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
2859 {
2860 if (CONSP (elt) &&
2861 check_test (test, key, item, XCAR (elt)) == test_not_unboundp)
2862 {
2863 XUNGCPRO (elt);
2864 return elt;
2865 }
2866 }
2867 END_GC_EXTERNAL_LIST_LOOP (elt);
2868 }
2869
2870 return Qnil;
2871 }
2872
1537 DEFUN ("rassoc", Frassoc, 2, 2, 0, /* 2873 DEFUN ("rassoc", Frassoc, 2, 2, 0, /*
1538 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST. 2874 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST.
1539 The value is actually the element of ALIST whose cdr equals VALUE. 2875 The value is actually the element of ALIST whose cdr equals VALUE.
1540 */ 2876 */
1541 (value, alist)) 2877 (value, alist))
1542 { 2878 {
1543 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist) 2879 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
1544 { 2880 {
1545 if (internal_equal (value, elt_cdr, 0)) 2881 if (internal_equal (value, elt_cdr, 0))
1546 return elt;
1547 }
1548 return Qnil;
1549 }
1550
1551 DEFUN ("old-rassoc", Fold_rassoc, 2, 2, 0, /*
1552 Return non-nil if VALUE is `old-equal' to the cdr of an element of ALIST.
1553 The value is actually the element of ALIST whose cdr equals VALUE.
1554 */
1555 (value, alist))
1556 {
1557 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
1558 {
1559 if (internal_old_equal (value, elt_cdr, 0))
1560 return elt; 2882 return elt;
1561 } 2883 }
1562 return Qnil; 2884 return Qnil;
1563 } 2885 }
1564 2886
1602 return elt; 2924 return elt;
1603 } 2925 }
1604 return Qnil; 2926 return Qnil;
1605 } 2927 }
1606 2928
2929 DEFUN ("rassoc*", FrassocX, 2, MANY, 0, /*
2930 Find the first item whose cdr matches ITEM in ALIST.
2931
2932 See `member*' for the meaning of :test, :test-not and :key.
2933
2934 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT)
2935 */
2936 (int nargs, Lisp_Object *args))
2937 {
2938 Lisp_Object item = args[0], alist = args[1];
2939 Boolint test_not_unboundp = 1;
2940 check_test_func_t check_test = NULL;
2941
2942 PARSE_KEYWORDS (FrassocX, nargs, args, 5, (test, if_, if_not, test_not, key),
2943 NULL);
2944
2945 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
2946 key, &test_not_unboundp);
2947
2948 if (check_test == check_eq_nokey)
2949 {
2950 /* TEST is #'eq, no need to call any C functions. */
2951 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2952 {
2953 if (EQ (item, elt_cdr) == test_not_unboundp)
2954 {
2955 return elt;
2956 }
2957 }
2958 }
2959 else
2960 {
2961 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
2962 {
2963 if (CONSP (elt) &&
2964 check_test (test, key, item, XCDR (elt)) == test_not_unboundp)
2965 {
2966 XUNGCPRO (elt);
2967 return elt;
2968 }
2969 }
2970 END_GC_EXTERNAL_LIST_LOOP (elt);
2971 }
2972
2973 return Qnil;
2974 }
1607 2975
1608 DEFUN ("delete", Fdelete, 2, 2, 0, /* 2976 /* This is the implementation of both #'find and #'position. */
1609 Delete by side effect any occurrences of ELT as a member of LIST. 2977 static Lisp_Object
1610 The modified LIST is returned. Comparison is done with `equal'. 2978 position (Lisp_Object *object_out, Lisp_Object item, Lisp_Object sequence,
1611 If the first member of LIST is ELT, there is no way to remove it by side 2979 check_test_func_t check_test, Boolint test_not_unboundp,
1612 effect; therefore, write `(setq foo (delete element foo))' to be sure 2980 Lisp_Object test, Lisp_Object key, Lisp_Object start, Lisp_Object end,
1613 of changing the value of `foo'. 2981 Lisp_Object from_end, Lisp_Object default_, Lisp_Object caller)
1614 Also see: `remove'. 2982 {
1615 */ 2983 Lisp_Object result = Qnil;
1616 (elt, list)) 2984 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0;
1617 { 2985
1618 EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list, 2986 CHECK_SEQUENCE (sequence);
1619 (internal_equal (elt, list_elt, 0))); 2987 CHECK_NATNUM (start);
1620 return list; 2988 starting = INTP (start) ? XINT (start) : 1 + EMACS_INT_MAX;
1621 } 2989
1622 2990 if (!NILP (end))
1623 DEFUN ("old-delete", Fold_delete, 2, 2, 0, /* 2991 {
1624 Delete by side effect any occurrences of ELT as a member of LIST. 2992 CHECK_NATNUM (end);
1625 The modified LIST is returned. Comparison is done with `old-equal'. 2993 ending = INTP (end) ? XINT (end) : 1 + EMACS_INT_MAX;
1626 If the first member of LIST is ELT, there is no way to remove it by side 2994 }
1627 effect; therefore, write `(setq foo (old-delete element foo))' to be sure 2995
1628 of changing the value of `foo'. 2996 *object_out = default_;
1629 */ 2997
1630 (elt, list)) 2998 if (CONSP (sequence))
1631 { 2999 {
1632 EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list, 3000 if (!(starting < ending))
1633 (internal_old_equal (elt, list_elt, 0))); 3001 {
1634 return list; 3002 check_sequence_range (sequence, start, end, Flength (sequence));
1635 } 3003 /* starting could be equal to ending, in which case nil is what
1636 3004 we want to return. */
1637 DEFUN ("delq", Fdelq, 2, 2, 0, /* 3005 return Qnil;
1638 Delete by side effect any occurrences of ELT as a member of LIST. 3006 }
1639 The modified LIST is returned. Comparison is done with `eq'. 3007
1640 If the first member of LIST is ELT, there is no way to remove it by side 3008 {
1641 effect; therefore, write `(setq foo (delq element foo))' to be sure of 3009 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
1642 changing the value of `foo'. 3010 {
1643 */ 3011 if (starting <= ii && ii < ending
1644 (elt, list)) 3012 && check_test (test, key, item, elt) == test_not_unboundp)
1645 { 3013 {
1646 EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list, 3014 result = make_integer (ii);
1647 (EQ_WITH_EBOLA_NOTICE (elt, list_elt))); 3015 *object_out = elt;
1648 return list; 3016
1649 } 3017 if (NILP (from_end))
1650 3018 {
1651 DEFUN ("old-delq", Fold_delq, 2, 2, 0, /* 3019 XUNGCPRO (elt);
1652 Delete by side effect any occurrences of ELT as a member of LIST. 3020 return result;
1653 The modified LIST is returned. Comparison is done with `old-eq'. 3021 }
1654 If the first member of LIST is ELT, there is no way to remove it by side 3022 }
1655 effect; therefore, write `(setq foo (old-delq element foo))' to be sure of 3023 else if (ii == ending)
1656 changing the value of `foo'. 3024 {
1657 */ 3025 break;
1658 (elt, list)) 3026 }
1659 { 3027
1660 EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list, 3028 ii++;
1661 (HACKEQ_UNSAFE (elt, list_elt))); 3029 }
1662 return list; 3030 END_GC_EXTERNAL_LIST_LOOP (elt);
1663 } 3031 }
1664 3032
3033 if (ii < starting || (ii < ending && !NILP (end)))
3034 {
3035 check_sequence_range (sequence, start, end, Flength (sequence));
3036 }
3037 }
3038 else if (STRINGP (sequence))
3039 {
3040 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp;
3041 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
3042 Lisp_Object character = Qnil;
3043
3044 while (cursor_offset < byte_len && ii < ending)
3045 {
3046 if (ii >= starting)
3047 {
3048 character = make_char (itext_ichar (cursor));
3049
3050 if (check_test (test, key, item, character) == test_not_unboundp)
3051 {
3052 result = make_integer (ii);
3053 *object_out = character;
3054
3055 if (NILP (from_end))
3056 {
3057 return result;
3058 }
3059 }
3060
3061 startp = XSTRING_DATA (sequence);
3062 cursor = startp + cursor_offset;
3063 if (byte_len != XSTRING_LENGTH (sequence)
3064 || !valid_ibyteptr_p (cursor))
3065 {
3066 mapping_interaction_error (caller, sequence);
3067 }
3068 }
3069
3070 INC_IBYTEPTR (cursor);
3071 cursor_offset = cursor - startp;
3072 ii++;
3073 }
3074
3075 if (ii < starting || (ii < ending && !NILP (end)))
3076 {
3077 check_sequence_range (sequence, start, end, Flength (sequence));
3078 }
3079 }
3080 else
3081 {
3082 Lisp_Object object = Qnil;
3083 len = XINT (Flength (sequence));
3084 check_sequence_range (sequence, start, end, make_int (len));
3085
3086 ending = min (ending, len);
3087 if (0 == len)
3088 {
3089 /* Catches the case where we have nil. */
3090 return result;
3091 }
3092
3093 if (NILP (from_end))
3094 {
3095 for (ii = starting; ii < ending; ii++)
3096 {
3097 object = Faref (sequence, make_int (ii));
3098 if (check_test (test, key, item, object) == test_not_unboundp)
3099 {
3100 result = make_integer (ii);
3101 *object_out = object;
3102 return result;
3103 }
3104 }
3105 }
3106 else
3107 {
3108 for (ii = ending - 1; ii >= starting; ii--)
3109 {
3110 object = Faref (sequence, make_int (ii));
3111 if (check_test (test, key, item, object) == test_not_unboundp)
3112 {
3113 result = make_integer (ii);
3114 *object_out = object;
3115 return result;
3116 }
3117 }
3118 }
3119 }
3120
3121 return result;
3122 }
3123
3124 DEFUN ("position", Fposition, 2, MANY, 0, /*
3125 Return the index of the first occurrence of ITEM in SEQUENCE.
3126
3127 Return nil if not found. See `remove*' for the meaning of the keywords.
3128
3129 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END TEST-NOT)
3130 */
3131 (int nargs, Lisp_Object *args))
3132 {
3133 Lisp_Object object = Qnil, item = args[0], sequence = args[1];
3134 Boolint test_not_unboundp = 1;
3135 check_test_func_t check_test = NULL;
3136
3137 PARSE_KEYWORDS (Fposition, nargs, args, 8,
3138 (test, if_, test_not, if_not, key, start, end, from_end),
3139 (start = Qzero));
3140
3141 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3142 key, &test_not_unboundp);
3143
3144 return position (&object, item, sequence, check_test, test_not_unboundp,
3145 test, key, start, end, from_end, Qnil, Qposition);
3146 }
3147
3148 DEFUN ("find", Ffind, 2, MANY, 0, /*
3149 Find the first occurrence of ITEM in SEQUENCE.
3150
3151 Return the matching ITEM, or nil if not found. See `remove*' for the
3152 meaning of the keywords.
3153
3154 The keyword :default, not specified by Common Lisp, designates an object to
3155 return instead of nil if ITEM is not found.
3156
3157 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) DEFAULT FROM-END TEST-NOT)
3158 */
3159 (int nargs, Lisp_Object *args))
3160 {
3161 Lisp_Object object = Qnil, item = args[0], sequence = args[1];
3162 Boolint test_not_unboundp = 1;
3163 check_test_func_t check_test = NULL;
3164
3165 PARSE_KEYWORDS (Ffind, nargs, args, 9,
3166 (test, if_, test_not, if_not, key, start, end, from_end,
3167 default_),
3168 (start = Qzero));
3169
3170 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3171 key, &test_not_unboundp);
3172
3173 position (&object, item, sequence, check_test, test_not_unboundp,
3174 test, key, start, end, from_end, default_, Qposition);
3175
3176 return object;
3177 }
3178
1665 /* Like Fdelq, but caller must ensure that LIST is properly 3179 /* Like Fdelq, but caller must ensure that LIST is properly
1666 nil-terminated and ebola-free. */ 3180 nil-terminated and ebola-free. */
1667 3181
1668 Lisp_Object 3182 Lisp_Object
1669 delq_no_quit (Lisp_Object elt, Lisp_Object list) 3183 delq_no_quit (Lisp_Object elt, Lisp_Object list)
1706 } 3220 }
1707 } 3221 }
1708 return list; 3222 return list;
1709 } 3223 }
1710 3224
3225 DEFUN ("delete*", FdeleteX, 2, MANY, 0, /*
3226 Remove all occurrences of ITEM in SEQUENCE, destructively.
3227
3228 If SEQUENCE is a non-nil list, this modifies the list directly. A non-list
3229 SEQUENCE will not be destructively modified, rather, if ITEM occurs in it, a
3230 new SEQUENCE of the same type without ITEM will be returned.
3231
3232 See `remove*' for a non-destructive alternative, and for explanation of the
3233 keyword arguments.
3234
3235 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT)
3236 */
3237 (int nargs, Lisp_Object *args))
3238 {
3239 Lisp_Object item = args[0], sequence = args[1];
3240 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX;
3241 Elemcount len, ii = 0, encountered = 0, presenting = 0;
3242 Boolint test_not_unboundp = 1;
3243 check_test_func_t check_test = NULL;
3244
3245 PARSE_KEYWORDS (FdeleteX, nargs, args, 9,
3246 (test, if_not, if_, test_not, key, start, end, from_end,
3247 count), (start = Qzero, count = Qunbound));
3248
3249 CHECK_SEQUENCE (sequence);
3250 CHECK_NATNUM (start);
3251 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
3252
3253 if (!NILP (end))
3254 {
3255 CHECK_NATNUM (end);
3256 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
3257 }
3258
3259 if (!UNBOUNDP (count))
3260 {
3261 if (!NILP (count))
3262 {
3263 CHECK_INTEGER (count);
3264 if (INTP (count))
3265 {
3266 counting = XINT (count);
3267 }
3268 #ifdef HAVE_BIGNUM
3269 else
3270 {
3271 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
3272 1 + EMACS_INT_MAX : EMACS_INT_MIN - 1;
3273 }
3274 #endif
3275
3276 if (counting < 1)
3277 {
3278 return sequence;
3279 }
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 }
3299 }
3300
3301 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3302 key, &test_not_unboundp);
3303
3304 if (CONSP (sequence))
3305 {
3306 Lisp_Object prev_tail_list_elt = Qnil, ignore = Qnil;
3307 Elemcount list_len = 0, deleted = 0;
3308 struct gcpro gcpro1;
3309
3310 if (!NILP (count) && !NILP (from_end))
3311 {
3312 /* Both COUNT and FROM-END were specified; we need to traverse the
3313 list twice. */
3314 Lisp_Object present = count_with_tail (&ignore, nargs, args,
3315 QdeleteX);
3316
3317 if (ZEROP (present))
3318 {
3319 return sequence;
3320 }
3321
3322 presenting = XINT (present);
3323
3324 /* If there are fewer items in the list than we have permission to
3325 delete, we don't need to differentiate between the :from-end
3326 nil and :from-end t cases. Otherwise, presenting is the number
3327 of matching items we need to ignore before we start to
3328 delete. */
3329 presenting = presenting <= counting ? 0 : presenting - counting;
3330 }
3331
3332 GCPRO1 (prev_tail_list_elt);
3333 ii = -1;
3334
3335 {
3336 GC_EXTERNAL_LIST_LOOP_4 (list_elt, sequence, tail, list_len)
3337 {
3338 ii++;
3339
3340 if (starting <= ii && ii < ending &&
3341 (check_test (test, key, item, list_elt) == test_not_unboundp)
3342 && (presenting ? encountered++ >= presenting
3343 : encountered++ < counting))
3344 {
3345 if (NILP (prev_tail_list_elt))
3346 {
3347 sequence = XCDR (tail);
3348 }
3349 else
3350 {
3351 XSETCDR (prev_tail_list_elt, XCDR (tail));
3352 }
3353
3354 /* Keep tortoise from ever passing hare. */
3355 list_len = 0;
3356 deleted++;
3357 }
3358 else
3359 {
3360 prev_tail_list_elt = tail;
3361 if (ii >= ending || (!presenting && encountered > counting))
3362 {
3363 break;
3364 }
3365 }
3366 }
3367 END_GC_EXTERNAL_LIST_LOOP (list_elt);
3368 }
3369
3370 UNGCPRO;
3371
3372 if ((ii < starting || (ii < ending && !NILP (end))) &&
3373 !(presenting ? encountered == presenting : encountered == counting))
3374 {
3375 check_sequence_range (args[1], start, end,
3376 make_int (deleted + XINT (Flength (args[1]))));
3377 }
3378
3379 return sequence;
3380 }
3381 else if (STRINGP (sequence))
3382 {
3383 Ibyte *staging = alloca_ibytes (XSTRING_LENGTH (sequence));
3384 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence);
3385 Ibyte *cursor = startp;
3386 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence);
3387 Lisp_Object character, result = sequence;
3388
3389 if (!NILP (count) && !NILP (from_end))
3390 {
3391 Lisp_Object present = count_with_tail (&character, nargs, args,
3392 QdeleteX);
3393
3394 if (ZEROP (present))
3395 {
3396 return sequence;
3397 }
3398
3399 presenting = XINT (present);
3400
3401 /* If there are fewer items in the list than we have permission to
3402 delete, we don't need to differentiate between the :from-end
3403 nil and :from-end t cases. Otherwise, presenting is the number
3404 of matching items we need to ignore before we start to
3405 delete. */
3406 presenting = presenting <= counting ? 0 : presenting - counting;
3407 }
3408
3409 ii = 0;
3410 while (cursor_offset < byte_len)
3411 {
3412 if (ii >= starting && ii < ending)
3413 {
3414 character = make_char (itext_ichar (cursor));
3415
3416 if ((check_test (test, key, item, character)
3417 == test_not_unboundp)
3418 && (presenting ? encountered++ >= presenting :
3419 encountered++ < counting))
3420 {
3421 DO_NOTHING;
3422 }
3423 else
3424 {
3425 staging_cursor
3426 += set_itext_ichar (staging_cursor, XCHAR (character));
3427 }
3428
3429 startp = XSTRING_DATA (sequence);
3430 cursor = startp + cursor_offset;
3431 if (byte_len != XSTRING_LENGTH (sequence)
3432 || !valid_ibyteptr_p (cursor))
3433 {
3434 mapping_interaction_error (QdeleteX, sequence);
3435 }
3436 }
3437 else
3438 {
3439 staging_cursor += itext_copy_ichar (cursor, staging_cursor);
3440 }
3441
3442 INC_IBYTEPTR (cursor);
3443 cursor_offset = cursor - startp;
3444 ii++;
3445 }
3446
3447 if (ii < starting || (ii < ending && !NILP (end)))
3448 {
3449 check_sequence_range (sequence, start, end, Flength (sequence));
3450 }
3451
3452 if (0 != encountered)
3453 {
3454 result = make_string (staging, staging_cursor - staging);
3455 copy_string_extents (result, sequence, 0, 0,
3456 staging_cursor - staging);
3457 sequence = result;
3458 }
3459
3460 return sequence;
3461 }
3462 else
3463 {
3464 Lisp_Object position0 = Qnil, object = Qnil;
3465 Lisp_Object *staging = NULL, *staging_cursor, *staging_limit;
3466 Elemcount positioning;
3467
3468 len = XINT (Flength (sequence));
3469
3470 check_sequence_range (sequence, start, end, make_int (len));
3471
3472 position0 = position (&object, item, sequence, check_test,
3473 test_not_unboundp, test, key, start, end,
3474 from_end, Qnil, QdeleteX);
3475 if (NILP (position0))
3476 {
3477 return sequence;
3478 }
3479
3480 ending = min (ending, len);
3481 positioning = XINT (position0);
3482 encountered = 1;
3483
3484 if (NILP (from_end))
3485 {
3486 staging = alloca_array (Lisp_Object, len - 1);
3487 staging_cursor = staging;
3488
3489 ii = 0;
3490 while (ii < positioning)
3491 {
3492 *staging_cursor++ = Faref (sequence, make_int (ii));
3493 ii++;
3494 }
3495
3496 ii = positioning + 1;
3497 while (ii < ending)
3498 {
3499 object = Faref (sequence, make_int (ii));
3500 if (encountered < counting
3501 && (check_test (test, key, item, object)
3502 == test_not_unboundp))
3503 {
3504 encountered++;
3505 }
3506 else
3507 {
3508 *staging_cursor++ = object;
3509 }
3510 ii++;
3511 }
3512
3513 while (ii < len)
3514 {
3515 *staging_cursor++ = Faref (sequence, make_int (ii));
3516 ii++;
3517 }
3518 }
3519 else
3520 {
3521 staging = alloca_array (Lisp_Object, len - 1);
3522 staging_cursor = staging_limit = staging + len - 1;
3523
3524 ii = len - 1;
3525 while (ii > positioning)
3526 {
3527 *--staging_cursor = Faref (sequence, make_int (ii));
3528 ii--;
3529 }
3530
3531 ii = positioning - 1;
3532 while (ii >= starting)
3533 {
3534 object = Faref (sequence, make_int (ii));
3535 if (encountered < counting
3536 && (check_test (test, key, item, object) ==
3537 test_not_unboundp))
3538 {
3539 encountered++;
3540 }
3541 else
3542 {
3543 *--staging_cursor = object;
3544 }
3545
3546 ii--;
3547 }
3548
3549 while (ii >= 0)
3550 {
3551 *--staging_cursor = Faref (sequence, make_int (ii));
3552 ii--;
3553 }
3554
3555 staging = staging_cursor;
3556 staging_cursor = staging_limit;
3557 }
3558
3559 if (VECTORP (sequence))
3560 {
3561 return Fvector (staging_cursor - staging, staging);
3562 }
3563 else if (BIT_VECTORP (sequence))
3564 {
3565 return Fbit_vector (staging_cursor - staging, staging);
3566 }
3567
3568 /* A nil sequence will have given us a nil #'position,
3569 above. */
3570 ABORT ();
3571
3572 return Qnil;
3573 }
3574 }
3575
3576 DEFUN ("remove*", FremoveX, 2, MANY, 0, /*
3577 Remove all occurrences of ITEM in SEQUENCE, non-destructively.
3578
3579 If SEQUENCE is a list, `remove*' makes a copy if that is necessary to avoid
3580 corrupting the original SEQUENCE.
3581
3582 The keywords :test and :test-not specify two-argument test and negated-test
3583 predicates, respectively; :test defaults to `eql'. :key specifies a
3584 one-argument function that transforms elements of SEQUENCE into \"comparison
3585 keys\" before the test predicate is applied. See `member*' for more
3586 information on these keywords.
3587
3588 :start and :end, if given, specify indices of a subsequence of SEQUENCE to
3589 be processed. Indices are 0-based and processing involves the subsequence
3590 starting at the index given by :start and ending just before the index given
3591 by :end.
3592
3593 :count, if given, limits the number of items removed to the number
3594 specified. :from-end, if given, causes processing to proceed starting from
3595 the end instead of the beginning; in this case, this matters only if :count
3596 is given.
3597
3598 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT)
3599 */
3600 (int nargs, Lisp_Object *args))
3601 {
3602 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil,
3603 tail = Qnil;
3604 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX;
3605 Elemcount ii = 0, encountered = 0, presenting = 0;
3606 Boolint test_not_unboundp = 1;
3607 check_test_func_t check_test = NULL;
3608
3609 PARSE_KEYWORDS (FremoveX, nargs, args, 9,
3610 (test, if_not, if_, test_not, key, start, end, from_end,
3611 count), (start = Qzero));
3612
3613 if (!CONSP (sequence))
3614 {
3615 return FdeleteX (nargs, args);
3616 }
3617
3618 CHECK_NATNUM (start);
3619 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
3620
3621 if (!NILP (end))
3622 {
3623 CHECK_NATNUM (end);
3624 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
3625 }
3626
3627 if (!NILP (count))
3628 {
3629 CHECK_INTEGER (count);
3630 if (INTP (count))
3631 {
3632 counting = XINT (count);
3633 }
3634 #ifdef HAVE_BIGNUM
3635 else
3636 {
3637 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
3638 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN;
3639 }
3640 #endif
3641
3642 if (counting <= 0)
3643 {
3644 return sequence;
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 }
3664 }
3665
3666 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3667 key, &test_not_unboundp);
3668
3669 matched_count = count_with_tail (&tail, nargs, args, QremoveX);
3670
3671 if (!ZEROP (matched_count))
3672 {
3673 Lisp_Object result = Qnil, result_tail = Qnil;
3674 struct gcpro gcpro1, gcpro2;
3675
3676 if (!NILP (count) && !NILP (from_end))
3677 {
3678 presenting = XINT (matched_count);
3679
3680 /* If there are fewer matching elements in the list than we have
3681 permission to delete, we don't need to differentiate between
3682 the :from-end nil and :from-end t cases. Otherwise, presenting
3683 is the number of matching items we need to ignore before we
3684 start to delete. */
3685 presenting = presenting <= counting ? 0 : presenting - counting;
3686 }
3687
3688 GCPRO2 (result, tail);
3689 {
3690 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
3691 {
3692 if (EQ (tail, tailing))
3693 {
3694 XUNGCPRO (elt);
3695 UNGCPRO;
3696
3697 if (NILP (result))
3698 {
3699 return XCDR (tail);
3700 }
3701
3702 XSETCDR (result_tail, XCDR (tail));
3703 return result;
3704 }
3705 else if (starting <= ii && ii < ending &&
3706 (check_test (test, key, item, elt) == test_not_unboundp)
3707 && (presenting ? encountered++ >= presenting
3708 : encountered++ < counting))
3709 {
3710 DO_NOTHING;
3711 }
3712 else if (NILP (result))
3713 {
3714 result = result_tail = Fcons (elt, Qnil);
3715 }
3716 else
3717 {
3718 XSETCDR (result_tail, Fcons (elt, Qnil));
3719 result_tail = XCDR (result_tail);
3720 }
3721
3722 if (ii == ending)
3723 {
3724 break;
3725 }
3726
3727 ii++;
3728 }
3729 END_GC_EXTERNAL_LIST_LOOP (elt);
3730 }
3731 UNGCPRO;
3732
3733 if (ii < starting || (ii < ending && !NILP (end)))
3734 {
3735 check_sequence_range (args[0], start, end, Flength (args[0]));
3736 }
3737
3738 return result;
3739 }
3740
3741 return sequence;
3742 }
3743
1711 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /* 3744 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /*
1712 Delete by side effect any elements of ALIST whose car is `equal' to KEY. 3745 Delete by side effect any elements of ALIST whose car is `equal' to KEY.
1713 The modified ALIST is returned. If the first member of ALIST has a car 3746 The modified ALIST is returned. If the first member of ALIST has a car
1714 that is `equal' to KEY, there is no way to remove it by side effect; 3747 that is `equal' to KEY, there is no way to remove it by side effect;
1715 therefore, write `(setq foo (remassoc key foo))' to be sure of changing 3748 therefore, write `(setq foo (remassoc key foo))' to be sure of changing
1794 LIST_LOOP_DELETE_IF (elt, alist, 3827 LIST_LOOP_DELETE_IF (elt, alist,
1795 (CONSP (elt) && 3828 (CONSP (elt) &&
1796 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); 3829 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt))));
1797 return alist; 3830 return alist;
1798 } 3831 }
1799 3832
3833 /* Remove duplicate elements between START and END from LIST, a non-nil
3834 list; if COPY is zero, do so destructively. Items to delete are selected
3835 according to the algorithm used when :from-end t is passed to
3836 #'delete-duplicates. Error if LIST is ill-formed or circular.
3837
3838 TEST and KEY are as in #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should
3839 reflect them, having been initialised with get_check_match_function() or
3840 get_check_test_function(). */
3841 static Lisp_Object
3842 list_delete_duplicates_from_end (Lisp_Object list,
3843 check_test_func_t check_test,
3844 Boolint test_not_unboundp,
3845 Lisp_Object test, Lisp_Object key,
3846 Lisp_Object start,
3847 Lisp_Object end, Boolint copy)
3848 {
3849 Lisp_Object checking = Qnil, result = list;
3850 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail;
3851 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start);
3852 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1;
3853 Elemcount ii = 0;
3854 struct gcpro gcpro1;
3855
3856 /* We can't delete (or remove) as we go, because that breaks START and
3857 END. We could if END were nil, and that would change an ON(N + 2)
3858 algorithm to an ON^2 algorithm; list_position_cons_before() would need to
3859 be modified to return the cons *before* the one containing the item for
3860 that. Here and now it doesn't matter, though, #'delete-duplicates is
3861 relatively expensive no matter what. */
3862 struct Lisp_Bit_Vector *deleting
3863 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
3864 + (sizeof (long)
3865 * (BIT_VECTOR_LONG_STORAGE (len)
3866 - 1)));
3867
3868 check_sequence_range (list, start, end, make_integer (len));
3869
3870 deleting->size = len;
3871 memset (&(deleting->bits), 0,
3872 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
3873
3874 GCPRO1 (keyed);
3875
3876 {
3877 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
3878 {
3879 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii))
3880 {
3881 ii++;
3882 continue;
3883 }
3884
3885 keyed = KEY (key, elt);
3886 checking = XCDR (tail);
3887 pos = ii + 1;
3888
3889 while (!NILP ((positioned = list_position_cons_before
3890 (&position_cons, keyed, checking, check_test,
3891 test_not_unboundp, test, key, 0,
3892 make_int (max (starting - pos, 0)),
3893 make_int (ending - pos)))))
3894 {
3895 pos = XINT (positioned) + pos;
3896 set_bit_vector_bit (deleting, pos, 1);
3897 greatest_pos_seen = max (greatest_pos_seen, pos);
3898 checking = NILP (position_cons) ?
3899 XCDR (checking) : XCDR (XCDR (position_cons));
3900 pos += 1;
3901 }
3902 ii++;
3903 }
3904 END_GC_EXTERNAL_LIST_LOOP (elt);
3905 }
3906
3907 UNGCPRO;
3908
3909 ii = 0;
3910
3911 if (greatest_pos_seen > -1)
3912 {
3913 if (copy)
3914 {
3915 result = result_tail = Fcons (XCAR (list), Qnil);
3916 list = XCDR (list);
3917 ii = 1;
3918
3919 {
3920 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
3921 {
3922 if (ii == greatest_pos_seen)
3923 {
3924 XSETCDR (result_tail, XCDR (tail));
3925 break;
3926 }
3927 else if (!bit_vector_bit (deleting, ii))
3928 {
3929 XSETCDR (result_tail, Fcons (elt, Qnil));
3930 result_tail = XCDR (result_tail);
3931 }
3932 ii++;
3933 }
3934 }
3935 }
3936 else
3937 {
3938 EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
3939 bit_vector_bit (deleting, ii++));
3940 }
3941 }
3942
3943 return result;
3944 }
3945
3946 DEFUN ("delete-duplicates", Fdelete_duplicates, 1, MANY, 0, /*
3947 Remove all duplicate elements from SEQUENCE, destructively.
3948
3949 If SEQUENCE is a list and has duplicates, modify and return it. Note that
3950 SEQUENCE may start with an element to be deleted; because of this, if
3951 modifying a variable, be sure to write `(setq VARIABLE (delete-duplicates
3952 VARIABLE))' to be certain to have a list without duplicate elements.
3953
3954 If SEQUENCE is an array and has duplicates, return a newly-allocated array
3955 of the same type comprising all unique elements of SEQUENCE.
3956
3957 If there are no duplicate elements in SEQUENCE, return it unmodified.
3958
3959 See `remove*' for the meaning of the keywords. See `remove-duplicates' for
3960 a non-destructive version of this function.
3961
3962 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
3963 */
3964 (int nargs, Lisp_Object *args))
3965 {
3966 Lisp_Object sequence = args[0], keyed = Qnil;
3967 Lisp_Object positioned = Qnil, ignore = Qnil;
3968 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0;
3969 Boolint test_not_unboundp = 1;
3970 check_test_func_t check_test = NULL;
3971 struct gcpro gcpro1, gcpro2;
3972
3973 PARSE_KEYWORDS (Fdelete_duplicates, nargs, args, 6,
3974 (test, key, test_not, start, end, from_end),
3975 (start = Qzero));
3976
3977 CHECK_SEQUENCE (sequence);
3978 CHECK_NATNUM (start);
3979 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
3980
3981 if (!NILP (end))
3982 {
3983 CHECK_NATNUM (end);
3984 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
3985 }
3986
3987 CHECK_KEY_ARGUMENT (key);
3988
3989 get_check_match_function (&test, test_not, Qnil, Qnil, key,
3990 &test_not_unboundp, &check_test);
3991
3992 if (CONSP (sequence))
3993 {
3994 if (NILP (from_end))
3995 {
3996 Lisp_Object prev_tail = Qnil;
3997 Elemcount deleted = 0;
3998
3999 GCPRO2 (keyed, prev_tail);
4000
4001 {
4002 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4003 {
4004 if (starting <= ii && ii < ending)
4005 {
4006 keyed = KEY (key, elt);
4007 positioned
4008 = list_position_cons_before (&ignore, keyed,
4009 XCDR (tail), check_test,
4010 test_not_unboundp, test, key,
4011 0, make_int (max (starting
4012 - (ii + 1),
4013 0)),
4014 make_int (ending
4015 - (ii + 1)));
4016 if (!NILP (positioned))
4017 {
4018 sequence = XCDR (tail);
4019 deleted++;
4020 }
4021 else
4022 {
4023 break;
4024 }
4025 }
4026 else
4027 {
4028 break;
4029 }
4030
4031 ii++;
4032 }
4033 END_GC_EXTERNAL_LIST_LOOP (elt);
4034 }
4035 {
4036 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4037 {
4038 if (!(starting <= ii && ii <= ending))
4039 {
4040 prev_tail = tail;
4041 ii++;
4042 continue;
4043 }
4044
4045 keyed = KEY (key, elt);
4046 positioned
4047 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4048 check_test, test_not_unboundp,
4049 test, key, 0,
4050 make_int (max (starting
4051 - (ii + 1), 0)),
4052 make_int (ending - (ii + 1)));
4053 if (!NILP (positioned))
4054 {
4055 /* We know this isn't the first iteration of the loop,
4056 because we advanced above to the point where we have at
4057 least one non-duplicate entry at the head of the
4058 list. */
4059 XSETCDR (prev_tail, XCDR (tail));
4060 len = 0;
4061 deleted++;
4062 }
4063 else
4064 {
4065 prev_tail = tail;
4066 if (ii >= ending)
4067 {
4068 break;
4069 }
4070 }
4071
4072 ii++;
4073 }
4074 END_GC_EXTERNAL_LIST_LOOP (elt);
4075 }
4076
4077 UNGCPRO;
4078
4079 if ((ii < starting || (ii < ending && !NILP (end))))
4080 {
4081 check_sequence_range (args[0], start, end,
4082 make_int (deleted
4083 + XINT (Flength (args[0]))));
4084 }
4085 }
4086 else
4087 {
4088 sequence = list_delete_duplicates_from_end (sequence, check_test,
4089 test_not_unboundp,
4090 test, key, start, end,
4091 0);
4092 }
4093 }
4094 else if (STRINGP (sequence))
4095 {
4096 Lisp_Object elt = Qnil;
4097
4098 if (EQ (Qidentity, key))
4099 {
4100 /* We know all the elements will be characters; set check_test to
4101 reflect that. This isn't useful if KEY is not #'identity, since
4102 it may return non-characters for the elements. */
4103 check_test = get_check_test_function (make_char ('a'),
4104 &test, test_not,
4105 Qnil, Qnil, key,
4106 &test_not_unboundp);
4107 }
4108
4109 if (NILP (from_end))
4110 {
4111 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
4112 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging;
4113 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor;
4114 Elemcount deleted = 0;
4115
4116 GCPRO1 (elt);
4117
4118 while (cursor_offset < byte_len)
4119 {
4120 if (starting <= ii && ii < ending)
4121 {
4122 Ibyte *cursor0 = cursor;
4123 Bytecount cursor0_offset;
4124 Boolint delete_this = 0;
4125
4126 elt = KEY (key, make_char (itext_ichar (cursor)));
4127 INC_IBYTEPTR (cursor0);
4128 cursor0_offset = cursor0 - startp;
4129
4130 for (jj = ii + 1; jj < ending && cursor0_offset < byte_len;
4131 jj++)
4132 {
4133 if (check_test (test, key, elt,
4134 make_char (itext_ichar (cursor0)))
4135 == test_not_unboundp)
4136 {
4137 delete_this = 1;
4138 deleted++;
4139 break;
4140 }
4141
4142 startp = XSTRING_DATA (sequence);
4143 cursor0 = startp + cursor0_offset;
4144 if (byte_len != XSTRING_LENGTH (sequence)
4145 || !valid_ibyteptr_p (cursor0))
4146 {
4147 mapping_interaction_error (Qdelete_duplicates,
4148 sequence);
4149 }
4150
4151 INC_IBYTEPTR (cursor0);
4152 cursor0_offset = cursor0 - startp;
4153 }
4154
4155 startp = XSTRING_DATA (sequence);
4156 cursor = startp + cursor_offset;
4157
4158 if (byte_len != XSTRING_LENGTH (sequence)
4159 || !valid_ibyteptr_p (cursor))
4160 {
4161 mapping_interaction_error (Qdelete_duplicates, sequence);
4162 }
4163
4164 if (!delete_this)
4165 {
4166 staging_cursor
4167 += itext_copy_ichar (cursor, staging_cursor);
4168
4169 }
4170 }
4171 else
4172 {
4173 staging_cursor += itext_copy_ichar (cursor, staging_cursor);
4174 }
4175
4176 INC_IBYTEPTR (cursor);
4177 cursor_offset = cursor - startp;
4178 ii++;
4179 }
4180
4181 UNGCPRO;
4182
4183 if (ii < starting || (ii < ending && !NILP (end)))
4184 {
4185 check_sequence_range (sequence, start, end, Flength (sequence));
4186 }
4187
4188 if (0 != deleted)
4189 {
4190 sequence = make_string (staging, staging_cursor - staging);
4191 }
4192 }
4193 else
4194 {
4195 Elemcount deleted = 0;
4196 Ibyte *staging = alloca_ibytes ((len = string_char_length (sequence))
4197 * MAX_ICHAR_LEN);
4198 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence);
4199 Ibyte *endp = startp + XSTRING_LENGTH (sequence);
4200 struct Lisp_Bit_Vector *deleting
4201 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4202 + (sizeof (long)
4203 * (BIT_VECTOR_LONG_STORAGE (len)
4204 - 1)));
4205
4206 check_sequence_range (sequence, start, end, make_integer (len));
4207
4208 /* For the from_end t case; transform contents to an array with
4209 elements addressable in constant time, use the same algorithm
4210 as for vectors. */
4211 deleting->size = len;
4212 memset (&(deleting->bits), 0,
4213 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
4214
4215 while (startp < endp)
4216 {
4217 itext_copy_ichar (startp, staging + (ii * MAX_ICHAR_LEN));
4218 INC_IBYTEPTR (startp);
4219 ii++;
4220 }
4221
4222 GCPRO1 (elt);
4223
4224 ending = min (ending, len);
4225
4226 for (ii = ending - 1; ii >= starting; ii--)
4227 {
4228 elt = KEY (key, make_char (itext_ichar (staging +
4229 (ii * MAX_ICHAR_LEN))));
4230 for (jj = ii - 1; jj >= starting; jj--)
4231 {
4232 if (check_test (test, key, elt,
4233 make_char (itext_ichar
4234 (staging + (jj * MAX_ICHAR_LEN))))
4235 == test_not_unboundp)
4236 {
4237 set_bit_vector_bit (deleting, ii, 1);
4238 deleted++;
4239 break;
4240 }
4241 }
4242 }
4243
4244 UNGCPRO;
4245
4246 if (0 != deleted)
4247 {
4248 startp = XSTRING_DATA (sequence);
4249
4250 for (ii = 0; ii < len; ii++)
4251 {
4252 if (!bit_vector_bit (deleting, ii))
4253 {
4254 staging_cursor
4255 += itext_copy_ichar (startp, staging_cursor);
4256 }
4257
4258 INC_IBYTEPTR (startp);
4259 }
4260
4261 sequence = make_string (staging, staging_cursor - staging);
4262 }
4263 }
4264 }
4265 else if (VECTORP (sequence))
4266 {
4267 Elemcount deleted = 0;
4268 Lisp_Object *content = XVECTOR_DATA (sequence);
4269 struct Lisp_Bit_Vector *deleting;
4270 Lisp_Object elt = Qnil;
4271
4272 len = XVECTOR_LENGTH (sequence);
4273 check_sequence_range (sequence, start, end, make_integer (len));
4274
4275 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4276 + (sizeof (long)
4277 * (BIT_VECTOR_LONG_STORAGE (len)
4278 - 1)));
4279 deleting->size = len;
4280 memset (&(deleting->bits), 0,
4281 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
4282
4283 GCPRO1 (elt);
4284
4285 ending = min (ending, len);
4286
4287 if (NILP (from_end))
4288 {
4289 for (ii = starting; ii < ending; ii++)
4290 {
4291 elt = KEY (key, content[ii]);
4292
4293 for (jj = ii + 1; jj < ending; jj++)
4294 {
4295 if (check_test (test, key, elt, content[jj])
4296 == test_not_unboundp)
4297 {
4298 set_bit_vector_bit (deleting, ii, 1);
4299 deleted++;
4300 break;
4301 }
4302 }
4303 }
4304 }
4305 else
4306 {
4307 for (ii = ending - 1; ii >= starting; ii--)
4308 {
4309 elt = KEY (key, content[ii]);
4310
4311 for (jj = ii - 1; jj >= starting; jj--)
4312 {
4313 if (check_test (test, key, elt, content[jj])
4314 == test_not_unboundp)
4315 {
4316 set_bit_vector_bit (deleting, ii, 1);
4317 deleted++;
4318 break;
4319 }
4320 }
4321 }
4322 }
4323
4324 UNGCPRO;
4325
4326 if (deleted)
4327 {
4328 Lisp_Object res = make_vector (len - deleted, Qnil),
4329 *res_content = XVECTOR_DATA (res);
4330
4331 for (ii = jj = 0; ii < len; ii++)
4332 {
4333 if (!bit_vector_bit (deleting, ii))
4334 {
4335 res_content[jj++] = content[ii];
4336 }
4337 }
4338
4339 sequence = res;
4340 }
4341 }
4342 else if (BIT_VECTORP (sequence))
4343 {
4344 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
4345 Elemcount deleted = 0;
4346 /* I'm a little irritated at this. Basically, the only reasonable
4347 thing delete-duplicates should do if handed a bit vector is return
4348 something of maximum length two and minimum length 0 (because
4349 that's the possible number of distinct elements if EQ is regarded
4350 as identity, which it should be). But to support arbitrary TEST
4351 and KEY arguments, which may be non-deterministic from our
4352 perspective, we need the same algorithm as for vectors. */
4353 struct Lisp_Bit_Vector *deleting;
4354 Lisp_Object elt = Qnil;
4355
4356 len = bit_vector_length (bv);
4357
4358 if (EQ (Qidentity, key))
4359 {
4360 /* We know all the elements will be bits; set check_test to
4361 reflect that. This isn't useful if KEY is not #'identity, since
4362 it may return non-bits for the elements. */
4363 check_test = get_check_test_function (Qzero, &test, test_not,
4364 Qnil, Qnil, key,
4365 &test_not_unboundp);
4366 }
4367
4368 check_sequence_range (sequence, start, end, make_integer (len));
4369
4370 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4371 + (sizeof (long)
4372 * (BIT_VECTOR_LONG_STORAGE (len)
4373 - 1)));
4374 deleting->size = len;
4375 memset (&(deleting->bits), 0,
4376 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
4377
4378 ending = min (ending, len);
4379
4380 GCPRO1 (elt);
4381
4382 if (NILP (from_end))
4383 {
4384 for (ii = starting; ii < ending; ii++)
4385 {
4386 elt = KEY (key, make_int (bit_vector_bit (bv, ii)));
4387
4388 for (jj = ii + 1; jj < ending; jj++)
4389 {
4390 if (check_test (test, key, elt,
4391 make_int (bit_vector_bit (bv, jj)))
4392 == test_not_unboundp)
4393 {
4394 set_bit_vector_bit (deleting, ii, 1);
4395 deleted++;
4396 break;
4397 }
4398 }
4399 }
4400 }
4401 else
4402 {
4403 for (ii = ending - 1; ii >= starting; ii--)
4404 {
4405 elt = KEY (key, make_int (bit_vector_bit (bv, ii)));
4406
4407 for (jj = ii - 1; jj >= starting; jj--)
4408 {
4409 if (check_test (test, key, elt,
4410 make_int (bit_vector_bit (bv, jj)))
4411 == test_not_unboundp)
4412 {
4413 set_bit_vector_bit (deleting, ii, 1);
4414 deleted++;
4415 break;
4416 }
4417 }
4418 }
4419 }
4420
4421 UNGCPRO;
4422
4423 if (deleted)
4424 {
4425 Lisp_Object res = make_bit_vector (len - deleted, Qzero);
4426 Lisp_Bit_Vector *resbv = XBIT_VECTOR (res);
4427
4428 for (ii = jj = 0; ii < len; ii++)
4429 {
4430 if (!bit_vector_bit (deleting, ii))
4431 {
4432 set_bit_vector_bit (resbv, jj++, bit_vector_bit (bv, ii));
4433 }
4434 }
4435
4436 sequence = res;
4437 }
4438 }
4439
4440 return sequence;
4441 }
4442
4443 DEFUN ("remove-duplicates", Fremove_duplicates, 1, MANY, 0, /*
4444 Remove duplicate elements from SEQUENCE, non-destructively.
4445
4446 If there are no duplicate elements in SEQUENCE, return it unmodified;
4447 otherwise, return a new object. If SEQUENCE is a list, the new object may
4448 share list structure with SEQUENCE.
4449
4450 See `remove*' for the meaning of the keywords.
4451
4452 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
4453 */
4454 (int nargs, Lisp_Object *args))
4455 {
4456 Lisp_Object sequence = args[0], keyed, positioned = Qnil;
4457 Lisp_Object result = sequence, result_tail = result, cursor = Qnil;
4458 Lisp_Object cons_with_shared_tail = Qnil;
4459 Elemcount starting = 0, ending = EMACS_INT_MAX, ii = 0;
4460 Boolint test_not_unboundp = 1;
4461 check_test_func_t check_test = NULL;
4462 struct gcpro gcpro1, gcpro2;
4463
4464 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6,
4465 (test, key, test_not, start, end, from_end),
4466 (start = Qzero));
4467
4468 CHECK_SEQUENCE (sequence);
4469
4470 if (!CONSP (sequence))
4471 {
4472 return Fdelete_duplicates (nargs, args);
4473 }
4474
4475 CHECK_NATNUM (start);
4476 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
4477
4478 if (!NILP (end))
4479 {
4480 CHECK_NATNUM (end);
4481 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
4482 }
4483
4484 if (NILP (key))
4485 {
4486 key = Qidentity;
4487 }
4488
4489 get_check_match_function (&test, test_not, Qnil, Qnil, key,
4490 &test_not_unboundp, &check_test);
4491
4492 if (NILP (from_end))
4493 {
4494 Lisp_Object ignore = Qnil;
4495
4496 GCPRO2 (keyed, result);
4497
4498 {
4499 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4500 {
4501 if (starting <= ii && ii <= ending)
4502 {
4503 keyed = KEY (key, elt);
4504 positioned
4505 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4506 check_test, test_not_unboundp,
4507 test, key, 0,
4508 make_int (max (starting
4509 - (ii + 1), 0)),
4510 make_int (ending - (ii + 1)));
4511 if (!NILP (positioned))
4512 {
4513 sequence = result = result_tail = XCDR (tail);
4514 }
4515 else
4516 {
4517 break;
4518 }
4519 }
4520 else
4521 {
4522 break;
4523 }
4524
4525 ii++;
4526 }
4527 END_GC_EXTERNAL_LIST_LOOP (elt);
4528 }
4529
4530 {
4531 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4532 {
4533 if (!(starting <= ii && ii <= ending))
4534 {
4535 ii++;
4536 continue;
4537 }
4538
4539 /* For this algorithm, each time we encounter an object to be
4540 removed, copy the output list from the tail beyond the last
4541 removed cons to this one. Otherwise, the tail of the output list
4542 is shared with the input list, which is OK. */
4543
4544 keyed = KEY (key, elt);
4545 positioned
4546 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4547 check_test, test_not_unboundp,
4548 test, key, 0,
4549 make_int (max (starting - (ii + 1),
4550 0)),
4551 make_int (ending - (ii + 1)));
4552 if (!NILP (positioned))
4553 {
4554 if (EQ (result, sequence))
4555 {
4556 result = cons_with_shared_tail
4557 = Fcons (XCAR (sequence), XCDR (sequence));
4558 }
4559
4560 result_tail = cons_with_shared_tail;
4561 cursor = XCDR (cons_with_shared_tail);
4562
4563 while (!EQ (cursor, tail) && !NILP (cursor))
4564 {
4565 XSETCDR (result_tail, Fcons (XCAR (cursor), Qnil));
4566 result_tail = XCDR (result_tail);
4567 cursor = XCDR (cursor);
4568 }
4569
4570 XSETCDR (result_tail, XCDR (tail));
4571 cons_with_shared_tail = result_tail;
4572 }
4573
4574 ii++;
4575 }
4576 END_GC_EXTERNAL_LIST_LOOP (elt);
4577 }
4578
4579 UNGCPRO;
4580
4581 if ((ii < starting || (ii < ending && !NILP (end))))
4582 {
4583 check_sequence_range (args[0], start, end, Flength (args[0]));
4584 }
4585 }
4586 else
4587 {
4588 result = list_delete_duplicates_from_end (sequence, check_test,
4589 test_not_unboundp, test, key,
4590 start, end, 1);
4591 }
4592
4593 return result;
4594 }
4595 #undef KEY
4596
1800 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* 4597 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /*
1801 Reverse LIST by destructively modifying cdr pointers. 4598 Reverse SEQUENCE, destructively.
1802 Return the beginning of the reversed list. 4599
1803 Also see: `reverse'. 4600 Return the beginning of the reversed sequence, which will be a distinct Lisp
1804 */ 4601 object if SEQUENCE is a list with length greater than one. See also
1805 (list)) 4602 `reverse', the non-destructive version of this function.
1806 { 4603 */
1807 struct gcpro gcpro1, gcpro2; 4604 (sequence))
1808 Lisp_Object prev = Qnil; 4605 {
1809 Lisp_Object tail = list; 4606 CHECK_SEQUENCE (sequence);
1810 4607
1811 /* We gcpro our args; see `nconc' */ 4608 if (CONSP (sequence))
1812 GCPRO2 (prev, tail); 4609 {
1813 while (!NILP (tail)) 4610 struct gcpro gcpro1, gcpro2;
1814 { 4611 Lisp_Object prev = Qnil;
1815 REGISTER Lisp_Object next; 4612 Lisp_Object tail = sequence;
1816 CONCHECK_CONS (tail); 4613
1817 next = XCDR (tail); 4614 /* We gcpro our args; see `nconc' */
1818 XCDR (tail) = prev; 4615 GCPRO2 (prev, tail);
1819 prev = tail; 4616 while (!NILP (tail))
1820 tail = next; 4617 {
1821 } 4618 REGISTER Lisp_Object next;
1822 UNGCPRO; 4619 CONCHECK_CONS (tail);
1823 return prev; 4620 next = XCDR (tail);
4621 XCDR (tail) = prev;
4622 prev = tail;
4623 tail = next;
4624 }
4625 UNGCPRO;
4626 return prev;
4627 }
4628 else if (VECTORP (sequence))
4629 {
4630 Elemcount length = XVECTOR_LENGTH (sequence), ii = length;
4631 Elemcount half = length / 2;
4632 Lisp_Object swap = Qnil;
4633 CHECK_LISP_WRITEABLE (sequence);
4634
4635 while (ii > half)
4636 {
4637 swap = XVECTOR_DATA (sequence) [length - ii];
4638 XVECTOR_DATA (sequence) [length - ii]
4639 = XVECTOR_DATA (sequence) [ii - 1];
4640 XVECTOR_DATA (sequence) [ii - 1] = swap;
4641 --ii;
4642 }
4643 }
4644 else if (STRINGP (sequence))
4645 {
4646 Elemcount length = XSTRING_LENGTH (sequence);
4647 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length;
4648 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length;
4649
4650 CHECK_LISP_WRITEABLE (sequence);
4651 while (cursor < endp)
4652 {
4653 staging_end -= itext_ichar_len (cursor);
4654 itext_copy_ichar (cursor, staging_end);
4655 INC_IBYTEPTR (cursor);
4656 }
4657
4658 assert (staging == staging_end);
4659
4660 memcpy (XSTRING_DATA (sequence), staging, length);
4661 init_string_ascii_begin (sequence);
4662 bump_string_modiff (sequence);
4663 sledgehammer_check_ascii_begin (sequence);
4664 }
4665 else if (BIT_VECTORP (sequence))
4666 {
4667 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
4668 Elemcount length = bit_vector_length (bv), ii = length;
4669 Elemcount half = length / 2;
4670 int swap = 0;
4671
4672 CHECK_LISP_WRITEABLE (sequence);
4673 while (ii > half)
4674 {
4675 swap = bit_vector_bit (bv, length - ii);
4676 set_bit_vector_bit (bv, length - ii, bit_vector_bit (bv, ii - 1));
4677 set_bit_vector_bit (bv, ii - 1, swap);
4678 --ii;
4679 }
4680 }
4681 else
4682 {
4683 assert (NILP (sequence));
4684 }
4685
4686 return sequence;
1824 } 4687 }
1825 4688
1826 DEFUN ("reverse", Freverse, 1, 1, 0, /* 4689 DEFUN ("reverse", Freverse, 1, 1, 0, /*
1827 Reverse LIST, copying. Return the beginning of the reversed list. 4690 Reverse SEQUENCE, copying. Return the reversed sequence.
1828 See also the function `nreverse', which is used more often. 4691 See also the function `nreverse', which is used more often.
1829 */ 4692 */
1830 (list)) 4693 (sequence))
1831 { 4694 {
1832 Lisp_Object reversed_list = Qnil; 4695 Lisp_Object result = Qnil;
1833 EXTERNAL_LIST_LOOP_2 (elt, list) 4696
1834 { 4697 CHECK_SEQUENCE (sequence);
1835 reversed_list = Fcons (elt, reversed_list); 4698
1836 } 4699 if (CONSP (sequence))
1837 return reversed_list; 4700 {
4701 EXTERNAL_LIST_LOOP_2 (elt, sequence)
4702 {
4703 result = Fcons (elt, result);
4704 }
4705 }
4706 else if (VECTORP (sequence))
4707 {
4708 Elemcount length = XVECTOR_LENGTH (sequence), ii = length;
4709 Lisp_Object *staging = alloca_array (Lisp_Object, length);
4710
4711 while (ii > 0)
4712 {
4713 staging[length - ii] = XVECTOR_DATA (sequence) [ii - 1];
4714 --ii;
4715 }
4716
4717 result = Fvector (length, staging);
4718 }
4719 else if (STRINGP (sequence))
4720 {
4721 Elemcount length = XSTRING_LENGTH (sequence);
4722 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length;
4723 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length;
4724
4725 while (cursor < endp)
4726 {
4727 staging_end -= itext_ichar_len (cursor);
4728 itext_copy_ichar (cursor, staging_end);
4729 INC_IBYTEPTR (cursor);
4730 }
4731
4732 assert (staging == staging_end);
4733
4734 result = make_string (staging, length);
4735 }
4736 else if (BIT_VECTORP (sequence))
4737 {
4738 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence), *res;
4739 Elemcount length = bit_vector_length (bv), ii = length;
4740
4741 result = make_bit_vector (length, Qzero);
4742 res = XBIT_VECTOR (result);
4743
4744 while (ii > 0)
4745 {
4746 set_bit_vector_bit (res, length - ii, bit_vector_bit (bv, ii - 1));
4747 --ii;
4748 }
4749 }
4750 else
4751 {
4752 assert (NILP (sequence));
4753 }
4754
4755 return result;
1838 } 4756 }
1839 4757
1840 static Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
1841 Lisp_Object lisp_arg,
1842 int (*pred_fn) (Lisp_Object, Lisp_Object,
1843 Lisp_Object lisp_arg));
1844
1845 /* The sort function should return > 0 if OBJ1 < OBJ2, < 0 otherwise.
1846 NOTE: This is backwards from the way qsort() works. */
1847
1848 Lisp_Object 4758 Lisp_Object
1849 list_sort (Lisp_Object list,
1850 Lisp_Object lisp_arg,
1851 int (*pred_fn) (Lisp_Object obj1, Lisp_Object obj2,
1852 Lisp_Object lisp_arg))
1853 {
1854 struct gcpro gcpro1, gcpro2, gcpro3;
1855 Lisp_Object back, tem;
1856 Lisp_Object front = list;
1857 Lisp_Object len = Flength (list);
1858
1859 if (XINT (len) < 2)
1860 return list;
1861
1862 len = make_int (XINT (len) / 2 - 1);
1863 tem = Fnthcdr (len, list);
1864 back = Fcdr (tem);
1865 Fsetcdr (tem, Qnil);
1866
1867 GCPRO3 (front, back, lisp_arg);
1868 front = list_sort (front, lisp_arg, pred_fn);
1869 back = list_sort (back, lisp_arg, pred_fn);
1870 UNGCPRO;
1871 return list_merge (front, back, lisp_arg, pred_fn);
1872 }
1873
1874
1875 static int
1876 merge_pred_function (Lisp_Object obj1, Lisp_Object obj2,
1877 Lisp_Object pred)
1878 {
1879 Lisp_Object tmp;
1880
1881 /* prevents the GC from happening in call2 */
1882 /* Emacs' GC doesn't actually relocate pointers, so this probably
1883 isn't strictly necessary */
1884 int speccount = begin_gc_forbidden ();
1885 tmp = call2 (pred, obj1, obj2);
1886 unbind_to (speccount);
1887
1888 if (NILP (tmp))
1889 return -1;
1890 else
1891 return 1;
1892 }
1893
1894 DEFUN ("sort", Fsort, 2, 2, 0, /*
1895 Sort LIST, stably, comparing elements using PREDICATE.
1896 Returns the sorted list. LIST is modified by side effects.
1897 PREDICATE is called with two elements of LIST, and should return T
1898 if the first element is "less" than the second.
1899 */
1900 (list, predicate))
1901 {
1902 return list_sort (list, predicate, merge_pred_function);
1903 }
1904
1905 Lisp_Object
1906 merge (Lisp_Object org_l1, Lisp_Object org_l2,
1907 Lisp_Object pred)
1908 {
1909 return list_merge (org_l1, org_l2, pred, merge_pred_function);
1910 }
1911
1912
1913 static Lisp_Object
1914 list_merge (Lisp_Object org_l1, Lisp_Object org_l2, 4759 list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
1915 Lisp_Object lisp_arg, 4760 check_test_func_t check_merge,
1916 int (*pred_fn) (Lisp_Object, Lisp_Object, Lisp_Object lisp_arg)) 4761 Lisp_Object predicate, Lisp_Object key)
1917 { 4762 {
1918 Lisp_Object value; 4763 Lisp_Object value;
1919 Lisp_Object tail; 4764 Lisp_Object tail;
1920 Lisp_Object tem; 4765 Lisp_Object tem;
1921 Lisp_Object l1, l2; 4766 Lisp_Object l1, l2;
1922 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; 4767 Lisp_Object tortoises[2];
4768 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4769 int l1_count = 0, l2_count = 0;
1923 4770
1924 l1 = org_l1; 4771 l1 = org_l1;
1925 l2 = org_l2; 4772 l2 = org_l2;
1926 tail = Qnil; 4773 tail = Qnil;
1927 value = Qnil; 4774 value = Qnil;
1928 4775 tortoises[0] = org_l1;
1929 /* It is sufficient to protect org_l1 and org_l2. 4776 tortoises[1] = org_l2;
1930 When l1 and l2 are updated, we copy the new values 4777
1931 back into the org_ vars. */ 4778 /* It is sufficient to protect org_l1 and org_l2. When l1 and l2 are
1932 4779 updated, we copy the new values back into the org_ vars. */
1933 GCPRO4 (org_l1, org_l2, lisp_arg, value); 4780
4781 GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]);
4782 gcpro5.nvars = 2;
1934 4783
1935 while (1) 4784 while (1)
1936 { 4785 {
1937 if (NILP (l1)) 4786 if (NILP (l1))
1938 { 4787 {
1949 return l1; 4798 return l1;
1950 Fsetcdr (tail, l1); 4799 Fsetcdr (tail, l1);
1951 return value; 4800 return value;
1952 } 4801 }
1953 4802
1954 if (((*pred_fn) (Fcar (l2), Fcar (l1), lisp_arg)) < 0) 4803 if (check_merge (predicate, key, Fcar (l2), Fcar (l1)) == 0)
1955 { 4804 {
1956 tem = l1; 4805 tem = l1;
1957 l1 = Fcdr (l1); 4806 l1 = Fcdr (l1);
1958 org_l1 = l1; 4807 org_l1 = l1;
4808
4809 if (l1_count++ > CIRCULAR_LIST_SUSPICION_LENGTH)
4810 {
4811 if (l1_count & 1)
4812 {
4813 if (!CONSP (tortoises[0]))
4814 {
4815 mapping_interaction_error (Qmerge, tortoises[0]);
4816 }
4817
4818 tortoises[0] = XCDR (tortoises[0]);
4819 }
4820
4821 if (EQ (org_l1, tortoises[0]))
4822 {
4823 signal_circular_list_error (org_l1);
4824 }
4825 }
1959 } 4826 }
1960 else 4827 else
1961 { 4828 {
1962 tem = l2; 4829 tem = l2;
1963 l2 = Fcdr (l2); 4830 l2 = Fcdr (l2);
1964 org_l2 = l2; 4831 org_l2 = l2;
1965 } 4832
4833 if (l2_count++ > CIRCULAR_LIST_SUSPICION_LENGTH)
4834 {
4835 if (l2_count & 1)
4836 {
4837 if (!CONSP (tortoises[1]))
4838 {
4839 mapping_interaction_error (Qmerge, tortoises[1]);
4840 }
4841
4842 tortoises[1] = XCDR (tortoises[1]);
4843 }
4844
4845 if (EQ (org_l2, tortoises[1]))
4846 {
4847 signal_circular_list_error (org_l2);
4848 }
4849 }
4850 }
4851
1966 if (NILP (tail)) 4852 if (NILP (tail))
1967 value = tem; 4853 value = tem;
1968 else 4854 else
1969 Fsetcdr (tail, tem); 4855 Fsetcdr (tail, tem);
4856
1970 tail = tem; 4857 tail = tem;
1971 } 4858 }
1972 } 4859 }
1973 4860
4861 static void
4862 array_merge (Lisp_Object *dest, Elemcount dest_len,
4863 Lisp_Object *front, Elemcount front_len,
4864 Lisp_Object *back, Elemcount back_len,
4865 check_test_func_t check_merge,
4866 Lisp_Object predicate, Lisp_Object key)
4867 {
4868 Elemcount ii, fronting, backing;
4869 Lisp_Object *front_staging = front;
4870 Lisp_Object *back_staging = back;
4871 struct gcpro gcpro1, gcpro2;
4872
4873 assert (dest_len == (back_len + front_len));
4874
4875 if (0 == dest_len)
4876 {
4877 return;
4878 }
4879
4880 if (front >= dest && front < (dest + dest_len))
4881 {
4882 front_staging = alloca_array (Lisp_Object, front_len);
4883
4884 for (ii = 0; ii < front_len; ++ii)
4885 {
4886 front_staging[ii] = front[ii];
4887 }
4888 }
4889
4890 if (back >= dest && back < (dest + dest_len))
4891 {
4892 back_staging = alloca_array (Lisp_Object, back_len);
4893
4894 for (ii = 0; ii < back_len; ++ii)
4895 {
4896 back_staging[ii] = back[ii];
4897 }
4898 }
4899
4900 GCPRO2 (front_staging[0], back_staging[0]);
4901 gcpro1.nvars = front_len;
4902 gcpro2.nvars = back_len;
4903
4904 for (ii = fronting = backing = 0; ii < dest_len; ++ii)
4905 {
4906 if (fronting >= front_len)
4907 {
4908 while (ii < dest_len)
4909 {
4910 dest[ii] = back_staging[backing];
4911 ++ii, ++backing;
4912 }
4913 UNGCPRO;
4914 return;
4915 }
4916
4917 if (backing >= back_len)
4918 {
4919 while (ii < dest_len)
4920 {
4921 dest[ii] = front_staging[fronting];
4922 ++ii, ++fronting;
4923 }
4924 UNGCPRO;
4925 return;
4926 }
4927
4928 if (check_merge (predicate, key, back_staging[backing],
4929 front_staging[fronting]) == 0)
4930 {
4931 dest[ii] = front_staging[fronting];
4932 ++fronting;
4933 }
4934 else
4935 {
4936 dest[ii] = back_staging[backing];
4937 ++backing;
4938 }
4939 }
4940
4941 UNGCPRO;
4942 }
4943
4944 static Lisp_Object
4945 list_array_merge_into_list (Lisp_Object list,
4946 Lisp_Object *array, Elemcount array_len,
4947 check_test_func_t check_merge,
4948 Lisp_Object predicate, Lisp_Object key,
4949 Boolint reverse_order)
4950 {
4951 Lisp_Object tail = Qnil, value = Qnil, tortoise = list;
4952 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4953 Elemcount array_index = 0;
4954 int looped = 0;
4955
4956 GCPRO4 (list, tail, value, tortoise);
4957
4958 while (1)
4959 {
4960 if (NILP (list))
4961 {
4962 UNGCPRO;
4963
4964 if (NILP (tail))
4965 {
4966 return Flist (array_len, array);
4967 }
4968
4969 Fsetcdr (tail, Flist (array_len - array_index, array + array_index));
4970 return value;
4971 }
4972
4973 if (array_index >= array_len)
4974 {
4975 UNGCPRO;
4976 if (NILP (tail))
4977 {
4978 return list;
4979 }
4980
4981 Fsetcdr (tail, list);
4982 return value;
4983 }
4984
4985
4986 if (reverse_order ?
4987 check_merge (predicate, key, Fcar (list), array [array_index])
4988 : !check_merge (predicate, key, array [array_index], Fcar (list)))
4989 {
4990 if (NILP (tail))
4991 {
4992 value = tail = list;
4993 }
4994 else
4995 {
4996 Fsetcdr (tail, list);
4997 tail = XCDR (tail);
4998 }
4999
5000 list = Fcdr (list);
5001 }
5002 else
5003 {
5004 if (NILP (tail))
5005 {
5006 value = tail = Fcons (array [array_index], Qnil);
5007 }
5008 else
5009 {
5010 Fsetcdr (tail, Fcons (array [array_index], tail));
5011 tail = XCDR (tail);
5012 }
5013 ++array_index;
5014 }
5015
5016 if (++looped > CIRCULAR_LIST_SUSPICION_LENGTH)
5017 {
5018 if (looped & 1)
5019 {
5020 tortoise = XCDR (tortoise);
5021 }
5022
5023 if (EQ (list, tortoise))
5024 {
5025 signal_circular_list_error (list);
5026 }
5027 }
5028 }
5029 }
5030
5031 static void
5032 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len,
5033 Lisp_Object list_one, Lisp_Object list_two,
5034 check_test_func_t check_merge,
5035 Lisp_Object predicate, Lisp_Object key)
5036 {
5037 Elemcount output_index = 0;
5038
5039 while (output_index < output_len)
5040 {
5041 if (NILP (list_one))
5042 {
5043 while (output_index < output_len)
5044 {
5045 output [output_index] = Fcar (list_two);
5046 list_two = Fcdr (list_two), ++output_index;
5047 }
5048 return;
5049 }
5050
5051 if (NILP (list_two))
5052 {
5053 while (output_index < output_len)
5054 {
5055 output [output_index] = Fcar (list_one);
5056 list_one = Fcdr (list_one), ++output_index;
5057 }
5058 return;
5059 }
5060
5061 if (check_merge (predicate, key, Fcar (list_two), Fcar (list_one))
5062 == 0)
5063 {
5064 output [output_index] = XCAR (list_one);
5065 list_one = XCDR (list_one);
5066 }
5067 else
5068 {
5069 output [output_index] = XCAR (list_two);
5070 list_two = XCDR (list_two);
5071 }
5072
5073 ++output_index;
5074
5075 /* No need to check for circularity. */
5076 }
5077 }
5078
5079 static void
5080 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len,
5081 Lisp_Object list,
5082 Lisp_Object *array, Elemcount array_len,
5083 check_test_func_t check_merge,
5084 Lisp_Object predicate, Lisp_Object key,
5085 Boolint reverse_order)
5086 {
5087 Elemcount output_index = 0, array_index = 0;
5088
5089 while (output_index < output_len)
5090 {
5091 if (NILP (list))
5092 {
5093 if (array_len - array_index != output_len - output_index)
5094 {
5095 mapping_interaction_error (Qmerge, list);
5096 }
5097
5098 while (array_index < array_len)
5099 {
5100 output [output_index++] = array [array_index++];
5101 }
5102
5103 return;
5104 }
5105
5106 if (array_index >= array_len)
5107 {
5108 while (output_index < output_len)
5109 {
5110 output [output_index++] = Fcar (list);
5111 list = Fcdr (list);
5112 }
5113
5114 return;
5115 }
5116
5117 if (reverse_order ?
5118 check_merge (predicate, key, Fcar (list), array [array_index]) :
5119 !check_merge (predicate, key, array [array_index], Fcar (list)))
5120 {
5121 output [output_index] = XCAR (list);
5122 list = XCDR (list);
5123 }
5124 else
5125 {
5126 output [output_index] = array [array_index];
5127 ++array_index;
5128 }
5129
5130 ++output_index;
5131 }
5132 }
5133
5134 #define STRING_DATA_TO_OBJECT_ARRAY(strdata, c_array, counter, len) \
5135 do { \
5136 c_array = alloca_array (Lisp_Object, len); \
5137 for (counter = 0; counter < len; ++counter) \
5138 { \
5139 c_array[counter] = make_char (itext_ichar (strdata)); \
5140 INC_IBYTEPTR (strdata); \
5141 } \
5142 } while (0)
5143
5144 #define BIT_VECTOR_TO_OBJECT_ARRAY(v, c_array, counter, len) do { \
5145 c_array = alloca_array (Lisp_Object, len); \
5146 for (counter = 0; counter < len; ++counter) \
5147 { \
5148 c_array[counter] = make_int (bit_vector_bit (v, counter)); \
5149 } \
5150 } while (0)
5151
5152 DEFUN ("merge", Fmerge, 4, MANY, 0, /*
5153 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence.
5154
5155 TYPE is the type of sequence to return. PREDICATE is a `less-than'
5156 predicate on the elements.
5157
5158 Optional keyword argument KEY is a function used to extract an object to be
5159 used for comparison from each element of SEQUENCE-ONE and SEQUENCE-TWO.
5160
5161 arguments: (TYPE SEQUENCE-ONE SEQUENCE-TWO PREDICATE &key (KEY #'IDENTITY))
5162 */
5163 (int nargs, Lisp_Object *args))
5164 {
5165 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2],
5166 predicate = args[3], result = Qnil;
5167 check_test_func_t check_merge = NULL;
5168
5169 PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL);
5170
5171 CHECK_SEQUENCE (sequence_one);
5172 CHECK_SEQUENCE (sequence_two);
5173
5174 CHECK_KEY_ARGUMENT (key);
5175
5176 check_merge = get_merge_predicate (predicate, key);
5177
5178 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two)))
5179 {
5180 if (NILP (sequence_two))
5181 {
5182 result = Fappend (2, args + 1);
5183 }
5184 else if (NILP (sequence_one))
5185 {
5186 args[3] = Qnil; /* Overwriting PREDICATE, and losing its GC
5187 protection, but that doesn't matter. */
5188 result = Fappend (2, args + 2);
5189 }
5190 else if (CONSP (sequence_one) && CONSP (sequence_two))
5191 {
5192 result = list_merge (sequence_one, sequence_two, check_merge,
5193 predicate, key);
5194 }
5195 else
5196 {
5197 Lisp_Object *array_storage, swap;
5198 Elemcount array_length, i;
5199 Boolint reverse_order = 0;
5200
5201 if (!CONSP (sequence_one))
5202 {
5203 /* Make sequence_one the cons, sequence_two the array: */
5204 swap = sequence_one;
5205 sequence_one = sequence_two;
5206 sequence_two = swap;
5207 reverse_order = 1;
5208 }
5209
5210 if (VECTORP (sequence_two))
5211 {
5212 array_storage = XVECTOR_DATA (sequence_two);
5213 array_length = XVECTOR_LENGTH (sequence_two);
5214 }
5215 else if (STRINGP (sequence_two))
5216 {
5217 Ibyte *strdata = XSTRING_DATA (sequence_two);
5218 array_length = string_char_length (sequence_two);
5219 /* No need to GCPRO, characters are immediate. */
5220 STRING_DATA_TO_OBJECT_ARRAY (strdata, array_storage, i,
5221 array_length);
5222
5223 }
5224 else
5225 {
5226 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence_two);
5227 array_length = bit_vector_length (v);
5228 /* No need to GCPRO, fixnums are immediate. */
5229 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length);
5230 }
5231
5232 result = list_array_merge_into_list (sequence_one,
5233 array_storage, array_length,
5234 check_merge, predicate, key,
5235 reverse_order);
5236 }
5237 }
5238 else
5239 {
5240 Elemcount sequence_one_len = XINT (Flength (sequence_one)),
5241 sequence_two_len = XINT (Flength (sequence_two)), i;
5242 Elemcount output_len = 1 + sequence_one_len + sequence_two_len;
5243 Lisp_Object *output = alloca_array (Lisp_Object, output_len),
5244 *sequence_one_storage = NULL, *sequence_two_storage = NULL;
5245 Boolint do_coerce = !(EQ (type, Qvector) || EQ (type, Qstring)
5246 || EQ (type, Qbit_vector) || EQ (type, Qlist));
5247 Ibyte *strdata = NULL;
5248 Lisp_Bit_Vector *v = NULL;
5249 struct gcpro gcpro1;
5250
5251 output[0] = do_coerce ? Qlist : type;
5252 for (i = 1; i < output_len; ++i)
5253 {
5254 output[i] = Qnil;
5255 }
5256
5257 GCPRO1 (output[0]);
5258 gcpro1.nvars = output_len;
5259
5260 if (VECTORP (sequence_one))
5261 {
5262 sequence_one_storage = XVECTOR_DATA (sequence_one);
5263 }
5264 else if (STRINGP (sequence_one))
5265 {
5266 strdata = XSTRING_DATA (sequence_one);
5267 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_one_storage,
5268 i, sequence_one_len);
5269 }
5270 else if (BIT_VECTORP (sequence_one))
5271 {
5272 v = XBIT_VECTOR (sequence_one);
5273 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_one_storage,
5274 i, sequence_one_len);
5275 }
5276
5277 if (VECTORP (sequence_two))
5278 {
5279 sequence_two_storage = XVECTOR_DATA (sequence_two);
5280 }
5281 else if (STRINGP (sequence_two))
5282 {
5283 strdata = XSTRING_DATA (sequence_two);
5284 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_two_storage,
5285 i, sequence_two_len);
5286 }
5287 else if (BIT_VECTORP (sequence_two))
5288 {
5289 v = XBIT_VECTOR (sequence_two);
5290 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_two_storage,
5291 i, sequence_two_len);
5292 }
5293
5294 if (LISTP (sequence_one) && LISTP (sequence_two))
5295 {
5296 list_list_merge_into_array (output + 1, output_len - 1,
5297 sequence_one, sequence_two,
5298 check_merge, predicate, key);
5299 }
5300 else if (LISTP (sequence_one))
5301 {
5302 list_array_merge_into_array (output + 1, output_len - 1,
5303 sequence_one,
5304 sequence_two_storage,
5305 sequence_two_len,
5306 check_merge, predicate, key, 0);
5307 }
5308 else if (LISTP (sequence_two))
5309 {
5310 list_array_merge_into_array (output + 1, output_len - 1,
5311 sequence_two,
5312 sequence_one_storage,
5313 sequence_one_len,
5314 check_merge, predicate, key, 1);
5315 }
5316 else
5317 {
5318 array_merge (output + 1, output_len - 1,
5319 sequence_one_storage, sequence_one_len,
5320 sequence_two_storage, sequence_two_len,
5321 check_merge, predicate,
5322 key);
5323 }
5324
5325 result = Ffuncall (output_len, output);
5326
5327 if (do_coerce)
5328 {
5329 result = call2 (Qcoerce, result, type);
5330 }
5331
5332 UNGCPRO;
5333 }
5334
5335 return result;
5336 }
5337
5338 Lisp_Object
5339 list_sort (Lisp_Object list, check_test_func_t check_merge,
5340 Lisp_Object predicate, Lisp_Object key)
5341 {
5342 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5343 Lisp_Object back, tem;
5344 Lisp_Object front = list;
5345 Lisp_Object len = Flength (list);
5346
5347 if (XINT (len) < 2)
5348 return list;
5349
5350 len = make_int (XINT (len) / 2 - 1);
5351 tem = Fnthcdr (len, list);
5352 back = Fcdr (tem);
5353 Fsetcdr (tem, Qnil);
5354
5355 GCPRO4 (front, back, predicate, key);
5356 front = list_sort (front, check_merge, predicate, key);
5357 back = list_sort (back, check_merge, predicate, key);
5358
5359 RETURN_UNGCPRO (list_merge (front, back, check_merge, predicate, key));
5360 }
5361
5362 static void
5363 array_sort (Lisp_Object *array, Elemcount array_len,
5364 check_test_func_t check_merge,
5365 Lisp_Object predicate, Lisp_Object key)
5366 {
5367 Elemcount split;
5368
5369 if (array_len < 2)
5370 return;
5371
5372 split = array_len / 2;
5373
5374 array_sort (array, split, check_merge, predicate, key);
5375 array_sort (array + split, array_len - split, check_merge, predicate,
5376 key);
5377 array_merge (array, array_len, array, split, array + split,
5378 array_len - split, check_merge, predicate, key);
5379 }
5380
5381 DEFUN ("sort*", FsortX, 2, MANY, 0, /*
5382 Sort SEQUENCE, comparing elements using PREDICATE.
5383 Returns the sorted sequence. SEQUENCE is modified by side effect.
5384
5385 PREDICATE is called with two elements of SEQUENCE, and should return t if
5386 the first element is `less' than the second.
5387
5388 Optional keyword argument KEY is a function used to extract an object to be
5389 used for comparison from each element of SEQUENCE.
5390
5391 In this implementation, sorting is always stable; but call `stable-sort' if
5392 this stability is important to you, other implementations may not make the
5393 same guarantees.
5394
5395 arguments: (SEQUENCE PREDICATE &key (KEY #'IDENTITY))
5396 */
5397 (int nargs, Lisp_Object *args))
5398 {
5399 Lisp_Object sequence = args[0], predicate = args[1];
5400 Lisp_Object *sequence_carray;
5401 check_test_func_t check_merge = NULL;
5402 Elemcount sequence_len, i;
5403
5404 PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL);
5405
5406 CHECK_SEQUENCE (sequence);
5407
5408 CHECK_KEY_ARGUMENT (key);
5409
5410 check_merge = get_merge_predicate (predicate, key);
5411
5412 if (LISTP (sequence))
5413 {
5414 sequence = list_sort (sequence, check_merge, predicate, key);
5415 }
5416 else if (VECTORP (sequence))
5417 {
5418 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence),
5419 check_merge, predicate, key);
5420 }
5421 else if (STRINGP (sequence))
5422 {
5423 Ibyte *strdata = XSTRING_DATA (sequence);
5424
5425 sequence_len = string_char_length (sequence);
5426
5427 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len);
5428
5429 /* No GCPRO necessary, characters are immediate. */
5430 array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
5431
5432 strdata = XSTRING_DATA (sequence);
5433
5434 CHECK_LISP_WRITEABLE (sequence);
5435 for (i = 0; i < sequence_len; ++i)
5436 {
5437 strdata += set_itext_ichar (strdata, XCHAR (sequence_carray[i]));
5438 }
5439
5440 init_string_ascii_begin (sequence);
5441 bump_string_modiff (sequence);
5442 sledgehammer_check_ascii_begin (sequence);
5443 }
5444 else if (BIT_VECTORP (sequence))
5445 {
5446 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
5447 sequence_len = bit_vector_length (v);
5448
5449 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len);
5450
5451 /* No GCPRO necessary, bits are immediate. */
5452 array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
5453
5454 for (i = 0; i < sequence_len; ++i)
5455 {
5456 set_bit_vector_bit (v, i, XINT (sequence_carray [i]));
5457 }
5458 }
5459
5460 return sequence;
5461 }
1974 5462
1975 /************************************************************************/ 5463 /************************************************************************/
1976 /* property-list functions */ 5464 /* property-list functions */
1977 /************************************************************************/ 5465 /************************************************************************/
1978 5466
2718 DEFUN ("get", Fget, 2, 3, 0, /* 6206 DEFUN ("get", Fget, 2, 3, 0, /*
2719 Return the value of OBJECT's PROPERTY property. 6207 Return the value of OBJECT's PROPERTY property.
2720 This is the last VALUE stored with `(put OBJECT PROPERTY VALUE)'. 6208 This is the last VALUE stored with `(put OBJECT PROPERTY VALUE)'.
2721 If there is no such property, return optional third arg DEFAULT 6209 If there is no such property, return optional third arg DEFAULT
2722 \(which defaults to `nil'). OBJECT can be a symbol, string, extent, 6210 \(which defaults to `nil'). OBJECT can be a symbol, string, extent,
2723 face, or glyph. See also `put', `remprop', and `object-plist'. 6211 face, glyph, or process. See also `put', `remprop', `object-plist', and
6212 `object-setplist'.
2724 */ 6213 */
2725 (object, property, default_)) 6214 (object, property, default_))
2726 { 6215 {
2727 /* Various places in emacs call Fget() and expect it not to quit, 6216 /* Various places in emacs call Fget() and expect it not to quit,
2728 so don't quit. */ 6217 so don't quit. */
2762 return value; 6251 return value;
2763 } 6252 }
2764 6253
2765 DEFUN ("remprop", Fremprop, 2, 2, 0, /* 6254 DEFUN ("remprop", Fremprop, 2, 2, 0, /*
2766 Remove, from OBJECT's property list, PROPERTY and its corresponding value. 6255 Remove, from OBJECT's property list, PROPERTY and its corresponding value.
2767 OBJECT can be a symbol, string, extent, face, or glyph. Return non-nil 6256 OBJECT can be a symbol, string, extent, face, glyph, or process.
2768 if the property list was actually modified (i.e. if PROPERTY was present 6257 Return non-nil if the property list was actually modified (i.e. if PROPERTY
2769 in the property list). See also `get', `put', and `object-plist'. 6258 was present in the property list). See also `get', `put', `object-plist',
6259 and `object-setplist'.
2770 */ 6260 */
2771 (object, property)) 6261 (object, property))
2772 { 6262 {
2773 int ret = 0; 6263 int ret = 0;
2774 6264
2800 else 6290 else
2801 invalid_operation ("Object type has no properties", object); 6291 invalid_operation ("Object type has no properties", object);
2802 6292
2803 return Qnil; 6293 return Qnil;
2804 } 6294 }
6295
6296 DEFUN ("object-setplist", Fobject_setplist, 2, 2, 0, /*
6297 Set OBJECT's property list to NEWPLIST, and return NEWPLIST.
6298 For a symbol, this is equivalent to `setplist'.
6299
6300 OBJECT can be a symbol or a process, other objects with visible plists do
6301 not allow their modification with `object-setplist'.
6302 */
6303 (object, newplist))
6304 {
6305 if (LRECORDP (object) && XRECORD_LHEADER_IMPLEMENTATION (object)->setplist)
6306 {
6307 return XRECORD_LHEADER_IMPLEMENTATION (object)->setplist (object,
6308 newplist);
6309 }
6310
6311 invalid_operation ("Not possible to set object's plist", object);
6312 return Qnil;
6313 }
6314
2805 6315
2806 6316
2807 static Lisp_Object 6317 static Lisp_Object
2808 tweaked_internal_equal (Lisp_Object obj1, Lisp_Object obj2, 6318 tweaked_internal_equal (Lisp_Object obj1, Lisp_Object obj2,
2809 Lisp_Object depth) 6319 Lisp_Object depth)
2832 } 6342 }
2833 6343
2834 int 6344 int
2835 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 6345 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2836 { 6346 {
2837 if (depth > 200) 6347 if (depth + lisp_eval_depth > max_lisp_eval_depth)
2838 stack_overflow ("Stack overflow in equal", Qunbound); 6348 stack_overflow ("Stack overflow in equal", Qunbound);
2839 QUIT; 6349 QUIT;
2840 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2)) 6350 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2))
2841 return 1; 6351 return 1;
2842 /* Note that (equal 20 20.0) should be nil */ 6352 /* Note that (equal 20 20.0) should be nil */
2877 } 6387 }
2878 6388
2879 int 6389 int
2880 internal_equalp (Lisp_Object obj1, Lisp_Object obj2, int depth) 6390 internal_equalp (Lisp_Object obj1, Lisp_Object obj2, int depth)
2881 { 6391 {
2882 if (depth > 200) 6392 if (depth + lisp_eval_depth > max_lisp_eval_depth)
2883 stack_overflow ("Stack overflow in equalp", Qunbound); 6393 stack_overflow ("Stack overflow in equalp", Qunbound);
2884 QUIT; 6394 QUIT;
2885 6395
2886 /* 1. Objects that are `eq' are equal. This will catch the common case 6396 /* 1. Objects that are `eq' are equal. This will catch the common case
2887 of two equal fixnums or the same object seen twice. */ 6397 of two equal fixnums or the same object seen twice. */
2945 return internal_equalp (obj1, obj2, depth); 6455 return internal_equalp (obj1, obj2, depth);
2946 else 6456 else
2947 return internal_equal (obj1, obj2, depth); 6457 return internal_equal (obj1, obj2, depth);
2948 } 6458 }
2949 6459
2950 /* Note that we may be calling sub-objects that will use
2951 internal_equal() (instead of internal_old_equal()). Oh well.
2952 We will get an Ebola note if there's any possibility of confusion,
2953 but that seems unlikely. */
2954
2955 static int
2956 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
2957 {
2958 if (depth > 200)
2959 stack_overflow ("Stack overflow in equal", Qunbound);
2960 QUIT;
2961 if (HACKEQ_UNSAFE (obj1, obj2))
2962 return 1;
2963 /* Note that (equal 20 20.0) should be nil */
2964 if (XTYPE (obj1) != XTYPE (obj2))
2965 return 0;
2966
2967 return internal_equal (obj1, obj2, depth);
2968 }
2969
2970 DEFUN ("equal", Fequal, 2, 2, 0, /* 6460 DEFUN ("equal", Fequal, 2, 2, 0, /*
2971 Return t if two Lisp objects have similar structure and contents. 6461 Return t if two Lisp objects have similar structure and contents.
2972 They must have the same data type. 6462 They must have the same data type.
2973 Conses are compared by comparing the cars and the cdrs. 6463 Conses are compared by comparing the cars and the cdrs.
2974 Vectors and strings are compared element by element. 6464 Vectors and strings are compared element by element.
3008 (object1, object2)) 6498 (object1, object2))
3009 { 6499 {
3010 return internal_equalp (object1, object2, 0) ? Qt : Qnil; 6500 return internal_equalp (object1, object2, 0) ? Qt : Qnil;
3011 } 6501 }
3012 6502
6503 #ifdef SUPPORT_CONFOUNDING_FUNCTIONS
6504
6505 /* Note that we may be calling sub-objects that will use
6506 internal_equal() (instead of internal_old_equal()). Oh well.
6507 We will get an Ebola note if there's any possibility of confusion,
6508 but that seems unlikely. */
6509
6510 static int
6511 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
6512 {
6513 if (depth + lisp_eval_depth > max_lisp_eval_depth)
6514 stack_overflow ("Stack overflow in equal", Qunbound);
6515 QUIT;
6516 if (HACKEQ_UNSAFE (obj1, obj2))
6517 return 1;
6518 /* Note that (equal 20 20.0) should be nil */
6519 if (XTYPE (obj1) != XTYPE (obj2))
6520 return 0;
6521
6522 return internal_equal (obj1, obj2, depth);
6523 }
6524
6525 DEFUN ("old-member", Fold_member, 2, 2, 0, /*
6526 Return non-nil if ELT is an element of LIST. Comparison done with `old-equal'.
6527 The value is actually the tail of LIST whose car is ELT.
6528 This function is provided only for byte-code compatibility with v19.
6529 Do not use it.
6530 */
6531 (elt, list))
6532 {
6533 EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
6534 {
6535 if (internal_old_equal (elt, list_elt, 0))
6536 return tail;
6537 }
6538 return Qnil;
6539 }
6540
6541 DEFUN ("old-memq", Fold_memq, 2, 2, 0, /*
6542 Return non-nil if ELT is an element of LIST. Comparison done with `old-eq'.
6543 The value is actually the tail of LIST whose car is ELT.
6544 This function is provided only for byte-code compatibility with v19.
6545 Do not use it.
6546 */
6547 (elt, list))
6548 {
6549 EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
6550 {
6551 if (HACKEQ_UNSAFE (elt, list_elt))
6552 return tail;
6553 }
6554 return Qnil;
6555 }
6556
6557 DEFUN ("old-assoc", Fold_assoc, 2, 2, 0, /*
6558 Return non-nil if KEY is `old-equal' to the car of an element of ALIST.
6559 The value is actually the element of ALIST whose car equals KEY.
6560 */
6561 (key, alist))
6562 {
6563 /* This function can GC. */
6564 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
6565 {
6566 if (internal_old_equal (key, elt_car, 0))
6567 return elt;
6568 }
6569 return Qnil;
6570 }
6571
6572 DEFUN ("old-assq", Fold_assq, 2, 2, 0, /*
6573 Return non-nil if KEY is `old-eq' to the car of an element of ALIST.
6574 The value is actually the element of ALIST whose car is KEY.
6575 Elements of ALIST that are not conses are ignored.
6576 This function is provided only for byte-code compatibility with v19.
6577 Do not use it.
6578 */
6579 (key, alist))
6580 {
6581 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
6582 {
6583 if (HACKEQ_UNSAFE (key, elt_car))
6584 return elt;
6585 }
6586 return Qnil;
6587 }
6588
6589 DEFUN ("old-rassoc", Fold_rassoc, 2, 2, 0, /*
6590 Return non-nil if VALUE is `old-equal' to the cdr of an element of ALIST.
6591 The value is actually the element of ALIST whose cdr equals VALUE.
6592 */
6593 (value, alist))
6594 {
6595 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
6596 {
6597 if (internal_old_equal (value, elt_cdr, 0))
6598 return elt;
6599 }
6600 return Qnil;
6601 }
6602
6603 DEFUN ("old-delete", Fold_delete, 2, 2, 0, /*
6604 Delete by side effect any occurrences of ELT as a member of LIST.
6605 The modified LIST is returned. Comparison is done with `old-equal'.
6606 If the first member of LIST is ELT, there is no way to remove it by side
6607 effect; therefore, write `(setq foo (old-delete element foo))' to be sure
6608 of changing the value of `foo'.
6609 */
6610 (elt, list))
6611 {
6612 EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
6613 (internal_old_equal (elt, list_elt, 0)));
6614 return list;
6615 }
6616
6617 DEFUN ("old-delq", Fold_delq, 2, 2, 0, /*
6618 Delete by side effect any occurrences of ELT as a member of LIST.
6619 The modified LIST is returned. Comparison is done with `old-eq'.
6620 If the first member of LIST is ELT, there is no way to remove it by side
6621 effect; therefore, write `(setq foo (old-delq element foo))' to be sure of
6622 changing the value of `foo'.
6623 */
6624 (elt, list))
6625 {
6626 EXTERNAL_LIST_LOOP_DELETE_IF (list_elt, list,
6627 (HACKEQ_UNSAFE (elt, list_elt)));
6628 return list;
6629 }
6630
3013 DEFUN ("old-equal", Fold_equal, 2, 2, 0, /* 6631 DEFUN ("old-equal", Fold_equal, 2, 2, 0, /*
3014 Return t if two Lisp objects have similar structure and contents. 6632 Return t if two Lisp objects have similar structure and contents.
3015 They must have the same data type. 6633 They must have the same data type.
3016 \(Note, however, that an exception is made for characters and integers; 6634 \(Note, however, that an exception is made for characters and integers;
3017 this is known as the "char-int confoundance disease." See `eq' and 6635 this is known as the "char-int confoundance disease." See `eq' and
3022 (object1, object2)) 6640 (object1, object2))
3023 { 6641 {
3024 return internal_old_equal (object1, object2, 0) ? Qt : Qnil; 6642 return internal_old_equal (object1, object2, 0) ? Qt : Qnil;
3025 } 6643 }
3026 6644
6645 DEFUN ("old-eq", Fold_eq, 2, 2, 0, /*
6646 Return t if the two args are (in most cases) the same Lisp object.
6647
6648 Special kludge: A character is considered `old-eq' to its equivalent integer
6649 even though they are not the same object and are in fact of different
6650 types. This is ABSOLUTELY AND UTTERLY HORRENDOUS but is necessary to
6651 preserve byte-code compatibility with v19. This kludge is known as the
6652 \"char-int confoundance disease\" and appears in a number of other
6653 functions with `old-foo' equivalents.
6654
6655 Do not use this function!
6656 */
6657 (object1, object2))
6658 {
6659 /* #### blasphemy */
6660 return HACKEQ_UNSAFE (object1, object2) ? Qt : Qnil;
6661 }
6662
6663 #endif
6664
3027 6665
3028 DEFUN ("fillarray", Ffillarray, 2, 2, 0, /* 6666 static Lisp_Object replace_string_range_1 (Lisp_Object dest,
3029 Destructively modify ARRAY by replacing each element with ITEM. 6667 Lisp_Object start,
3030 ARRAY is a vector, bit vector, or string. 6668 Lisp_Object end,
3031 */ 6669 const Ibyte *source,
3032 (array, item)) 6670 const Ibyte *source_limit,
3033 { 6671 Lisp_Object item);
6672
6673 /* Fill the substring of DEST beginning at START and ending before END with
6674 the character ITEM. If DEST does not have sufficient space for END -
6675 START characters at START, write as many as is possible without changing
6676 the character length of DEST. Update the string modification flag and do
6677 any sledgehammer checks we have turned on.
6678
6679 START must be a Lisp integer. END can be nil, indicating the length of the
6680 string, or a Lisp integer. The condition (<= 0 START END (length DEST))
6681 must hold, or fill_string_range() will signal an error. */
6682 static Lisp_Object
6683 fill_string_range (Lisp_Object dest, Lisp_Object item, Lisp_Object start,
6684 Lisp_Object end)
6685 {
6686 return replace_string_range_1 (dest, start, end, NULL, NULL, item);
6687 }
6688
6689 DEFUN ("fill", Ffill, 2, MANY, 0, /*
6690 Destructively modify SEQUENCE by replacing each element with ITEM.
6691 SEQUENCE is a list, vector, bit vector, or string.
6692
6693 Optional keyword START is the index of the first element of SEQUENCE
6694 to be modified, and defaults to zero. Optional keyword END is the
6695 exclusive upper bound on the elements of SEQUENCE to be modified, and
6696 defaults to the length of SEQUENCE.
6697
6698 arguments: (SEQUENCE ITEM &key (START 0) (END (length SEQUENCE)))
6699 */
6700 (int nargs, Lisp_Object *args))
6701 {
6702 Lisp_Object sequence = args[0];
6703 Lisp_Object item = args[1];
6704 Elemcount starting, ending = EMACS_INT_MAX + 1, ii, len;
6705
6706 PARSE_KEYWORDS (Ffill, nargs, args, 2, (start, end), (start = Qzero));
6707
6708 CHECK_NATNUM (start);
6709 starting = BIGNUMP (start) ? EMACS_INT_MAX + 1 : XINT (start);
6710
6711 if (!NILP (end))
6712 {
6713 CHECK_NATNUM (end);
6714 ending = BIGNUMP (end) ? EMACS_INT_MAX + 1 : XINT (end);
6715 }
6716
3034 retry: 6717 retry:
3035 if (STRINGP (array)) 6718 if (STRINGP (sequence))
3036 { 6719 {
3037 Bytecount old_bytecount = XSTRING_LENGTH (array);
3038 Bytecount new_bytecount;
3039 Bytecount item_bytecount;
3040 Ibyte item_buf[MAX_ICHAR_LEN];
3041 Ibyte *p;
3042 Ibyte *end;
3043
3044 CHECK_CHAR_COERCE_INT (item); 6720 CHECK_CHAR_COERCE_INT (item);
3045 6721 CHECK_LISP_WRITEABLE (sequence);
3046 CHECK_LISP_WRITEABLE (array); 6722
3047 sledgehammer_check_ascii_begin (array); 6723 fill_string_range (sequence, item, start, end);
3048 item_bytecount = set_itext_ichar (item_buf, XCHAR (item)); 6724 }
3049 new_bytecount = item_bytecount * (Bytecount) string_char_length (array); 6725 else if (VECTORP (sequence))
3050 6726 {
3051 resize_string (array, -1, new_bytecount - old_bytecount); 6727 Lisp_Object *p = XVECTOR_DATA (sequence);
3052 6728
3053 for (p = XSTRING_DATA (array), end = p + new_bytecount; 6729 CHECK_LISP_WRITEABLE (sequence);
3054 p < end; 6730 len = XVECTOR_LENGTH (sequence);
3055 p += item_bytecount) 6731
3056 memcpy (p, item_buf, item_bytecount); 6732 check_sequence_range (sequence, start, end, make_int (len));
3057 *p = '\0'; 6733 ending = min (ending, len);
3058 6734
3059 XSET_STRING_ASCII_BEGIN (array, 6735 for (ii = starting; ii < ending; ++ii)
3060 item_bytecount == 1 ? 6736 {
3061 min (new_bytecount, MAX_STRING_ASCII_BEGIN) : 6737 p[ii] = item;
3062 0); 6738 }
3063 bump_string_modiff (array); 6739 }
3064 sledgehammer_check_ascii_begin (array); 6740 else if (BIT_VECTORP (sequence))
3065 } 6741 {
3066 else if (VECTORP (array)) 6742 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
3067 {
3068 Lisp_Object *p = XVECTOR_DATA (array);
3069 Elemcount len = XVECTOR_LENGTH (array);
3070 CHECK_LISP_WRITEABLE (array);
3071 while (len--)
3072 *p++ = item;
3073 }
3074 else if (BIT_VECTORP (array))
3075 {
3076 Lisp_Bit_Vector *v = XBIT_VECTOR (array);
3077 Elemcount len = bit_vector_length (v);
3078 int bit; 6743 int bit;
6744
3079 CHECK_BIT (item); 6745 CHECK_BIT (item);
3080 bit = XINT (item); 6746 bit = XINT (item);
3081 CHECK_LISP_WRITEABLE (array); 6747 CHECK_LISP_WRITEABLE (sequence);
3082 while (len--) 6748 len = bit_vector_length (v);
3083 set_bit_vector_bit (v, len, bit); 6749
6750 check_sequence_range (sequence, start, end, make_int (len));
6751 ending = min (ending, len);
6752
6753 for (ii = starting; ii < ending; ++ii)
6754 {
6755 set_bit_vector_bit (v, ii, bit);
6756 }
6757 }
6758 else if (LISTP (sequence))
6759 {
6760 Elemcount counting = 0;
6761
6762 {
6763 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
6764 {
6765 if (counting >= starting)
6766 {
6767 if (counting < ending)
6768 {
6769 XSETCAR (tail, item);
6770 }
6771 else if (counting == ending)
6772 {
6773 break;
6774 }
6775 }
6776 ++counting;
6777 }
6778 }
6779
6780 if (counting < starting || (counting != ending && !NILP (end)))
6781 {
6782 check_sequence_range (args[0], start, end, Flength (args[0]));
6783 }
3084 } 6784 }
3085 else 6785 else
3086 { 6786 {
3087 array = wrong_type_argument (Qarrayp, array); 6787 sequence = wrong_type_argument (Qsequencep, sequence);
3088 goto retry; 6788 goto retry;
3089 } 6789 }
3090 return array; 6790 return sequence;
3091 } 6791 }
3092 6792
3093 Lisp_Object 6793 Lisp_Object
3094 nconc2 (Lisp_Object arg1, Lisp_Object arg2) 6794 nconc2 (Lisp_Object arg1, Lisp_Object arg2)
3095 { 6795 {
3223 } 6923 }
3224 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ 6924 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */
3225 } 6925 }
3226 6926
3227 6927
6928 /* Replace the substring of DEST beginning at START and ending before END
6929 with the text at SOURCE, which is END - START characters long and
6930 SOURCE_LIMIT - SOURCE octets long. If DEST does not have sufficient
6931 space for END - START characters at START, write as many as is possible
6932 without changing the length of DEST. Update the string modification flag
6933 and do any sledgehammer checks we have turned on in this build.
6934
6935 START must be a Lisp integer. END can be nil, indicating the length of the
6936 string, or a Lisp integer. The condition (<= 0 START END (length DEST))
6937 must hold, or replace_string_range() will signal an error. */
6938 static Lisp_Object
6939 replace_string_range (Lisp_Object dest, Lisp_Object start, Lisp_Object end,
6940 const Ibyte *source, const Ibyte *source_limit)
6941 {
6942 return replace_string_range_1 (dest, start, end, source, source_limit,
6943 Qnil);
6944 }
6945
3228 /* This is the guts of several mapping functions. 6946 /* This is the guts of several mapping functions.
3229 6947
3230 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time, 6948 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time,
3231 taking the elements from SEQUENCES. If VALS is non-NULL, store the 6949 taking the elements from SEQUENCES. If VALS is non-NULL, store the
3232 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is 6950 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is
3233 non-nil, store the results into LISP_VALS, a sequence with sufficient 6951 non-nil, store the results into LISP_VALS, a sequence with sufficient
3234 room for CALL_COUNT results. Else, do not accumulate any result. 6952 room for CALL_COUNT results (but see the documentation of SOME_OR_EVERY.)
6953 Else, do not accumulate any result.
3235 6954
3236 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons, 6955 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons,
3237 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them, 6956 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them,
3238 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off 6957 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off
3239 mapcarX. 6958 mapcarX.
3240 6959
3241 Otherwise, mapcarX signals a wrong-type-error if it encounters a 6960 Otherwise, mapcarX signals an invalid state error (see
3242 non-cons, non-array when traversing SEQUENCES. Common Lisp specifies in 6961 mapping_interaction_error(), above) if it encounters a non-cons,
6962 non-array when traversing SEQUENCES. Common Lisp specifies in
3243 MAPPING-DESTRUCTIVE-INTERACTION that it is an error when FUNCTION 6963 MAPPING-DESTRUCTIVE-INTERACTION that it is an error when FUNCTION
3244 destructively modifies SEQUENCES in a way that might affect the ongoing 6964 destructively modifies SEQUENCES in a way that might affect the ongoing
3245 traversal operation. 6965 traversal operation.
3246 6966
3247 If SOME_OR_EVERY is SOME_OR_EVERY_SOME, return the (possibly multiple) 6967 CALLER is a symbol describing the Lisp-visible function that was called,
3248 values given by FUNCTION the first time it is non-nil, and abandon the 6968 and any errors thrown because SEQUENCES was modified will reflect it.
3249 iterations. LISP_VALS in this case must be an object created by 6969
3250 make_opaque_ptr, dereferenced as pointing to a Lisp object. If 6970 If CALLER is Qsome, return the (possibly multiple) values given by
3251 SOME_OR_EVERY is SOME_OR_EVERY_EVERY, store Qnil at the Lisp_Object 6971 FUNCTION the first time it is non-nil, and abandon the iterations.
3252 pointer address provided by LISP_VALS if FUNCTION gives nil; otherwise 6972 LISP_VALS must be the result of calling STORE_VOID_IN_LISP on the address
3253 leave it alone. */ 6973 of a Lisp object, and the return value will be stored at that address.
3254 6974 If CALLER is Qevery, LISP_VALS must also reflect a pointer to a Lisp
3255 #define SOME_OR_EVERY_NEITHER 0 6975 object, and Qnil will be stored at that address if FUNCTION gives nil;
3256 #define SOME_OR_EVERY_SOME 1 6976 otherwise it will be left alone. */
3257 #define SOME_OR_EVERY_EVERY 2
3258 6977
3259 static void 6978 static void
3260 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals, 6979 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals,
3261 Lisp_Object function, int nsequences, Lisp_Object *sequences, 6980 Lisp_Object function, int nsequences, Lisp_Object *sequences,
3262 int some_or_every) 6981 Lisp_Object caller)
3263 { 6982 {
3264 Lisp_Object called, *args; 6983 Lisp_Object called, *args;
3265 struct gcpro gcpro1, gcpro2; 6984 struct gcpro gcpro1, gcpro2;
6985 Ibyte *lisp_vals_staging = NULL, *cursor = NULL;
3266 int i, j; 6986 int i, j;
3267 enum lrecord_type lisp_vals_type; 6987
3268 6988 assert ((EQ (caller, Qsome) || EQ (caller, Qevery)) ? vals == NULL : 1);
3269 assert (LRECORDP (lisp_vals));
3270 lisp_vals_type = (enum lrecord_type) XRECORD_LHEADER (lisp_vals)->type;
3271 6989
3272 args = alloca_array (Lisp_Object, nsequences + 1); 6990 args = alloca_array (Lisp_Object, nsequences + 1);
3273 args[0] = function; 6991 args[0] = function;
3274 for (i = 1; i <= nsequences; ++i) 6992 for (i = 1; i <= nsequences; ++i)
3275 { 6993 {
3304 gcpro2.nvars = call_count; 7022 gcpro2.nvars = call_count;
3305 7023
3306 for (i = 0; i < call_count; ++i) 7024 for (i = 0; i < call_count; ++i)
3307 { 7025 {
3308 args[1] = vals[i]; 7026 args[1] = vals[i];
3309 vals[i] = Ffuncall (nsequences + 1, args); 7027 vals[i] = IGNORE_MULTIPLE_VALUES (Ffuncall (nsequences + 1, args));
3310 } 7028 }
3311 } 7029 }
3312 else 7030 else
3313 { 7031 {
7032 enum lrecord_type lisp_vals_type = lrecord_type_symbol;
3314 Binbyte *sequence_types = alloca_array (Binbyte, nsequences); 7033 Binbyte *sequence_types = alloca_array (Binbyte, nsequences);
3315 for (j = 0; j < nsequences; ++j) 7034 for (j = 0; j < nsequences; ++j)
3316 { 7035 {
3317 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type; 7036 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type;
3318 } 7037 }
7038
7039 if (!EQ (caller, Qsome) && !EQ (caller, Qevery))
7040 {
7041 assert (LRECORDP (lisp_vals));
7042
7043 lisp_vals_type
7044 = (enum lrecord_type) XRECORD_LHEADER (lisp_vals)->type;
7045
7046 if (lrecord_type_string == lisp_vals_type)
7047 {
7048 lisp_vals_staging = cursor
7049 = alloca_ibytes (call_count * MAX_ICHAR_LEN);
7050 }
7051 else if (ARRAYP (lisp_vals))
7052 {
7053 CHECK_LISP_WRITEABLE (lisp_vals);
7054 }
7055 }
3319 7056
3320 for (i = 0; i < call_count; ++i) 7057 for (i = 0; i < call_count; ++i)
3321 { 7058 {
3322 for (j = 0; j < nsequences; ++j) 7059 for (j = 0; j < nsequences; ++j)
3323 { 7060 {
3325 { 7062 {
3326 case lrecord_type_cons: 7063 case lrecord_type_cons:
3327 { 7064 {
3328 if (!CONSP (sequences[j])) 7065 if (!CONSP (sequences[j]))
3329 { 7066 {
3330 /* This means FUNCTION has probably messed 7067 /* This means FUNCTION has messed around with a cons
3331 around with a cons in one of the sequences, 7068 in one of the sequences, since we checked the
3332 since we checked the type 7069 type (CHECK_SEQUENCE()) and the length and
3333 (CHECK_SEQUENCE()) and the length and
3334 structure (with Flength()) correctly in our 7070 structure (with Flength()) correctly in our
3335 callers. */ 7071 callers. */
3336 dead_wrong_type_argument (Qconsp, sequences[j]); 7072 mapping_interaction_error (caller, sequences[j]);
3337 } 7073 }
3338 args[j + 1] = XCAR (sequences[j]); 7074 args[j + 1] = XCAR (sequences[j]);
3339 sequences[j] = XCDR (sequences[j]); 7075 sequences[j] = XCDR (sequences[j]);
3340 break; 7076 break;
3341 } 7077 }
3364 if (vals != NULL) 7100 if (vals != NULL)
3365 { 7101 {
3366 vals[i] = IGNORE_MULTIPLE_VALUES (called); 7102 vals[i] = IGNORE_MULTIPLE_VALUES (called);
3367 gcpro2.nvars += 1; 7103 gcpro2.nvars += 1;
3368 } 7104 }
3369 else 7105 else if (EQ (Qsome, caller))
3370 { 7106 {
3371 switch (lisp_vals_type) 7107 if (!NILP (IGNORE_MULTIPLE_VALUES (called)))
3372 { 7108 {
3373 case lrecord_type_symbol: 7109 Lisp_Object *result
3374 break; 7110 = (Lisp_Object *) GET_VOID_FROM_LISP (lisp_vals);
3375 case lrecord_type_cons: 7111 *result = called;
3376 { 7112 UNGCPRO;
3377 if (SOME_OR_EVERY_NEITHER == some_or_every) 7113 return;
3378 { 7114 }
3379 called = IGNORE_MULTIPLE_VALUES (called); 7115 }
3380 if (!CONSP (lisp_vals)) 7116 else if (EQ (Qevery, caller))
3381 { 7117 {
3382 /* If FUNCTION has inserted a non-cons non-nil 7118 if (NILP (IGNORE_MULTIPLE_VALUES (called)))
3383 cdr into the list before we've processed the 7119 {
3384 relevant part, error. */ 7120 Lisp_Object *result
3385 dead_wrong_type_argument (Qconsp, lisp_vals); 7121 = (Lisp_Object *) GET_VOID_FROM_LISP (lisp_vals);
3386 } 7122 *result = Qnil;
3387 7123 UNGCPRO;
3388 XSETCAR (lisp_vals, called); 7124 return;
3389 lisp_vals = XCDR (lisp_vals); 7125 }
3390 break; 7126 }
3391 } 7127 else
3392 7128 {
3393 if (SOME_OR_EVERY_SOME == some_or_every) 7129 called = IGNORE_MULTIPLE_VALUES (called);
3394 { 7130 switch (lisp_vals_type)
3395 if (!NILP (IGNORE_MULTIPLE_VALUES (called))) 7131 {
3396 { 7132 case lrecord_type_symbol:
3397 XCAR (lisp_vals) = called; 7133 /* Discard the result of funcall. */
3398 UNGCPRO; 7134 break;
3399 return; 7135 case lrecord_type_cons:
3400 } 7136 {
3401 break; 7137 if (!CONSP (lisp_vals))
3402 } 7138 {
3403 7139 /* If FUNCTION has inserted a non-cons non-nil
3404 if (SOME_OR_EVERY_EVERY == some_or_every) 7140 cdr into the list before we've processed the
3405 { 7141 relevant part, error. */
3406 called = IGNORE_MULTIPLE_VALUES (called); 7142 mapping_interaction_error (caller, lisp_vals);
3407 if (NILP (called)) 7143 }
3408 { 7144 XSETCAR (lisp_vals, called);
3409 XCAR (lisp_vals) = Qnil; 7145 lisp_vals = XCDR (lisp_vals);
3410 UNGCPRO; 7146 break;
3411 return; 7147 }
3412 } 7148 case lrecord_type_vector:
3413 break; 7149 {
3414 } 7150 i < XVECTOR_LENGTH (lisp_vals) ?
3415 7151 (XVECTOR_DATA (lisp_vals)[i] = called) :
3416 goto bad_show_or_every_flag; 7152 /* Let #'aset error. */
3417 } 7153 Faset (lisp_vals, make_int (i), called);
3418 case lrecord_type_vector: 7154 break;
3419 { 7155 }
3420 called = IGNORE_MULTIPLE_VALUES (called); 7156 case lrecord_type_string:
3421 i < XVECTOR_LENGTH (lisp_vals) ? 7157 {
3422 (XVECTOR_DATA (lisp_vals)[i] = called) : 7158 CHECK_CHAR_COERCE_INT (called);
3423 /* Let #'aset error. */ 7159 cursor += set_itext_ichar (cursor, XCHAR (called));
3424 Faset (lisp_vals, make_int (i), called); 7160 break;
3425 break; 7161 }
3426 } 7162 case lrecord_type_bit_vector:
3427 case lrecord_type_string: 7163 {
3428 { 7164 (BITP (called) &&
3429 /* If this ever becomes a code hotspot, we can keep 7165 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ?
3430 around pointers into the data of the string, checking 7166 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i,
3431 each time that it hasn't been relocated. */ 7167 XINT (called)) :
3432 called = IGNORE_MULTIPLE_VALUES (called); 7168 (void) Faset (lisp_vals, make_int (i), called);
3433 Faset (lisp_vals, make_int (i), called); 7169 break;
3434 break; 7170 }
3435 } 7171 default:
3436 case lrecord_type_bit_vector: 7172 {
3437 { 7173 ABORT();
3438 called = IGNORE_MULTIPLE_VALUES (called); 7174 break;
3439 (BITP (called) && 7175 }
3440 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ? 7176 }
3441 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i, 7177 }
3442 XINT (called)) : 7178 }
3443 (void) Faset (lisp_vals, make_int (i), called); 7179
3444 break; 7180 if (lisp_vals_staging != NULL)
3445 } 7181 {
3446 bad_show_or_every_flag: 7182 CHECK_LISP_WRITEABLE (lisp_vals);
3447 default: 7183 replace_string_range (lisp_vals, Qzero, make_int (call_count),
3448 { 7184 lisp_vals_staging, cursor);
3449 ABORT(); 7185 }
3450 break; 7186 }
3451 } 7187
3452 }
3453 }
3454 }
3455 }
3456 UNGCPRO; 7188 UNGCPRO;
7189 }
7190
7191 /* Given NSEQUENCES objects at the address pointed to by SEQUENCES, return
7192 the length of the shortest sequence. Error if all are circular, or if any
7193 one of them is not a sequence. */
7194 static Elemcount
7195 shortest_length_among_sequences (int nsequences, Lisp_Object *sequences)
7196 {
7197 Elemcount len = 1 + EMACS_INT_MAX;
7198 Lisp_Object length = Qnil;
7199 int i;
7200
7201 for (i = 0; i < nsequences; ++i)
7202 {
7203 if (CONSP (sequences[i]))
7204 {
7205 length = Flist_length (sequences[i]);
7206 if (!NILP (length))
7207 {
7208 len = min (len, XINT (length));
7209 }
7210 }
7211 else
7212 {
7213 CHECK_SEQUENCE (sequences[i]);
7214 length = Flength (sequences[i]);
7215 len = min (len, XINT (length));
7216 }
7217 }
7218
7219 if (len == 1 + EMACS_INT_MAX)
7220 {
7221 signal_circular_list_error (sequences[0]);
7222 }
7223
7224 return len;
3457 } 7225 }
3458 7226
3459 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /* 7227 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /*
3460 Call FUNCTION on each element of SEQUENCE, and concat results to a string. 7228 Call FUNCTION on each element of SEQUENCE, and concat results to a string.
3461 Between each pair of results, insert SEPARATOR. 7229 Between each pair of results, insert SEPARATOR.
3481 EMACS_INT i, nargs0; 7249 EMACS_INT i, nargs0;
3482 7250
3483 args[2] = sequence; 7251 args[2] = sequence;
3484 args[1] = separator; 7252 args[1] = separator;
3485 7253
3486 for (i = 2; i < nargs; ++i) 7254 len = shortest_length_among_sequences (nargs - 2, args + 2);
3487 {
3488 CHECK_SEQUENCE (args[i]);
3489 len = min (len, XINT (Flength (args[i])));
3490 }
3491 7255
3492 if (len == 0) return build_ascstring (""); 7256 if (len == 0) return build_ascstring ("");
3493 7257
3494 nargs0 = len + len - 1; 7258 nargs0 = len + len - 1;
3495 args0 = alloca_array (Lisp_Object, nargs0); 7259 args0 = alloca_array (Lisp_Object, nargs0);
3505 sequence = XCDR (sequence); 7269 sequence = XCDR (sequence);
3506 } 7270 }
3507 } 7271 }
3508 else 7272 else
3509 { 7273 {
3510 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, 7274 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, Qmapconcat);
3511 SOME_OR_EVERY_NEITHER);
3512 } 7275 }
3513 7276
3514 for (i = len - 1; i >= 0; i--) 7277 for (i = len - 1; i >= 0; i--)
3515 args0[i + i] = args0[i]; 7278 args0[i + i] = args0[i];
3516 7279
3533 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) 7296 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3534 */ 7297 */
3535 (int nargs, Lisp_Object *args)) 7298 (int nargs, Lisp_Object *args))
3536 { 7299 {
3537 Lisp_Object function = args[0]; 7300 Lisp_Object function = args[0];
3538 Elemcount len = EMACS_INT_MAX; 7301 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
3539 Lisp_Object *args0; 7302 Lisp_Object *args0;
3540 int i;
3541
3542 for (i = 1; i < nargs; ++i)
3543 {
3544 CHECK_SEQUENCE (args[i]);
3545 len = min (len, XINT (Flength (args[i])));
3546 }
3547 7303
3548 args0 = alloca_array (Lisp_Object, len); 7304 args0 = alloca_array (Lisp_Object, len);
3549 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1, 7305 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1, QmapcarX);
3550 SOME_OR_EVERY_NEITHER);
3551 7306
3552 return Flist ((int) len, args0); 7307 return Flist ((int) len, args0);
3553 } 7308 }
3554 7309
3555 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /* 7310 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /*
3565 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) 7320 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3566 */ 7321 */
3567 (int nargs, Lisp_Object *args)) 7322 (int nargs, Lisp_Object *args))
3568 { 7323 {
3569 Lisp_Object function = args[0]; 7324 Lisp_Object function = args[0];
3570 Elemcount len = EMACS_INT_MAX; 7325 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
3571 Lisp_Object result; 7326 Lisp_Object result = make_vector (len, Qnil);
7327
3572 struct gcpro gcpro1; 7328 struct gcpro gcpro1;
3573 int i;
3574
3575 for (i = 1; i < nargs; ++i)
3576 {
3577 CHECK_SEQUENCE (args[i]);
3578 len = min (len, XINT (Flength (args[i])));
3579 }
3580
3581 result = make_vector (len, Qnil);
3582 GCPRO1 (result); 7329 GCPRO1 (result);
3583 /* Don't pass result as the lisp_object argument, we want mapcarX to protect 7330 /* Don't pass result as the lisp_object argument, we want mapcarX to protect
3584 a single list argument's elements from being garbage-collected. */ 7331 a single list argument's elements from being garbage-collected. */
3585 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1, 7332 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1,
3586 SOME_OR_EVERY_NEITHER); 7333 Qmapvector);
3587 UNGCPRO; 7334 RETURN_UNGCPRO (result);
3588
3589 return result;
3590 } 7335 }
3591 7336
3592 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /* 7337 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /*
3593 Call FUNCTION on each element of SEQUENCE; chain the results together. 7338 Call FUNCTION on each element of SEQUENCE; chain the results together.
3594 7339
3602 7347
3603 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) 7348 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3604 */ 7349 */
3605 (int nargs, Lisp_Object *args)) 7350 (int nargs, Lisp_Object *args))
3606 { 7351 {
3607 Lisp_Object function = args[0], nconcing; 7352 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
3608 Elemcount len = EMACS_INT_MAX; 7353 Lisp_Object function = args[0], *result = alloca_array (Lisp_Object, len);
3609 Lisp_Object *args0; 7354
3610 struct gcpro gcpro1; 7355 mapcarX (len, result, Qnil, function, nargs - 1, args + 1, Qmapcan);
3611 int i; 7356
3612 7357 /* #'nconc GCPROs its args in case of signals and error. */
3613 for (i = 1; i < nargs; ++i) 7358 return Fnconc (len, result);
3614 {
3615 CHECK_SEQUENCE (args[i]);
3616 len = min (len, XINT (Flength (args[i])));
3617 }
3618
3619 args0 = alloca_array (Lisp_Object, len + 1);
3620 mapcarX (len, args0 + 1, Qnil, function, nargs - 1, args + 1,
3621 SOME_OR_EVERY_NEITHER);
3622
3623 if (len < 2)
3624 {
3625 return len ? args0[1] : Qnil;
3626 }
3627
3628 /* bytecode_nconc2 can signal and return, we need to GCPRO the args, since
3629 mapcarX is no longer doing this for us. */
3630 args0[0] = Fcons (Qnil, Qnil);
3631 GCPRO1 (args0[0]);
3632 gcpro1.nvars = len + 1;
3633
3634 for (i = 0; i < len; ++i)
3635 {
3636 nconcing = bytecode_nconc2 (args0 + i);
3637 args0[i + 1] = nconcing;
3638 }
3639
3640 RETURN_UNGCPRO (XCDR (nconcing));
3641 } 7359 }
3642 7360
3643 DEFUN ("mapc", Fmapc, 2, MANY, 0, /* 7361 DEFUN ("mapc", Fmapc, 2, MANY, 0, /*
3644 Call FUNCTION on each element of SEQUENCE. 7362 Call FUNCTION on each element of SEQUENCE.
3645 7363
3656 7374
3657 arguments: (FUNCTION SEQUENCE &rest SEQUENCES) 7375 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
3658 */ 7376 */
3659 (int nargs, Lisp_Object *args)) 7377 (int nargs, Lisp_Object *args))
3660 { 7378 {
3661 Elemcount len = EMACS_INT_MAX; 7379 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
3662 Lisp_Object sequence = args[1]; 7380 Lisp_Object sequence = args[1];
3663 struct gcpro gcpro1; 7381 struct gcpro gcpro1;
3664 int i;
3665
3666 for (i = 1; i < nargs; ++i)
3667 {
3668 CHECK_SEQUENCE (args[i]);
3669 len = min (len, XINT (Flength (args[i])));
3670 }
3671
3672 /* We need to GCPRO sequence, because mapcarX will modify the 7382 /* We need to GCPRO sequence, because mapcarX will modify the
3673 elements of the args array handed to it, and this may involve 7383 elements of the args array handed to it, and this may involve
3674 elements of sequence getting garbage collected. */ 7384 elements of sequence getting garbage collected. */
3675 GCPRO1 (sequence); 7385 GCPRO1 (sequence);
3676 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1, 7386 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1, Qmapc);
3677 SOME_OR_EVERY_NEITHER);
3678 RETURN_UNGCPRO (sequence); 7387 RETURN_UNGCPRO (sequence);
3679 } 7388 }
3680 7389
3681 DEFUN ("map", Fmap, 3, MANY, 0, /* 7390 DEFUN ("map", Fmap, 3, MANY, 0, /*
3682 Map FUNCTION across one or more sequences, returning a sequence. 7391 Map FUNCTION across one or more sequences, returning a sequence.
3697 { 7406 {
3698 Lisp_Object type = args[0]; 7407 Lisp_Object type = args[0];
3699 Lisp_Object function = args[1]; 7408 Lisp_Object function = args[1];
3700 Lisp_Object result = Qnil; 7409 Lisp_Object result = Qnil;
3701 Lisp_Object *args0 = NULL; 7410 Lisp_Object *args0 = NULL;
3702 Elemcount len = EMACS_INT_MAX; 7411 Elemcount len = shortest_length_among_sequences (nargs - 2, args + 2);
3703 int i;
3704 struct gcpro gcpro1; 7412 struct gcpro gcpro1;
3705 7413
3706 for (i = 2; i < nargs; ++i)
3707 {
3708 CHECK_SEQUENCE (args[i]);
3709 len = min (len, XINT (Flength (args[i])));
3710 }
3711
3712 if (!NILP (type)) 7414 if (!NILP (type))
3713 { 7415 {
3714 args0 = alloca_array (Lisp_Object, len); 7416 args0 = alloca_array (Lisp_Object, len);
3715 } 7417 }
3716 7418
3717 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, 7419 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, Qmap);
3718 SOME_OR_EVERY_NEITHER);
3719 7420
3720 if (EQ (type, Qnil)) 7421 if (EQ (type, Qnil))
3721 { 7422 {
3722 return result; 7423 return result;
3723 } 7424 }
3763 7464
3764 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES) 7465 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES)
3765 */ 7466 */
3766 (int nargs, Lisp_Object *args)) 7467 (int nargs, Lisp_Object *args))
3767 { 7468 {
3768 Elemcount len = EMACS_INT_MAX; 7469 Elemcount len;
3769 Lisp_Object result_sequence = args[0]; 7470 Lisp_Object result_sequence = args[0];
3770 Lisp_Object function = args[1]; 7471 Lisp_Object function = args[1];
3771 int i;
3772 7472
3773 args[0] = function; 7473 args[0] = function;
3774 args[1] = result_sequence; 7474 args[1] = result_sequence;
3775 7475
3776 for (i = 1; i < nargs; ++i) 7476 len = shortest_length_among_sequences (nargs - 1, args + 1);
3777 {
3778 CHECK_SEQUENCE (args[i]);
3779 len = min (len, XINT (Flength (args[i])));
3780 }
3781 7477
3782 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2, 7478 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2,
3783 SOME_OR_EVERY_NEITHER); 7479 Qmap_into);
3784 7480
3785 return result_sequence; 7481 return result_sequence;
3786 } 7482 }
3787 7483
3788 DEFUN ("some", Fsome, 2, MANY, 0, /* 7484 DEFUN ("some", Fsome, 2, MANY, 0, /*
3791 If so, return the value (possibly multiple) given by PREDICATE. 7487 If so, return the value (possibly multiple) given by PREDICATE.
3792 7488
3793 With optional SEQUENCES, call PREDICATE each time with as many arguments as 7489 With optional SEQUENCES, call PREDICATE each time with as many arguments as
3794 there are SEQUENCES (plus one for the element from SEQUENCE). 7490 there are SEQUENCES (plus one for the element from SEQUENCE).
3795 7491
7492 See also `find-if', which returns the corresponding element of SEQUENCE,
7493 rather than the value given by PREDICATE, and accepts bounding index
7494 keywords.
7495
3796 arguments: (PREDICATE SEQUENCE &rest SEQUENCES) 7496 arguments: (PREDICATE SEQUENCE &rest SEQUENCES)
3797 */ 7497 */
3798 (int nargs, Lisp_Object *args)) 7498 (int nargs, Lisp_Object *args))
3799 { 7499 {
3800 Lisp_Object result_box = Fcons (Qnil, Qnil); 7500 Lisp_Object result = Qnil,
3801 struct gcpro gcpro1; 7501 result_ptr = STORE_VOID_IN_LISP ((void *) &result);
3802 Elemcount len = EMACS_INT_MAX; 7502 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
3803 int i; 7503
3804 7504 mapcarX (len, NULL, result_ptr, args[0], nargs - 1, args +1, Qsome);
3805 GCPRO1 (result_box); 7505
3806 7506 return result;
3807 for (i = 1; i < nargs; ++i)
3808 {
3809 CHECK_SEQUENCE (args[i]);
3810 len = min (len, XINT (Flength (args[i])));
3811 }
3812
3813 mapcarX (len, NULL, result_box, args[0], nargs - 1, args +1,
3814 SOME_OR_EVERY_SOME);
3815
3816 RETURN_UNGCPRO (XCAR (result_box));
3817 } 7507 }
3818 7508
3819 DEFUN ("every", Fevery, 2, MANY, 0, /* 7509 DEFUN ("every", Fevery, 2, MANY, 0, /*
3820 Return true if PREDICATE is true of every element of SEQUENCE. 7510 Return true if PREDICATE is true of every element of SEQUENCE.
3821 7511
3826 7516
3827 arguments: (PREDICATE SEQUENCE &rest SEQUENCES) 7517 arguments: (PREDICATE SEQUENCE &rest SEQUENCES)
3828 */ 7518 */
3829 (int nargs, Lisp_Object *args)) 7519 (int nargs, Lisp_Object *args))
3830 { 7520 {
3831 Lisp_Object result_box = Fcons (Qt, Qnil); 7521 Lisp_Object result = Qt, result_ptr = STORE_VOID_IN_LISP ((void *) &result);
3832 struct gcpro gcpro1; 7522 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
3833 Elemcount len = EMACS_INT_MAX; 7523
3834 int i; 7524 mapcarX (len, NULL, result_ptr, args[0], nargs - 1, args +1, Qevery);
3835 7525
3836 GCPRO1 (result_box); 7526 return result;
3837
3838 for (i = 1; i < nargs; ++i)
3839 {
3840 CHECK_SEQUENCE (args[i]);
3841 len = min (len, XINT (Flength (args[i])));
3842 }
3843
3844 mapcarX (len, NULL, result_box, args[0], nargs - 1, args +1,
3845 SOME_OR_EVERY_EVERY);
3846
3847 RETURN_UNGCPRO (XCAR (result_box));
3848 } 7527 }
3849 7528
3850 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument 7529 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument
3851 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]), 7530 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]),
3852 until that #'nthcdr expression gives nil for some element of LISTS. 7531 until that #'nthcdr expression gives nil for some element of LISTS.
3853 7532
3854 If MAPLP is zero, return LISTS[0]. Otherwise, return a list of the return 7533 CALLER is a symbol reflecting the Lisp-visible function that was called,
3855 values from FUNCTION; if NCONCP is non-zero, nconc them together. 7534 and any errors thrown because SEQUENCES was modified will reflect it.
7535
7536 If CALLER is Qmapl, return LISTS[0]. Otherwise, return a list of the
7537 return values from FUNCTION; if caller is Qmapcan, nconc them together.
3856 7538
3857 In contrast to mapcarX, we don't require our callers to check LISTS for 7539 In contrast to mapcarX, we don't require our callers to check LISTS for
3858 well-formedness, we signal wrong-type-argument if it's not a list, or 7540 well-formedness, we signal wrong-type-argument if it's not a list, or
3859 circular-list if it's circular. */ 7541 circular-list if it's circular. */
3860 7542
3861 static Lisp_Object 7543 static Lisp_Object
3862 maplist (Lisp_Object function, int nlists, Lisp_Object *lists, int maplp, 7544 maplist (Lisp_Object function, int nlists, Lisp_Object *lists,
3863 int nconcp) 7545 Lisp_Object caller)
3864 { 7546 {
3865 Lisp_Object result = maplp ? lists[0] : Fcons (Qnil, Qnil), funcalled; 7547 Lisp_Object nconcing[2], accum = Qnil, *args, *tortoises, funcalled;
3866 Lisp_Object nconcing[2], accum = result, *args; 7548 Lisp_Object result = EQ (caller, Qmapl) ? lists[0] : Qnil;
3867 struct gcpro gcpro1, gcpro2, gcpro3; 7549 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
3868 int i, j, continuing = (nlists > 0), called_count = 0; 7550 int i, j, continuing = (nlists > 0), called_count = 0;
3869 7551
3870 args = alloca_array (Lisp_Object, nlists + 1); 7552 args = alloca_array (Lisp_Object, nlists + 1);
3871 args[0] = function; 7553 args[0] = function;
3872 for (i = 1; i <= nlists; ++i) 7554 for (i = 1; i <= nlists; ++i)
3873 { 7555 {
3874 args[i] = Qnil; 7556 args[i] = Qnil;
3875 } 7557 }
3876 7558
3877 if (nconcp) 7559 tortoises = alloca_array (Lisp_Object, nlists);
3878 { 7560 memcpy (tortoises, lists, nlists * sizeof (Lisp_Object));
3879 nconcing[0] = result; 7561
7562 if (EQ (caller, Qmapcon))
7563 {
7564 nconcing[0] = Qnil;
3880 nconcing[1] = Qnil; 7565 nconcing[1] = Qnil;
3881 GCPRO3 (args[0], nconcing[0], result); 7566 GCPRO4 (args[0], nconcing[0], tortoises[0], result);
3882 gcpro1.nvars = 1; 7567 gcpro1.nvars = 1;
3883 gcpro2.nvars = 2; 7568 gcpro2.nvars = 2;
7569 gcpro3.nvars = nlists;
3884 } 7570 }
3885 else 7571 else
3886 { 7572 {
3887 GCPRO2 (args[0], result); 7573 GCPRO3 (args[0], tortoises[0], result);
3888 gcpro1.nvars = 1; 7574 gcpro1.nvars = 1;
7575 gcpro2.nvars = nlists;
3889 } 7576 }
3890 7577
3891 while (continuing) 7578 while (continuing)
3892 { 7579 {
3893 for (j = 0; j < nlists; ++j) 7580 for (j = 0; j < nlists; ++j)
3902 continuing = 0; 7589 continuing = 0;
3903 break; 7590 break;
3904 } 7591 }
3905 else 7592 else
3906 { 7593 {
3907 dead_wrong_type_argument (Qlistp, lists[j]); 7594 lists[j] = wrong_type_argument (Qlistp, lists[j]);
3908 } 7595 }
3909 } 7596 }
3910 if (!continuing) break; 7597 if (!continuing) break;
3911 funcalled = IGNORE_MULTIPLE_VALUES (Ffuncall (nlists + 1, args)); 7598 funcalled = IGNORE_MULTIPLE_VALUES (Ffuncall (nlists + 1, args));
3912 if (!maplp) 7599
3913 { 7600 if (EQ (caller, Qmapl))
3914 if (nconcp) 7601 {
3915 { 7602 DO_NOTHING;
3916 /* This order of calls means we check that each list is 7603 }
3917 well-formed once and once only. The last result does 7604 else if (EQ (caller, Qmapcon))
3918 not have to be a list. */ 7605 {
3919 nconcing[1] = funcalled; 7606 nconcing[1] = funcalled;
3920 nconcing[0] = bytecode_nconc2 (nconcing); 7607 accum = bytecode_nconc2 (nconcing);
3921 } 7608 if (NILP (result))
3922 else 7609 {
3923 { 7610 result = accum;
3924 /* Add to the end, avoiding the need to call nreverse 7611 }
3925 once we're done: */ 7612 /* Only check a given stretch of result for well-formedness
3926 XSETCDR (accum, Fcons (funcalled, Qnil)); 7613 once: */
3927 accum = XCDR (accum); 7614 nconcing[0] = funcalled;
3928 } 7615 }
3929 } 7616 else if (NILP (accum))
3930 7617 {
3931 if (++called_count % CIRCULAR_LIST_SUSPICION_LENGTH) continue; 7618 accum = result = Fcons (funcalled, Qnil);
3932 7619 }
3933 for (j = 0; j < nlists; ++j) 7620 else
3934 { 7621 {
3935 EXTERNAL_LIST_LOOP_1 (lists[j]) 7622 /* Add to the end, avoiding the need to call nreverse
3936 { 7623 once we're done: */
3937 /* Just check the lists aren't circular, using the 7624 XSETCDR (accum, Fcons (funcalled, Qnil));
3938 EXTERNAL_LIST_LOOP_1 macro. */ 7625 accum = XCDR (accum);
3939 } 7626 }
3940 } 7627
3941 } 7628 if (++called_count > CIRCULAR_LIST_SUSPICION_LENGTH)
3942 7629 {
3943 if (!maplp) 7630 if (called_count & 1)
3944 { 7631 {
3945 result = XCDR (result); 7632 for (j = 0; j < nlists; ++j)
7633 {
7634 tortoises[j] = XCDR (tortoises[j]);
7635 if (EQ (lists[j], tortoises[j]))
7636 {
7637 signal_circular_list_error (lists[j]);
7638 }
7639 }
7640 }
7641 else
7642 {
7643 for (j = 0; j < nlists; ++j)
7644 {
7645 if (EQ (lists[j], tortoises[j]))
7646 {
7647 signal_circular_list_error (lists[j]);
7648 }
7649 }
7650 }
7651 }
3946 } 7652 }
3947 7653
3948 RETURN_UNGCPRO (result); 7654 RETURN_UNGCPRO (result);
3949 } 7655 }
3950 7656
3955 7661
3956 arguments: (FUNCTION LIST &rest LISTS) 7662 arguments: (FUNCTION LIST &rest LISTS)
3957 */ 7663 */
3958 (int nargs, Lisp_Object *args)) 7664 (int nargs, Lisp_Object *args))
3959 { 7665 {
3960 return maplist (args[0], nargs - 1, args + 1, 0, 0); 7666 return maplist (args[0], nargs - 1, args + 1, Qmaplist);
3961 } 7667 }
3962 7668
3963 DEFUN ("mapl", Fmapl, 2, MANY, 0, /* 7669 DEFUN ("mapl", Fmapl, 2, MANY, 0, /*
3964 Like `maplist', but do not accumulate values returned by the function. 7670 Like `maplist', but do not accumulate values returned by the function.
3965 7671
3966 arguments: (FUNCTION LIST &rest LISTS) 7672 arguments: (FUNCTION LIST &rest LISTS)
3967 */ 7673 */
3968 (int nargs, Lisp_Object *args)) 7674 (int nargs, Lisp_Object *args))
3969 { 7675 {
3970 return maplist (args[0], nargs - 1, args + 1, 1, 0); 7676 return maplist (args[0], nargs - 1, args + 1, Qmapl);
3971 } 7677 }
3972 7678
3973 DEFUN ("mapcon", Fmapcon, 2, MANY, 0, /* 7679 DEFUN ("mapcon", Fmapcon, 2, MANY, 0, /*
3974 Like `maplist', but chains together the values returned by FUNCTION. 7680 Like `maplist', but chains together the values returned by FUNCTION.
3975 7681
3978 7684
3979 arguments: (FUNCTION LIST &rest LISTS) 7685 arguments: (FUNCTION LIST &rest LISTS)
3980 */ 7686 */
3981 (int nargs, Lisp_Object *args)) 7687 (int nargs, Lisp_Object *args))
3982 { 7688 {
3983 return maplist (args[0], nargs - 1, args + 1, 0, 1); 7689 return maplist (args[0], nargs - 1, args + 1, Qmapcon);
3984 } 7690 }
3985 7691
3986 /* Extra random functions */ 7692 /* Extra random functions */
7693
7694 DEFUN ("reduce", Freduce, 2, MANY, 0, /*
7695 Combine the elements of sequence using FUNCTION, a binary operation.
7696
7697 For example, `(reduce #'+ SEQUENCE)' returns the sum of all elements in
7698 SEQUENCE, and `(reduce #'union SEQUENCE)' returns the union of all elements
7699 in SEQUENCE.
7700
7701 Keywords supported: :start :end :from-end :initial-value :key
7702 See `remove*' for the meaning of :start, :end, :from-end and :key.
7703
7704 :initial-value specifies an element (typically an identity element, such as
7705 0) that is conceptually prepended to the sequence (or appended, when
7706 :from-end is given).
7707
7708 If the sequence has one element, that element is returned directly.
7709 If the sequence has no elements, :initial-value is returned if given;
7710 otherwise, FUNCTION is called with no arguments, and its result returned.
7711
7712 arguments: (FUNCTION SEQUENCE &key (START 0) (END (length SEQUENCE)) FROM-END INITIAL-VALUE (KEY #'identity))
7713 */
7714 (int nargs, Lisp_Object *args))
7715 {
7716 Lisp_Object function = args[0], sequence = args[1], accum = Qunbound;
7717 Elemcount starting, ending = EMACS_INT_MAX + 1, ii = 0;
7718
7719 PARSE_KEYWORDS (Freduce, nargs, args, 5,
7720 (start, end, from_end, initial_value, key),
7721 (start = Qzero, initial_value = Qunbound));
7722
7723 CHECK_SEQUENCE (sequence);
7724 CHECK_NATNUM (start);
7725 starting = BIGNUMP (start) ? EMACS_INT_MAX + 1 : XINT (start);
7726 CHECK_KEY_ARGUMENT (key);
7727
7728 #define KEY(key, item) (EQ (Qidentity, key) ? item : \
7729 IGNORE_MULTIPLE_VALUES (call1 (key, item)))
7730 #define CALL2(function, accum, item) \
7731 IGNORE_MULTIPLE_VALUES (call2 (function, accum, item))
7732
7733 if (!NILP (end))
7734 {
7735 CHECK_NATNUM (end);
7736 ending = BIGNUMP (end) ? EMACS_INT_MAX + 1 : XINT (end);
7737 }
7738
7739 if (VECTORP (sequence))
7740 {
7741 Lisp_Vector *vv = XVECTOR (sequence);
7742 struct gcpro gcpro1;
7743
7744 check_sequence_range (sequence, start, end, make_int (vv->size));
7745
7746 ending = min (ending, vv->size);
7747
7748 GCPRO1 (accum);
7749
7750 if (!UNBOUNDP (initial_value))
7751 {
7752 accum = initial_value;
7753 }
7754 else if (ending - starting)
7755 {
7756 if (NILP (from_end))
7757 {
7758 accum = KEY (key, vv->contents[starting]);
7759 starting++;
7760 }
7761 else
7762 {
7763 accum = KEY (key, vv->contents[ending - 1]);
7764 ending--;
7765 }
7766 }
7767
7768 if (NILP (from_end))
7769 {
7770 for (ii = starting; ii < ending; ++ii)
7771 {
7772 accum = CALL2 (function, accum, KEY (key, vv->contents[ii]));
7773 }
7774 }
7775 else
7776 {
7777 for (ii = ending - 1; ii >= starting; --ii)
7778 {
7779 accum = CALL2 (function, KEY (key, vv->contents[ii]), accum);
7780 }
7781 }
7782
7783 UNGCPRO;
7784 }
7785 else if (BIT_VECTORP (sequence))
7786 {
7787 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
7788 struct gcpro gcpro1;
7789
7790 check_sequence_range (sequence, start, end, make_int (bv->size));
7791 ending = min (ending, bv->size);
7792
7793 GCPRO1 (accum);
7794
7795 if (!UNBOUNDP (initial_value))
7796 {
7797 accum = initial_value;
7798 }
7799 else if (ending - starting)
7800 {
7801 if (NILP (from_end))
7802 {
7803 accum = KEY (key, make_int (bit_vector_bit (bv, starting)));
7804 starting++;
7805 }
7806 else
7807 {
7808 accum = KEY (key, make_int (bit_vector_bit (bv, ending - 1)));
7809 ending--;
7810 }
7811 }
7812
7813 if (NILP (from_end))
7814 {
7815 for (ii = starting; ii < ending; ++ii)
7816 {
7817 accum = CALL2 (function, accum,
7818 KEY (key, make_int (bit_vector_bit (bv, ii))));
7819 }
7820 }
7821 else
7822 {
7823 for (ii = ending - 1; ii >= starting; --ii)
7824 {
7825 accum = CALL2 (function, KEY (key,
7826 make_int (bit_vector_bit (bv,
7827 ii))),
7828 accum);
7829 }
7830 }
7831
7832 UNGCPRO;
7833
7834 }
7835 else if (STRINGP (sequence))
7836 {
7837 struct gcpro gcpro1;
7838
7839 GCPRO1 (accum);
7840
7841 if (NILP (from_end))
7842 {
7843 Bytecount byte_len = XSTRING_LENGTH (sequence);
7844 Bytecount cursor_offset = 0;
7845 const Ibyte *startp = XSTRING_DATA (sequence);
7846 const Ibyte *cursor = startp;
7847
7848 for (ii = 0; ii != starting && cursor_offset < byte_len; ++ii)
7849 {
7850 INC_IBYTEPTR (cursor);
7851 cursor_offset = cursor - startp;
7852 }
7853
7854 if (!UNBOUNDP (initial_value))
7855 {
7856 accum = initial_value;
7857 }
7858 else if (ending - starting && cursor_offset < byte_len)
7859 {
7860 accum = KEY (key, make_char (itext_ichar (cursor)));
7861 starting++;
7862 startp = XSTRING_DATA (sequence);
7863 cursor = startp + cursor_offset;
7864
7865 if (byte_len != XSTRING_LENGTH (sequence)
7866 || !valid_ibyteptr_p (cursor))
7867 {
7868 mapping_interaction_error (Qreduce, sequence);
7869 }
7870
7871 INC_IBYTEPTR (cursor);
7872 cursor_offset = cursor - startp;
7873 ii++;
7874 }
7875
7876 while (cursor_offset < byte_len && ii < ending)
7877 {
7878 accum = CALL2 (function, accum,
7879 KEY (key, make_char (itext_ichar (cursor))));
7880
7881 startp = XSTRING_DATA (sequence);
7882 cursor = startp + cursor_offset;
7883
7884 if (byte_len != XSTRING_LENGTH (sequence)
7885 || !valid_ibyteptr_p (cursor))
7886 {
7887 mapping_interaction_error (Qreduce, sequence);
7888 }
7889
7890 INC_IBYTEPTR (cursor);
7891 cursor_offset = cursor - startp;
7892 ++ii;
7893 }
7894
7895 if (ii < starting || (ii < ending && !NILP (end)))
7896 {
7897 check_sequence_range (sequence, start, end, Flength (sequence));
7898 }
7899 }
7900 else
7901 {
7902 Elemcount len = string_char_length (sequence);
7903 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence);
7904 const Ibyte *cursor;
7905
7906 check_sequence_range (sequence, start, end, make_int (len));
7907 ending = min (ending, len);
7908 starting = XINT (start);
7909
7910 cursor = string_char_addr (sequence, ending - 1);
7911 cursor_offset = cursor - XSTRING_DATA (sequence);
7912
7913 if (!UNBOUNDP (initial_value))
7914 {
7915 accum = initial_value;
7916 }
7917 else if (ending - starting)
7918 {
7919 accum = KEY (key, make_char (itext_ichar (cursor)));
7920 ending--;
7921 if (ending > 0)
7922 {
7923 cursor = XSTRING_DATA (sequence) + cursor_offset;
7924
7925 if (!valid_ibyteptr_p (cursor))
7926 {
7927 mapping_interaction_error (Qreduce, sequence);
7928 }
7929
7930 DEC_IBYTEPTR (cursor);
7931 cursor_offset = cursor - XSTRING_DATA (sequence);
7932 }
7933 }
7934
7935 for (ii = ending - 1; ii >= starting; --ii)
7936 {
7937 accum = CALL2 (function, KEY (key,
7938 make_char (itext_ichar (cursor))),
7939 accum);
7940 if (ii > 0)
7941 {
7942 cursor = XSTRING_DATA (sequence) + cursor_offset;
7943
7944 if (byte_len != XSTRING_LENGTH (sequence)
7945 || !valid_ibyteptr_p (cursor))
7946 {
7947 mapping_interaction_error (Qreduce, sequence);
7948 }
7949
7950 DEC_IBYTEPTR (cursor);
7951 cursor_offset = cursor - XSTRING_DATA (sequence);
7952 }
7953 }
7954 }
7955
7956 UNGCPRO;
7957 }
7958 else if (LISTP (sequence))
7959 {
7960 if (NILP (from_end))
7961 {
7962 struct gcpro gcpro1;
7963
7964 GCPRO1 (accum);
7965
7966 if (!UNBOUNDP (initial_value))
7967 {
7968 accum = initial_value;
7969 }
7970 else if (ending - starting)
7971 {
7972 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
7973 {
7974 if (ii == starting)
7975 {
7976 accum = KEY (key, elt);
7977 starting++;
7978 break;
7979 }
7980 ++ii;
7981 }
7982 END_GC_EXTERNAL_LIST_LOOP (elt);
7983 }
7984
7985 ii = 0;
7986
7987 if (ending - starting)
7988 {
7989 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
7990 {
7991 if (ii >= starting)
7992 {
7993 if (ii < ending)
7994 {
7995 accum = CALL2 (function, accum, KEY (key, elt));
7996 }
7997 else if (ii == ending)
7998 {
7999 break;
8000 }
8001 }
8002 ++ii;
8003 }
8004 END_GC_EXTERNAL_LIST_LOOP (elt);
8005 }
8006
8007 UNGCPRO;
8008
8009 if (ii < starting || (ii < ending && !NILP (end)))
8010 {
8011 check_sequence_range (sequence, start, end, Flength (sequence));
8012 }
8013 }
8014 else
8015 {
8016 Boolint need_accum = 0;
8017 Lisp_Object *subsequence = NULL;
8018 Elemcount counting = 0, len = 0;
8019 struct gcpro gcpro1;
8020
8021 len = XINT (Flength (sequence));
8022 check_sequence_range (sequence, start, end, make_int (len));
8023 ending = min (ending, len);
8024
8025 /* :from-end with a list; make an alloca copy of the relevant list
8026 data, attempting to go backwards isn't worth the trouble. */
8027 if (!UNBOUNDP (initial_value))
8028 {
8029 accum = initial_value;
8030 if (ending - starting && starting < ending)
8031 {
8032 subsequence = alloca_array (Lisp_Object, ending - starting);
8033 }
8034 }
8035 else if (ending - starting && starting < ending)
8036 {
8037 subsequence = alloca_array (Lisp_Object, ending - starting);
8038 need_accum = 1;
8039 }
8040
8041 if (ending - starting && starting < ending)
8042 {
8043 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
8044 {
8045 if (counting >= starting)
8046 {
8047 if (counting < ending)
8048 {
8049 subsequence[ii++] = elt;
8050 }
8051 else if (counting == ending)
8052 {
8053 break;
8054 }
8055 }
8056 ++counting;
8057 }
8058 }
8059
8060 if (subsequence != NULL)
8061 {
8062 len = ending - starting;
8063 /* If we could be sure that neither FUNCTION nor KEY modify
8064 SEQUENCE, this wouldn't be necessary, since all the
8065 elements of SUBSEQUENCE would definitely always be
8066 reachable via SEQUENCE. */
8067 GCPRO1 (subsequence[0]);
8068 gcpro1.nvars = len;
8069 }
8070
8071 if (need_accum)
8072 {
8073 accum = KEY (key, subsequence[len - 1]);
8074 --len;
8075 }
8076
8077 for (ii = len; ii != 0;)
8078 {
8079 --ii;
8080 accum = CALL2 (function, KEY (key, subsequence[ii]), accum);
8081 }
8082
8083 if (subsequence != NULL)
8084 {
8085 UNGCPRO;
8086 }
8087 }
8088 }
8089
8090 /* At this point, if ACCUM is unbound, SEQUENCE has no elements; we
8091 need to return the result of calling FUNCTION with zero
8092 arguments. */
8093 if (UNBOUNDP (accum))
8094 {
8095 accum = IGNORE_MULTIPLE_VALUES (call0 (function));
8096 }
8097
8098 return accum;
8099 }
3987 8100
3988 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* 8101 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /*
3989 Destructively replace the list OLD with NEW. 8102 Destructively replace the list OLD with NEW.
3990 This is like (copy-sequence NEW) except that it reuses the 8103 This is like (copy-sequence NEW) except that it reuses the
3991 conses in OLD as much as possible. If OLD and NEW are the same 8104 conses in OLD as much as possible. If OLD and NEW are the same
4023 old = Qnil; 8136 old = Qnil;
4024 8137
4025 return old; 8138 return old;
4026 } 8139 }
4027 8140
8141 /* This function is the implementation of fill_string_range() and
8142 replace_string_range(); see the comments for those functions. */
8143 static Lisp_Object
8144 replace_string_range_1 (Lisp_Object dest, Lisp_Object start, Lisp_Object end,
8145 const Ibyte *source, const Ibyte *source_limit,
8146 Lisp_Object item)
8147 {
8148 Ibyte *destp = XSTRING_DATA (dest), *p = destp,
8149 *pend = p + XSTRING_LENGTH (dest), *pcursor, item_buf[MAX_ICHAR_LEN];
8150 Bytecount prefix_bytecount, source_len = source_limit - source;
8151 Charcount ii = 0, ending, len;
8152 Charcount starting = BIGNUMP (start) ? EMACS_INT_MAX + 1 : XINT (start);
8153 Elemcount delta;
8154
8155 while (ii < starting && p < pend)
8156 {
8157 INC_IBYTEPTR (p);
8158 ii++;
8159 }
8160
8161 pcursor = p;
8162
8163 if (NILP (end))
8164 {
8165 while (pcursor < pend)
8166 {
8167 INC_IBYTEPTR (pcursor);
8168 ii++;
8169 }
8170
8171 ending = len = ii;
8172 }
8173 else
8174 {
8175 ending = BIGNUMP (end) ? EMACS_INT_MAX + 1 : XINT (end);
8176 while (ii < ending && pcursor < pend)
8177 {
8178 INC_IBYTEPTR (pcursor);
8179 ii++;
8180 }
8181 }
8182
8183 if (pcursor == pend)
8184 {
8185 /* We have the length, check it for our callers. */
8186 check_sequence_range (dest, start, end, make_int (ii));
8187 }
8188
8189 if (!(p == pend || p == pcursor))
8190 {
8191 prefix_bytecount = p - destp;
8192
8193 if (!NILP (item))
8194 {
8195 assert (source == NULL && source_limit == NULL);
8196 source_len = set_itext_ichar (item_buf, XCHAR (item));
8197 delta = (source_len * (ending - starting)) - (pcursor - p);
8198 }
8199 else
8200 {
8201 assert (source != NULL && source_limit != NULL);
8202 delta = source_len - (pcursor - p);
8203 }
8204
8205 if (delta)
8206 {
8207 resize_string (dest, prefix_bytecount, delta);
8208 destp = XSTRING_DATA (dest);
8209 pcursor = destp + prefix_bytecount + (pcursor - p);
8210 p = destp + prefix_bytecount;
8211 }
8212
8213 if (CHARP (item))
8214 {
8215 while (starting < ending)
8216 {
8217 memcpy (p, item_buf, source_len);
8218 p += source_len;
8219 starting++;
8220 }
8221 }
8222 else
8223 {
8224 while (starting < ending && source < source_limit)
8225 {
8226 source_len = itext_copy_ichar (source, p);
8227 p += source_len, source += source_len;
8228 }
8229 }
8230
8231 init_string_ascii_begin (dest);
8232 bump_string_modiff (dest);
8233 sledgehammer_check_ascii_begin (dest);
8234 }
8235
8236 return dest;
8237 }
8238
8239 DEFUN ("replace", Freplace, 2, MANY, 0, /*
8240 Replace the elements of SEQUENCE-ONE with the elements of SEQUENCE-TWO.
8241
8242 SEQUENCE-ONE is destructively modified, and returned. Its length is not
8243 changed.
8244
8245 Keywords :start1 and :end1 specify a subsequence of SEQUENCE-ONE, and
8246 :start2 and :end2 a subsequence of SEQUENCE-TWO. See `search' for more
8247 information.
8248
8249 arguments: (SEQUENCE-ONE SEQUENCE-TWO &key (START1 0) (END1 (length SEQUENCE-ONE)) (START2 0) (END2 (length SEQUENCE-TWO)))
8250 */
8251 (int nargs, Lisp_Object *args))
8252 {
8253 Lisp_Object sequence1 = args[0], sequence2 = args[1],
8254 result = sequence1;
8255 Elemcount starting1, ending1 = EMACS_INT_MAX + 1, starting2;
8256 Elemcount ending2 = EMACS_INT_MAX + 1, counting = 0, startcounting;
8257 Boolint sequence1_listp, sequence2_listp,
8258 overwriting = EQ (sequence1, sequence2);
8259
8260 PARSE_KEYWORDS (Freplace, nargs, args, 4, (start1, end1, start2, end2),
8261 (start1 = start2 = Qzero));
8262
8263 CHECK_SEQUENCE (sequence1);
8264 CHECK_LISP_WRITEABLE (sequence1);
8265
8266 CHECK_SEQUENCE (sequence2);
8267
8268 CHECK_NATNUM (start1);
8269 starting1 = BIGNUMP (start1) ? EMACS_INT_MAX + 1 : XINT (start1);
8270 CHECK_NATNUM (start2);
8271 starting2 = BIGNUMP (start2) ? EMACS_INT_MAX + 1 : XINT (start2);
8272
8273 if (!NILP (end1))
8274 {
8275 CHECK_NATNUM (end1);
8276 ending1 = BIGNUMP (end1) ? EMACS_INT_MAX + 1 : XINT (end1);
8277 }
8278
8279 if (!NILP (end2))
8280 {
8281 CHECK_NATNUM (end2);
8282 ending2 = BIGNUMP (end2) ? EMACS_INT_MAX + 1 : XINT (end2);
8283 }
8284
8285 sequence1_listp = LISTP (sequence1);
8286 sequence2_listp = LISTP (sequence2);
8287
8288 overwriting = overwriting && starting2 <= starting1;
8289
8290 if (sequence1_listp && !ZEROP (start1))
8291 {
8292 sequence1 = Fnthcdr (start1, sequence1);
8293
8294 if (NILP (sequence1))
8295 {
8296 check_sequence_range (args[0], start1, end1, Flength (args[0]));
8297 /* Give up early here. */
8298 return result;
8299 }
8300
8301 ending1 -= starting1;
8302 starting1 = 0;
8303 }
8304
8305 if (sequence2_listp && !ZEROP (start2))
8306 {
8307 sequence2 = Fnthcdr (start2, sequence2);
8308
8309 if (NILP (sequence2))
8310 {
8311 check_sequence_range (args[1], start1, end1, Flength (args[1]));
8312 /* Nothing available to replace sequence1's contents. */
8313 return result;
8314 }
8315
8316 ending2 -= starting2;
8317 starting2 = 0;
8318 }
8319
8320 if (overwriting)
8321 {
8322 if (EQ (start1, start2))
8323 {
8324 return result;
8325 }
8326
8327 /* Our ranges may overlap. Save the data that might be overwritten. */
8328
8329 if (CONSP (sequence2))
8330 {
8331 Elemcount len = XINT (Flength (sequence2));
8332 Lisp_Object *subsequence
8333 = alloca_array (Lisp_Object, min (ending2, len));
8334 Elemcount ii = 0;
8335
8336 LIST_LOOP_2 (elt, sequence2)
8337 {
8338 if (counting == ending2)
8339 {
8340 break;
8341 }
8342
8343 subsequence[ii++] = elt;
8344 counting++;
8345 }
8346
8347 check_sequence_range (sequence1, start1, end1,
8348 /* The XINT (start2) is intentional here; we
8349 called #'length after doing (nthcdr
8350 start2 sequence2). */
8351 make_int (XINT (start2) + len));
8352 check_sequence_range (sequence2, start2, end2,
8353 make_int (XINT (start2) + len));
8354
8355 while (starting1 < ending1
8356 && starting2 < ending2 && !NILP (sequence1))
8357 {
8358 XSETCAR (sequence1, subsequence[starting2]);
8359 sequence1 = XCDR (sequence1);
8360 starting1++;
8361 starting2++;
8362 }
8363 }
8364 else if (STRINGP (sequence2))
8365 {
8366 Ibyte *p = XSTRING_DATA (sequence2),
8367 *pend = p + XSTRING_LENGTH (sequence2), *pcursor,
8368 *staging;
8369 Bytecount ii = 0;
8370
8371 while (ii < starting2 && p < pend)
8372 {
8373 INC_IBYTEPTR (p);
8374 ii++;
8375 }
8376
8377 pcursor = p;
8378
8379 while (ii < ending2 && starting1 < ending1 && pcursor < pend)
8380 {
8381 INC_IBYTEPTR (pcursor);
8382 starting1++;
8383 ii++;
8384 }
8385
8386 if (pcursor == pend)
8387 {
8388 check_sequence_range (sequence1, start1, end1, make_int (ii));
8389 check_sequence_range (sequence2, start2, end2, make_int (ii));
8390 }
8391 else
8392 {
8393 assert ((pcursor - p) > 0);
8394 staging = alloca_ibytes (pcursor - p);
8395 memcpy (staging, p, pcursor - p);
8396 replace_string_range (result, start1,
8397 make_int (starting1),
8398 staging, staging + (pcursor - p));
8399 }
8400 }
8401 else
8402 {
8403 Elemcount seq_len = XINT (Flength (sequence2)), ii = 0,
8404 subseq_len = min (min (ending1 - starting1, seq_len - starting1),
8405 min (ending2 - starting2, seq_len - starting2));
8406 Lisp_Object *subsequence = alloca_array (Lisp_Object, subseq_len);
8407
8408 check_sequence_range (sequence1, start1, end1, make_int (seq_len));
8409 check_sequence_range (sequence2, start2, end2, make_int (seq_len));
8410
8411 while (starting2 < ending2 && ii < seq_len)
8412 {
8413 subsequence[ii] = Faref (sequence2, make_int (starting2));
8414 ii++, starting2++;
8415 }
8416
8417 ii = 0;
8418
8419 while (starting1 < ending1 && ii < seq_len)
8420 {
8421 Faset (sequence1, make_int (starting1), subsequence[ii]);
8422 ii++, starting1++;
8423 }
8424 }
8425 }
8426 else if (sequence1_listp && sequence2_listp)
8427 {
8428 Lisp_Object sequence1_tortoise = sequence1,
8429 sequence2_tortoise = sequence2;
8430 Elemcount shortest_len = 0;
8431
8432 counting = startcounting = min (ending1, ending2);
8433
8434 while (counting-- > 0 && !NILP (sequence1) && !NILP (sequence2))
8435 {
8436 XSETCAR (sequence1,
8437 CONSP (sequence2) ? XCAR (sequence2)
8438 : Fcar (sequence2));
8439 sequence1 = CONSP (sequence1) ? XCDR (sequence1)
8440 : Fcdr (sequence1);
8441 sequence2 = CONSP (sequence2) ? XCDR (sequence2)
8442 : Fcdr (sequence2);
8443
8444 shortest_len++;
8445
8446 if (startcounting - counting > CIRCULAR_LIST_SUSPICION_LENGTH)
8447 {
8448 if (counting & 1)
8449 {
8450 sequence1_tortoise = XCDR (sequence1_tortoise);
8451 sequence2_tortoise = XCDR (sequence2_tortoise);
8452 }
8453
8454 if (EQ (sequence1, sequence1_tortoise))
8455 {
8456 signal_circular_list_error (sequence1);
8457 }
8458
8459 if (EQ (sequence2, sequence2_tortoise))
8460 {
8461 signal_circular_list_error (sequence2);
8462 }
8463 }
8464 }
8465
8466 if (NILP (sequence1))
8467 {
8468 check_sequence_range (args[0], start1, end1,
8469 make_int (XINT (start1) + shortest_len));
8470 }
8471 else if (NILP (sequence2))
8472 {
8473 check_sequence_range (args[1], start2, end2,
8474 make_int (XINT (start2) + shortest_len));
8475 }
8476 }
8477 else if (sequence1_listp)
8478 {
8479 if (STRINGP (sequence2))
8480 {
8481 Ibyte *s2_data = XSTRING_DATA (sequence2),
8482 *s2_end = s2_data + XSTRING_LENGTH (sequence2);
8483 Elemcount char_count = 0;
8484 Lisp_Object character;
8485
8486 while (char_count < starting2 && s2_data < s2_end)
8487 {
8488 INC_IBYTEPTR (s2_data);
8489 char_count++;
8490 }
8491
8492 while (starting1 < ending1 && starting2 < ending2
8493 && s2_data < s2_end && !NILP (sequence1))
8494 {
8495 character = make_char (itext_ichar (s2_data));
8496 CONSP (sequence1) ?
8497 XSETCAR (sequence1, character)
8498 : Fsetcar (sequence1, character);
8499 sequence1 = XCDR (sequence1);
8500 starting1++;
8501 starting2++;
8502 char_count++;
8503 INC_IBYTEPTR (s2_data);
8504 }
8505
8506 if (NILP (sequence1))
8507 {
8508 check_sequence_range (sequence1, start1, end1,
8509 make_int (XINT (start1) + starting1));
8510 }
8511
8512 if (s2_data == s2_end)
8513 {
8514 check_sequence_range (sequence2, start2, end2,
8515 make_int (char_count));
8516 }
8517 }
8518 else
8519 {
8520 Elemcount len2 = XINT (Flength (sequence2));
8521 check_sequence_range (sequence2, start2, end2, make_int (len2));
8522
8523 ending2 = min (ending2, len2);
8524 while (starting2 < ending2
8525 && starting1 < ending1 && !NILP (sequence1))
8526 {
8527 CHECK_CONS (sequence1);
8528 XSETCAR (sequence1, Faref (sequence2, make_int (starting2)));
8529 sequence1 = XCDR (sequence1);
8530 starting1++;
8531 starting2++;
8532 }
8533
8534 if (NILP (sequence1))
8535 {
8536 check_sequence_range (args[0], start1, end1,
8537 make_int (XINT (start1) + starting1));
8538 }
8539 }
8540 }
8541 else if (sequence2_listp)
8542 {
8543 if (STRINGP (sequence1))
8544 {
8545 Elemcount ii = 0, count, len = string_char_length (sequence1);
8546 Ibyte *staging, *cursor;
8547 Lisp_Object obj;
8548
8549 check_sequence_range (sequence1, start1, end1, make_int (len));
8550 ending1 = min (ending1, len);
8551 count = ending1 - starting1;
8552 staging = cursor = alloca_ibytes (count * MAX_ICHAR_LEN);
8553
8554 while (ii < count && !NILP (sequence2))
8555 {
8556 obj = CONSP (sequence2) ? XCAR (sequence2)
8557 : Fcar (sequence2);
8558
8559 CHECK_CHAR_COERCE_INT (obj);
8560 cursor += set_itext_ichar (cursor, XCHAR (obj));
8561 ii++;
8562 sequence2 = XCDR (sequence2);
8563 }
8564
8565 if (NILP (sequence2))
8566 {
8567 check_sequence_range (sequence2, start2, end2,
8568 make_int (XINT (start2) + ii));
8569 }
8570
8571 replace_string_range (result, start1, make_int (XINT (start1) + ii),
8572 staging, cursor);
8573 }
8574 else
8575 {
8576 Elemcount len = XINT (Flength (sequence1));
8577
8578 check_sequence_range (sequence1, start2, end1, make_int (len));
8579 ending1 = min (ending2, min (ending1, len));
8580
8581 while (starting1 < ending1 && !NILP (sequence2))
8582 {
8583 Faset (sequence1, make_int (starting1),
8584 CONSP (sequence2) ? XCAR (sequence2)
8585 : Fcar (sequence2));
8586 sequence2 = XCDR (sequence2);
8587 starting1++;
8588 starting2++;
8589 }
8590
8591 if (NILP (sequence2))
8592 {
8593 check_sequence_range (args[1], start2, end2,
8594 make_int (XINT (start2) + starting2));
8595 }
8596 }
8597 }
8598 else
8599 {
8600 if (STRINGP (sequence1) && STRINGP (sequence2))
8601 {
8602 Ibyte *p2 = XSTRING_DATA (sequence2),
8603 *p2end = p2 + XSTRING_LENGTH (sequence2), *p2cursor;
8604 Charcount ii = 0, len1 = string_char_length (sequence1);
8605
8606 check_sequence_range (sequence1, start1, end1, make_int (len1));
8607
8608 while (ii < starting2 && p2 < p2end)
8609 {
8610 INC_IBYTEPTR (p2);
8611 ii++;
8612 }
8613
8614 p2cursor = p2;
8615 ending1 = min (ending1, len1);
8616
8617 while (ii < ending2 && starting1 < ending1 && p2cursor < p2end)
8618 {
8619 INC_IBYTEPTR (p2cursor);
8620 ii++;
8621 starting1++;
8622 }
8623
8624 if (p2cursor == p2end)
8625 {
8626 check_sequence_range (sequence2, start2, end2, make_int (ii));
8627 }
8628
8629 /* This isn't great; any error message won't necessarily reflect
8630 the END1 that was supplied to #'replace. */
8631 replace_string_range (result, start1, make_int (starting1),
8632 p2, p2cursor);
8633 }
8634 else if (STRINGP (sequence1))
8635 {
8636 Ibyte *staging, *cursor;
8637 Elemcount count, len1 = string_char_length (sequence1);
8638 Elemcount len2 = XINT (Flength (sequence2)), ii = 0;
8639 Lisp_Object obj;
8640
8641 check_sequence_range (sequence1, start1, end1, make_int (len1));
8642 check_sequence_range (sequence2, start2, end2, make_int (len2));
8643
8644 ending1 = min (ending1, len1);
8645 ending2 = min (ending2, len2);
8646 count = min (ending1 - starting1, ending2 - starting2);
8647 staging = cursor = alloca_ibytes (count * MAX_ICHAR_LEN);
8648
8649 ii = 0;
8650 while (ii < count)
8651 {
8652 obj = Faref (sequence2, make_int (starting2));
8653
8654 CHECK_CHAR_COERCE_INT (obj);
8655 cursor += set_itext_ichar (cursor, XCHAR (obj));
8656 starting2++, ii++;
8657 }
8658
8659 replace_string_range (result, start1,
8660 make_int (XINT (start1) + count),
8661 staging, cursor);
8662 }
8663 else if (STRINGP (sequence2))
8664 {
8665 Ibyte *p2 = XSTRING_DATA (sequence2),
8666 *p2end = p2 + XSTRING_LENGTH (sequence2);
8667 Elemcount len1 = XINT (Flength (sequence1)), ii = 0;
8668
8669 check_sequence_range (sequence1, start1, end1, make_int (len1));
8670 ending1 = min (ending1, len1);
8671
8672 while (ii < starting2 && p2 < p2end)
8673 {
8674 INC_IBYTEPTR (p2);
8675 ii++;
8676 }
8677
8678 while (p2 < p2end && starting1 < ending1 && starting2 < ending2)
8679 {
8680 Faset (sequence1, make_int (starting1),
8681 make_char (itext_ichar (p2)));
8682 INC_IBYTEPTR (p2);
8683 starting1++;
8684 starting2++;
8685 ii++;
8686 }
8687
8688 if (p2 == p2end)
8689 {
8690 check_sequence_range (sequence2, start2, end2, make_int (ii));
8691 }
8692 }
8693 else
8694 {
8695 Elemcount len1 = XINT (Flength (sequence1)),
8696 len2 = XINT (Flength (sequence2));
8697
8698 check_sequence_range (sequence1, start1, end1, make_int (len1));
8699 check_sequence_range (sequence2, start2, end2, make_int (len2));
8700
8701 ending1 = min (ending1, len1);
8702 ending2 = min (ending2, len2);
8703
8704 while (starting1 < ending1 && starting2 < ending2)
8705 {
8706 Faset (sequence1, make_int (starting1),
8707 Faref (sequence2, make_int (starting2)));
8708 starting1++;
8709 starting2++;
8710 }
8711 }
8712 }
8713
8714 return result;
8715 }
8716
8717 DEFUN ("nsubstitute", Fnsubstitute, 3, MANY, 0, /*
8718 Substitute NEW for OLD in SEQUENCE.
8719
8720 This is a destructive function; it reuses the storage of SEQUENCE whenever
8721 possible. See `remove*' for the meaning of the keywords.
8722
8723 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT)
8724 */
8725 (int nargs, Lisp_Object *args))
8726 {
8727 Lisp_Object new_ = args[0], item = args[1], sequence = args[2];
8728 Lisp_Object object_, position0;
8729 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
8730 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0;
8731 Boolint test_not_unboundp = 1;
8732 check_test_func_t check_test = NULL;
8733
8734 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9,
8735 (test, if_, if_not, test_not, key, start, end, count,
8736 from_end), (start = Qzero));
8737
8738 CHECK_SEQUENCE (sequence);
8739 CHECK_NATNUM (start);
8740 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
8741
8742 if (!NILP (end))
8743 {
8744 CHECK_NATNUM (end);
8745 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
8746 }
8747
8748 if (!NILP (count))
8749 {
8750 CHECK_INTEGER (count);
8751 if (INTP (count))
8752 {
8753 counting = XINT (count);
8754 }
8755 #ifdef HAVE_BIGNUM
8756 else
8757 {
8758 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
8759 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN;
8760 }
8761 #endif
8762
8763 if (counting <= 0)
8764 {
8765 return sequence;
8766 }
8767 }
8768
8769 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
8770 key, &test_not_unboundp);
8771
8772 if (CONSP (sequence))
8773 {
8774 if (!NILP (count) && !NILP (from_end))
8775 {
8776 Lisp_Object present = count_with_tail (&object_, nargs - 1, args + 1,
8777 Qnsubstitute);
8778
8779 if (ZEROP (present))
8780 {
8781 return sequence;
8782 }
8783
8784 presenting = XINT (present);
8785 presenting = presenting <= counting ? 0 : presenting - counting;
8786 }
8787
8788 {
8789 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
8790 {
8791 if (!(ii < ending))
8792 {
8793 break;
8794 }
8795
8796 if (starting <= ii &&
8797 check_test (test, key, item, elt) == test_not_unboundp
8798 && (presenting ? encountered++ >= presenting
8799 : encountered++ < counting))
8800 {
8801 CHECK_LISP_WRITEABLE (tail);
8802 XSETCAR (tail, new_);
8803 }
8804 else if (!presenting && encountered >= counting)
8805 {
8806 break;
8807 }
8808
8809 ii++;
8810 }
8811 END_GC_EXTERNAL_LIST_LOOP (elt);
8812 }
8813
8814 if ((ii < starting || (ii < ending && !NILP (end)))
8815 && encountered < counting)
8816 {
8817 check_sequence_range (args[0], start, end, Flength (args[0]));
8818 }
8819 }
8820 else if (STRINGP (sequence))
8821 {
8822 Ibyte *staging, new_bytes[MAX_ICHAR_LEN], *staging_cursor;
8823 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp;
8824 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence);
8825 Bytecount new_len;
8826 Lisp_Object character;
8827
8828 CHECK_CHAR_COERCE_INT (new_);
8829
8830 new_len = set_itext_ichar (new_bytes, XCHAR (new_));
8831
8832 /* Worst case scenario; new char is four octets long, all the old ones
8833 were one octet long, all the old ones match. */
8834 staging = alloca_ibytes (XSTRING_LENGTH (sequence) * new_len);
8835 staging_cursor = staging;
8836
8837 if (!NILP (count) && !NILP (from_end))
8838 {
8839 Lisp_Object present = count_with_tail (&character, nargs - 1,
8840 args + 1, Qnsubstitute);
8841
8842 if (ZEROP (present))
8843 {
8844 return sequence;
8845 }
8846
8847 presenting = XINT (present);
8848
8849 /* If there are fewer items in the string than we have
8850 permission to change, we don't need to differentiate
8851 between the :from-end nil and :from-end t
8852 cases. Otherwise, presenting is the number of matching
8853 items we need to ignore before we start to change. */
8854 presenting = presenting <= counting ? 0 : presenting - counting;
8855 }
8856
8857 ii = 0;
8858 while (cursor_offset < byte_len && ii < ending)
8859 {
8860 if (ii >= starting)
8861 {
8862 character = make_char (itext_ichar (cursor));
8863
8864 if ((check_test (test, key, item, character)
8865 == test_not_unboundp)
8866 && (presenting ? encountered++ >= presenting :
8867 encountered++ < counting))
8868 {
8869 staging_cursor
8870 += itext_copy_ichar (new_bytes, staging_cursor);
8871 }
8872 else
8873 {
8874 staging_cursor
8875 += itext_copy_ichar (cursor, staging_cursor);
8876 }
8877
8878 startp = XSTRING_DATA (sequence);
8879 cursor = startp + cursor_offset;
8880
8881 if (byte_len != XSTRING_LENGTH (sequence)
8882 || !valid_ibyteptr_p (cursor))
8883 {
8884 mapping_interaction_error (Qnsubstitute, sequence);
8885 }
8886 }
8887 else
8888 {
8889 staging_cursor += itext_copy_ichar (cursor, staging_cursor);
8890 }
8891
8892 INC_IBYTEPTR (cursor);
8893 cursor_offset = cursor - startp;
8894 ii++;
8895 }
8896
8897 if (ii < starting || (ii < ending && !NILP (end)))
8898 {
8899 check_sequence_range (sequence, start, end, Flength (sequence));
8900 }
8901
8902 if (0 != encountered)
8903 {
8904 CHECK_LISP_WRITEABLE (sequence);
8905 replace_string_range (sequence, Qzero, make_int (ii),
8906 staging, staging_cursor);
8907 }
8908 }
8909 else
8910 {
8911 Elemcount positioning;
8912 Lisp_Object object = Qnil;
8913
8914 len = XINT (Flength (sequence));
8915 check_sequence_range (sequence, start, end, make_int (len));
8916
8917 position0 = position (&object, item, sequence, check_test,
8918 test_not_unboundp, test, key, start, end, from_end,
8919 Qnil, Qnsubstitute);
8920
8921 if (NILP (position0))
8922 {
8923 return sequence;
8924 }
8925
8926 positioning = XINT (position0);
8927 ending = min (len, ending);
8928
8929 Faset (sequence, position0, new_);
8930 encountered = 1;
8931
8932 if (NILP (from_end))
8933 {
8934 for (ii = positioning + 1; ii < ending; ii++)
8935 {
8936 object_ = Faref (sequence, make_int (ii));
8937
8938 if (check_test (test, key, item, object_) == test_not_unboundp
8939 && encountered++ < counting)
8940 {
8941 Faset (sequence, make_int (ii), new_);
8942 }
8943 else if (encountered == counting)
8944 {
8945 break;
8946 }
8947 }
8948 }
8949 else
8950 {
8951 for (ii = positioning - 1; ii >= starting; ii--)
8952 {
8953 object_ = Faref (sequence, make_int (ii));
8954
8955 if (check_test (test, key, item, object_) == test_not_unboundp
8956 && encountered++ < counting)
8957 {
8958 Faset (sequence, make_int (ii), new_);
8959 }
8960 else if (encountered == counting)
8961 {
8962 break;
8963 }
8964 }
8965 }
8966 }
8967
8968 return sequence;
8969 }
8970
8971 DEFUN ("substitute", Fsubstitute, 3, MANY, 0, /*
8972 Substitute NEW for OLD in SEQUENCE.
8973
8974 This is a non-destructive function; it makes a copy of SEQUENCE if necessary
8975 to avoid corrupting the original SEQUENCE.
8976
8977 See `remove*' for the meaning of the keywords.
8978
8979 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT)
8980 */
8981 (int nargs, Lisp_Object *args))
8982 {
8983 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil;
8984 Lisp_Object result = Qnil, result_tail = Qnil;
8985 Lisp_Object object, position0, matched_count;
8986 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0;
8987 Elemcount ii = 0, counting = EMACS_INT_MAX, presenting = 0;
8988 Boolint test_not_unboundp = 1;
8989 check_test_func_t check_test = NULL;
8990 struct gcpro gcpro1;
8991
8992 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9,
8993 (test, if_, if_not, test_not, key, start, end, count,
8994 from_end), (start = Qzero, count = Qunbound));
8995
8996 CHECK_SEQUENCE (sequence);
8997
8998 CHECK_NATNUM (start);
8999 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start);
9000
9001 if (!NILP (end))
9002 {
9003 CHECK_NATNUM (end);
9004 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end);
9005 }
9006
9007 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
9008 key, &test_not_unboundp);
9009
9010 if (!UNBOUNDP (count))
9011 {
9012 if (!NILP (count))
9013 {
9014 CHECK_INTEGER (count);
9015 if (INTP (count))
9016 {
9017 counting = XINT (count);
9018 }
9019 #ifdef HAVE_BIGNUM
9020 else
9021 {
9022 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
9023 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN;
9024 }
9025 #endif
9026
9027 if (counting <= 0)
9028 {
9029 return sequence;
9030 }
9031 }
9032 }
9033
9034 if (!CONSP (sequence))
9035 {
9036 position0 = position (&object, item, sequence, check_test,
9037 test_not_unboundp, test, key, start, end, from_end,
9038 Qnil, Qsubstitute);
9039
9040 if (NILP (position0))
9041 {
9042 return sequence;
9043 }
9044 else
9045 {
9046 args[2] = Fcopy_sequence (sequence);
9047 return Fnsubstitute (nargs, args);
9048 }
9049 }
9050
9051 matched_count = count_with_tail (&tail, nargs - 1, args + 1, Qsubstitute);
9052
9053 if (ZEROP (matched_count))
9054 {
9055 return sequence;
9056 }
9057
9058 if (!NILP (count) && !NILP (from_end))
9059 {
9060 presenting = XINT (matched_count);
9061 presenting = presenting <= counting ? 0 : presenting - counting;
9062 }
9063
9064 GCPRO1 (result);
9065 {
9066 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
9067 {
9068 if (EQ (tail, tailing))
9069 {
9070 XUNGCPRO (elt);
9071 UNGCPRO;
9072
9073 if (NILP (result))
9074 {
9075 return XCDR (tail);
9076 }
9077
9078 XSETCDR (result_tail, XCDR (tail));
9079 return result;
9080 }
9081 else if (starting <= ii && ii < ending &&
9082 (check_test (test, key, item, elt) == test_not_unboundp)
9083 && (presenting ? encountered++ >= presenting
9084 : encountered++ < counting))
9085 {
9086 if (NILP (result))
9087 {
9088 result = result_tail = Fcons (new_, Qnil);
9089 }
9090 else
9091 {
9092 XSETCDR (result_tail, Fcons (new_, Qnil));
9093 result_tail = XCDR (result_tail);
9094 }
9095 }
9096 else if (NILP (result))
9097 {
9098 result = result_tail = Fcons (elt, Qnil);
9099 }
9100 else
9101 {
9102 XSETCDR (result_tail, Fcons (elt, Qnil));
9103 result_tail = XCDR (result_tail);
9104 }
9105
9106 if (ii == ending)
9107 {
9108 break;
9109 }
9110
9111 ii++;
9112 }
9113 END_GC_EXTERNAL_LIST_LOOP (elt);
9114 }
9115 UNGCPRO;
9116
9117 if (ii < starting || (ii < ending && !NILP (end)))
9118 {
9119 check_sequence_range (args[0], start, end, Flength (args[0]));
9120 }
9121
9122 return result;
9123 }
9124
9125 static Lisp_Object
9126 subst (Lisp_Object new_, Lisp_Object old, Lisp_Object tree, int depth)
9127 {
9128 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9129 {
9130 stack_overflow ("Stack overflow in subst", tree);
9131 }
9132
9133 if (EQ (tree, old))
9134 {
9135 return new_;
9136 }
9137 else if (CONSP (tree))
9138 {
9139 Lisp_Object aa = subst (new_, old, XCAR (tree), depth + 1);
9140 Lisp_Object dd = subst (new_, old, XCDR (tree), depth + 1);
9141
9142 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree)))
9143 {
9144 return tree;
9145 }
9146 else
9147 {
9148 return Fcons (aa, dd);
9149 }
9150 }
9151 else
9152 {
9153 return tree;
9154 }
9155 }
9156
9157 static Lisp_Object
9158 sublis (Lisp_Object alist, Lisp_Object tree,
9159 check_test_func_t check_test, Boolint test_not_unboundp,
9160 Lisp_Object test, Lisp_Object key, int depth)
9161 {
9162 Lisp_Object keyed = KEY (key, tree), aa, dd;
9163 struct gcpro gcpro1;
9164
9165 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9166 {
9167 stack_overflow ("Stack overflow in sublis", tree);
9168 }
9169
9170 {
9171 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9172 {
9173 if (CONSP (elt) &&
9174 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9175 {
9176 XUNGCPRO (elt);
9177 return XCDR (elt);
9178 }
9179 }
9180 END_GC_EXTERNAL_LIST_LOOP (elt);
9181 }
9182
9183 if (!CONSP (tree))
9184 {
9185 return tree;
9186 }
9187
9188 aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key,
9189 depth + 1);
9190 dd = sublis (alist, XCDR (tree), check_test, test_not_unboundp, test, key,
9191 depth + 1);
9192
9193 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree)))
9194 {
9195 return tree;
9196 }
9197
9198 return Fcons (aa, dd);
9199 }
9200
9201 DEFUN ("sublis", Fsublis, 2, MANY, 0, /*
9202 Perform substitutions indicated by ALIST in TREE (non-destructively).
9203 Return a copy of TREE with all matching elements replaced.
9204
9205 See `member*' for the meaning of :test, :test-not and :key.
9206
9207 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9208 */
9209 (int nargs, Lisp_Object *args))
9210 {
9211 Lisp_Object alist = args[0], tree = args[1];
9212 Boolint test_not_unboundp = 1;
9213 check_test_func_t check_test = NULL;
9214
9215 PARSE_KEYWORDS (Fsublis, nargs, args, 5, (test, if_, test_not, if_not, key),
9216 (key = Qidentity));
9217
9218 if (NILP (key))
9219 {
9220 key = Qidentity;
9221 }
9222
9223 get_check_match_function (&test, test_not, if_, if_not,
9224 /* sublis() is going to apply the key, don't ask
9225 for a match function that will do it for
9226 us. */
9227 Qidentity, &test_not_unboundp, &check_test);
9228
9229 if (CONSP (alist) && NILP (XCDR (alist)) && CONSP (XCAR (alist))
9230 && EQ (key, Qidentity) && 1 == test_not_unboundp
9231 && (check_eq_nokey == check_test ||
9232 (check_eql_nokey == check_test &&
9233 !NON_FIXNUM_NUMBER_P (XCAR (XCAR (alist))))))
9234 {
9235 /* #'subst with #'eq is very cheap indeed; call it. */
9236 return subst (XCDR (XCAR (alist)), XCAR (XCAR (alist)), tree, 0);
9237 }
9238
9239 return sublis (alist, tree, check_test, test_not_unboundp, test, key, 0);
9240 }
9241
9242 static Lisp_Object
9243 nsublis (Lisp_Object alist, Lisp_Object tree,
9244 check_test_func_t check_test,
9245 Boolint test_not_unboundp,
9246 Lisp_Object test, Lisp_Object key, int depth)
9247 {
9248 Lisp_Object tree_saved = tree, tortoise = tree, keyed = Qnil;
9249 struct gcpro gcpro1, gcpro2;
9250 int count = 0;
9251
9252 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9253 {
9254 stack_overflow ("Stack overflow in nsublis", tree);
9255 }
9256
9257 GCPRO2 (tree_saved, keyed);
9258
9259 while (CONSP (tree))
9260 {
9261 Boolint replaced = 0;
9262 keyed = KEY (key, XCAR (tree));
9263
9264 {
9265 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9266 {
9267 if (CONSP (elt) &&
9268 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9269 {
9270 CHECK_LISP_WRITEABLE (tree);
9271 /* See comment in sublis() on using elt_cdr. */
9272 XSETCAR (tree, XCDR (elt));
9273 replaced = 1;
9274 break;
9275 }
9276 }
9277 END_GC_EXTERNAL_LIST_LOOP (elt);
9278 }
9279
9280 if (!replaced)
9281 {
9282 if (CONSP (XCAR (tree)))
9283 {
9284 nsublis (alist, XCAR (tree), check_test, test_not_unboundp,
9285 test, key, depth + 1);
9286 }
9287 }
9288
9289 keyed = KEY (key, XCDR (tree));
9290 replaced = 0;
9291
9292 {
9293 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9294 {
9295 if (CONSP (elt) &&
9296 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9297 {
9298 CHECK_LISP_WRITEABLE (tree);
9299 XSETCDR (tree, XCDR (elt));
9300 tree = Qnil;
9301 break;
9302 }
9303 }
9304 END_GC_EXTERNAL_LIST_LOOP (elt);
9305 }
9306
9307 if (!NILP (tree))
9308 {
9309 tree = XCDR (tree);
9310 }
9311
9312 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH)
9313 {
9314 if (count & 1)
9315 {
9316 tortoise = XCDR (tortoise);
9317 }
9318
9319 if (EQ (tortoise, tree))
9320 {
9321 signal_circular_list_error (tree);
9322 }
9323 }
9324 }
9325
9326 RETURN_UNGCPRO (tree_saved);
9327 }
9328
9329 DEFUN ("nsublis", Fnsublis, 2, MANY, 0, /*
9330 Perform substitutions indicated by ALIST in TREE (destructively).
9331 Any matching element of TREE is changed via a call to `setcar'.
9332
9333 See `member*' for the meaning of :test, :test-not and :key.
9334
9335 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9336 */
9337 (int nargs, Lisp_Object *args))
9338 {
9339 Lisp_Object alist = args[0], tree = args[1], tailed = Qnil, keyed = Qnil;
9340 Boolint test_not_unboundp = 1;
9341 check_test_func_t check_test = NULL;
9342 struct gcpro gcpro1, gcpro2;
9343
9344 PARSE_KEYWORDS (Fnsublis, nargs, args, 5, (test, if_, test_not, if_not, key),
9345 (key = Qidentity));
9346
9347 if (NILP (key))
9348 {
9349 key = Qidentity;
9350 }
9351
9352 get_check_match_function (&test, test_not, if_, if_not,
9353 /* nsublis() is going to apply the key, don't ask
9354 for a match function that will do it for
9355 us. */
9356 Qidentity, &test_not_unboundp, &check_test);
9357
9358 GCPRO2 (tailed, keyed);
9359
9360 keyed = KEY (key, tree);
9361
9362 {
9363 /* nsublis() won't attempt to replace a cons handed to it, do that
9364 ourselves. */
9365 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9366 {
9367 if (CONSP (elt) &&
9368 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9369 {
9370 XUNGCPRO (elt);
9371 return XCDR (elt);
9372 }
9373 }
9374 END_GC_EXTERNAL_LIST_LOOP (elt);
9375 }
9376
9377 UNGCPRO;
9378
9379 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0);
9380 }
9381
9382 DEFUN ("subst", Fsubst, 3, MANY, 0, /*
9383 Substitute NEW for OLD everywhere in TREE (non-destructively).
9384
9385 Return a copy of TREE with all elements `eql' to OLD replaced by NEW.
9386
9387 See `member*' for the meaning of :test, :test-not and :key.
9388
9389 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9390 */
9391 (int nargs, Lisp_Object *args))
9392 {
9393 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]),
9394 Qnil);
9395 args[1] = alist;
9396 result = Fsublis (nargs - 1, args + 1);
9397 free_cons (XCAR (alist));
9398 free_cons (alist);
9399
9400 return result;
9401 }
9402
9403 DEFUN ("nsubst", Fnsubst, 3, MANY, 0, /*
9404 Substitute NEW for OLD everywhere in TREE (destructively).
9405
9406 Any element of TREE which is `eql' to OLD is changed to NEW (via a call to
9407 `setcar').
9408
9409 See `member*' for the meaning of the keywords.
9410
9411 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9412 */
9413 (int nargs, Lisp_Object *args))
9414 {
9415 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]),
9416 Qnil);
9417 args[1] = alist;
9418 result = Fnsublis (nargs - 1, args + 1);
9419 free_cons (XCAR (alist));
9420 free_cons (alist);
9421
9422 return result;
9423 }
9424
9425 static Boolint
9426 tree_equal (Lisp_Object tree1, Lisp_Object tree2,
9427 check_test_func_t check_test, Boolint test_not_unboundp,
9428 Lisp_Object test, Lisp_Object key, int depth)
9429 {
9430 Lisp_Object tortoise1 = tree1, tortoise2 = tree2;
9431 struct gcpro gcpro1, gcpro2;
9432 int count = 0;
9433 Boolint result;
9434
9435 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9436 {
9437 stack_overflow ("Stack overflow in tree-equal", tree1);
9438 }
9439
9440 GCPRO2 (tree1, tree2);
9441
9442 while (CONSP (tree1) && CONSP (tree2)
9443 && tree_equal (XCAR (tree1), XCAR (tree2), check_test,
9444 test_not_unboundp, test, key, depth + 1))
9445 {
9446 tree1 = XCDR (tree1);
9447 tree2 = XCDR (tree2);
9448
9449 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH)
9450 {
9451 if (count & 1)
9452 {
9453 tortoise1 = XCDR (tortoise1);
9454 tortoise2 = XCDR (tortoise2);
9455 }
9456
9457 if (EQ (tortoise1, tree1))
9458 {
9459 signal_circular_list_error (tree1);
9460 }
9461
9462 if (EQ (tortoise2, tree2))
9463 {
9464 signal_circular_list_error (tree2);
9465 }
9466 }
9467 }
9468
9469 if (CONSP (tree1) || CONSP (tree2))
9470 {
9471 UNGCPRO;
9472 return 0;
9473 }
9474
9475 result = check_test (test, key, tree1, tree2) == test_not_unboundp;
9476 UNGCPRO;
9477
9478 return result;
9479 }
9480
9481 DEFUN ("tree-equal", Ftree_equal, 2, MANY, 0, /*
9482 Return t if TREE1 and TREE2 have `eql' leaves.
9483
9484 Atoms are compared by `eql', unless another test is specified using
9485 :test; cons cells are compared recursively.
9486
9487 See `union' for the meaning of :test, :test-not and :key.
9488
9489 arguments: (TREE1 TREE2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9490 */
9491 (int nargs, Lisp_Object *args))
9492 {
9493 Lisp_Object tree1 = args[0], tree2 = args[1];
9494 Boolint test_not_unboundp = 1;
9495 check_test_func_t check_test = NULL;
9496
9497 PARSE_KEYWORDS (Ftree_equal, nargs, args, 3, (test, key, test_not),
9498 (key = Qidentity));
9499
9500 get_check_match_function (&test, test_not, Qnil, Qnil, key,
9501 &test_not_unboundp, &check_test);
9502
9503 return tree_equal (tree1, tree2, check_test, test_not_unboundp, test, key,
9504 0) ? Qt : Qnil;
9505 }
9506
9507 static Lisp_Object
9508 mismatch_from_end (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1,
9509 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2,
9510 check_test_func_t check_match, Boolint test_not_unboundp,
9511 Lisp_Object test, Lisp_Object key,
9512 Boolint UNUSED (return_sequence1_index))
9513 {
9514 Elemcount sequence1_len = XINT (Flength (sequence1));
9515 Elemcount sequence2_len = XINT (Flength (sequence2)), ii = 0;
9516 Elemcount starting1, ending1, starting2, ending2;
9517 Lisp_Object *sequence1_storage = NULL, *sequence2_storage = NULL;
9518 struct gcpro gcpro1, gcpro2;
9519
9520 check_sequence_range (sequence1, start1, end1, make_int (sequence1_len));
9521 starting1 = XINT (start1);
9522 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX;
9523 ending1 = min (ending1, sequence1_len);
9524
9525 check_sequence_range (sequence2, start2, end2, make_int (sequence2_len));
9526 starting2 = XINT (start2);
9527 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX;
9528 ending2 = min (ending2, sequence2_len);
9529
9530 if (LISTP (sequence1))
9531 {
9532 Lisp_Object *saving;
9533 sequence1_storage = saving
9534 = alloca_array (Lisp_Object, ending1 - starting1);
9535
9536 {
9537 EXTERNAL_LIST_LOOP_2 (elt, sequence1)
9538 {
9539 if (starting1 <= ii && ii < ending1)
9540 {
9541 *saving++ = elt;
9542 }
9543 else if (ii == ending1)
9544 {
9545 break;
9546 }
9547
9548 ++ii;
9549 }
9550 }
9551 }
9552 else if (STRINGP (sequence1))
9553 {
9554 const Ibyte *cursor = string_char_addr (sequence1, starting1);
9555
9556 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence1_storage, ii,
9557 ending1 - starting1);
9558
9559 }
9560 else if (BIT_VECTORP (sequence1))
9561 {
9562 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence1);
9563 sequence1_storage = alloca_array (Lisp_Object, ending1 - starting1);
9564 for (ii = starting1; ii < ending1; ++ii)
9565 {
9566 sequence1_storage[ii - starting1]
9567 = make_int (bit_vector_bit (vv, ii));
9568 }
9569 }
9570 else
9571 {
9572 sequence1_storage = XVECTOR_DATA (sequence1) + starting1;
9573 }
9574
9575 ii = 0;
9576
9577 if (LISTP (sequence2))
9578 {
9579 Lisp_Object *saving;
9580 sequence2_storage = saving
9581 = alloca_array (Lisp_Object, ending2 - starting2);
9582
9583 {
9584 EXTERNAL_LIST_LOOP_2 (elt, sequence2)
9585 {
9586 if (starting2 <= ii && ii < ending2)
9587 {
9588 *saving++ = elt;
9589 }
9590 else if (ii == ending2)
9591 {
9592 break;
9593 }
9594
9595 ++ii;
9596 }
9597 }
9598 }
9599 else if (STRINGP (sequence2))
9600 {
9601 const Ibyte *cursor = string_char_addr (sequence2, starting2);
9602
9603 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence2_storage, ii,
9604 ending2 - starting2);
9605
9606 }
9607 else if (BIT_VECTORP (sequence2))
9608 {
9609 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence2);
9610 sequence2_storage = alloca_array (Lisp_Object, ending2 - starting2);
9611 for (ii = starting2; ii < ending2; ++ii)
9612 {
9613 sequence2_storage[ii - starting2]
9614 = make_int (bit_vector_bit (vv, ii));
9615 }
9616 }
9617 else
9618 {
9619 sequence2_storage = XVECTOR_DATA (sequence2) + starting2;
9620 }
9621
9622 GCPRO2 (sequence1_storage[0], sequence2_storage[0]);
9623 gcpro1.nvars = ending1 - starting1;
9624 gcpro2.nvars = ending2 - starting2;
9625
9626 while (ending1 > starting1 && ending2 > starting2)
9627 {
9628 --ending1;
9629 --ending2;
9630
9631 if (check_match (test, key, sequence1_storage[ending1 - starting1],
9632 sequence2_storage[ending2 - starting2])
9633 != test_not_unboundp)
9634 {
9635 UNGCPRO;
9636 return make_integer (ending1 + 1);
9637 }
9638 }
9639
9640 UNGCPRO;
9641
9642 if (ending1 > starting1 || ending2 > starting2)
9643 {
9644 return make_integer (ending1);
9645 }
9646
9647 return Qnil;
9648 }
9649
9650 static Lisp_Object
9651 mismatch_list_list (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1,
9652 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2,
9653 check_test_func_t check_match, Boolint test_not_unboundp,
9654 Lisp_Object test, Lisp_Object key,
9655 Boolint UNUSED (return_list_index))
9656 {
9657 Lisp_Object sequence1_tortoise = sequence1, sequence2_tortoise = sequence2;
9658 Lisp_Object orig_sequence1 = sequence1, orig_sequence2 = sequence2;
9659 Elemcount ending1 = EMACS_INT_MAX, ending2 = EMACS_INT_MAX;
9660 Elemcount starting1, starting2, counting, startcounting;
9661 Elemcount shortest_len = 0;
9662 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9663
9664 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX;
9665 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX;
9666
9667 if (!NILP (end1))
9668 {
9669 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX;
9670 }
9671
9672 if (!NILP (end2))
9673 {
9674 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX;
9675 }
9676
9677 if (!ZEROP (start1))
9678 {
9679 sequence1 = Fnthcdr (start1, sequence1);
9680
9681 if (NILP (sequence1))
9682 {
9683 check_sequence_range (sequence1_tortoise, start1, end1,
9684 Flength (sequence1_tortoise));
9685 /* Give up early here. */
9686 return Qnil;
9687 }
9688
9689 ending1 -= starting1;
9690 starting1 = 0;
9691 sequence1_tortoise = sequence1;
9692 }
9693
9694 if (!ZEROP (start2))
9695 {
9696 sequence2 = Fnthcdr (start2, sequence2);
9697
9698 if (NILP (sequence2))
9699 {
9700 check_sequence_range (sequence2_tortoise, start2, end2,
9701 Flength (sequence2_tortoise));
9702 return Qnil;
9703 }
9704
9705 ending2 -= starting2;
9706 starting2 = 0;
9707 sequence2_tortoise = sequence2;
9708 }
9709
9710 GCPRO4 (sequence1, sequence2, sequence1_tortoise, sequence2_tortoise);
9711
9712 counting = startcounting = min (ending1, ending2);
9713
9714 while (counting-- > 0 && !NILP (sequence1) && !NILP (sequence2))
9715 {
9716 if (check_match (test, key,
9717 CONSP (sequence1) ? XCAR (sequence1)
9718 : Fcar (sequence1),
9719 CONSP (sequence2) ? XCAR (sequence2)
9720 : Fcar (sequence2) ) != test_not_unboundp)
9721 {
9722 UNGCPRO;
9723 return make_integer (XINT (start1) + shortest_len);
9724 }
9725
9726 sequence1 = CONSP (sequence1) ? XCDR (sequence1) : Fcdr (sequence1);
9727 sequence2 = CONSP (sequence2) ? XCDR (sequence2) : Fcdr (sequence2);
9728
9729 shortest_len++;
9730
9731 if (startcounting - counting > CIRCULAR_LIST_SUSPICION_LENGTH)
9732 {
9733 if (counting & 1)
9734 {
9735 sequence1_tortoise = XCDR (sequence1_tortoise);
9736 sequence2_tortoise = XCDR (sequence2_tortoise);
9737 }
9738
9739 if (EQ (sequence1, sequence1_tortoise))
9740 {
9741 signal_circular_list_error (sequence1);
9742 }
9743
9744 if (EQ (sequence2, sequence2_tortoise))
9745 {
9746 signal_circular_list_error (sequence2);
9747 }
9748 }
9749 }
9750
9751 UNGCPRO;
9752
9753 if (NILP (sequence1))
9754 {
9755 Lisp_Object args[] = { start1, make_int (shortest_len) };
9756 check_sequence_range (orig_sequence1, start1, end1,
9757 Fplus (countof (args), args));
9758 }
9759
9760 if (NILP (sequence2))
9761 {
9762 Lisp_Object args[] = { start2, make_int (shortest_len) };
9763 check_sequence_range (orig_sequence2, start2, end2,
9764 Fplus (countof (args), args));
9765 }
9766
9767 if ((!NILP (end1) && shortest_len != ending1 - starting1) ||
9768 (!NILP (end2) && shortest_len != ending2 - starting2))
9769 {
9770 return make_integer (XINT (start1) + shortest_len);
9771 }
9772
9773 if ((NILP (end1) && CONSP (sequence1)) || (NILP (end2) && CONSP (sequence2)))
9774 {
9775 return make_integer (XINT (start1) + shortest_len);
9776 }
9777
9778 return Qnil;
9779 }
9780
9781 static Lisp_Object
9782 mismatch_list_string (Lisp_Object list, Lisp_Object list_start,
9783 Lisp_Object list_end,
9784 Lisp_Object string, Lisp_Object string_start,
9785 Lisp_Object string_end,
9786 check_test_func_t check_match,
9787 Boolint test_not_unboundp,
9788 Lisp_Object test, Lisp_Object key,
9789 Boolint return_list_index)
9790 {
9791 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data;
9792 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string);
9793 Elemcount char_count = 0, list_starting, list_ending;
9794 Elemcount string_starting, string_ending;
9795 Lisp_Object character, orig_list = list;
9796 struct gcpro gcpro1;
9797
9798 list_ending = INTP (list_end) ? XINT (list_end) : 1 + EMACS_INT_MAX;
9799 list_starting = INTP (list_start) ? XINT (list_start) : 1 + EMACS_INT_MAX;
9800
9801 string_ending = INTP (string_end) ? XINT (string_end) : 1 + EMACS_INT_MAX;
9802 string_starting
9803 = INTP (string_start) ? XINT (string_start) : 1 + EMACS_INT_MAX;
9804
9805 while (char_count < string_starting && string_offset < string_len)
9806 {
9807 INC_IBYTEPTR (string_data);
9808 string_offset = string_data - startp;
9809 char_count++;
9810 }
9811
9812 if (!ZEROP (list_start))
9813 {
9814 list = Fnthcdr (list_start, list);
9815 if (NILP (list))
9816 {
9817 check_sequence_range (orig_list, list_start, list_end,
9818 Flength (orig_list));
9819 return Qnil;
9820 }
9821
9822 list_ending -= list_starting;
9823 list_starting = 0;
9824 }
9825
9826 GCPRO1 (list);
9827
9828 while (list_starting < list_ending && string_starting < string_ending
9829 && string_offset < string_len && !NILP (list))
9830 {
9831 character = make_char (itext_ichar (string_data));
9832
9833 if (return_list_index)
9834 {
9835 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list),
9836 character)
9837 != test_not_unboundp)
9838 {
9839 UNGCPRO;
9840 return make_integer (XINT (list_start) + char_count);
9841 }
9842 }
9843 else
9844 {
9845 if (check_match (test, key, character,
9846 CONSP (list) ? XCAR (list) : Fcar (list))
9847 != test_not_unboundp)
9848 {
9849 UNGCPRO;
9850 return make_integer (char_count);
9851 }
9852 }
9853
9854 list = CONSP (list) ? XCDR (list) : Fcdr (list);
9855
9856 startp = XSTRING_DATA (string);
9857 string_data = startp + string_offset;
9858 if (string_len != XSTRING_LENGTH (string)
9859 || !valid_ibyteptr_p (string_data))
9860 {
9861 mapping_interaction_error (Qmismatch, string);
9862 }
9863
9864 list_starting++;
9865 string_starting++;
9866 char_count++;
9867 INC_IBYTEPTR (string_data);
9868 string_offset = string_data - startp;
9869 }
9870
9871 UNGCPRO;
9872
9873 if (NILP (list))
9874 {
9875 Lisp_Object args[] = { list_start, make_int (char_count) };
9876 check_sequence_range (orig_list, list_start, list_end,
9877 Fplus (countof (args), args));
9878 }
9879
9880 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string))
9881 {
9882 check_sequence_range (string, string_start, string_end,
9883 make_int (char_count));
9884 }
9885
9886 if ((NILP (string_end) ?
9887 string_offset < string_len : string_starting < string_ending) ||
9888 (NILP (list_end) ? !NILP (list) : list_starting < list_ending))
9889 {
9890 return make_integer (return_list_index ? XINT (list_start) + char_count :
9891 char_count);
9892 }
9893
9894 return Qnil;
9895 }
9896
9897 static Lisp_Object
9898 mismatch_list_array (Lisp_Object list, Lisp_Object list_start,
9899 Lisp_Object list_end,
9900 Lisp_Object array, Lisp_Object array_start,
9901 Lisp_Object array_end,
9902 check_test_func_t check_match,
9903 Boolint test_not_unboundp,
9904 Lisp_Object test, Lisp_Object key,
9905 Boolint return_list_index)
9906 {
9907 Elemcount ii = 0, list_starting, list_ending;
9908 Elemcount array_starting, array_ending, array_len;
9909 Lisp_Object orig_list = list;
9910 struct gcpro gcpro1;
9911
9912 list_ending = INTP (list_end) ? XINT (list_end) : 1 + EMACS_INT_MAX;
9913 list_starting = INTP (list_start) ? XINT (list_start) : 1 + EMACS_INT_MAX;
9914
9915 array_ending = INTP (array_end) ? XINT (array_end) : 1 + EMACS_INT_MAX;
9916 array_starting = INTP (array_start) ? XINT (array_start) : 1 + EMACS_INT_MAX;
9917 array_len = XINT (Flength (array));
9918
9919 array_ending = min (array_ending, array_len);
9920
9921 check_sequence_range (array, array_start, array_end, make_int (array_len));
9922
9923 if (!ZEROP (list_start))
9924 {
9925 list = Fnthcdr (list_start, list);
9926 if (NILP (list))
9927 {
9928 check_sequence_range (orig_list, list_start, list_end,
9929 Flength (orig_list));
9930 return Qnil;
9931 }
9932
9933 list_ending -= list_starting;
9934 list_starting = 0;
9935 }
9936
9937 GCPRO1 (list);
9938
9939 while (list_starting < list_ending && array_starting < array_ending
9940 && !NILP (list))
9941 {
9942 if (return_list_index)
9943 {
9944 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list),
9945 Faref (array, make_int (array_starting)))
9946 != test_not_unboundp)
9947 {
9948 UNGCPRO;
9949 return make_integer (XINT (list_start) + ii);
9950 }
9951 }
9952 else
9953 {
9954 if (check_match (test, key, Faref (array, make_int (array_starting)),
9955 CONSP (list) ? XCAR (list) : Fcar (list))
9956 != test_not_unboundp)
9957 {
9958 UNGCPRO;
9959 return make_integer (array_starting);
9960 }
9961 }
9962
9963 list = CONSP (list) ? XCDR (list) : Fcdr (list);
9964 list_starting++;
9965 array_starting++;
9966 ii++;
9967 }
9968
9969 UNGCPRO;
9970
9971 if (NILP (list))
9972 {
9973 Lisp_Object args[] = { list_start, make_int (ii) };
9974 check_sequence_range (orig_list, list_start, list_end,
9975 Fplus (countof (args), args));
9976 }
9977
9978 if (array_starting < array_ending ||
9979 (NILP (list_end) ? !NILP (list) : list_starting < list_ending))
9980 {
9981 return make_integer (return_list_index ? XINT (list_start) + ii :
9982 array_starting);
9983 }
9984
9985 return Qnil;
9986 }
9987
9988 static Lisp_Object
9989 mismatch_string_array (Lisp_Object string, Lisp_Object string_start,
9990 Lisp_Object string_end,
9991 Lisp_Object array, Lisp_Object array_start,
9992 Lisp_Object array_end,
9993 check_test_func_t check_match, Boolint test_not_unboundp,
9994 Lisp_Object test, Lisp_Object key,
9995 Boolint return_string_index)
9996 {
9997 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data;
9998 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string);
9999 Elemcount char_count = 0, array_starting, array_ending, array_length;
10000 Elemcount string_starting, string_ending;
10001 Lisp_Object character;
10002
10003 array_starting = INTP (array_start) ? XINT (array_start) : 1 + EMACS_INT_MAX;
10004 array_ending = INTP (array_end) ? XINT (array_end) : 1 + EMACS_INT_MAX;
10005 array_length = XINT (Flength (array));
10006 check_sequence_range (array, array_start, array_end, make_int (array_length));
10007 array_ending = min (array_ending, array_length);
10008
10009 string_ending = INTP (string_end) ? XINT (string_end) : 1 + EMACS_INT_MAX;
10010 string_starting
10011 = INTP (string_start) ? XINT (string_start) : 1 + EMACS_INT_MAX;
10012
10013 while (char_count < string_starting && string_offset < string_len)
10014 {
10015 INC_IBYTEPTR (string_data);
10016 string_offset = string_data - startp;
10017 char_count++;
10018 }
10019
10020 while (array_starting < array_ending && string_starting < string_ending
10021 && string_offset < string_len)
10022 {
10023 character = make_char (itext_ichar (string_data));
10024
10025 if (return_string_index)
10026 {
10027 if (check_match (test, key, character,
10028 Faref (array, make_int (array_starting)))
10029 != test_not_unboundp)
10030 {
10031 return make_integer (char_count);
10032 }
10033 }
10034 else
10035 {
10036 if (check_match (test, key,
10037 Faref (array, make_int (array_starting)),
10038 character)
10039 != test_not_unboundp)
10040 {
10041 return make_integer (XINT (array_start) + char_count);
10042 }
10043 }
10044
10045 startp = XSTRING_DATA (string);
10046 string_data = startp + string_offset;
10047 if (string_len != XSTRING_LENGTH (string)
10048 || !valid_ibyteptr_p (string_data))
10049 {
10050 mapping_interaction_error (Qmismatch, string);
10051 }
10052
10053 array_starting++;
10054 string_starting++;
10055 char_count++;
10056 INC_IBYTEPTR (string_data);
10057 string_offset = string_data - startp;
10058 }
10059
10060 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string))
10061 {
10062 check_sequence_range (string, string_start, string_end,
10063 make_int (char_count));
10064 }
10065
10066 if ((NILP (string_end) ?
10067 string_offset < string_len : string_starting < string_ending) ||
10068 (NILP (array_end) ? !NILP (array) : array_starting < array_ending))
10069 {
10070 return make_integer (return_string_index ? char_count :
10071 XINT (array_start) + char_count);
10072 }
10073
10074 return Qnil;
10075 }
10076
10077 static Lisp_Object
10078 mismatch_string_string (Lisp_Object string1,
10079 Lisp_Object string1_start, Lisp_Object string1_end,
10080 Lisp_Object string2, Lisp_Object string2_start,
10081 Lisp_Object string2_end,
10082 check_test_func_t check_match,
10083 Boolint test_not_unboundp,
10084 Lisp_Object test, Lisp_Object key,
10085 Boolint UNUSED (return_string1_index))
10086 {
10087 Ibyte *string1_data = XSTRING_DATA (string1), *startp1 = string1_data;
10088 Bytecount string1_offset = 0, string1_len = XSTRING_LENGTH (string1);
10089 Ibyte *string2_data = XSTRING_DATA (string2), *startp2 = string2_data;
10090 Bytecount string2_offset = 0, string2_len = XSTRING_LENGTH (string2);
10091 Elemcount char_count1 = 0, string1_starting, string1_ending;
10092 Elemcount char_count2 = 0, string2_starting, string2_ending;
10093 Lisp_Object character1, character2;
10094
10095 string1_ending = INTP (string1_end) ? XINT (string1_end) : 1 + EMACS_INT_MAX;
10096 string1_starting
10097 = INTP (string1_start) ? XINT (string1_start) : 1 + EMACS_INT_MAX;
10098
10099 string2_starting
10100 = INTP (string2_start) ? XINT (string2_start) : 1 + EMACS_INT_MAX;
10101 string2_ending = INTP (string2_end) ? XINT (string2_end) : 1 + EMACS_INT_MAX;
10102
10103 while (char_count1 < string1_starting && string1_offset < string1_len)
10104 {
10105 INC_IBYTEPTR (string1_data);
10106 string1_offset = string1_data - startp1;
10107 char_count1++;
10108 }
10109
10110 while (char_count2 < string2_starting && string2_offset < string2_len)
10111 {
10112 INC_IBYTEPTR (string2_data);
10113 string2_offset = string2_data - startp2;
10114 char_count2++;
10115 }
10116
10117 while (string2_starting < string2_ending && string1_starting < string1_ending
10118 && string1_offset < string1_len && string2_offset < string2_len)
10119 {
10120 character1 = make_char (itext_ichar (string1_data));
10121 character2 = make_char (itext_ichar (string2_data));
10122
10123 if (check_match (test, key, character1, character2)
10124 != test_not_unboundp)
10125 {
10126 return make_integer (char_count1);
10127 }
10128
10129 startp1 = XSTRING_DATA (string1);
10130 string1_data = startp1 + string1_offset;
10131 if (string1_len != XSTRING_LENGTH (string1)
10132 || !valid_ibyteptr_p (string1_data))
10133 {
10134 mapping_interaction_error (Qmismatch, string1);
10135 }
10136
10137 startp2 = XSTRING_DATA (string2);
10138 string2_data = startp2 + string2_offset;
10139 if (string2_len != XSTRING_LENGTH (string2)
10140 || !valid_ibyteptr_p (string2_data))
10141 {
10142 mapping_interaction_error (Qmismatch, string2);
10143 }
10144
10145 string2_starting++;
10146 string1_starting++;
10147 char_count1++;
10148 char_count2++;
10149 INC_IBYTEPTR (string1_data);
10150 string1_offset = string1_data - startp1;
10151 INC_IBYTEPTR (string2_data);
10152 string2_offset = string2_data - startp2;
10153 }
10154
10155 if (string1_data == XSTRING_DATA (string1) + XSTRING_LENGTH (string1))
10156 {
10157 check_sequence_range (string1, string1_start, string1_end,
10158 make_int (char_count1));
10159 }
10160
10161 if (string2_data == XSTRING_DATA (string2) + XSTRING_LENGTH (string2))
10162 {
10163 check_sequence_range (string2, string2_start, string2_end,
10164 make_int (char_count2));
10165 }
10166
10167 if ((!NILP (string1_end) && string1_starting < string1_ending) ||
10168 (!NILP (string2_end) && string2_starting < string2_ending))
10169 {
10170 return make_integer (char_count1);
10171 }
10172
10173 if ((NILP (string1_end) && string1_data
10174 < (XSTRING_DATA (string1) + XSTRING_LENGTH (string1))) ||
10175 (NILP (string2_end) && string2_data
10176 < (XSTRING_DATA (string2) + XSTRING_LENGTH (string2))))
10177 {
10178 return make_integer (char_count1);
10179 }
10180
10181 return Qnil;
10182 }
10183
10184 static Lisp_Object
10185 mismatch_array_array (Lisp_Object array1, Lisp_Object start1, Lisp_Object end1,
10186 Lisp_Object array2, Lisp_Object start2, Lisp_Object end2,
10187 check_test_func_t check_match, Boolint test_not_unboundp,
10188 Lisp_Object test, Lisp_Object key,
10189 Boolint UNUSED (return_array1_index))
10190 {
10191 Elemcount len1 = XINT (Flength (array1)), len2 = XINT (Flength (array2));
10192 Elemcount ending1 = EMACS_INT_MAX, ending2 = EMACS_INT_MAX;
10193 Elemcount starting1, starting2;
10194
10195 check_sequence_range (array1, start1, end1, make_int (len1));
10196 check_sequence_range (array2, start2, end2, make_int (len2));
10197
10198 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX;
10199 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX;
10200
10201 if (!NILP (end1))
10202 {
10203 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX;
10204 }
10205
10206 if (!NILP (end2))
10207 {
10208 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX;
10209 }
10210
10211 ending1 = min (ending1, len1);
10212 ending2 = min (ending2, len2);
10213
10214 while (starting1 < ending1 && starting2 < ending2)
10215 {
10216 if (check_match (test, key, Faref (array1, make_int (starting1)),
10217 Faref (array2, make_int (starting2)))
10218 != test_not_unboundp)
10219 {
10220 return make_integer (starting1);
10221 }
10222 starting1++;
10223 starting2++;
10224 }
10225
10226 if (starting1 < ending1 || starting2 < ending2)
10227 {
10228 return make_integer (starting1);
10229 }
10230
10231 return Qnil;
10232 }
10233
10234 typedef Lisp_Object
10235 (*mismatch_func_t) (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1,
10236 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2,
10237 check_test_func_t check_match, Boolint test_not_unboundp,
10238 Lisp_Object test, Lisp_Object key,
10239 Boolint return_list_index);
10240
10241 static mismatch_func_t
10242 get_mismatch_func (Lisp_Object sequence1, Lisp_Object sequence2,
10243 Lisp_Object from_end, Boolint *return_sequence1_index_out)
10244 {
10245 CHECK_SEQUENCE (sequence1);
10246 CHECK_SEQUENCE (sequence2);
10247
10248 if (!NILP (from_end))
10249 {
10250 *return_sequence1_index_out = 1;
10251 return mismatch_from_end;
10252 }
10253
10254 if (LISTP (sequence1))
10255 {
10256 if (LISTP (sequence2))
10257 {
10258 *return_sequence1_index_out = 1;
10259 return mismatch_list_list;
10260 }
10261
10262 if (STRINGP (sequence2))
10263 {
10264 *return_sequence1_index_out = 1;
10265 return mismatch_list_string;
10266 }
10267
10268 *return_sequence1_index_out = 1;
10269 return mismatch_list_array;
10270 }
10271
10272 if (STRINGP (sequence1))
10273 {
10274 if (STRINGP (sequence2))
10275 {
10276 *return_sequence1_index_out = 1;
10277 return mismatch_string_string;
10278 }
10279
10280 if (LISTP (sequence2))
10281 {
10282 *return_sequence1_index_out = 0;
10283 return mismatch_list_string;
10284 }
10285
10286 *return_sequence1_index_out = 1;
10287 return mismatch_string_array;
10288 }
10289
10290 if (ARRAYP (sequence1))
10291 {
10292 if (STRINGP (sequence2))
10293 {
10294 *return_sequence1_index_out = 0;
10295 return mismatch_string_array;
10296 }
10297
10298 if (LISTP (sequence2))
10299 {
10300 *return_sequence1_index_out = 0;
10301 return mismatch_list_array;
10302 }
10303
10304 *return_sequence1_index_out = 1;
10305 return mismatch_array_array;
10306 }
10307
10308 RETURN_NOT_REACHED (NULL);
10309 return NULL;
10310 }
10311
10312 DEFUN ("mismatch", Fmismatch, 2, MANY, 0, /*
10313 Compare SEQUENCE1 with SEQUENCE2, return index of first mismatching element.
10314
10315 Return nil if the sequences match. If one sequence is a prefix of the
10316 other, the return value indicates the end of the shorter sequence. A
10317 non-nil return value always reflects an index into SEQUENCE1.
10318
10319 See `search' for the meaning of the keywords."
10320
10321 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT)
10322 */
10323 (int nargs, Lisp_Object *args))
10324 {
10325 Lisp_Object sequence1 = args[0], sequence2 = args[1];
10326 Boolint test_not_unboundp = 1, return_first_index = 0;
10327 check_test_func_t check_match = NULL;
10328 mismatch_func_t mismatch = NULL;
10329
10330 PARSE_KEYWORDS (Fmismatch, nargs, args, 8,
10331 (test, key, from_end, start1, end1, start2, end2, test_not),
10332 (start1 = start2 = Qzero));
10333
10334 CHECK_SEQUENCE (sequence1);
10335 CHECK_SEQUENCE (sequence2);
10336
10337 CHECK_NATNUM (start1);
10338 CHECK_NATNUM (start2);
10339
10340 if (!NILP (end1))
10341 {
10342 CHECK_NATNUM (end1);
10343 }
10344
10345 if (!NILP (end2))
10346 {
10347 CHECK_NATNUM (end2);
10348 }
10349
10350 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10351 &test_not_unboundp, NULL);
10352 mismatch = get_mismatch_func (sequence1, sequence2, from_end,
10353 &return_first_index);
10354
10355 if (return_first_index)
10356 {
10357 return mismatch (sequence1, start1, end1, sequence2, start2, end2,
10358 check_match, test_not_unboundp, test, key, 1);
10359 }
10360
10361 return mismatch (sequence2, start2, end2, sequence1, start1, end1,
10362 check_match, test_not_unboundp, test, key, 0);
10363 }
10364
10365 DEFUN ("search", Fsearch, 2, MANY, 0, /*
10366 Search for SEQUENCE1 as a subsequence of SEQUENCE2.
10367
10368 Return the index of the leftmost element of the first match found; return
10369 nil if there are no matches.
10370
10371 In this function, :start1 and :end1 specify a subsequence of SEQUENCE1, and
10372 :start2 and :end2 specify a subsequence of SEQUENCE2. See `remove*' for
10373 details of the other keywords.
10374
10375 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT)
10376 */
10377 (int nargs, Lisp_Object *args))
10378 {
10379 Lisp_Object sequence1 = args[0], sequence2 = args[1], position0 = Qnil;
10380 Boolint test_not_unboundp = 1, return_first = 0;
10381 check_test_func_t check_test = NULL, check_match = NULL;
10382 mismatch_func_t mismatch = NULL;
10383 Elemcount starting1 = 0, ending1 = 1 + EMACS_INT_MAX, starting2 = 0;
10384 Elemcount ending2 = 1 + EMACS_INT_MAX, ii = 0;
10385 Elemcount length1;
10386 Lisp_Object object = Qnil;
10387 struct gcpro gcpro1, gcpro2;
10388
10389 PARSE_KEYWORDS (Fsearch, nargs, args, 8,
10390 (test, key, from_end, start1, end1, start2, end2, test_not),
10391 (start1 = start2 = Qzero));
10392
10393 CHECK_SEQUENCE (sequence1);
10394 CHECK_SEQUENCE (sequence2);
10395 CHECK_KEY_ARGUMENT (key);
10396
10397 CHECK_NATNUM (start1);
10398 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX;
10399 CHECK_NATNUM (start2);
10400 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX;
10401
10402 if (!NILP (end1))
10403 {
10404 Lisp_Object len1 = Flength (sequence1);
10405
10406 CHECK_NATNUM (end1);
10407 check_sequence_range (sequence1, start1, end1, len1);
10408 ending1 = min (XINT (end1), XINT (len1));
10409 }
10410 else
10411 {
10412 end1 = Flength (sequence1);
10413 check_sequence_range (sequence1, start1, end1, end1);
10414 ending1 = XINT (end1);
10415 }
10416
10417 length1 = ending1 - starting1;
10418
10419 if (!NILP (end2))
10420 {
10421 Lisp_Object len2 = Flength (sequence2);
10422
10423 CHECK_NATNUM (end2);
10424 check_sequence_range (sequence2, start2, end2, len2);
10425 ending2 = min (XINT (end2), XINT (len2));
10426 }
10427 else
10428 {
10429 end2 = Flength (sequence2);
10430 check_sequence_range (sequence2, start2, end2, end2);
10431 ending2 = XINT (end2);
10432 }
10433
10434 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10435 &test_not_unboundp, &check_test);
10436 mismatch = get_mismatch_func (sequence1, sequence2, from_end, &return_first);
10437
10438 if (bytecode_arithcompare (start1, make_integer (ending1)) >= 0)
10439 {
10440 if (NILP (from_end))
10441 {
10442 return start2;
10443 }
10444
10445 if (NILP (end2))
10446 {
10447 return Flength (sequence2);
10448 }
10449
10450 return end2;
10451 }
10452
10453 if (NILP (from_end))
10454 {
10455 Lisp_Object mismatch_start1 = Fadd1 (start1);
10456 Lisp_Object first = KEY (key, Felt (sequence1, start1));
10457 GCPRO2 (first, mismatch_start1);
10458
10459 ii = starting2;
10460 while (ii < ending2)
10461 {
10462 position0 = position (&object, first, sequence2, check_test,
10463 test_not_unboundp, test, key, make_int (ii),
10464 end2, Qnil, Qnil, Qsearch);
10465 if (NILP (position0))
10466 {
10467 UNGCPRO;
10468 return Qnil;
10469 }
10470
10471 if (length1 + XINT (position0) <= ending2 &&
10472 (return_first ?
10473 NILP (mismatch (sequence1, mismatch_start1, end1,
10474 sequence2,
10475 make_int (1 + XINT (position0)),
10476 make_int (length1 + XINT (position0)),
10477 check_match, test_not_unboundp, test, key, 1)) :
10478 NILP (mismatch (sequence2,
10479 make_int (1 + XINT (position0)),
10480 make_int (length1 + XINT (position0)),
10481 sequence1, mismatch_start1, end1,
10482 check_match, test_not_unboundp, test, key, 0))))
10483
10484
10485 {
10486 UNGCPRO;
10487 return position0;
10488 }
10489
10490 ii = XINT (position0) + 1;
10491 }
10492
10493 UNGCPRO;
10494 }
10495 else
10496 {
10497 Lisp_Object mismatch_end1 = make_integer (ending1 - 1);
10498 Lisp_Object last = KEY (key, Felt (sequence1, mismatch_end1));
10499 GCPRO2 (last, mismatch_end1);
10500
10501 ii = ending2;
10502 while (ii > starting2)
10503 {
10504 position0 = position (&object, last, sequence2, check_test,
10505 test_not_unboundp, test, key, start2,
10506 make_int (ii), Qt, Qnil, Qsearch);
10507
10508 if (NILP (position0))
10509 {
10510 UNGCPRO;
10511 return Qnil;
10512 }
10513
10514 if (XINT (position0) - length1 + 1 >= starting2 &&
10515 (return_first ?
10516 NILP (mismatch (sequence1, start1, mismatch_end1,
10517 sequence2,
10518 make_int (XINT (position0) - length1 + 1),
10519 make_int (XINT (position0)),
10520 check_match, test_not_unboundp, test, key, 1)) :
10521 NILP (mismatch (sequence2,
10522 make_int (XINT (position0) - length1 + 1),
10523 make_int (XINT (position0)),
10524 sequence1, start1, mismatch_end1,
10525 check_match, test_not_unboundp, test, key, 0))))
10526 {
10527 UNGCPRO;
10528 return make_int (XINT (position0) - length1 + 1);
10529 }
10530
10531 ii = XINT (position0);
10532 }
10533
10534 UNGCPRO;
10535 }
10536
10537 return Qnil;
10538 }
10539
10540 /* These two functions do set operations, those that can be visualised with
10541 Venn diagrams. */
10542 static Lisp_Object
10543 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp)
10544 {
10545 Lisp_Object liszt1 = args[0], liszt2 = args[1];
10546 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil;
10547 Lisp_Object keyed = Qnil, ignore = Qnil;
10548 Boolint test_not_unboundp = 1;
10549 check_test_func_t check_test = NULL;
10550 struct gcpro gcpro1, gcpro2;
10551
10552 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable),
10553 NULL, 2, 0);
10554
10555 CHECK_LIST (liszt1);
10556 CHECK_LIST (liszt2);
10557
10558 CHECK_KEY_ARGUMENT (key);
10559
10560 if (NILP (liszt1) && intersectionp)
10561 {
10562 return Qnil;
10563 }
10564
10565 if (NILP (liszt2))
10566 {
10567 return intersectionp ? Qnil : liszt1;
10568 }
10569
10570 get_check_match_function (&test, test_not, Qnil, Qnil, key,
10571 &test_not_unboundp, &check_test);
10572
10573 GCPRO2 (keyed, result);
10574
10575 {
10576 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10577 {
10578 keyed = KEY (key, elt);
10579 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10580 check_test, test_not_unboundp,
10581 test, key, 0, Qzero, Qnil))
10582 != intersectionp)
10583 {
10584 if (EQ (Qsubsetp, caller))
10585 {
10586 result = Qnil;
10587 break;
10588 }
10589 else if (NILP (stable))
10590 {
10591 result = Fcons (elt, result);
10592 }
10593 else if (NILP (result))
10594 {
10595 result = result_tail = Fcons (elt, Qnil);
10596 }
10597 else
10598 {
10599 XSETCDR (result_tail, Fcons (elt, Qnil));
10600 result_tail = XCDR (result_tail);
10601 }
10602 }
10603 }
10604 END_GC_EXTERNAL_LIST_LOOP (elt);
10605 }
10606
10607 UNGCPRO;
10608
10609 return result;
10610 }
10611
10612 static Lisp_Object
10613 nvenn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp)
10614 {
10615 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil;
10616 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil;
10617 Elemcount count;
10618 Boolint test_not_unboundp = 1;
10619 check_test_func_t check_test = NULL;
10620 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10621
10622 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not),
10623 NULL, 2, 0);
10624
10625 CHECK_LIST (liszt1);
10626 CHECK_LIST (liszt2);
10627
10628 CHECK_KEY_ARGUMENT (key);
10629
10630 if (NILP (liszt1) && intersectionp)
10631 {
10632 return Qnil;
10633 }
10634
10635 if (NILP (liszt2))
10636 {
10637 return intersectionp ? Qnil : liszt1;
10638 }
10639
10640 get_check_match_function (&test, test_not, Qnil, Qnil, key,
10641 &test_not_unboundp, &check_test);
10642
10643 tortoise_elt = tail = liszt1, count = 0;
10644
10645 GCPRO4 (tail, keyed, liszt1, tortoise_elt);
10646
10647 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
10648 (signal_malformed_list_error (liszt1), 0))
10649 {
10650 keyed = KEY (key, elt);
10651 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10652 check_test, test_not_unboundp,
10653 test, key, 0, Qzero, Qnil))
10654 == intersectionp)
10655 {
10656 if (NILP (prev_tail))
10657 {
10658 liszt1 = XCDR (tail);
10659 }
10660 else
10661 {
10662 XSETCDR (prev_tail, XCDR (tail));
10663 }
10664
10665 tail = XCDR (tail);
10666 /* List is definitely not circular now! */
10667 count = 0;
10668 }
10669 else
10670 {
10671 prev_tail = tail;
10672 tail = XCDR (tail);
10673 }
10674
10675 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
10676
10677 if (count & 1)
10678 {
10679 tortoise_elt = XCDR (tortoise_elt);
10680 }
10681
10682 if (EQ (elt, tortoise_elt))
10683 {
10684 signal_circular_list_error (liszt1);
10685 }
10686 }
10687
10688 UNGCPRO;
10689
10690 return liszt1;
10691 }
10692
10693 DEFUN ("intersection", Fintersection, 2, MANY, 0, /*
10694 Combine LIST1 and LIST2 using a set-intersection operation.
10695
10696 The result list contains all items that appear in both LIST1 and LIST2.
10697 This is a non-destructive function; it makes a copy of the data if necessary
10698 to avoid corrupting the original LIST1 and LIST2.
10699
10700 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10701 return the items in the order they appear in LIST1.
10702
10703 See `union' for the meaning of :test, :test-not and :key."
10704
10705 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10706 */
10707 (int nargs, Lisp_Object *args))
10708 {
10709 return venn (Qintersection, nargs, args, 1);
10710 }
10711
10712 DEFUN ("nintersection", Fnintersection, 2, MANY, 0, /*
10713 Combine LIST1 and LIST2 using a set-intersection operation.
10714
10715 The result list contains all items that appear in both LIST1 and LIST2.
10716 This is a destructive function; it reuses the storage of LIST1 whenever
10717 possible.
10718
10719 See `union' for the meaning of :test, :test-not and :key."
10720
10721 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10722 */
10723 (int nargs, Lisp_Object *args))
10724 {
10725 return nvenn (Qnintersection, nargs, args, 1);
10726 }
10727
10728 DEFUN ("subsetp", Fsubsetp, 2, MANY, 0, /*
10729 Return non-nil if every element of LIST1 also appears in LIST2.
10730
10731 See `union' for the meaning of the keyword arguments.
10732
10733 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10734 */
10735 (int nargs, Lisp_Object *args))
10736 {
10737 return venn (Qsubsetp, nargs, args, 0);
10738 }
10739
10740 DEFUN ("set-difference", Fset_difference, 2, MANY, 0, /*
10741 Combine LIST1 and LIST2 using a set-difference operation.
10742
10743 The result list contains all items that appear in LIST1 but not LIST2. This
10744 is a non-destructive function; it makes a copy of the data if necessary to
10745 avoid corrupting the original LIST1 and LIST2.
10746
10747 See `union' for the meaning of :test, :test-not and :key.
10748
10749 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10750 return the items in the order they appear in LIST1.
10751
10752 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10753 */
10754 (int nargs, Lisp_Object *args))
10755 {
10756 return venn (Qset_difference, nargs, args, 0);
10757 }
10758
10759 DEFUN ("nset-difference", Fnset_difference, 2, MANY, 0, /*
10760 Combine LIST1 and LIST2 using a set-difference operation.
10761
10762 The result list contains all items that appear in LIST1 but not LIST2. This
10763 is a destructive function; it reuses the storage of LIST1 whenever possible.
10764
10765 See `union' for the meaning of :test, :test-not and :key."
10766
10767 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10768 */
10769 (int nargs, Lisp_Object *args))
10770 {
10771 return nvenn (Qnset_difference, nargs, args, 0);
10772 }
10773
10774 DEFUN ("nunion", Fnunion, 2, MANY, 0, /*
10775 Combine LIST1 and LIST2 using a set-union operation.
10776 The result list contains all items that appear in either LIST1 or LIST2.
10777
10778 This is a destructive function, it reuses the storage of LIST1 whenever
10779 possible.
10780
10781 See `union' for the meaning of :test, :test-not and :key.
10782
10783 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10784 */
10785 (int nargs, Lisp_Object *args))
10786 {
10787 args[0] = nvenn (Qnunion, nargs, args, 0);
10788 return bytecode_nconc2 (args);
10789 }
10790
10791 DEFUN ("union", Funion, 2, MANY, 0, /*
10792 Combine LIST1 and LIST2 using a set-union operation.
10793 The result list contains all items that appear in either LIST1 or LIST2.
10794 This is a non-destructive function; it makes a copy of the data if necessary
10795 to avoid corrupting the original LIST1 and LIST2.
10796
10797 The keywords :test and :test-not specify two-argument test and negated-test
10798 predicates, respectively; :test defaults to `eql'. See `member*' for more
10799 information.
10800
10801 :key specifies a one-argument function that transforms elements of LIST1
10802 and LIST2 into \"comparison keys\" before the test predicate is applied.
10803 For example, if :key is #'car, then the car of elements from LIST1 is
10804 compared with the car of elements from LIST2. The :key function, however,
10805 does not affect the elements in the returned list, which are taken directly
10806 from the elements in LIST1 and LIST2.
10807
10808 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10809 return the items of LIST1 in order, followed by the remaining items of LIST2
10810 in the order they occur in LIST2.
10811
10812 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10813 */
10814 (int nargs, Lisp_Object *args))
10815 {
10816 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil;
10817 Lisp_Object keyed = Qnil, result, result_tail;
10818 Boolint test_not_unboundp = 1;
10819 check_test_func_t check_test = NULL, check_match = NULL;
10820 struct gcpro gcpro1, gcpro2;
10821
10822 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL);
10823
10824 CHECK_LIST (liszt1);
10825 CHECK_LIST (liszt2);
10826
10827 CHECK_KEY_ARGUMENT (key);
10828
10829 if (NILP (liszt1))
10830 {
10831 return liszt2;
10832 }
10833
10834 if (NILP (liszt2))
10835 {
10836 return liszt1;
10837 }
10838
10839 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10840 &test_not_unboundp, &check_test);
10841
10842 GCPRO2 (keyed, result);
10843
10844 if (NILP (stable))
10845 {
10846 result = liszt2;
10847 {
10848 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10849 {
10850 keyed = KEY (key, elt);
10851 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10852 check_test, test_not_unboundp,
10853 test, key, 0, Qzero, Qnil)))
10854 {
10855 /* The Lisp version of #'union used to check which list was
10856 longer, and use that as the tail of the constructed
10857 list. That fails when the order of arguments to TEST is
10858 specified, as is the case for these functions. We could
10859 pass the reverse_check argument to
10860 list_position_cons_before, but that means any key argument
10861 is called an awful lot more, so it's a space win but not
10862 a time win. */
10863 result = Fcons (elt, result);
10864 }
10865 }
10866 END_GC_EXTERNAL_LIST_LOOP (elt);
10867 }
10868 }
10869 else
10870 {
10871 result = result_tail = Qnil;
10872
10873 /* The standard `union' doesn't produce a "stable" union -- it
10874 iterates over the second list instead of the first one, and returns
10875 the values in backwards order. According to the CLTL2
10876 documentation, `union' is not required to preserve the ordering of
10877 elements in any fashion; providing the functionality for a stable
10878 union is an XEmacs extension. */
10879 {
10880 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
10881 {
10882 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10883 check_match, test_not_unboundp,
10884 test, key, 1, Qzero, Qnil)))
10885 {
10886 if (NILP (result))
10887 {
10888 result = result_tail = Fcons (elt, Qnil);
10889 }
10890 else
10891 {
10892 XSETCDR (result_tail, Fcons (elt, Qnil));
10893 result_tail = XCDR (result_tail);
10894 }
10895 }
10896 }
10897 END_GC_EXTERNAL_LIST_LOOP (elt);
10898 }
10899
10900 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result);
10901 }
10902
10903 UNGCPRO;
10904
10905 return result;
10906 }
10907
10908 DEFUN ("set-exclusive-or", Fset_exclusive_or, 2, MANY, 0, /*
10909 Combine LIST1 and LIST2 using a set-exclusive-or operation.
10910
10911 The result list contains all items that appear in exactly one of LIST1, LIST2.
10912 This is a non-destructive function; it makes a copy of the data if necessary
10913 to avoid corrupting the original LIST1 and LIST2.
10914
10915 See `union' for the meaning of :test, :test-not and :key.
10916
10917 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10918 return the items in the order they appear in LIST1, followed by the
10919 remaining items in the order they appear in LIST2.
10920
10921 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10922 */
10923 (int nargs, Lisp_Object *args))
10924 {
10925 Lisp_Object liszt1 = args[0], liszt2 = args[1];
10926 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil;
10927 Boolint test_not_unboundp = 1;
10928 check_test_func_t check_match = NULL, check_test = NULL;
10929 struct gcpro gcpro1, gcpro2;
10930
10931 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4,
10932 (test, key, test_not, stable), NULL);
10933
10934 CHECK_LIST (liszt1);
10935 CHECK_LIST (liszt2);
10936
10937 CHECK_KEY_ARGUMENT (key);
10938
10939 if (NILP (liszt2))
10940 {
10941 return liszt1;
10942 }
10943
10944 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10945 &test_not_unboundp, &check_test);
10946
10947 GCPRO2 (keyed, result);
10948 {
10949 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10950 {
10951 keyed = KEY (key, elt);
10952 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10953 check_test, test_not_unboundp,
10954 test, key, 0, Qzero, Qnil)))
10955 {
10956 if (NILP (stable))
10957 {
10958 result = Fcons (elt, result);
10959 }
10960 else if (NILP (result))
10961 {
10962 result = result_tail = Fcons (elt, Qnil);
10963 }
10964 else
10965 {
10966 XSETCDR (result_tail, Fcons (elt, Qnil));
10967 result_tail = XCDR (result_tail);
10968 }
10969 }
10970 }
10971 END_GC_EXTERNAL_LIST_LOOP (elt);
10972 }
10973
10974 {
10975 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
10976 {
10977 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10978 check_match, test_not_unboundp,
10979 test, key, 1, Qzero, Qnil)))
10980 {
10981 if (NILP (stable))
10982 {
10983 result = Fcons (elt, result);
10984 }
10985 else if (NILP (result))
10986 {
10987 result = result_tail = Fcons (elt, Qnil);
10988 }
10989 else
10990 {
10991 XSETCDR (result_tail, Fcons (elt, Qnil));
10992 result_tail = XCDR (result_tail);
10993 }
10994 }
10995 }
10996 END_GC_EXTERNAL_LIST_LOOP (elt);
10997 }
10998
10999 UNGCPRO;
11000
11001 return result;
11002 }
11003
11004 DEFUN ("nset-exclusive-or", Fnset_exclusive_or, 2, MANY, 0, /*
11005 Combine LIST1 and LIST2 using a set-exclusive-or operation.
11006
11007 The result list contains all items that appear in exactly one of LIST1 and
11008 LIST2. This is a destructive function; it reuses the storage of LIST1 and
11009 LIST2 whenever possible.
11010
11011 See `union' for the meaning of :test, :test-not and :key.
11012
11013 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
11014 */
11015 (int nargs, Lisp_Object *args))
11016 {
11017 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil;
11018 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap;
11019 Lisp_Object prev_tail = Qnil, ignore = Qnil;
11020 Elemcount count;
11021 Boolint test_not_unboundp = 1;
11022 check_test_func_t check_match = NULL, check_test = NULL;
11023 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
11024
11025 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4,
11026 (test, key, test_not, stable), NULL);
11027
11028 CHECK_LIST (liszt1);
11029 CHECK_LIST (liszt2);
11030
11031 CHECK_KEY_ARGUMENT (key);
11032
11033 if (NILP (liszt2))
11034 {
11035 return liszt1;
11036 }
11037
11038 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
11039 &test_not_unboundp, &check_test);
11040
11041 tortoise_elt = tail = liszt1, count = 0;
11042
11043 GCPRO4 (tail, keyed, result, tortoise_elt);
11044
11045 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
11046 (signal_malformed_list_error (liszt1), 0))
11047 {
11048 keyed = KEY (key, elt);
11049 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
11050 check_test, test_not_unboundp,
11051 test, key, 0, Qzero, Qnil)))
11052 {
11053 swap = XCDR (tail);
11054
11055 if (NILP (prev_tail))
11056 {
11057 liszt1 = XCDR (tail);
11058 }
11059 else
11060 {
11061 XSETCDR (prev_tail, swap);
11062 }
11063
11064 XSETCDR (tail, result);
11065 result = tail;
11066 tail = swap;
11067
11068 /* List is definitely not circular now! */
11069 count = 0;
11070 }
11071 else
11072 {
11073 prev_tail = tail;
11074 tail = XCDR (tail);
11075 }
11076
11077 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
11078
11079 if (count & 1)
11080 {
11081 tortoise_elt = XCDR (tortoise_elt);
11082 }
11083
11084 if (EQ (elt, tortoise_elt))
11085 {
11086 signal_circular_list_error (liszt1);
11087 }
11088 }
11089
11090 tortoise_elt = tail = liszt2, count = 0;
11091
11092 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
11093 (signal_malformed_list_error (liszt2), 0))
11094 {
11095 /* Need to leave the key calculation to list_position_cons_before(). */
11096 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
11097 check_match, test_not_unboundp,
11098 test, key, 1, Qzero, Qnil)))
11099 {
11100 swap = XCDR (tail);
11101 XSETCDR (tail, result);
11102 result = tail;
11103 tail = swap;
11104 count = 0;
11105 }
11106 else
11107 {
11108 tail = XCDR (tail);
11109 }
11110
11111 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
11112
11113 if (count & 1)
11114 {
11115 tortoise_elt = XCDR (tortoise_elt);
11116 }
11117
11118 if (EQ (elt, tortoise_elt))
11119 {
11120 signal_circular_list_error (liszt1);
11121 }
11122 }
11123
11124 UNGCPRO;
11125
11126 return result;
11127 }
11128
4028 11129
4029 Lisp_Object 11130 Lisp_Object
4030 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) 11131 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string)
4031 { 11132 {
4032 return Fintern (concat2 (Fsymbol_name (symbol), 11133 return Fintern (concat2 (Fsymbol_name (symbol),
4039 { 11140 {
4040 return Fintern (concat2 (build_ascstring (ascii_string), 11141 return Fintern (concat2 (build_ascstring (ascii_string),
4041 Fsymbol_name (symbol)), 11142 Fsymbol_name (symbol)),
4042 Qnil); 11143 Qnil);
4043 } 11144 }
4044
4045 11145
4046 /* #### this function doesn't belong in this file! */ 11146 /* #### this function doesn't belong in this file! */
4047 11147
4048 #ifdef HAVE_GETLOADAVG 11148 #ifdef HAVE_GETLOADAVG
4049 #ifdef HAVE_SYS_LOADAVG_H 11149 #ifdef HAVE_SYS_LOADAVG_H
4528 /* We needn't multiply allength with MAX_ICHAR_LEN because all the 11628 /* We needn't multiply allength with MAX_ICHAR_LEN because all the
4529 base64 characters will be single-byte. */ 11629 base64 characters will be single-byte. */
4530 encoded = (Ibyte *) MALLOC_OR_ALLOCA (allength); 11630 encoded = (Ibyte *) MALLOC_OR_ALLOCA (allength);
4531 encoded_length = base64_encode_1 (XLSTREAM (input), encoded, 11631 encoded_length = base64_encode_1 (XLSTREAM (input), encoded,
4532 NILP (no_line_break)); 11632 NILP (no_line_break));
4533 if (encoded_length > allength) 11633 assert (encoded_length <= allength);
4534 ABORT ();
4535 Lstream_delete (XLSTREAM (input)); 11634 Lstream_delete (XLSTREAM (input));
4536 11635
4537 /* Now we have encoded the region, so we insert the new contents 11636 /* Now we have encoded the region, so we insert the new contents
4538 and delete the old. (Insert first in order to preserve markers.) */ 11637 and delete the old. (Insert first in order to preserve markers.) */
4539 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0); 11638 buffer_insert_raw_string_1 (buf, begv, encoded, encoded_length, 0);
4570 11669
4571 input = make_lisp_string_input_stream (string, 0, -1); 11670 input = make_lisp_string_input_stream (string, 0, -1);
4572 encoded = (Ibyte *) MALLOC_OR_ALLOCA (allength); 11671 encoded = (Ibyte *) MALLOC_OR_ALLOCA (allength);
4573 encoded_length = base64_encode_1 (XLSTREAM (input), encoded, 11672 encoded_length = base64_encode_1 (XLSTREAM (input), encoded,
4574 NILP (no_line_break)); 11673 NILP (no_line_break));
4575 if (encoded_length > allength) 11674 assert (encoded_length <= allength);
4576 ABORT ();
4577 Lstream_delete (XLSTREAM (input)); 11675 Lstream_delete (XLSTREAM (input));
4578 result = make_string (encoded, encoded_length); 11676 result = make_string (encoded, encoded_length);
4579 unbind_to (speccount); 11677 unbind_to (speccount);
4580 return result; 11678 return result;
4581 } 11679 }
4603 11701
4604 input = make_lisp_buffer_input_stream (buf, begv, zv, 0); 11702 input = make_lisp_buffer_input_stream (buf, begv, zv, 0);
4605 /* We need to allocate enough room for decoding the text. */ 11703 /* We need to allocate enough room for decoding the text. */
4606 decoded = (Ibyte *) MALLOC_OR_ALLOCA (length * MAX_ICHAR_LEN); 11704 decoded = (Ibyte *) MALLOC_OR_ALLOCA (length * MAX_ICHAR_LEN);
4607 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length); 11705 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, &cc_decoded_length);
4608 if (decoded_length > length * MAX_ICHAR_LEN) 11706 assert (decoded_length <= length * MAX_ICHAR_LEN);
4609 ABORT ();
4610 Lstream_delete (XLSTREAM (input)); 11707 Lstream_delete (XLSTREAM (input));
4611 11708
4612 /* Now we have decoded the region, so we insert the new contents 11709 /* Now we have decoded the region, so we insert the new contents
4613 and delete the old. (Insert first in order to preserve markers.) */ 11710 and delete the old. (Insert first in order to preserve markers.) */
4614 BUF_SET_PT (buf, begv); 11711 BUF_SET_PT (buf, begv);
4644 decoded = (Ibyte *) MALLOC_OR_ALLOCA (length * MAX_ICHAR_LEN); 11741 decoded = (Ibyte *) MALLOC_OR_ALLOCA (length * MAX_ICHAR_LEN);
4645 11742
4646 input = make_lisp_string_input_stream (string, 0, -1); 11743 input = make_lisp_string_input_stream (string, 0, -1);
4647 decoded_length = base64_decode_1 (XLSTREAM (input), decoded, 11744 decoded_length = base64_decode_1 (XLSTREAM (input), decoded,
4648 &cc_decoded_length); 11745 &cc_decoded_length);
4649 if (decoded_length > length * MAX_ICHAR_LEN) 11746 assert (decoded_length <= length * MAX_ICHAR_LEN);
4650 ABORT ();
4651 Lstream_delete (XLSTREAM (input)); 11747 Lstream_delete (XLSTREAM (input));
4652 11748
4653 result = make_string (decoded, decoded_length); 11749 result = make_string (decoded, decoded_length);
4654 unbind_to (speccount); 11750 unbind_to (speccount);
4655 return result; 11751 return result;
4658 Lisp_Object Qyes_or_no_p; 11754 Lisp_Object Qyes_or_no_p;
4659 11755
4660 void 11756 void
4661 syms_of_fns (void) 11757 syms_of_fns (void)
4662 { 11758 {
4663 INIT_LRECORD_IMPLEMENTATION (bit_vector); 11759 INIT_LISP_OBJECT (bit_vector);
4664 11760
4665 DEFSYMBOL (Qstring_lessp); 11761 DEFSYMBOL (Qstring_lessp);
11762 DEFSYMBOL (Qmerge);
11763 DEFSYMBOL (Qfill);
4666 DEFSYMBOL (Qidentity); 11764 DEFSYMBOL (Qidentity);
4667 DEFSYMBOL (Qvector); 11765 DEFSYMBOL (Qvector);
4668 DEFSYMBOL (Qarray); 11766 DEFSYMBOL (Qarray);
4669 DEFSYMBOL (Qstring); 11767 DEFSYMBOL (Qstring);
4670 DEFSYMBOL (Qlist); 11768 DEFSYMBOL (Qlist);
4671 DEFSYMBOL (Qbit_vector); 11769 DEFSYMBOL (Qbit_vector);
11770 defsymbol (&QsortX, "sort*");
11771 DEFSYMBOL (Qreduce);
11772 DEFSYMBOL (Qreplace);
11773 DEFSYMBOL (Qposition);
11774 DEFSYMBOL (Qfind);
11775 defsymbol (&QdeleteX, "delete*");
11776 defsymbol (&QremoveX, "remove*");
11777
11778 DEFSYMBOL (Qmapconcat);
11779 defsymbol (&QmapcarX, "mapcar*");
11780 DEFSYMBOL (Qmapvector);
11781 DEFSYMBOL (Qmapcan);
11782 DEFSYMBOL (Qmapc);
11783 DEFSYMBOL (Qmap);
11784 DEFSYMBOL (Qmap_into);
11785 DEFSYMBOL (Qsome);
11786 DEFSYMBOL (Qevery);
11787 DEFSYMBOL (Qmaplist);
11788 DEFSYMBOL (Qmapl);
11789 DEFSYMBOL (Qmapcon);
11790 DEFSYMBOL (Qnsubstitute);
11791 DEFSYMBOL (Qdelete_duplicates);
11792 DEFSYMBOL (Qsubstitute);
11793 DEFSYMBOL (Qmismatch);
11794 DEFSYMBOL (Qintersection);
11795 DEFSYMBOL (Qnintersection);
11796 DEFSYMBOL (Qsubsetp);
11797 DEFSYMBOL (Qcar_less_than_car);
11798 DEFSYMBOL (Qset_difference);
11799 DEFSYMBOL (Qnset_difference);
11800 DEFSYMBOL (Qnunion);
11801
11802 DEFKEYWORD (Q_from_end);
11803 DEFKEYWORD (Q_initial_value);
11804 DEFKEYWORD (Q_start1);
11805 DEFKEYWORD (Q_start2);
11806 DEFKEYWORD (Q_end1);
11807 DEFKEYWORD (Q_end2);
11808 defkeyword (&Q_if_, ":if");
11809 DEFKEYWORD (Q_if_not);
11810 DEFKEYWORD (Q_test_not);
11811 DEFKEYWORD (Q_count);
11812 DEFKEYWORD (Q_stable);
4672 11813
4673 DEFSYMBOL (Qyes_or_no_p); 11814 DEFSYMBOL (Qyes_or_no_p);
4674 11815
4675 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); 11816 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error);
4676 11817
4677 DEFSUBR (Fidentity); 11818 DEFSUBR (Fidentity);
4678 DEFSUBR (Frandom); 11819 DEFSUBR (Frandom);
4679 DEFSUBR (Flength); 11820 DEFSUBR (Flength);
4680 DEFSUBR (Fsafe_length); 11821 DEFSUBR (Fsafe_length);
11822 DEFSUBR (Flist_length);
11823 DEFSUBR (Fcount);
4681 DEFSUBR (Fstring_equal); 11824 DEFSUBR (Fstring_equal);
4682 DEFSUBR (Fcompare_strings); 11825 DEFSUBR (Fcompare_strings);
4683 DEFSUBR (Fstring_lessp); 11826 DEFSUBR (Fstring_lessp);
4684 DEFSUBR (Fstring_modified_tick); 11827 DEFSUBR (Fstring_modified_tick);
4685 DEFSUBR (Fappend); 11828 DEFSUBR (Fappend);
4688 DEFSUBR (Fbvconcat); 11831 DEFSUBR (Fbvconcat);
4689 DEFSUBR (Fcopy_list); 11832 DEFSUBR (Fcopy_list);
4690 DEFSUBR (Fcopy_sequence); 11833 DEFSUBR (Fcopy_sequence);
4691 DEFSUBR (Fcopy_alist); 11834 DEFSUBR (Fcopy_alist);
4692 DEFSUBR (Fcopy_tree); 11835 DEFSUBR (Fcopy_tree);
4693 DEFSUBR (Fsubstring);
4694 DEFSUBR (Fsubseq); 11836 DEFSUBR (Fsubseq);
4695 DEFSUBR (Fnthcdr); 11837 DEFSUBR (Fnthcdr);
4696 DEFSUBR (Fnth); 11838 DEFSUBR (Fnth);
4697 DEFSUBR (Felt); 11839 DEFSUBR (Felt);
4698 DEFSUBR (Flast); 11840 DEFSUBR (Flast);
4699 DEFSUBR (Fbutlast); 11841 DEFSUBR (Fbutlast);
4700 DEFSUBR (Fnbutlast); 11842 DEFSUBR (Fnbutlast);
4701 DEFSUBR (Fmember); 11843 DEFSUBR (Fmember);
4702 DEFSUBR (Fold_member);
4703 DEFSUBR (Fmemq); 11844 DEFSUBR (Fmemq);
4704 DEFSUBR (Fold_memq); 11845 DEFSUBR (FmemberX);
11846 DEFSUBR (Fadjoin);
4705 DEFSUBR (Fassoc); 11847 DEFSUBR (Fassoc);
4706 DEFSUBR (Fold_assoc);
4707 DEFSUBR (Fassq); 11848 DEFSUBR (Fassq);
4708 DEFSUBR (Fold_assq);
4709 DEFSUBR (Frassoc); 11849 DEFSUBR (Frassoc);
4710 DEFSUBR (Fold_rassoc);
4711 DEFSUBR (Frassq); 11850 DEFSUBR (Frassq);
4712 DEFSUBR (Fold_rassq); 11851
4713 DEFSUBR (Fdelete); 11852 DEFSUBR (Fposition);
4714 DEFSUBR (Fold_delete); 11853 DEFSUBR (Ffind);
4715 DEFSUBR (Fdelq); 11854
4716 DEFSUBR (Fold_delq); 11855 DEFSUBR (FdeleteX);
11856 DEFSUBR (FremoveX);
4717 DEFSUBR (Fremassoc); 11857 DEFSUBR (Fremassoc);
4718 DEFSUBR (Fremassq); 11858 DEFSUBR (Fremassq);
4719 DEFSUBR (Fremrassoc); 11859 DEFSUBR (Fremrassoc);
4720 DEFSUBR (Fremrassq); 11860 DEFSUBR (Fremrassq);
11861 DEFSUBR (Fdelete_duplicates);
11862 DEFSUBR (Fremove_duplicates);
4721 DEFSUBR (Fnreverse); 11863 DEFSUBR (Fnreverse);
4722 DEFSUBR (Freverse); 11864 DEFSUBR (Freverse);
4723 DEFSUBR (Fsort); 11865 DEFSUBR (FsortX);
11866 DEFSUBR (Fmerge);
4724 DEFSUBR (Fplists_eq); 11867 DEFSUBR (Fplists_eq);
4725 DEFSUBR (Fplists_equal); 11868 DEFSUBR (Fplists_equal);
4726 DEFSUBR (Flax_plists_eq); 11869 DEFSUBR (Flax_plists_eq);
4727 DEFSUBR (Flax_plists_equal); 11870 DEFSUBR (Flax_plists_equal);
4728 DEFSUBR (Fplist_get); 11871 DEFSUBR (Fplist_get);
4740 DEFSUBR (Fdestructive_alist_to_plist); 11883 DEFSUBR (Fdestructive_alist_to_plist);
4741 DEFSUBR (Fget); 11884 DEFSUBR (Fget);
4742 DEFSUBR (Fput); 11885 DEFSUBR (Fput);
4743 DEFSUBR (Fremprop); 11886 DEFSUBR (Fremprop);
4744 DEFSUBR (Fobject_plist); 11887 DEFSUBR (Fobject_plist);
11888 DEFSUBR (Fobject_setplist);
4745 DEFSUBR (Fequal); 11889 DEFSUBR (Fequal);
4746 DEFSUBR (Fequalp); 11890 DEFSUBR (Fequalp);
11891 DEFSUBR (Ffill);
11892
11893 #ifdef SUPPORT_CONFOUNDING_FUNCTIONS
11894 DEFSUBR (Fold_member);
11895 DEFSUBR (Fold_memq);
11896 DEFSUBR (Fold_assoc);
11897 DEFSUBR (Fold_assq);
11898 DEFSUBR (Fold_rassoc);
11899 DEFSUBR (Fold_rassq);
11900 DEFSUBR (Fold_delete);
11901 DEFSUBR (Fold_delq);
4747 DEFSUBR (Fold_equal); 11902 DEFSUBR (Fold_equal);
4748 DEFSUBR (Ffillarray); 11903 DEFSUBR (Fold_eq);
11904 #endif
11905
11906 DEFSUBR (FassocX);
11907 DEFSUBR (FrassocX);
11908
4749 DEFSUBR (Fnconc); 11909 DEFSUBR (Fnconc);
4750 DEFSUBR (FmapcarX); 11910 DEFSUBR (FmapcarX);
4751 DEFSUBR (Fmapvector); 11911 DEFSUBR (Fmapvector);
4752 DEFSUBR (Fmapcan); 11912 DEFSUBR (Fmapcan);
4753 DEFSUBR (Fmapc); 11913 DEFSUBR (Fmapc);
4754 DEFSUBR (Fmapconcat); 11914 DEFSUBR (Fmapconcat);
4755 DEFSUBR (Fmap); 11915 DEFSUBR (Fmap);
4756 DEFSUBR (Fmap_into); 11916 DEFSUBR (Fmap_into);
4757 DEFSUBR (Fsome); 11917 DEFSUBR (Fsome);
4758 DEFSUBR (Fevery); 11918 DEFSUBR (Fevery);
4759 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc"))); 11919 Ffset (intern ("mapc-internal"), Qmapc);
4760 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*"))); 11920 Ffset (intern ("mapcar"), QmapcarX);
4761 DEFSUBR (Fmaplist); 11921 DEFSUBR (Fmaplist);
4762 DEFSUBR (Fmapl); 11922 DEFSUBR (Fmapl);
4763 DEFSUBR (Fmapcon); 11923 DEFSUBR (Fmapcon);
4764 11924
11925 DEFSUBR (Freduce);
4765 DEFSUBR (Freplace_list); 11926 DEFSUBR (Freplace_list);
11927 DEFSUBR (Freplace);
11928 DEFSUBR (Fsubsetp);
11929 DEFSUBR (Fnsubstitute);
11930 DEFSUBR (Fsubstitute);
11931 DEFSUBR (Fsublis);
11932 DEFSUBR (Fnsublis);
11933 DEFSUBR (Fsubst);
11934 DEFSUBR (Fnsubst);
11935 DEFSUBR (Ftree_equal);
11936 DEFSUBR (Fmismatch);
11937 DEFSUBR (Fsearch);
11938 DEFSUBR (Funion);
11939 DEFSUBR (Fnunion);
11940 DEFSUBR (Fintersection);
11941 DEFSUBR (Fnintersection);
11942 DEFSUBR (Fset_difference);
11943 DEFSUBR (Fnset_difference);
11944 DEFSUBR (Fset_exclusive_or);
11945 DEFSUBR (Fnset_exclusive_or);
11946
4766 DEFSUBR (Fload_average); 11947 DEFSUBR (Fload_average);
4767 DEFSUBR (Ffeaturep); 11948 DEFSUBR (Ffeaturep);
4768 DEFSUBR (Frequire); 11949 DEFSUBR (Frequire);
4769 DEFSUBR (Fprovide); 11950 DEFSUBR (Fprovide);
4770 DEFSUBR (Fbase64_encode_region); 11951 DEFSUBR (Fbase64_encode_region);
4771 DEFSUBR (Fbase64_encode_string); 11952 DEFSUBR (Fbase64_encode_string);
4772 DEFSUBR (Fbase64_decode_region); 11953 DEFSUBR (Fbase64_decode_region);
4773 DEFSUBR (Fbase64_decode_string); 11954 DEFSUBR (Fbase64_decode_string);
4774 11955
11956 DEFSUBR (Fsubstring_no_properties);
4775 DEFSUBR (Fsplit_string_by_char); 11957 DEFSUBR (Fsplit_string_by_char);
4776 DEFSUBR (Fsplit_path); /* #### */ 11958 DEFSUBR (Fsplit_path); /* #### */
4777 } 11959 }
4778 11960
4779 void 11961 void