comparison src/fns.c @ 5607:1a507c4c6c42

Refactor out sequence-oriented builtins from fns.c to the new sequence.c. src/ChangeLog addition: 2011-12-04 Aidan Kehoe <kehoea@parhasard.net> * Makefile.in.in (objs): * depend: Add sequence.o to the list of objects and dependencies. * alloc.c: * alloc.c (mark_bit_vector): * alloc.c (print_bit_vector): * alloc.c (bit_vector_equal): * alloc.c (internal_bit_vector_equalp_hash): * alloc.c (bit_vector_hash): * alloc.c (init_alloc_once_early): Move the implementation of the bit vector type here from fns.c. * emacs.c (main_1): Call syms_of_sequence() here, now sequence.c is included. * fns.c (Fold_rassq): Move this together with the rest of the Fold_* functions. * fns.c: * fns.c (syms_of_fns): Move most functions dealing with sequences generally, and especially those taking key arguments, to a separate file, sequence.c. * general-slots.h: Qyes_or_no_p belong here, not fns.c. * lisp.h: Make Flist_length available here, it's used by sequence.c * sequence.c: * sequence.c (check_sequence_range): * sequence.c (Flength): * sequence.c (check_other_nokey): * sequence.c (check_other_key): * sequence.c (check_if_key): * sequence.c (check_match_eq_key): * sequence.c (check_match_eql_key): * sequence.c (check_match_equal_key): * sequence.c (check_match_equalp_key): * sequence.c (check_match_other_key): * sequence.c (check_lss_key): * sequence.c (check_lss_key_car): * sequence.c (check_string_lessp_key): * sequence.c (check_string_lessp_key_car): * sequence.c (get_check_match_function_1): * sequence.c (get_merge_predicate): * sequence.c (count_with_tail): * sequence.c (list_count_from_end): * sequence.c (string_count_from_end): * sequence.c (Fcount): * sequence.c (Fsubseq): * sequence.c (list_position_cons_before): * sequence.c (FmemberX): * sequence.c (Fadjoin): * sequence.c (FassocX): * sequence.c (FrassocX): * sequence.c (position): * sequence.c (Fposition): * sequence.c (Ffind): * sequence.c (delq_no_quit_and_free_cons): * sequence.c (FdeleteX): * sequence.c (FremoveX): * sequence.c (list_delete_duplicates_from_end): * sequence.c (Fdelete_duplicates): * sequence.c (Fremove_duplicates): * sequence.c (Fnreverse): * sequence.c (Freverse): * sequence.c (list_merge): * sequence.c (array_merge): * sequence.c (list_array_merge_into_list): * sequence.c (list_list_merge_into_array): * sequence.c (list_array_merge_into_array): * sequence.c (Fmerge): * sequence.c (list_sort): * sequence.c (array_sort): * sequence.c (FsortX): * sequence.c (Ffill): * sequence.c (mapcarX): * sequence.c (shortest_length_among_sequences): * sequence.c (Fmapconcat): * sequence.c (FmapcarX): * sequence.c (Fmapvector): * sequence.c (Fmapcan): * sequence.c (Fmap): * sequence.c (Fmap_into): * sequence.c (Fsome): * sequence.c (Fevery): * sequence.c (Freduce): * sequence.c (replace_string_range_1): * sequence.c (Freplace): * sequence.c (Fnsubstitute): * sequence.c (Fsubstitute): * sequence.c (subst): * sequence.c (sublis): * sequence.c (Fsublis): * sequence.c (nsublis): * sequence.c (Fnsublis): * sequence.c (Fsubst): * sequence.c (Fnsubst): * sequence.c (tree_equal): * sequence.c (Ftree_equal): * sequence.c (mismatch_from_end): * sequence.c (mismatch_list_list): * sequence.c (mismatch_list_string): * sequence.c (mismatch_list_array): * sequence.c (mismatch_string_array): * sequence.c (mismatch_string_string): * sequence.c (mismatch_array_array): * sequence.c (get_mismatch_func): * sequence.c (Fmismatch): * sequence.c (Fsearch): * sequence.c (venn): * sequence.c (nvenn): * sequence.c (Funion): * sequence.c (Fset_exclusive_or): * sequence.c (Fnset_exclusive_or): * sequence.c (syms_of_sequence): Add this file, containing those general functions that dealt with sequences that were in fns.c. * symsinit.h: Make syms_of_sequence() available here. man/ChangeLog addition: 2011-12-04 Aidan Kehoe <kehoea@parhasard.net> * internals/internals.texi (Basic Lisp Modules): Document sequence.c here too.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 04 Dec 2011 18:42:50 +0000
parents 10f179710250
children e2fae7783046
comparison
equal deleted inserted replaced
5606:7c383c5784ed 5607:1a507c4c6c42
50 #include "opaque.h" 50 #include "opaque.h"
51 51
52 /* NOTE: This symbol is also used in lread.c */ 52 /* NOTE: This symbol is also used in lread.c */
53 #define FEATUREP_SYNTAX 53 #define FEATUREP_SYNTAX
54 54
55 Lisp_Object Qstring_lessp, Qmerge, Qfill, Qreplace, QassocX, QrassocX;
56 Lisp_Object Qposition, Qfind, QdeleteX, QremoveX, Qidentity, Qadjoin;
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 Lisp_Object Q_descend_structures;
63
64 Lisp_Object Qintersection, Qset_difference, Qnset_difference;
65 Lisp_Object Qnunion, Qnintersection, Qsubsetp, Qcar_less_than_car;
66
67 Lisp_Object Qbase64_conversion_error;
68
69 Lisp_Object Vpath_separator;
70
71 extern Fixnum max_lisp_eval_depth; 55 extern Fixnum max_lisp_eval_depth;
72 extern int lisp_eval_depth; 56 extern int lisp_eval_depth;
73 57
74 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth); 58 Lisp_Object Qmapl, Qmapcon, Qmaplist, Qbase64_conversion_error;
75 59
76 static DOESNT_RETURN 60 Lisp_Object Vpath_separator;
77 mapping_interaction_error (Lisp_Object func, Lisp_Object object)
78 {
79 invalid_state_2 ("object modified while traversing it", func, object);
80 }
81
82 static void
83 check_sequence_range (Lisp_Object sequence, Lisp_Object start,
84 Lisp_Object end, Lisp_Object length)
85 {
86 Lisp_Object args[] = { Qzero, start, NILP (end) ? length : end, length };
87
88 if (NILP (Fleq (countof (args), args)))
89 {
90 args_out_of_range_3 (sequence, start, end);
91 }
92 }
93
94 static Lisp_Object
95 mark_bit_vector (Lisp_Object UNUSED (obj))
96 {
97 return Qnil;
98 }
99
100 static void
101 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun,
102 int UNUSED (escapeflag))
103 {
104 Elemcount i;
105 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
106 Elemcount len = bit_vector_length (v);
107 Elemcount last = len;
108
109 if (FIXNUMP (Vprint_length))
110 last = min (len, XFIXNUM (Vprint_length));
111 write_ascstring (printcharfun, "#*");
112 for (i = 0; i < last; i++)
113 {
114 if (bit_vector_bit (v, i))
115 write_ascstring (printcharfun, "1");
116 else
117 write_ascstring (printcharfun, "0");
118 }
119
120 if (last != len)
121 write_ascstring (printcharfun, "...");
122 }
123
124 static int
125 bit_vector_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth),
126 int UNUSED (foldcase))
127 {
128 Lisp_Bit_Vector *v1 = XBIT_VECTOR (obj1);
129 Lisp_Bit_Vector *v2 = XBIT_VECTOR (obj2);
130
131 return ((bit_vector_length (v1) == bit_vector_length (v2)) &&
132 !memcmp (v1->bits, v2->bits,
133 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) *
134 sizeof (long)));
135 }
136
137 /* This needs to be algorithmically identical to internal_array_hash in
138 elhash.c when equalp is one, so arrays and bit vectors with the same
139 contents hash the same. It would be possible to enforce this by giving
140 internal_ARRAYLIKE_hash its own file and including it twice, but right
141 now that doesn't seem worth it. */
142 static Hashcode
143 internal_bit_vector_equalp_hash (Lisp_Bit_Vector *v)
144 {
145 int ii, size = bit_vector_length (v);
146 Hashcode hash = 0;
147
148 if (size <= 5)
149 {
150 for (ii = 0; ii < size; ii++)
151 {
152 hash = HASH2
153 (hash,
154 FLOAT_HASHCODE_FROM_DOUBLE ((double) (bit_vector_bit (v, ii))));
155 }
156 return hash;
157 }
158
159 /* just pick five elements scattered throughout the array.
160 A slightly better approach would be to offset by some
161 noise factor from the points chosen below. */
162 for (ii = 0; ii < 5; ii++)
163 hash = HASH2 (hash,
164 FLOAT_HASHCODE_FROM_DOUBLE
165 ((double) (bit_vector_bit (v, ii * size / 5))));
166
167 return hash;
168 }
169
170 static Hashcode
171 bit_vector_hash (Lisp_Object obj, int UNUSED (depth), Boolint equalp)
172 {
173 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
174 if (equalp)
175 {
176 return HASH2 (bit_vector_length (v),
177 internal_bit_vector_equalp_hash (v));
178 }
179
180 return HASH2 (bit_vector_length (v),
181 memory_hash (v->bits,
182 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) *
183 sizeof (long)));
184 }
185
186 static Bytecount
187 size_bit_vector (Lisp_Object obj)
188 {
189 Lisp_Bit_Vector *v = XBIT_VECTOR (obj);
190 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, unsigned long, bits,
191 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)));
192 }
193
194 static const struct memory_description bit_vector_description[] = {
195 { XD_END }
196 };
197
198
199 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("bit-vector", bit_vector,
200 mark_bit_vector,
201 print_bit_vector, 0,
202 bit_vector_equal,
203 bit_vector_hash,
204 bit_vector_description,
205 size_bit_vector,
206 Lisp_Bit_Vector);
207
208 /* Various test functions for #'member*, #'assoc* and the other functions
209 that take both TEST and KEY arguments. */
210
211 Boolint
212 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
213 Lisp_Object item, Lisp_Object elt)
214 {
215 return EQ (item, elt);
216 }
217
218 static Boolint
219 check_eq_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item,
220 Lisp_Object elt)
221 {
222 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
223 return EQ (item, elt);
224 }
225
226 /* The next two are not used by #'member* and #'assoc*, since we can decide
227 on #'eq vs. #'equal when we have the type of ITEM. */
228 static Boolint
229 check_eql_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
230 Lisp_Object elt1, Lisp_Object elt2)
231 {
232 return EQ (elt1, elt2)
233 || (NON_FIXNUM_NUMBER_P (elt1) && internal_equal (elt1, elt2, 0));
234 }
235
236 static Boolint
237 check_eql_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item,
238 Lisp_Object elt)
239 {
240 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
241 return EQ (item, elt)
242 || (NON_FIXNUM_NUMBER_P (item) && internal_equal (item, elt, 0));
243 }
244
245 static Boolint
246 check_equal_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
247 Lisp_Object item, Lisp_Object elt)
248 {
249 return internal_equal (item, elt, 0);
250 }
251
252 static Boolint
253 check_equal_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item,
254 Lisp_Object elt)
255 {
256 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
257 return internal_equal (item, elt, 0);
258 }
259
260 static Boolint
261 check_equalp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
262 Lisp_Object item, Lisp_Object elt)
263 {
264 return internal_equalp (item, elt, 0);
265 }
266
267 static Boolint
268 check_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key,
269 Lisp_Object item, Lisp_Object elt)
270 {
271 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
272 return internal_equalp (item, elt, 0);
273 }
274
275 static Boolint
276 check_string_match_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
277 Lisp_Object item, Lisp_Object elt)
278 {
279 return !NILP (Fstring_match (item, elt, Qnil, Qnil));
280 }
281
282 static Boolint
283 check_string_match_key (Lisp_Object UNUSED (test), Lisp_Object key,
284 Lisp_Object item, Lisp_Object elt)
285 {
286 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt));
287 return !NILP (Fstring_match (item, elt, Qnil, Qnil));
288 }
289
290 static Boolint
291 check_other_nokey (Lisp_Object test, Lisp_Object UNUSED (key),
292 Lisp_Object item, Lisp_Object elt)
293 {
294 Lisp_Object args[] = { test, item, elt };
295 struct gcpro gcpro1;
296
297 GCPRO1 (args[0]);
298 gcpro1.nvars = countof (args);
299 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
300 UNGCPRO;
301
302 return !NILP (item);
303 }
304
305 static Boolint
306 check_other_key (Lisp_Object test, Lisp_Object key,
307 Lisp_Object item, Lisp_Object elt)
308 {
309 Lisp_Object args[] = { item, key, elt };
310 struct gcpro gcpro1;
311
312 GCPRO1 (args[0]);
313 gcpro1.nvars = countof (args);
314 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args) - 1, args + 1));
315 args[1] = item;
316 args[0] = test;
317 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
318 UNGCPRO;
319
320 return !NILP (item);
321 }
322
323 static Boolint
324 check_if_nokey (Lisp_Object test, Lisp_Object UNUSED (key),
325 Lisp_Object UNUSED (item), Lisp_Object elt)
326 {
327 elt = IGNORE_MULTIPLE_VALUES (call1 (test, elt));
328 return !NILP (elt);
329 }
330
331 static Boolint
332 check_if_key (Lisp_Object test, Lisp_Object key,
333 Lisp_Object UNUSED (item), Lisp_Object elt)
334 {
335 Lisp_Object args[] = { key, elt };
336 struct gcpro gcpro1;
337
338 GCPRO1 (args[0]);
339 gcpro1.nvars = countof (args);
340 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
341 args[0] = test;
342 elt = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
343 UNGCPRO;
344
345 return !NILP (elt);
346 }
347
348 static Boolint
349 check_match_eq_key (Lisp_Object UNUSED (test), Lisp_Object key,
350 Lisp_Object elt1, Lisp_Object elt2)
351 {
352 Lisp_Object args[] = { key, elt1, elt2 };
353 struct gcpro gcpro1;
354
355 GCPRO1 (args[0]);
356 gcpro1.nvars = countof (args);
357 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
358 args[1] = key;
359 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
360 UNGCPRO;
361
362 return EQ (args[0], args[1]);
363 }
364
365 static Boolint
366 check_match_eql_key (Lisp_Object UNUSED (test), Lisp_Object key,
367 Lisp_Object elt1, Lisp_Object elt2)
368 {
369 Lisp_Object args[] = { key, elt1, elt2 };
370 struct gcpro gcpro1;
371
372 GCPRO1 (args[0]);
373 gcpro1.nvars = countof (args);
374 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
375 args[1] = key;
376 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
377 UNGCPRO;
378
379 return EQ (args[0], args[1]) ||
380 (NON_FIXNUM_NUMBER_P (args[0]) && internal_equal (args[0], args[1], 0));
381 }
382
383 static Boolint
384 check_match_equal_key (Lisp_Object UNUSED (test), Lisp_Object key,
385 Lisp_Object elt1, Lisp_Object elt2)
386 {
387 Lisp_Object args[] = { key, elt1, elt2 };
388 struct gcpro gcpro1;
389
390 GCPRO1 (args[0]);
391 gcpro1.nvars = countof (args);
392 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
393 args[1] = key;
394 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
395 UNGCPRO;
396
397 return internal_equal (args[0], args[1], 0);
398 }
399
400 static Boolint
401 check_match_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key,
402 Lisp_Object elt1, Lisp_Object elt2)
403 {
404 Lisp_Object args[] = { key, elt1, elt2 };
405 struct gcpro gcpro1;
406
407 GCPRO1 (args[0]);
408 gcpro1.nvars = countof (args);
409 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
410 args[1] = key;
411 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
412 UNGCPRO;
413
414 return internal_equalp (args[0], args[1], 0);
415 }
416
417 static Boolint
418 check_match_other_key (Lisp_Object test, Lisp_Object key,
419 Lisp_Object elt1, Lisp_Object elt2)
420 {
421 Lisp_Object args[] = { key, elt1, elt2 };
422 struct gcpro gcpro1;
423
424 GCPRO1 (args[0]);
425 gcpro1.nvars = countof (args);
426 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
427 args[1] = key;
428 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
429 args[1] = args[0];
430 args[0] = test;
431
432 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
433 UNGCPRO;
434
435 return !NILP (elt1);
436 }
437
438 static Boolint
439 check_lss_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
440 Lisp_Object elt1, Lisp_Object elt2)
441 {
442 return bytecode_arithcompare (elt1, elt2) < 0;
443 }
444
445 static Boolint
446 check_lss_key (Lisp_Object UNUSED (test), Lisp_Object key,
447 Lisp_Object elt1, Lisp_Object elt2)
448 {
449 Lisp_Object args[] = { key, elt1, elt2 };
450 struct gcpro gcpro1;
451
452 GCPRO1 (args[0]);
453 gcpro1.nvars = countof (args);
454 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
455 args[1] = key;
456 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
457 UNGCPRO;
458
459 return bytecode_arithcompare (args[0], args[1]) < 0;
460 }
461
462 Boolint
463 check_lss_key_car (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
464 Lisp_Object elt1, Lisp_Object elt2)
465 {
466 struct gcpro gcpro1, gcpro2;
467
468 GCPRO2 (elt1, elt2);
469 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
470 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
471 UNGCPRO;
472
473 return bytecode_arithcompare (elt1, elt2) < 0;
474 }
475
476 Boolint
477 check_string_lessp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key),
478 Lisp_Object elt1, Lisp_Object elt2)
479 {
480 return !NILP (Fstring_lessp (elt1, elt2));
481 }
482
483 static Boolint
484 check_string_lessp_key (Lisp_Object UNUSED (test), Lisp_Object key,
485 Lisp_Object elt1, Lisp_Object elt2)
486 {
487 Lisp_Object args[] = { key, elt1, elt2 };
488 struct gcpro gcpro1;
489
490 GCPRO1 (args[0]);
491 gcpro1.nvars = countof (args);
492 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args));
493 args[1] = key;
494 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1));
495 UNGCPRO;
496
497 return !NILP (Fstring_lessp (args[0], args[1]));
498 }
499
500 static Boolint
501 check_string_lessp_key_car (Lisp_Object UNUSED (test),
502 Lisp_Object UNUSED (key),
503 Lisp_Object elt1, Lisp_Object elt2)
504 {
505 struct gcpro gcpro1, gcpro2;
506
507 GCPRO2 (elt1, elt2);
508 elt1 = CONSP (elt1) ? XCAR (elt1) : Fcar (elt1);
509 elt2 = CONSP (elt2) ? XCAR (elt2) : Fcar (elt2);
510 UNGCPRO;
511
512 return !NILP (Fstring_lessp (elt1, elt2));
513 }
514
515 static check_test_func_t
516 get_check_match_function_1 (Lisp_Object item,
517 Lisp_Object *test_inout, Lisp_Object test_not,
518 Lisp_Object if_, Lisp_Object if_not,
519 Lisp_Object key, Boolint *test_not_unboundp_out,
520 check_test_func_t *test_func_out)
521 {
522 Lisp_Object test = *test_inout;
523 check_test_func_t result = NULL, test_func = NULL;
524 Boolint force_if = 0;
525
526 if (!NILP (if_))
527 {
528 if (!(NILP (test) && NILP (test_not) && NILP (if_not)))
529 {
530 invalid_argument ("only one keyword among :test :test-not "
531 ":if :if-not allowed", if_);
532 }
533
534 test = *test_inout = if_;
535 force_if = 1;
536 }
537 else if (!NILP (if_not))
538 {
539 if (!(NILP (test) && NILP (test_not)))
540 {
541 invalid_argument ("only one keyword among :test :test-not "
542 ":if :if-not allowed", if_not);
543 }
544
545 test_not = if_not;
546 force_if = 1;
547 }
548
549 if (NILP (test))
550 {
551 if (!NILP (test_not))
552 {
553 test = *test_inout = test_not;
554 if (NULL != test_not_unboundp_out)
555 {
556 *test_not_unboundp_out = 0;
557 }
558 }
559 else
560 {
561 test = Qeql;
562 if (NULL != test_not_unboundp_out)
563 {
564 *test_not_unboundp_out = 1;
565 }
566 }
567 }
568 else if (!NILP (test_not))
569 {
570 invalid_argument_2 ("conflicting :test and :test-not keyword arguments",
571 test, test_not);
572 }
573
574 test = indirect_function (test, 1);
575
576 if (NILP (key) ||
577 EQ (indirect_function (key, 1), XSYMBOL_FUNCTION (Qidentity)))
578 {
579 key = Qidentity;
580 }
581
582 if (force_if)
583 {
584 result = EQ (key, Qidentity) ? check_if_nokey : check_if_key;
585
586 if (NULL != test_func_out)
587 {
588 *test_func_out = result;
589 }
590
591 return result;
592 }
593
594 if (!UNBOUNDP (item) && EQ (test, XSYMBOL_FUNCTION (Qeql)))
595 {
596 test = XSYMBOL_FUNCTION (NON_FIXNUM_NUMBER_P (item) ? Qequal : Qeq);
597 }
598
599 #define FROB(known_test, eq_condition) \
600 if (EQ (test, XSYMBOL_FUNCTION (Q##known_test))) do \
601 { \
602 if (eq_condition) \
603 { \
604 test = XSYMBOL_FUNCTION (Qeq); \
605 goto force_eq_check; \
606 } \
607 \
608 if (!EQ (Qidentity, key)) \
609 { \
610 test_func = check_##known_test##_key; \
611 result = check_match_##known_test##_key; \
612 } \
613 else \
614 { \
615 result = test_func = check_##known_test##_nokey; \
616 } \
617 } while (0)
618
619 FROB (eql, 0);
620 else if (SUBRP (test))
621 {
622 force_eq_check:
623 FROB (eq, 0);
624 else FROB (equal, (SYMBOLP (item) || FIXNUMP (item) || CHARP (item)));
625 else FROB (equalp, (SYMBOLP (item)));
626 else if (EQ (test, XSYMBOL_FUNCTION (Qstring_match)))
627 {
628 if (EQ (Qidentity, key))
629 {
630 test_func = result = check_string_match_nokey;
631 }
632 else
633 {
634 test_func = check_string_match_key;
635 result = check_other_key;
636 }
637 }
638 }
639
640 if (NULL == result)
641 {
642 if (EQ (Qidentity, key))
643 {
644 test_func = result = check_other_nokey;
645 }
646 else
647 {
648 test_func = check_other_key;
649 result = check_match_other_key;
650 }
651 }
652
653 if (NULL != test_func_out)
654 {
655 *test_func_out = test_func;
656 }
657
658 return result;
659 }
660 #undef FROB
661
662 /* Given TEST, TEST_NOT, IF, IF_NOT, KEY, and ITEM, return a C function
663 pointer appropriate for use in deciding whether a given element of a
664 sequence satisfies TEST.
665
666 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero
667 if it was bound, and set *test_inout to the value it was bound to. If
668 TEST was not bound, leave *test_inout alone; the value is not used by
669 check_eq_*key() or check_equal_*key(), which are the defaults, depending
670 on the type of ITEM.
671
672 The returned function takes arguments (TEST, KEY, ITEM, ELT), where ITEM
673 is the item being searched for and ELT is the element of the sequence
674 being examined.
675
676 Error if both TEST and TEST_NOT were specified, which Common Lisp says is
677 undefined behaviour. */
678
679 static check_test_func_t
680 get_check_test_function (Lisp_Object item,
681 Lisp_Object *test_inout, Lisp_Object test_not,
682 Lisp_Object if_, Lisp_Object if_not,
683 Lisp_Object key, Boolint *test_not_unboundp_out)
684 {
685 check_test_func_t result = NULL;
686 get_check_match_function_1 (item, test_inout, test_not, if_, if_not,
687 key, test_not_unboundp_out, &result);
688 return result;
689 }
690
691 /* Given TEST, TEST_NOT, IF, IF_NOT and KEY, return a C function pointer
692 appropriate for use in deciding whether two given elements of a sequence
693 satisfy TEST.
694
695 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero
696 if it was bound, and set *test_inout to the value it was bound to. If
697 TEST was not bound, leave *test_inout alone; the value is not used by
698 check_eql_*key().
699
700 The returned function takes arguments (TEST, KEY, ELT1, ELT2), where ELT1
701 and ELT2 are elements of the sequence being examined.
702
703 The value that would be given by get_check_test_function() is returned in
704 *TEST_FUNC_OUT, which allows calling functions to do their own key checks
705 if they're processing one element at a time.
706
707 Error if both TEST and TEST_NOT were specified, which Common Lisp says is
708 undefined behaviour. */
709
710 static check_test_func_t
711 get_check_match_function (Lisp_Object *test_inout, Lisp_Object test_not,
712 Lisp_Object if_, Lisp_Object if_not,
713 Lisp_Object key, Boolint *test_not_unboundp_out,
714 check_test_func_t *test_func_out)
715 {
716 return get_check_match_function_1 (Qunbound, test_inout, test_not,
717 if_, if_not, key,
718 test_not_unboundp_out, test_func_out);
719 }
720
721 /* Given PREDICATE and KEY, return a C function pointer appropriate for use
722 in deciding whether one given element of a sequence is less than
723 another. */
724
725 static check_test_func_t
726 get_merge_predicate (Lisp_Object predicate, Lisp_Object key)
727 {
728 predicate = indirect_function (predicate, 1);
729
730 if (NILP (key))
731 {
732 key = Qidentity;
733 }
734 else
735 {
736 key = indirect_function (key, 1);
737 if (EQ (key, XSYMBOL_FUNCTION (Qidentity)))
738 {
739 key = Qidentity;
740 }
741 }
742
743 if (EQ (key, Qidentity) && EQ (predicate,
744 XSYMBOL_FUNCTION (Qcar_less_than_car)))
745 {
746 key = XSYMBOL_FUNCTION (Qcar);
747 predicate = XSYMBOL_FUNCTION (Qlss);
748 }
749
750 if (EQ (predicate, XSYMBOL_FUNCTION (Qlss)))
751 {
752 if (EQ (key, Qidentity))
753 {
754 return check_lss_nokey;
755 }
756
757 if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
758 {
759 return check_lss_key_car;
760 }
761
762 return check_lss_key;
763 }
764
765 if (EQ (predicate, XSYMBOL_FUNCTION (Qstring_lessp)))
766 {
767 if (EQ (key, Qidentity))
768 {
769 return check_string_lessp_nokey;
770 }
771
772 if (EQ (key, XSYMBOL_FUNCTION (Qcar)))
773 {
774 return check_string_lessp_key_car;
775 }
776
777 return check_string_lessp_key;
778 }
779
780 if (EQ (key, Qidentity))
781 {
782 return check_other_nokey;
783 }
784
785 return check_match_other_key;
786 }
787 61
788 DEFUN ("identity", Fidentity, 1, 1, 0, /* 62 DEFUN ("identity", Fidentity, 1, 1, 0, /*
789 Return the argument unchanged. 63 Return the argument unchanged.
790 */ 64 */
791 (arg)) 65 (arg))
845 (Qinvalid_argument, seq, 119 (Qinvalid_argument, seq,
846 "As of 20.3, `%s' no longer works with compiled-function objects", 120 "As of 20.3, `%s' no longer works with compiled-function objects",
847 function); 121 function);
848 } 122 }
849 123
850 DEFUN ("length", Flength, 1, 1, 0, /*
851 Return the length of vector, bit vector, list or string SEQUENCE.
852 */
853 (sequence))
854 {
855 retry:
856 if (STRINGP (sequence))
857 return make_fixnum (string_char_length (sequence));
858 else if (CONSP (sequence))
859 {
860 Elemcount len;
861 GET_EXTERNAL_LIST_LENGTH (sequence, len);
862 return make_fixnum (len);
863 }
864 else if (VECTORP (sequence))
865 return make_fixnum (XVECTOR_LENGTH (sequence));
866 else if (NILP (sequence))
867 return Qzero;
868 else if (BIT_VECTORP (sequence))
869 return make_fixnum (bit_vector_length (XBIT_VECTOR (sequence)));
870 else
871 {
872 check_losing_bytecode ("length", sequence);
873 sequence = wrong_type_argument (Qsequencep, sequence);
874 goto retry;
875 }
876 }
877
878 DEFUN ("safe-length", Fsafe_length, 1, 1, 0, /* 124 DEFUN ("safe-length", Fsafe_length, 1, 1, 0, /*
879 Return the length of a list, but avoid error or infinite loop. 125 Return the length of a list, but avoid error or infinite loop.
880 This function never gets an error. If LIST is not really a list, 126 This function never gets an error. If LIST is not really a list,
881 it returns 0. If LIST is circular, it returns a finite value 127 it returns 0. If LIST is circular, it returns a finite value
882 which is at least the number of distinct elements. 128 which is at least the number of distinct elements.
922 { 168 {
923 signal_malformed_list_error (list); 169 signal_malformed_list_error (list);
924 } 170 }
925 171
926 return EQ (hare, tortoise) && len != 0 ? Qnil : make_fixnum (len); 172 return EQ (hare, tortoise) && len != 0 ? Qnil : make_fixnum (len);
927 }
928
929 static Lisp_Object string_count_from_end (Lisp_Object, Lisp_Object ,
930 check_test_func_t, Boolint,
931 Lisp_Object, Lisp_Object,
932 Lisp_Object, Lisp_Object);
933
934 static Lisp_Object list_count_from_end (Lisp_Object, Lisp_Object,
935 check_test_func_t, Boolint,
936 Lisp_Object, Lisp_Object,
937 Lisp_Object, Lisp_Object);
938
939 /* Count the number of occurrences of ITEM in SEQUENCE; if SEQUENCE is a
940 list, store the cons cell of which the car is the last ITEM in SEQUENCE,
941 at the address given by tail_out. */
942
943 static Lisp_Object
944 count_with_tail (Lisp_Object *tail_out, int nargs, Lisp_Object *args,
945 Lisp_Object caller)
946 {
947 Lisp_Object item = args[0], sequence = args[1];
948 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, encountered = 0;
949 Elemcount len, ii = 0, counting = MOST_POSITIVE_FIXNUM;
950 Boolint test_not_unboundp = 1;
951 check_test_func_t check_test = NULL;
952
953 PARSE_KEYWORDS_8 (caller, nargs, args, 9,
954 (test, key, start, end, from_end, test_not, count,
955 if_, if_not), (start = Qzero), 2, 0);
956
957 CHECK_SEQUENCE (sequence);
958 CHECK_NATNUM (start);
959 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
960
961 if (!NILP (end))
962 {
963 CHECK_NATNUM (end);
964 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
965 }
966
967 if (!NILP (count))
968 {
969 CHECK_INTEGER (count);
970 counting = BIGNUMP (count) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (count);
971
972 /* Our callers should have filtered out non-positive COUNT. */
973 assert (counting >= 0);
974 /* And we're not prepared to handle COUNT from any other caller at the
975 moment. */
976 assert (EQ (caller, QremoveX)|| EQ (caller, QdeleteX));
977 }
978
979 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
980 key, &test_not_unboundp);
981
982 *tail_out = Qnil;
983
984 if (CONSP (sequence))
985 {
986 if (EQ (caller, Qcount) && !NILP (from_end)
987 && (!EQ (key, Qnil) ||
988 check_test == check_other_nokey || check_test == check_if_nokey))
989 {
990 /* #'count, #'count-if, and #'count-if-not are documented to have
991 a given traversal order if :from-end t is passed in, even
992 though forward traversal of the sequence has the same result
993 and is algorithmically less expensive for lists and strings.
994 This order isn't necessary for other callers, though. */
995 return list_count_from_end (item, sequence, check_test,
996 test_not_unboundp, test, key,
997 start, end);
998 }
999
1000 /* If COUNT is non-nil and FROM-END is t, we can give the tail
1001 containing the last match, since that's what #'remove* is
1002 interested in (a zero or negative COUNT won't ever reach
1003 count_with_tail(), our callers will return immediately on seeing
1004 it). */
1005 if (!NILP (count) && !NILP (from_end))
1006 {
1007 counting = MOST_POSITIVE_FIXNUM;
1008 }
1009
1010 {
1011 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
1012 {
1013 if (!(ii < ending))
1014 {
1015 break;
1016 }
1017
1018 if (starting <= ii &&
1019 check_test (test, key, item, elt) == test_not_unboundp)
1020 {
1021 encountered++;
1022 *tail_out = tail;
1023
1024 if (encountered == counting)
1025 {
1026 break;
1027 }
1028 }
1029
1030 ii++;
1031 }
1032 END_GC_EXTERNAL_LIST_LOOP (elt);
1033 }
1034
1035 if ((ii < starting || (ii < ending && !NILP (end))) &&
1036 encountered != counting)
1037 {
1038 check_sequence_range (args[1], start, end, Flength (args[1]));
1039 }
1040 }
1041 else if (STRINGP (sequence))
1042 {
1043 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp;
1044 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
1045 Lisp_Object character = Qnil;
1046
1047 if (EQ (caller, Qcount) && !NILP (from_end)
1048 && (!EQ (key, Qnil) ||
1049 check_test == check_other_nokey || check_test == check_if_nokey))
1050 {
1051 /* See comment above in the list code. */
1052 return string_count_from_end (item, sequence,
1053 check_test, test_not_unboundp,
1054 test, key, start, end);
1055 }
1056
1057 while (cursor_offset < byte_len && ii < ending && encountered < counting)
1058 {
1059 if (ii >= starting)
1060 {
1061 character = make_char (itext_ichar (cursor));
1062
1063 if (check_test (test, key, item, character)
1064 == test_not_unboundp)
1065 {
1066 encountered++;
1067 }
1068
1069 startp = XSTRING_DATA (sequence);
1070 cursor = startp + cursor_offset;
1071 if (byte_len != XSTRING_LENGTH (sequence)
1072 || !valid_ibyteptr_p (cursor))
1073 {
1074 mapping_interaction_error (caller, sequence);
1075 }
1076 }
1077
1078 INC_IBYTEPTR (cursor);
1079 cursor_offset = cursor - startp;
1080 ii++;
1081 }
1082
1083 if (ii < starting || (ii < ending && !NILP (end)))
1084 {
1085 check_sequence_range (sequence, start, end, Flength (sequence));
1086 }
1087 }
1088 else
1089 {
1090 Lisp_Object object = Qnil;
1091
1092 len = XFIXNUM (Flength (sequence));
1093 check_sequence_range (sequence, start, end, make_fixnum (len));
1094
1095 ending = min (ending, len);
1096 if (0 == len)
1097 {
1098 /* Catches the case where we have nil. */
1099 return make_integer (encountered);
1100 }
1101
1102 if (NILP (from_end))
1103 {
1104 for (ii = starting; ii < ending && encountered < counting; ii++)
1105 {
1106 object = Faref (sequence, make_fixnum (ii));
1107 if (check_test (test, key, item, object) == test_not_unboundp)
1108 {
1109 encountered++;
1110 }
1111 }
1112 }
1113 else
1114 {
1115 for (ii = ending - 1; ii >= starting && encountered < counting; ii--)
1116 {
1117 object = Faref (sequence, make_fixnum (ii));
1118 if (check_test (test, key, item, object) == test_not_unboundp)
1119 {
1120 encountered++;
1121 }
1122 }
1123 }
1124 }
1125
1126 return make_integer (encountered);
1127 }
1128
1129 static Lisp_Object
1130 list_count_from_end (Lisp_Object item, Lisp_Object sequence,
1131 check_test_func_t check_test, Boolint test_not_unboundp,
1132 Lisp_Object test, Lisp_Object key,
1133 Lisp_Object start, Lisp_Object end)
1134 {
1135 Elemcount length = XFIXNUM (Flength (sequence)), ii = 0, starting = XFIXNUM (start);
1136 Elemcount ending = NILP (end) ? length : XFIXNUM (end), encountered = 0;
1137 Lisp_Object *storage;
1138 struct gcpro gcpro1;
1139
1140 check_sequence_range (sequence, start, end, make_integer (length));
1141
1142 storage = alloca_array (Lisp_Object, ending - starting);
1143
1144 {
1145 EXTERNAL_LIST_LOOP_2 (elt, sequence)
1146 {
1147 if (starting <= ii && ii < ending)
1148 {
1149 storage[ii - starting] = elt;
1150 }
1151 ii++;
1152 }
1153 }
1154
1155 GCPRO1 (storage[0]);
1156 gcpro1.nvars = ending - starting;
1157
1158 for (ii = ending - 1; ii >= starting; ii--)
1159 {
1160 if (check_test (test, key, item, storage[ii - starting])
1161 == test_not_unboundp)
1162 {
1163 encountered++;
1164 }
1165 }
1166
1167 UNGCPRO;
1168
1169 return make_integer (encountered);
1170 }
1171
1172 static Lisp_Object
1173 string_count_from_end (Lisp_Object item, Lisp_Object sequence,
1174 check_test_func_t check_test, Boolint test_not_unboundp,
1175 Lisp_Object test, Lisp_Object key,
1176 Lisp_Object start, Lisp_Object end)
1177 {
1178 Elemcount length = string_char_length (sequence), ii = 0;
1179 Elemcount starting = XFIXNUM (start), ending = NILP (end) ? length : XFIXNUM (end);
1180 Elemcount encountered = 0;
1181 Ibyte *cursor = XSTRING_DATA (sequence);
1182 Ibyte *endp = cursor + XSTRING_LENGTH (sequence);
1183 Ichar *storage;
1184
1185 check_sequence_range (sequence, start, end, make_integer (length));
1186
1187 storage = alloca_array (Ichar, ending - starting);
1188
1189 while (cursor < endp && ii < ending)
1190 {
1191 if (starting <= ii && ii < ending)
1192 {
1193 storage [ii - starting] = itext_ichar (cursor);
1194 }
1195
1196 ii++;
1197 INC_IBYTEPTR (cursor);
1198 }
1199
1200 for (ii = ending - 1; ii >= starting; ii--)
1201 {
1202 if (check_test (test, key, item, make_char (storage [ii - starting]))
1203 == test_not_unboundp)
1204 {
1205 encountered++;
1206 }
1207 }
1208
1209 return make_integer (encountered);
1210 }
1211
1212 DEFUN ("count", Fcount, 2, MANY, 0, /*
1213 Count the number of occurrences of ITEM in SEQUENCE.
1214
1215 See `remove*' for the meaning of the keywords.
1216
1217 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
1218 */
1219 (int nargs, Lisp_Object *args))
1220 {
1221 Lisp_Object tail = Qnil;
1222
1223 /* count_with_tail() accepts more keywords than we do, check those we've
1224 been given. */
1225 PARSE_KEYWORDS (Fcount, nargs, args, 8,
1226 (test, test_not, if_, if_not, key, start, end, from_end),
1227 NULL);
1228
1229 return count_with_tail (&tail, nargs, args, Qcount);
1230 } 173 }
1231 174
1232 /*** string functions. ***/ 175 /*** string functions. ***/
1233 176
1234 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /* 177 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /*
1834 XCAR (tail) = Fcons (XCAR (car), XCDR (car)); 777 XCAR (tail) = Fcons (XCAR (car), XCDR (car));
1835 } 778 }
1836 return alist; 779 return alist;
1837 } 780 }
1838 781
1839 DEFUN ("copy-tree", Fcopy_tree, 1, 2, 0, /*
1840 Return a copy of a list and substructures.
1841 The argument is copied, and any lists contained within it are copied
1842 recursively. Circularities and shared substructures are not preserved.
1843 Second arg VECP causes vectors to be copied, too. Strings and bit vectors
1844 are not copied.
1845 */
1846 (arg, vecp))
1847 {
1848 return safe_copy_tree (arg, vecp, 0);
1849 }
1850
1851 Lisp_Object
1852 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth)
1853 {
1854 if (depth + lisp_eval_depth > max_lisp_eval_depth)
1855 stack_overflow ("Stack overflow in copy-tree", arg);
1856
1857 if (CONSP (arg))
1858 {
1859 Lisp_Object rest;
1860 rest = arg = Fcopy_sequence (arg);
1861 while (CONSP (rest))
1862 {
1863 Lisp_Object elt = XCAR (rest);
1864 QUIT;
1865 if (CONSP (elt) || VECTORP (elt))
1866 XCAR (rest) = safe_copy_tree (elt, vecp, depth + 1);
1867 if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */
1868 XCDR (rest) = safe_copy_tree (XCDR (rest), vecp, depth +1);
1869 rest = XCDR (rest);
1870 }
1871 }
1872 else if (VECTORP (arg) && ! NILP (vecp))
1873 {
1874 int i = XVECTOR_LENGTH (arg);
1875 int j;
1876 arg = Fcopy_sequence (arg);
1877 for (j = 0; j < i; j++)
1878 {
1879 Lisp_Object elt = XVECTOR_DATA (arg) [j];
1880 QUIT;
1881 if (CONSP (elt) || VECTORP (elt))
1882 XVECTOR_DATA (arg) [j] = safe_copy_tree (elt, vecp, depth + 1);
1883 }
1884 }
1885 return arg;
1886 }
1887
1888 DEFUN ("subseq", Fsubseq, 2, 3, 0, /*
1889 Return the subsequence of SEQUENCE starting at START and ending before END.
1890 END may be omitted; then the subsequence runs to the end of SEQUENCE.
1891
1892 If START or END is negative, it counts from the end, in contravention of
1893 Common Lisp.
1894 The returned subsequence is always of the same type as SEQUENCE.
1895 If SEQUENCE is a string, relevant parts of the string-extent-data
1896 are copied to the new string.
1897
1898 See also `substring-no-properties', which only operates on strings, and does
1899 not copy extent data.
1900 */
1901 (sequence, start, end))
1902 {
1903 Elemcount len, ss, ee = MOST_POSITIVE_FIXNUM, ii;
1904 Lisp_Object result = Qnil;
1905
1906 CHECK_SEQUENCE (sequence);
1907 CHECK_FIXNUM (start);
1908 ss = XFIXNUM (start);
1909
1910 if (!NILP (end))
1911 {
1912 CHECK_FIXNUM (end);
1913 ee = XFIXNUM (end);
1914 }
1915
1916 if (STRINGP (sequence))
1917 {
1918 Bytecount bstart, blen;
1919
1920 get_string_range_char (sequence, start, end, &ss, &ee,
1921 GB_HISTORICAL_STRING_BEHAVIOR);
1922 bstart = string_index_char_to_byte (sequence, ss);
1923 blen = string_offset_char_to_byte_len (sequence, bstart, ee - ss);
1924
1925 result = make_string (XSTRING_DATA (sequence) + bstart, blen);
1926 /* Copy any applicable extent information into the new string. */
1927 copy_string_extents (result, sequence, 0, bstart, blen);
1928 }
1929 else if (CONSP (sequence))
1930 {
1931 Lisp_Object result_tail, saved = sequence;
1932
1933 if (ss < 0 || ee < 0)
1934 {
1935 len = XFIXNUM (Flength (sequence));
1936 if (ss < 0)
1937 {
1938 ss = len + ss;
1939 start = make_integer (ss);
1940 }
1941
1942 if (ee < 0)
1943 {
1944 ee = len + ee;
1945 end = make_integer (ee);
1946 }
1947 else
1948 {
1949 ee = min (ee, len);
1950 }
1951 }
1952
1953 if (0 != ss)
1954 {
1955 sequence = Fnthcdr (make_fixnum (ss), sequence);
1956 }
1957
1958 ii = ss + 1;
1959
1960 if (ss < ee && !NILP (sequence))
1961 {
1962 result = result_tail = Fcons (Fcar (sequence), Qnil);
1963 sequence = Fcdr (sequence);
1964
1965 {
1966 EXTERNAL_LIST_LOOP_2 (elt, sequence)
1967 {
1968 if (!(ii < ee))
1969 {
1970 break;
1971 }
1972
1973 XSETCDR (result_tail, Fcons (elt, Qnil));
1974 result_tail = XCDR (result_tail);
1975 ii++;
1976 }
1977 }
1978 }
1979
1980 if (NILP (result) || (ii < ee && !NILP (end)))
1981 {
1982 /* We were handed a cons, which definitely has elements. nil
1983 result means either ss >= ee or SEQUENCE was nil after the
1984 nthcdr; in both cases that means START and END were incorrectly
1985 specified for this sequence. ii < ee with a non-nil end means
1986 the user handed us a bogus end value. */
1987 check_sequence_range (saved, start, end, Flength (saved));
1988 }
1989 }
1990 else
1991 {
1992 len = XFIXNUM (Flength (sequence));
1993 if (ss < 0)
1994 {
1995 ss = len + ss;
1996 start = make_integer (ss);
1997 }
1998
1999 if (ee < 0)
2000 {
2001 ee = len + ee;
2002 end = make_integer (ee);
2003 }
2004 else
2005 {
2006 ee = min (len, ee);
2007 }
2008
2009 check_sequence_range (sequence, start, end, make_fixnum (len));
2010
2011 if (VECTORP (sequence))
2012 {
2013 result = Fvector (ee - ss, XVECTOR_DATA (sequence) + ss);
2014 }
2015 else if (BIT_VECTORP (sequence))
2016 {
2017 result = make_bit_vector (ee - ss, Qzero);
2018
2019 for (ii = ss; ii < ee; ii++)
2020 {
2021 set_bit_vector_bit (XBIT_VECTOR (result), ii - ss,
2022 bit_vector_bit (XBIT_VECTOR (sequence), ii));
2023 }
2024 }
2025 else if (NILP (sequence))
2026 {
2027 DO_NOTHING;
2028 }
2029 else
2030 {
2031 /* Won't happen, since CHECK_SEQUENCE didn't error. */
2032 ABORT ();
2033 }
2034 }
2035
2036 return result;
2037 }
2038
2039 DEFUN ("substring-no-properties", Fsubstring_no_properties, 1, 3, 0, /* 782 DEFUN ("substring-no-properties", Fsubstring_no_properties, 1, 3, 0, /*
2040 Return a substring of STRING, without copying the extents. 783 Return a substring of STRING, without copying the extents.
2041 END may be nil or omitted; then the substring runs to the end of STRING. 784 END may be nil or omitted; then the substring runs to the end of STRING.
2042 If START or END is negative, it counts from the end. 785 If START or END is negative, it counts from the end.
2043 786
2283 { 1026 {
2284 /* This function can GC */ 1027 /* This function can GC */
2285 return Fcar (Fnthcdr (n, list)); 1028 return Fcar (Fnthcdr (n, list));
2286 } 1029 }
2287 1030
2288 DEFUN ("elt", Felt, 2, 2, 0, /*
2289 Return element of SEQUENCE at index N.
2290 */
2291 (sequence, n))
2292 {
2293 /* This function can GC */
2294 retry:
2295 CHECK_FIXNUM_COERCE_CHAR (n); /* yuck! */
2296 if (LISTP (sequence))
2297 {
2298 Lisp_Object tem = Fnthcdr (n, sequence);
2299 /* #### Utterly, completely, fucking disgusting.
2300 * #### The whole point of "elt" is that it operates on
2301 * #### sequences, and does error- (bounds-) checking.
2302 */
2303 if (CONSP (tem))
2304 return XCAR (tem);
2305 else
2306 #if 1
2307 /* This is The Way It Has Always Been. */
2308 return Qnil;
2309 #else
2310 /* This is The Way Mly and Cltl2 say It Should Be. */
2311 args_out_of_range (sequence, n);
2312 #endif
2313 }
2314 else if (STRINGP (sequence) ||
2315 VECTORP (sequence) ||
2316 BIT_VECTORP (sequence))
2317 return Faref (sequence, n);
2318 else
2319 {
2320 check_losing_bytecode ("elt", sequence);
2321 sequence = wrong_type_argument (Qsequencep, sequence);
2322 goto retry;
2323 }
2324 }
2325
2326 DEFUN ("last", Flast, 1, 2, 0, /* 1031 DEFUN ("last", Flast, 1, 2, 0, /*
2327 Return the tail of list LIST, of length N (default 1). 1032 Return the tail of list LIST, of length N (default 1).
2328 LIST may be a dotted list, but not a circular list. 1033 LIST may be a dotted list, but not a circular list.
2329 Optional argument N must be a non-negative integer. 1034 Optional argument N must be a non-negative integer.
2330 If N is zero, then the atom that terminates the list is returned. 1035 If N is zero, then the atom that terminates the list is returned.
2457 } 1162 }
2458 1163
2459 return retval; 1164 return retval;
2460 } 1165 }
2461 1166
2462 DEFUN ("member", Fmember, 2, 2, 0, /*
2463 Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
2464 The value is actually the tail of LIST whose car is ELT.
2465 */
2466 (elt, list))
2467 {
2468 EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
2469 {
2470 if (internal_equal (elt, list_elt, 0))
2471 return tail;
2472 }
2473 return Qnil;
2474 }
2475
2476 DEFUN ("memq", Fmemq, 2, 2, 0, /*
2477 Return non-nil if ELT is an element of LIST. Comparison done with `eq'.
2478 The value is actually the tail of LIST whose car is ELT.
2479 */
2480 (elt, list))
2481 {
2482 EXTERNAL_LIST_LOOP_3 (list_elt, list, tail)
2483 {
2484 if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
2485 return tail;
2486 }
2487 return Qnil;
2488 }
2489
2490 Lisp_Object
2491 memq_no_quit (Lisp_Object elt, Lisp_Object list)
2492 {
2493 LIST_LOOP_3 (list_elt, list, tail)
2494 {
2495 if (EQ_WITH_EBOLA_NOTICE (elt, list_elt))
2496 return tail;
2497 }
2498 return Qnil;
2499 }
2500
2501 /* Return the first index of ITEM in LIST. In CONS_OUT, return the cons cell
2502 before that containing the element. If the element is in the first cons
2503 cell, return Qnil in CONS_OUT. TEST, KEY, START, END are as in
2504 #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should have been initialized
2505 with get_check_match_function() or get_check_test_function(). A non-zero
2506 REVERSE_TEST_ORDER means call TEST with the element from LIST as its
2507 first argument and ITEM as its second. Error if LIST is ill-formed, or
2508 circular. */
2509 static Lisp_Object
2510 list_position_cons_before (Lisp_Object *cons_out,
2511 Lisp_Object item, Lisp_Object list,
2512 check_test_func_t check_test,
2513 Boolint test_not_unboundp,
2514 Lisp_Object test, Lisp_Object key,
2515 Boolint reverse_test_order,
2516 Lisp_Object start, Lisp_Object end)
2517 {
2518 struct gcpro gcpro1;
2519 Lisp_Object tail_before = Qnil;
2520 Elemcount ii = 0, starting = XFIXNUM (start);
2521 Elemcount ending = NILP (end) ? MOST_POSITIVE_FIXNUM : XFIXNUM (end);
2522
2523 GCPRO1 (tail_before);
2524
2525 if (check_test == check_eq_nokey)
2526 {
2527 /* TEST is #'eq, no need to call any C functions, and the test order
2528 won't be visible. */
2529 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
2530 {
2531 if (starting <= ii && ii < ending &&
2532 EQ (item, elt) == test_not_unboundp)
2533 {
2534 *cons_out = tail_before;
2535 RETURN_UNGCPRO (make_integer (ii));
2536 }
2537 else
2538 {
2539 if (ii >= ending)
2540 {
2541 break;
2542 }
2543 }
2544 ii++;
2545 tail_before = tail;
2546 }
2547 }
2548 else
2549 {
2550 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
2551 {
2552 if (starting <= ii && ii < ending &&
2553 (reverse_test_order ?
2554 check_test (test, key, elt, item) :
2555 check_test (test, key, item, elt)) == test_not_unboundp)
2556 {
2557 *cons_out = tail_before;
2558 XUNGCPRO (elt);
2559 UNGCPRO;
2560 return make_integer (ii);
2561 }
2562 else
2563 {
2564 if (ii >= ending)
2565 {
2566 break;
2567 }
2568 }
2569 ii++;
2570 tail_before = tail;
2571 }
2572 END_GC_EXTERNAL_LIST_LOOP (elt);
2573 }
2574
2575 RETURN_UNGCPRO (Qnil);
2576 }
2577
2578 DEFUN ("member*", FmemberX, 2, MANY, 0, /*
2579 Return the first sublist of LIST with car ITEM, or nil if no such sublist.
2580
2581 The keyword :test specifies a two-argument function that is used to compare
2582 ITEM with elements in LIST; if omitted, it defaults to `eql'.
2583
2584 The keyword :test-not is similar, but specifies a negated function. That
2585 is, ITEM is considered equal to an element in LIST if the given function
2586 returns nil. Common Lisp deprecates :test-not, and if both are specified,
2587 XEmacs signals an error.
2588
2589 :key specifies a one-argument function that transforms elements of LIST into
2590 \"comparison keys\" before the test predicate is applied. For example,
2591 if :key is #'car, then ITEM is compared with the car of elements from LIST.
2592 The :key function, however, is not applied to ITEM, and does not affect the
2593 elements in the returned list, which are taken directly from the elements in
2594 LIST.
2595
2596 arguments: (ITEM LIST &key (TEST #'eql) TEST-NOT (KEY #'identity))
2597 */
2598 (int nargs, Lisp_Object *args))
2599 {
2600 Lisp_Object item = args[0], list = args[1], result = Qnil, position0;
2601 Boolint test_not_unboundp = 1;
2602 check_test_func_t check_test = NULL;
2603
2604 PARSE_KEYWORDS (FmemberX, nargs, args, 5, (test, if_not, if_, test_not, key),
2605 NULL);
2606 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
2607 key, &test_not_unboundp);
2608 position0
2609 = list_position_cons_before (&result, item, list, check_test,
2610 test_not_unboundp, test, key, 0, Qzero, Qnil);
2611
2612 return CONSP (result) ? XCDR (result) : ZEROP (position0) ? list : Qnil;
2613 }
2614
2615 /* This macro might eventually find a better home than here. */
2616
2617 #define CHECK_KEY_ARGUMENT(key) \
2618 do { \
2619 if (NILP (key)) \
2620 { \
2621 key = Qidentity; \
2622 } \
2623 \
2624 if (!EQ (key, Qidentity)) \
2625 { \
2626 key = indirect_function (key, 1); \
2627 if (EQ (key, XSYMBOL_FUNCTION (Qidentity))) \
2628 { \
2629 key = Qidentity; \
2630 } \
2631 } \
2632 } while (0)
2633
2634 #define KEY(key, item) (EQ (Qidentity, key) ? item : \
2635 IGNORE_MULTIPLE_VALUES (call1 (key, item)))
2636
2637 DEFUN ("adjoin", Fadjoin, 2, MANY, 0, /*
2638 Return ITEM consed onto the front of LIST, if not already in LIST.
2639
2640 Otherwise, return LIST unmodified.
2641
2642 See `member*' for the meaning of the keywords.
2643
2644 arguments: (ITEM LIST &key (TEST #'eql) (KEY #'identity) TEST-NOT)
2645 */
2646 (int nargs, Lisp_Object *args))
2647 {
2648 Lisp_Object item = args[0], list = args[1], keyed = Qnil, ignore = Qnil;
2649 struct gcpro gcpro1;
2650 Boolint test_not_unboundp = 1;
2651 check_test_func_t check_test = NULL;
2652
2653 PARSE_KEYWORDS (Fadjoin, nargs, args, 3, (test, key, test_not),
2654 NULL);
2655
2656 CHECK_KEY_ARGUMENT (key);
2657
2658 keyed = KEY (key, item);
2659
2660 GCPRO1 (keyed);
2661 check_test = get_check_test_function (keyed, &test, test_not, Qnil, Qnil,
2662 key, &test_not_unboundp);
2663 if (NILP (list_position_cons_before (&ignore, keyed, list, check_test,
2664 test_not_unboundp, test, key, 0, Qzero,
2665 Qnil)))
2666 {
2667 RETURN_UNGCPRO (Fcons (item, list));
2668 }
2669
2670 RETURN_UNGCPRO (list);
2671 }
2672
2673 DEFUN ("assoc", Fassoc, 2, 2, 0, /*
2674 Return non-nil if KEY is `equal' to the car of an element of ALIST.
2675 The value is actually the element of ALIST whose car equals KEY.
2676 */
2677 (key, alist))
2678 {
2679 /* This function can GC. */
2680 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2681 {
2682 if (internal_equal (key, elt_car, 0))
2683 return elt;
2684 }
2685 return Qnil;
2686 }
2687
2688 Lisp_Object
2689 assoc_no_quit (Lisp_Object key, Lisp_Object alist)
2690 {
2691 int speccount = specpdl_depth ();
2692 specbind (Qinhibit_quit, Qt);
2693 return unbind_to_1 (speccount, Fassoc (key, alist));
2694 }
2695
2696 DEFUN ("assq", Fassq, 2, 2, 0, /*
2697 Return non-nil if KEY is `eq' to the car of an element of ALIST.
2698 The value is actually the element of ALIST whose car is KEY.
2699 Elements of ALIST that are not conses are ignored.
2700 */
2701 (key, alist))
2702 {
2703 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2704 {
2705 if (EQ_WITH_EBOLA_NOTICE (key, elt_car))
2706 return elt;
2707 }
2708 return Qnil;
2709 }
2710
2711 /* Like Fassq but never report an error and do not allow quits.
2712 Use only on lists known never to be circular. */
2713
2714 Lisp_Object
2715 assq_no_quit (Lisp_Object key, Lisp_Object alist)
2716 {
2717 /* This cannot GC. */
2718 LIST_LOOP_2 (elt, alist)
2719 {
2720 Lisp_Object elt_car = XCAR (elt);
2721 if (EQ_WITH_EBOLA_NOTICE (key, elt_car))
2722 return elt;
2723 }
2724 return Qnil;
2725 }
2726
2727 DEFUN ("assoc*", FassocX, 2, MANY, 0, /*
2728 Find the first item whose car matches ITEM in ALIST.
2729
2730 See `member*' for the meaning of :test, :test-not and :key.
2731
2732 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT)
2733 */
2734 (int nargs, Lisp_Object *args))
2735 {
2736 Lisp_Object item = args[0], alist = args[1];
2737 Boolint test_not_unboundp = 1;
2738 check_test_func_t check_test = NULL;
2739
2740 PARSE_KEYWORDS (FassocX, nargs, args, 5, (test, if_, if_not, test_not, key),
2741 NULL);
2742
2743 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
2744 key, &test_not_unboundp);
2745
2746 if (check_test == check_eq_nokey)
2747 {
2748 /* TEST is #'eq, no need to call any C functions. */
2749 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2750 {
2751 if (EQ (item, elt_car) == test_not_unboundp)
2752 {
2753 return elt;
2754 }
2755 }
2756 }
2757 else
2758 {
2759 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
2760 {
2761 if (CONSP (elt) &&
2762 check_test (test, key, item, XCAR (elt)) == test_not_unboundp)
2763 {
2764 XUNGCPRO (elt);
2765 return elt;
2766 }
2767 }
2768 END_GC_EXTERNAL_LIST_LOOP (elt);
2769 }
2770
2771 return Qnil;
2772 }
2773
2774 DEFUN ("rassoc", Frassoc, 2, 2, 0, /*
2775 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST.
2776 The value is actually the element of ALIST whose cdr equals VALUE.
2777 */
2778 (value, alist))
2779 {
2780 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2781 {
2782 if (internal_equal (value, elt_cdr, 0))
2783 return elt;
2784 }
2785 return Qnil;
2786 }
2787
2788 DEFUN ("rassq", Frassq, 2, 2, 0, /*
2789 Return non-nil if VALUE is `eq' to the cdr of an element of ALIST.
2790 The value is actually the element of ALIST whose cdr is VALUE.
2791 */
2792 (value, alist))
2793 {
2794 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2795 {
2796 if (EQ_WITH_EBOLA_NOTICE (value, elt_cdr))
2797 return elt;
2798 }
2799 return Qnil;
2800 }
2801
2802 DEFUN ("old-rassq", Fold_rassq, 2, 2, 0, /*
2803 Return non-nil if VALUE is `old-eq' to the cdr of an element of ALIST.
2804 The value is actually the element of ALIST whose cdr is VALUE.
2805 */
2806 (value, alist))
2807 {
2808 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2809 {
2810 if (HACKEQ_UNSAFE (value, elt_cdr))
2811 return elt;
2812 }
2813 return Qnil;
2814 }
2815
2816 /* Like Frassq, but caller must ensure that ALIST is properly
2817 nil-terminated and ebola-free. */
2818 Lisp_Object
2819 rassq_no_quit (Lisp_Object value, Lisp_Object alist)
2820 {
2821 LIST_LOOP_2 (elt, alist)
2822 {
2823 Lisp_Object elt_cdr = XCDR (elt);
2824 if (EQ_WITH_EBOLA_NOTICE (value, elt_cdr))
2825 return elt;
2826 }
2827 return Qnil;
2828 }
2829
2830 DEFUN ("rassoc*", FrassocX, 2, MANY, 0, /*
2831 Find the first item whose cdr matches ITEM in ALIST.
2832
2833 See `member*' for the meaning of :test, :test-not and :key.
2834
2835 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT)
2836 */
2837 (int nargs, Lisp_Object *args))
2838 {
2839 Lisp_Object item = args[0], alist = args[1];
2840 Boolint test_not_unboundp = 1;
2841 check_test_func_t check_test = NULL;
2842
2843 PARSE_KEYWORDS (FrassocX, nargs, args, 5, (test, if_, if_not, test_not, key),
2844 NULL);
2845
2846 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
2847 key, &test_not_unboundp);
2848
2849 if (check_test == check_eq_nokey)
2850 {
2851 /* TEST is #'eq, no need to call any C functions. */
2852 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2853 {
2854 if (EQ (item, elt_cdr) == test_not_unboundp)
2855 {
2856 return elt;
2857 }
2858 }
2859 }
2860 else
2861 {
2862 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
2863 {
2864 if (CONSP (elt) &&
2865 check_test (test, key, item, XCDR (elt)) == test_not_unboundp)
2866 {
2867 XUNGCPRO (elt);
2868 return elt;
2869 }
2870 }
2871 END_GC_EXTERNAL_LIST_LOOP (elt);
2872 }
2873
2874 return Qnil;
2875 }
2876
2877 /* This is the implementation of both #'find and #'position. */
2878 static Lisp_Object
2879 position (Lisp_Object *object_out, Lisp_Object item, Lisp_Object sequence,
2880 check_test_func_t check_test, Boolint test_not_unboundp,
2881 Lisp_Object test, Lisp_Object key, Lisp_Object start, Lisp_Object end,
2882 Lisp_Object from_end, Lisp_Object default_, Lisp_Object caller)
2883 {
2884 Lisp_Object result = Qnil;
2885 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, len, ii = 0;
2886
2887 CHECK_SEQUENCE (sequence);
2888 CHECK_NATNUM (start);
2889 starting = FIXNUMP (start) ? XFIXNUM (start) : 1 + MOST_POSITIVE_FIXNUM;
2890
2891 if (!NILP (end))
2892 {
2893 CHECK_NATNUM (end);
2894 ending = FIXNUMP (end) ? XFIXNUM (end) : 1 + MOST_POSITIVE_FIXNUM;
2895 }
2896
2897 *object_out = default_;
2898
2899 if (CONSP (sequence))
2900 {
2901 if (!(starting < ending))
2902 {
2903 check_sequence_range (sequence, start, end, Flength (sequence));
2904 /* starting could be equal to ending, in which case nil is what
2905 we want to return. */
2906 return Qnil;
2907 }
2908
2909 {
2910 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
2911 {
2912 if (starting <= ii && ii < ending
2913 && check_test (test, key, item, elt) == test_not_unboundp)
2914 {
2915 result = make_integer (ii);
2916 *object_out = elt;
2917
2918 if (NILP (from_end))
2919 {
2920 XUNGCPRO (elt);
2921 return result;
2922 }
2923 }
2924 else if (ii == ending)
2925 {
2926 break;
2927 }
2928
2929 ii++;
2930 }
2931 END_GC_EXTERNAL_LIST_LOOP (elt);
2932 }
2933
2934 if (ii < starting || (ii < ending && !NILP (end)))
2935 {
2936 check_sequence_range (sequence, start, end, Flength (sequence));
2937 }
2938 }
2939 else if (STRINGP (sequence))
2940 {
2941 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp;
2942 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
2943 Lisp_Object character = Qnil;
2944
2945 while (cursor_offset < byte_len && ii < ending)
2946 {
2947 if (ii >= starting)
2948 {
2949 character = make_char (itext_ichar (cursor));
2950
2951 if (check_test (test, key, item, character) == test_not_unboundp)
2952 {
2953 result = make_integer (ii);
2954 *object_out = character;
2955
2956 if (NILP (from_end))
2957 {
2958 return result;
2959 }
2960 }
2961
2962 startp = XSTRING_DATA (sequence);
2963 cursor = startp + cursor_offset;
2964 if (byte_len != XSTRING_LENGTH (sequence)
2965 || !valid_ibyteptr_p (cursor))
2966 {
2967 mapping_interaction_error (caller, sequence);
2968 }
2969 }
2970
2971 INC_IBYTEPTR (cursor);
2972 cursor_offset = cursor - startp;
2973 ii++;
2974 }
2975
2976 if (ii < starting || (ii < ending && !NILP (end)))
2977 {
2978 check_sequence_range (sequence, start, end, Flength (sequence));
2979 }
2980 }
2981 else
2982 {
2983 Lisp_Object object = Qnil;
2984 len = XFIXNUM (Flength (sequence));
2985 check_sequence_range (sequence, start, end, make_fixnum (len));
2986
2987 ending = min (ending, len);
2988 if (0 == len)
2989 {
2990 /* Catches the case where we have nil. */
2991 return result;
2992 }
2993
2994 if (NILP (from_end))
2995 {
2996 for (ii = starting; ii < ending; ii++)
2997 {
2998 object = Faref (sequence, make_fixnum (ii));
2999 if (check_test (test, key, item, object) == test_not_unboundp)
3000 {
3001 result = make_integer (ii);
3002 *object_out = object;
3003 return result;
3004 }
3005 }
3006 }
3007 else
3008 {
3009 for (ii = ending - 1; ii >= starting; ii--)
3010 {
3011 object = Faref (sequence, make_fixnum (ii));
3012 if (check_test (test, key, item, object) == test_not_unboundp)
3013 {
3014 result = make_integer (ii);
3015 *object_out = object;
3016 return result;
3017 }
3018 }
3019 }
3020 }
3021
3022 return result;
3023 }
3024
3025 DEFUN ("position", Fposition, 2, MANY, 0, /*
3026 Return the index of the first occurrence of ITEM in SEQUENCE.
3027
3028 Return nil if not found. See `remove*' for the meaning of the keywords.
3029
3030 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END TEST-NOT)
3031 */
3032 (int nargs, Lisp_Object *args))
3033 {
3034 Lisp_Object object = Qnil, item = args[0], sequence = args[1];
3035 Boolint test_not_unboundp = 1;
3036 check_test_func_t check_test = NULL;
3037
3038 PARSE_KEYWORDS (Fposition, nargs, args, 8,
3039 (test, if_, test_not, if_not, key, start, end, from_end),
3040 (start = Qzero));
3041
3042 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3043 key, &test_not_unboundp);
3044
3045 return position (&object, item, sequence, check_test, test_not_unboundp,
3046 test, key, start, end, from_end, Qnil, Qposition);
3047 }
3048
3049 DEFUN ("find", Ffind, 2, MANY, 0, /*
3050 Find the first occurrence of ITEM in SEQUENCE.
3051
3052 Return the matching ITEM, or nil if not found. See `remove*' for the
3053 meaning of the keywords.
3054
3055 The keyword :default, not specified by Common Lisp, designates an object to
3056 return instead of nil if ITEM is not found.
3057
3058 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) DEFAULT FROM-END TEST-NOT)
3059 */
3060 (int nargs, Lisp_Object *args))
3061 {
3062 Lisp_Object object = Qnil, item = args[0], sequence = args[1];
3063 Boolint test_not_unboundp = 1;
3064 check_test_func_t check_test = NULL;
3065
3066 PARSE_KEYWORDS (Ffind, nargs, args, 9,
3067 (test, if_, test_not, if_not, key, start, end, from_end,
3068 default_),
3069 (start = Qzero));
3070
3071 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3072 key, &test_not_unboundp);
3073
3074 position (&object, item, sequence, check_test, test_not_unboundp,
3075 test, key, start, end, from_end, default_, Qposition);
3076
3077 return object;
3078 }
3079
3080 /* Like Fdelq, but caller must ensure that LIST is properly
3081 nil-terminated and ebola-free. */
3082
3083 Lisp_Object
3084 delq_no_quit (Lisp_Object elt, Lisp_Object list)
3085 {
3086 LIST_LOOP_DELETE_IF (list_elt, list,
3087 (EQ_WITH_EBOLA_NOTICE (elt, list_elt)));
3088 return list;
3089 }
3090
3091 /* Be VERY careful with this. This is like delq_no_quit() but
3092 also calls free_cons() on the removed conses. You must be SURE
3093 that no pointers to the freed conses remain around (e.g.
3094 someone else is pointing to part of the list). This function
3095 is useful on internal lists that are used frequently and where
3096 the actual list doesn't escape beyond known code bounds. */
3097
3098 Lisp_Object
3099 delq_no_quit_and_free_cons (Lisp_Object elt, Lisp_Object list)
3100 {
3101 REGISTER Lisp_Object tail = list;
3102 REGISTER Lisp_Object prev = Qnil;
3103
3104 while (!NILP (tail))
3105 {
3106 REGISTER Lisp_Object tem = XCAR (tail);
3107 if (EQ (elt, tem))
3108 {
3109 Lisp_Object cons_to_free = tail;
3110 if (NILP (prev))
3111 list = XCDR (tail);
3112 else
3113 XCDR (prev) = XCDR (tail);
3114 tail = XCDR (tail);
3115 free_cons (cons_to_free);
3116 }
3117 else
3118 {
3119 prev = tail;
3120 tail = XCDR (tail);
3121 }
3122 }
3123 return list;
3124 }
3125
3126 DEFUN ("delete*", FdeleteX, 2, MANY, 0, /*
3127 Remove all occurrences of ITEM in SEQUENCE, destructively.
3128
3129 If SEQUENCE is a non-nil list, this modifies the list directly. A non-list
3130 SEQUENCE will not be destructively modified, rather, if ITEM occurs in it, a
3131 new SEQUENCE of the same type without ITEM will be returned.
3132
3133 See `remove*' for a non-destructive alternative, and for explanation of the
3134 keyword arguments.
3135
3136 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT)
3137 */
3138 (int nargs, Lisp_Object *args))
3139 {
3140 Lisp_Object item = args[0], sequence = args[1];
3141 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, counting = MOST_POSITIVE_FIXNUM;
3142 Elemcount len, ii = 0, encountered = 0, presenting = 0;
3143 Boolint test_not_unboundp = 1;
3144 check_test_func_t check_test = NULL;
3145
3146 PARSE_KEYWORDS (FdeleteX, nargs, args, 9,
3147 (test, if_not, if_, test_not, key, start, end, from_end,
3148 count), (start = Qzero, count = Qunbound));
3149
3150 CHECK_SEQUENCE (sequence);
3151 CHECK_NATNUM (start);
3152 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
3153
3154 if (!NILP (end))
3155 {
3156 CHECK_NATNUM (end);
3157 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
3158 }
3159
3160 if (!UNBOUNDP (count))
3161 {
3162 if (!NILP (count))
3163 {
3164 CHECK_INTEGER (count);
3165 if (FIXNUMP (count))
3166 {
3167 counting = XFIXNUM (count);
3168 }
3169 #ifdef HAVE_BIGNUM
3170 else
3171 {
3172 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
3173 1 + MOST_POSITIVE_FIXNUM : MOST_NEGATIVE_FIXNUM - 1;
3174 }
3175 #endif
3176
3177 if (counting < 1)
3178 {
3179 return sequence;
3180 }
3181
3182 if (!NILP (from_end))
3183 {
3184 /* Sigh, this is inelegant. Force count_with_tail () to ignore
3185 the count keyword, so we get the actual number of matching
3186 elements, and can start removing from the beginning for the
3187 from-end case. */
3188 for (ii = XSUBR (GET_DEFUN_LISP_OBJECT (FdeleteX))->min_args;
3189 ii < nargs; ii += 2)
3190 {
3191 if (EQ (args[ii], Q_count))
3192 {
3193 args[ii + 1] = Qnil;
3194 break;
3195 }
3196 }
3197 ii = 0;
3198 }
3199 }
3200 }
3201
3202 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3203 key, &test_not_unboundp);
3204
3205 if (CONSP (sequence))
3206 {
3207 Lisp_Object prev_tail_list_elt = Qnil, ignore = Qnil;
3208 Elemcount list_len = 0, deleted = 0;
3209 struct gcpro gcpro1;
3210
3211 if (!NILP (count) && !NILP (from_end))
3212 {
3213 /* Both COUNT and FROM-END were specified; we need to traverse the
3214 list twice. */
3215 Lisp_Object present = count_with_tail (&ignore, nargs, args,
3216 QdeleteX);
3217
3218 if (ZEROP (present))
3219 {
3220 return sequence;
3221 }
3222
3223 presenting = XFIXNUM (present);
3224
3225 /* If there are fewer items in the list than we have permission to
3226 delete, we don't need to differentiate between the :from-end
3227 nil and :from-end t cases. Otherwise, presenting is the number
3228 of matching items we need to ignore before we start to
3229 delete. */
3230 presenting = presenting <= counting ? 0 : presenting - counting;
3231 }
3232
3233 GCPRO1 (prev_tail_list_elt);
3234 ii = -1;
3235
3236 {
3237 GC_EXTERNAL_LIST_LOOP_4 (list_elt, sequence, tail, list_len)
3238 {
3239 ii++;
3240
3241 if (starting <= ii && ii < ending &&
3242 (check_test (test, key, item, list_elt) == test_not_unboundp)
3243 && (presenting ? encountered++ >= presenting
3244 : encountered++ < counting))
3245 {
3246 if (NILP (prev_tail_list_elt))
3247 {
3248 sequence = XCDR (tail);
3249 }
3250 else
3251 {
3252 XSETCDR (prev_tail_list_elt, XCDR (tail));
3253 }
3254
3255 /* Keep tortoise from ever passing hare. */
3256 list_len = 0;
3257 deleted++;
3258 }
3259 else
3260 {
3261 prev_tail_list_elt = tail;
3262 if (ii >= ending || (!presenting && encountered > counting))
3263 {
3264 break;
3265 }
3266 }
3267 }
3268 END_GC_EXTERNAL_LIST_LOOP (list_elt);
3269 }
3270
3271 UNGCPRO;
3272
3273 if ((ii < starting || (ii < ending && !NILP (end))) &&
3274 !(presenting ? encountered == presenting : encountered == counting))
3275 {
3276 check_sequence_range (args[1], start, end,
3277 make_fixnum (deleted + XFIXNUM (Flength (args[1]))));
3278 }
3279
3280 return sequence;
3281 }
3282 else if (STRINGP (sequence))
3283 {
3284 Ibyte *staging = alloca_ibytes (XSTRING_LENGTH (sequence));
3285 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence);
3286 Ibyte *cursor = startp;
3287 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence);
3288 Lisp_Object character, result = sequence;
3289
3290 if (!NILP (count) && !NILP (from_end))
3291 {
3292 Lisp_Object present = count_with_tail (&character, nargs, args,
3293 QdeleteX);
3294
3295 if (ZEROP (present))
3296 {
3297 return sequence;
3298 }
3299
3300 presenting = XFIXNUM (present);
3301
3302 /* If there are fewer items in the list than we have permission to
3303 delete, we don't need to differentiate between the :from-end
3304 nil and :from-end t cases. Otherwise, presenting is the number
3305 of matching items we need to ignore before we start to
3306 delete. */
3307 presenting = presenting <= counting ? 0 : presenting - counting;
3308 }
3309
3310 ii = 0;
3311 while (cursor_offset < byte_len)
3312 {
3313 if (ii >= starting && ii < ending)
3314 {
3315 character = make_char (itext_ichar (cursor));
3316
3317 if ((check_test (test, key, item, character)
3318 == test_not_unboundp)
3319 && (presenting ? encountered++ >= presenting :
3320 encountered++ < counting))
3321 {
3322 DO_NOTHING;
3323 }
3324 else
3325 {
3326 staging_cursor
3327 += set_itext_ichar (staging_cursor, XCHAR (character));
3328 }
3329
3330 startp = XSTRING_DATA (sequence);
3331 cursor = startp + cursor_offset;
3332 if (byte_len != XSTRING_LENGTH (sequence)
3333 || !valid_ibyteptr_p (cursor))
3334 {
3335 mapping_interaction_error (QdeleteX, sequence);
3336 }
3337 }
3338 else
3339 {
3340 staging_cursor += itext_copy_ichar (cursor, staging_cursor);
3341 }
3342
3343 INC_IBYTEPTR (cursor);
3344 cursor_offset = cursor - startp;
3345 ii++;
3346 }
3347
3348 if (ii < starting || (ii < ending && !NILP (end)))
3349 {
3350 check_sequence_range (sequence, start, end, Flength (sequence));
3351 }
3352
3353 if (0 != encountered)
3354 {
3355 result = make_string (staging, staging_cursor - staging);
3356 copy_string_extents (result, sequence, 0, 0,
3357 staging_cursor - staging);
3358 sequence = result;
3359 }
3360
3361 return sequence;
3362 }
3363 else
3364 {
3365 Lisp_Object position0 = Qnil, object = Qnil;
3366 Lisp_Object *staging = NULL, *staging_cursor, *staging_limit;
3367 Elemcount positioning;
3368
3369 len = XFIXNUM (Flength (sequence));
3370
3371 check_sequence_range (sequence, start, end, make_fixnum (len));
3372
3373 position0 = position (&object, item, sequence, check_test,
3374 test_not_unboundp, test, key, start, end,
3375 from_end, Qnil, QdeleteX);
3376 if (NILP (position0))
3377 {
3378 return sequence;
3379 }
3380
3381 ending = min (ending, len);
3382 positioning = XFIXNUM (position0);
3383 encountered = 1;
3384
3385 if (NILP (from_end))
3386 {
3387 staging = alloca_array (Lisp_Object, len - 1);
3388 staging_cursor = staging;
3389
3390 ii = 0;
3391 while (ii < positioning)
3392 {
3393 *staging_cursor++ = Faref (sequence, make_fixnum (ii));
3394 ii++;
3395 }
3396
3397 ii = positioning + 1;
3398 while (ii < ending)
3399 {
3400 object = Faref (sequence, make_fixnum (ii));
3401 if (encountered < counting
3402 && (check_test (test, key, item, object)
3403 == test_not_unboundp))
3404 {
3405 encountered++;
3406 }
3407 else
3408 {
3409 *staging_cursor++ = object;
3410 }
3411 ii++;
3412 }
3413
3414 while (ii < len)
3415 {
3416 *staging_cursor++ = Faref (sequence, make_fixnum (ii));
3417 ii++;
3418 }
3419 }
3420 else
3421 {
3422 staging = alloca_array (Lisp_Object, len - 1);
3423 staging_cursor = staging_limit = staging + len - 1;
3424
3425 ii = len - 1;
3426 while (ii > positioning)
3427 {
3428 *--staging_cursor = Faref (sequence, make_fixnum (ii));
3429 ii--;
3430 }
3431
3432 ii = positioning - 1;
3433 while (ii >= starting)
3434 {
3435 object = Faref (sequence, make_fixnum (ii));
3436 if (encountered < counting
3437 && (check_test (test, key, item, object) ==
3438 test_not_unboundp))
3439 {
3440 encountered++;
3441 }
3442 else
3443 {
3444 *--staging_cursor = object;
3445 }
3446
3447 ii--;
3448 }
3449
3450 while (ii >= 0)
3451 {
3452 *--staging_cursor = Faref (sequence, make_fixnum (ii));
3453 ii--;
3454 }
3455
3456 staging = staging_cursor;
3457 staging_cursor = staging_limit;
3458 }
3459
3460 if (VECTORP (sequence))
3461 {
3462 return Fvector (staging_cursor - staging, staging);
3463 }
3464 else if (BIT_VECTORP (sequence))
3465 {
3466 return Fbit_vector (staging_cursor - staging, staging);
3467 }
3468
3469 /* A nil sequence will have given us a nil #'position,
3470 above. */
3471 ABORT ();
3472
3473 return Qnil;
3474 }
3475 }
3476
3477 DEFUN ("remove*", FremoveX, 2, MANY, 0, /*
3478 Remove all occurrences of ITEM in SEQUENCE, non-destructively.
3479
3480 If SEQUENCE is a list, `remove*' makes a copy if that is necessary to avoid
3481 corrupting the original SEQUENCE.
3482
3483 The keywords :test and :test-not specify two-argument test and negated-test
3484 predicates, respectively; :test defaults to `eql'. :key specifies a
3485 one-argument function that transforms elements of SEQUENCE into \"comparison
3486 keys\" before the test predicate is applied. See `member*' for more
3487 information on these keywords.
3488
3489 :start and :end, if given, specify indices of a subsequence of SEQUENCE to
3490 be processed. Indices are 0-based and processing involves the subsequence
3491 starting at the index given by :start and ending just before the index given
3492 by :end.
3493
3494 :count, if given, limits the number of items removed to the number
3495 specified. :from-end, if given, causes processing to proceed starting from
3496 the end instead of the beginning; in this case, this matters only if :count
3497 is given.
3498
3499 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT)
3500 */
3501 (int nargs, Lisp_Object *args))
3502 {
3503 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil,
3504 tail = Qnil;
3505 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, counting = MOST_POSITIVE_FIXNUM;
3506 Elemcount ii = 0, encountered = 0, presenting = 0;
3507 Boolint test_not_unboundp = 1;
3508 check_test_func_t check_test = NULL;
3509
3510 PARSE_KEYWORDS (FremoveX, nargs, args, 9,
3511 (test, if_not, if_, test_not, key, start, end, from_end,
3512 count), (start = Qzero));
3513
3514 if (!CONSP (sequence))
3515 {
3516 return FdeleteX (nargs, args);
3517 }
3518
3519 CHECK_NATNUM (start);
3520 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
3521
3522 if (!NILP (end))
3523 {
3524 CHECK_NATNUM (end);
3525 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
3526 }
3527
3528 if (!NILP (count))
3529 {
3530 CHECK_INTEGER (count);
3531 if (FIXNUMP (count))
3532 {
3533 counting = XFIXNUM (count);
3534 }
3535 #ifdef HAVE_BIGNUM
3536 else
3537 {
3538 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
3539 1 + MOST_POSITIVE_FIXNUM : -1 + MOST_NEGATIVE_FIXNUM;
3540 }
3541 #endif
3542
3543 if (counting <= 0)
3544 {
3545 return sequence;
3546 }
3547
3548 if (!NILP (from_end))
3549 {
3550 /* Sigh, this is inelegant. Force count_with_tail () to ignore the
3551 count keyword, so we get the actual number of matching
3552 elements, and can start removing from the beginning for the
3553 from-end case. */
3554 for (ii = XSUBR (GET_DEFUN_LISP_OBJECT (FremoveX))->min_args;
3555 ii < nargs; ii += 2)
3556 {
3557 if (EQ (args[ii], Q_count))
3558 {
3559 args[ii + 1] = Qnil;
3560 break;
3561 }
3562 }
3563 ii = 0;
3564 }
3565 }
3566
3567 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
3568 key, &test_not_unboundp);
3569
3570 matched_count = count_with_tail (&tail, nargs, args, QremoveX);
3571
3572 if (!ZEROP (matched_count))
3573 {
3574 Lisp_Object result = Qnil, result_tail = Qnil;
3575 struct gcpro gcpro1, gcpro2;
3576
3577 if (!NILP (count) && !NILP (from_end))
3578 {
3579 presenting = XFIXNUM (matched_count);
3580
3581 /* If there are fewer matching elements in the list than we have
3582 permission to delete, we don't need to differentiate between
3583 the :from-end nil and :from-end t cases. Otherwise, presenting
3584 is the number of matching items we need to ignore before we
3585 start to delete. */
3586 presenting = presenting <= counting ? 0 : presenting - counting;
3587 }
3588
3589 GCPRO2 (result, tail);
3590 {
3591 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
3592 {
3593 if (EQ (tail, tailing))
3594 {
3595 XUNGCPRO (elt);
3596 UNGCPRO;
3597
3598 if (NILP (result))
3599 {
3600 return XCDR (tail);
3601 }
3602
3603 XSETCDR (result_tail, XCDR (tail));
3604 return result;
3605 }
3606 else if (starting <= ii && ii < ending &&
3607 (check_test (test, key, item, elt) == test_not_unboundp)
3608 && (presenting ? encountered++ >= presenting
3609 : encountered++ < counting))
3610 {
3611 DO_NOTHING;
3612 }
3613 else if (NILP (result))
3614 {
3615 result = result_tail = Fcons (elt, Qnil);
3616 }
3617 else
3618 {
3619 XSETCDR (result_tail, Fcons (elt, Qnil));
3620 result_tail = XCDR (result_tail);
3621 }
3622
3623 if (ii == ending)
3624 {
3625 break;
3626 }
3627
3628 ii++;
3629 }
3630 END_GC_EXTERNAL_LIST_LOOP (elt);
3631 }
3632 UNGCPRO;
3633
3634 if (ii < starting || (ii < ending && !NILP (end)))
3635 {
3636 check_sequence_range (args[0], start, end, Flength (args[0]));
3637 }
3638
3639 return result;
3640 }
3641
3642 return sequence;
3643 }
3644
3645 Lisp_Object
3646 remassoc_no_quit (Lisp_Object key, Lisp_Object alist)
3647 {
3648 LIST_LOOP_DELETE_IF (elt, alist,
3649 (CONSP (elt) &&
3650 internal_equal (key, XCAR (elt), 0)));
3651 return alist;
3652 }
3653
3654 /* no quit, no errors; be careful */
3655
3656 Lisp_Object
3657 remassq_no_quit (Lisp_Object key, Lisp_Object alist)
3658 {
3659 LIST_LOOP_DELETE_IF (elt, alist,
3660 (CONSP (elt) &&
3661 EQ_WITH_EBOLA_NOTICE (key, XCAR (elt))));
3662 return alist;
3663 }
3664
3665 /* Like Fremrassq, fast and unsafe; be careful */
3666 Lisp_Object
3667 remrassq_no_quit (Lisp_Object value, Lisp_Object alist)
3668 {
3669 LIST_LOOP_DELETE_IF (elt, alist,
3670 (CONSP (elt) &&
3671 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt))));
3672 return alist;
3673 }
3674
3675 /* Remove duplicate elements between START and END from LIST, a non-nil
3676 list; if COPY is zero, do so destructively. Items to delete are selected
3677 according to the algorithm used when :from-end t is passed to
3678 #'delete-duplicates. Error if LIST is ill-formed or circular.
3679
3680 TEST and KEY are as in #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should
3681 reflect them, having been initialised with get_check_match_function() or
3682 get_check_test_function(). */
3683 static Lisp_Object
3684 list_delete_duplicates_from_end (Lisp_Object list,
3685 check_test_func_t check_test,
3686 Boolint test_not_unboundp,
3687 Lisp_Object test, Lisp_Object key,
3688 Lisp_Object start,
3689 Lisp_Object end, Boolint copy)
3690 {
3691 Lisp_Object checking = Qnil, result = list;
3692 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail;
3693 Elemcount len = XFIXNUM (Flength (list)), pos, starting = XFIXNUM (start);
3694 Elemcount ending = (NILP (end) ? len : XFIXNUM (end)), greatest_pos_seen = -1;
3695 Elemcount ii = 0;
3696 struct gcpro gcpro1;
3697
3698 /* We can't delete (or remove) as we go, because that breaks START and
3699 END. We could if END were nil, and that would change an ON(N + 2)
3700 algorithm to an ON^2 algorithm. Here and now it doesn't matter, though,
3701 #'delete-duplicates is relatively expensive no matter what. */
3702 struct Lisp_Bit_Vector *deleting
3703 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
3704 + (sizeof (long)
3705 * (BIT_VECTOR_LONG_STORAGE (len)
3706 - 1)));
3707
3708 check_sequence_range (list, start, end, make_integer (len));
3709
3710 deleting->size = len;
3711 memset (&(deleting->bits), 0,
3712 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
3713
3714 GCPRO1 (keyed);
3715
3716 {
3717 GC_EXTERNAL_LIST_LOOP_3 (elt, list, tail)
3718 {
3719 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii))
3720 {
3721 ii++;
3722 continue;
3723 }
3724
3725 keyed = KEY (key, elt);
3726 checking = XCDR (tail);
3727 pos = ii + 1;
3728
3729 while (!NILP ((positioned = list_position_cons_before
3730 (&position_cons, keyed, checking, check_test,
3731 test_not_unboundp, test, key, 0,
3732 make_fixnum (max (starting - pos, 0)),
3733 make_fixnum (ending - pos)))))
3734 {
3735 pos = XFIXNUM (positioned) + pos;
3736 set_bit_vector_bit (deleting, pos, 1);
3737 greatest_pos_seen = max (greatest_pos_seen, pos);
3738 checking = NILP (position_cons) ?
3739 XCDR (checking) : XCDR (XCDR (position_cons));
3740 pos += 1;
3741 }
3742 ii++;
3743 }
3744 END_GC_EXTERNAL_LIST_LOOP (elt);
3745 }
3746
3747 UNGCPRO;
3748
3749 ii = 0;
3750
3751 if (greatest_pos_seen > -1)
3752 {
3753 if (copy)
3754 {
3755 result = result_tail = Fcons (XCAR (list), Qnil);
3756 list = XCDR (list);
3757 ii = 1;
3758
3759 {
3760 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
3761 {
3762 if (ii == greatest_pos_seen)
3763 {
3764 XSETCDR (result_tail, XCDR (tail));
3765 break;
3766 }
3767 else if (!bit_vector_bit (deleting, ii))
3768 {
3769 XSETCDR (result_tail, Fcons (elt, Qnil));
3770 result_tail = XCDR (result_tail);
3771 }
3772 ii++;
3773 }
3774 }
3775 }
3776 else
3777 {
3778 EXTERNAL_LIST_LOOP_DELETE_IF (elt, list,
3779 bit_vector_bit (deleting, ii++));
3780 }
3781 }
3782
3783 return result;
3784 }
3785
3786 DEFUN ("delete-duplicates", Fdelete_duplicates, 1, MANY, 0, /*
3787 Remove all duplicate elements from SEQUENCE, destructively.
3788
3789 If SEQUENCE is a list and has duplicates, modify and return it. Note that
3790 SEQUENCE may start with an element to be deleted; because of this, if
3791 modifying a variable, be sure to write `(setq VARIABLE (delete-duplicates
3792 VARIABLE))' to be certain to have a list without duplicate elements.
3793
3794 If SEQUENCE is an array and has duplicates, return a newly-allocated array
3795 of the same type comprising all unique elements of SEQUENCE.
3796
3797 If there are no duplicate elements in SEQUENCE, return it unmodified.
3798
3799 See `remove*' for the meaning of the keywords. See `remove-duplicates' for
3800 a non-destructive version of this function.
3801
3802 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
3803 */
3804 (int nargs, Lisp_Object *args))
3805 {
3806 Lisp_Object sequence = args[0], keyed = Qnil;
3807 Lisp_Object positioned = Qnil, ignore = Qnil;
3808 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, len, ii = 0, jj = 0;
3809 Boolint test_not_unboundp = 1;
3810 check_test_func_t check_test = NULL;
3811 struct gcpro gcpro1, gcpro2;
3812
3813 PARSE_KEYWORDS (Fdelete_duplicates, nargs, args, 6,
3814 (test, key, test_not, start, end, from_end),
3815 (start = Qzero));
3816
3817 CHECK_SEQUENCE (sequence);
3818 CHECK_NATNUM (start);
3819 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
3820
3821 if (!NILP (end))
3822 {
3823 CHECK_NATNUM (end);
3824 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
3825 }
3826
3827 CHECK_KEY_ARGUMENT (key);
3828
3829 get_check_match_function (&test, test_not, Qnil, Qnil, key,
3830 &test_not_unboundp, &check_test);
3831
3832 if (CONSP (sequence))
3833 {
3834 if (NILP (from_end))
3835 {
3836 Lisp_Object prev_tail = Qnil;
3837 Elemcount deleted = 0;
3838
3839 GCPRO2 (keyed, prev_tail);
3840
3841 {
3842 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
3843 {
3844 if (starting <= ii && ii < ending)
3845 {
3846 keyed = KEY (key, elt);
3847 positioned
3848 = list_position_cons_before (&ignore, keyed,
3849 XCDR (tail), check_test,
3850 test_not_unboundp, test, key,
3851 0, make_fixnum (max (starting
3852 - (ii + 1),
3853 0)),
3854 make_fixnum (ending
3855 - (ii + 1)));
3856 if (!NILP (positioned))
3857 {
3858 sequence = XCDR (tail);
3859 deleted++;
3860 }
3861 else
3862 {
3863 break;
3864 }
3865 }
3866 else
3867 {
3868 break;
3869 }
3870
3871 ii++;
3872 }
3873 END_GC_EXTERNAL_LIST_LOOP (elt);
3874 }
3875 {
3876 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
3877 {
3878 if (!(starting <= ii && ii <= ending))
3879 {
3880 prev_tail = tail;
3881 ii++;
3882 continue;
3883 }
3884
3885 keyed = KEY (key, elt);
3886 positioned
3887 = list_position_cons_before (&ignore, keyed, XCDR (tail),
3888 check_test, test_not_unboundp,
3889 test, key, 0,
3890 make_fixnum (max (starting
3891 - (ii + 1), 0)),
3892 make_fixnum (ending - (ii + 1)));
3893 if (!NILP (positioned))
3894 {
3895 /* We know this isn't the first iteration of the loop,
3896 because we advanced above to the point where we have at
3897 least one non-duplicate entry at the head of the
3898 list. */
3899 XSETCDR (prev_tail, XCDR (tail));
3900 len = 0;
3901 deleted++;
3902 }
3903 else
3904 {
3905 prev_tail = tail;
3906 if (ii >= ending)
3907 {
3908 break;
3909 }
3910 }
3911
3912 ii++;
3913 }
3914 END_GC_EXTERNAL_LIST_LOOP (elt);
3915 }
3916
3917 UNGCPRO;
3918
3919 if ((ii < starting || (ii < ending && !NILP (end))))
3920 {
3921 check_sequence_range (args[0], start, end,
3922 make_fixnum (deleted
3923 + XFIXNUM (Flength (args[0]))));
3924 }
3925 }
3926 else
3927 {
3928 sequence = list_delete_duplicates_from_end (sequence, check_test,
3929 test_not_unboundp,
3930 test, key, start, end,
3931 0);
3932 }
3933 }
3934 else if (STRINGP (sequence))
3935 {
3936 Lisp_Object elt = Qnil;
3937
3938 if (EQ (Qidentity, key))
3939 {
3940 /* We know all the elements will be characters; set check_test to
3941 reflect that. This isn't useful if KEY is not #'identity, since
3942 it may return non-characters for the elements. */
3943 check_test = get_check_test_function (make_char ('a'),
3944 &test, test_not,
3945 Qnil, Qnil, key,
3946 &test_not_unboundp);
3947 }
3948
3949 if (NILP (from_end))
3950 {
3951 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0;
3952 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging;
3953 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor;
3954 Elemcount deleted = 0;
3955
3956 GCPRO1 (elt);
3957
3958 while (cursor_offset < byte_len)
3959 {
3960 if (starting <= ii && ii < ending)
3961 {
3962 Ibyte *cursor0 = cursor;
3963 Bytecount cursor0_offset;
3964 Boolint delete_this = 0;
3965
3966 elt = KEY (key, make_char (itext_ichar (cursor)));
3967 INC_IBYTEPTR (cursor0);
3968 cursor0_offset = cursor0 - startp;
3969
3970 for (jj = ii + 1; jj < ending && cursor0_offset < byte_len;
3971 jj++)
3972 {
3973 if (check_test (test, key, elt,
3974 make_char (itext_ichar (cursor0)))
3975 == test_not_unboundp)
3976 {
3977 delete_this = 1;
3978 deleted++;
3979 break;
3980 }
3981
3982 startp = XSTRING_DATA (sequence);
3983 cursor0 = startp + cursor0_offset;
3984 if (byte_len != XSTRING_LENGTH (sequence)
3985 || !valid_ibyteptr_p (cursor0))
3986 {
3987 mapping_interaction_error (Qdelete_duplicates,
3988 sequence);
3989 }
3990
3991 INC_IBYTEPTR (cursor0);
3992 cursor0_offset = cursor0 - startp;
3993 }
3994
3995 startp = XSTRING_DATA (sequence);
3996 cursor = startp + cursor_offset;
3997
3998 if (byte_len != XSTRING_LENGTH (sequence)
3999 || !valid_ibyteptr_p (cursor))
4000 {
4001 mapping_interaction_error (Qdelete_duplicates, sequence);
4002 }
4003
4004 if (!delete_this)
4005 {
4006 staging_cursor
4007 += itext_copy_ichar (cursor, staging_cursor);
4008
4009 }
4010 }
4011 else
4012 {
4013 staging_cursor += itext_copy_ichar (cursor, staging_cursor);
4014 }
4015
4016 INC_IBYTEPTR (cursor);
4017 cursor_offset = cursor - startp;
4018 ii++;
4019 }
4020
4021 UNGCPRO;
4022
4023 if (ii < starting || (ii < ending && !NILP (end)))
4024 {
4025 check_sequence_range (sequence, start, end, Flength (sequence));
4026 }
4027
4028 if (0 != deleted)
4029 {
4030 sequence = make_string (staging, staging_cursor - staging);
4031 }
4032 }
4033 else
4034 {
4035 Elemcount deleted = 0;
4036 Ibyte *staging = alloca_ibytes ((len = string_char_length (sequence))
4037 * MAX_ICHAR_LEN);
4038 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence);
4039 Ibyte *endp = startp + XSTRING_LENGTH (sequence);
4040 struct Lisp_Bit_Vector *deleting
4041 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4042 + (sizeof (long)
4043 * (BIT_VECTOR_LONG_STORAGE (len)
4044 - 1)));
4045
4046 check_sequence_range (sequence, start, end, make_integer (len));
4047
4048 /* For the from_end t case; transform contents to an array with
4049 elements addressable in constant time, use the same algorithm
4050 as for vectors. */
4051 deleting->size = len;
4052 memset (&(deleting->bits), 0,
4053 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
4054
4055 while (startp < endp)
4056 {
4057 itext_copy_ichar (startp, staging + (ii * MAX_ICHAR_LEN));
4058 INC_IBYTEPTR (startp);
4059 ii++;
4060 }
4061
4062 GCPRO1 (elt);
4063
4064 ending = min (ending, len);
4065
4066 for (ii = ending - 1; ii >= starting; ii--)
4067 {
4068 elt = KEY (key, make_char (itext_ichar (staging +
4069 (ii * MAX_ICHAR_LEN))));
4070 for (jj = ii - 1; jj >= starting; jj--)
4071 {
4072 if (check_test (test, key, elt,
4073 make_char (itext_ichar
4074 (staging + (jj * MAX_ICHAR_LEN))))
4075 == test_not_unboundp)
4076 {
4077 set_bit_vector_bit (deleting, ii, 1);
4078 deleted++;
4079 break;
4080 }
4081 }
4082 }
4083
4084 UNGCPRO;
4085
4086 if (0 != deleted)
4087 {
4088 startp = XSTRING_DATA (sequence);
4089
4090 for (ii = 0; ii < len; ii++)
4091 {
4092 if (!bit_vector_bit (deleting, ii))
4093 {
4094 staging_cursor
4095 += itext_copy_ichar (startp, staging_cursor);
4096 }
4097
4098 INC_IBYTEPTR (startp);
4099 }
4100
4101 sequence = make_string (staging, staging_cursor - staging);
4102 }
4103 }
4104 }
4105 else if (VECTORP (sequence))
4106 {
4107 Elemcount deleted = 0;
4108 Lisp_Object *content = XVECTOR_DATA (sequence);
4109 struct Lisp_Bit_Vector *deleting;
4110 Lisp_Object elt = Qnil;
4111
4112 len = XVECTOR_LENGTH (sequence);
4113 check_sequence_range (sequence, start, end, make_integer (len));
4114
4115 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4116 + (sizeof (long)
4117 * (BIT_VECTOR_LONG_STORAGE (len)
4118 - 1)));
4119 deleting->size = len;
4120 memset (&(deleting->bits), 0,
4121 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
4122
4123 GCPRO1 (elt);
4124
4125 ending = min (ending, len);
4126
4127 if (NILP (from_end))
4128 {
4129 for (ii = starting; ii < ending; ii++)
4130 {
4131 elt = KEY (key, content[ii]);
4132
4133 for (jj = ii + 1; jj < ending; jj++)
4134 {
4135 if (check_test (test, key, elt, content[jj])
4136 == test_not_unboundp)
4137 {
4138 set_bit_vector_bit (deleting, ii, 1);
4139 deleted++;
4140 break;
4141 }
4142 }
4143 }
4144 }
4145 else
4146 {
4147 for (ii = ending - 1; ii >= starting; ii--)
4148 {
4149 elt = KEY (key, content[ii]);
4150
4151 for (jj = ii - 1; jj >= starting; jj--)
4152 {
4153 if (check_test (test, key, elt, content[jj])
4154 == test_not_unboundp)
4155 {
4156 set_bit_vector_bit (deleting, ii, 1);
4157 deleted++;
4158 break;
4159 }
4160 }
4161 }
4162 }
4163
4164 UNGCPRO;
4165
4166 if (deleted)
4167 {
4168 Lisp_Object res = make_vector (len - deleted, Qnil),
4169 *res_content = XVECTOR_DATA (res);
4170
4171 for (ii = jj = 0; ii < len; ii++)
4172 {
4173 if (!bit_vector_bit (deleting, ii))
4174 {
4175 res_content[jj++] = content[ii];
4176 }
4177 }
4178
4179 sequence = res;
4180 }
4181 }
4182 else if (BIT_VECTORP (sequence))
4183 {
4184 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
4185 Elemcount deleted = 0;
4186 /* I'm a little irritated at this. Basically, the only reasonable
4187 thing delete-duplicates should do if handed a bit vector is return
4188 something of maximum length two and minimum length 0 (because
4189 that's the possible number of distinct elements if EQ is regarded
4190 as identity, which it should be). But to support arbitrary TEST
4191 and KEY arguments, which may be non-deterministic from our
4192 perspective, we need the same algorithm as for vectors. */
4193 struct Lisp_Bit_Vector *deleting;
4194 Lisp_Object elt = Qnil;
4195
4196 len = bit_vector_length (bv);
4197
4198 if (EQ (Qidentity, key))
4199 {
4200 /* We know all the elements will be bits; set check_test to
4201 reflect that. This isn't useful if KEY is not #'identity, since
4202 it may return non-bits for the elements. */
4203 check_test = get_check_test_function (Qzero, &test, test_not,
4204 Qnil, Qnil, key,
4205 &test_not_unboundp);
4206 }
4207
4208 check_sequence_range (sequence, start, end, make_integer (len));
4209
4210 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector)
4211 + (sizeof (long)
4212 * (BIT_VECTOR_LONG_STORAGE (len)
4213 - 1)));
4214 deleting->size = len;
4215 memset (&(deleting->bits), 0,
4216 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len));
4217
4218 ending = min (ending, len);
4219
4220 GCPRO1 (elt);
4221
4222 if (NILP (from_end))
4223 {
4224 for (ii = starting; ii < ending; ii++)
4225 {
4226 elt = KEY (key, make_fixnum (bit_vector_bit (bv, ii)));
4227
4228 for (jj = ii + 1; jj < ending; jj++)
4229 {
4230 if (check_test (test, key, elt,
4231 make_fixnum (bit_vector_bit (bv, jj)))
4232 == test_not_unboundp)
4233 {
4234 set_bit_vector_bit (deleting, ii, 1);
4235 deleted++;
4236 break;
4237 }
4238 }
4239 }
4240 }
4241 else
4242 {
4243 for (ii = ending - 1; ii >= starting; ii--)
4244 {
4245 elt = KEY (key, make_fixnum (bit_vector_bit (bv, ii)));
4246
4247 for (jj = ii - 1; jj >= starting; jj--)
4248 {
4249 if (check_test (test, key, elt,
4250 make_fixnum (bit_vector_bit (bv, jj)))
4251 == test_not_unboundp)
4252 {
4253 set_bit_vector_bit (deleting, ii, 1);
4254 deleted++;
4255 break;
4256 }
4257 }
4258 }
4259 }
4260
4261 UNGCPRO;
4262
4263 if (deleted)
4264 {
4265 Lisp_Object res = make_bit_vector (len - deleted, Qzero);
4266 Lisp_Bit_Vector *resbv = XBIT_VECTOR (res);
4267
4268 for (ii = jj = 0; ii < len; ii++)
4269 {
4270 if (!bit_vector_bit (deleting, ii))
4271 {
4272 set_bit_vector_bit (resbv, jj++, bit_vector_bit (bv, ii));
4273 }
4274 }
4275
4276 sequence = res;
4277 }
4278 }
4279
4280 return sequence;
4281 }
4282
4283 DEFUN ("remove-duplicates", Fremove_duplicates, 1, MANY, 0, /*
4284 Remove duplicate elements from SEQUENCE, non-destructively.
4285
4286 If there are no duplicate elements in SEQUENCE, return it unmodified;
4287 otherwise, return a new object. If SEQUENCE is a list, the new object may
4288 share list structure with SEQUENCE.
4289
4290 See `remove*' for the meaning of the keywords.
4291
4292 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT)
4293 */
4294 (int nargs, Lisp_Object *args))
4295 {
4296 Lisp_Object sequence = args[0], keyed, positioned = Qnil;
4297 Lisp_Object result = sequence, result_tail = result, cursor = Qnil;
4298 Lisp_Object cons_with_shared_tail = Qnil;
4299 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, ii = 0;
4300 Boolint test_not_unboundp = 1;
4301 check_test_func_t check_test = NULL;
4302 struct gcpro gcpro1, gcpro2;
4303
4304 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6,
4305 (test, key, test_not, start, end, from_end),
4306 (start = Qzero));
4307
4308 CHECK_SEQUENCE (sequence);
4309
4310 if (!CONSP (sequence))
4311 {
4312 return Fdelete_duplicates (nargs, args);
4313 }
4314
4315 CHECK_NATNUM (start);
4316 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
4317
4318 if (!NILP (end))
4319 {
4320 CHECK_NATNUM (end);
4321 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
4322 }
4323
4324 if (NILP (key))
4325 {
4326 key = Qidentity;
4327 }
4328
4329 get_check_match_function (&test, test_not, Qnil, Qnil, key,
4330 &test_not_unboundp, &check_test);
4331
4332 if (NILP (from_end))
4333 {
4334 Lisp_Object ignore = Qnil;
4335
4336 GCPRO2 (keyed, result);
4337
4338 {
4339 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4340 {
4341 if (starting <= ii && ii <= ending)
4342 {
4343 keyed = KEY (key, elt);
4344 positioned
4345 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4346 check_test, test_not_unboundp,
4347 test, key, 0,
4348 make_fixnum (max (starting
4349 - (ii + 1), 0)),
4350 make_fixnum (ending - (ii + 1)));
4351 if (!NILP (positioned))
4352 {
4353 sequence = result = result_tail = XCDR (tail);
4354 }
4355 else
4356 {
4357 break;
4358 }
4359 }
4360 else
4361 {
4362 break;
4363 }
4364
4365 ii++;
4366 }
4367 END_GC_EXTERNAL_LIST_LOOP (elt);
4368 }
4369
4370 {
4371 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
4372 {
4373 if (!(starting <= ii && ii <= ending))
4374 {
4375 ii++;
4376 continue;
4377 }
4378
4379 /* For this algorithm, each time we encounter an object to be
4380 removed, copy the output list from the tail beyond the last
4381 removed cons to this one. Otherwise, the tail of the output list
4382 is shared with the input list, which is OK. */
4383
4384 keyed = KEY (key, elt);
4385 positioned
4386 = list_position_cons_before (&ignore, keyed, XCDR (tail),
4387 check_test, test_not_unboundp,
4388 test, key, 0,
4389 make_fixnum (max (starting - (ii + 1),
4390 0)),
4391 make_fixnum (ending - (ii + 1)));
4392 if (!NILP (positioned))
4393 {
4394 if (EQ (result, sequence))
4395 {
4396 result = cons_with_shared_tail
4397 = Fcons (XCAR (sequence), XCDR (sequence));
4398 }
4399
4400 result_tail = cons_with_shared_tail;
4401 cursor = XCDR (cons_with_shared_tail);
4402
4403 while (!EQ (cursor, tail) && !NILP (cursor))
4404 {
4405 XSETCDR (result_tail, Fcons (XCAR (cursor), Qnil));
4406 result_tail = XCDR (result_tail);
4407 cursor = XCDR (cursor);
4408 }
4409
4410 XSETCDR (result_tail, XCDR (tail));
4411 cons_with_shared_tail = result_tail;
4412 }
4413
4414 ii++;
4415 }
4416 END_GC_EXTERNAL_LIST_LOOP (elt);
4417 }
4418
4419 UNGCPRO;
4420
4421 if ((ii < starting || (ii < ending && !NILP (end))))
4422 {
4423 check_sequence_range (args[0], start, end, Flength (args[0]));
4424 }
4425 }
4426 else
4427 {
4428 result = list_delete_duplicates_from_end (sequence, check_test,
4429 test_not_unboundp, test, key,
4430 start, end, 1);
4431 }
4432
4433 return result;
4434 }
4435 #undef KEY
4436
4437 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /*
4438 Reverse SEQUENCE, destructively.
4439
4440 Return the beginning of the reversed sequence, which will be a distinct Lisp
4441 object if SEQUENCE is a list with length greater than one. See also
4442 `reverse', the non-destructive version of this function.
4443 */
4444 (sequence))
4445 {
4446 CHECK_SEQUENCE (sequence);
4447
4448 if (CONSP (sequence))
4449 {
4450 struct gcpro gcpro1, gcpro2;
4451 Lisp_Object prev = Qnil;
4452 Lisp_Object tail = sequence;
4453
4454 /* We gcpro our args; see `nconc' */
4455 GCPRO2 (prev, tail);
4456 while (!NILP (tail))
4457 {
4458 REGISTER Lisp_Object next;
4459 CONCHECK_CONS (tail);
4460 next = XCDR (tail);
4461 XCDR (tail) = prev;
4462 prev = tail;
4463 tail = next;
4464 }
4465 UNGCPRO;
4466 return prev;
4467 }
4468 else if (VECTORP (sequence))
4469 {
4470 Elemcount length = XVECTOR_LENGTH (sequence), ii = length;
4471 Elemcount half = length / 2;
4472 Lisp_Object swap = Qnil;
4473 CHECK_LISP_WRITEABLE (sequence);
4474
4475 while (ii > half)
4476 {
4477 swap = XVECTOR_DATA (sequence) [length - ii];
4478 XVECTOR_DATA (sequence) [length - ii]
4479 = XVECTOR_DATA (sequence) [ii - 1];
4480 XVECTOR_DATA (sequence) [ii - 1] = swap;
4481 --ii;
4482 }
4483 }
4484 else if (STRINGP (sequence))
4485 {
4486 Elemcount length = XSTRING_LENGTH (sequence);
4487 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length;
4488 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length;
4489
4490 CHECK_LISP_WRITEABLE (sequence);
4491 while (cursor < endp)
4492 {
4493 staging_end -= itext_ichar_len (cursor);
4494 itext_copy_ichar (cursor, staging_end);
4495 INC_IBYTEPTR (cursor);
4496 }
4497
4498 assert (staging == staging_end);
4499
4500 memcpy (XSTRING_DATA (sequence), staging, length);
4501 init_string_ascii_begin (sequence);
4502 bump_string_modiff (sequence);
4503 sledgehammer_check_ascii_begin (sequence);
4504 }
4505 else if (BIT_VECTORP (sequence))
4506 {
4507 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
4508 Elemcount length = bit_vector_length (bv), ii = length;
4509 Elemcount half = length / 2;
4510 int swap = 0;
4511
4512 CHECK_LISP_WRITEABLE (sequence);
4513 while (ii > half)
4514 {
4515 swap = bit_vector_bit (bv, length - ii);
4516 set_bit_vector_bit (bv, length - ii, bit_vector_bit (bv, ii - 1));
4517 set_bit_vector_bit (bv, ii - 1, swap);
4518 --ii;
4519 }
4520 }
4521 else
4522 {
4523 assert (NILP (sequence));
4524 }
4525
4526 return sequence;
4527 }
4528
4529 DEFUN ("reverse", Freverse, 1, 1, 0, /*
4530 Reverse SEQUENCE, copying. Return the reversed sequence.
4531 See also the function `nreverse', which is used more often.
4532 */
4533 (sequence))
4534 {
4535 Lisp_Object result = Qnil;
4536
4537 CHECK_SEQUENCE (sequence);
4538
4539 if (CONSP (sequence))
4540 {
4541 EXTERNAL_LIST_LOOP_2 (elt, sequence)
4542 {
4543 result = Fcons (elt, result);
4544 }
4545 }
4546 else if (VECTORP (sequence))
4547 {
4548 Elemcount length = XVECTOR_LENGTH (sequence), ii = length;
4549 Lisp_Object *staging = alloca_array (Lisp_Object, length);
4550
4551 while (ii > 0)
4552 {
4553 staging[length - ii] = XVECTOR_DATA (sequence) [ii - 1];
4554 --ii;
4555 }
4556
4557 result = Fvector (length, staging);
4558 }
4559 else if (STRINGP (sequence))
4560 {
4561 Elemcount length = XSTRING_LENGTH (sequence);
4562 Ibyte *staging = alloca_ibytes (length), *staging_end = staging + length;
4563 Ibyte *cursor = XSTRING_DATA (sequence), *endp = cursor + length;
4564
4565 while (cursor < endp)
4566 {
4567 staging_end -= itext_ichar_len (cursor);
4568 itext_copy_ichar (cursor, staging_end);
4569 INC_IBYTEPTR (cursor);
4570 }
4571
4572 assert (staging == staging_end);
4573
4574 result = make_string (staging, length);
4575 }
4576 else if (BIT_VECTORP (sequence))
4577 {
4578 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence), *res;
4579 Elemcount length = bit_vector_length (bv), ii = length;
4580
4581 result = make_bit_vector (length, Qzero);
4582 res = XBIT_VECTOR (result);
4583
4584 while (ii > 0)
4585 {
4586 set_bit_vector_bit (res, length - ii, bit_vector_bit (bv, ii - 1));
4587 --ii;
4588 }
4589 }
4590 else
4591 {
4592 assert (NILP (sequence));
4593 }
4594
4595 return result;
4596 }
4597
4598 Lisp_Object
4599 list_merge (Lisp_Object org_l1, Lisp_Object org_l2,
4600 check_test_func_t check_merge,
4601 Lisp_Object predicate, Lisp_Object key)
4602 {
4603 Lisp_Object value;
4604 Lisp_Object tail;
4605 Lisp_Object tem;
4606 Lisp_Object l1, l2;
4607 Lisp_Object tortoises[2];
4608 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4609 int l1_count = 0, l2_count = 0;
4610
4611 l1 = org_l1;
4612 l2 = org_l2;
4613 tail = Qnil;
4614 value = Qnil;
4615 tortoises[0] = org_l1;
4616 tortoises[1] = org_l2;
4617
4618 /* It is sufficient to protect org_l1 and org_l2. When l1 and l2 are
4619 updated, we copy the new values back into the org_ vars. */
4620
4621 GCPRO5 (org_l1, org_l2, predicate, value, tortoises[0]);
4622 gcpro5.nvars = 2;
4623
4624 while (1)
4625 {
4626 if (NILP (l1))
4627 {
4628 UNGCPRO;
4629 if (NILP (tail))
4630 return l2;
4631 Fsetcdr (tail, l2);
4632 return value;
4633 }
4634 if (NILP (l2))
4635 {
4636 UNGCPRO;
4637 if (NILP (tail))
4638 return l1;
4639 Fsetcdr (tail, l1);
4640 return value;
4641 }
4642
4643 if (check_merge (predicate, key, Fcar (l2), Fcar (l1)) == 0)
4644 {
4645 tem = l1;
4646 l1 = Fcdr (l1);
4647 org_l1 = l1;
4648
4649 if (l1_count++ > CIRCULAR_LIST_SUSPICION_LENGTH)
4650 {
4651 if (l1_count & 1)
4652 {
4653 if (!CONSP (tortoises[0]))
4654 {
4655 mapping_interaction_error (Qmerge, tortoises[0]);
4656 }
4657
4658 tortoises[0] = XCDR (tortoises[0]);
4659 }
4660
4661 if (EQ (org_l1, tortoises[0]))
4662 {
4663 signal_circular_list_error (org_l1);
4664 }
4665 }
4666 }
4667 else
4668 {
4669 tem = l2;
4670 l2 = Fcdr (l2);
4671 org_l2 = l2;
4672
4673 if (l2_count++ > CIRCULAR_LIST_SUSPICION_LENGTH)
4674 {
4675 if (l2_count & 1)
4676 {
4677 if (!CONSP (tortoises[1]))
4678 {
4679 mapping_interaction_error (Qmerge, tortoises[1]);
4680 }
4681
4682 tortoises[1] = XCDR (tortoises[1]);
4683 }
4684
4685 if (EQ (org_l2, tortoises[1]))
4686 {
4687 signal_circular_list_error (org_l2);
4688 }
4689 }
4690 }
4691
4692 if (NILP (tail))
4693 value = tem;
4694 else
4695 Fsetcdr (tail, tem);
4696
4697 tail = tem;
4698 }
4699 }
4700
4701 static void
4702 array_merge (Lisp_Object *dest, Elemcount dest_len,
4703 Lisp_Object *front, Elemcount front_len,
4704 Lisp_Object *back, Elemcount back_len,
4705 check_test_func_t check_merge,
4706 Lisp_Object predicate, Lisp_Object key)
4707 {
4708 Elemcount ii, fronting, backing;
4709 Lisp_Object *front_staging = front;
4710 Lisp_Object *back_staging = back;
4711 struct gcpro gcpro1, gcpro2;
4712
4713 assert (dest_len == (back_len + front_len));
4714
4715 if (0 == dest_len)
4716 {
4717 return;
4718 }
4719
4720 if (front >= dest && front < (dest + dest_len))
4721 {
4722 front_staging = alloca_array (Lisp_Object, front_len);
4723
4724 for (ii = 0; ii < front_len; ++ii)
4725 {
4726 front_staging[ii] = front[ii];
4727 }
4728 }
4729
4730 if (back >= dest && back < (dest + dest_len))
4731 {
4732 back_staging = alloca_array (Lisp_Object, back_len);
4733
4734 for (ii = 0; ii < back_len; ++ii)
4735 {
4736 back_staging[ii] = back[ii];
4737 }
4738 }
4739
4740 GCPRO2 (front_staging[0], back_staging[0]);
4741 gcpro1.nvars = front_len;
4742 gcpro2.nvars = back_len;
4743
4744 for (ii = fronting = backing = 0; ii < dest_len; ++ii)
4745 {
4746 if (fronting >= front_len)
4747 {
4748 while (ii < dest_len)
4749 {
4750 dest[ii] = back_staging[backing];
4751 ++ii, ++backing;
4752 }
4753 UNGCPRO;
4754 return;
4755 }
4756
4757 if (backing >= back_len)
4758 {
4759 while (ii < dest_len)
4760 {
4761 dest[ii] = front_staging[fronting];
4762 ++ii, ++fronting;
4763 }
4764 UNGCPRO;
4765 return;
4766 }
4767
4768 if (check_merge (predicate, key, back_staging[backing],
4769 front_staging[fronting]) == 0)
4770 {
4771 dest[ii] = front_staging[fronting];
4772 ++fronting;
4773 }
4774 else
4775 {
4776 dest[ii] = back_staging[backing];
4777 ++backing;
4778 }
4779 }
4780
4781 UNGCPRO;
4782 }
4783
4784 static Lisp_Object
4785 list_array_merge_into_list (Lisp_Object list,
4786 Lisp_Object *array, Elemcount array_len,
4787 check_test_func_t check_merge,
4788 Lisp_Object predicate, Lisp_Object key,
4789 Boolint reverse_order)
4790 {
4791 Lisp_Object tail = Qnil, value = Qnil, tortoise = list;
4792 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4793 Elemcount array_index = 0;
4794 int looped = 0;
4795
4796 GCPRO4 (list, tail, value, tortoise);
4797
4798 while (1)
4799 {
4800 if (NILP (list))
4801 {
4802 UNGCPRO;
4803
4804 if (NILP (tail))
4805 {
4806 return Flist (array_len, array);
4807 }
4808
4809 Fsetcdr (tail, Flist (array_len - array_index, array + array_index));
4810 return value;
4811 }
4812
4813 if (array_index >= array_len)
4814 {
4815 UNGCPRO;
4816 if (NILP (tail))
4817 {
4818 return list;
4819 }
4820
4821 Fsetcdr (tail, list);
4822 return value;
4823 }
4824
4825
4826 if (reverse_order ?
4827 check_merge (predicate, key, Fcar (list), array [array_index])
4828 : !check_merge (predicate, key, array [array_index], Fcar (list)))
4829 {
4830 if (NILP (tail))
4831 {
4832 value = tail = list;
4833 }
4834 else
4835 {
4836 Fsetcdr (tail, list);
4837 tail = XCDR (tail);
4838 }
4839
4840 list = Fcdr (list);
4841 }
4842 else
4843 {
4844 if (NILP (tail))
4845 {
4846 value = tail = Fcons (array [array_index], Qnil);
4847 }
4848 else
4849 {
4850 Fsetcdr (tail, Fcons (array [array_index], tail));
4851 tail = XCDR (tail);
4852 }
4853 ++array_index;
4854 }
4855
4856 if (++looped > CIRCULAR_LIST_SUSPICION_LENGTH)
4857 {
4858 if (looped & 1)
4859 {
4860 tortoise = XCDR (tortoise);
4861 }
4862
4863 if (EQ (list, tortoise))
4864 {
4865 signal_circular_list_error (list);
4866 }
4867 }
4868 }
4869 }
4870
4871 static void
4872 list_list_merge_into_array (Lisp_Object *output, Elemcount output_len,
4873 Lisp_Object list_one, Lisp_Object list_two,
4874 check_test_func_t check_merge,
4875 Lisp_Object predicate, Lisp_Object key)
4876 {
4877 Elemcount output_index = 0;
4878
4879 while (output_index < output_len)
4880 {
4881 if (NILP (list_one))
4882 {
4883 while (output_index < output_len)
4884 {
4885 output [output_index] = Fcar (list_two);
4886 list_two = Fcdr (list_two), ++output_index;
4887 }
4888 return;
4889 }
4890
4891 if (NILP (list_two))
4892 {
4893 while (output_index < output_len)
4894 {
4895 output [output_index] = Fcar (list_one);
4896 list_one = Fcdr (list_one), ++output_index;
4897 }
4898 return;
4899 }
4900
4901 if (check_merge (predicate, key, Fcar (list_two), Fcar (list_one))
4902 == 0)
4903 {
4904 output [output_index] = XCAR (list_one);
4905 list_one = XCDR (list_one);
4906 }
4907 else
4908 {
4909 output [output_index] = XCAR (list_two);
4910 list_two = XCDR (list_two);
4911 }
4912
4913 ++output_index;
4914
4915 /* No need to check for circularity. */
4916 }
4917 }
4918
4919 static void
4920 list_array_merge_into_array (Lisp_Object *output, Elemcount output_len,
4921 Lisp_Object list,
4922 Lisp_Object *array, Elemcount array_len,
4923 check_test_func_t check_merge,
4924 Lisp_Object predicate, Lisp_Object key,
4925 Boolint reverse_order)
4926 {
4927 Elemcount output_index = 0, array_index = 0;
4928
4929 while (output_index < output_len)
4930 {
4931 if (NILP (list))
4932 {
4933 if (array_len - array_index != output_len - output_index)
4934 {
4935 mapping_interaction_error (Qmerge, list);
4936 }
4937
4938 while (array_index < array_len)
4939 {
4940 output [output_index++] = array [array_index++];
4941 }
4942
4943 return;
4944 }
4945
4946 if (array_index >= array_len)
4947 {
4948 while (output_index < output_len)
4949 {
4950 output [output_index++] = Fcar (list);
4951 list = Fcdr (list);
4952 }
4953
4954 return;
4955 }
4956
4957 if (reverse_order ?
4958 check_merge (predicate, key, Fcar (list), array [array_index]) :
4959 !check_merge (predicate, key, array [array_index], Fcar (list)))
4960 {
4961 output [output_index] = XCAR (list);
4962 list = XCDR (list);
4963 }
4964 else
4965 {
4966 output [output_index] = array [array_index];
4967 ++array_index;
4968 }
4969
4970 ++output_index;
4971 }
4972 }
4973
4974 #define STRING_DATA_TO_OBJECT_ARRAY(strdata, c_array, counter, len) \
4975 do { \
4976 c_array = alloca_array (Lisp_Object, len); \
4977 for (counter = 0; counter < len; ++counter) \
4978 { \
4979 c_array[counter] = make_char (itext_ichar (strdata)); \
4980 INC_IBYTEPTR (strdata); \
4981 } \
4982 } while (0)
4983
4984 #define BIT_VECTOR_TO_OBJECT_ARRAY(v, c_array, counter, len) do { \
4985 c_array = alloca_array (Lisp_Object, len); \
4986 for (counter = 0; counter < len; ++counter) \
4987 { \
4988 c_array[counter] = make_fixnum (bit_vector_bit (v, counter)); \
4989 } \
4990 } while (0)
4991
4992 DEFUN ("merge", Fmerge, 4, MANY, 0, /*
4993 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence.
4994
4995 TYPE is the type of sequence to return. PREDICATE is a `less-than'
4996 predicate on the elements.
4997
4998 Optional keyword argument KEY is a function used to extract an object to be
4999 used for comparison from each element of SEQUENCE-ONE and SEQUENCE-TWO.
5000
5001 arguments: (TYPE SEQUENCE-ONE SEQUENCE-TWO PREDICATE &key (KEY #'IDENTITY))
5002 */
5003 (int nargs, Lisp_Object *args))
5004 {
5005 Lisp_Object type = args[0], sequence_one = args[1], sequence_two = args[2],
5006 predicate = args[3], result = Qnil;
5007 check_test_func_t check_merge = NULL;
5008
5009 PARSE_KEYWORDS (Fmerge, nargs, args, 1, (key), NULL);
5010
5011 CHECK_SEQUENCE (sequence_one);
5012 CHECK_SEQUENCE (sequence_two);
5013
5014 CHECK_KEY_ARGUMENT (key);
5015
5016 check_merge = get_merge_predicate (predicate, key);
5017
5018 if (EQ (type, Qlist) && (LISTP (sequence_one) || LISTP (sequence_two)))
5019 {
5020 if (NILP (sequence_two))
5021 {
5022 result = Fappend (2, args + 1);
5023 }
5024 else if (NILP (sequence_one))
5025 {
5026 args[3] = Qnil; /* Overwriting PREDICATE, and losing its GC
5027 protection, but that doesn't matter. */
5028 result = Fappend (2, args + 2);
5029 }
5030 else if (CONSP (sequence_one) && CONSP (sequence_two))
5031 {
5032 result = list_merge (sequence_one, sequence_two, check_merge,
5033 predicate, key);
5034 }
5035 else
5036 {
5037 Lisp_Object *array_storage, swap;
5038 Elemcount array_length, i;
5039 Boolint reverse_order = 0;
5040
5041 if (!CONSP (sequence_one))
5042 {
5043 /* Make sequence_one the cons, sequence_two the array: */
5044 swap = sequence_one;
5045 sequence_one = sequence_two;
5046 sequence_two = swap;
5047 reverse_order = 1;
5048 }
5049
5050 if (VECTORP (sequence_two))
5051 {
5052 array_storage = XVECTOR_DATA (sequence_two);
5053 array_length = XVECTOR_LENGTH (sequence_two);
5054 }
5055 else if (STRINGP (sequence_two))
5056 {
5057 Ibyte *strdata = XSTRING_DATA (sequence_two);
5058 array_length = string_char_length (sequence_two);
5059 /* No need to GCPRO, characters are immediate. */
5060 STRING_DATA_TO_OBJECT_ARRAY (strdata, array_storage, i,
5061 array_length);
5062
5063 }
5064 else
5065 {
5066 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence_two);
5067 array_length = bit_vector_length (v);
5068 /* No need to GCPRO, fixnums are immediate. */
5069 BIT_VECTOR_TO_OBJECT_ARRAY (v, array_storage, i, array_length);
5070 }
5071
5072 result = list_array_merge_into_list (sequence_one,
5073 array_storage, array_length,
5074 check_merge, predicate, key,
5075 reverse_order);
5076 }
5077 }
5078 else
5079 {
5080 Elemcount sequence_one_len = XFIXNUM (Flength (sequence_one)),
5081 sequence_two_len = XFIXNUM (Flength (sequence_two)), i;
5082 Elemcount output_len = 1 + sequence_one_len + sequence_two_len;
5083 Lisp_Object *output = alloca_array (Lisp_Object, output_len),
5084 *sequence_one_storage = NULL, *sequence_two_storage = NULL;
5085 Boolint do_coerce = !(EQ (type, Qvector) || EQ (type, Qstring)
5086 || EQ (type, Qbit_vector) || EQ (type, Qlist));
5087 Ibyte *strdata = NULL;
5088 Lisp_Bit_Vector *v = NULL;
5089 struct gcpro gcpro1;
5090
5091 output[0] = do_coerce ? Qlist : type;
5092 for (i = 1; i < output_len; ++i)
5093 {
5094 output[i] = Qnil;
5095 }
5096
5097 GCPRO1 (output[0]);
5098 gcpro1.nvars = output_len;
5099
5100 if (VECTORP (sequence_one))
5101 {
5102 sequence_one_storage = XVECTOR_DATA (sequence_one);
5103 }
5104 else if (STRINGP (sequence_one))
5105 {
5106 strdata = XSTRING_DATA (sequence_one);
5107 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_one_storage,
5108 i, sequence_one_len);
5109 }
5110 else if (BIT_VECTORP (sequence_one))
5111 {
5112 v = XBIT_VECTOR (sequence_one);
5113 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_one_storage,
5114 i, sequence_one_len);
5115 }
5116
5117 if (VECTORP (sequence_two))
5118 {
5119 sequence_two_storage = XVECTOR_DATA (sequence_two);
5120 }
5121 else if (STRINGP (sequence_two))
5122 {
5123 strdata = XSTRING_DATA (sequence_two);
5124 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_two_storage,
5125 i, sequence_two_len);
5126 }
5127 else if (BIT_VECTORP (sequence_two))
5128 {
5129 v = XBIT_VECTOR (sequence_two);
5130 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_two_storage,
5131 i, sequence_two_len);
5132 }
5133
5134 if (LISTP (sequence_one) && LISTP (sequence_two))
5135 {
5136 list_list_merge_into_array (output + 1, output_len - 1,
5137 sequence_one, sequence_two,
5138 check_merge, predicate, key);
5139 }
5140 else if (LISTP (sequence_one))
5141 {
5142 list_array_merge_into_array (output + 1, output_len - 1,
5143 sequence_one,
5144 sequence_two_storage,
5145 sequence_two_len,
5146 check_merge, predicate, key, 0);
5147 }
5148 else if (LISTP (sequence_two))
5149 {
5150 list_array_merge_into_array (output + 1, output_len - 1,
5151 sequence_two,
5152 sequence_one_storage,
5153 sequence_one_len,
5154 check_merge, predicate, key, 1);
5155 }
5156 else
5157 {
5158 array_merge (output + 1, output_len - 1,
5159 sequence_one_storage, sequence_one_len,
5160 sequence_two_storage, sequence_two_len,
5161 check_merge, predicate,
5162 key);
5163 }
5164
5165 result = Ffuncall (output_len, output);
5166
5167 if (do_coerce)
5168 {
5169 result = call2 (Qcoerce, result, type);
5170 }
5171
5172 UNGCPRO;
5173 }
5174
5175 return result;
5176 }
5177
5178 Lisp_Object
5179 list_sort (Lisp_Object list, check_test_func_t check_merge,
5180 Lisp_Object predicate, Lisp_Object key)
5181 {
5182 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
5183 Lisp_Object back, tem;
5184 Lisp_Object front = list;
5185 Lisp_Object len = Flength (list);
5186
5187 if (XFIXNUM (len) < 2)
5188 return list;
5189
5190 len = make_fixnum (XFIXNUM (len) / 2 - 1);
5191 tem = Fnthcdr (len, list);
5192 back = Fcdr (tem);
5193 Fsetcdr (tem, Qnil);
5194
5195 GCPRO4 (front, back, predicate, key);
5196 front = list_sort (front, check_merge, predicate, key);
5197 back = list_sort (back, check_merge, predicate, key);
5198
5199 RETURN_UNGCPRO (list_merge (front, back, check_merge, predicate, key));
5200 }
5201
5202 static void
5203 array_sort (Lisp_Object *array, Elemcount array_len,
5204 check_test_func_t check_merge,
5205 Lisp_Object predicate, Lisp_Object key)
5206 {
5207 Elemcount split;
5208
5209 if (array_len < 2)
5210 return;
5211
5212 split = array_len / 2;
5213
5214 array_sort (array, split, check_merge, predicate, key);
5215 array_sort (array + split, array_len - split, check_merge, predicate,
5216 key);
5217 array_merge (array, array_len, array, split, array + split,
5218 array_len - split, check_merge, predicate, key);
5219 }
5220
5221 DEFUN ("sort*", FsortX, 2, MANY, 0, /*
5222 Sort SEQUENCE, comparing elements using PREDICATE.
5223 Returns the sorted sequence. SEQUENCE is modified by side effect.
5224
5225 PREDICATE is called with two elements of SEQUENCE, and should return t if
5226 the first element is `less' than the second.
5227
5228 Optional keyword argument KEY is a function used to extract an object to be
5229 used for comparison from each element of SEQUENCE.
5230
5231 In this implementation, sorting is always stable; but call `stable-sort' if
5232 this stability is important to you, other implementations may not make the
5233 same guarantees.
5234
5235 arguments: (SEQUENCE PREDICATE &key (KEY #'IDENTITY))
5236 */
5237 (int nargs, Lisp_Object *args))
5238 {
5239 Lisp_Object sequence = args[0], predicate = args[1];
5240 Lisp_Object *sequence_carray;
5241 check_test_func_t check_merge = NULL;
5242 Elemcount sequence_len, i;
5243
5244 PARSE_KEYWORDS (FsortX, nargs, args, 1, (key), NULL);
5245
5246 CHECK_SEQUENCE (sequence);
5247
5248 CHECK_KEY_ARGUMENT (key);
5249
5250 check_merge = get_merge_predicate (predicate, key);
5251
5252 if (LISTP (sequence))
5253 {
5254 sequence = list_sort (sequence, check_merge, predicate, key);
5255 }
5256 else if (VECTORP (sequence))
5257 {
5258 array_sort (XVECTOR_DATA (sequence), XVECTOR_LENGTH (sequence),
5259 check_merge, predicate, key);
5260 }
5261 else if (STRINGP (sequence))
5262 {
5263 Ibyte *strdata = XSTRING_DATA (sequence);
5264
5265 sequence_len = string_char_length (sequence);
5266
5267 STRING_DATA_TO_OBJECT_ARRAY (strdata, sequence_carray, i, sequence_len);
5268
5269 /* No GCPRO necessary, characters are immediate. */
5270 array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
5271
5272 strdata = XSTRING_DATA (sequence);
5273
5274 CHECK_LISP_WRITEABLE (sequence);
5275 for (i = 0; i < sequence_len; ++i)
5276 {
5277 strdata += set_itext_ichar (strdata, XCHAR (sequence_carray[i]));
5278 }
5279
5280 init_string_ascii_begin (sequence);
5281 bump_string_modiff (sequence);
5282 sledgehammer_check_ascii_begin (sequence);
5283 }
5284 else if (BIT_VECTORP (sequence))
5285 {
5286 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
5287 sequence_len = bit_vector_length (v);
5288
5289 BIT_VECTOR_TO_OBJECT_ARRAY (v, sequence_carray, i, sequence_len);
5290
5291 /* No GCPRO necessary, bits are immediate. */
5292 array_sort (sequence_carray, sequence_len, check_merge, predicate, key);
5293
5294 for (i = 0; i < sequence_len; ++i)
5295 {
5296 set_bit_vector_bit (v, i, XFIXNUM (sequence_carray [i]));
5297 }
5298 }
5299
5300 return sequence;
5301 }
5302 1167
5303 /************************************************************************/ 1168 /************************************************************************/
5304 /* property-list functions */ 1169 /* property-list functions */
5305 /************************************************************************/ 1170 /************************************************************************/
5306 1171
6424 return elt; 2289 return elt;
6425 } 2290 }
6426 return Qnil; 2291 return Qnil;
6427 } 2292 }
6428 2293
2294 DEFUN ("old-rassq", Fold_rassq, 2, 2, 0, /*
2295 Return non-nil if VALUE is `old-eq' to the cdr of an element of ALIST.
2296 The value is actually the element of ALIST whose cdr is VALUE.
2297 */
2298 (value, alist))
2299 {
2300 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist)
2301 {
2302 if (HACKEQ_UNSAFE (value, elt_cdr))
2303 return elt;
2304 }
2305 return Qnil;
2306 }
2307
6429 DEFUN ("old-rassoc", Fold_rassoc, 2, 2, 0, /* 2308 DEFUN ("old-rassoc", Fold_rassoc, 2, 2, 0, /*
6430 Return non-nil if VALUE is `old-equal' to the cdr of an element of ALIST. 2309 Return non-nil if VALUE is `old-equal' to the cdr of an element of ALIST.
6431 The value is actually the element of ALIST whose cdr equals VALUE. 2310 The value is actually the element of ALIST whose cdr equals VALUE.
6432 */ 2311 */
6433 (value, alist)) 2312 (value, alist))
6499 /* #### blasphemy */ 2378 /* #### blasphemy */
6500 return HACKEQ_UNSAFE (object1, object2) ? Qt : Qnil; 2379 return HACKEQ_UNSAFE (object1, object2) ? Qt : Qnil;
6501 } 2380 }
6502 2381
6503 #endif 2382 #endif
6504
6505
6506 static Lisp_Object replace_string_range_1 (Lisp_Object dest,
6507 Lisp_Object start,
6508 Lisp_Object end,
6509 const Ibyte *source,
6510 const Ibyte *source_limit,
6511 Lisp_Object item);
6512
6513 /* Fill the substring of DEST beginning at START and ending before END with
6514 the character ITEM. If DEST does not have sufficient space for END -
6515 START characters at START, write as many as is possible without changing
6516 the character length of DEST. Update the string modification flag and do
6517 any sledgehammer checks we have turned on.
6518
6519 START must be a Lisp integer. END can be nil, indicating the length of the
6520 string, or a Lisp integer. The condition (<= 0 START END (length DEST))
6521 must hold, or fill_string_range() will signal an error. */
6522 static Lisp_Object
6523 fill_string_range (Lisp_Object dest, Lisp_Object item, Lisp_Object start,
6524 Lisp_Object end)
6525 {
6526 return replace_string_range_1 (dest, start, end, NULL, NULL, item);
6527 }
6528
6529 DEFUN ("fill", Ffill, 2, MANY, 0, /*
6530 Destructively modify SEQUENCE by replacing each element with ITEM.
6531 SEQUENCE is a list, vector, bit vector, or string.
6532
6533 Optional keyword START is the index of the first element of SEQUENCE
6534 to be modified, and defaults to zero. Optional keyword END is the
6535 exclusive upper bound on the elements of SEQUENCE to be modified, and
6536 defaults to the length of SEQUENCE.
6537
6538 arguments: (SEQUENCE ITEM &key (START 0) (END (length SEQUENCE)))
6539 */
6540 (int nargs, Lisp_Object *args))
6541 {
6542 Lisp_Object sequence = args[0];
6543 Lisp_Object item = args[1];
6544 Elemcount starting, ending = MOST_POSITIVE_FIXNUM + 1, ii, len;
6545
6546 PARSE_KEYWORDS (Ffill, nargs, args, 2, (start, end), (start = Qzero));
6547
6548 CHECK_NATNUM (start);
6549 starting = BIGNUMP (start) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (start);
6550
6551 if (!NILP (end))
6552 {
6553 CHECK_NATNUM (end);
6554 ending = BIGNUMP (end) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (end);
6555 }
6556
6557 retry:
6558 if (STRINGP (sequence))
6559 {
6560 CHECK_CHAR_COERCE_INT (item);
6561 CHECK_LISP_WRITEABLE (sequence);
6562
6563 fill_string_range (sequence, item, start, end);
6564 }
6565 else if (VECTORP (sequence))
6566 {
6567 Lisp_Object *p = XVECTOR_DATA (sequence);
6568
6569 CHECK_LISP_WRITEABLE (sequence);
6570 len = XVECTOR_LENGTH (sequence);
6571
6572 check_sequence_range (sequence, start, end, make_fixnum (len));
6573 ending = min (ending, len);
6574
6575 for (ii = starting; ii < ending; ++ii)
6576 {
6577 p[ii] = item;
6578 }
6579 }
6580 else if (BIT_VECTORP (sequence))
6581 {
6582 Lisp_Bit_Vector *v = XBIT_VECTOR (sequence);
6583 int bit;
6584
6585 CHECK_BIT (item);
6586 bit = XFIXNUM (item);
6587 CHECK_LISP_WRITEABLE (sequence);
6588 len = bit_vector_length (v);
6589
6590 check_sequence_range (sequence, start, end, make_fixnum (len));
6591 ending = min (ending, len);
6592
6593 for (ii = starting; ii < ending; ++ii)
6594 {
6595 set_bit_vector_bit (v, ii, bit);
6596 }
6597 }
6598 else if (LISTP (sequence))
6599 {
6600 Elemcount counting = 0;
6601
6602 {
6603 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
6604 {
6605 if (counting >= starting)
6606 {
6607 if (counting < ending)
6608 {
6609 XSETCAR (tail, item);
6610 }
6611 else if (counting == ending)
6612 {
6613 break;
6614 }
6615 }
6616 ++counting;
6617 }
6618 }
6619
6620 if (counting < starting || (counting != ending && !NILP (end)))
6621 {
6622 check_sequence_range (args[0], start, end, Flength (args[0]));
6623 }
6624 }
6625 else
6626 {
6627 sequence = wrong_type_argument (Qsequencep, sequence);
6628 goto retry;
6629 }
6630 return sequence;
6631 }
6632 2383
6633 Lisp_Object 2384 Lisp_Object
6634 nconc2 (Lisp_Object arg1, Lisp_Object arg2) 2385 nconc2 (Lisp_Object arg1, Lisp_Object arg2)
6635 { 2386 {
6636 Lisp_Object args[2]; 2387 Lisp_Object args[2];
6763 } 2514 }
6764 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */ 2515 RETURN_UNGCPRO (Qnil); /* No non-nil args provided. */
6765 } 2516 }
6766 2517
6767 2518
6768 /* Replace the substring of DEST beginning at START and ending before END
6769 with the text at SOURCE, which is END - START characters long and
6770 SOURCE_LIMIT - SOURCE octets long. If DEST does not have sufficient
6771 space for END - START characters at START, write as many as is possible
6772 without changing the length of DEST. Update the string modification flag
6773 and do any sledgehammer checks we have turned on in this build.
6774
6775 START must be a Lisp integer. END can be nil, indicating the length of the
6776 string, or a Lisp integer. The condition (<= 0 START END (length DEST))
6777 must hold, or replace_string_range() will signal an error. */
6778 static Lisp_Object
6779 replace_string_range (Lisp_Object dest, Lisp_Object start, Lisp_Object end,
6780 const Ibyte *source, const Ibyte *source_limit)
6781 {
6782 return replace_string_range_1 (dest, start, end, source, source_limit,
6783 Qnil);
6784 }
6785
6786 /* This is the guts of several mapping functions.
6787
6788 Call FUNCTION CALL_COUNT times, with NSEQUENCES arguments each time,
6789 taking the elements from SEQUENCES. If VALS is non-NULL, store the
6790 results into VALS, a C array of Lisp_Objects; else, if LISP_VALS is
6791 non-nil, store the results into LISP_VALS, a sequence with sufficient
6792 room for CALL_COUNT results (but see the documentation of SOME_OR_EVERY.)
6793 Else, do not accumulate any result.
6794
6795 If VALS is non-NULL, NSEQUENCES is one, and SEQUENCES[0] is a cons,
6796 mapcarX will store the elements of SEQUENCES[0] in stack and GCPRO them,
6797 so FUNCTION cannot insert a non-cons into SEQUENCES[0] and throw off
6798 mapcarX.
6799
6800 Otherwise, mapcarX signals an invalid state error (see
6801 mapping_interaction_error(), above) if it encounters a non-cons,
6802 non-array when traversing SEQUENCES. Common Lisp specifies in
6803 MAPPING-DESTRUCTIVE-INTERACTION that it is an error when FUNCTION
6804 destructively modifies SEQUENCES in a way that might affect the ongoing
6805 traversal operation.
6806
6807 CALLER is a symbol describing the Lisp-visible function that was called,
6808 and any errors thrown because SEQUENCES was modified will reflect it.
6809
6810 If CALLER is Qsome, return the (possibly multiple) values given by
6811 FUNCTION the first time it is non-nil, and abandon the iterations.
6812 LISP_VALS must be the result of calling STORE_VOID_IN_LISP on the address
6813 of a Lisp object, and the return value will be stored at that address.
6814 If CALLER is Qevery, LISP_VALS must also reflect a pointer to a Lisp
6815 object, and Qnil will be stored at that address if FUNCTION gives nil;
6816 otherwise it will be left alone. */
6817
6818 static void
6819 mapcarX (Elemcount call_count, Lisp_Object *vals, Lisp_Object lisp_vals,
6820 Lisp_Object function, int nsequences, Lisp_Object *sequences,
6821 Lisp_Object caller)
6822 {
6823 Lisp_Object called, *args;
6824 struct gcpro gcpro1, gcpro2;
6825 Ibyte *lisp_vals_staging = NULL, *cursor = NULL;
6826 int i, j;
6827
6828 assert ((EQ (caller, Qsome) || EQ (caller, Qevery)) ? vals == NULL : 1);
6829
6830 args = alloca_array (Lisp_Object, nsequences + 1);
6831 args[0] = function;
6832 for (i = 1; i <= nsequences; ++i)
6833 {
6834 args[i] = Qnil;
6835 }
6836
6837 if (vals != NULL)
6838 {
6839 GCPRO2 (args[0], vals[0]);
6840 gcpro1.nvars = nsequences + 1;
6841 gcpro2.nvars = 0;
6842 }
6843 else
6844 {
6845 GCPRO1 (args[0]);
6846 gcpro1.nvars = nsequences + 1;
6847 }
6848
6849 /* Be extra nice in the event that we've been handed one list and one
6850 only; make it possible for FUNCTION to set cdrs not yet processed to
6851 non-cons, non-nil objects without ill-effect, if we have been handed
6852 the stack space to do that. */
6853 if (vals != NULL && 1 == nsequences && CONSP (sequences[0]))
6854 {
6855 Lisp_Object lst = sequences[0];
6856 Lisp_Object *val = vals;
6857 for (i = 0; i < call_count; ++i)
6858 {
6859 *val++ = XCAR (lst);
6860 lst = XCDR (lst);
6861 }
6862 gcpro2.nvars = call_count;
6863
6864 for (i = 0; i < call_count; ++i)
6865 {
6866 args[1] = vals[i];
6867 vals[i] = IGNORE_MULTIPLE_VALUES (Ffuncall (nsequences + 1, args));
6868 }
6869 }
6870 else
6871 {
6872 enum lrecord_type lisp_vals_type = lrecord_type_symbol;
6873 Binbyte *sequence_types = alloca_array (Binbyte, nsequences);
6874 for (j = 0; j < nsequences; ++j)
6875 {
6876 sequence_types[j] = XRECORD_LHEADER (sequences[j])->type;
6877 }
6878
6879 if (!EQ (caller, Qsome) && !EQ (caller, Qevery))
6880 {
6881 assert (LRECORDP (lisp_vals));
6882
6883 lisp_vals_type
6884 = (enum lrecord_type) XRECORD_LHEADER (lisp_vals)->type;
6885
6886 if (lrecord_type_string == lisp_vals_type)
6887 {
6888 lisp_vals_staging = cursor
6889 = alloca_ibytes (call_count * MAX_ICHAR_LEN);
6890 }
6891 else if (ARRAYP (lisp_vals))
6892 {
6893 CHECK_LISP_WRITEABLE (lisp_vals);
6894 }
6895 }
6896
6897 for (i = 0; i < call_count; ++i)
6898 {
6899 for (j = 0; j < nsequences; ++j)
6900 {
6901 switch (sequence_types[j])
6902 {
6903 case lrecord_type_cons:
6904 {
6905 if (!CONSP (sequences[j]))
6906 {
6907 /* This means FUNCTION has messed around with a cons
6908 in one of the sequences, since we checked the
6909 type (CHECK_SEQUENCE()) and the length and
6910 structure (with Flength()) correctly in our
6911 callers. */
6912 mapping_interaction_error (caller, sequences[j]);
6913 }
6914 args[j + 1] = XCAR (sequences[j]);
6915 sequences[j] = XCDR (sequences[j]);
6916 break;
6917 }
6918 case lrecord_type_vector:
6919 {
6920 args[j + 1] = XVECTOR_DATA (sequences[j])[i];
6921 break;
6922 }
6923 case lrecord_type_string:
6924 {
6925 args[j + 1] = make_char (string_ichar (sequences[j], i));
6926 break;
6927 }
6928 case lrecord_type_bit_vector:
6929 {
6930 args[j + 1]
6931 = make_fixnum (bit_vector_bit (XBIT_VECTOR (sequences[j]),
6932 i));
6933 break;
6934 }
6935 default:
6936 ABORT();
6937 }
6938 }
6939 called = Ffuncall (nsequences + 1, args);
6940 if (vals != NULL)
6941 {
6942 vals[i] = IGNORE_MULTIPLE_VALUES (called);
6943 gcpro2.nvars += 1;
6944 }
6945 else if (EQ (Qsome, caller))
6946 {
6947 if (!NILP (IGNORE_MULTIPLE_VALUES (called)))
6948 {
6949 Lisp_Object *result
6950 = (Lisp_Object *) GET_VOID_FROM_LISP (lisp_vals);
6951 *result = called;
6952 UNGCPRO;
6953 return;
6954 }
6955 }
6956 else if (EQ (Qevery, caller))
6957 {
6958 if (NILP (IGNORE_MULTIPLE_VALUES (called)))
6959 {
6960 Lisp_Object *result
6961 = (Lisp_Object *) GET_VOID_FROM_LISP (lisp_vals);
6962 *result = Qnil;
6963 UNGCPRO;
6964 return;
6965 }
6966 }
6967 else
6968 {
6969 called = IGNORE_MULTIPLE_VALUES (called);
6970 switch (lisp_vals_type)
6971 {
6972 case lrecord_type_symbol:
6973 /* Discard the result of funcall. */
6974 break;
6975 case lrecord_type_cons:
6976 {
6977 if (!CONSP (lisp_vals))
6978 {
6979 /* If FUNCTION has inserted a non-cons non-nil
6980 cdr into the list before we've processed the
6981 relevant part, error. */
6982 mapping_interaction_error (caller, lisp_vals);
6983 }
6984 XSETCAR (lisp_vals, called);
6985 lisp_vals = XCDR (lisp_vals);
6986 break;
6987 }
6988 case lrecord_type_vector:
6989 {
6990 i < XVECTOR_LENGTH (lisp_vals) ?
6991 (XVECTOR_DATA (lisp_vals)[i] = called) :
6992 /* Let #'aset error. */
6993 Faset (lisp_vals, make_fixnum (i), called);
6994 break;
6995 }
6996 case lrecord_type_string:
6997 {
6998 CHECK_CHAR_COERCE_INT (called);
6999 cursor += set_itext_ichar (cursor, XCHAR (called));
7000 break;
7001 }
7002 case lrecord_type_bit_vector:
7003 {
7004 (BITP (called) &&
7005 i < bit_vector_length (XBIT_VECTOR (lisp_vals))) ?
7006 set_bit_vector_bit (XBIT_VECTOR (lisp_vals), i,
7007 XFIXNUM (called)) :
7008 (void) Faset (lisp_vals, make_fixnum (i), called);
7009 break;
7010 }
7011 default:
7012 {
7013 ABORT();
7014 break;
7015 }
7016 }
7017 }
7018 }
7019
7020 if (lisp_vals_staging != NULL)
7021 {
7022 CHECK_LISP_WRITEABLE (lisp_vals);
7023 replace_string_range (lisp_vals, Qzero, make_fixnum (call_count),
7024 lisp_vals_staging, cursor);
7025 }
7026 }
7027
7028 UNGCPRO;
7029 }
7030
7031 /* Given NSEQUENCES objects at the address pointed to by SEQUENCES, return
7032 the length of the shortest sequence. Error if all are circular, or if any
7033 one of them is not a sequence. */
7034 static Elemcount
7035 shortest_length_among_sequences (int nsequences, Lisp_Object *sequences)
7036 {
7037 Elemcount len = 1 + MOST_POSITIVE_FIXNUM;
7038 Lisp_Object length = Qnil;
7039 int i;
7040
7041 for (i = 0; i < nsequences; ++i)
7042 {
7043 if (CONSP (sequences[i]))
7044 {
7045 length = Flist_length (sequences[i]);
7046 if (!NILP (length))
7047 {
7048 len = min (len, XFIXNUM (length));
7049 }
7050 }
7051 else
7052 {
7053 CHECK_SEQUENCE (sequences[i]);
7054 length = Flength (sequences[i]);
7055 len = min (len, XFIXNUM (length));
7056 }
7057 }
7058
7059 if (len == 1 + MOST_POSITIVE_FIXNUM)
7060 {
7061 signal_circular_list_error (sequences[0]);
7062 }
7063
7064 return len;
7065 }
7066
7067 DEFUN ("mapconcat", Fmapconcat, 3, MANY, 0, /*
7068 Call FUNCTION on each element of SEQUENCE, and concat results to a string.
7069 Between each pair of results, insert SEPARATOR.
7070
7071 Each result, and SEPARATOR, should be strings. Thus, using " " as SEPARATOR
7072 results in spaces between the values returned by FUNCTION. SEQUENCE itself
7073 may be a list, a vector, a bit vector, or a string.
7074
7075 With optional SEQUENCES, call FUNCTION each time with as many arguments as
7076 there are SEQUENCES, plus one for the element from SEQUENCE. One element
7077 from each sequence will be used each time FUNCTION is called, and
7078 `mapconcat' will give up once the shortest sequence is exhausted.
7079
7080 arguments: (FUNCTION SEQUENCE SEPARATOR &rest SEQUENCES)
7081 */
7082 (int nargs, Lisp_Object *args))
7083 {
7084 Lisp_Object function = args[0];
7085 Lisp_Object sequence = args[1];
7086 Lisp_Object separator = args[2];
7087 Elemcount len = MOST_POSITIVE_FIXNUM;
7088 Lisp_Object *args0;
7089 EMACS_INT i, nargs0;
7090
7091 args[2] = sequence;
7092 args[1] = separator;
7093
7094 len = shortest_length_among_sequences (nargs - 2, args + 2);
7095
7096 if (len == 0) return build_ascstring ("");
7097
7098 nargs0 = len + len - 1;
7099 args0 = alloca_array (Lisp_Object, nargs0);
7100
7101 /* Special-case this, it's very common and doesn't require any
7102 funcalls. Upside of doing it here, instead of cl-macs.el: no consing,
7103 apart from the final string, we allocate everything on the stack. */
7104 if (EQ (function, Qidentity) && 3 == nargs && CONSP (sequence))
7105 {
7106 for (i = 0; i < len; ++i)
7107 {
7108 args0[i] = XCAR (sequence);
7109 sequence = XCDR (sequence);
7110 }
7111 }
7112 else
7113 {
7114 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, Qmapconcat);
7115 }
7116
7117 for (i = len - 1; i >= 0; i--)
7118 args0[i + i] = args0[i];
7119
7120 for (i = 1; i < nargs0; i += 2)
7121 args0[i] = separator;
7122
7123 return Fconcat (nargs0, args0);
7124 }
7125
7126 DEFUN ("mapcar*", FmapcarX, 2, MANY, 0, /*
7127 Call FUNCTION on each element of SEQUENCE; return a list of the results.
7128 The result is a list of the same length as SEQUENCE.
7129 SEQUENCE may be a list, a vector, a bit vector, or a string.
7130
7131 With optional SEQUENCES, call FUNCTION each time with as many arguments as
7132 there are SEQUENCES, plus one for the element from SEQUENCE. One element
7133 from each sequence will be used each time FUNCTION is called, and `mapcar'
7134 stops calling FUNCTION once the shortest sequence is exhausted.
7135
7136 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
7137 */
7138 (int nargs, Lisp_Object *args))
7139 {
7140 Lisp_Object function = args[0];
7141 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
7142 Lisp_Object *args0;
7143
7144 args0 = alloca_array (Lisp_Object, len);
7145 mapcarX (len, args0, Qnil, function, nargs - 1, args + 1, QmapcarX);
7146
7147 return Flist ((int) len, args0);
7148 }
7149
7150 DEFUN ("mapvector", Fmapvector, 2, MANY, 0, /*
7151 Call FUNCTION on each element of SEQUENCE; return a vector of the results.
7152 The result is a vector of the same length as SEQUENCE.
7153 SEQUENCE may be a list, a vector, a bit vector, or a string.
7154
7155 With optional SEQUENCES, call FUNCTION each time with as many arguments as
7156 there are SEQUENCES, plus one for the element from SEQUENCE. One element
7157 from each sequence will be used each time FUNCTION is called, and
7158 `mapvector' stops calling FUNCTION once the shortest sequence is exhausted.
7159
7160 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
7161 */
7162 (int nargs, Lisp_Object *args))
7163 {
7164 Lisp_Object function = args[0];
7165 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
7166 Lisp_Object result = make_vector (len, Qnil);
7167
7168 struct gcpro gcpro1;
7169 GCPRO1 (result);
7170 /* Don't pass result as the lisp_object argument, we want mapcarX to protect
7171 a single list argument's elements from being garbage-collected. */
7172 mapcarX (len, XVECTOR_DATA (result), Qnil, function, nargs - 1, args +1,
7173 Qmapvector);
7174 RETURN_UNGCPRO (result);
7175 }
7176
7177 DEFUN ("mapcan", Fmapcan, 2, MANY, 0, /*
7178 Call FUNCTION on each element of SEQUENCE; chain the results together.
7179
7180 FUNCTION must normally return a list; the results will be concatenated
7181 together using `nconc'.
7182
7183 With optional SEQUENCES, call FUNCTION each time with as many arguments as
7184 there are SEQUENCES, plus one for the element from SEQUENCE. One element
7185 from each sequence will be used each time FUNCTION is called, and
7186 `mapcan' stops calling FUNCTION once the shortest sequence is exhausted.
7187
7188 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
7189 */
7190 (int nargs, Lisp_Object *args))
7191 {
7192 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
7193 Lisp_Object function = args[0], *result = alloca_array (Lisp_Object, len);
7194
7195 mapcarX (len, result, Qnil, function, nargs - 1, args + 1, Qmapcan);
7196
7197 /* #'nconc GCPROs its args in case of signals and error. */
7198 return Fnconc (len, result);
7199 }
7200
7201 DEFUN ("mapc", Fmapc, 2, MANY, 0, /*
7202 Call FUNCTION on each element of SEQUENCE.
7203
7204 SEQUENCE may be a list, a vector, a bit vector, or a string.
7205 This function is like `mapcar' but does not accumulate the results,
7206 which is more efficient if you do not use the results.
7207
7208 With optional SEQUENCES, call FUNCTION each time with as many arguments as
7209 there are SEQUENCES, plus one for the elements from SEQUENCE. One element
7210 from each sequence will be used each time FUNCTION is called, and
7211 `mapc' stops calling FUNCTION once the shortest sequence is exhausted.
7212
7213 Return SEQUENCE.
7214
7215 arguments: (FUNCTION SEQUENCE &rest SEQUENCES)
7216 */
7217 (int nargs, Lisp_Object *args))
7218 {
7219 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
7220 Lisp_Object sequence = args[1];
7221 struct gcpro gcpro1;
7222 /* We need to GCPRO sequence, because mapcarX will modify the
7223 elements of the args array handed to it, and this may involve
7224 elements of sequence getting garbage collected. */
7225 GCPRO1 (sequence);
7226 mapcarX (len, NULL, Qnil, args[0], nargs - 1, args + 1, Qmapc);
7227 RETURN_UNGCPRO (sequence);
7228 }
7229
7230 DEFUN ("map", Fmap, 3, MANY, 0, /*
7231 Map FUNCTION across one or more sequences, returning a sequence.
7232
7233 TYPE is the sequence type to return, FUNCTION is the function, SEQUENCE is
7234 the first argument sequence, SEQUENCES are the other argument sequences.
7235
7236 FUNCTION will be called with (1+ (length SEQUENCES)) arguments, and must be
7237 capable of accepting this number of arguments.
7238
7239 Certain TYPEs are recognised internally by `map', but others are not, and
7240 `coerce' may throw an error on an attempt to convert to a TYPE it does not
7241 understand. A null TYPE means do not accumulate any values.
7242
7243 arguments: (TYPE FUNCTION SEQUENCE &rest SEQUENCES)
7244 */
7245 (int nargs, Lisp_Object *args))
7246 {
7247 Lisp_Object type = args[0];
7248 Lisp_Object function = args[1];
7249 Lisp_Object result = Qnil;
7250 Lisp_Object *args0 = NULL;
7251 Elemcount len = shortest_length_among_sequences (nargs - 2, args + 2);
7252 struct gcpro gcpro1;
7253
7254 if (!NILP (type))
7255 {
7256 args0 = alloca_array (Lisp_Object, len);
7257 }
7258
7259 mapcarX (len, args0, Qnil, function, nargs - 2, args + 2, Qmap);
7260
7261 if (EQ (type, Qnil))
7262 {
7263 return result;
7264 }
7265
7266 if (EQ (type, Qvector) || EQ (type, Qarray))
7267 {
7268 result = Fvector (len, args0);
7269 }
7270 else if (EQ (type, Qstring))
7271 {
7272 result = Fstring (len, args0);
7273 }
7274 else if (EQ (type, Qlist))
7275 {
7276 result = Flist (len, args0);
7277 }
7278 else if (EQ (type, Qbit_vector))
7279 {
7280 result = Fbit_vector (len, args0);
7281 }
7282 else
7283 {
7284 result = Flist (len, args0);
7285 GCPRO1 (result);
7286 result = call2 (Qcoerce, result, type);
7287 UNGCPRO;
7288 }
7289
7290 return result;
7291 }
7292
7293 DEFUN ("map-into", Fmap_into, 2, MANY, 0, /*
7294 Modify RESULT-SEQUENCE using the return values of FUNCTION on SEQUENCES.
7295
7296 RESULT-SEQUENCE and SEQUENCES can be lists or arrays.
7297
7298 FUNCTION must accept at least as many arguments as there are SEQUENCES
7299 \(possibly zero). If RESULT-SEQUENCE and the elements of SEQUENCES are not
7300 the same length, stop when the shortest is exhausted; any elements of
7301 RESULT-SEQUENCE beyond that are unmodified.
7302
7303 Return RESULT-SEQUENCE.
7304
7305 arguments: (RESULT-SEQUENCE FUNCTION &rest SEQUENCES)
7306 */
7307 (int nargs, Lisp_Object *args))
7308 {
7309 Elemcount len;
7310 Lisp_Object result_sequence = args[0];
7311 Lisp_Object function = args[1];
7312
7313 args[0] = function;
7314 args[1] = result_sequence;
7315
7316 len = shortest_length_among_sequences (nargs - 1, args + 1);
7317
7318 mapcarX (len, NULL, result_sequence, function, nargs - 2, args + 2,
7319 Qmap_into);
7320
7321 return result_sequence;
7322 }
7323
7324 DEFUN ("some", Fsome, 2, MANY, 0, /*
7325 Return true if PREDICATE gives non-nil for an element of SEQUENCE.
7326
7327 If so, return the value (possibly multiple) given by PREDICATE.
7328
7329 With optional SEQUENCES, call PREDICATE each time with as many arguments as
7330 there are SEQUENCES (plus one for the element from SEQUENCE).
7331
7332 See also `find-if', which returns the corresponding element of SEQUENCE,
7333 rather than the value given by PREDICATE, and accepts bounding index
7334 keywords.
7335
7336 arguments: (PREDICATE SEQUENCE &rest SEQUENCES)
7337 */
7338 (int nargs, Lisp_Object *args))
7339 {
7340 Lisp_Object result = Qnil,
7341 result_ptr = STORE_VOID_IN_LISP ((void *) &result);
7342 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
7343
7344 mapcarX (len, NULL, result_ptr, args[0], nargs - 1, args +1, Qsome);
7345
7346 return result;
7347 }
7348
7349 DEFUN ("every", Fevery, 2, MANY, 0, /*
7350 Return true if PREDICATE is true of every element of SEQUENCE.
7351
7352 With optional SEQUENCES, call PREDICATE each time with as many arguments as
7353 there are SEQUENCES (plus one for the element from SEQUENCE).
7354
7355 In contrast to `some', `every' never returns multiple values.
7356
7357 arguments: (PREDICATE SEQUENCE &rest SEQUENCES)
7358 */
7359 (int nargs, Lisp_Object *args))
7360 {
7361 Lisp_Object result = Qt, result_ptr = STORE_VOID_IN_LISP ((void *) &result);
7362 Elemcount len = shortest_length_among_sequences (nargs - 1, args + 1);
7363
7364 mapcarX (len, NULL, result_ptr, args[0], nargs - 1, args +1, Qevery);
7365
7366 return result;
7367 }
7368
7369 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument 2519 /* Call FUNCTION with NLISTS arguments repeatedly, each Nth argument
7370 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]), 2520 corresponding to the result of calling (nthcdr ITERATION-COUNT LISTS[N]),
7371 until that #'nthcdr expression gives nil for some element of LISTS. 2521 until that #'nthcdr expression gives nil for some element of LISTS.
7372 2522
7373 CALLER is a symbol reflecting the Lisp-visible function that was called, 2523 CALLER is a symbol reflecting the Lisp-visible function that was called,
7526 */ 2676 */
7527 (int nargs, Lisp_Object *args)) 2677 (int nargs, Lisp_Object *args))
7528 { 2678 {
7529 return maplist (args[0], nargs - 1, args + 1, Qmapcon); 2679 return maplist (args[0], nargs - 1, args + 1, Qmapcon);
7530 } 2680 }
7531
7532 /* Extra random functions */
7533
7534 DEFUN ("reduce", Freduce, 2, MANY, 0, /*
7535 Combine the elements of sequence using FUNCTION, a binary operation.
7536
7537 For example, `(reduce #'+ SEQUENCE)' returns the sum of all elements in
7538 SEQUENCE, and `(reduce #'union SEQUENCE)' returns the union of all elements
7539 in SEQUENCE.
7540
7541 Keywords supported: :start :end :from-end :initial-value :key
7542 See `remove*' for the meaning of :start, :end, :from-end and :key.
7543
7544 :initial-value specifies an element (typically an identity element, such as
7545 0) that is conceptually prepended to the sequence (or appended, when
7546 :from-end is given).
7547
7548 If the sequence has one element, that element is returned directly.
7549 If the sequence has no elements, :initial-value is returned if given;
7550 otherwise, FUNCTION is called with no arguments, and its result returned.
7551
7552 arguments: (FUNCTION SEQUENCE &key (START 0) (END (length SEQUENCE)) FROM-END INITIAL-VALUE (KEY #'identity))
7553 */
7554 (int nargs, Lisp_Object *args))
7555 {
7556 Lisp_Object function = args[0], sequence = args[1], accum = Qunbound;
7557 Elemcount starting, ending = MOST_POSITIVE_FIXNUM + 1, ii = 0;
7558
7559 PARSE_KEYWORDS (Freduce, nargs, args, 5,
7560 (start, end, from_end, initial_value, key),
7561 (start = Qzero, initial_value = Qunbound));
7562
7563 CHECK_SEQUENCE (sequence);
7564 CHECK_NATNUM (start);
7565 starting = BIGNUMP (start) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (start);
7566 CHECK_KEY_ARGUMENT (key);
7567
7568 #define KEY(key, item) (EQ (Qidentity, key) ? item : \
7569 IGNORE_MULTIPLE_VALUES (call1 (key, item)))
7570 #define CALL2(function, accum, item) \
7571 IGNORE_MULTIPLE_VALUES (call2 (function, accum, item))
7572
7573 if (!NILP (end))
7574 {
7575 CHECK_NATNUM (end);
7576 ending = BIGNUMP (end) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (end);
7577 }
7578
7579 if (VECTORP (sequence))
7580 {
7581 Lisp_Vector *vv = XVECTOR (sequence);
7582 struct gcpro gcpro1;
7583
7584 check_sequence_range (sequence, start, end, make_fixnum (vv->size));
7585
7586 ending = min (ending, vv->size);
7587
7588 GCPRO1 (accum);
7589
7590 if (!UNBOUNDP (initial_value))
7591 {
7592 accum = initial_value;
7593 }
7594 else if (ending - starting)
7595 {
7596 if (NILP (from_end))
7597 {
7598 accum = KEY (key, vv->contents[starting]);
7599 starting++;
7600 }
7601 else
7602 {
7603 accum = KEY (key, vv->contents[ending - 1]);
7604 ending--;
7605 }
7606 }
7607
7608 if (NILP (from_end))
7609 {
7610 for (ii = starting; ii < ending; ++ii)
7611 {
7612 accum = CALL2 (function, accum, KEY (key, vv->contents[ii]));
7613 }
7614 }
7615 else
7616 {
7617 for (ii = ending - 1; ii >= starting; --ii)
7618 {
7619 accum = CALL2 (function, KEY (key, vv->contents[ii]), accum);
7620 }
7621 }
7622
7623 UNGCPRO;
7624 }
7625 else if (BIT_VECTORP (sequence))
7626 {
7627 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence);
7628 struct gcpro gcpro1;
7629
7630 check_sequence_range (sequence, start, end, make_fixnum (bv->size));
7631 ending = min (ending, bv->size);
7632
7633 GCPRO1 (accum);
7634
7635 if (!UNBOUNDP (initial_value))
7636 {
7637 accum = initial_value;
7638 }
7639 else if (ending - starting)
7640 {
7641 if (NILP (from_end))
7642 {
7643 accum = KEY (key, make_fixnum (bit_vector_bit (bv, starting)));
7644 starting++;
7645 }
7646 else
7647 {
7648 accum = KEY (key, make_fixnum (bit_vector_bit (bv, ending - 1)));
7649 ending--;
7650 }
7651 }
7652
7653 if (NILP (from_end))
7654 {
7655 for (ii = starting; ii < ending; ++ii)
7656 {
7657 accum = CALL2 (function, accum,
7658 KEY (key, make_fixnum (bit_vector_bit (bv, ii))));
7659 }
7660 }
7661 else
7662 {
7663 for (ii = ending - 1; ii >= starting; --ii)
7664 {
7665 accum = CALL2 (function, KEY (key,
7666 make_fixnum (bit_vector_bit (bv,
7667 ii))),
7668 accum);
7669 }
7670 }
7671
7672 UNGCPRO;
7673
7674 }
7675 else if (STRINGP (sequence))
7676 {
7677 struct gcpro gcpro1;
7678
7679 GCPRO1 (accum);
7680
7681 if (NILP (from_end))
7682 {
7683 Bytecount byte_len = XSTRING_LENGTH (sequence);
7684 Bytecount cursor_offset = 0;
7685 const Ibyte *startp = XSTRING_DATA (sequence);
7686 const Ibyte *cursor = startp;
7687
7688 for (ii = 0; ii != starting && cursor_offset < byte_len; ++ii)
7689 {
7690 INC_IBYTEPTR (cursor);
7691 cursor_offset = cursor - startp;
7692 }
7693
7694 if (!UNBOUNDP (initial_value))
7695 {
7696 accum = initial_value;
7697 }
7698 else if (ending - starting && cursor_offset < byte_len)
7699 {
7700 accum = KEY (key, make_char (itext_ichar (cursor)));
7701 starting++;
7702 startp = XSTRING_DATA (sequence);
7703 cursor = startp + cursor_offset;
7704
7705 if (byte_len != XSTRING_LENGTH (sequence)
7706 || !valid_ibyteptr_p (cursor))
7707 {
7708 mapping_interaction_error (Qreduce, sequence);
7709 }
7710
7711 INC_IBYTEPTR (cursor);
7712 cursor_offset = cursor - startp;
7713 ii++;
7714 }
7715
7716 while (cursor_offset < byte_len && ii < ending)
7717 {
7718 accum = CALL2 (function, accum,
7719 KEY (key, make_char (itext_ichar (cursor))));
7720
7721 startp = XSTRING_DATA (sequence);
7722 cursor = startp + cursor_offset;
7723
7724 if (byte_len != XSTRING_LENGTH (sequence)
7725 || !valid_ibyteptr_p (cursor))
7726 {
7727 mapping_interaction_error (Qreduce, sequence);
7728 }
7729
7730 INC_IBYTEPTR (cursor);
7731 cursor_offset = cursor - startp;
7732 ++ii;
7733 }
7734
7735 if (ii < starting || (ii < ending && !NILP (end)))
7736 {
7737 check_sequence_range (sequence, start, end, Flength (sequence));
7738 }
7739 }
7740 else
7741 {
7742 Elemcount len = string_char_length (sequence);
7743 Bytecount cursor_offset, byte_len = XSTRING_LENGTH (sequence);
7744 const Ibyte *cursor;
7745
7746 check_sequence_range (sequence, start, end, make_fixnum (len));
7747 ending = min (ending, len);
7748 starting = XFIXNUM (start);
7749
7750 cursor = string_char_addr (sequence, ending - 1);
7751 cursor_offset = cursor - XSTRING_DATA (sequence);
7752
7753 if (!UNBOUNDP (initial_value))
7754 {
7755 accum = initial_value;
7756 }
7757 else if (ending - starting)
7758 {
7759 accum = KEY (key, make_char (itext_ichar (cursor)));
7760 ending--;
7761 if (ending > 0)
7762 {
7763 cursor = XSTRING_DATA (sequence) + cursor_offset;
7764
7765 if (!valid_ibyteptr_p (cursor))
7766 {
7767 mapping_interaction_error (Qreduce, sequence);
7768 }
7769
7770 DEC_IBYTEPTR (cursor);
7771 cursor_offset = cursor - XSTRING_DATA (sequence);
7772 }
7773 }
7774
7775 for (ii = ending - 1; ii >= starting; --ii)
7776 {
7777 accum = CALL2 (function, KEY (key,
7778 make_char (itext_ichar (cursor))),
7779 accum);
7780 if (ii > 0)
7781 {
7782 cursor = XSTRING_DATA (sequence) + cursor_offset;
7783
7784 if (byte_len != XSTRING_LENGTH (sequence)
7785 || !valid_ibyteptr_p (cursor))
7786 {
7787 mapping_interaction_error (Qreduce, sequence);
7788 }
7789
7790 DEC_IBYTEPTR (cursor);
7791 cursor_offset = cursor - XSTRING_DATA (sequence);
7792 }
7793 }
7794 }
7795
7796 UNGCPRO;
7797 }
7798 else if (LISTP (sequence))
7799 {
7800 if (NILP (from_end))
7801 {
7802 struct gcpro gcpro1;
7803
7804 GCPRO1 (accum);
7805
7806 if (!UNBOUNDP (initial_value))
7807 {
7808 accum = initial_value;
7809 }
7810 else if (ending - starting)
7811 {
7812 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
7813 {
7814 if (ii == starting)
7815 {
7816 accum = KEY (key, elt);
7817 starting++;
7818 break;
7819 }
7820 ++ii;
7821 }
7822 END_GC_EXTERNAL_LIST_LOOP (elt);
7823 }
7824
7825 ii = 0;
7826
7827 if (ending - starting)
7828 {
7829 GC_EXTERNAL_LIST_LOOP_2 (elt, sequence)
7830 {
7831 if (ii >= starting)
7832 {
7833 if (ii < ending)
7834 {
7835 accum = CALL2 (function, accum, KEY (key, elt));
7836 }
7837 else if (ii == ending)
7838 {
7839 break;
7840 }
7841 }
7842 ++ii;
7843 }
7844 END_GC_EXTERNAL_LIST_LOOP (elt);
7845 }
7846
7847 UNGCPRO;
7848
7849 if (ii < starting || (ii < ending && !NILP (end)))
7850 {
7851 check_sequence_range (sequence, start, end, Flength (sequence));
7852 }
7853 }
7854 else
7855 {
7856 Boolint need_accum = 0;
7857 Lisp_Object *subsequence = NULL;
7858 Elemcount counting = 0, len = 0;
7859 struct gcpro gcpro1;
7860
7861 len = XFIXNUM (Flength (sequence));
7862 check_sequence_range (sequence, start, end, make_fixnum (len));
7863 ending = min (ending, len);
7864
7865 /* :from-end with a list; make an alloca copy of the relevant list
7866 data, attempting to go backwards isn't worth the trouble. */
7867 if (!UNBOUNDP (initial_value))
7868 {
7869 accum = initial_value;
7870 if (ending - starting && starting < ending)
7871 {
7872 subsequence = alloca_array (Lisp_Object, ending - starting);
7873 }
7874 }
7875 else if (ending - starting && starting < ending)
7876 {
7877 subsequence = alloca_array (Lisp_Object, ending - starting);
7878 need_accum = 1;
7879 }
7880
7881 if (ending - starting && starting < ending)
7882 {
7883 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
7884 {
7885 if (counting >= starting)
7886 {
7887 if (counting < ending)
7888 {
7889 subsequence[ii++] = elt;
7890 }
7891 else if (counting == ending)
7892 {
7893 break;
7894 }
7895 }
7896 ++counting;
7897 }
7898 }
7899
7900 if (subsequence != NULL)
7901 {
7902 len = ending - starting;
7903 /* If we could be sure that neither FUNCTION nor KEY modify
7904 SEQUENCE, this wouldn't be necessary, since all the
7905 elements of SUBSEQUENCE would definitely always be
7906 reachable via SEQUENCE. */
7907 GCPRO1 (subsequence[0]);
7908 gcpro1.nvars = len;
7909 }
7910
7911 if (need_accum)
7912 {
7913 accum = KEY (key, subsequence[len - 1]);
7914 --len;
7915 }
7916
7917 for (ii = len; ii != 0;)
7918 {
7919 --ii;
7920 accum = CALL2 (function, KEY (key, subsequence[ii]), accum);
7921 }
7922
7923 if (subsequence != NULL)
7924 {
7925 UNGCPRO;
7926 }
7927 }
7928 }
7929
7930 /* At this point, if ACCUM is unbound, SEQUENCE has no elements; we
7931 need to return the result of calling FUNCTION with zero
7932 arguments. */
7933 if (UNBOUNDP (accum))
7934 {
7935 accum = IGNORE_MULTIPLE_VALUES (call0 (function));
7936 }
7937
7938 return accum;
7939 }
7940 2681
7941 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /* 2682 DEFUN ("replace-list", Freplace_list, 2, 2, 0, /*
7942 Destructively replace the list OLD with NEW. 2683 Destructively replace the list OLD with NEW.
7943 This is like (copy-sequence NEW) except that it reuses the 2684 This is like (copy-sequence NEW) except that it reuses the
7944 conses in OLD as much as possible. If OLD and NEW are the same 2685 conses in OLD as much as possible. If OLD and NEW are the same
7974 XCDR (prevoldtail) = Qnil; 2715 XCDR (prevoldtail) = Qnil;
7975 else 2716 else
7976 old = Qnil; 2717 old = Qnil;
7977 2718
7978 return old; 2719 return old;
7979 }
7980
7981 /* This function is the implementation of fill_string_range() and
7982 replace_string_range(); see the comments for those functions. */
7983 static Lisp_Object
7984 replace_string_range_1 (Lisp_Object dest, Lisp_Object start, Lisp_Object end,
7985 const Ibyte *source, const Ibyte *source_limit,
7986 Lisp_Object item)
7987 {
7988 Ibyte *destp = XSTRING_DATA (dest), *p = destp,
7989 *pend = p + XSTRING_LENGTH (dest), *pcursor, item_buf[MAX_ICHAR_LEN];
7990 Bytecount prefix_bytecount, source_len = source_limit - source;
7991 Charcount ii = 0, ending, len;
7992 Charcount starting = BIGNUMP (start) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (start);
7993 Elemcount delta;
7994
7995 while (ii < starting && p < pend)
7996 {
7997 INC_IBYTEPTR (p);
7998 ii++;
7999 }
8000
8001 pcursor = p;
8002
8003 if (NILP (end))
8004 {
8005 while (pcursor < pend)
8006 {
8007 INC_IBYTEPTR (pcursor);
8008 ii++;
8009 }
8010
8011 ending = len = ii;
8012 }
8013 else
8014 {
8015 ending = BIGNUMP (end) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (end);
8016 while (ii < ending && pcursor < pend)
8017 {
8018 INC_IBYTEPTR (pcursor);
8019 ii++;
8020 }
8021 }
8022
8023 if (pcursor == pend)
8024 {
8025 /* We have the length, check it for our callers. */
8026 check_sequence_range (dest, start, end, make_fixnum (ii));
8027 }
8028
8029 if (!(p == pend || p == pcursor))
8030 {
8031 prefix_bytecount = p - destp;
8032
8033 if (!NILP (item))
8034 {
8035 assert (source == NULL && source_limit == NULL);
8036 source_len = set_itext_ichar (item_buf, XCHAR (item));
8037 delta = (source_len * (ending - starting)) - (pcursor - p);
8038 }
8039 else
8040 {
8041 assert (source != NULL && source_limit != NULL);
8042 delta = source_len - (pcursor - p);
8043 }
8044
8045 if (delta)
8046 {
8047 resize_string (dest, prefix_bytecount, delta);
8048 destp = XSTRING_DATA (dest);
8049 pcursor = destp + prefix_bytecount + (pcursor - p);
8050 p = destp + prefix_bytecount;
8051 }
8052
8053 if (CHARP (item))
8054 {
8055 while (starting < ending)
8056 {
8057 memcpy (p, item_buf, source_len);
8058 p += source_len;
8059 starting++;
8060 }
8061 }
8062 else
8063 {
8064 while (starting < ending && source < source_limit)
8065 {
8066 source_len = itext_copy_ichar (source, p);
8067 p += source_len, source += source_len;
8068 }
8069 }
8070
8071 init_string_ascii_begin (dest);
8072 bump_string_modiff (dest);
8073 sledgehammer_check_ascii_begin (dest);
8074 }
8075
8076 return dest;
8077 }
8078
8079 DEFUN ("replace", Freplace, 2, MANY, 0, /*
8080 Replace the elements of SEQUENCE-ONE with the elements of SEQUENCE-TWO.
8081
8082 SEQUENCE-ONE is destructively modified, and returned. Its length is not
8083 changed.
8084
8085 Keywords :start1 and :end1 specify a subsequence of SEQUENCE-ONE, and
8086 :start2 and :end2 a subsequence of SEQUENCE-TWO. See `search' for more
8087 information.
8088
8089 arguments: (SEQUENCE-ONE SEQUENCE-TWO &key (START1 0) (END1 (length SEQUENCE-ONE)) (START2 0) (END2 (length SEQUENCE-TWO)))
8090 */
8091 (int nargs, Lisp_Object *args))
8092 {
8093 Lisp_Object sequence1 = args[0], sequence2 = args[1],
8094 result = sequence1;
8095 Elemcount starting1, ending1 = MOST_POSITIVE_FIXNUM + 1, starting2;
8096 Elemcount ending2 = MOST_POSITIVE_FIXNUM + 1, counting = 0, startcounting;
8097 Boolint sequence1_listp, sequence2_listp,
8098 overwriting = EQ (sequence1, sequence2);
8099
8100 PARSE_KEYWORDS (Freplace, nargs, args, 4, (start1, end1, start2, end2),
8101 (start1 = start2 = Qzero));
8102
8103 CHECK_SEQUENCE (sequence1);
8104 CHECK_LISP_WRITEABLE (sequence1);
8105
8106 CHECK_SEQUENCE (sequence2);
8107
8108 CHECK_NATNUM (start1);
8109 starting1 = BIGNUMP (start1) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (start1);
8110 CHECK_NATNUM (start2);
8111 starting2 = BIGNUMP (start2) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (start2);
8112
8113 if (!NILP (end1))
8114 {
8115 CHECK_NATNUM (end1);
8116 ending1 = BIGNUMP (end1) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (end1);
8117 }
8118
8119 if (!NILP (end2))
8120 {
8121 CHECK_NATNUM (end2);
8122 ending2 = BIGNUMP (end2) ? MOST_POSITIVE_FIXNUM + 1 : XFIXNUM (end2);
8123 }
8124
8125 sequence1_listp = LISTP (sequence1);
8126 sequence2_listp = LISTP (sequence2);
8127
8128 overwriting = overwriting && starting2 <= starting1;
8129
8130 if (sequence1_listp && !ZEROP (start1))
8131 {
8132 sequence1 = Fnthcdr (start1, sequence1);
8133
8134 if (NILP (sequence1))
8135 {
8136 check_sequence_range (args[0], start1, end1, Flength (args[0]));
8137 /* Give up early here. */
8138 return result;
8139 }
8140
8141 ending1 -= starting1;
8142 starting1 = 0;
8143 }
8144
8145 if (sequence2_listp && !ZEROP (start2))
8146 {
8147 sequence2 = Fnthcdr (start2, sequence2);
8148
8149 if (NILP (sequence2))
8150 {
8151 check_sequence_range (args[1], start1, end1, Flength (args[1]));
8152 /* Nothing available to replace sequence1's contents. */
8153 return result;
8154 }
8155
8156 ending2 -= starting2;
8157 starting2 = 0;
8158 }
8159
8160 if (overwriting)
8161 {
8162 if (EQ (start1, start2))
8163 {
8164 return result;
8165 }
8166
8167 /* Our ranges may overlap. Save the data that might be overwritten. */
8168
8169 if (CONSP (sequence2))
8170 {
8171 Elemcount len = XFIXNUM (Flength (sequence2));
8172 Lisp_Object *subsequence
8173 = alloca_array (Lisp_Object, min (ending2, len));
8174 Elemcount ii = 0;
8175
8176 LIST_LOOP_2 (elt, sequence2)
8177 {
8178 if (counting == ending2)
8179 {
8180 break;
8181 }
8182
8183 subsequence[ii++] = elt;
8184 counting++;
8185 }
8186
8187 check_sequence_range (sequence1, start1, end1,
8188 /* The XFIXNUM (start2) is intentional here; we
8189 called #'length after doing (nthcdr
8190 start2 sequence2). */
8191 make_fixnum (XFIXNUM (start2) + len));
8192 check_sequence_range (sequence2, start2, end2,
8193 make_fixnum (XFIXNUM (start2) + len));
8194
8195 while (starting1 < ending1
8196 && starting2 < ending2 && !NILP (sequence1))
8197 {
8198 XSETCAR (sequence1, subsequence[starting2]);
8199 sequence1 = XCDR (sequence1);
8200 starting1++;
8201 starting2++;
8202 }
8203 }
8204 else if (STRINGP (sequence2))
8205 {
8206 Ibyte *p = XSTRING_DATA (sequence2),
8207 *pend = p + XSTRING_LENGTH (sequence2), *pcursor,
8208 *staging;
8209 Bytecount ii = 0;
8210
8211 while (ii < starting2 && p < pend)
8212 {
8213 INC_IBYTEPTR (p);
8214 ii++;
8215 }
8216
8217 pcursor = p;
8218
8219 while (ii < ending2 && starting1 < ending1 && pcursor < pend)
8220 {
8221 INC_IBYTEPTR (pcursor);
8222 starting1++;
8223 ii++;
8224 }
8225
8226 if (pcursor == pend)
8227 {
8228 check_sequence_range (sequence1, start1, end1, make_fixnum (ii));
8229 check_sequence_range (sequence2, start2, end2, make_fixnum (ii));
8230 }
8231 else
8232 {
8233 assert ((pcursor - p) > 0);
8234 staging = alloca_ibytes (pcursor - p);
8235 memcpy (staging, p, pcursor - p);
8236 replace_string_range (result, start1,
8237 make_fixnum (starting1),
8238 staging, staging + (pcursor - p));
8239 }
8240 }
8241 else
8242 {
8243 Elemcount seq_len = XFIXNUM (Flength (sequence2)), ii = 0,
8244 subseq_len = min (min (ending1 - starting1, seq_len - starting1),
8245 min (ending2 - starting2, seq_len - starting2));
8246 Lisp_Object *subsequence = alloca_array (Lisp_Object, subseq_len);
8247
8248 check_sequence_range (sequence1, start1, end1, make_fixnum (seq_len));
8249 check_sequence_range (sequence2, start2, end2, make_fixnum (seq_len));
8250
8251 while (starting2 < ending2 && ii < seq_len)
8252 {
8253 subsequence[ii] = Faref (sequence2, make_fixnum (starting2));
8254 ii++, starting2++;
8255 }
8256
8257 ii = 0;
8258
8259 while (starting1 < ending1 && ii < seq_len)
8260 {
8261 Faset (sequence1, make_fixnum (starting1), subsequence[ii]);
8262 ii++, starting1++;
8263 }
8264 }
8265 }
8266 else if (sequence1_listp && sequence2_listp)
8267 {
8268 Lisp_Object sequence1_tortoise = sequence1,
8269 sequence2_tortoise = sequence2;
8270 Elemcount shortest_len = 0;
8271
8272 counting = startcounting = min (ending1, ending2);
8273
8274 while (counting-- > 0 && !NILP (sequence1) && !NILP (sequence2))
8275 {
8276 XSETCAR (sequence1,
8277 CONSP (sequence2) ? XCAR (sequence2)
8278 : Fcar (sequence2));
8279 sequence1 = CONSP (sequence1) ? XCDR (sequence1)
8280 : Fcdr (sequence1);
8281 sequence2 = CONSP (sequence2) ? XCDR (sequence2)
8282 : Fcdr (sequence2);
8283
8284 shortest_len++;
8285
8286 if (startcounting - counting > CIRCULAR_LIST_SUSPICION_LENGTH)
8287 {
8288 if (counting & 1)
8289 {
8290 sequence1_tortoise = XCDR (sequence1_tortoise);
8291 sequence2_tortoise = XCDR (sequence2_tortoise);
8292 }
8293
8294 if (EQ (sequence1, sequence1_tortoise))
8295 {
8296 signal_circular_list_error (sequence1);
8297 }
8298
8299 if (EQ (sequence2, sequence2_tortoise))
8300 {
8301 signal_circular_list_error (sequence2);
8302 }
8303 }
8304 }
8305
8306 if (NILP (sequence1))
8307 {
8308 check_sequence_range (args[0], start1, end1,
8309 make_fixnum (XFIXNUM (start1) + shortest_len));
8310 }
8311 else if (NILP (sequence2))
8312 {
8313 check_sequence_range (args[1], start2, end2,
8314 make_fixnum (XFIXNUM (start2) + shortest_len));
8315 }
8316 }
8317 else if (sequence1_listp)
8318 {
8319 if (STRINGP (sequence2))
8320 {
8321 Ibyte *s2_data = XSTRING_DATA (sequence2),
8322 *s2_end = s2_data + XSTRING_LENGTH (sequence2);
8323 Elemcount char_count = 0;
8324 Lisp_Object character;
8325
8326 while (char_count < starting2 && s2_data < s2_end)
8327 {
8328 INC_IBYTEPTR (s2_data);
8329 char_count++;
8330 }
8331
8332 while (starting1 < ending1 && starting2 < ending2
8333 && s2_data < s2_end && !NILP (sequence1))
8334 {
8335 character = make_char (itext_ichar (s2_data));
8336 CONSP (sequence1) ?
8337 XSETCAR (sequence1, character)
8338 : Fsetcar (sequence1, character);
8339 sequence1 = XCDR (sequence1);
8340 starting1++;
8341 starting2++;
8342 char_count++;
8343 INC_IBYTEPTR (s2_data);
8344 }
8345
8346 if (NILP (sequence1))
8347 {
8348 check_sequence_range (sequence1, start1, end1,
8349 make_fixnum (XFIXNUM (start1) + starting1));
8350 }
8351
8352 if (s2_data == s2_end)
8353 {
8354 check_sequence_range (sequence2, start2, end2,
8355 make_fixnum (char_count));
8356 }
8357 }
8358 else
8359 {
8360 Elemcount len2 = XFIXNUM (Flength (sequence2));
8361 check_sequence_range (sequence2, start2, end2, make_fixnum (len2));
8362
8363 ending2 = min (ending2, len2);
8364 while (starting2 < ending2
8365 && starting1 < ending1 && !NILP (sequence1))
8366 {
8367 CHECK_CONS (sequence1);
8368 XSETCAR (sequence1, Faref (sequence2, make_fixnum (starting2)));
8369 sequence1 = XCDR (sequence1);
8370 starting1++;
8371 starting2++;
8372 }
8373
8374 if (NILP (sequence1))
8375 {
8376 check_sequence_range (args[0], start1, end1,
8377 make_fixnum (XFIXNUM (start1) + starting1));
8378 }
8379 }
8380 }
8381 else if (sequence2_listp)
8382 {
8383 if (STRINGP (sequence1))
8384 {
8385 Elemcount ii = 0, count, len = string_char_length (sequence1);
8386 Ibyte *staging, *cursor;
8387 Lisp_Object obj;
8388
8389 check_sequence_range (sequence1, start1, end1, make_fixnum (len));
8390 ending1 = min (ending1, len);
8391 count = ending1 - starting1;
8392 staging = cursor = alloca_ibytes (count * MAX_ICHAR_LEN);
8393
8394 while (ii < count && !NILP (sequence2))
8395 {
8396 obj = CONSP (sequence2) ? XCAR (sequence2)
8397 : Fcar (sequence2);
8398
8399 CHECK_CHAR_COERCE_INT (obj);
8400 cursor += set_itext_ichar (cursor, XCHAR (obj));
8401 ii++;
8402 sequence2 = XCDR (sequence2);
8403 }
8404
8405 if (NILP (sequence2))
8406 {
8407 check_sequence_range (sequence2, start2, end2,
8408 make_fixnum (XFIXNUM (start2) + ii));
8409 }
8410
8411 replace_string_range (result, start1, make_fixnum (XFIXNUM (start1) + ii),
8412 staging, cursor);
8413 }
8414 else
8415 {
8416 Elemcount len = XFIXNUM (Flength (sequence1));
8417
8418 check_sequence_range (sequence1, start2, end1, make_fixnum (len));
8419 ending1 = min (ending2, min (ending1, len));
8420
8421 while (starting1 < ending1 && !NILP (sequence2))
8422 {
8423 Faset (sequence1, make_fixnum (starting1),
8424 CONSP (sequence2) ? XCAR (sequence2)
8425 : Fcar (sequence2));
8426 sequence2 = XCDR (sequence2);
8427 starting1++;
8428 starting2++;
8429 }
8430
8431 if (NILP (sequence2))
8432 {
8433 check_sequence_range (args[1], start2, end2,
8434 make_fixnum (XFIXNUM (start2) + starting2));
8435 }
8436 }
8437 }
8438 else
8439 {
8440 if (STRINGP (sequence1) && STRINGP (sequence2))
8441 {
8442 Ibyte *p2 = XSTRING_DATA (sequence2),
8443 *p2end = p2 + XSTRING_LENGTH (sequence2), *p2cursor;
8444 Charcount ii = 0, len1 = string_char_length (sequence1);
8445
8446 check_sequence_range (sequence1, start1, end1, make_fixnum (len1));
8447
8448 while (ii < starting2 && p2 < p2end)
8449 {
8450 INC_IBYTEPTR (p2);
8451 ii++;
8452 }
8453
8454 p2cursor = p2;
8455 ending1 = min (ending1, len1);
8456
8457 while (ii < ending2 && starting1 < ending1 && p2cursor < p2end)
8458 {
8459 INC_IBYTEPTR (p2cursor);
8460 ii++;
8461 starting1++;
8462 }
8463
8464 if (p2cursor == p2end)
8465 {
8466 check_sequence_range (sequence2, start2, end2, make_fixnum (ii));
8467 }
8468
8469 /* This isn't great; any error message won't necessarily reflect
8470 the END1 that was supplied to #'replace. */
8471 replace_string_range (result, start1, make_fixnum (starting1),
8472 p2, p2cursor);
8473 }
8474 else if (STRINGP (sequence1))
8475 {
8476 Ibyte *staging, *cursor;
8477 Elemcount count, len1 = string_char_length (sequence1);
8478 Elemcount len2 = XFIXNUM (Flength (sequence2)), ii = 0;
8479 Lisp_Object obj;
8480
8481 check_sequence_range (sequence1, start1, end1, make_fixnum (len1));
8482 check_sequence_range (sequence2, start2, end2, make_fixnum (len2));
8483
8484 ending1 = min (ending1, len1);
8485 ending2 = min (ending2, len2);
8486 count = min (ending1 - starting1, ending2 - starting2);
8487 staging = cursor = alloca_ibytes (count * MAX_ICHAR_LEN);
8488
8489 ii = 0;
8490 while (ii < count)
8491 {
8492 obj = Faref (sequence2, make_fixnum (starting2));
8493
8494 CHECK_CHAR_COERCE_INT (obj);
8495 cursor += set_itext_ichar (cursor, XCHAR (obj));
8496 starting2++, ii++;
8497 }
8498
8499 replace_string_range (result, start1,
8500 make_fixnum (XFIXNUM (start1) + count),
8501 staging, cursor);
8502 }
8503 else if (STRINGP (sequence2))
8504 {
8505 Ibyte *p2 = XSTRING_DATA (sequence2),
8506 *p2end = p2 + XSTRING_LENGTH (sequence2);
8507 Elemcount len1 = XFIXNUM (Flength (sequence1)), ii = 0;
8508
8509 check_sequence_range (sequence1, start1, end1, make_fixnum (len1));
8510 ending1 = min (ending1, len1);
8511
8512 while (ii < starting2 && p2 < p2end)
8513 {
8514 INC_IBYTEPTR (p2);
8515 ii++;
8516 }
8517
8518 while (p2 < p2end && starting1 < ending1 && starting2 < ending2)
8519 {
8520 Faset (sequence1, make_fixnum (starting1),
8521 make_char (itext_ichar (p2)));
8522 INC_IBYTEPTR (p2);
8523 starting1++;
8524 starting2++;
8525 ii++;
8526 }
8527
8528 if (p2 == p2end)
8529 {
8530 check_sequence_range (sequence2, start2, end2, make_fixnum (ii));
8531 }
8532 }
8533 else
8534 {
8535 Elemcount len1 = XFIXNUM (Flength (sequence1)),
8536 len2 = XFIXNUM (Flength (sequence2));
8537
8538 check_sequence_range (sequence1, start1, end1, make_fixnum (len1));
8539 check_sequence_range (sequence2, start2, end2, make_fixnum (len2));
8540
8541 ending1 = min (ending1, len1);
8542 ending2 = min (ending2, len2);
8543
8544 while (starting1 < ending1 && starting2 < ending2)
8545 {
8546 Faset (sequence1, make_fixnum (starting1),
8547 Faref (sequence2, make_fixnum (starting2)));
8548 starting1++;
8549 starting2++;
8550 }
8551 }
8552 }
8553
8554 return result;
8555 }
8556
8557 DEFUN ("nsubstitute", Fnsubstitute, 3, MANY, 0, /*
8558 Substitute NEW for OLD in SEQUENCE.
8559
8560 This is a destructive function; it reuses the storage of SEQUENCE whenever
8561 possible. See `remove*' for the meaning of the keywords.
8562
8563 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT)
8564 */
8565 (int nargs, Lisp_Object *args))
8566 {
8567 Lisp_Object new_ = args[0], item = args[1], sequence = args[2];
8568 Lisp_Object object_, position0;
8569 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, encountered = 0;
8570 Elemcount len, ii = 0, counting = MOST_POSITIVE_FIXNUM, presenting = 0;
8571 Boolint test_not_unboundp = 1;
8572 check_test_func_t check_test = NULL;
8573
8574 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9,
8575 (test, if_, if_not, test_not, key, start, end, count,
8576 from_end), (start = Qzero));
8577
8578 CHECK_SEQUENCE (sequence);
8579 CHECK_NATNUM (start);
8580 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
8581
8582 if (!NILP (end))
8583 {
8584 CHECK_NATNUM (end);
8585 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
8586 }
8587
8588 if (!NILP (count))
8589 {
8590 CHECK_INTEGER (count);
8591 if (FIXNUMP (count))
8592 {
8593 counting = XFIXNUM (count);
8594 }
8595 #ifdef HAVE_BIGNUM
8596 else
8597 {
8598 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
8599 1 + MOST_POSITIVE_FIXNUM : -1 + MOST_NEGATIVE_FIXNUM;
8600 }
8601 #endif
8602
8603 if (counting <= 0)
8604 {
8605 return sequence;
8606 }
8607 }
8608
8609 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
8610 key, &test_not_unboundp);
8611
8612 if (CONSP (sequence))
8613 {
8614 if (!NILP (count) && !NILP (from_end))
8615 {
8616 Lisp_Object present = count_with_tail (&object_, nargs - 1, args + 1,
8617 Qnsubstitute);
8618
8619 if (ZEROP (present))
8620 {
8621 return sequence;
8622 }
8623
8624 presenting = XFIXNUM (present);
8625 presenting = presenting <= counting ? 0 : presenting - counting;
8626 }
8627
8628 {
8629 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tail)
8630 {
8631 if (!(ii < ending))
8632 {
8633 break;
8634 }
8635
8636 if (starting <= ii &&
8637 check_test (test, key, item, elt) == test_not_unboundp
8638 && (presenting ? encountered++ >= presenting
8639 : encountered++ < counting))
8640 {
8641 CHECK_LISP_WRITEABLE (tail);
8642 XSETCAR (tail, new_);
8643 }
8644 else if (!presenting && encountered >= counting)
8645 {
8646 break;
8647 }
8648
8649 ii++;
8650 }
8651 END_GC_EXTERNAL_LIST_LOOP (elt);
8652 }
8653
8654 if ((ii < starting || (ii < ending && !NILP (end)))
8655 && encountered < counting)
8656 {
8657 check_sequence_range (args[0], start, end, Flength (args[0]));
8658 }
8659 }
8660 else if (STRINGP (sequence))
8661 {
8662 Ibyte *staging, new_bytes[MAX_ICHAR_LEN], *staging_cursor;
8663 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp;
8664 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence);
8665 Bytecount new_len;
8666 Lisp_Object character;
8667
8668 CHECK_CHAR_COERCE_INT (new_);
8669
8670 new_len = set_itext_ichar (new_bytes, XCHAR (new_));
8671
8672 /* Worst case scenario; new char is four octets long, all the old ones
8673 were one octet long, all the old ones match. */
8674 staging = alloca_ibytes (XSTRING_LENGTH (sequence) * new_len);
8675 staging_cursor = staging;
8676
8677 if (!NILP (count) && !NILP (from_end))
8678 {
8679 Lisp_Object present = count_with_tail (&character, nargs - 1,
8680 args + 1, Qnsubstitute);
8681
8682 if (ZEROP (present))
8683 {
8684 return sequence;
8685 }
8686
8687 presenting = XFIXNUM (present);
8688
8689 /* If there are fewer items in the string than we have
8690 permission to change, we don't need to differentiate
8691 between the :from-end nil and :from-end t
8692 cases. Otherwise, presenting is the number of matching
8693 items we need to ignore before we start to change. */
8694 presenting = presenting <= counting ? 0 : presenting - counting;
8695 }
8696
8697 ii = 0;
8698 while (cursor_offset < byte_len && ii < ending)
8699 {
8700 if (ii >= starting)
8701 {
8702 character = make_char (itext_ichar (cursor));
8703
8704 if ((check_test (test, key, item, character)
8705 == test_not_unboundp)
8706 && (presenting ? encountered++ >= presenting :
8707 encountered++ < counting))
8708 {
8709 staging_cursor
8710 += itext_copy_ichar (new_bytes, staging_cursor);
8711 }
8712 else
8713 {
8714 staging_cursor
8715 += itext_copy_ichar (cursor, staging_cursor);
8716 }
8717
8718 startp = XSTRING_DATA (sequence);
8719 cursor = startp + cursor_offset;
8720
8721 if (byte_len != XSTRING_LENGTH (sequence)
8722 || !valid_ibyteptr_p (cursor))
8723 {
8724 mapping_interaction_error (Qnsubstitute, sequence);
8725 }
8726 }
8727 else
8728 {
8729 staging_cursor += itext_copy_ichar (cursor, staging_cursor);
8730 }
8731
8732 INC_IBYTEPTR (cursor);
8733 cursor_offset = cursor - startp;
8734 ii++;
8735 }
8736
8737 if (ii < starting || (ii < ending && !NILP (end)))
8738 {
8739 check_sequence_range (sequence, start, end, Flength (sequence));
8740 }
8741
8742 if (0 != encountered)
8743 {
8744 CHECK_LISP_WRITEABLE (sequence);
8745 replace_string_range (sequence, Qzero, make_fixnum (ii),
8746 staging, staging_cursor);
8747 }
8748 }
8749 else
8750 {
8751 Elemcount positioning;
8752 Lisp_Object object = Qnil;
8753
8754 len = XFIXNUM (Flength (sequence));
8755 check_sequence_range (sequence, start, end, make_fixnum (len));
8756
8757 position0 = position (&object, item, sequence, check_test,
8758 test_not_unboundp, test, key, start, end, from_end,
8759 Qnil, Qnsubstitute);
8760
8761 if (NILP (position0))
8762 {
8763 return sequence;
8764 }
8765
8766 positioning = XFIXNUM (position0);
8767 ending = min (len, ending);
8768
8769 Faset (sequence, position0, new_);
8770 encountered = 1;
8771
8772 if (NILP (from_end))
8773 {
8774 for (ii = positioning + 1; ii < ending; ii++)
8775 {
8776 object_ = Faref (sequence, make_fixnum (ii));
8777
8778 if (check_test (test, key, item, object_) == test_not_unboundp
8779 && encountered++ < counting)
8780 {
8781 Faset (sequence, make_fixnum (ii), new_);
8782 }
8783 else if (encountered == counting)
8784 {
8785 break;
8786 }
8787 }
8788 }
8789 else
8790 {
8791 for (ii = positioning - 1; ii >= starting; ii--)
8792 {
8793 object_ = Faref (sequence, make_fixnum (ii));
8794
8795 if (check_test (test, key, item, object_) == test_not_unboundp
8796 && encountered++ < counting)
8797 {
8798 Faset (sequence, make_fixnum (ii), new_);
8799 }
8800 else if (encountered == counting)
8801 {
8802 break;
8803 }
8804 }
8805 }
8806 }
8807
8808 return sequence;
8809 }
8810
8811 DEFUN ("substitute", Fsubstitute, 3, MANY, 0, /*
8812 Substitute NEW for OLD in SEQUENCE.
8813
8814 This is a non-destructive function; it makes a copy of SEQUENCE if necessary
8815 to avoid corrupting the original SEQUENCE.
8816
8817 See `remove*' for the meaning of the keywords.
8818
8819 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT)
8820 */
8821 (int nargs, Lisp_Object *args))
8822 {
8823 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil;
8824 Lisp_Object result = Qnil, result_tail = Qnil;
8825 Lisp_Object object, position0, matched_count;
8826 Elemcount starting = 0, ending = MOST_POSITIVE_FIXNUM, encountered = 0;
8827 Elemcount ii = 0, counting = MOST_POSITIVE_FIXNUM, presenting = 0;
8828 Boolint test_not_unboundp = 1;
8829 check_test_func_t check_test = NULL;
8830 struct gcpro gcpro1;
8831
8832 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9,
8833 (test, if_, if_not, test_not, key, start, end, count,
8834 from_end), (start = Qzero, count = Qunbound));
8835
8836 CHECK_SEQUENCE (sequence);
8837
8838 CHECK_NATNUM (start);
8839 starting = BIGNUMP (start) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (start);
8840
8841 if (!NILP (end))
8842 {
8843 CHECK_NATNUM (end);
8844 ending = BIGNUMP (end) ? 1 + MOST_POSITIVE_FIXNUM : XFIXNUM (end);
8845 }
8846
8847 check_test = get_check_test_function (item, &test, test_not, if_, if_not,
8848 key, &test_not_unboundp);
8849
8850 if (!UNBOUNDP (count))
8851 {
8852 if (!NILP (count))
8853 {
8854 CHECK_INTEGER (count);
8855 if (FIXNUMP (count))
8856 {
8857 counting = XFIXNUM (count);
8858 }
8859 #ifdef HAVE_BIGNUM
8860 else
8861 {
8862 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ?
8863 1 + MOST_POSITIVE_FIXNUM : -1 + MOST_NEGATIVE_FIXNUM;
8864 }
8865 #endif
8866
8867 if (counting <= 0)
8868 {
8869 return sequence;
8870 }
8871 }
8872 }
8873
8874 if (!CONSP (sequence))
8875 {
8876 position0 = position (&object, item, sequence, check_test,
8877 test_not_unboundp, test, key, start, end, from_end,
8878 Qnil, Qsubstitute);
8879
8880 if (NILP (position0))
8881 {
8882 return sequence;
8883 }
8884 else
8885 {
8886 args[2] = Fcopy_sequence (sequence);
8887 return Fnsubstitute (nargs, args);
8888 }
8889 }
8890
8891 matched_count = count_with_tail (&tail, nargs - 1, args + 1, Qsubstitute);
8892
8893 if (ZEROP (matched_count))
8894 {
8895 return sequence;
8896 }
8897
8898 if (!NILP (count) && !NILP (from_end))
8899 {
8900 presenting = XFIXNUM (matched_count);
8901 presenting = presenting <= counting ? 0 : presenting - counting;
8902 }
8903
8904 GCPRO1 (result);
8905 {
8906 GC_EXTERNAL_LIST_LOOP_3 (elt, sequence, tailing)
8907 {
8908 if (EQ (tail, tailing))
8909 {
8910 XUNGCPRO (elt);
8911 UNGCPRO;
8912
8913 if (NILP (result))
8914 {
8915 return XCDR (tail);
8916 }
8917
8918 XSETCDR (result_tail, XCDR (tail));
8919 return result;
8920 }
8921 else if (starting <= ii && ii < ending &&
8922 (check_test (test, key, item, elt) == test_not_unboundp)
8923 && (presenting ? encountered++ >= presenting
8924 : encountered++ < counting))
8925 {
8926 if (NILP (result))
8927 {
8928 result = result_tail = Fcons (new_, Qnil);
8929 }
8930 else
8931 {
8932 XSETCDR (result_tail, Fcons (new_, Qnil));
8933 result_tail = XCDR (result_tail);
8934 }
8935 }
8936 else if (NILP (result))
8937 {
8938 result = result_tail = Fcons (elt, Qnil);
8939 }
8940 else
8941 {
8942 XSETCDR (result_tail, Fcons (elt, Qnil));
8943 result_tail = XCDR (result_tail);
8944 }
8945
8946 if (ii == ending)
8947 {
8948 break;
8949 }
8950
8951 ii++;
8952 }
8953 END_GC_EXTERNAL_LIST_LOOP (elt);
8954 }
8955 UNGCPRO;
8956
8957 if (ii < starting || (ii < ending && !NILP (end)))
8958 {
8959 check_sequence_range (args[0], start, end, Flength (args[0]));
8960 }
8961
8962 return result;
8963 }
8964
8965 static Lisp_Object
8966 subst (Lisp_Object new_, Lisp_Object old, Lisp_Object tree, int depth)
8967 {
8968 if (depth + lisp_eval_depth > max_lisp_eval_depth)
8969 {
8970 stack_overflow ("Stack overflow in subst", tree);
8971 }
8972
8973 if (EQ (tree, old))
8974 {
8975 return new_;
8976 }
8977 else if (CONSP (tree))
8978 {
8979 Lisp_Object aa = subst (new_, old, XCAR (tree), depth + 1);
8980 Lisp_Object dd = subst (new_, old, XCDR (tree), depth + 1);
8981
8982 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree)))
8983 {
8984 return tree;
8985 }
8986 else
8987 {
8988 return Fcons (aa, dd);
8989 }
8990 }
8991 else
8992 {
8993 return tree;
8994 }
8995 }
8996
8997 static Lisp_Object
8998 sublis (Lisp_Object alist, Lisp_Object tree,
8999 check_test_func_t check_test, Boolint test_not_unboundp,
9000 Lisp_Object test, Lisp_Object key, int depth)
9001 {
9002 Lisp_Object keyed = KEY (key, tree), aa, dd;
9003
9004 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9005 {
9006 stack_overflow ("Stack overflow in sublis", tree);
9007 }
9008
9009 {
9010 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9011 {
9012 if (CONSP (elt) &&
9013 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9014 {
9015 XUNGCPRO (elt);
9016 return XCDR (elt);
9017 }
9018 }
9019 END_GC_EXTERNAL_LIST_LOOP (elt);
9020 }
9021
9022 if (!CONSP (tree))
9023 {
9024 return tree;
9025 }
9026
9027 aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key,
9028 depth + 1);
9029 dd = sublis (alist, XCDR (tree), check_test, test_not_unboundp, test, key,
9030 depth + 1);
9031
9032 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree)))
9033 {
9034 return tree;
9035 }
9036
9037 return Fcons (aa, dd);
9038 }
9039
9040 DEFUN ("sublis", Fsublis, 2, MANY, 0, /*
9041 Perform substitutions indicated by ALIST in TREE (non-destructively).
9042 Return a copy of TREE with all matching elements replaced.
9043
9044 See `member*' for the meaning of :test, :test-not and :key.
9045
9046 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9047 */
9048 (int nargs, Lisp_Object *args))
9049 {
9050 Lisp_Object alist = args[0], tree = args[1];
9051 Boolint test_not_unboundp = 1;
9052 check_test_func_t check_test = NULL;
9053
9054 PARSE_KEYWORDS (Fsublis, nargs, args, 5, (test, if_, test_not, if_not, key),
9055 (key = Qidentity));
9056
9057 if (NILP (key))
9058 {
9059 key = Qidentity;
9060 }
9061
9062 get_check_match_function (&test, test_not, if_, if_not,
9063 /* sublis() is going to apply the key, don't ask
9064 for a match function that will do it for
9065 us. */
9066 Qidentity, &test_not_unboundp, &check_test);
9067
9068 if (CONSP (alist) && NILP (XCDR (alist)) && CONSP (XCAR (alist))
9069 && EQ (key, Qidentity) && 1 == test_not_unboundp
9070 && (check_eq_nokey == check_test ||
9071 (check_eql_nokey == check_test &&
9072 !NON_FIXNUM_NUMBER_P (XCAR (XCAR (alist))))))
9073 {
9074 /* #'subst with #'eq is very cheap indeed; call it. */
9075 return subst (XCDR (XCAR (alist)), XCAR (XCAR (alist)), tree, 0);
9076 }
9077
9078 return sublis (alist, tree, check_test, test_not_unboundp, test, key, 0);
9079 }
9080
9081 static Lisp_Object
9082 nsublis (Lisp_Object alist, Lisp_Object tree,
9083 check_test_func_t check_test,
9084 Boolint test_not_unboundp,
9085 Lisp_Object test, Lisp_Object key, int depth)
9086 {
9087 Lisp_Object tree_saved = tree, tortoise = tree, keyed = Qnil;
9088 struct gcpro gcpro1, gcpro2;
9089 int count = 0;
9090
9091 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9092 {
9093 stack_overflow ("Stack overflow in nsublis", tree);
9094 }
9095
9096 GCPRO2 (tree_saved, keyed);
9097
9098 while (CONSP (tree))
9099 {
9100 Boolint replaced = 0;
9101 keyed = KEY (key, XCAR (tree));
9102
9103 {
9104 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9105 {
9106 if (CONSP (elt) &&
9107 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9108 {
9109 CHECK_LISP_WRITEABLE (tree);
9110 /* See comment in sublis() on using elt_cdr. */
9111 XSETCAR (tree, XCDR (elt));
9112 replaced = 1;
9113 break;
9114 }
9115 }
9116 END_GC_EXTERNAL_LIST_LOOP (elt);
9117 }
9118
9119 if (!replaced)
9120 {
9121 if (CONSP (XCAR (tree)))
9122 {
9123 nsublis (alist, XCAR (tree), check_test, test_not_unboundp,
9124 test, key, depth + 1);
9125 }
9126 }
9127
9128 keyed = KEY (key, XCDR (tree));
9129 replaced = 0;
9130
9131 {
9132 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9133 {
9134 if (CONSP (elt) &&
9135 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9136 {
9137 CHECK_LISP_WRITEABLE (tree);
9138 XSETCDR (tree, XCDR (elt));
9139 tree = Qnil;
9140 break;
9141 }
9142 }
9143 END_GC_EXTERNAL_LIST_LOOP (elt);
9144 }
9145
9146 if (!NILP (tree))
9147 {
9148 tree = XCDR (tree);
9149 }
9150
9151 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH)
9152 {
9153 if (count & 1)
9154 {
9155 tortoise = XCDR (tortoise);
9156 }
9157
9158 if (EQ (tortoise, tree))
9159 {
9160 signal_circular_list_error (tree);
9161 }
9162 }
9163 }
9164
9165 RETURN_UNGCPRO (tree_saved);
9166 }
9167
9168 DEFUN ("nsublis", Fnsublis, 2, MANY, 0, /*
9169 Perform substitutions indicated by ALIST in TREE (destructively).
9170 Any matching element of TREE is changed via a call to `setcar'.
9171
9172 See `member*' for the meaning of :test, :test-not and :key.
9173
9174 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9175 */
9176 (int nargs, Lisp_Object *args))
9177 {
9178 Lisp_Object alist = args[0], tree = args[1], tailed = Qnil, keyed = Qnil;
9179 Boolint test_not_unboundp = 1;
9180 check_test_func_t check_test = NULL;
9181 struct gcpro gcpro1, gcpro2;
9182
9183 PARSE_KEYWORDS (Fnsublis, nargs, args, 5, (test, if_, test_not, if_not, key),
9184 (key = Qidentity));
9185
9186 if (NILP (key))
9187 {
9188 key = Qidentity;
9189 }
9190
9191 get_check_match_function (&test, test_not, if_, if_not,
9192 /* nsublis() is going to apply the key, don't ask
9193 for a match function that will do it for
9194 us. */
9195 Qidentity, &test_not_unboundp, &check_test);
9196
9197 GCPRO2 (tailed, keyed);
9198
9199 keyed = KEY (key, tree);
9200
9201 {
9202 /* nsublis() won't attempt to replace a cons handed to it, do that
9203 ourselves. */
9204 GC_EXTERNAL_LIST_LOOP_2 (elt, alist)
9205 {
9206 if (CONSP (elt) &&
9207 check_test (test, key, XCAR (elt), keyed) == test_not_unboundp)
9208 {
9209 XUNGCPRO (elt);
9210 return XCDR (elt);
9211 }
9212 }
9213 END_GC_EXTERNAL_LIST_LOOP (elt);
9214 }
9215
9216 UNGCPRO;
9217
9218 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0);
9219 }
9220
9221 DEFUN ("subst", Fsubst, 3, MANY, 0, /*
9222 Substitute NEW for OLD everywhere in TREE (non-destructively).
9223
9224 Return a copy of TREE with all elements `eql' to OLD replaced by NEW.
9225
9226 See `member*' for the meaning of :test, :test-not and :key.
9227
9228 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9229 */
9230 (int nargs, Lisp_Object *args))
9231 {
9232 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]),
9233 Qnil);
9234 args[1] = alist;
9235 result = Fsublis (nargs - 1, args + 1);
9236 free_cons (XCAR (alist));
9237 free_cons (alist);
9238
9239 return result;
9240 }
9241
9242 DEFUN ("nsubst", Fnsubst, 3, MANY, 0, /*
9243 Substitute NEW for OLD everywhere in TREE (destructively).
9244
9245 Any element of TREE which is `eql' to OLD is changed to NEW (via a call to
9246 `setcar').
9247
9248 See `member*' for the meaning of the keywords. The keyword
9249 :descend-structures, not specified by Common Lisp, allows callers to specify
9250 that non-cons objects (vectors and range tables, among others) should also
9251 undergo substitution.
9252
9253 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT DESCEND-STRUCTURES)
9254 */
9255 (int nargs, Lisp_Object *args))
9256 {
9257 Lisp_Object new_ = args[0], old = args[1], tree = args[2], result, alist;
9258 Boolint test_not_unboundp = 1;
9259 check_test_func_t check_test = NULL;
9260
9261 PARSE_KEYWORDS (Fnsubst, nargs, args, 6, (test, if_, test_not, if_not, key,
9262 descend_structures), NULL);
9263 if (!NILP (descend_structures))
9264 {
9265 check_test = get_check_test_function (old, &test, test_not, if_, if_not,
9266 key, &test_not_unboundp);
9267
9268 return nsubst_structures (new_, old, tree, check_test, test_not_unboundp,
9269 test, key);
9270
9271 }
9272
9273 alist = noseeum_cons (noseeum_cons (old, new_), Qnil);
9274 args[1] = alist;
9275 result = Fnsublis (nargs - 1, args + 1);
9276 free_cons (XCAR (alist));
9277 free_cons (alist);
9278
9279 return result;
9280 }
9281
9282 static Boolint
9283 tree_equal (Lisp_Object tree1, Lisp_Object tree2,
9284 check_test_func_t check_test, Boolint test_not_unboundp,
9285 Lisp_Object test, Lisp_Object key, int depth)
9286 {
9287 Lisp_Object tortoise1 = tree1, tortoise2 = tree2;
9288 struct gcpro gcpro1, gcpro2;
9289 int count = 0;
9290 Boolint result;
9291
9292 if (depth + lisp_eval_depth > max_lisp_eval_depth)
9293 {
9294 stack_overflow ("Stack overflow in tree-equal", tree1);
9295 }
9296
9297 GCPRO2 (tree1, tree2);
9298
9299 while (CONSP (tree1) && CONSP (tree2)
9300 && tree_equal (XCAR (tree1), XCAR (tree2), check_test,
9301 test_not_unboundp, test, key, depth + 1))
9302 {
9303 tree1 = XCDR (tree1);
9304 tree2 = XCDR (tree2);
9305
9306 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH)
9307 {
9308 if (count & 1)
9309 {
9310 tortoise1 = XCDR (tortoise1);
9311 tortoise2 = XCDR (tortoise2);
9312 }
9313
9314 if (EQ (tortoise1, tree1))
9315 {
9316 signal_circular_list_error (tree1);
9317 }
9318
9319 if (EQ (tortoise2, tree2))
9320 {
9321 signal_circular_list_error (tree2);
9322 }
9323 }
9324 }
9325
9326 if (CONSP (tree1) || CONSP (tree2))
9327 {
9328 UNGCPRO;
9329 return 0;
9330 }
9331
9332 result = check_test (test, key, tree1, tree2) == test_not_unboundp;
9333 UNGCPRO;
9334
9335 return result;
9336 }
9337
9338 DEFUN ("tree-equal", Ftree_equal, 2, MANY, 0, /*
9339 Return t if TREE1 and TREE2 have `eql' leaves.
9340
9341 Atoms are compared by `eql', unless another test is specified using
9342 :test; cons cells are compared recursively.
9343
9344 See `union' for the meaning of :test, :test-not and :key.
9345
9346 arguments: (TREE1 TREE2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
9347 */
9348 (int nargs, Lisp_Object *args))
9349 {
9350 Lisp_Object tree1 = args[0], tree2 = args[1];
9351 Boolint test_not_unboundp = 1;
9352 check_test_func_t check_test = NULL;
9353
9354 PARSE_KEYWORDS (Ftree_equal, nargs, args, 3, (test, key, test_not),
9355 (key = Qidentity));
9356
9357 get_check_match_function (&test, test_not, Qnil, Qnil, key,
9358 &test_not_unboundp, &check_test);
9359
9360 return tree_equal (tree1, tree2, check_test, test_not_unboundp, test, key,
9361 0) ? Qt : Qnil;
9362 }
9363
9364 static Lisp_Object
9365 mismatch_from_end (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1,
9366 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2,
9367 check_test_func_t check_match, Boolint test_not_unboundp,
9368 Lisp_Object test, Lisp_Object key,
9369 Boolint UNUSED (return_sequence1_index))
9370 {
9371 Elemcount sequence1_len = XFIXNUM (Flength (sequence1));
9372 Elemcount sequence2_len = XFIXNUM (Flength (sequence2)), ii = 0;
9373 Elemcount starting1, ending1, starting2, ending2;
9374 Lisp_Object *sequence1_storage = NULL, *sequence2_storage = NULL;
9375 struct gcpro gcpro1, gcpro2;
9376
9377 check_sequence_range (sequence1, start1, end1, make_fixnum (sequence1_len));
9378 starting1 = XFIXNUM (start1);
9379 ending1 = FIXNUMP (end1) ? XFIXNUM (end1) : 1 + MOST_POSITIVE_FIXNUM;
9380 ending1 = min (ending1, sequence1_len);
9381
9382 check_sequence_range (sequence2, start2, end2, make_fixnum (sequence2_len));
9383 starting2 = XFIXNUM (start2);
9384 ending2 = FIXNUMP (end2) ? XFIXNUM (end2) : 1 + MOST_POSITIVE_FIXNUM;
9385 ending2 = min (ending2, sequence2_len);
9386
9387 if (LISTP (sequence1))
9388 {
9389 Lisp_Object *saving;
9390 sequence1_storage = saving
9391 = alloca_array (Lisp_Object, ending1 - starting1);
9392
9393 {
9394 EXTERNAL_LIST_LOOP_2 (elt, sequence1)
9395 {
9396 if (starting1 <= ii && ii < ending1)
9397 {
9398 *saving++ = elt;
9399 }
9400 else if (ii == ending1)
9401 {
9402 break;
9403 }
9404
9405 ++ii;
9406 }
9407 }
9408 }
9409 else if (STRINGP (sequence1))
9410 {
9411 const Ibyte *cursor = string_char_addr (sequence1, starting1);
9412
9413 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence1_storage, ii,
9414 ending1 - starting1);
9415
9416 }
9417 else if (BIT_VECTORP (sequence1))
9418 {
9419 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence1);
9420 sequence1_storage = alloca_array (Lisp_Object, ending1 - starting1);
9421 for (ii = starting1; ii < ending1; ++ii)
9422 {
9423 sequence1_storage[ii - starting1]
9424 = make_fixnum (bit_vector_bit (vv, ii));
9425 }
9426 }
9427 else
9428 {
9429 sequence1_storage = XVECTOR_DATA (sequence1) + starting1;
9430 }
9431
9432 ii = 0;
9433
9434 if (LISTP (sequence2))
9435 {
9436 Lisp_Object *saving;
9437 sequence2_storage = saving
9438 = alloca_array (Lisp_Object, ending2 - starting2);
9439
9440 {
9441 EXTERNAL_LIST_LOOP_2 (elt, sequence2)
9442 {
9443 if (starting2 <= ii && ii < ending2)
9444 {
9445 *saving++ = elt;
9446 }
9447 else if (ii == ending2)
9448 {
9449 break;
9450 }
9451
9452 ++ii;
9453 }
9454 }
9455 }
9456 else if (STRINGP (sequence2))
9457 {
9458 const Ibyte *cursor = string_char_addr (sequence2, starting2);
9459
9460 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence2_storage, ii,
9461 ending2 - starting2);
9462
9463 }
9464 else if (BIT_VECTORP (sequence2))
9465 {
9466 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence2);
9467 sequence2_storage = alloca_array (Lisp_Object, ending2 - starting2);
9468 for (ii = starting2; ii < ending2; ++ii)
9469 {
9470 sequence2_storage[ii - starting2]
9471 = make_fixnum (bit_vector_bit (vv, ii));
9472 }
9473 }
9474 else
9475 {
9476 sequence2_storage = XVECTOR_DATA (sequence2) + starting2;
9477 }
9478
9479 GCPRO2 (sequence1_storage[0], sequence2_storage[0]);
9480 gcpro1.nvars = ending1 - starting1;
9481 gcpro2.nvars = ending2 - starting2;
9482
9483 while (ending1 > starting1 && ending2 > starting2)
9484 {
9485 --ending1;
9486 --ending2;
9487
9488 if (check_match (test, key, sequence1_storage[ending1 - starting1],
9489 sequence2_storage[ending2 - starting2])
9490 != test_not_unboundp)
9491 {
9492 UNGCPRO;
9493 return make_integer (ending1 + 1);
9494 }
9495 }
9496
9497 UNGCPRO;
9498
9499 if (ending1 > starting1 || ending2 > starting2)
9500 {
9501 return make_integer (ending1);
9502 }
9503
9504 return Qnil;
9505 }
9506
9507 static Lisp_Object
9508 mismatch_list_list (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_list_index))
9513 {
9514 Lisp_Object sequence1_tortoise = sequence1, sequence2_tortoise = sequence2;
9515 Lisp_Object orig_sequence1 = sequence1, orig_sequence2 = sequence2;
9516 Elemcount ending1 = MOST_POSITIVE_FIXNUM, ending2 = MOST_POSITIVE_FIXNUM;
9517 Elemcount starting1, starting2, counting, startcounting;
9518 Elemcount shortest_len = 0;
9519 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
9520
9521 starting1 = FIXNUMP (start1) ? XFIXNUM (start1) : 1 + MOST_POSITIVE_FIXNUM;
9522 starting2 = FIXNUMP (start2) ? XFIXNUM (start2) : 1 + MOST_POSITIVE_FIXNUM;
9523
9524 if (!NILP (end1))
9525 {
9526 ending1 = FIXNUMP (end1) ? XFIXNUM (end1) : 1 + MOST_POSITIVE_FIXNUM;
9527 }
9528
9529 if (!NILP (end2))
9530 {
9531 ending2 = FIXNUMP (end2) ? XFIXNUM (end2) : 1 + MOST_POSITIVE_FIXNUM;
9532 }
9533
9534 if (!ZEROP (start1))
9535 {
9536 sequence1 = Fnthcdr (start1, sequence1);
9537
9538 if (NILP (sequence1))
9539 {
9540 check_sequence_range (sequence1_tortoise, start1, end1,
9541 Flength (sequence1_tortoise));
9542 /* Give up early here. */
9543 return Qnil;
9544 }
9545
9546 ending1 -= starting1;
9547 starting1 = 0;
9548 sequence1_tortoise = sequence1;
9549 }
9550
9551 if (!ZEROP (start2))
9552 {
9553 sequence2 = Fnthcdr (start2, sequence2);
9554
9555 if (NILP (sequence2))
9556 {
9557 check_sequence_range (sequence2_tortoise, start2, end2,
9558 Flength (sequence2_tortoise));
9559 return Qnil;
9560 }
9561
9562 ending2 -= starting2;
9563 starting2 = 0;
9564 sequence2_tortoise = sequence2;
9565 }
9566
9567 GCPRO4 (sequence1, sequence2, sequence1_tortoise, sequence2_tortoise);
9568
9569 counting = startcounting = min (ending1, ending2);
9570
9571 while (counting-- > 0 && !NILP (sequence1) && !NILP (sequence2))
9572 {
9573 if (check_match (test, key,
9574 CONSP (sequence1) ? XCAR (sequence1)
9575 : Fcar (sequence1),
9576 CONSP (sequence2) ? XCAR (sequence2)
9577 : Fcar (sequence2) ) != test_not_unboundp)
9578 {
9579 UNGCPRO;
9580 return make_integer (XFIXNUM (start1) + shortest_len);
9581 }
9582
9583 sequence1 = CONSP (sequence1) ? XCDR (sequence1) : Fcdr (sequence1);
9584 sequence2 = CONSP (sequence2) ? XCDR (sequence2) : Fcdr (sequence2);
9585
9586 shortest_len++;
9587
9588 if (startcounting - counting > CIRCULAR_LIST_SUSPICION_LENGTH)
9589 {
9590 if (counting & 1)
9591 {
9592 sequence1_tortoise = XCDR (sequence1_tortoise);
9593 sequence2_tortoise = XCDR (sequence2_tortoise);
9594 }
9595
9596 if (EQ (sequence1, sequence1_tortoise))
9597 {
9598 signal_circular_list_error (sequence1);
9599 }
9600
9601 if (EQ (sequence2, sequence2_tortoise))
9602 {
9603 signal_circular_list_error (sequence2);
9604 }
9605 }
9606 }
9607
9608 UNGCPRO;
9609
9610 if (NILP (sequence1))
9611 {
9612 Lisp_Object args[] = { start1, make_fixnum (shortest_len) };
9613 check_sequence_range (orig_sequence1, start1, end1,
9614 Fplus (countof (args), args));
9615 }
9616
9617 if (NILP (sequence2))
9618 {
9619 Lisp_Object args[] = { start2, make_fixnum (shortest_len) };
9620 check_sequence_range (orig_sequence2, start2, end2,
9621 Fplus (countof (args), args));
9622 }
9623
9624 if ((!NILP (end1) && shortest_len != ending1 - starting1) ||
9625 (!NILP (end2) && shortest_len != ending2 - starting2))
9626 {
9627 return make_integer (XFIXNUM (start1) + shortest_len);
9628 }
9629
9630 if ((NILP (end1) && CONSP (sequence1)) || (NILP (end2) && CONSP (sequence2)))
9631 {
9632 return make_integer (XFIXNUM (start1) + shortest_len);
9633 }
9634
9635 return Qnil;
9636 }
9637
9638 static Lisp_Object
9639 mismatch_list_string (Lisp_Object list, Lisp_Object list_start,
9640 Lisp_Object list_end,
9641 Lisp_Object string, Lisp_Object string_start,
9642 Lisp_Object string_end,
9643 check_test_func_t check_match,
9644 Boolint test_not_unboundp,
9645 Lisp_Object test, Lisp_Object key,
9646 Boolint return_list_index)
9647 {
9648 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data;
9649 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string);
9650 Elemcount char_count = 0, list_starting, list_ending;
9651 Elemcount string_starting, string_ending;
9652 Lisp_Object character, orig_list = list;
9653 struct gcpro gcpro1;
9654
9655 list_ending = FIXNUMP (list_end) ? XFIXNUM (list_end) : 1 + MOST_POSITIVE_FIXNUM;
9656 list_starting = FIXNUMP (list_start) ? XFIXNUM (list_start) : 1 + MOST_POSITIVE_FIXNUM;
9657
9658 string_ending = FIXNUMP (string_end) ? XFIXNUM (string_end) : 1 + MOST_POSITIVE_FIXNUM;
9659 string_starting
9660 = FIXNUMP (string_start) ? XFIXNUM (string_start) : 1 + MOST_POSITIVE_FIXNUM;
9661
9662 while (char_count < string_starting && string_offset < string_len)
9663 {
9664 INC_IBYTEPTR (string_data);
9665 string_offset = string_data - startp;
9666 char_count++;
9667 }
9668
9669 if (!ZEROP (list_start))
9670 {
9671 list = Fnthcdr (list_start, list);
9672 if (NILP (list))
9673 {
9674 check_sequence_range (orig_list, list_start, list_end,
9675 Flength (orig_list));
9676 return Qnil;
9677 }
9678
9679 list_ending -= list_starting;
9680 list_starting = 0;
9681 }
9682
9683 GCPRO1 (list);
9684
9685 while (list_starting < list_ending && string_starting < string_ending
9686 && string_offset < string_len && !NILP (list))
9687 {
9688 character = make_char (itext_ichar (string_data));
9689
9690 if (return_list_index)
9691 {
9692 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list),
9693 character)
9694 != test_not_unboundp)
9695 {
9696 UNGCPRO;
9697 return make_integer (XFIXNUM (list_start) + char_count);
9698 }
9699 }
9700 else
9701 {
9702 if (check_match (test, key, character,
9703 CONSP (list) ? XCAR (list) : Fcar (list))
9704 != test_not_unboundp)
9705 {
9706 UNGCPRO;
9707 return make_integer (char_count);
9708 }
9709 }
9710
9711 list = CONSP (list) ? XCDR (list) : Fcdr (list);
9712
9713 startp = XSTRING_DATA (string);
9714 string_data = startp + string_offset;
9715 if (string_len != XSTRING_LENGTH (string)
9716 || !valid_ibyteptr_p (string_data))
9717 {
9718 mapping_interaction_error (Qmismatch, string);
9719 }
9720
9721 list_starting++;
9722 string_starting++;
9723 char_count++;
9724 INC_IBYTEPTR (string_data);
9725 string_offset = string_data - startp;
9726 }
9727
9728 UNGCPRO;
9729
9730 if (NILP (list))
9731 {
9732 Lisp_Object args[] = { list_start, make_fixnum (char_count) };
9733 check_sequence_range (orig_list, list_start, list_end,
9734 Fplus (countof (args), args));
9735 }
9736
9737 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string))
9738 {
9739 check_sequence_range (string, string_start, string_end,
9740 make_fixnum (char_count));
9741 }
9742
9743 if ((NILP (string_end) ?
9744 string_offset < string_len : string_starting < string_ending) ||
9745 (NILP (list_end) ? !NILP (list) : list_starting < list_ending))
9746 {
9747 return make_integer (return_list_index ? XFIXNUM (list_start) + char_count :
9748 char_count);
9749 }
9750
9751 return Qnil;
9752 }
9753
9754 static Lisp_Object
9755 mismatch_list_array (Lisp_Object list, Lisp_Object list_start,
9756 Lisp_Object list_end,
9757 Lisp_Object array, Lisp_Object array_start,
9758 Lisp_Object array_end,
9759 check_test_func_t check_match,
9760 Boolint test_not_unboundp,
9761 Lisp_Object test, Lisp_Object key,
9762 Boolint return_list_index)
9763 {
9764 Elemcount ii = 0, list_starting, list_ending;
9765 Elemcount array_starting, array_ending, array_len;
9766 Lisp_Object orig_list = list;
9767 struct gcpro gcpro1;
9768
9769 list_ending = FIXNUMP (list_end) ? XFIXNUM (list_end) : 1 + MOST_POSITIVE_FIXNUM;
9770 list_starting = FIXNUMP (list_start) ? XFIXNUM (list_start) : 1 + MOST_POSITIVE_FIXNUM;
9771
9772 array_ending = FIXNUMP (array_end) ? XFIXNUM (array_end) : 1 + MOST_POSITIVE_FIXNUM;
9773 array_starting = FIXNUMP (array_start) ? XFIXNUM (array_start) : 1 + MOST_POSITIVE_FIXNUM;
9774 array_len = XFIXNUM (Flength (array));
9775
9776 array_ending = min (array_ending, array_len);
9777
9778 check_sequence_range (array, array_start, array_end, make_fixnum (array_len));
9779
9780 if (!ZEROP (list_start))
9781 {
9782 list = Fnthcdr (list_start, list);
9783 if (NILP (list))
9784 {
9785 check_sequence_range (orig_list, list_start, list_end,
9786 Flength (orig_list));
9787 return Qnil;
9788 }
9789
9790 list_ending -= list_starting;
9791 list_starting = 0;
9792 }
9793
9794 GCPRO1 (list);
9795
9796 while (list_starting < list_ending && array_starting < array_ending
9797 && !NILP (list))
9798 {
9799 if (return_list_index)
9800 {
9801 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list),
9802 Faref (array, make_fixnum (array_starting)))
9803 != test_not_unboundp)
9804 {
9805 UNGCPRO;
9806 return make_integer (XFIXNUM (list_start) + ii);
9807 }
9808 }
9809 else
9810 {
9811 if (check_match (test, key, Faref (array, make_fixnum (array_starting)),
9812 CONSP (list) ? XCAR (list) : Fcar (list))
9813 != test_not_unboundp)
9814 {
9815 UNGCPRO;
9816 return make_integer (array_starting);
9817 }
9818 }
9819
9820 list = CONSP (list) ? XCDR (list) : Fcdr (list);
9821 list_starting++;
9822 array_starting++;
9823 ii++;
9824 }
9825
9826 UNGCPRO;
9827
9828 if (NILP (list))
9829 {
9830 Lisp_Object args[] = { list_start, make_fixnum (ii) };
9831 check_sequence_range (orig_list, list_start, list_end,
9832 Fplus (countof (args), args));
9833 }
9834
9835 if (array_starting < array_ending ||
9836 (NILP (list_end) ? !NILP (list) : list_starting < list_ending))
9837 {
9838 return make_integer (return_list_index ? XFIXNUM (list_start) + ii :
9839 array_starting);
9840 }
9841
9842 return Qnil;
9843 }
9844
9845 static Lisp_Object
9846 mismatch_string_array (Lisp_Object string, Lisp_Object string_start,
9847 Lisp_Object string_end,
9848 Lisp_Object array, Lisp_Object array_start,
9849 Lisp_Object array_end,
9850 check_test_func_t check_match, Boolint test_not_unboundp,
9851 Lisp_Object test, Lisp_Object key,
9852 Boolint return_string_index)
9853 {
9854 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data;
9855 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string);
9856 Elemcount char_count = 0, array_starting, array_ending, array_length;
9857 Elemcount string_starting, string_ending;
9858 Lisp_Object character;
9859
9860 array_starting = FIXNUMP (array_start) ? XFIXNUM (array_start) : 1 + MOST_POSITIVE_FIXNUM;
9861 array_ending = FIXNUMP (array_end) ? XFIXNUM (array_end) : 1 + MOST_POSITIVE_FIXNUM;
9862 array_length = XFIXNUM (Flength (array));
9863 check_sequence_range (array, array_start, array_end, make_fixnum (array_length));
9864 array_ending = min (array_ending, array_length);
9865
9866 string_ending = FIXNUMP (string_end) ? XFIXNUM (string_end) : 1 + MOST_POSITIVE_FIXNUM;
9867 string_starting
9868 = FIXNUMP (string_start) ? XFIXNUM (string_start) : 1 + MOST_POSITIVE_FIXNUM;
9869
9870 while (char_count < string_starting && string_offset < string_len)
9871 {
9872 INC_IBYTEPTR (string_data);
9873 string_offset = string_data - startp;
9874 char_count++;
9875 }
9876
9877 while (array_starting < array_ending && string_starting < string_ending
9878 && string_offset < string_len)
9879 {
9880 character = make_char (itext_ichar (string_data));
9881
9882 if (return_string_index)
9883 {
9884 if (check_match (test, key, character,
9885 Faref (array, make_fixnum (array_starting)))
9886 != test_not_unboundp)
9887 {
9888 return make_integer (char_count);
9889 }
9890 }
9891 else
9892 {
9893 if (check_match (test, key,
9894 Faref (array, make_fixnum (array_starting)),
9895 character)
9896 != test_not_unboundp)
9897 {
9898 return make_integer (XFIXNUM (array_start) + char_count);
9899 }
9900 }
9901
9902 startp = XSTRING_DATA (string);
9903 string_data = startp + string_offset;
9904 if (string_len != XSTRING_LENGTH (string)
9905 || !valid_ibyteptr_p (string_data))
9906 {
9907 mapping_interaction_error (Qmismatch, string);
9908 }
9909
9910 array_starting++;
9911 string_starting++;
9912 char_count++;
9913 INC_IBYTEPTR (string_data);
9914 string_offset = string_data - startp;
9915 }
9916
9917 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string))
9918 {
9919 check_sequence_range (string, string_start, string_end,
9920 make_fixnum (char_count));
9921 }
9922
9923 if ((NILP (string_end) ?
9924 string_offset < string_len : string_starting < string_ending) ||
9925 (NILP (array_end) ? !NILP (array) : array_starting < array_ending))
9926 {
9927 return make_integer (return_string_index ? char_count :
9928 XFIXNUM (array_start) + char_count);
9929 }
9930
9931 return Qnil;
9932 }
9933
9934 static Lisp_Object
9935 mismatch_string_string (Lisp_Object string1,
9936 Lisp_Object string1_start, Lisp_Object string1_end,
9937 Lisp_Object string2, Lisp_Object string2_start,
9938 Lisp_Object string2_end,
9939 check_test_func_t check_match,
9940 Boolint test_not_unboundp,
9941 Lisp_Object test, Lisp_Object key,
9942 Boolint UNUSED (return_string1_index))
9943 {
9944 Ibyte *string1_data = XSTRING_DATA (string1), *startp1 = string1_data;
9945 Bytecount string1_offset = 0, string1_len = XSTRING_LENGTH (string1);
9946 Ibyte *string2_data = XSTRING_DATA (string2), *startp2 = string2_data;
9947 Bytecount string2_offset = 0, string2_len = XSTRING_LENGTH (string2);
9948 Elemcount char_count1 = 0, string1_starting, string1_ending;
9949 Elemcount char_count2 = 0, string2_starting, string2_ending;
9950 Lisp_Object character1, character2;
9951
9952 string1_ending = FIXNUMP (string1_end) ? XFIXNUM (string1_end) : 1 + MOST_POSITIVE_FIXNUM;
9953 string1_starting
9954 = FIXNUMP (string1_start) ? XFIXNUM (string1_start) : 1 + MOST_POSITIVE_FIXNUM;
9955
9956 string2_starting
9957 = FIXNUMP (string2_start) ? XFIXNUM (string2_start) : 1 + MOST_POSITIVE_FIXNUM;
9958 string2_ending = FIXNUMP (string2_end) ? XFIXNUM (string2_end) : 1 + MOST_POSITIVE_FIXNUM;
9959
9960 while (char_count1 < string1_starting && string1_offset < string1_len)
9961 {
9962 INC_IBYTEPTR (string1_data);
9963 string1_offset = string1_data - startp1;
9964 char_count1++;
9965 }
9966
9967 while (char_count2 < string2_starting && string2_offset < string2_len)
9968 {
9969 INC_IBYTEPTR (string2_data);
9970 string2_offset = string2_data - startp2;
9971 char_count2++;
9972 }
9973
9974 while (string2_starting < string2_ending && string1_starting < string1_ending
9975 && string1_offset < string1_len && string2_offset < string2_len)
9976 {
9977 character1 = make_char (itext_ichar (string1_data));
9978 character2 = make_char (itext_ichar (string2_data));
9979
9980 if (check_match (test, key, character1, character2)
9981 != test_not_unboundp)
9982 {
9983 return make_integer (char_count1);
9984 }
9985
9986 startp1 = XSTRING_DATA (string1);
9987 string1_data = startp1 + string1_offset;
9988 if (string1_len != XSTRING_LENGTH (string1)
9989 || !valid_ibyteptr_p (string1_data))
9990 {
9991 mapping_interaction_error (Qmismatch, string1);
9992 }
9993
9994 startp2 = XSTRING_DATA (string2);
9995 string2_data = startp2 + string2_offset;
9996 if (string2_len != XSTRING_LENGTH (string2)
9997 || !valid_ibyteptr_p (string2_data))
9998 {
9999 mapping_interaction_error (Qmismatch, string2);
10000 }
10001
10002 string2_starting++;
10003 string1_starting++;
10004 char_count1++;
10005 char_count2++;
10006 INC_IBYTEPTR (string1_data);
10007 string1_offset = string1_data - startp1;
10008 INC_IBYTEPTR (string2_data);
10009 string2_offset = string2_data - startp2;
10010 }
10011
10012 if (string1_data == XSTRING_DATA (string1) + XSTRING_LENGTH (string1))
10013 {
10014 check_sequence_range (string1, string1_start, string1_end,
10015 make_fixnum (char_count1));
10016 }
10017
10018 if (string2_data == XSTRING_DATA (string2) + XSTRING_LENGTH (string2))
10019 {
10020 check_sequence_range (string2, string2_start, string2_end,
10021 make_fixnum (char_count2));
10022 }
10023
10024 if ((!NILP (string1_end) && string1_starting < string1_ending) ||
10025 (!NILP (string2_end) && string2_starting < string2_ending))
10026 {
10027 return make_integer (char_count1);
10028 }
10029
10030 if ((NILP (string1_end) && string1_data
10031 < (XSTRING_DATA (string1) + XSTRING_LENGTH (string1))) ||
10032 (NILP (string2_end) && string2_data
10033 < (XSTRING_DATA (string2) + XSTRING_LENGTH (string2))))
10034 {
10035 return make_integer (char_count1);
10036 }
10037
10038 return Qnil;
10039 }
10040
10041 static Lisp_Object
10042 mismatch_array_array (Lisp_Object array1, Lisp_Object start1, Lisp_Object end1,
10043 Lisp_Object array2, Lisp_Object start2, Lisp_Object end2,
10044 check_test_func_t check_match, Boolint test_not_unboundp,
10045 Lisp_Object test, Lisp_Object key,
10046 Boolint UNUSED (return_array1_index))
10047 {
10048 Elemcount len1 = XFIXNUM (Flength (array1)), len2 = XFIXNUM (Flength (array2));
10049 Elemcount ending1 = MOST_POSITIVE_FIXNUM, ending2 = MOST_POSITIVE_FIXNUM;
10050 Elemcount starting1, starting2;
10051
10052 check_sequence_range (array1, start1, end1, make_fixnum (len1));
10053 check_sequence_range (array2, start2, end2, make_fixnum (len2));
10054
10055 starting1 = FIXNUMP (start1) ? XFIXNUM (start1) : 1 + MOST_POSITIVE_FIXNUM;
10056 starting2 = FIXNUMP (start2) ? XFIXNUM (start2) : 1 + MOST_POSITIVE_FIXNUM;
10057
10058 if (!NILP (end1))
10059 {
10060 ending1 = FIXNUMP (end1) ? XFIXNUM (end1) : 1 + MOST_POSITIVE_FIXNUM;
10061 }
10062
10063 if (!NILP (end2))
10064 {
10065 ending2 = FIXNUMP (end2) ? XFIXNUM (end2) : 1 + MOST_POSITIVE_FIXNUM;
10066 }
10067
10068 ending1 = min (ending1, len1);
10069 ending2 = min (ending2, len2);
10070
10071 while (starting1 < ending1 && starting2 < ending2)
10072 {
10073 if (check_match (test, key, Faref (array1, make_fixnum (starting1)),
10074 Faref (array2, make_fixnum (starting2)))
10075 != test_not_unboundp)
10076 {
10077 return make_integer (starting1);
10078 }
10079 starting1++;
10080 starting2++;
10081 }
10082
10083 if (starting1 < ending1 || starting2 < ending2)
10084 {
10085 return make_integer (starting1);
10086 }
10087
10088 return Qnil;
10089 }
10090
10091 typedef Lisp_Object
10092 (*mismatch_func_t) (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1,
10093 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2,
10094 check_test_func_t check_match, Boolint test_not_unboundp,
10095 Lisp_Object test, Lisp_Object key,
10096 Boolint return_list_index);
10097
10098 static mismatch_func_t
10099 get_mismatch_func (Lisp_Object sequence1, Lisp_Object sequence2,
10100 Lisp_Object from_end, Boolint *return_sequence1_index_out)
10101 {
10102 CHECK_SEQUENCE (sequence1);
10103 CHECK_SEQUENCE (sequence2);
10104
10105 if (!NILP (from_end))
10106 {
10107 *return_sequence1_index_out = 1;
10108 return mismatch_from_end;
10109 }
10110
10111 if (LISTP (sequence1))
10112 {
10113 if (LISTP (sequence2))
10114 {
10115 *return_sequence1_index_out = 1;
10116 return mismatch_list_list;
10117 }
10118
10119 if (STRINGP (sequence2))
10120 {
10121 *return_sequence1_index_out = 1;
10122 return mismatch_list_string;
10123 }
10124
10125 *return_sequence1_index_out = 1;
10126 return mismatch_list_array;
10127 }
10128
10129 if (STRINGP (sequence1))
10130 {
10131 if (STRINGP (sequence2))
10132 {
10133 *return_sequence1_index_out = 1;
10134 return mismatch_string_string;
10135 }
10136
10137 if (LISTP (sequence2))
10138 {
10139 *return_sequence1_index_out = 0;
10140 return mismatch_list_string;
10141 }
10142
10143 *return_sequence1_index_out = 1;
10144 return mismatch_string_array;
10145 }
10146
10147 if (ARRAYP (sequence1))
10148 {
10149 if (STRINGP (sequence2))
10150 {
10151 *return_sequence1_index_out = 0;
10152 return mismatch_string_array;
10153 }
10154
10155 if (LISTP (sequence2))
10156 {
10157 *return_sequence1_index_out = 0;
10158 return mismatch_list_array;
10159 }
10160
10161 *return_sequence1_index_out = 1;
10162 return mismatch_array_array;
10163 }
10164
10165 RETURN_NOT_REACHED (NULL);
10166 return NULL;
10167 }
10168
10169 DEFUN ("mismatch", Fmismatch, 2, MANY, 0, /*
10170 Compare SEQUENCE1 with SEQUENCE2, return index of first mismatching element.
10171
10172 Return nil if the sequences match. If one sequence is a prefix of the
10173 other, the return value indicates the end of the shorter sequence. A
10174 non-nil return value always reflects an index into SEQUENCE1.
10175
10176 See `search' for the meaning of the keywords."
10177
10178 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT)
10179 */
10180 (int nargs, Lisp_Object *args))
10181 {
10182 Lisp_Object sequence1 = args[0], sequence2 = args[1];
10183 Boolint test_not_unboundp = 1, return_first_index = 0;
10184 check_test_func_t check_match = NULL;
10185 mismatch_func_t mismatch = NULL;
10186
10187 PARSE_KEYWORDS (Fmismatch, nargs, args, 8,
10188 (test, key, from_end, start1, end1, start2, end2, test_not),
10189 (start1 = start2 = Qzero));
10190
10191 CHECK_SEQUENCE (sequence1);
10192 CHECK_SEQUENCE (sequence2);
10193
10194 CHECK_NATNUM (start1);
10195 CHECK_NATNUM (start2);
10196
10197 if (!NILP (end1))
10198 {
10199 CHECK_NATNUM (end1);
10200 }
10201
10202 if (!NILP (end2))
10203 {
10204 CHECK_NATNUM (end2);
10205 }
10206
10207 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10208 &test_not_unboundp, NULL);
10209 mismatch = get_mismatch_func (sequence1, sequence2, from_end,
10210 &return_first_index);
10211
10212 if (return_first_index)
10213 {
10214 return mismatch (sequence1, start1, end1, sequence2, start2, end2,
10215 check_match, test_not_unboundp, test, key, 1);
10216 }
10217
10218 return mismatch (sequence2, start2, end2, sequence1, start1, end1,
10219 check_match, test_not_unboundp, test, key, 0);
10220 }
10221
10222 DEFUN ("search", Fsearch, 2, MANY, 0, /*
10223 Search for SEQUENCE1 as a subsequence of SEQUENCE2.
10224
10225 Return the index of the leftmost element of the first match found; return
10226 nil if there are no matches.
10227
10228 In this function, :start1 and :end1 specify a subsequence of SEQUENCE1, and
10229 :start2 and :end2 specify a subsequence of SEQUENCE2. See `remove*' for
10230 details of the other keywords.
10231
10232 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT)
10233 */
10234 (int nargs, Lisp_Object *args))
10235 {
10236 Lisp_Object sequence1 = args[0], sequence2 = args[1], position0 = Qnil;
10237 Boolint test_not_unboundp = 1, return_first = 0;
10238 check_test_func_t check_test = NULL, check_match = NULL;
10239 mismatch_func_t mismatch = NULL;
10240 Elemcount starting1 = 0, ending1 = 1 + MOST_POSITIVE_FIXNUM, starting2 = 0;
10241 Elemcount ending2 = 1 + MOST_POSITIVE_FIXNUM, ii = 0;
10242 Elemcount length1;
10243 Lisp_Object object = Qnil;
10244 struct gcpro gcpro1, gcpro2;
10245
10246 PARSE_KEYWORDS (Fsearch, nargs, args, 8,
10247 (test, key, from_end, start1, end1, start2, end2, test_not),
10248 (start1 = start2 = Qzero));
10249
10250 CHECK_SEQUENCE (sequence1);
10251 CHECK_SEQUENCE (sequence2);
10252 CHECK_KEY_ARGUMENT (key);
10253
10254 CHECK_NATNUM (start1);
10255 starting1 = FIXNUMP (start1) ? XFIXNUM (start1) : 1 + MOST_POSITIVE_FIXNUM;
10256 CHECK_NATNUM (start2);
10257 starting2 = FIXNUMP (start2) ? XFIXNUM (start2) : 1 + MOST_POSITIVE_FIXNUM;
10258
10259 if (!NILP (end1))
10260 {
10261 Lisp_Object len1 = Flength (sequence1);
10262
10263 CHECK_NATNUM (end1);
10264 check_sequence_range (sequence1, start1, end1, len1);
10265 ending1 = min (XFIXNUM (end1), XFIXNUM (len1));
10266 }
10267 else
10268 {
10269 end1 = Flength (sequence1);
10270 check_sequence_range (sequence1, start1, end1, end1);
10271 ending1 = XFIXNUM (end1);
10272 }
10273
10274 length1 = ending1 - starting1;
10275
10276 if (!NILP (end2))
10277 {
10278 Lisp_Object len2 = Flength (sequence2);
10279
10280 CHECK_NATNUM (end2);
10281 check_sequence_range (sequence2, start2, end2, len2);
10282 ending2 = min (XFIXNUM (end2), XFIXNUM (len2));
10283 }
10284 else
10285 {
10286 end2 = Flength (sequence2);
10287 check_sequence_range (sequence2, start2, end2, end2);
10288 ending2 = XFIXNUM (end2);
10289 }
10290
10291 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10292 &test_not_unboundp, &check_test);
10293 mismatch = get_mismatch_func (sequence1, sequence2, from_end, &return_first);
10294
10295 if (bytecode_arithcompare (start1, make_integer (ending1)) >= 0)
10296 {
10297 if (NILP (from_end))
10298 {
10299 return start2;
10300 }
10301
10302 if (NILP (end2))
10303 {
10304 return Flength (sequence2);
10305 }
10306
10307 return end2;
10308 }
10309
10310 if (NILP (from_end))
10311 {
10312 Lisp_Object mismatch_start1 = Fadd1 (start1);
10313 Lisp_Object first = KEY (key, Felt (sequence1, start1));
10314 GCPRO2 (first, mismatch_start1);
10315
10316 ii = starting2;
10317 while (ii < ending2)
10318 {
10319 position0 = position (&object, first, sequence2, check_test,
10320 test_not_unboundp, test, key, make_fixnum (ii),
10321 end2, Qnil, Qnil, Qsearch);
10322 if (NILP (position0))
10323 {
10324 UNGCPRO;
10325 return Qnil;
10326 }
10327
10328 if (length1 + XFIXNUM (position0) <= ending2 &&
10329 (return_first ?
10330 NILP (mismatch (sequence1, mismatch_start1, end1,
10331 sequence2,
10332 make_fixnum (1 + XFIXNUM (position0)),
10333 make_fixnum (length1 + XFIXNUM (position0)),
10334 check_match, test_not_unboundp, test, key, 1)) :
10335 NILP (mismatch (sequence2,
10336 make_fixnum (1 + XFIXNUM (position0)),
10337 make_fixnum (length1 + XFIXNUM (position0)),
10338 sequence1, mismatch_start1, end1,
10339 check_match, test_not_unboundp, test, key, 0))))
10340
10341
10342 {
10343 UNGCPRO;
10344 return position0;
10345 }
10346
10347 ii = XFIXNUM (position0) + 1;
10348 }
10349
10350 UNGCPRO;
10351 }
10352 else
10353 {
10354 Lisp_Object mismatch_end1 = make_integer (ending1 - 1);
10355 Lisp_Object last = KEY (key, Felt (sequence1, mismatch_end1));
10356 GCPRO2 (last, mismatch_end1);
10357
10358 ii = ending2;
10359 while (ii > starting2)
10360 {
10361 position0 = position (&object, last, sequence2, check_test,
10362 test_not_unboundp, test, key, start2,
10363 make_fixnum (ii), Qt, Qnil, Qsearch);
10364
10365 if (NILP (position0))
10366 {
10367 UNGCPRO;
10368 return Qnil;
10369 }
10370
10371 if (XFIXNUM (position0) - length1 + 1 >= starting2 &&
10372 (return_first ?
10373 NILP (mismatch (sequence1, start1, mismatch_end1,
10374 sequence2,
10375 make_fixnum (XFIXNUM (position0) - length1 + 1),
10376 make_fixnum (XFIXNUM (position0)),
10377 check_match, test_not_unboundp, test, key, 1)) :
10378 NILP (mismatch (sequence2,
10379 make_fixnum (XFIXNUM (position0) - length1 + 1),
10380 make_fixnum (XFIXNUM (position0)),
10381 sequence1, start1, mismatch_end1,
10382 check_match, test_not_unboundp, test, key, 0))))
10383 {
10384 UNGCPRO;
10385 return make_fixnum (XFIXNUM (position0) - length1 + 1);
10386 }
10387
10388 ii = XFIXNUM (position0);
10389 }
10390
10391 UNGCPRO;
10392 }
10393
10394 return Qnil;
10395 }
10396
10397 /* These two functions do set operations, those that can be visualised with
10398 Venn diagrams. */
10399 static Lisp_Object
10400 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp)
10401 {
10402 Lisp_Object liszt1 = args[0], liszt2 = args[1];
10403 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil;
10404 Lisp_Object keyed = Qnil, ignore = Qnil;
10405 Boolint test_not_unboundp = 1;
10406 check_test_func_t check_test = NULL;
10407 struct gcpro gcpro1, gcpro2;
10408
10409 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable),
10410 NULL, 2, 0);
10411
10412 CHECK_LIST (liszt1);
10413 CHECK_LIST (liszt2);
10414
10415 CHECK_KEY_ARGUMENT (key);
10416
10417 if (NILP (liszt1) && intersectionp)
10418 {
10419 return Qnil;
10420 }
10421
10422 if (NILP (liszt2))
10423 {
10424 return intersectionp ? Qnil : liszt1;
10425 }
10426
10427 get_check_match_function (&test, test_not, Qnil, Qnil, key,
10428 &test_not_unboundp, &check_test);
10429
10430 GCPRO2 (keyed, result);
10431
10432 {
10433 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10434 {
10435 keyed = KEY (key, elt);
10436 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10437 check_test, test_not_unboundp,
10438 test, key, 0, Qzero, Qnil))
10439 != intersectionp)
10440 {
10441 if (EQ (Qsubsetp, caller))
10442 {
10443 result = Qnil;
10444 break;
10445 }
10446 else if (NILP (stable))
10447 {
10448 result = Fcons (elt, result);
10449 }
10450 else if (NILP (result))
10451 {
10452 result = result_tail = Fcons (elt, Qnil);
10453 }
10454 else
10455 {
10456 XSETCDR (result_tail, Fcons (elt, Qnil));
10457 result_tail = XCDR (result_tail);
10458 }
10459 }
10460 }
10461 END_GC_EXTERNAL_LIST_LOOP (elt);
10462 }
10463
10464 UNGCPRO;
10465
10466 return result;
10467 }
10468
10469 static Lisp_Object
10470 nvenn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp)
10471 {
10472 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil;
10473 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil;
10474 Elemcount count;
10475 Boolint test_not_unboundp = 1;
10476 check_test_func_t check_test = NULL;
10477 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10478
10479 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not),
10480 NULL, 2, 0);
10481
10482 CHECK_LIST (liszt1);
10483 CHECK_LIST (liszt2);
10484
10485 CHECK_KEY_ARGUMENT (key);
10486
10487 if (NILP (liszt1) && intersectionp)
10488 {
10489 return Qnil;
10490 }
10491
10492 if (NILP (liszt2))
10493 {
10494 return intersectionp ? Qnil : liszt1;
10495 }
10496
10497 get_check_match_function (&test, test_not, Qnil, Qnil, key,
10498 &test_not_unboundp, &check_test);
10499
10500 tortoise_elt = tail = liszt1, count = 0;
10501
10502 GCPRO4 (tail, keyed, liszt1, tortoise_elt);
10503
10504 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
10505 (signal_malformed_list_error (liszt1), 0))
10506 {
10507 keyed = KEY (key, elt);
10508 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10509 check_test, test_not_unboundp,
10510 test, key, 0, Qzero, Qnil))
10511 == intersectionp)
10512 {
10513 if (NILP (prev_tail))
10514 {
10515 liszt1 = XCDR (tail);
10516 }
10517 else
10518 {
10519 XSETCDR (prev_tail, XCDR (tail));
10520 }
10521
10522 tail = XCDR (tail);
10523 /* List is definitely not circular now! */
10524 count = 0;
10525 }
10526 else
10527 {
10528 prev_tail = tail;
10529 tail = XCDR (tail);
10530 }
10531
10532 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
10533
10534 if (count & 1)
10535 {
10536 tortoise_elt = XCDR (tortoise_elt);
10537 }
10538
10539 if (EQ (elt, tortoise_elt))
10540 {
10541 signal_circular_list_error (liszt1);
10542 }
10543 }
10544
10545 UNGCPRO;
10546
10547 return liszt1;
10548 }
10549
10550 DEFUN ("intersection", Fintersection, 2, MANY, 0, /*
10551 Combine LIST1 and LIST2 using a set-intersection operation.
10552
10553 The result list contains all items that appear in both LIST1 and LIST2.
10554 This is a non-destructive function; it makes a copy of the data if necessary
10555 to avoid corrupting the original LIST1 and LIST2.
10556
10557 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10558 return the items in the order they appear in LIST1.
10559
10560 See `union' for the meaning of :test, :test-not and :key."
10561
10562 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10563 */
10564 (int nargs, Lisp_Object *args))
10565 {
10566 return venn (Qintersection, nargs, args, 1);
10567 }
10568
10569 DEFUN ("nintersection", Fnintersection, 2, MANY, 0, /*
10570 Combine LIST1 and LIST2 using a set-intersection operation.
10571
10572 The result list contains all items that appear in both LIST1 and LIST2.
10573 This is a destructive function; it reuses the storage of LIST1 whenever
10574 possible.
10575
10576 See `union' for the meaning of :test, :test-not and :key."
10577
10578 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10579 */
10580 (int nargs, Lisp_Object *args))
10581 {
10582 return nvenn (Qnintersection, nargs, args, 1);
10583 }
10584
10585 DEFUN ("subsetp", Fsubsetp, 2, MANY, 0, /*
10586 Return non-nil if every element of LIST1 also appears in LIST2.
10587
10588 See `union' for the meaning of the keyword arguments.
10589
10590 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10591 */
10592 (int nargs, Lisp_Object *args))
10593 {
10594 return venn (Qsubsetp, nargs, args, 0);
10595 }
10596
10597 DEFUN ("set-difference", Fset_difference, 2, MANY, 0, /*
10598 Combine LIST1 and LIST2 using a set-difference operation.
10599
10600 The result list contains all items that appear in LIST1 but not LIST2. This
10601 is a non-destructive function; it makes a copy of the data if necessary to
10602 avoid corrupting the original LIST1 and LIST2.
10603
10604 See `union' for the meaning of :test, :test-not and :key.
10605
10606 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10607 return the items in the order they appear in LIST1.
10608
10609 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10610 */
10611 (int nargs, Lisp_Object *args))
10612 {
10613 return venn (Qset_difference, nargs, args, 0);
10614 }
10615
10616 DEFUN ("nset-difference", Fnset_difference, 2, MANY, 0, /*
10617 Combine LIST1 and LIST2 using a set-difference operation.
10618
10619 The result list contains all items that appear in LIST1 but not LIST2. This
10620 is a destructive function; it reuses the storage of LIST1 whenever possible.
10621
10622 See `union' for the meaning of :test, :test-not and :key."
10623
10624 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10625 */
10626 (int nargs, Lisp_Object *args))
10627 {
10628 return nvenn (Qnset_difference, nargs, args, 0);
10629 }
10630
10631 DEFUN ("nunion", Fnunion, 2, MANY, 0, /*
10632 Combine LIST1 and LIST2 using a set-union operation.
10633 The result list contains all items that appear in either LIST1 or LIST2.
10634
10635 This is a destructive function, it reuses the storage of LIST1 whenever
10636 possible.
10637
10638 See `union' for the meaning of :test, :test-not and :key.
10639
10640 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10641 */
10642 (int nargs, Lisp_Object *args))
10643 {
10644 args[0] = nvenn (Qnunion, nargs, args, 0);
10645 return bytecode_nconc2 (args);
10646 }
10647
10648 DEFUN ("union", Funion, 2, MANY, 0, /*
10649 Combine LIST1 and LIST2 using a set-union operation.
10650 The result list contains all items that appear in either LIST1 or LIST2.
10651 This is a non-destructive function; it makes a copy of the data if necessary
10652 to avoid corrupting the original LIST1 and LIST2.
10653
10654 The keywords :test and :test-not specify two-argument test and negated-test
10655 predicates, respectively; :test defaults to `eql'. See `member*' for more
10656 information.
10657
10658 :key specifies a one-argument function that transforms elements of LIST1
10659 and LIST2 into \"comparison keys\" before the test predicate is applied.
10660 For example, if :key is #'car, then the car of elements from LIST1 is
10661 compared with the car of elements from LIST2. The :key function, however,
10662 does not affect the elements in the returned list, which are taken directly
10663 from the elements in LIST1 and LIST2.
10664
10665 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10666 return the items of LIST1 in order, followed by the remaining items of LIST2
10667 in the order they occur in LIST2.
10668
10669 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10670 */
10671 (int nargs, Lisp_Object *args))
10672 {
10673 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil;
10674 Lisp_Object keyed = Qnil, result, result_tail;
10675 Boolint test_not_unboundp = 1;
10676 check_test_func_t check_test = NULL, check_match = NULL;
10677 struct gcpro gcpro1, gcpro2;
10678
10679 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL);
10680
10681 CHECK_LIST (liszt1);
10682 CHECK_LIST (liszt2);
10683
10684 CHECK_KEY_ARGUMENT (key);
10685
10686 if (NILP (liszt1))
10687 {
10688 return liszt2;
10689 }
10690
10691 if (NILP (liszt2))
10692 {
10693 return liszt1;
10694 }
10695
10696 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10697 &test_not_unboundp, &check_test);
10698
10699 GCPRO2 (keyed, result);
10700
10701 if (NILP (stable))
10702 {
10703 result = liszt2;
10704 {
10705 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10706 {
10707 keyed = KEY (key, elt);
10708 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10709 check_test, test_not_unboundp,
10710 test, key, 0, Qzero, Qnil)))
10711 {
10712 /* The Lisp version of #'union used to check which list was
10713 longer, and use that as the tail of the constructed
10714 list. That fails when the order of arguments to TEST is
10715 specified, as is the case for these functions. We could
10716 pass the reverse_check argument to
10717 list_position_cons_before, but that means any key argument
10718 is called an awful lot more, so it's a space win but not
10719 a time win. */
10720 result = Fcons (elt, result);
10721 }
10722 }
10723 END_GC_EXTERNAL_LIST_LOOP (elt);
10724 }
10725 }
10726 else
10727 {
10728 result = result_tail = Qnil;
10729
10730 /* The standard `union' doesn't produce a "stable" union -- it
10731 iterates over the second list instead of the first one, and returns
10732 the values in backwards order. According to the CLTL2
10733 documentation, `union' is not required to preserve the ordering of
10734 elements in any fashion; providing the functionality for a stable
10735 union is an XEmacs extension. */
10736 {
10737 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
10738 {
10739 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10740 check_match, test_not_unboundp,
10741 test, key, 1, Qzero, Qnil)))
10742 {
10743 if (NILP (result))
10744 {
10745 result = result_tail = Fcons (elt, Qnil);
10746 }
10747 else
10748 {
10749 XSETCDR (result_tail, Fcons (elt, Qnil));
10750 result_tail = XCDR (result_tail);
10751 }
10752 }
10753 }
10754 END_GC_EXTERNAL_LIST_LOOP (elt);
10755 }
10756
10757 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result);
10758 }
10759
10760 UNGCPRO;
10761
10762 return result;
10763 }
10764
10765 DEFUN ("set-exclusive-or", Fset_exclusive_or, 2, MANY, 0, /*
10766 Combine LIST1 and LIST2 using a set-exclusive-or operation.
10767
10768 The result list contains all items that appear in exactly one of LIST1, LIST2.
10769 This is a non-destructive function; it makes a copy of the data if necessary
10770 to avoid corrupting the original LIST1 and LIST2.
10771
10772 See `union' for the meaning of :test, :test-not and :key.
10773
10774 A non-nil value for the :stable keyword, not specified by Common Lisp, means
10775 return the items in the order they appear in LIST1, followed by the
10776 remaining items in the order they appear in LIST2.
10777
10778 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE)
10779 */
10780 (int nargs, Lisp_Object *args))
10781 {
10782 Lisp_Object liszt1 = args[0], liszt2 = args[1];
10783 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil;
10784 Boolint test_not_unboundp = 1;
10785 check_test_func_t check_match = NULL, check_test = NULL;
10786 struct gcpro gcpro1, gcpro2;
10787
10788 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4,
10789 (test, key, test_not, stable), NULL);
10790
10791 CHECK_LIST (liszt1);
10792 CHECK_LIST (liszt2);
10793
10794 CHECK_KEY_ARGUMENT (key);
10795
10796 if (NILP (liszt2))
10797 {
10798 return liszt1;
10799 }
10800
10801 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10802 &test_not_unboundp, &check_test);
10803
10804 GCPRO2 (keyed, result);
10805 {
10806 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt1)
10807 {
10808 keyed = KEY (key, elt);
10809 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10810 check_test, test_not_unboundp,
10811 test, key, 0, Qzero, Qnil)))
10812 {
10813 if (NILP (stable))
10814 {
10815 result = Fcons (elt, result);
10816 }
10817 else if (NILP (result))
10818 {
10819 result = result_tail = Fcons (elt, Qnil);
10820 }
10821 else
10822 {
10823 XSETCDR (result_tail, Fcons (elt, Qnil));
10824 result_tail = XCDR (result_tail);
10825 }
10826 }
10827 }
10828 END_GC_EXTERNAL_LIST_LOOP (elt);
10829 }
10830
10831 {
10832 GC_EXTERNAL_LIST_LOOP_2 (elt, liszt2)
10833 {
10834 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10835 check_match, test_not_unboundp,
10836 test, key, 1, Qzero, Qnil)))
10837 {
10838 if (NILP (stable))
10839 {
10840 result = Fcons (elt, result);
10841 }
10842 else if (NILP (result))
10843 {
10844 result = result_tail = Fcons (elt, Qnil);
10845 }
10846 else
10847 {
10848 XSETCDR (result_tail, Fcons (elt, Qnil));
10849 result_tail = XCDR (result_tail);
10850 }
10851 }
10852 }
10853 END_GC_EXTERNAL_LIST_LOOP (elt);
10854 }
10855
10856 UNGCPRO;
10857
10858 return result;
10859 }
10860
10861 DEFUN ("nset-exclusive-or", Fnset_exclusive_or, 2, MANY, 0, /*
10862 Combine LIST1 and LIST2 using a set-exclusive-or operation.
10863
10864 The result list contains all items that appear in exactly one of LIST1 and
10865 LIST2. This is a destructive function; it reuses the storage of LIST1 and
10866 LIST2 whenever possible.
10867
10868 See `union' for the meaning of :test, :test-not and :key.
10869
10870 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT)
10871 */
10872 (int nargs, Lisp_Object *args))
10873 {
10874 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil;
10875 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap;
10876 Lisp_Object prev_tail = Qnil, ignore = Qnil;
10877 Elemcount count;
10878 Boolint test_not_unboundp = 1;
10879 check_test_func_t check_match = NULL, check_test = NULL;
10880 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
10881
10882 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4,
10883 (test, key, test_not, stable), NULL);
10884
10885 CHECK_LIST (liszt1);
10886 CHECK_LIST (liszt2);
10887
10888 CHECK_KEY_ARGUMENT (key);
10889
10890 if (NILP (liszt2))
10891 {
10892 return liszt1;
10893 }
10894
10895 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key,
10896 &test_not_unboundp, &check_test);
10897
10898 tortoise_elt = tail = liszt1, count = 0;
10899
10900 GCPRO4 (tail, keyed, result, tortoise_elt);
10901
10902 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
10903 (signal_malformed_list_error (liszt1), 0))
10904 {
10905 keyed = KEY (key, elt);
10906 if (NILP (list_position_cons_before (&ignore, keyed, liszt2,
10907 check_test, test_not_unboundp,
10908 test, key, 0, Qzero, Qnil)))
10909 {
10910 swap = XCDR (tail);
10911
10912 if (NILP (prev_tail))
10913 {
10914 liszt1 = XCDR (tail);
10915 }
10916 else
10917 {
10918 XSETCDR (prev_tail, swap);
10919 }
10920
10921 XSETCDR (tail, result);
10922 result = tail;
10923 tail = swap;
10924
10925 /* List is definitely not circular now! */
10926 count = 0;
10927 }
10928 else
10929 {
10930 prev_tail = tail;
10931 tail = XCDR (tail);
10932 }
10933
10934 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
10935
10936 if (count & 1)
10937 {
10938 tortoise_elt = XCDR (tortoise_elt);
10939 }
10940
10941 if (EQ (elt, tortoise_elt))
10942 {
10943 signal_circular_list_error (liszt1);
10944 }
10945 }
10946
10947 tortoise_elt = tail = liszt2, count = 0;
10948
10949 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 :
10950 (signal_malformed_list_error (liszt2), 0))
10951 {
10952 /* Need to leave the key calculation to list_position_cons_before(). */
10953 if (NILP (list_position_cons_before (&ignore, elt, liszt1,
10954 check_match, test_not_unboundp,
10955 test, key, 1, Qzero, Qnil)))
10956 {
10957 swap = XCDR (tail);
10958 XSETCDR (tail, result);
10959 result = tail;
10960 tail = swap;
10961 count = 0;
10962 }
10963 else
10964 {
10965 tail = XCDR (tail);
10966 }
10967
10968 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue;
10969
10970 if (count & 1)
10971 {
10972 tortoise_elt = XCDR (tortoise_elt);
10973 }
10974
10975 if (EQ (elt, tortoise_elt))
10976 {
10977 signal_circular_list_error (liszt1);
10978 }
10979 }
10980
10981 UNGCPRO;
10982
10983 return result;
10984 } 2720 }
10985 2721
10986 2722
10987 Lisp_Object 2723 Lisp_Object
10988 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) 2724 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string)
11606 result = make_string (decoded, decoded_length); 3342 result = make_string (decoded, decoded_length);
11607 unbind_to (speccount); 3343 unbind_to (speccount);
11608 return result; 3344 return result;
11609 } 3345 }
11610 3346
11611 Lisp_Object Qyes_or_no_p;
11612
11613 void 3347 void
11614 syms_of_fns (void) 3348 syms_of_fns (void)
11615 { 3349 {
11616 INIT_LISP_OBJECT (bit_vector);
11617
11618 DEFSYMBOL (Qstring_lessp);
11619 DEFSYMBOL (Qmerge);
11620 DEFSYMBOL (Qfill);
11621 DEFSYMBOL (Qidentity);
11622 DEFSYMBOL (Qvector);
11623 DEFSYMBOL (Qarray);
11624 DEFSYMBOL (Qstring);
11625 DEFSYMBOL (Qlist);
11626 DEFSYMBOL (Qbit_vector);
11627 defsymbol (&QsortX, "sort*");
11628 DEFSYMBOL (Qreduce);
11629 DEFSYMBOL (Qreplace);
11630 DEFSYMBOL (Qposition);
11631 DEFSYMBOL (Qfind);
11632 defsymbol (&QdeleteX, "delete*");
11633 defsymbol (&QremoveX, "remove*");
11634
11635 DEFSYMBOL (Qmapconcat);
11636 defsymbol (&QmapcarX, "mapcar*");
11637 DEFSYMBOL (Qmapvector);
11638 DEFSYMBOL (Qmapcan);
11639 DEFSYMBOL (Qmapc);
11640 DEFSYMBOL (Qmap);
11641 DEFSYMBOL (Qmap_into);
11642 DEFSYMBOL (Qsome);
11643 DEFSYMBOL (Qevery);
11644 DEFSYMBOL (Qmaplist);
11645 DEFSYMBOL (Qmapl); 3350 DEFSYMBOL (Qmapl);
11646 DEFSYMBOL (Qmapcon); 3351 DEFSYMBOL (Qmapcon);
11647 DEFSYMBOL (Qnsubstitute); 3352 DEFSYMBOL (Qmaplist);
11648 DEFSYMBOL (Qdelete_duplicates);
11649 DEFSYMBOL (Qsubstitute);
11650 DEFSYMBOL (Qmismatch);
11651 DEFSYMBOL (Qintersection);
11652 DEFSYMBOL (Qnintersection);
11653 DEFSYMBOL (Qsubsetp);
11654 DEFSYMBOL (Qcar_less_than_car);
11655 DEFSYMBOL (Qset_difference);
11656 DEFSYMBOL (Qnset_difference);
11657 DEFSYMBOL (Qnunion);
11658
11659 DEFKEYWORD (Q_from_end);
11660 DEFKEYWORD (Q_initial_value);
11661 DEFKEYWORD (Q_start1);
11662 DEFKEYWORD (Q_start2);
11663 DEFKEYWORD (Q_end1);
11664 DEFKEYWORD (Q_end2);
11665 defkeyword (&Q_if_, ":if");
11666 DEFKEYWORD (Q_if_not);
11667 DEFKEYWORD (Q_test_not);
11668 DEFKEYWORD (Q_count);
11669 DEFKEYWORD (Q_stable);
11670 DEFKEYWORD (Q_descend_structures);
11671
11672 DEFSYMBOL (Qyes_or_no_p);
11673 3353
11674 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); 3354 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error);
11675 3355
11676 DEFSUBR (Fidentity); 3356 DEFSUBR (Fidentity);
11677 DEFSUBR (Frandom); 3357 DEFSUBR (Frandom);
11678 DEFSUBR (Flength);
11679 DEFSUBR (Fsafe_length); 3358 DEFSUBR (Fsafe_length);
11680 DEFSUBR (Flist_length); 3359 DEFSUBR (Flist_length);
11681 DEFSUBR (Fcount);
11682 DEFSUBR (Fstring_equal); 3360 DEFSUBR (Fstring_equal);
11683 DEFSUBR (Fcompare_strings); 3361 DEFSUBR (Fcompare_strings);
11684 DEFSUBR (Fstring_lessp); 3362 DEFSUBR (Fstring_lessp);
11685 DEFSUBR (Fstring_modified_tick); 3363 DEFSUBR (Fstring_modified_tick);
11686 DEFSUBR (Fappend); 3364 DEFSUBR (Fappend);
11688 DEFSUBR (Fvconcat); 3366 DEFSUBR (Fvconcat);
11689 DEFSUBR (Fbvconcat); 3367 DEFSUBR (Fbvconcat);
11690 DEFSUBR (Fcopy_list); 3368 DEFSUBR (Fcopy_list);
11691 DEFSUBR (Fcopy_sequence); 3369 DEFSUBR (Fcopy_sequence);
11692 DEFSUBR (Fcopy_alist); 3370 DEFSUBR (Fcopy_alist);
11693 DEFSUBR (Fcopy_tree);
11694 DEFSUBR (Fsubseq);
11695 DEFSUBR (Fnthcdr); 3371 DEFSUBR (Fnthcdr);
11696 DEFSUBR (Fnth); 3372 DEFSUBR (Fnth);
11697 DEFSUBR (Felt);
11698 DEFSUBR (Flast); 3373 DEFSUBR (Flast);
11699 DEFSUBR (Fbutlast); 3374 DEFSUBR (Fbutlast);
11700 DEFSUBR (Fnbutlast); 3375 DEFSUBR (Fnbutlast);
11701 DEFSUBR (Fmember);
11702 DEFSUBR (Fmemq);
11703 DEFSUBR (FmemberX);
11704 DEFSUBR (Fadjoin);
11705 DEFSUBR (Fassoc);
11706 DEFSUBR (Fassq);
11707 DEFSUBR (Frassoc);
11708 DEFSUBR (Frassq);
11709
11710 DEFSUBR (Fposition);
11711 DEFSUBR (Ffind);
11712
11713 DEFSUBR (FdeleteX);
11714 DEFSUBR (FremoveX);
11715 DEFSUBR (Fdelete_duplicates);
11716 DEFSUBR (Fremove_duplicates);
11717 DEFSUBR (Fnreverse);
11718 DEFSUBR (Freverse);
11719 DEFSUBR (FsortX);
11720 DEFSUBR (Fmerge);
11721 DEFSUBR (Fplists_eq); 3376 DEFSUBR (Fplists_eq);
11722 DEFSUBR (Fplists_equal); 3377 DEFSUBR (Fplists_equal);
11723 DEFSUBR (Flax_plists_eq); 3378 DEFSUBR (Flax_plists_eq);
11724 DEFSUBR (Flax_plists_equal); 3379 DEFSUBR (Flax_plists_equal);
11725 DEFSUBR (Fplist_get); 3380 DEFSUBR (Fplist_get);
11740 DEFSUBR (Fremprop); 3395 DEFSUBR (Fremprop);
11741 DEFSUBR (Fobject_plist); 3396 DEFSUBR (Fobject_plist);
11742 DEFSUBR (Fobject_setplist); 3397 DEFSUBR (Fobject_setplist);
11743 DEFSUBR (Fequal); 3398 DEFSUBR (Fequal);
11744 DEFSUBR (Fequalp); 3399 DEFSUBR (Fequalp);
11745 DEFSUBR (Ffill);
11746 3400
11747 #ifdef SUPPORT_CONFOUNDING_FUNCTIONS 3401 #ifdef SUPPORT_CONFOUNDING_FUNCTIONS
11748 DEFSUBR (Fold_member); 3402 DEFSUBR (Fold_member);
11749 DEFSUBR (Fold_memq); 3403 DEFSUBR (Fold_memq);
11750 DEFSUBR (Fold_assoc); 3404 DEFSUBR (Fold_assoc);
11751 DEFSUBR (Fold_assq); 3405 DEFSUBR (Fold_assq);
3406 DEFSUBR (Fold_rassq);
11752 DEFSUBR (Fold_rassoc); 3407 DEFSUBR (Fold_rassoc);
11753 DEFSUBR (Fold_rassq);
11754 DEFSUBR (Fold_delete); 3408 DEFSUBR (Fold_delete);
11755 DEFSUBR (Fold_delq); 3409 DEFSUBR (Fold_delq);
11756 DEFSUBR (Fold_equal); 3410 DEFSUBR (Fold_equal);
11757 DEFSUBR (Fold_eq); 3411 DEFSUBR (Fold_eq);
11758 #endif 3412 #endif
11759 3413
11760 DEFSUBR (FassocX);
11761 DEFSUBR (FrassocX);
11762
11763 DEFSUBR (Fnconc); 3414 DEFSUBR (Fnconc);
11764 DEFSUBR (FmapcarX);
11765 DEFSUBR (Fmapvector);
11766 DEFSUBR (Fmapcan);
11767 DEFSUBR (Fmapc);
11768 DEFSUBR (Fmapconcat);
11769 DEFSUBR (Fmap);
11770 DEFSUBR (Fmap_into);
11771 DEFSUBR (Fsome);
11772 DEFSUBR (Fevery);
11773 Ffset (intern ("mapc-internal"), Qmapc);
11774 Ffset (intern ("mapcar"), QmapcarX);
11775 DEFSUBR (Fmaplist); 3415 DEFSUBR (Fmaplist);
11776 DEFSUBR (Fmapl); 3416 DEFSUBR (Fmapl);
11777 DEFSUBR (Fmapcon); 3417 DEFSUBR (Fmapcon);
11778 3418
11779 DEFSUBR (Freduce);
11780 DEFSUBR (Freplace_list); 3419 DEFSUBR (Freplace_list);
11781 DEFSUBR (Freplace);
11782 DEFSUBR (Fsubsetp);
11783 DEFSUBR (Fnsubstitute);
11784 DEFSUBR (Fsubstitute);
11785 DEFSUBR (Fsublis);
11786 DEFSUBR (Fnsublis);
11787 DEFSUBR (Fsubst);
11788 DEFSUBR (Fnsubst);
11789 DEFSUBR (Ftree_equal);
11790 DEFSUBR (Fmismatch);
11791 DEFSUBR (Fsearch);
11792 DEFSUBR (Funion);
11793 DEFSUBR (Fnunion);
11794 DEFSUBR (Fintersection);
11795 DEFSUBR (Fnintersection);
11796 DEFSUBR (Fset_difference);
11797 DEFSUBR (Fnset_difference);
11798 DEFSUBR (Fset_exclusive_or);
11799 DEFSUBR (Fnset_exclusive_or);
11800 3420
11801 DEFSUBR (Fload_average); 3421 DEFSUBR (Fload_average);
11802 DEFSUBR (Ffeaturep); 3422 DEFSUBR (Ffeaturep);
11803 DEFSUBR (Frequire); 3423 DEFSUBR (Frequire);
11804 DEFSUBR (Fprovide); 3424 DEFSUBR (Fprovide);