Mercurial > hg > xemacs-beta
comparison src/fns.c @ 5327:d1b17a33450b
Move the heavy lifting from cl-seq.el to C.
src/ChangeLog addition:
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
Move the heavy lifting from cl-seq.el to C, finally making those
functions first-class XEmacs citizens, with circularity checking,
built-in support for tests other than #'eql, and as much
compatibility with current Common Lisp as Paul Dietz' tests require.
* fns.c (check_eq_nokey, check_eq_key, check_eql_nokey)
(check_eql_key, check_equal_nokey, check_equal_key)
(check_equalp_nokey, check_equalp_key, check_string_match_nokey)
(check_string_match_key, check_other_nokey, check_other_key)
(check_if_nokey, check_if_key, check_match_eq_key)
(check_match_eql_key, check_match_equal_key)
(check_match_equalp_key, check_match_other_key): New. These are
basically to provide function pointers to be used by Lisp
functions that take TEST, TEST-NOT and KEY arguments.
(get_check_match_function_1, get_check_test_function)
(get_check_match_function): These functions work out which of the
previous list of functions to use, given the keywords supplied by
the user.
(count_with_tail): New. This is the bones of #'count.
(list_count_from_end, string_count_from_end): Utility functions
for #'count.
(Fcount): New, moved from cl-seq.el.
(list_position_cons_before): New. The implementation of #'member*,
and important in implementing various other functions.
(FmemberX, Fadjoin, FassocX, FrassocX, Fposition, Ffind)
(FdeleteX, FremoveX, Fdelete_duplicates, Fremove_duplicates)
(Fnsubstitute, Fsubstitute, Fsublis, Fnsublis, Fsubst, Fnsubst)
(Ftree_equal, Fmismatch, Fsearch, Fintersection, Fnintersection)
(Fsubsetp, Fset_difference, Fnset_difference, Fnunion, Funion)
(Fset_exclusive_or, Fnset_exclusive_or): New, moved here from
cl-seq.el.
(position): New. The implementation of #'find and #'position.
(list_delete_duplicates_from_end, subst, sublis, nsublis)
(tree_equal, mismatch_from_end, mismatch_list_list)
(mismatch_list_string, mismatch_list_array)
(mismatch_string_array, mismatch_string_string)
(mismatch_array_array, get_mismatch_func): Helper C functions for
the Lisp-visible functions.
(venn, nvenn): New. The implementation of the main Lisp functions that
treat lists as sets.
lisp/ChangeLog addition:
2010-12-30 Aidan Kehoe <kehoea@parhasard.net>
* cl-seq.el:
Move the heavy lifting from this file to C. Dump the
cl-parsing-keywords macro, but don't use defun* for the functions
we define that do take keywords, dynamic scope lossage makes that
not practical.
* subr.el (sort, fillarray): Move these aliases here.
(map-plist): #'nsublis is now built-in, but at this point #'eql
isn't necessarily available as a test; use #'eq.
* obsolete.el (cl-delete-duplicates): Make this available for old
compiler macros and old code.
(memql): Document that this is equivalent to #'member*, and worse.
* cl.el (adjoin, subst): Removed. These are in C.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Thu, 30 Dec 2010 01:59:52 +0000 |
parents | c290121b0c3f |
children | 7ea837399734 |
comparison
equal
deleted
inserted
replaced
5323:f87bb35a6b94 | 5327:d1b17a33450b |
---|---|
52 #include "opaque.h" | 52 #include "opaque.h" |
53 | 53 |
54 /* NOTE: This symbol is also used in lread.c */ | 54 /* NOTE: This symbol is also used in lread.c */ |
55 #define FEATUREP_SYNTAX | 55 #define FEATUREP_SYNTAX |
56 | 56 |
57 Lisp_Object Qstring_lessp, Qsort, Qmerge, Qfill, Qreplace; | 57 Lisp_Object Qstring_lessp, Qmerge, Qfill, Qreplace, QassocX, QrassocX; |
58 Lisp_Object Qidentity; | 58 Lisp_Object Qposition, Qfind, QdeleteX, QremoveX, Qidentity, Qadjoin; |
59 Lisp_Object Qvector, Qarray, Qbit_vector, QsortX, Q_from_end, Q_initial_value; | 59 Lisp_Object Qvector, Qarray, Qbit_vector, QsortX, Q_from_end, Q_initial_value; |
60 Lisp_Object Qmapconcat, QmapcarX, Qmapvector, Qmapcan, Qmapc, Qmap, Qmap_into; | 60 Lisp_Object Qmapconcat, QmapcarX, Qmapvector, Qmapcan, Qmapc, Qmap, Qmap_into; |
61 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce; | 61 Lisp_Object Qsome, Qevery, Qmaplist, Qmapl, Qmapcon, Qreduce, Qsubstitute; |
62 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2; | 62 Lisp_Object Q_start1, Q_start2, Q_end1, Q_end2, Q_if_, Q_if_not, Q_stable; |
63 Lisp_Object Q_test_not, Q_count, Qnsubstitute, Qdelete_duplicates, Qmismatch; | |
64 | |
65 Lisp_Object Qintersection, Qnintersection, Qset_difference, Qnset_difference; | |
66 Lisp_Object Qnunion, Qnintersection, Qsubsetp, Qnset_difference; | |
63 | 67 |
64 Lisp_Object Qbase64_conversion_error; | 68 Lisp_Object Qbase64_conversion_error; |
65 | 69 |
66 Lisp_Object Vpath_separator; | 70 Lisp_Object Vpath_separator; |
71 | |
72 extern Fixnum max_lisp_eval_depth; | |
73 extern int lisp_eval_depth; | |
67 | 74 |
68 static int internal_old_equal (Lisp_Object, Lisp_Object, int); | 75 static int internal_old_equal (Lisp_Object, Lisp_Object, int); |
69 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth); | 76 Lisp_Object safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth); |
70 | 77 |
71 static DOESNT_RETURN | 78 static DOESNT_RETURN |
197 bit_vector_equal, | 204 bit_vector_equal, |
198 bit_vector_hash, | 205 bit_vector_hash, |
199 bit_vector_description, | 206 bit_vector_description, |
200 size_bit_vector, | 207 size_bit_vector, |
201 Lisp_Bit_Vector); | 208 Lisp_Bit_Vector); |
209 | |
210 /* Various test functions for #'member*, #'assoc* and the other functions | |
211 that take both TEST and KEY arguments. */ | |
212 | |
213 typedef Boolint (*check_test_func_t) (Lisp_Object test, Lisp_Object key, | |
214 Lisp_Object item, Lisp_Object elt); | |
215 | |
216 static Boolint | |
217 check_eq_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
218 Lisp_Object item, Lisp_Object elt) | |
219 { | |
220 return EQ (item, elt); | |
221 } | |
222 | |
223 static Boolint | |
224 check_eq_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item, | |
225 Lisp_Object elt) | |
226 { | |
227 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
228 return EQ (item, elt); | |
229 } | |
230 | |
231 /* The next two are not used by #'member* and #'assoc*, since we can decide | |
232 on #'eq vs. #'equal when we have the type of ITEM. */ | |
233 static Boolint | |
234 check_eql_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
235 Lisp_Object elt1, Lisp_Object elt2) | |
236 { | |
237 return EQ (elt1, elt2) | |
238 || (NON_FIXNUM_NUMBER_P (elt1) && internal_equal (elt1, elt2, 0)); | |
239 } | |
240 | |
241 static Boolint | |
242 check_eql_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item, | |
243 Lisp_Object elt) | |
244 { | |
245 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
246 return EQ (item, elt) | |
247 || (NON_FIXNUM_NUMBER_P (item) && internal_equal (item, elt, 0)); | |
248 } | |
249 | |
250 static Boolint | |
251 check_equal_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
252 Lisp_Object item, Lisp_Object elt) | |
253 { | |
254 return internal_equal (item, elt, 0); | |
255 } | |
256 | |
257 static Boolint | |
258 check_equal_key (Lisp_Object UNUSED (test), Lisp_Object key, Lisp_Object item, | |
259 Lisp_Object elt) | |
260 { | |
261 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
262 return internal_equal (item, elt, 0); | |
263 } | |
264 | |
265 static Boolint | |
266 check_equalp_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
267 Lisp_Object item, Lisp_Object elt) | |
268 { | |
269 return internal_equalp (item, elt, 0); | |
270 } | |
271 | |
272 static Boolint | |
273 check_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
274 Lisp_Object item, Lisp_Object elt) | |
275 { | |
276 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
277 return internal_equalp (item, elt, 0); | |
278 } | |
279 | |
280 static Boolint | |
281 check_string_match_nokey (Lisp_Object UNUSED (test), Lisp_Object UNUSED (key), | |
282 Lisp_Object item, Lisp_Object elt) | |
283 { | |
284 return !NILP (Fstring_match (item, elt, Qnil, Qnil)); | |
285 } | |
286 | |
287 static Boolint | |
288 check_string_match_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
289 Lisp_Object item, Lisp_Object elt) | |
290 { | |
291 elt = IGNORE_MULTIPLE_VALUES (call1 (key, elt)); | |
292 return !NILP (Fstring_match (item, elt, Qnil, Qnil)); | |
293 } | |
294 | |
295 static Boolint | |
296 check_other_nokey (Lisp_Object test, Lisp_Object UNUSED (key), | |
297 Lisp_Object item, Lisp_Object elt) | |
298 { | |
299 Lisp_Object args[] = { test, item, elt }; | |
300 struct gcpro gcpro1; | |
301 | |
302 GCPRO1 (args[0]); | |
303 gcpro1.nvars = countof (args); | |
304 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
305 UNGCPRO; | |
306 | |
307 return !NILP (item); | |
308 } | |
309 | |
310 static Boolint | |
311 check_other_key (Lisp_Object test, Lisp_Object key, | |
312 Lisp_Object item, Lisp_Object elt) | |
313 { | |
314 Lisp_Object args[] = { item, key, elt }; | |
315 struct gcpro gcpro1; | |
316 | |
317 GCPRO1 (args[0]); | |
318 gcpro1.nvars = countof (args); | |
319 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args) - 1, args + 1)); | |
320 args[1] = item; | |
321 args[0] = test; | |
322 item = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
323 UNGCPRO; | |
324 | |
325 return !NILP (item); | |
326 } | |
327 | |
328 static Boolint | |
329 check_if_nokey (Lisp_Object test, Lisp_Object UNUSED (key), | |
330 Lisp_Object UNUSED (item), Lisp_Object elt) | |
331 { | |
332 elt = IGNORE_MULTIPLE_VALUES (call1 (test, elt)); | |
333 return !NILP (elt); | |
334 } | |
335 | |
336 static Boolint | |
337 check_if_key (Lisp_Object test, Lisp_Object key, | |
338 Lisp_Object UNUSED (item), Lisp_Object elt) | |
339 { | |
340 Lisp_Object args[] = { key, elt }; | |
341 struct gcpro gcpro1; | |
342 | |
343 GCPRO1 (args[0]); | |
344 gcpro1.nvars = countof (args); | |
345 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
346 args[0] = test; | |
347 elt = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
348 UNGCPRO; | |
349 | |
350 return !NILP (elt); | |
351 } | |
352 | |
353 static Boolint | |
354 check_match_eq_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
355 Lisp_Object elt1, Lisp_Object elt2) | |
356 { | |
357 Lisp_Object args[] = { key, elt1, elt2 }; | |
358 struct gcpro gcpro1; | |
359 | |
360 GCPRO1 (args[0]); | |
361 gcpro1.nvars = countof (args); | |
362 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
363 args[1] = key; | |
364 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
365 UNGCPRO; | |
366 | |
367 return EQ (args[0], args[1]); | |
368 } | |
369 | |
370 static Boolint | |
371 check_match_eql_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
372 Lisp_Object elt1, Lisp_Object elt2) | |
373 { | |
374 Lisp_Object args[] = { key, elt1, elt2 }; | |
375 struct gcpro gcpro1; | |
376 | |
377 GCPRO1 (args[0]); | |
378 gcpro1.nvars = countof (args); | |
379 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
380 args[1] = key; | |
381 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
382 UNGCPRO; | |
383 | |
384 return EQ (args[0], args[1]) || | |
385 (NON_FIXNUM_NUMBER_P (args[0]) && internal_equal (args[0], args[1], 0)); | |
386 } | |
387 | |
388 static Boolint | |
389 check_match_equal_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
390 Lisp_Object elt1, Lisp_Object elt2) | |
391 { | |
392 Lisp_Object args[] = { key, elt1, elt2 }; | |
393 struct gcpro gcpro1; | |
394 | |
395 GCPRO1 (args[0]); | |
396 gcpro1.nvars = countof (args); | |
397 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
398 args[1] = key; | |
399 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
400 UNGCPRO; | |
401 | |
402 return internal_equal (args[0], args[1], 0); | |
403 } | |
404 | |
405 static Boolint | |
406 check_match_equalp_key (Lisp_Object UNUSED (test), Lisp_Object key, | |
407 Lisp_Object elt1, Lisp_Object elt2) | |
408 { | |
409 Lisp_Object args[] = { key, elt1, elt2 }; | |
410 struct gcpro gcpro1; | |
411 | |
412 GCPRO1 (args[0]); | |
413 gcpro1.nvars = countof (args); | |
414 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
415 args[1] = key; | |
416 args[1] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
417 UNGCPRO; | |
418 | |
419 return internal_equalp (args[0], args[1], 0); | |
420 } | |
421 | |
422 static Boolint | |
423 check_match_other_key (Lisp_Object test, Lisp_Object key, | |
424 Lisp_Object elt1, Lisp_Object elt2) | |
425 { | |
426 Lisp_Object args[] = { key, elt1, elt2 }; | |
427 struct gcpro gcpro1; | |
428 | |
429 GCPRO1 (args[0]); | |
430 gcpro1.nvars = countof (args); | |
431 args[0] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args)); | |
432 args[1] = key; | |
433 args[2] = IGNORE_MULTIPLE_VALUES (Ffuncall (2, args + 1)); | |
434 args[1] = args[0]; | |
435 args[0] = test; | |
436 | |
437 elt1 = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args)); | |
438 UNGCPRO; | |
439 | |
440 return !NILP (elt1); | |
441 } | |
442 | |
443 static check_test_func_t | |
444 get_check_match_function_1 (Lisp_Object item, | |
445 Lisp_Object *test_inout, Lisp_Object test_not, | |
446 Lisp_Object if_, Lisp_Object if_not, | |
447 Lisp_Object key, Boolint *test_not_unboundp_out, | |
448 check_test_func_t *test_func_out) | |
449 { | |
450 Lisp_Object test = *test_inout; | |
451 check_test_func_t result = NULL, test_func = NULL; | |
452 Boolint force_if = 0; | |
453 | |
454 if (!NILP (if_)) | |
455 { | |
456 if (!(NILP (test) && NILP (test_not) && NILP (if_not))) | |
457 { | |
458 invalid_argument ("only one keyword among :test :test-not " | |
459 ":if :if-not allowed", if_); | |
460 } | |
461 | |
462 test = *test_inout = if_; | |
463 force_if = 1; | |
464 } | |
465 else if (!NILP (if_not)) | |
466 { | |
467 if (!(NILP (test) && NILP (test_not))) | |
468 { | |
469 invalid_argument ("only one keyword among :test :test-not " | |
470 ":if :if-not allowed", if_not); | |
471 } | |
472 | |
473 test_not = if_not; | |
474 force_if = 1; | |
475 } | |
476 | |
477 if (NILP (test)) | |
478 { | |
479 if (!NILP (test_not)) | |
480 { | |
481 test = *test_inout = test_not; | |
482 if (NULL != test_not_unboundp_out) | |
483 { | |
484 *test_not_unboundp_out = 0; | |
485 } | |
486 } | |
487 else | |
488 { | |
489 test = Qeql; | |
490 if (NULL != test_not_unboundp_out) | |
491 { | |
492 *test_not_unboundp_out = 1; | |
493 } | |
494 } | |
495 } | |
496 else if (!NILP (test_not)) | |
497 { | |
498 invalid_argument_2 ("conflicting :test and :test-not keyword arguments", | |
499 test, test_not); | |
500 } | |
501 | |
502 test = indirect_function (test, 1); | |
503 | |
504 if (NILP (key) || | |
505 EQ (indirect_function (key, 1), XSYMBOL_FUNCTION (Qidentity))) | |
506 { | |
507 key = Qidentity; | |
508 } | |
509 | |
510 if (force_if) | |
511 { | |
512 result = EQ (key, Qidentity) ? check_if_nokey : check_if_key; | |
513 | |
514 if (NULL != test_func_out) | |
515 { | |
516 *test_func_out = result; | |
517 } | |
518 | |
519 return result; | |
520 } | |
521 | |
522 if (!UNBOUNDP (item) && EQ (test, XSYMBOL_FUNCTION (Qeql))) | |
523 { | |
524 test = XSYMBOL_FUNCTION (NON_FIXNUM_NUMBER_P (item) ? Qequal : Qeq); | |
525 } | |
526 | |
527 #define FROB(known_test, eq_condition) \ | |
528 if (EQ (test, XSYMBOL_FUNCTION (Q##known_test))) do \ | |
529 { \ | |
530 if (eq_condition) \ | |
531 { \ | |
532 test = XSYMBOL_FUNCTION (Qeq); \ | |
533 goto force_eq_check; \ | |
534 } \ | |
535 \ | |
536 if (!EQ (Qidentity, key)) \ | |
537 { \ | |
538 test_func = check_##known_test##_key; \ | |
539 result = check_match_##known_test##_key; \ | |
540 } \ | |
541 else \ | |
542 { \ | |
543 result = test_func = check_##known_test##_nokey; \ | |
544 } \ | |
545 } while (0) | |
546 | |
547 FROB (eql, 0); | |
548 else if (SUBRP (test)) | |
549 { | |
550 force_eq_check: | |
551 FROB (eq, 0); | |
552 else FROB (equal, (SYMBOLP (item) || INTP (item) || CHARP (item))); | |
553 else FROB (equalp, (SYMBOLP (item))); | |
554 else if (EQ (test, XSYMBOL_FUNCTION (Qstring_match))) | |
555 { | |
556 if (EQ (Qidentity, key)) | |
557 { | |
558 test_func = result = check_string_match_nokey; | |
559 } | |
560 else | |
561 { | |
562 test_func = check_string_match_key; | |
563 result = check_other_key; | |
564 } | |
565 } | |
566 } | |
567 | |
568 if (NULL == result) | |
569 { | |
570 if (EQ (Qidentity, key)) | |
571 { | |
572 test_func = result = check_other_nokey; | |
573 } | |
574 else | |
575 { | |
576 test_func = check_other_key; | |
577 result = check_match_other_key; | |
578 } | |
579 } | |
580 | |
581 if (NULL != test_func_out) | |
582 { | |
583 *test_func_out = test_func; | |
584 } | |
585 | |
586 return result; | |
587 } | |
588 #undef FROB | |
589 | |
590 /* Given TEST, TEST_NOT, IF, IF_NOT, KEY, and ITEM, return a C function | |
591 pointer appropriate for use in deciding whether a given element of a | |
592 sequence satisfies TEST. | |
593 | |
594 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero | |
595 if it was bound, and set *test_inout to the value it was bound to. If | |
596 TEST was not bound, leave *test_inout alone; the value is not used by | |
597 check_eq_*key() or check_equal_*key(), which are the defaults, depending | |
598 on the type of ITEM. | |
599 | |
600 The returned function takes arguments (TEST, KEY, ITEM, ELT), where ITEM | |
601 is the item being searched for and ELT is the element of the sequence | |
602 being examined. | |
603 | |
604 Error if both TEST and TEST_NOT were specified, which Common Lisp says is | |
605 undefined behaviour. */ | |
606 | |
607 static check_test_func_t | |
608 get_check_test_function (Lisp_Object item, | |
609 Lisp_Object *test_inout, Lisp_Object test_not, | |
610 Lisp_Object if_, Lisp_Object if_not, | |
611 Lisp_Object key, Boolint *test_not_unboundp_out) | |
612 { | |
613 check_test_func_t result = NULL; | |
614 get_check_match_function_1 (item, test_inout, test_not, if_, if_not, | |
615 key, test_not_unboundp_out, &result); | |
616 return result; | |
617 } | |
618 | |
619 /* Given TEST, TEST_NOT, IF, IF_NOT and KEY, return a C function pointer | |
620 appropriate for use in deciding whether two given elements of a sequence | |
621 satisfy TEST. | |
622 | |
623 Set *test_not_unboundp_out to 1 if TEST_NOT was not bound; set it to zero | |
624 if it was bound, and set *test_inout to the value it was bound to. If | |
625 TEST was not bound, leave *test_inout alone; the value is not used by | |
626 check_eql_*key(). | |
627 | |
628 The returned function takes arguments (TEST, KEY, ELT1, ELT2), where ELT1 | |
629 and ELT2 are elements of the sequence being examined. | |
630 | |
631 The value that would be given by get_check_test_function() is returned in | |
632 *TEST_FUNC_OUT, which allows calling functions to do their own key checks | |
633 if they're processing one element at a time. | |
634 | |
635 Error if both TEST and TEST_NOT were specified, which Common Lisp says is | |
636 undefined behaviour. */ | |
637 | |
638 static check_test_func_t | |
639 get_check_match_function (Lisp_Object *test_inout, Lisp_Object test_not, | |
640 Lisp_Object if_, Lisp_Object if_not, | |
641 Lisp_Object key, Boolint *test_not_unboundp_out, | |
642 check_test_func_t *test_func_out) | |
643 { | |
644 return get_check_match_function_1 (Qunbound, test_inout, test_not, | |
645 if_, if_not, key, | |
646 test_not_unboundp_out, test_func_out); | |
647 } | |
202 | 648 |
203 | 649 |
204 DEFUN ("identity", Fidentity, 1, 1, 0, /* | 650 DEFUN ("identity", Fidentity, 1, 1, 0, /* |
205 Return the argument unchanged. | 651 Return the argument unchanged. |
206 */ | 652 */ |
364 signal_malformed_list_error (list); | 810 signal_malformed_list_error (list); |
365 } | 811 } |
366 | 812 |
367 return EQ (hare, tortoise) && len != 0 ? Qnil : make_int (len); | 813 return EQ (hare, tortoise) && len != 0 ? Qnil : make_int (len); |
368 } | 814 } |
369 | 815 |
816 static Lisp_Object string_count_from_end (Lisp_Object, Lisp_Object , | |
817 check_test_func_t, Boolint, | |
818 Lisp_Object, Lisp_Object, | |
819 Lisp_Object, Lisp_Object); | |
820 | |
821 static Lisp_Object list_count_from_end (Lisp_Object, Lisp_Object, | |
822 check_test_func_t, Boolint, | |
823 Lisp_Object, Lisp_Object, | |
824 Lisp_Object, Lisp_Object); | |
825 | |
826 /* Count the number of occurrences of ITEM in SEQUENCE; if SEQUENCE is a | |
827 list, store the cons cell of which the car is the last ITEM in SEQUENCE, | |
828 at the address given by tail_out. */ | |
829 | |
830 static Lisp_Object | |
831 count_with_tail (Lisp_Object *tail_out, int nargs, Lisp_Object *args, | |
832 Lisp_Object caller) | |
833 { | |
834 Lisp_Object item = args[0], sequence = args[1]; | |
835 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | |
836 Elemcount len, ii = 0, counting = EMACS_INT_MAX; | |
837 Boolint test_not_unboundp = 1; | |
838 check_test_func_t check_test = NULL; | |
839 | |
840 PARSE_KEYWORDS_8 (caller, nargs, args, 9, | |
841 (test, key, start, end, from_end, test_not, count, | |
842 if_, if_not), (start = Qzero), 2, 0); | |
843 | |
844 CHECK_SEQUENCE (sequence); | |
845 CHECK_NATNUM (start); | |
846 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
847 | |
848 if (!NILP (end)) | |
849 { | |
850 CHECK_NATNUM (end); | |
851 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
852 } | |
853 | |
854 if (!NILP (count)) | |
855 { | |
856 CHECK_INTEGER (count); | |
857 counting = BIGNUMP (count) ? EMACS_INT_MAX + 1 : XINT (count); | |
858 | |
859 /* Our callers should have filtered out non-positive COUNT. */ | |
860 assert (counting >= 0); | |
861 /* And we're not prepared to handle COUNT from any other caller at the | |
862 moment. */ | |
863 assert (EQ (caller, QremoveX)); | |
864 } | |
865 | |
866 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
867 key, &test_not_unboundp); | |
868 | |
869 *tail_out = Qnil; | |
870 | |
871 if (CONSP (sequence)) | |
872 { | |
873 Lisp_Object elt, tail = Qnil; | |
874 struct gcpro gcpro1; | |
875 | |
876 if (EQ (caller, Qcount) && !NILP (from_end) | |
877 && (!EQ (key, Qnil) || | |
878 check_test == check_other_nokey || check_test == check_if_nokey)) | |
879 { | |
880 /* #'count, #'count-if, and #'count-if-not are documented to have | |
881 a given traversal order if :from-end t is passed in, even | |
882 though forward traversal of the sequence has the same result | |
883 and is algorithmically less expensive for lists and strings. | |
884 This order isn't necessary for other callers, though. */ | |
885 return list_count_from_end (item, sequence, check_test, | |
886 test_not_unboundp, test, key, | |
887 start, end); | |
888 } | |
889 | |
890 GCPRO1 (tail); | |
891 | |
892 /* If COUNT is non-nil and FROM-END is t, we can give the tail | |
893 containing the last match, since that's what #'remove* is | |
894 interested in (a zero or negative COUNT won't ever reach | |
895 count_with_tail(), our callers will return immediately on seeing | |
896 it). */ | |
897 if (!NILP (count) && !NILP (from_end)) | |
898 { | |
899 counting = EMACS_INT_MAX; | |
900 } | |
901 | |
902 { | |
903 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
904 { | |
905 if (!(ii < ending)) | |
906 { | |
907 break; | |
908 } | |
909 | |
910 if (starting <= ii && | |
911 check_test (test, key, item, elt) == test_not_unboundp) | |
912 { | |
913 encountered++; | |
914 *tail_out = tail; | |
915 | |
916 if (encountered == counting) | |
917 { | |
918 break; | |
919 } | |
920 } | |
921 | |
922 ii++; | |
923 } | |
924 } | |
925 | |
926 UNGCPRO; | |
927 | |
928 if ((ii < starting || (ii < ending && !NILP (end))) && | |
929 encountered != counting) | |
930 { | |
931 check_sequence_range (args[1], start, end, Flength (args[1])); | |
932 } | |
933 } | |
934 else if (STRINGP (sequence)) | |
935 { | |
936 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp; | |
937 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | |
938 Lisp_Object character = Qnil; | |
939 | |
940 if (EQ (caller, Qcount) && !NILP (from_end) | |
941 && (!EQ (key, Qnil) || | |
942 check_test == check_other_nokey || check_test == check_if_nokey)) | |
943 { | |
944 /* See comment above in the list code. */ | |
945 return string_count_from_end (item, sequence, | |
946 check_test, test_not_unboundp, | |
947 test, key, start, end); | |
948 } | |
949 | |
950 while (cursor_offset < byte_len && ii < ending && encountered < counting) | |
951 { | |
952 if (ii >= starting) | |
953 { | |
954 character = make_char (itext_ichar (cursor)); | |
955 | |
956 if (check_test (test, key, item, character) | |
957 == test_not_unboundp) | |
958 { | |
959 encountered++; | |
960 } | |
961 | |
962 startp = XSTRING_DATA (sequence); | |
963 cursor = startp + cursor_offset; | |
964 if (byte_len != XSTRING_LENGTH (sequence) | |
965 || !valid_ibyteptr_p (cursor)) | |
966 { | |
967 mapping_interaction_error (caller, sequence); | |
968 } | |
969 } | |
970 | |
971 INC_IBYTEPTR (cursor); | |
972 cursor_offset = cursor - startp; | |
973 ii++; | |
974 } | |
975 | |
976 if (ii < starting || (ii < ending && !NILP (end))) | |
977 { | |
978 check_sequence_range (sequence, start, end, Flength (sequence)); | |
979 } | |
980 } | |
981 else | |
982 { | |
983 Lisp_Object object = Qnil; | |
984 | |
985 len = XINT (Flength (sequence)); | |
986 check_sequence_range (sequence, start, end, make_int (len)); | |
987 | |
988 ending = min (ending, len); | |
989 if (0 == len) | |
990 { | |
991 /* Catches the case where we have nil. */ | |
992 return make_integer (encountered); | |
993 } | |
994 | |
995 if (NILP (from_end)) | |
996 { | |
997 for (ii = starting; ii < ending && encountered < counting; ii++) | |
998 { | |
999 object = Faref (sequence, make_int (ii)); | |
1000 if (check_test (test, key, item, object) == test_not_unboundp) | |
1001 { | |
1002 encountered++; | |
1003 } | |
1004 } | |
1005 } | |
1006 else | |
1007 { | |
1008 for (ii = ending - 1; ii >= starting && encountered < counting; ii--) | |
1009 { | |
1010 object = Faref (sequence, make_int (ii)); | |
1011 if (check_test (test, key, item, object) == test_not_unboundp) | |
1012 { | |
1013 encountered++; | |
1014 } | |
1015 } | |
1016 } | |
1017 } | |
1018 | |
1019 return make_integer (encountered); | |
1020 } | |
1021 | |
1022 static Lisp_Object | |
1023 list_count_from_end (Lisp_Object item, Lisp_Object sequence, | |
1024 check_test_func_t check_test, Boolint test_not_unboundp, | |
1025 Lisp_Object test, Lisp_Object key, | |
1026 Lisp_Object start, Lisp_Object end) | |
1027 { | |
1028 Elemcount length = XINT (Flength (sequence)), ii = 0, starting = XINT (start); | |
1029 Elemcount ending = NILP (end) ? length : XINT (end), encountered = 0; | |
1030 Lisp_Object *storage; | |
1031 struct gcpro gcpro1; | |
1032 | |
1033 check_sequence_range (sequence, start, end, make_integer (length)); | |
1034 | |
1035 storage = alloca_array (Lisp_Object, ending - starting); | |
1036 | |
1037 { | |
1038 EXTERNAL_LIST_LOOP_2 (elt, sequence) | |
1039 { | |
1040 if (starting <= ii && ii < ending) | |
1041 { | |
1042 storage[ii - starting] = elt; | |
1043 } | |
1044 ii++; | |
1045 } | |
1046 } | |
1047 | |
1048 GCPRO1 (storage[0]); | |
1049 gcpro1.nvars = ending - starting; | |
1050 | |
1051 for (ii = ending - 1; ii >= starting; ii--) | |
1052 { | |
1053 if (check_test (test, key, item, storage[ii - starting]) | |
1054 == test_not_unboundp) | |
1055 { | |
1056 encountered++; | |
1057 } | |
1058 } | |
1059 | |
1060 UNGCPRO; | |
1061 | |
1062 return make_integer (encountered); | |
1063 } | |
1064 | |
1065 static Lisp_Object | |
1066 string_count_from_end (Lisp_Object item, Lisp_Object sequence, | |
1067 check_test_func_t check_test, Boolint test_not_unboundp, | |
1068 Lisp_Object test, Lisp_Object key, | |
1069 Lisp_Object start, Lisp_Object end) | |
1070 { | |
1071 Elemcount length = string_char_length (sequence), ii = 0; | |
1072 Elemcount starting = XINT (start), ending = NILP (end) ? length : XINT (end); | |
1073 Elemcount encountered = 0; | |
1074 Ibyte *cursor = XSTRING_DATA (sequence); | |
1075 Ibyte *endp = cursor + XSTRING_LENGTH (sequence); | |
1076 Ichar *storage; | |
1077 | |
1078 check_sequence_range (sequence, start, end, make_integer (length)); | |
1079 | |
1080 storage = alloca_array (Ichar, ending - starting); | |
1081 | |
1082 while (cursor < endp && ii < ending) | |
1083 { | |
1084 if (starting <= ii && ii < ending) | |
1085 { | |
1086 storage [ii - starting] = itext_ichar (cursor); | |
1087 } | |
1088 | |
1089 ii++; | |
1090 INC_IBYTEPTR (cursor); | |
1091 } | |
1092 | |
1093 for (ii = ending - 1; ii >= starting; ii--) | |
1094 { | |
1095 if (check_test (test, key, item, make_char (storage [ii - starting])) | |
1096 == test_not_unboundp) | |
1097 { | |
1098 encountered++; | |
1099 } | |
1100 } | |
1101 | |
1102 return make_integer (encountered); | |
1103 } | |
1104 | |
1105 DEFUN ("count", Fcount, 2, MANY, 0, /* | |
1106 Count the number of occurrences of ITEM in SEQUENCE. | |
1107 | |
1108 See `remove*' for the meaning of the keywords. | |
1109 | |
1110 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | |
1111 */ | |
1112 (int nargs, Lisp_Object *args)) | |
1113 { | |
1114 Lisp_Object tail = Qnil; | |
1115 | |
1116 /* count_with_tail() accepts more keywords than we do, check those we've | |
1117 been given. */ | |
1118 PARSE_KEYWORDS (Fcount, nargs, args, 8, | |
1119 (test, test_not, if_, if_not, key, start, end, from_end), | |
1120 NULL); | |
1121 | |
1122 return count_with_tail (&tail, nargs, args, Qcount); | |
1123 } | |
1124 | |
370 /*** string functions. ***/ | 1125 /*** string functions. ***/ |
371 | 1126 |
372 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /* | 1127 DEFUN ("string-equal", Fstring_equal, 2, 2, 0, /* |
373 Return t if two strings have identical contents. | 1128 Return t if two strings have identical contents. |
374 Case is significant. Text properties are ignored. | 1129 Case is significant. Text properties are ignored. |
1000 } | 1755 } |
1001 | 1756 |
1002 Lisp_Object | 1757 Lisp_Object |
1003 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth) | 1758 safe_copy_tree (Lisp_Object arg, Lisp_Object vecp, int depth) |
1004 { | 1759 { |
1005 if (depth > 200) | 1760 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
1006 stack_overflow ("Stack overflow in copy-tree", arg); | 1761 stack_overflow ("Stack overflow in copy-tree", arg); |
1007 | 1762 |
1008 if (CONSP (arg)) | 1763 if (CONSP (arg)) |
1009 { | 1764 { |
1010 Lisp_Object rest; | 1765 Lisp_Object rest; |
1740 return tail; | 2495 return tail; |
1741 } | 2496 } |
1742 return Qnil; | 2497 return Qnil; |
1743 } | 2498 } |
1744 | 2499 |
2500 /* Return the first index of ITEM in LIST. In CONS_OUT, return the cons cell | |
2501 before that containing the element. If the element is in the first cons | |
2502 cell, return Qnil in CONS_OUT. TEST, KEY, START, END are as in | |
2503 #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should have been initialized | |
2504 with get_check_match_function() or get_check_test_function(). A non-zero | |
2505 REVERSE_TEST_ORDER means call TEST with the element from LIST as its | |
2506 first argument and ITEM as its second. Error if LIST is ill-formed, or | |
2507 circular. */ | |
2508 static Lisp_Object | |
2509 list_position_cons_before (Lisp_Object *cons_out, | |
2510 Lisp_Object item, Lisp_Object list, | |
2511 check_test_func_t check_test, | |
2512 Boolint test_not_unboundp, | |
2513 Lisp_Object test, Lisp_Object key, | |
2514 Boolint reverse_test_order, | |
2515 Lisp_Object start, Lisp_Object end) | |
2516 { | |
2517 struct gcpro gcpro1, gcpro2; | |
2518 Lisp_Object elt = Qnil, tail = list, tail_before = Qnil; | |
2519 Elemcount len, ii = 0, starting = XINT (start); | |
2520 Elemcount ending = NILP (end) ? EMACS_INT_MAX : XINT (end); | |
2521 | |
2522 GCPRO2 (elt, tail); | |
2523 | |
2524 if (check_test == check_eq_nokey) | |
2525 { | |
2526 /* TEST is #'eq, no need to call any C functions, and the test order | |
2527 won't be visible. */ | |
2528 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
2529 { | |
2530 if (starting <= ii && ii < ending && | |
2531 EQ (item, elt) == test_not_unboundp) | |
2532 { | |
2533 *cons_out = tail_before; | |
2534 RETURN_UNGCPRO (make_integer (ii)); | |
2535 } | |
2536 else | |
2537 { | |
2538 if (ii >= ending) | |
2539 { | |
2540 break; | |
2541 } | |
2542 } | |
2543 ii++; | |
2544 tail_before = tail; | |
2545 } | |
2546 } | |
2547 else | |
2548 { | |
2549 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
2550 { | |
2551 if (starting <= ii && ii < ending && | |
2552 (reverse_test_order ? | |
2553 check_test (test, key, elt, item) : | |
2554 check_test (test, key, item, elt)) == test_not_unboundp) | |
2555 { | |
2556 *cons_out = tail_before; | |
2557 RETURN_UNGCPRO (make_integer (ii)); | |
2558 } | |
2559 else | |
2560 { | |
2561 if (ii >= ending) | |
2562 { | |
2563 break; | |
2564 } | |
2565 } | |
2566 ii++; | |
2567 tail_before = tail; | |
2568 } | |
2569 } | |
2570 | |
2571 RETURN_UNGCPRO (Qnil); | |
2572 } | |
2573 | |
2574 DEFUN ("member*", FmemberX, 2, MANY, 0, /* | |
2575 Return the first sublist of LIST with car ITEM, or nil if no such sublist. | |
2576 | |
2577 The keyword :test specifies a two-argument function that is used to compare | |
2578 ITEM with elements in LIST; if omitted, it defaults to `eql'. | |
2579 | |
2580 The keyword :test-not is similar, but specifies a negated function. That | |
2581 is, ITEM is considered equal to an element in LIST if the given function | |
2582 returns nil. Common Lisp deprecates :test-not, and if both are specified, | |
2583 XEmacs signals an error. | |
2584 | |
2585 :key specifies a one-argument function that transforms elements of LIST into | |
2586 \"comparison keys\" before the test predicate is applied. For example, | |
2587 if :key is #'car, then ITEM is compared with the car of elements from LIST. | |
2588 The :key function, however, is not applied to ITEM, and does not affect the | |
2589 elements in the returned list, which are taken directly from the elements in | |
2590 LIST. | |
2591 | |
2592 arguments: (ITEM LIST &key (TEST #'eql) TEST-NOT (KEY #'identity)) | |
2593 */ | |
2594 (int nargs, Lisp_Object *args)) | |
2595 { | |
2596 Lisp_Object item = args[0], list = args[1], result = Qnil, position0; | |
2597 Boolint test_not_unboundp = 1; | |
2598 check_test_func_t check_test = NULL; | |
2599 | |
2600 PARSE_KEYWORDS (FmemberX, nargs, args, 5, (test, if_not, if_, test_not, key), | |
2601 NULL); | |
2602 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
2603 key, &test_not_unboundp); | |
2604 position0 | |
2605 = list_position_cons_before (&result, item, list, check_test, | |
2606 test_not_unboundp, test, key, 0, Qzero, Qnil); | |
2607 | |
2608 return CONSP (result) ? XCDR (result) : ZEROP (position0) ? list : Qnil; | |
2609 } | |
2610 | |
2611 /* This macro might eventually find a better home than here. */ | |
2612 | |
2613 #define CHECK_KEY_ARGUMENT(key) \ | |
2614 do { \ | |
2615 if (NILP (key)) \ | |
2616 { \ | |
2617 key = Qidentity; \ | |
2618 } \ | |
2619 \ | |
2620 if (!EQ (key, Qidentity)) \ | |
2621 { \ | |
2622 key = indirect_function (key, 1); \ | |
2623 if (EQ (key, XSYMBOL_FUNCTION (Qidentity))) \ | |
2624 { \ | |
2625 key = Qidentity; \ | |
2626 } \ | |
2627 } \ | |
2628 } while (0) | |
2629 | |
2630 #define KEY(key, item) (EQ (Qidentity, key) ? item : \ | |
2631 IGNORE_MULTIPLE_VALUES (call1 (key, item))) | |
2632 | |
2633 DEFUN ("adjoin", Fadjoin, 2, MANY, 0, /* | |
2634 Return ITEM consed onto the front of LIST, if not already in LIST. | |
2635 | |
2636 Otherwise, return LIST unmodified. | |
2637 | |
2638 See `member*' for the meaning of the keywords. | |
2639 | |
2640 arguments: (ITEM LIST &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
2641 */ | |
2642 (int nargs, Lisp_Object *args)) | |
2643 { | |
2644 Lisp_Object item = args[0], list = args[1], keyed = Qnil, ignore = Qnil; | |
2645 struct gcpro gcpro1; | |
2646 Boolint test_not_unboundp = 1; | |
2647 check_test_func_t check_test = NULL; | |
2648 | |
2649 PARSE_KEYWORDS (Fadjoin, nargs, args, 3, (test, key, test_not), | |
2650 NULL); | |
2651 | |
2652 CHECK_KEY_ARGUMENT (key); | |
2653 | |
2654 keyed = KEY (key, item); | |
2655 | |
2656 GCPRO1 (keyed); | |
2657 check_test = get_check_test_function (keyed, &test, test_not, Qnil, Qnil, | |
2658 key, &test_not_unboundp); | |
2659 if (NILP (list_position_cons_before (&ignore, keyed, list, check_test, | |
2660 test_not_unboundp, test, key, 0, Qzero, | |
2661 Qnil))) | |
2662 { | |
2663 RETURN_UNGCPRO (Fcons (item, list)); | |
2664 } | |
2665 | |
2666 RETURN_UNGCPRO (list); | |
2667 } | |
2668 | |
1745 DEFUN ("assoc", Fassoc, 2, 2, 0, /* | 2669 DEFUN ("assoc", Fassoc, 2, 2, 0, /* |
1746 Return non-nil if KEY is `equal' to the car of an element of ALIST. | 2670 Return non-nil if KEY is `equal' to the car of an element of ALIST. |
1747 The value is actually the element of ALIST whose car equals KEY. | 2671 The value is actually the element of ALIST whose car equals KEY. |
1748 */ | 2672 */ |
1749 (key, alist)) | 2673 (key, alist)) |
1826 return elt; | 2750 return elt; |
1827 } | 2751 } |
1828 return Qnil; | 2752 return Qnil; |
1829 } | 2753 } |
1830 | 2754 |
2755 DEFUN ("assoc*", FassocX, 2, MANY, 0, /* | |
2756 Find the first item whose car matches ITEM in ALIST. | |
2757 | |
2758 See `member*' for the meaning of :test, :test-not and :key. | |
2759 | |
2760 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
2761 */ | |
2762 (int nargs, Lisp_Object *args)) | |
2763 { | |
2764 Lisp_Object item = args[0], alist = args[1]; | |
2765 Boolint test_not_unboundp = 1; | |
2766 check_test_func_t check_test = NULL; | |
2767 | |
2768 PARSE_KEYWORDS (FassocX, nargs, args, 5, (test, if_, if_not, test_not, key), | |
2769 NULL); | |
2770 | |
2771 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
2772 key, &test_not_unboundp); | |
2773 | |
2774 if (check_test == check_eq_nokey) | |
2775 { | |
2776 /* TEST is #'eq, no need to call any C functions. */ | |
2777 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist) | |
2778 { | |
2779 if (EQ (item, elt_car) == test_not_unboundp) | |
2780 { | |
2781 return elt; | |
2782 } | |
2783 } | |
2784 } | |
2785 else | |
2786 { | |
2787 Lisp_Object tailed = alist; | |
2788 struct gcpro gcpro1; | |
2789 | |
2790 GCPRO1 (tailed); | |
2791 { | |
2792 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
2793 { | |
2794 tailed = tail; | |
2795 | |
2796 if (check_test (test, key, item, elt_car) == test_not_unboundp) | |
2797 { | |
2798 RETURN_UNGCPRO (elt); | |
2799 } | |
2800 } | |
2801 } | |
2802 UNGCPRO; | |
2803 } | |
2804 | |
2805 return Qnil; | |
2806 } | |
2807 | |
1831 DEFUN ("rassoc", Frassoc, 2, 2, 0, /* | 2808 DEFUN ("rassoc", Frassoc, 2, 2, 0, /* |
1832 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST. | 2809 Return non-nil if VALUE is `equal' to the cdr of an element of ALIST. |
1833 The value is actually the element of ALIST whose cdr equals VALUE. | 2810 The value is actually the element of ALIST whose cdr equals VALUE. |
1834 */ | 2811 */ |
1835 (value, alist)) | 2812 (value, alist)) |
1896 return elt; | 2873 return elt; |
1897 } | 2874 } |
1898 return Qnil; | 2875 return Qnil; |
1899 } | 2876 } |
1900 | 2877 |
2878 DEFUN ("rassoc*", FrassocX, 2, MANY, 0, /* | |
2879 Find the first item whose cdr matches ITEM in ALIST. | |
2880 | |
2881 See `member*' for the meaning of :test, :test-not and :key. | |
2882 | |
2883 arguments: (ITEM ALIST &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
2884 */ | |
2885 (int nargs, Lisp_Object *args)) | |
2886 { | |
2887 Lisp_Object item = args[0], alist = args[1]; | |
2888 Boolint test_not_unboundp = 1; | |
2889 check_test_func_t check_test = NULL; | |
2890 | |
2891 PARSE_KEYWORDS (FrassocX, nargs, args, 5, (test, if_, if_not, test_not, key), | |
2892 NULL); | |
2893 | |
2894 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
2895 key, &test_not_unboundp); | |
2896 | |
2897 if (check_test == check_eq_nokey) | |
2898 { | |
2899 /* TEST is #'eq, no need to call any C functions. */ | |
2900 EXTERNAL_ALIST_LOOP_4 (elt, elt_car, elt_cdr, alist) | |
2901 { | |
2902 if (EQ (item, elt_cdr) == test_not_unboundp) | |
2903 { | |
2904 return elt; | |
2905 } | |
2906 } | |
2907 } | |
2908 else | |
2909 { | |
2910 struct gcpro gcpro1; | |
2911 Lisp_Object tailed = alist; | |
2912 | |
2913 GCPRO1 (tailed); | |
2914 { | |
2915 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
2916 { | |
2917 tailed = tail; | |
2918 | |
2919 if (check_test (test, key, item, elt_cdr) == test_not_unboundp) | |
2920 { | |
2921 RETURN_UNGCPRO (elt); | |
2922 } | |
2923 } | |
2924 } | |
2925 UNGCPRO; | |
2926 } | |
2927 | |
2928 return Qnil; | |
2929 } | |
2930 | |
2931 /* This is the implementation of both #'find and #'position. */ | |
2932 static Lisp_Object | |
2933 position (Lisp_Object *object_out, Lisp_Object item, Lisp_Object sequence, | |
2934 check_test_func_t check_test, Boolint test_not_unboundp, | |
2935 Lisp_Object test, Lisp_Object key, Lisp_Object start, Lisp_Object end, | |
2936 Lisp_Object from_end, Lisp_Object default_, Lisp_Object caller) | |
2937 { | |
2938 Lisp_Object result = Qnil; | |
2939 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0; | |
2940 | |
2941 CHECK_SEQUENCE (sequence); | |
2942 CHECK_NATNUM (start); | |
2943 starting = INTP (start) ? XINT (start) : 1 + EMACS_INT_MAX; | |
2944 | |
2945 if (!NILP (end)) | |
2946 { | |
2947 CHECK_NATNUM (end); | |
2948 ending = INTP (end) ? XINT (end) : 1 + EMACS_INT_MAX; | |
2949 } | |
2950 | |
2951 *object_out = default_; | |
2952 | |
2953 if (CONSP (sequence)) | |
2954 { | |
2955 Lisp_Object elt, tail = Qnil; | |
2956 struct gcpro gcpro1; | |
2957 | |
2958 if (!(starting < ending)) | |
2959 { | |
2960 check_sequence_range (sequence, start, end, Flength (sequence)); | |
2961 /* starting could be equal to ending, in which case nil is what | |
2962 we want to return. */ | |
2963 return Qnil; | |
2964 } | |
2965 | |
2966 GCPRO1 (tail); | |
2967 | |
2968 { | |
2969 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
2970 { | |
2971 if (starting <= ii && ii < ending | |
2972 && check_test (test, key, item, elt) == test_not_unboundp) | |
2973 { | |
2974 result = make_integer (ii); | |
2975 *object_out = elt; | |
2976 | |
2977 if (NILP (from_end)) | |
2978 { | |
2979 UNGCPRO; | |
2980 return result; | |
2981 } | |
2982 } | |
2983 else if (ii == ending) | |
2984 { | |
2985 break; | |
2986 } | |
2987 | |
2988 ii++; | |
2989 } | |
2990 } | |
2991 | |
2992 UNGCPRO; | |
2993 | |
2994 if (ii < starting || (ii < ending && !NILP (end))) | |
2995 { | |
2996 check_sequence_range (sequence, start, end, Flength (sequence)); | |
2997 } | |
2998 } | |
2999 else if (STRINGP (sequence)) | |
3000 { | |
3001 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp; | |
3002 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | |
3003 Lisp_Object character = Qnil; | |
3004 | |
3005 while (cursor_offset < byte_len && ii < ending) | |
3006 { | |
3007 if (ii >= starting) | |
3008 { | |
3009 character = make_char (itext_ichar (cursor)); | |
3010 | |
3011 if (check_test (test, key, item, character) == test_not_unboundp) | |
3012 { | |
3013 result = make_integer (ii); | |
3014 *object_out = character; | |
3015 | |
3016 if (NILP (from_end)) | |
3017 { | |
3018 return result; | |
3019 } | |
3020 } | |
3021 | |
3022 startp = XSTRING_DATA (sequence); | |
3023 cursor = startp + cursor_offset; | |
3024 if (byte_len != XSTRING_LENGTH (sequence) | |
3025 || !valid_ibyteptr_p (cursor)) | |
3026 { | |
3027 mapping_interaction_error (caller, sequence); | |
3028 } | |
3029 } | |
3030 | |
3031 INC_IBYTEPTR (cursor); | |
3032 cursor_offset = cursor - startp; | |
3033 ii++; | |
3034 } | |
3035 | |
3036 if (ii < starting || (ii < ending && !NILP (end))) | |
3037 { | |
3038 check_sequence_range (sequence, start, end, Flength (sequence)); | |
3039 } | |
3040 } | |
3041 else | |
3042 { | |
3043 Lisp_Object object = Qnil; | |
3044 len = XINT (Flength (sequence)); | |
3045 check_sequence_range (sequence, start, end, make_int (len)); | |
3046 | |
3047 ending = min (ending, len); | |
3048 if (0 == len) | |
3049 { | |
3050 /* Catches the case where we have nil. */ | |
3051 return result; | |
3052 } | |
3053 | |
3054 if (NILP (from_end)) | |
3055 { | |
3056 for (ii = starting; ii < ending; ii++) | |
3057 { | |
3058 object = Faref (sequence, make_int (ii)); | |
3059 if (check_test (test, key, item, object) == test_not_unboundp) | |
3060 { | |
3061 result = make_integer (ii); | |
3062 *object_out = object; | |
3063 return result; | |
3064 } | |
3065 } | |
3066 } | |
3067 else | |
3068 { | |
3069 for (ii = ending - 1; ii >= starting; ii--) | |
3070 { | |
3071 object = Faref (sequence, make_int (ii)); | |
3072 if (check_test (test, key, item, object) == test_not_unboundp) | |
3073 { | |
3074 result = make_integer (ii); | |
3075 *object_out = object; | |
3076 return result; | |
3077 } | |
3078 } | |
3079 } | |
3080 } | |
3081 | |
3082 return result; | |
3083 } | |
3084 | |
3085 DEFUN ("position", Fposition, 2, MANY, 0, /* | |
3086 Return the index of the first occurrence of ITEM in SEQUENCE. | |
3087 | |
3088 Return nil if not found. See `remove*' for the meaning of the keywords. | |
3089 | |
3090 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END TEST-NOT) | |
3091 */ | |
3092 (int nargs, Lisp_Object *args)) | |
3093 { | |
3094 Lisp_Object object = Qnil, item = args[0], sequence = args[1]; | |
3095 Boolint test_not_unboundp = 1; | |
3096 check_test_func_t check_test = NULL; | |
3097 | |
3098 PARSE_KEYWORDS (Fposition, nargs, args, 8, | |
3099 (test, if_, test_not, if_not, key, start, end, from_end), | |
3100 (start = Qzero)); | |
3101 | |
3102 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3103 key, &test_not_unboundp); | |
3104 | |
3105 return position (&object, item, sequence, check_test, test_not_unboundp, | |
3106 test, key, start, end, from_end, Qnil, Qposition); | |
3107 } | |
3108 | |
3109 DEFUN ("find", Ffind, 2, MANY, 0, /* | |
3110 Find the first occurrence of ITEM in SEQUENCE. | |
3111 | |
3112 Return the matching ITEM, or nil if not found. See `remove*' for the | |
3113 meaning of the keywords. | |
3114 | |
3115 The keyword :default, not specified by Common Lisp, designates an object to | |
3116 return instead of nil if ITEM is not found. | |
3117 | |
3118 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) DEFAULT FROM-END TEST-NOT) | |
3119 */ | |
3120 (int nargs, Lisp_Object *args)) | |
3121 { | |
3122 Lisp_Object object = Qnil, item = args[0], sequence = args[1]; | |
3123 Boolint test_not_unboundp = 1; | |
3124 check_test_func_t check_test = NULL; | |
3125 | |
3126 PARSE_KEYWORDS (Fposition, nargs, args, 9, | |
3127 (test, if_, test_not, if_not, key, start, end, from_end, | |
3128 default_), | |
3129 (start = Qzero)); | |
3130 | |
3131 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3132 key, &test_not_unboundp); | |
3133 | |
3134 position (&object, item, sequence, check_test, test_not_unboundp, | |
3135 test, key, start, end, from_end, Qnil, Qposition); | |
3136 | |
3137 return object; | |
3138 } | |
1901 | 3139 |
1902 DEFUN ("delete", Fdelete, 2, 2, 0, /* | 3140 DEFUN ("delete", Fdelete, 2, 2, 0, /* |
1903 Delete by side effect any occurrences of ELT as a member of LIST. | 3141 Delete by side effect any occurrences of ELT as a member of LIST. |
1904 The modified LIST is returned. Comparison is done with `equal'. | 3142 The modified LIST is returned. Comparison is done with `equal'. |
1905 If the first member of LIST is ELT, there is no way to remove it by side | 3143 If the first member of LIST is ELT, there is no way to remove it by side |
2000 } | 3238 } |
2001 } | 3239 } |
2002 return list; | 3240 return list; |
2003 } | 3241 } |
2004 | 3242 |
3243 DEFUN ("delete*", FdeleteX, 2, MANY, 0, /* | |
3244 Remove all occurrences of ITEM in SEQUENCE, destructively. | |
3245 | |
3246 If SEQUENCE is a non-nil list, this modifies the list directly. A non-list | |
3247 SEQUENCE will not be destructively modified, rather, if ITEM occurs in it, a | |
3248 new SEQUENCE of the same type without ITEM will be returned. | |
3249 | |
3250 See `remove*' for a non-destructive alternative, and for explanation of the | |
3251 keyword arguments. | |
3252 | |
3253 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) | |
3254 */ | |
3255 (int nargs, Lisp_Object *args)) | |
3256 { | |
3257 Lisp_Object item = args[0], sequence = args[1], tail = sequence; | |
3258 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; | |
3259 Elemcount len, ii = 0, encountered = 0, presenting = 0; | |
3260 Boolint test_not_unboundp = 1; | |
3261 check_test_func_t check_test = NULL; | |
3262 struct gcpro gcpro1; | |
3263 | |
3264 PARSE_KEYWORDS (FdeleteX, nargs, args, 9, | |
3265 (test, if_not, if_, test_not, key, start, end, from_end, | |
3266 count), (start = Qzero, count = Qunbound)); | |
3267 | |
3268 CHECK_SEQUENCE (sequence); | |
3269 CHECK_NATNUM (start); | |
3270 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
3271 | |
3272 if (!NILP (end)) | |
3273 { | |
3274 CHECK_NATNUM (end); | |
3275 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
3276 } | |
3277 | |
3278 if (!UNBOUNDP (count)) | |
3279 { | |
3280 if (!NILP (count)) | |
3281 { | |
3282 CHECK_INTEGER (count); | |
3283 if (BIGNUMP (count)) | |
3284 { | |
3285 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
3286 1 + EMACS_INT_MAX : EMACS_INT_MIN - 1; | |
3287 } | |
3288 else | |
3289 { | |
3290 counting = XINT (count); | |
3291 } | |
3292 | |
3293 if (counting < 1) | |
3294 { | |
3295 return sequence; | |
3296 } | |
3297 } | |
3298 } | |
3299 | |
3300 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3301 key, &test_not_unboundp); | |
3302 | |
3303 if (CONSP (sequence)) | |
3304 { | |
3305 Lisp_Object prev_tail_list_elt = Qnil, list_elt = Qnil; | |
3306 Elemcount list_len = 0, deleted = 0; | |
3307 | |
3308 if (!NILP (count) && !NILP (from_end)) | |
3309 { | |
3310 /* Both COUNT and FROM-END were specified; we need to traverse the | |
3311 list twice. */ | |
3312 Lisp_Object present = count_with_tail (&list_elt, nargs, args, | |
3313 QdeleteX); | |
3314 | |
3315 if (ZEROP (present)) | |
3316 { | |
3317 return sequence; | |
3318 } | |
3319 | |
3320 presenting = XINT (present); | |
3321 | |
3322 /* If there are fewer items in the list than we have permission to | |
3323 delete, we don't need to differentiate between the :from-end | |
3324 nil and :from-end t cases. Otherwise, presenting is the number | |
3325 of matching items we need to ignore before we start to | |
3326 delete. */ | |
3327 presenting = presenting <= counting ? 0 : presenting - counting; | |
3328 } | |
3329 | |
3330 GCPRO1 (tail); | |
3331 ii = -1; | |
3332 | |
3333 { | |
3334 EXTERNAL_LIST_LOOP_4_NO_DECLARE (list_elt, sequence, tail, list_len) | |
3335 { | |
3336 ii++; | |
3337 | |
3338 if (starting <= ii && ii < ending && | |
3339 (check_test (test, key, item, list_elt) == test_not_unboundp) | |
3340 && (presenting ? encountered++ >= presenting | |
3341 : encountered++ < counting)) | |
3342 { | |
3343 if (NILP (prev_tail_list_elt)) | |
3344 { | |
3345 sequence = XCDR (tail); | |
3346 } | |
3347 else | |
3348 { | |
3349 XSETCDR (prev_tail_list_elt, XCDR (tail)); | |
3350 } | |
3351 | |
3352 /* Keep tortoise from ever passing hare. */ | |
3353 list_len = 0; | |
3354 deleted++; | |
3355 } | |
3356 else | |
3357 { | |
3358 prev_tail_list_elt = tail; | |
3359 if (ii >= ending || (!presenting && encountered > counting)) | |
3360 { | |
3361 break; | |
3362 } | |
3363 } | |
3364 } | |
3365 } | |
3366 | |
3367 UNGCPRO; | |
3368 | |
3369 if ((ii < starting || (ii < ending && !NILP (end))) && | |
3370 !(presenting ? encountered == presenting : encountered == counting)) | |
3371 { | |
3372 check_sequence_range (args[1], start, end, | |
3373 make_int (deleted + XINT (Flength (args[1])))); | |
3374 } | |
3375 | |
3376 return sequence; | |
3377 } | |
3378 else if (STRINGP (sequence)) | |
3379 { | |
3380 Ibyte *staging = alloca_ibytes (XSTRING_LENGTH (sequence)); | |
3381 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence); | |
3382 Ibyte *cursor = startp; | |
3383 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence); | |
3384 Lisp_Object character, result = sequence; | |
3385 | |
3386 if (!NILP (count) && !NILP (from_end)) | |
3387 { | |
3388 Lisp_Object present = count_with_tail (&character, nargs, args, | |
3389 QdeleteX); | |
3390 | |
3391 if (ZEROP (present)) | |
3392 { | |
3393 return sequence; | |
3394 } | |
3395 | |
3396 presenting = XINT (present); | |
3397 | |
3398 /* If there are fewer items in the list than we have permission to | |
3399 delete, we don't need to differentiate between the :from-end | |
3400 nil and :from-end t cases. Otherwise, presenting is the number | |
3401 of matching items we need to ignore before we start to | |
3402 delete. */ | |
3403 presenting = presenting <= counting ? 0 : presenting - counting; | |
3404 } | |
3405 | |
3406 ii = 0; | |
3407 while (cursor_offset < byte_len) | |
3408 { | |
3409 if (ii >= starting && ii < ending) | |
3410 { | |
3411 character = make_char (itext_ichar (cursor)); | |
3412 | |
3413 if ((check_test (test, key, item, character) | |
3414 == test_not_unboundp) | |
3415 && (presenting ? encountered++ >= presenting : | |
3416 encountered++ < counting)) | |
3417 { | |
3418 DO_NOTHING; | |
3419 } | |
3420 else | |
3421 { | |
3422 staging_cursor | |
3423 += set_itext_ichar (staging_cursor, XCHAR (character)); | |
3424 } | |
3425 | |
3426 startp = XSTRING_DATA (sequence); | |
3427 cursor = startp + cursor_offset; | |
3428 if (byte_len != XSTRING_LENGTH (sequence) | |
3429 || !valid_ibyteptr_p (cursor)) | |
3430 { | |
3431 mapping_interaction_error (QdeleteX, sequence); | |
3432 } | |
3433 } | |
3434 else | |
3435 { | |
3436 staging_cursor += itext_copy_ichar (cursor, staging_cursor); | |
3437 } | |
3438 | |
3439 INC_IBYTEPTR (cursor); | |
3440 cursor_offset = cursor - startp; | |
3441 ii++; | |
3442 } | |
3443 | |
3444 if (ii < starting || (ii < ending && !NILP (end))) | |
3445 { | |
3446 check_sequence_range (sequence, start, end, Flength (sequence)); | |
3447 } | |
3448 | |
3449 if (0 != encountered) | |
3450 { | |
3451 result = make_string (staging, staging_cursor - staging); | |
3452 copy_string_extents (result, sequence, 0, 0, | |
3453 staging_cursor - staging); | |
3454 sequence = result; | |
3455 } | |
3456 | |
3457 return sequence; | |
3458 } | |
3459 else | |
3460 { | |
3461 Lisp_Object position0 = Qnil, object = Qnil; | |
3462 Lisp_Object *staging = NULL, *staging_cursor, *staging_limit; | |
3463 Elemcount positioning; | |
3464 | |
3465 len = XINT (Flength (sequence)); | |
3466 | |
3467 check_sequence_range (sequence, start, end, make_int (len)); | |
3468 | |
3469 position0 = position (&object, item, sequence, check_test, | |
3470 test_not_unboundp, test, key, start, end, | |
3471 from_end, Qnil, QdeleteX); | |
3472 if (NILP (position0)) | |
3473 { | |
3474 return sequence; | |
3475 } | |
3476 | |
3477 ending = min (ending, len); | |
3478 positioning = XINT (position0); | |
3479 encountered = 1; | |
3480 | |
3481 if (NILP (from_end)) | |
3482 { | |
3483 staging = alloca_array (Lisp_Object, len - 1); | |
3484 staging_cursor = staging; | |
3485 | |
3486 ii = 0; | |
3487 while (ii < positioning) | |
3488 { | |
3489 *staging_cursor++ = Faref (sequence, make_int (ii)); | |
3490 ii++; | |
3491 } | |
3492 | |
3493 ii = positioning + 1; | |
3494 while (ii < ending) | |
3495 { | |
3496 object = Faref (sequence, make_int (ii)); | |
3497 if (encountered < counting | |
3498 && (check_test (test, key, item, object) | |
3499 == test_not_unboundp)) | |
3500 { | |
3501 encountered++; | |
3502 } | |
3503 else | |
3504 { | |
3505 *staging_cursor++ = object; | |
3506 } | |
3507 ii++; | |
3508 } | |
3509 | |
3510 while (ii < len) | |
3511 { | |
3512 *staging_cursor++ = Faref (sequence, make_int (ii)); | |
3513 ii++; | |
3514 } | |
3515 } | |
3516 else | |
3517 { | |
3518 staging = alloca_array (Lisp_Object, len - 1); | |
3519 staging_cursor = staging_limit = staging + len - 1; | |
3520 | |
3521 ii = len - 1; | |
3522 while (ii > positioning) | |
3523 { | |
3524 *--staging_cursor = Faref (sequence, make_int (ii)); | |
3525 ii--; | |
3526 } | |
3527 | |
3528 ii = positioning - 1; | |
3529 while (ii >= starting) | |
3530 { | |
3531 object = Faref (sequence, make_int (ii)); | |
3532 if (encountered < counting | |
3533 && (check_test (test, key, item, object) == | |
3534 test_not_unboundp)) | |
3535 { | |
3536 encountered++; | |
3537 } | |
3538 else | |
3539 { | |
3540 *--staging_cursor = object; | |
3541 } | |
3542 | |
3543 ii--; | |
3544 } | |
3545 | |
3546 while (ii >= 0) | |
3547 { | |
3548 *--staging_cursor = Faref (sequence, make_int (ii)); | |
3549 ii--; | |
3550 } | |
3551 | |
3552 staging = staging_cursor; | |
3553 staging_cursor = staging_limit; | |
3554 } | |
3555 | |
3556 if (VECTORP (sequence)) | |
3557 { | |
3558 return Fvector (staging_cursor - staging, staging); | |
3559 } | |
3560 else if (BIT_VECTORP (sequence)) | |
3561 { | |
3562 return Fbit_vector (staging_cursor - staging, staging); | |
3563 } | |
3564 | |
3565 /* A nil sequence will have given us a nil #'position, | |
3566 above. */ | |
3567 ABORT (); | |
3568 | |
3569 return Qnil; | |
3570 } | |
3571 } | |
3572 | |
3573 DEFUN ("remove*", FremoveX, 2, MANY, 0, /* | |
3574 Remove all occurrences of ITEM in SEQUENCE, non-destructively. | |
3575 | |
3576 If SEQUENCE is a list, `remove*' makes a copy if that is necessary to avoid | |
3577 corrupting the original SEQUENCE. | |
3578 | |
3579 The keywords :test and :test-not specify two-argument test and negated-test | |
3580 predicates, respectively; :test defaults to `eql'. :key specifies a | |
3581 one-argument function that transforms elements of SEQUENCE into \"comparison | |
3582 keys\" before the test predicate is applied. See `member*' for more | |
3583 information on these keywords. | |
3584 | |
3585 :start and :end, if given, specify indices of a subsequence of SEQUENCE to | |
3586 be processed. Indices are 0-based and processing involves the subsequence | |
3587 starting at the index given by :start and ending just before the index given | |
3588 by :end. | |
3589 | |
3590 :count, if given, limits the number of items removed to the number | |
3591 specified. :from-end, if given, causes processing to proceed starting from | |
3592 the end instead of the beginning; in this case, this matters only if :count | |
3593 is given. | |
3594 | |
3595 arguments: (ITEM SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT TEST-NOT) | |
3596 */ | |
3597 (int nargs, Lisp_Object *args)) | |
3598 { | |
3599 Lisp_Object item = args[0], sequence = args[1], matched_count = Qnil, | |
3600 tail = Qnil; | |
3601 Elemcount starting = 0, ending = EMACS_INT_MAX, counting = EMACS_INT_MAX; | |
3602 Elemcount len, ii = 0, encountered = 0, presenting = 0; | |
3603 Boolint test_not_unboundp = 1; | |
3604 check_test_func_t check_test = NULL; | |
3605 struct gcpro gcpro1; | |
3606 | |
3607 PARSE_KEYWORDS (FremoveX, nargs, args, 9, | |
3608 (test, if_not, if_, test_not, key, start, end, from_end, | |
3609 count), (start = Qzero)); | |
3610 | |
3611 if (!CONSP (sequence)) | |
3612 { | |
3613 return FdeleteX (nargs, args); | |
3614 } | |
3615 | |
3616 CHECK_NATNUM (start); | |
3617 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
3618 | |
3619 if (!NILP (end)) | |
3620 { | |
3621 CHECK_NATNUM (end); | |
3622 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
3623 } | |
3624 | |
3625 if (!NILP (count)) | |
3626 { | |
3627 CHECK_INTEGER (count); | |
3628 if (BIGNUMP (count)) | |
3629 { | |
3630 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
3631 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN; | |
3632 } | |
3633 else | |
3634 { | |
3635 counting = XINT (count); | |
3636 } | |
3637 | |
3638 if (counting <= 0) | |
3639 { | |
3640 return sequence; | |
3641 } | |
3642 } | |
3643 | |
3644 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
3645 key, &test_not_unboundp); | |
3646 | |
3647 matched_count = count_with_tail (&tail, nargs, args, QremoveX); | |
3648 | |
3649 if (!ZEROP (matched_count)) | |
3650 { | |
3651 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; | |
3652 GCPRO1 (tailing); | |
3653 | |
3654 if (!NILP (count) && !NILP (from_end)) | |
3655 { | |
3656 presenting = XINT (matched_count); | |
3657 | |
3658 /* If there are fewer matching elements in the list than we have | |
3659 permission to delete, we don't need to differentiate between | |
3660 the :from-end nil and :from-end t cases. Otherwise, presenting | |
3661 is the number of matching items we need to ignore before we | |
3662 start to delete. */ | |
3663 presenting = presenting <= counting ? 0 : presenting - counting; | |
3664 } | |
3665 | |
3666 { | |
3667 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) | |
3668 { | |
3669 if (EQ (tail, tailing)) | |
3670 { | |
3671 if (NILP (result)) | |
3672 { | |
3673 RETURN_UNGCPRO (XCDR (tail)); | |
3674 } | |
3675 | |
3676 XSETCDR (result_tail, XCDR (tail)); | |
3677 RETURN_UNGCPRO (result); | |
3678 } | |
3679 else if (starting <= ii && ii < ending && | |
3680 (check_test (test, key, item, elt) == test_not_unboundp) | |
3681 && (presenting ? encountered++ >= presenting | |
3682 : encountered++ < counting)) | |
3683 { | |
3684 DO_NOTHING; | |
3685 } | |
3686 else if (NILP (result)) | |
3687 { | |
3688 result = result_tail = Fcons (elt, Qnil); | |
3689 } | |
3690 else | |
3691 { | |
3692 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
3693 result_tail = XCDR (result_tail); | |
3694 } | |
3695 | |
3696 if (ii == ending) | |
3697 { | |
3698 break; | |
3699 } | |
3700 | |
3701 ii++; | |
3702 } | |
3703 } | |
3704 | |
3705 UNGCPRO; | |
3706 | |
3707 if (ii < starting || (ii < ending && !NILP (end))) | |
3708 { | |
3709 check_sequence_range (args[0], start, end, Flength (args[0])); | |
3710 } | |
3711 | |
3712 return result; | |
3713 } | |
3714 | |
3715 return sequence; | |
3716 } | |
3717 | |
2005 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /* | 3718 DEFUN ("remassoc", Fremassoc, 2, 2, 0, /* |
2006 Delete by side effect any elements of ALIST whose car is `equal' to KEY. | 3719 Delete by side effect any elements of ALIST whose car is `equal' to KEY. |
2007 The modified ALIST is returned. If the first member of ALIST has a car | 3720 The modified ALIST is returned. If the first member of ALIST has a car |
2008 that is `equal' to KEY, there is no way to remove it by side effect; | 3721 that is `equal' to KEY, there is no way to remove it by side effect; |
2009 therefore, write `(setq foo (remassoc key foo))' to be sure of changing | 3722 therefore, write `(setq foo (remassoc key foo))' to be sure of changing |
2088 LIST_LOOP_DELETE_IF (elt, alist, | 3801 LIST_LOOP_DELETE_IF (elt, alist, |
2089 (CONSP (elt) && | 3802 (CONSP (elt) && |
2090 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); | 3803 EQ_WITH_EBOLA_NOTICE (value, XCDR (elt)))); |
2091 return alist; | 3804 return alist; |
2092 } | 3805 } |
2093 | 3806 |
3807 /* Remove duplicate elements between START and END from LIST, a non-nil | |
3808 list; if COPY is zero, do so destructively. Items to delete are selected | |
3809 according to the algorithm used when :from-end t is passed to | |
3810 #'delete-duplicates. Error if LIST is ill-formed or circular. | |
3811 | |
3812 TEST and KEY are as in #'remove*; CHECK_TEST and TEST_NOT_UNBOUNDP should | |
3813 reflect them, having been initialised with get_check_match_function() or | |
3814 get_check_test_function(). */ | |
3815 static Lisp_Object | |
3816 list_delete_duplicates_from_end (Lisp_Object list, | |
3817 check_test_func_t check_test, | |
3818 Boolint test_not_unboundp, | |
3819 Lisp_Object test, Lisp_Object key, | |
3820 Lisp_Object start, | |
3821 Lisp_Object end, Boolint copy) | |
3822 { | |
3823 Lisp_Object checking = Qnil, elt, tail, result = list; | |
3824 Lisp_Object keyed, positioned, position_cons = Qnil, result_tail; | |
3825 Elemcount len = XINT (Flength (list)), pos, starting = XINT (start); | |
3826 Elemcount ending = (NILP (end) ? len : XINT (end)), greatest_pos_seen = -1; | |
3827 Elemcount ii = 0; | |
3828 struct gcpro gcpro1, gcpro2; | |
3829 | |
3830 /* We can't delete (or remove) as we go, because that breaks START and | |
3831 END. We could if END were nil, and that would change an ON(N + 2) | |
3832 algorithm to an ON^2 algorithm; list_position_cons_before() would need to | |
3833 be modified to return the cons *before* the one containing the item for | |
3834 that. Here and now it doesn't matter, though, #'delete-duplicates is | |
3835 relatively expensive no matter what. */ | |
3836 struct Lisp_Bit_Vector *deleting | |
3837 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
3838 + (sizeof (long) | |
3839 * (BIT_VECTOR_LONG_STORAGE (len) | |
3840 - 1))); | |
3841 | |
3842 check_sequence_range (list, start, end, make_integer (len)); | |
3843 | |
3844 deleting->size = len; | |
3845 memset (&(deleting->bits), 0, | |
3846 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
3847 | |
3848 GCPRO2 (tail, keyed); | |
3849 | |
3850 { | |
3851 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
3852 { | |
3853 if (!(starting <= ii && ii <= ending) || bit_vector_bit (deleting, ii)) | |
3854 { | |
3855 ii++; | |
3856 continue; | |
3857 } | |
3858 | |
3859 keyed = KEY (key, elt); | |
3860 checking = XCDR (tail); | |
3861 pos = ii + 1; | |
3862 | |
3863 while (!NILP ((positioned = list_position_cons_before | |
3864 (&position_cons, keyed, checking, check_test, | |
3865 test_not_unboundp, test, key, 0, | |
3866 make_int (max (starting - pos, 0)), | |
3867 make_int (ending - pos))))) | |
3868 { | |
3869 pos = XINT (positioned) + pos; | |
3870 set_bit_vector_bit (deleting, pos, 1); | |
3871 greatest_pos_seen = max (greatest_pos_seen, pos); | |
3872 checking = NILP (position_cons) ? | |
3873 XCDR (checking) : XCDR (XCDR (position_cons)); | |
3874 pos += 1; | |
3875 } | |
3876 ii++; | |
3877 } | |
3878 } | |
3879 | |
3880 UNGCPRO; | |
3881 | |
3882 ii = 0; | |
3883 | |
3884 if (greatest_pos_seen > -1) | |
3885 { | |
3886 if (copy) | |
3887 { | |
3888 result = result_tail = Fcons (XCAR (list), Qnil); | |
3889 list = XCDR (list); | |
3890 ii = 1; | |
3891 | |
3892 { | |
3893 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, list, tail, len) | |
3894 { | |
3895 if (ii == greatest_pos_seen) | |
3896 { | |
3897 XSETCDR (result_tail, XCDR (tail)); | |
3898 break; | |
3899 } | |
3900 else if (!bit_vector_bit (deleting, ii)) | |
3901 { | |
3902 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
3903 result_tail = XCDR (result_tail); | |
3904 } | |
3905 ii++; | |
3906 } | |
3907 } | |
3908 } | |
3909 else | |
3910 { | |
3911 EXTERNAL_LIST_LOOP_DELETE_IF (elt0, list, | |
3912 bit_vector_bit (deleting, ii++)); | |
3913 } | |
3914 } | |
3915 | |
3916 return result; | |
3917 } | |
3918 | |
3919 DEFUN ("delete-duplicates", Fdelete_duplicates, 1, MANY, 0, /* | |
3920 Remove all duplicate elements from SEQUENCE, destructively. | |
3921 | |
3922 If SEQUENCE is a list and has duplicates, modify and return it. Note that | |
3923 SEQUENCE may start with an element to be deleted; because of this, if | |
3924 modifying a variable, be sure to write `(setq VARIABLE (delete-duplicates | |
3925 VARIABLE))' to be certain to have a list without duplicate elements. | |
3926 | |
3927 If SEQUENCE is an array and has duplicates, return a newly-allocated array | |
3928 of the same type comprising all unique elements of SEQUENCE. | |
3929 | |
3930 If there are no duplicate elements in SEQUENCE, return it unmodified. | |
3931 | |
3932 See `remove*' for the meaning of the keywords. See `remove-duplicates' for | |
3933 a non-destructive version of this function. | |
3934 | |
3935 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | |
3936 */ | |
3937 (int nargs, Lisp_Object *args)) | |
3938 { | |
3939 Lisp_Object sequence = args[0], tail = sequence, keyed = Qnil, elt = Qnil; | |
3940 Lisp_Object elt0 = Qnil, positioned = Qnil, ignore = Qnil; | |
3941 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0, jj = 0; | |
3942 Boolint test_not_unboundp = 1; | |
3943 check_test_func_t check_test = NULL; | |
3944 struct gcpro gcpro1, gcpro2; | |
3945 | |
3946 PARSE_KEYWORDS (Fdelete_duplicates, nargs, args, 6, | |
3947 (test, key, test_not, start, end, from_end), | |
3948 (start = Qzero)); | |
3949 | |
3950 CHECK_SEQUENCE (sequence); | |
3951 CHECK_NATNUM (start); | |
3952 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
3953 | |
3954 if (!NILP (end)) | |
3955 { | |
3956 CHECK_NATNUM (end); | |
3957 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
3958 } | |
3959 | |
3960 CHECK_KEY_ARGUMENT (key); | |
3961 | |
3962 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
3963 &test_not_unboundp, &check_test); | |
3964 | |
3965 if (CONSP (sequence)) | |
3966 { | |
3967 if (NILP (from_end)) | |
3968 { | |
3969 Lisp_Object prev_tail = Qnil; | |
3970 Elemcount deleted = 0; | |
3971 | |
3972 GCPRO2 (tail, keyed); | |
3973 | |
3974 { | |
3975 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
3976 { | |
3977 if (starting <= ii && ii < ending) | |
3978 { | |
3979 keyed = KEY (key, elt); | |
3980 positioned | |
3981 = list_position_cons_before (&ignore, keyed, | |
3982 XCDR (tail), check_test, | |
3983 test_not_unboundp, test, key, | |
3984 0, make_int (max (starting | |
3985 - (ii + 1), | |
3986 0)), | |
3987 make_int (ending | |
3988 - (ii + 1))); | |
3989 if (!NILP (positioned)) | |
3990 { | |
3991 sequence = XCDR (tail); | |
3992 deleted++; | |
3993 } | |
3994 else | |
3995 { | |
3996 break; | |
3997 } | |
3998 } | |
3999 else | |
4000 { | |
4001 break; | |
4002 } | |
4003 | |
4004 ii++; | |
4005 } | |
4006 } | |
4007 { | |
4008 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) | |
4009 { | |
4010 if (!(starting <= ii && ii <= ending)) | |
4011 { | |
4012 prev_tail = tail; | |
4013 ii++; | |
4014 continue; | |
4015 } | |
4016 | |
4017 keyed = KEY (key, elt0); | |
4018 positioned | |
4019 = list_position_cons_before (&ignore, keyed, XCDR (tail), | |
4020 check_test, test_not_unboundp, | |
4021 test, key, 0, | |
4022 make_int (max (starting | |
4023 - (ii + 1), 0)), | |
4024 make_int (ending - (ii + 1))); | |
4025 if (!NILP (positioned)) | |
4026 { | |
4027 /* We know this isn't the first iteration of the loop, | |
4028 because we advanced above to the point where we have at | |
4029 least one non-duplicate entry at the head of the | |
4030 list. */ | |
4031 XSETCDR (prev_tail, XCDR (tail)); | |
4032 len = 0; | |
4033 deleted++; | |
4034 } | |
4035 else | |
4036 { | |
4037 prev_tail = tail; | |
4038 if (ii >= ending) | |
4039 { | |
4040 break; | |
4041 } | |
4042 } | |
4043 | |
4044 ii++; | |
4045 } | |
4046 } | |
4047 UNGCPRO; | |
4048 | |
4049 if ((ii < starting || (ii < ending && !NILP (end)))) | |
4050 { | |
4051 check_sequence_range (args[0], start, end, | |
4052 make_int (deleted | |
4053 + XINT (Flength (args[0])))); | |
4054 } | |
4055 } | |
4056 else | |
4057 { | |
4058 sequence = list_delete_duplicates_from_end (sequence, check_test, | |
4059 test_not_unboundp, | |
4060 test, key, start, end, | |
4061 0); | |
4062 } | |
4063 } | |
4064 else if (STRINGP (sequence)) | |
4065 { | |
4066 if (EQ (Qidentity, key)) | |
4067 { | |
4068 /* We know all the elements will be characters; set check_test to | |
4069 reflect that. This isn't useful if KEY is not #'identity, since | |
4070 it may return non-characters for the elements. */ | |
4071 check_test = get_check_test_function (make_char ('a'), | |
4072 &test, test_not, | |
4073 Qnil, Qnil, key, | |
4074 &test_not_unboundp); | |
4075 } | |
4076 | |
4077 if (NILP (from_end)) | |
4078 { | |
4079 Bytecount byte_len = XSTRING_LENGTH (sequence), cursor_offset = 0; | |
4080 Ibyte *staging = alloca_ibytes (byte_len), *staging_cursor = staging; | |
4081 Ibyte *cursor = XSTRING_DATA (sequence), *startp = cursor; | |
4082 Elemcount deleted = 0; | |
4083 | |
4084 elt = Qnil; | |
4085 GCPRO1 (elt); | |
4086 | |
4087 while (cursor_offset < byte_len) | |
4088 { | |
4089 if (starting <= ii && ii < ending) | |
4090 { | |
4091 Ibyte *cursor0 = cursor; | |
4092 Bytecount cursor0_offset; | |
4093 Boolint delete_this = 0; | |
4094 | |
4095 elt = KEY (key, make_char (itext_ichar (cursor))); | |
4096 INC_IBYTEPTR (cursor0); | |
4097 cursor0_offset = cursor0 - startp; | |
4098 | |
4099 for (jj = ii + 1; jj < ending && cursor0_offset < byte_len; | |
4100 jj++) | |
4101 { | |
4102 if (check_test (test, key, elt, | |
4103 make_char (itext_ichar (cursor0))) | |
4104 == test_not_unboundp) | |
4105 { | |
4106 delete_this = 1; | |
4107 deleted++; | |
4108 break; | |
4109 } | |
4110 | |
4111 startp = XSTRING_DATA (sequence); | |
4112 cursor0 = startp + cursor0_offset; | |
4113 if (byte_len != XSTRING_LENGTH (sequence) | |
4114 || !valid_ibyteptr_p (cursor0)) | |
4115 { | |
4116 mapping_interaction_error (Qdelete_duplicates, | |
4117 sequence); | |
4118 } | |
4119 | |
4120 INC_IBYTEPTR (cursor0); | |
4121 cursor0_offset = cursor0 - startp; | |
4122 } | |
4123 | |
4124 startp = XSTRING_DATA (sequence); | |
4125 cursor = startp + cursor_offset; | |
4126 | |
4127 if (byte_len != XSTRING_LENGTH (sequence) | |
4128 || !valid_ibyteptr_p (cursor)) | |
4129 { | |
4130 mapping_interaction_error (Qdelete_duplicates, sequence); | |
4131 } | |
4132 | |
4133 if (!delete_this) | |
4134 { | |
4135 staging_cursor | |
4136 += itext_copy_ichar (cursor, staging_cursor); | |
4137 | |
4138 } | |
4139 } | |
4140 else | |
4141 { | |
4142 staging_cursor += itext_copy_ichar (cursor, staging_cursor); | |
4143 } | |
4144 | |
4145 INC_IBYTEPTR (cursor); | |
4146 cursor_offset = cursor - startp; | |
4147 ii++; | |
4148 } | |
4149 | |
4150 UNGCPRO; | |
4151 | |
4152 if (ii < starting || (ii < ending && !NILP (end))) | |
4153 { | |
4154 check_sequence_range (sequence, start, end, Flength (sequence)); | |
4155 } | |
4156 | |
4157 if (0 != deleted) | |
4158 { | |
4159 sequence = make_string (staging, staging_cursor - staging); | |
4160 } | |
4161 } | |
4162 else | |
4163 { | |
4164 Elemcount deleted = 0; | |
4165 Ibyte *staging = alloca_ibytes ((len = string_char_length (sequence)) | |
4166 * MAX_ICHAR_LEN); | |
4167 Ibyte *staging_cursor = staging, *startp = XSTRING_DATA (sequence); | |
4168 Ibyte *endp = startp + XSTRING_LENGTH (sequence); | |
4169 struct Lisp_Bit_Vector *deleting | |
4170 = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
4171 + (sizeof (long) | |
4172 * (BIT_VECTOR_LONG_STORAGE (len) | |
4173 - 1))); | |
4174 | |
4175 check_sequence_range (sequence, start, end, make_integer (len)); | |
4176 | |
4177 /* For the from_end t case; transform contents to an array with | |
4178 elements addressable in constant time, use the same algorithm | |
4179 as for vectors. */ | |
4180 deleting->size = len; | |
4181 memset (&(deleting->bits), 0, | |
4182 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
4183 | |
4184 while (startp < endp) | |
4185 { | |
4186 itext_copy_ichar (startp, staging + (ii * MAX_ICHAR_LEN)); | |
4187 INC_IBYTEPTR (startp); | |
4188 ii++; | |
4189 } | |
4190 | |
4191 GCPRO1 (elt); | |
4192 | |
4193 ending = min (ending, len); | |
4194 | |
4195 for (ii = ending - 1; ii >= starting; ii--) | |
4196 { | |
4197 elt = KEY (key, make_char (itext_ichar (staging + | |
4198 (ii * MAX_ICHAR_LEN)))); | |
4199 for (jj = ii - 1; jj >= starting; jj--) | |
4200 { | |
4201 if (check_test (test, key, elt, | |
4202 make_char (itext_ichar | |
4203 (staging + (jj * MAX_ICHAR_LEN)))) | |
4204 == test_not_unboundp) | |
4205 { | |
4206 set_bit_vector_bit (deleting, ii, 1); | |
4207 deleted++; | |
4208 break; | |
4209 } | |
4210 } | |
4211 } | |
4212 | |
4213 UNGCPRO; | |
4214 | |
4215 if (0 != deleted) | |
4216 { | |
4217 startp = XSTRING_DATA (sequence); | |
4218 | |
4219 for (ii = 0; ii < len; ii++) | |
4220 { | |
4221 if (!bit_vector_bit (deleting, ii)) | |
4222 { | |
4223 staging_cursor | |
4224 += itext_copy_ichar (startp, staging_cursor); | |
4225 } | |
4226 | |
4227 INC_IBYTEPTR (startp); | |
4228 } | |
4229 | |
4230 sequence = make_string (staging, staging_cursor - staging); | |
4231 } | |
4232 } | |
4233 } | |
4234 else if (VECTORP (sequence)) | |
4235 { | |
4236 Elemcount deleted = 0; | |
4237 Lisp_Object *content = XVECTOR_DATA (sequence); | |
4238 struct Lisp_Bit_Vector *deleting; | |
4239 | |
4240 len = XVECTOR_LENGTH (sequence); | |
4241 check_sequence_range (sequence, start, end, make_integer (len)); | |
4242 | |
4243 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
4244 + (sizeof (long) | |
4245 * (BIT_VECTOR_LONG_STORAGE (len) | |
4246 - 1))); | |
4247 deleting->size = len; | |
4248 memset (&(deleting->bits), 0, | |
4249 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
4250 | |
4251 GCPRO1 (elt); | |
4252 | |
4253 ending = min (ending, len); | |
4254 | |
4255 if (NILP (from_end)) | |
4256 { | |
4257 for (ii = starting; ii < ending; ii++) | |
4258 { | |
4259 elt = KEY (key, content[ii]); | |
4260 | |
4261 for (jj = ii + 1; jj < ending; jj++) | |
4262 { | |
4263 if (check_test (test, key, elt, content[jj]) | |
4264 == test_not_unboundp) | |
4265 { | |
4266 set_bit_vector_bit (deleting, ii, 1); | |
4267 deleted++; | |
4268 break; | |
4269 } | |
4270 } | |
4271 } | |
4272 } | |
4273 else | |
4274 { | |
4275 for (ii = ending - 1; ii >= starting; ii--) | |
4276 { | |
4277 elt = KEY (key, content[ii]); | |
4278 | |
4279 for (jj = ii - 1; jj >= starting; jj--) | |
4280 { | |
4281 if (check_test (test, key, elt, content[jj]) | |
4282 == test_not_unboundp) | |
4283 { | |
4284 set_bit_vector_bit (deleting, ii, 1); | |
4285 deleted++; | |
4286 break; | |
4287 } | |
4288 } | |
4289 } | |
4290 } | |
4291 | |
4292 UNGCPRO; | |
4293 | |
4294 if (deleted) | |
4295 { | |
4296 Lisp_Object res = make_vector (len - deleted, Qnil), | |
4297 *res_content = XVECTOR_DATA (res); | |
4298 | |
4299 for (ii = jj = 0; ii < len; ii++) | |
4300 { | |
4301 if (!bit_vector_bit (deleting, ii)) | |
4302 { | |
4303 res_content[jj++] = content[ii]; | |
4304 } | |
4305 } | |
4306 | |
4307 sequence = res; | |
4308 } | |
4309 } | |
4310 else if (BIT_VECTORP (sequence)) | |
4311 { | |
4312 Lisp_Bit_Vector *bv = XBIT_VECTOR (sequence); | |
4313 Elemcount deleted = 0; | |
4314 /* I'm a little irritated at this. Basically, the only reasonable | |
4315 thing delete-duplicates should do if handed a bit vector is return | |
4316 something of maximum length two and minimum length 0 (because | |
4317 that's the possible number of distinct elements if EQ is regarded | |
4318 as identity, which it should be). But to support arbitrary TEST | |
4319 and KEY arguments, which may be non-deterministic from our | |
4320 perspective, we need the same algorithm as for vectors. */ | |
4321 struct Lisp_Bit_Vector *deleting; | |
4322 | |
4323 len = bit_vector_length (bv); | |
4324 | |
4325 if (EQ (Qidentity, key)) | |
4326 { | |
4327 /* We know all the elements will be bits; set check_test to | |
4328 reflect that. This isn't useful if KEY is not #'identity, since | |
4329 it may return non-bits for the elements. */ | |
4330 check_test = get_check_test_function (Qzero, &test, test_not, | |
4331 Qnil, Qnil, key, | |
4332 &test_not_unboundp); | |
4333 } | |
4334 | |
4335 check_sequence_range (sequence, start, end, make_integer (len)); | |
4336 | |
4337 deleting = (Lisp_Bit_Vector *) ALLOCA (sizeof (struct Lisp_Bit_Vector) | |
4338 + (sizeof (long) | |
4339 * (BIT_VECTOR_LONG_STORAGE (len) | |
4340 - 1))); | |
4341 deleting->size = len; | |
4342 memset (&(deleting->bits), 0, | |
4343 sizeof (long) * BIT_VECTOR_LONG_STORAGE (len)); | |
4344 | |
4345 ending = min (ending, len); | |
4346 | |
4347 GCPRO1 (elt); | |
4348 | |
4349 if (NILP (from_end)) | |
4350 { | |
4351 for (ii = starting; ii < ending; ii++) | |
4352 { | |
4353 elt = KEY (key, make_int (bit_vector_bit (bv, ii))); | |
4354 | |
4355 for (jj = ii + 1; jj < ending; jj++) | |
4356 { | |
4357 if (check_test (test, key, elt, | |
4358 make_int (bit_vector_bit (bv, jj))) | |
4359 == test_not_unboundp) | |
4360 { | |
4361 set_bit_vector_bit (deleting, ii, 1); | |
4362 deleted++; | |
4363 break; | |
4364 } | |
4365 } | |
4366 } | |
4367 } | |
4368 else | |
4369 { | |
4370 for (ii = ending - 1; ii >= starting; ii--) | |
4371 { | |
4372 elt = KEY (key, make_int (bit_vector_bit (bv, ii))); | |
4373 | |
4374 for (jj = ii - 1; jj >= starting; jj--) | |
4375 { | |
4376 if (check_test (test, key, elt, | |
4377 make_int (bit_vector_bit (bv, jj))) | |
4378 == test_not_unboundp) | |
4379 { | |
4380 set_bit_vector_bit (deleting, ii, 1); | |
4381 deleted++; | |
4382 break; | |
4383 } | |
4384 } | |
4385 } | |
4386 } | |
4387 | |
4388 UNGCPRO; | |
4389 | |
4390 if (deleted) | |
4391 { | |
4392 Lisp_Object res = make_bit_vector (len - deleted, Qzero); | |
4393 Lisp_Bit_Vector *resbv = XBIT_VECTOR (res); | |
4394 | |
4395 for (ii = jj = 0; ii < len; ii++) | |
4396 { | |
4397 if (!bit_vector_bit (deleting, ii)) | |
4398 { | |
4399 set_bit_vector_bit (resbv, jj++, bit_vector_bit (bv, ii)); | |
4400 } | |
4401 } | |
4402 | |
4403 sequence = res; | |
4404 } | |
4405 } | |
4406 | |
4407 return sequence; | |
4408 } | |
4409 | |
4410 DEFUN ("remove-duplicates", Fremove_duplicates, 1, MANY, 0, /* | |
4411 Remove duplicate elements from SEQUENCE, non-destructively. | |
4412 | |
4413 If there are no duplicate elements in SEQUENCE, return it unmodified; | |
4414 otherwise, return a new object. If SEQUENCE is a list, the new object may | |
4415 share list structure with SEQUENCE. | |
4416 | |
4417 See `remove*' for the meaning of the keywords. | |
4418 | |
4419 arguments: (SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) END FROM-END TEST-NOT) | |
4420 */ | |
4421 (int nargs, Lisp_Object *args)) | |
4422 { | |
4423 Lisp_Object sequence = args[0], tail = sequence, keyed, positioned = Qnil; | |
4424 Lisp_Object result = sequence, result_tail = result, cursor = Qnil; | |
4425 Lisp_Object cons_with_shared_tail = Qnil, elt, elt0; | |
4426 Elemcount starting = 0, ending = EMACS_INT_MAX, len, ii = 0; | |
4427 Boolint test_not_unboundp = 1; | |
4428 check_test_func_t check_test = NULL; | |
4429 struct gcpro gcpro1, gcpro2, gcpro3; | |
4430 | |
4431 PARSE_KEYWORDS (Fremove_duplicates, nargs, args, 6, | |
4432 (test, key, test_not, start, end, from_end), | |
4433 (start = Qzero)); | |
4434 | |
4435 CHECK_SEQUENCE (sequence); | |
4436 | |
4437 if (!CONSP (sequence)) | |
4438 { | |
4439 return Fdelete_duplicates (nargs, args); | |
4440 } | |
4441 | |
4442 CHECK_NATNUM (start); | |
4443 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
4444 | |
4445 if (!NILP (end)) | |
4446 { | |
4447 CHECK_NATNUM (end); | |
4448 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
4449 } | |
4450 | |
4451 if (NILP (key)) | |
4452 { | |
4453 key = Qidentity; | |
4454 } | |
4455 | |
4456 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
4457 &test_not_unboundp, &check_test); | |
4458 | |
4459 if (NILP (from_end)) | |
4460 { | |
4461 Lisp_Object ignore = Qnil; | |
4462 | |
4463 GCPRO3 (tail, keyed, result); | |
4464 | |
4465 { | |
4466 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
4467 { | |
4468 if (starting <= ii && ii <= ending) | |
4469 { | |
4470 keyed = KEY (key, elt); | |
4471 positioned | |
4472 = list_position_cons_before (&ignore, keyed, XCDR (tail), | |
4473 check_test, test_not_unboundp, | |
4474 test, key, 0, | |
4475 make_int (max (starting | |
4476 - (ii + 1), 0)), | |
4477 make_int (ending - (ii + 1))); | |
4478 if (!NILP (positioned)) | |
4479 { | |
4480 sequence = result = result_tail = XCDR (tail); | |
4481 } | |
4482 else | |
4483 { | |
4484 break; | |
4485 } | |
4486 } | |
4487 else | |
4488 { | |
4489 break; | |
4490 } | |
4491 | |
4492 ii++; | |
4493 } | |
4494 } | |
4495 | |
4496 { | |
4497 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt0, sequence, tail, len) | |
4498 { | |
4499 if (!(starting <= ii && ii <= ending)) | |
4500 { | |
4501 ii++; | |
4502 continue; | |
4503 } | |
4504 | |
4505 /* For this algorithm, each time we encounter an object to be | |
4506 removed, copy the output list from the tail beyond the last | |
4507 removed cons to this one. Otherwise, the tail of the output list | |
4508 is shared with the input list, which is OK. */ | |
4509 | |
4510 keyed = KEY (key, elt0); | |
4511 positioned | |
4512 = list_position_cons_before (&ignore, keyed, XCDR (tail), | |
4513 check_test, test_not_unboundp, | |
4514 test, key, 0, | |
4515 make_int (max (starting - (ii + 1), | |
4516 0)), | |
4517 make_int (ending - (ii + 1))); | |
4518 if (!NILP (positioned)) | |
4519 { | |
4520 if (EQ (result, sequence)) | |
4521 { | |
4522 result = cons_with_shared_tail | |
4523 = Fcons (XCAR (sequence), XCDR (sequence)); | |
4524 } | |
4525 | |
4526 result_tail = cons_with_shared_tail; | |
4527 cursor = XCDR (cons_with_shared_tail); | |
4528 | |
4529 while (!EQ (cursor, tail) && !NILP (cursor)) | |
4530 { | |
4531 XSETCDR (result_tail, Fcons (XCAR (cursor), Qnil)); | |
4532 result_tail = XCDR (result_tail); | |
4533 cursor = XCDR (cursor); | |
4534 } | |
4535 | |
4536 XSETCDR (result_tail, XCDR (tail)); | |
4537 cons_with_shared_tail = result_tail; | |
4538 } | |
4539 | |
4540 ii++; | |
4541 } | |
4542 } | |
4543 UNGCPRO; | |
4544 | |
4545 if ((ii < starting || (ii < ending && !NILP (end)))) | |
4546 { | |
4547 check_sequence_range (args[0], start, end, Flength (args[0])); | |
4548 } | |
4549 } | |
4550 else | |
4551 { | |
4552 result = list_delete_duplicates_from_end (sequence, check_test, | |
4553 test_not_unboundp, test, key, | |
4554 start, end, 1); | |
4555 } | |
4556 | |
4557 return result; | |
4558 } | |
4559 #undef KEY | |
4560 | |
2094 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* | 4561 DEFUN ("nreverse", Fnreverse, 1, 1, 0, /* |
2095 Reverse SEQUENCE, destructively. | 4562 Reverse SEQUENCE, destructively. |
2096 | 4563 |
2097 Return the beginning of the reversed sequence, which will be a distinct Lisp | 4564 Return the beginning of the reversed sequence, which will be a distinct Lisp |
2098 object if SEQUENCE is a list with length greater than one. See also | 4565 object if SEQUENCE is a list with length greater than one. See also |
2712 for (counter = 0; counter < len; ++counter) \ | 5179 for (counter = 0; counter < len; ++counter) \ |
2713 { \ | 5180 { \ |
2714 c_array[counter] = make_int (bit_vector_bit (v, counter)); \ | 5181 c_array[counter] = make_int (bit_vector_bit (v, counter)); \ |
2715 } \ | 5182 } \ |
2716 } while (0) | 5183 } while (0) |
2717 | |
2718 /* This macro might eventually find a better home than here. */ | |
2719 | |
2720 #define CHECK_KEY_ARGUMENT(key) \ | |
2721 do { \ | |
2722 if (NILP (key)) \ | |
2723 { \ | |
2724 key = Qidentity; \ | |
2725 } \ | |
2726 \ | |
2727 if (!EQ (key, Qidentity)) \ | |
2728 { \ | |
2729 key = indirect_function (key, 1); \ | |
2730 } \ | |
2731 } while (0) | |
2732 | 5184 |
2733 DEFUN ("merge", Fmerge, 4, MANY, 0, /* | 5185 DEFUN ("merge", Fmerge, 4, MANY, 0, /* |
2734 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence. | 5186 Destructively merge SEQUENCE-ONE and SEQUENCE-TWO, producing a new sequence. |
2735 | 5187 |
2736 TYPE is the type of sequence to return. PREDICATE is a `less-than' | 5188 TYPE is the type of sequence to return. PREDICATE is a `less-than' |
3942 } | 6394 } |
3943 | 6395 |
3944 int | 6396 int |
3945 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 6397 internal_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
3946 { | 6398 { |
3947 if (depth > 200) | 6399 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
3948 stack_overflow ("Stack overflow in equal", Qunbound); | 6400 stack_overflow ("Stack overflow in equal", Qunbound); |
3949 QUIT; | 6401 QUIT; |
3950 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2)) | 6402 if (EQ_WITH_EBOLA_NOTICE (obj1, obj2)) |
3951 return 1; | 6403 return 1; |
3952 /* Note that (equal 20 20.0) should be nil */ | 6404 /* Note that (equal 20 20.0) should be nil */ |
3987 } | 6439 } |
3988 | 6440 |
3989 int | 6441 int |
3990 internal_equalp (Lisp_Object obj1, Lisp_Object obj2, int depth) | 6442 internal_equalp (Lisp_Object obj1, Lisp_Object obj2, int depth) |
3991 { | 6443 { |
3992 if (depth > 200) | 6444 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
3993 stack_overflow ("Stack overflow in equalp", Qunbound); | 6445 stack_overflow ("Stack overflow in equalp", Qunbound); |
3994 QUIT; | 6446 QUIT; |
3995 | 6447 |
3996 /* 1. Objects that are `eq' are equal. This will catch the common case | 6448 /* 1. Objects that are `eq' are equal. This will catch the common case |
3997 of two equal fixnums or the same object seen twice. */ | 6449 of two equal fixnums or the same object seen twice. */ |
4063 but that seems unlikely. */ | 6515 but that seems unlikely. */ |
4064 | 6516 |
4065 static int | 6517 static int |
4066 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 6518 internal_old_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
4067 { | 6519 { |
4068 if (depth > 200) | 6520 if (depth + lisp_eval_depth > max_lisp_eval_depth) |
4069 stack_overflow ("Stack overflow in equal", Qunbound); | 6521 stack_overflow ("Stack overflow in equal", Qunbound); |
4070 QUIT; | 6522 QUIT; |
4071 if (HACKEQ_UNSAFE (obj1, obj2)) | 6523 if (HACKEQ_UNSAFE (obj1, obj2)) |
4072 return 1; | 6524 return 1; |
4073 /* Note that (equal 20 20.0) should be nil */ | 6525 /* Note that (equal 20 20.0) should be nil */ |
4229 } | 6681 } |
4230 else if (LISTP (sequence)) | 6682 else if (LISTP (sequence)) |
4231 { | 6683 { |
4232 Elemcount counting = 0; | 6684 Elemcount counting = 0; |
4233 | 6685 |
4234 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) | 6686 { |
4235 { | 6687 EXTERNAL_LIST_LOOP_3 (elt, sequence, tail) |
4236 if (counting >= starting) | 6688 { |
4237 { | 6689 if (counting >= starting) |
4238 if (counting < ending) | 6690 { |
4239 { | 6691 if (counting < ending) |
4240 XSETCAR (tail, item); | 6692 { |
4241 } | 6693 XSETCAR (tail, item); |
4242 else if (counting == ending) | 6694 } |
4243 { | 6695 else if (counting == ending) |
4244 break; | 6696 { |
4245 } | 6697 break; |
4246 } | 6698 } |
4247 ++counting; | 6699 } |
4248 } | 6700 ++counting; |
6701 } | |
6702 } | |
4249 | 6703 |
4250 if (counting < starting || (counting != ending && !NILP (end))) | 6704 if (counting < starting || (counting != ending && !NILP (end))) |
4251 { | 6705 { |
4252 check_sequence_range (args[0], start, end, Flength (args[0])); | 6706 check_sequence_range (args[0], start, end, Flength (args[0])); |
4253 } | 6707 } |
6077 { | 8531 { |
6078 Ibyte *p2 = XSTRING_DATA (sequence2), | 8532 Ibyte *p2 = XSTRING_DATA (sequence2), |
6079 *p2end = p2 + XSTRING_LENGTH (sequence2), *p2cursor; | 8533 *p2end = p2 + XSTRING_LENGTH (sequence2), *p2cursor; |
6080 Charcount ii = 0, len1 = string_char_length (sequence1); | 8534 Charcount ii = 0, len1 = string_char_length (sequence1); |
6081 | 8535 |
8536 check_sequence_range (sequence1, start1, end1, make_int (len1)); | |
8537 | |
6082 while (ii < starting2 && p2 < p2end) | 8538 while (ii < starting2 && p2 < p2end) |
6083 { | 8539 { |
6084 INC_IBYTEPTR (p2); | 8540 INC_IBYTEPTR (p2); |
6085 ii++; | 8541 ii++; |
6086 } | 8542 } |
6186 } | 8642 } |
6187 | 8643 |
6188 return result; | 8644 return result; |
6189 } | 8645 } |
6190 | 8646 |
8647 DEFUN ("nsubstitute", Fnsubstitute, 3, MANY, 0, /* | |
8648 Substitute NEW for OLD in SEQUENCE. | |
8649 | |
8650 This is a destructive function; it reuses the storage of SEQUENCE whenever | |
8651 possible. See `remove*' for the meaning of the keywords. | |
8652 | |
8653 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) FROM-END COUNT) | |
8654 */ | |
8655 (int nargs, Lisp_Object *args)) | |
8656 { | |
8657 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; | |
8658 Lisp_Object object_, position0; | |
8659 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | |
8660 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; | |
8661 Boolint test_not_unboundp = 1; | |
8662 check_test_func_t check_test = NULL; | |
8663 struct gcpro gcpro1; | |
8664 | |
8665 PARSE_KEYWORDS (Fnsubstitute, nargs, args, 9, | |
8666 (test, if_, if_not, test_not, key, start, end, count, | |
8667 from_end), (start = Qzero)); | |
8668 | |
8669 CHECK_SEQUENCE (sequence); | |
8670 CHECK_NATNUM (start); | |
8671 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
8672 | |
8673 if (!NILP (end)) | |
8674 { | |
8675 CHECK_NATNUM (end); | |
8676 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
8677 } | |
8678 | |
8679 if (!NILP (count)) | |
8680 { | |
8681 CHECK_INTEGER (count); | |
8682 if (BIGNUMP (count)) | |
8683 { | |
8684 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
8685 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN; | |
8686 } | |
8687 else | |
8688 { | |
8689 counting = XINT (count); | |
8690 } | |
8691 | |
8692 if (counting <= 0) | |
8693 { | |
8694 return sequence; | |
8695 } | |
8696 } | |
8697 | |
8698 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
8699 key, &test_not_unboundp); | |
8700 | |
8701 if (CONSP (sequence)) | |
8702 { | |
8703 Lisp_Object elt; | |
8704 | |
8705 if (!NILP (count) && !NILP (from_end)) | |
8706 { | |
8707 Lisp_Object present = count_with_tail (&elt, nargs - 1, args + 1, | |
8708 Qnsubstitute); | |
8709 | |
8710 if (ZEROP (present)) | |
8711 { | |
8712 return sequence; | |
8713 } | |
8714 | |
8715 presenting = XINT (present); | |
8716 presenting = presenting <= counting ? 0 : presenting - counting; | |
8717 } | |
8718 | |
8719 GCPRO1 (tail); | |
8720 { | |
8721 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tail, len) | |
8722 { | |
8723 if (!(ii < ending)) | |
8724 { | |
8725 break; | |
8726 } | |
8727 | |
8728 if (starting <= ii && | |
8729 check_test (test, key, item, elt) == test_not_unboundp | |
8730 && (presenting ? encountered++ >= presenting | |
8731 : encountered++ < counting)) | |
8732 { | |
8733 CHECK_LISP_WRITEABLE (tail); | |
8734 XSETCAR (tail, new_); | |
8735 } | |
8736 else if (!presenting && encountered >= counting) | |
8737 { | |
8738 break; | |
8739 } | |
8740 | |
8741 ii++; | |
8742 } | |
8743 } | |
8744 UNGCPRO; | |
8745 | |
8746 if ((ii < starting || (ii < ending && !NILP (end))) | |
8747 && encountered < counting) | |
8748 { | |
8749 check_sequence_range (args[0], start, end, Flength (args[0])); | |
8750 } | |
8751 } | |
8752 else if (STRINGP (sequence)) | |
8753 { | |
8754 Ibyte *staging, new_bytes[MAX_ICHAR_LEN], *staging_cursor; | |
8755 Ibyte *startp = XSTRING_DATA (sequence), *cursor = startp; | |
8756 Bytecount cursor_offset = 0, byte_len = XSTRING_LENGTH (sequence); | |
8757 Bytecount new_len; | |
8758 Lisp_Object character; | |
8759 | |
8760 CHECK_CHAR_COERCE_INT (new_); | |
8761 | |
8762 new_len = set_itext_ichar (new_bytes, XCHAR (new_)); | |
8763 | |
8764 /* Worst case scenario; new char is four octets long, all the old ones | |
8765 were one octet long, all the old ones match. */ | |
8766 staging = alloca_ibytes (XSTRING_LENGTH (sequence) * new_len); | |
8767 staging_cursor = staging; | |
8768 | |
8769 if (!NILP (count) && !NILP (from_end)) | |
8770 { | |
8771 Lisp_Object present = count_with_tail (&character, nargs - 1, | |
8772 args + 1, Qnsubstitute); | |
8773 | |
8774 if (ZEROP (present)) | |
8775 { | |
8776 return sequence; | |
8777 } | |
8778 | |
8779 presenting = XINT (present); | |
8780 | |
8781 /* If there are fewer items in the string than we have | |
8782 permission to change, we don't need to differentiate | |
8783 between the :from-end nil and :from-end t | |
8784 cases. Otherwise, presenting is the number of matching | |
8785 items we need to ignore before we start to change. */ | |
8786 presenting = presenting <= counting ? 0 : presenting - counting; | |
8787 } | |
8788 | |
8789 ii = 0; | |
8790 while (cursor_offset < byte_len && ii < ending) | |
8791 { | |
8792 if (ii >= starting) | |
8793 { | |
8794 character = make_char (itext_ichar (cursor)); | |
8795 | |
8796 if ((check_test (test, key, item, character) | |
8797 == test_not_unboundp) | |
8798 && (presenting ? encountered++ >= presenting : | |
8799 encountered++ < counting)) | |
8800 { | |
8801 staging_cursor | |
8802 += itext_copy_ichar (new_bytes, staging_cursor); | |
8803 } | |
8804 else | |
8805 { | |
8806 staging_cursor | |
8807 += itext_copy_ichar (cursor, staging_cursor); | |
8808 } | |
8809 | |
8810 startp = XSTRING_DATA (sequence); | |
8811 cursor = startp + cursor_offset; | |
8812 | |
8813 if (byte_len != XSTRING_LENGTH (sequence) | |
8814 || !valid_ibyteptr_p (cursor)) | |
8815 { | |
8816 mapping_interaction_error (Qnsubstitute, sequence); | |
8817 } | |
8818 } | |
8819 else | |
8820 { | |
8821 staging_cursor += itext_copy_ichar (cursor, staging_cursor); | |
8822 } | |
8823 | |
8824 INC_IBYTEPTR (cursor); | |
8825 cursor_offset = cursor - startp; | |
8826 ii++; | |
8827 } | |
8828 | |
8829 if (ii < starting || (ii < ending && !NILP (end))) | |
8830 { | |
8831 check_sequence_range (sequence, start, end, Flength (sequence)); | |
8832 } | |
8833 | |
8834 if (0 != encountered) | |
8835 { | |
8836 CHECK_LISP_WRITEABLE (sequence); | |
8837 replace_string_range (sequence, Qzero, make_int (ii), | |
8838 staging, staging_cursor); | |
8839 } | |
8840 } | |
8841 else | |
8842 { | |
8843 Elemcount positioning; | |
8844 Lisp_Object object = Qnil; | |
8845 | |
8846 len = XINT (Flength (sequence)); | |
8847 check_sequence_range (sequence, start, end, make_int (len)); | |
8848 | |
8849 position0 = position (&object, item, sequence, check_test, | |
8850 test_not_unboundp, test, key, start, end, from_end, | |
8851 Qnil, Qnsubstitute); | |
8852 | |
8853 if (NILP (position0)) | |
8854 { | |
8855 return sequence; | |
8856 } | |
8857 | |
8858 positioning = XINT (position0); | |
8859 ending = min (len, ending); | |
8860 | |
8861 Faset (sequence, position0, new_); | |
8862 encountered = 1; | |
8863 | |
8864 if (NILP (from_end)) | |
8865 { | |
8866 for (ii = positioning + 1; ii < ending; ii++) | |
8867 { | |
8868 object_ = Faref (sequence, make_int (ii)); | |
8869 | |
8870 if (check_test (test, key, item, object_) == test_not_unboundp | |
8871 && encountered++ < counting) | |
8872 { | |
8873 Faset (sequence, make_int (ii), new_); | |
8874 } | |
8875 else if (encountered == counting) | |
8876 { | |
8877 break; | |
8878 } | |
8879 } | |
8880 } | |
8881 else | |
8882 { | |
8883 for (ii = positioning - 1; ii >= starting; ii--) | |
8884 { | |
8885 object_ = Faref (sequence, make_int (ii)); | |
8886 | |
8887 if (check_test (test, key, item, object_) == test_not_unboundp | |
8888 && encountered++ < counting) | |
8889 { | |
8890 Faset (sequence, make_int (ii), new_); | |
8891 } | |
8892 else if (encountered == counting) | |
8893 { | |
8894 break; | |
8895 } | |
8896 } | |
8897 } | |
8898 } | |
8899 | |
8900 return sequence; | |
8901 } | |
8902 | |
8903 DEFUN ("substitute", Fsubstitute, 3, MANY, 0, /* | |
8904 Substitute NEW for OLD in SEQUENCE. | |
8905 | |
8906 This is a non-destructive function; it makes a copy of SEQUENCE if necessary | |
8907 to avoid corrupting the original SEQUENCE. | |
8908 | |
8909 See `remove*' for the meaning of the keywords. | |
8910 | |
8911 arguments: (NEW OLD SEQUENCE &key (TEST #'eql) (KEY #'identity) (START 0) (END (length SEQUENCE)) COUNT) | |
8912 */ | |
8913 (int nargs, Lisp_Object *args)) | |
8914 { | |
8915 Lisp_Object new_ = args[0], item = args[1], sequence = args[2], tail = Qnil; | |
8916 Lisp_Object elt, tailing = Qnil, result = Qnil, result_tail = Qnil; | |
8917 Lisp_Object object, position0, matched_count; | |
8918 Elemcount starting = 0, ending = EMACS_INT_MAX, encountered = 0; | |
8919 Elemcount len, ii = 0, counting = EMACS_INT_MAX, presenting = 0; | |
8920 Boolint test_not_unboundp = 1; | |
8921 check_test_func_t check_test = NULL; | |
8922 struct gcpro gcpro1; | |
8923 | |
8924 PARSE_KEYWORDS (Fsubstitute, nargs, args, 9, | |
8925 (test, if_, if_not, test_not, key, start, end, count, | |
8926 from_end), (start = Qzero, count = Qunbound)); | |
8927 | |
8928 CHECK_SEQUENCE (sequence); | |
8929 | |
8930 CHECK_NATNUM (start); | |
8931 starting = BIGNUMP (start) ? 1 + EMACS_INT_MAX : XINT (start); | |
8932 | |
8933 if (!NILP (end)) | |
8934 { | |
8935 CHECK_NATNUM (end); | |
8936 ending = BIGNUMP (end) ? 1 + EMACS_INT_MAX : XINT (end); | |
8937 } | |
8938 | |
8939 check_test = get_check_test_function (item, &test, test_not, if_, if_not, | |
8940 key, &test_not_unboundp); | |
8941 | |
8942 if (!UNBOUNDP (count)) | |
8943 { | |
8944 if (!NILP (count)) | |
8945 { | |
8946 CHECK_INTEGER (count); | |
8947 if (BIGNUMP (count)) | |
8948 { | |
8949 counting = bignum_sign (XBIGNUM_DATA (count)) > 0 ? | |
8950 1 + EMACS_INT_MAX : -1 + EMACS_INT_MIN; | |
8951 } | |
8952 else | |
8953 { | |
8954 counting = XINT (count); | |
8955 } | |
8956 | |
8957 if (counting <= 0) | |
8958 { | |
8959 return sequence; | |
8960 } | |
8961 } | |
8962 } | |
8963 | |
8964 if (!CONSP (sequence)) | |
8965 { | |
8966 position0 = position (&object, item, sequence, check_test, | |
8967 test_not_unboundp, test, key, start, end, from_end, | |
8968 Qnil, Qsubstitute); | |
8969 | |
8970 if (NILP (position0)) | |
8971 { | |
8972 return sequence; | |
8973 } | |
8974 else | |
8975 { | |
8976 args[2] = Fcopy_sequence (sequence); | |
8977 return Fnsubstitute (nargs, args); | |
8978 } | |
8979 } | |
8980 | |
8981 matched_count = count_with_tail (&tail, nargs - 1, args + 1, Qsubstitute); | |
8982 | |
8983 if (ZEROP (matched_count)) | |
8984 { | |
8985 return sequence; | |
8986 } | |
8987 | |
8988 if (!NILP (count) && !NILP (from_end)) | |
8989 { | |
8990 presenting = XINT (matched_count); | |
8991 presenting = presenting <= counting ? 0 : presenting - counting; | |
8992 } | |
8993 | |
8994 GCPRO1 (tailing); | |
8995 { | |
8996 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, sequence, tailing, len) | |
8997 { | |
8998 if (EQ (tail, tailing)) | |
8999 { | |
9000 if (NILP (result)) | |
9001 { | |
9002 RETURN_UNGCPRO (XCDR (tail)); | |
9003 } | |
9004 | |
9005 XSETCDR (result_tail, XCDR (tail)); | |
9006 RETURN_UNGCPRO (result); | |
9007 } | |
9008 else if (starting <= ii && ii < ending && | |
9009 (check_test (test, key, item, elt) == test_not_unboundp) | |
9010 && (presenting ? encountered++ >= presenting | |
9011 : encountered++ < counting)) | |
9012 { | |
9013 if (NILP (result)) | |
9014 { | |
9015 result = result_tail = Fcons (new_, Qnil); | |
9016 } | |
9017 else | |
9018 { | |
9019 XSETCDR (result_tail, Fcons (new_, Qnil)); | |
9020 result_tail = XCDR (result_tail); | |
9021 } | |
9022 } | |
9023 else if (NILP (result)) | |
9024 { | |
9025 result = result_tail = Fcons (elt, Qnil); | |
9026 } | |
9027 else | |
9028 { | |
9029 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
9030 result_tail = XCDR (result_tail); | |
9031 } | |
9032 | |
9033 if (ii == ending) | |
9034 { | |
9035 break; | |
9036 } | |
9037 | |
9038 ii++; | |
9039 } | |
9040 } | |
9041 UNGCPRO; | |
9042 | |
9043 if (ii < starting || (ii < ending && !NILP (end))) | |
9044 { | |
9045 check_sequence_range (args[0], start, end, Flength (args[0])); | |
9046 } | |
9047 | |
9048 return result; | |
9049 } | |
9050 | |
9051 static Lisp_Object | |
9052 subst (Lisp_Object new_, Lisp_Object old, Lisp_Object tree, int depth) | |
9053 { | |
9054 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9055 { | |
9056 stack_overflow ("Stack overflow in subst", tree); | |
9057 } | |
9058 | |
9059 if (EQ (tree, old)) | |
9060 { | |
9061 return new_; | |
9062 } | |
9063 else if (CONSP (tree)) | |
9064 { | |
9065 Lisp_Object aa = subst (new_, old, XCAR (tree), depth + 1); | |
9066 Lisp_Object dd = subst (new_, old, XCDR (tree), depth + 1); | |
9067 | |
9068 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree))) | |
9069 { | |
9070 return tree; | |
9071 } | |
9072 else | |
9073 { | |
9074 return Fcons (aa, dd); | |
9075 } | |
9076 } | |
9077 else | |
9078 { | |
9079 return tree; | |
9080 } | |
9081 } | |
9082 | |
9083 static Lisp_Object | |
9084 sublis (Lisp_Object alist, Lisp_Object tree, | |
9085 check_test_func_t check_test, Boolint test_not_unboundp, | |
9086 Lisp_Object test, Lisp_Object key, int depth) | |
9087 { | |
9088 Lisp_Object keyed = KEY (key, tree), tailed = alist, aa, dd; | |
9089 struct gcpro gcpro1, gcpro2, gcpro3; | |
9090 | |
9091 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9092 { | |
9093 stack_overflow ("Stack overflow in sublis", tree); | |
9094 } | |
9095 | |
9096 GCPRO3 (tailed, alist, tree); | |
9097 { | |
9098 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9099 { | |
9100 tailed = tail; | |
9101 | |
9102 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9103 { | |
9104 /* Don't use elt_cdr, it is helpful to allow TEST or KEY to | |
9105 modify the alist while it executes. */ | |
9106 RETURN_UNGCPRO (XCDR (elt)); | |
9107 } | |
9108 } | |
9109 } | |
9110 if (!CONSP (tree)) | |
9111 { | |
9112 RETURN_UNGCPRO (tree); | |
9113 } | |
9114 | |
9115 aa = sublis (alist, XCAR (tree), check_test, test_not_unboundp, test, key, | |
9116 depth + 1); | |
9117 dd = sublis (alist, XCDR (tree), check_test, test_not_unboundp, test, key, | |
9118 depth + 1); | |
9119 | |
9120 if (EQ (aa, XCAR (tree)) && EQ (dd, XCDR (tree))) | |
9121 { | |
9122 RETURN_UNGCPRO (tree); | |
9123 } | |
9124 | |
9125 RETURN_UNGCPRO (Fcons (aa, dd)); | |
9126 } | |
9127 | |
9128 DEFUN ("sublis", Fsublis, 2, MANY, 0, /* | |
9129 Perform substitutions indicated by ALIST in TREE (non-destructively). | |
9130 Return a copy of TREE with all matching elements replaced. | |
9131 | |
9132 See `member*' for the meaning of :test, :test-not and :key. | |
9133 | |
9134 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9135 */ | |
9136 (int nargs, Lisp_Object *args)) | |
9137 { | |
9138 Lisp_Object alist = args[0], tree = args[1]; | |
9139 Boolint test_not_unboundp = 1; | |
9140 check_test_func_t check_test = NULL; | |
9141 | |
9142 PARSE_KEYWORDS (Fsublis, nargs, args, 5, (test, if_, test_not, if_not, key), | |
9143 (key = Qidentity)); | |
9144 | |
9145 if (NILP (key)) | |
9146 { | |
9147 key = Qidentity; | |
9148 } | |
9149 | |
9150 get_check_match_function (&test, test_not, if_, if_not, | |
9151 /* sublis() is going to apply the key, don't ask | |
9152 for a match function that will do it for | |
9153 us. */ | |
9154 Qidentity, &test_not_unboundp, &check_test); | |
9155 | |
9156 if (CONSP (alist) && NILP (XCDR (alist)) && CONSP (XCAR (alist)) | |
9157 && EQ (key, Qidentity) && 1 == test_not_unboundp | |
9158 && (check_eq_nokey == check_test || | |
9159 (check_eql_nokey == check_test && | |
9160 !NON_FIXNUM_NUMBER_P (XCAR (XCAR (alist)))))) | |
9161 { | |
9162 /* #'subst with #'eq is very cheap indeed; call it. */ | |
9163 return subst (XCDR (XCAR (alist)), XCAR (XCAR (alist)), tree, 0); | |
9164 } | |
9165 | |
9166 return sublis (alist, tree, check_test, test_not_unboundp, test, key, 0); | |
9167 } | |
9168 | |
9169 static Lisp_Object | |
9170 nsublis (Lisp_Object alist, Lisp_Object tree, | |
9171 check_test_func_t check_test, | |
9172 Boolint test_not_unboundp, | |
9173 Lisp_Object test, Lisp_Object key, int depth) | |
9174 { | |
9175 Lisp_Object tree_saved = tree, tailed = alist, tortoise = tree, keyed = Qnil; | |
9176 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
9177 int count = 0; | |
9178 | |
9179 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9180 { | |
9181 stack_overflow ("Stack overflow in nsublis", tree); | |
9182 } | |
9183 | |
9184 GCPRO4 (tailed, alist, tree_saved, keyed); | |
9185 | |
9186 while (CONSP (tree)) | |
9187 { | |
9188 Boolint replaced = 0; | |
9189 keyed = KEY (key, XCAR (tree)); | |
9190 | |
9191 { | |
9192 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9193 { | |
9194 tailed = tail; | |
9195 | |
9196 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9197 { | |
9198 CHECK_LISP_WRITEABLE (tree); | |
9199 /* See comment in sublis() on using elt_cdr. */ | |
9200 XSETCAR (tree, XCDR (elt)); | |
9201 replaced = 1; | |
9202 break; | |
9203 } | |
9204 } | |
9205 } | |
9206 | |
9207 if (!replaced) | |
9208 { | |
9209 if (CONSP (XCAR (tree))) | |
9210 { | |
9211 nsublis (alist, XCAR (tree), check_test, test_not_unboundp, | |
9212 test, key, depth + 1); | |
9213 } | |
9214 } | |
9215 | |
9216 keyed = KEY (key, XCDR (tree)); | |
9217 replaced = 0; | |
9218 | |
9219 { | |
9220 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9221 { | |
9222 tailed = tail; | |
9223 | |
9224 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9225 { | |
9226 CHECK_LISP_WRITEABLE (tree); | |
9227 /* See comment in sublis() on using elt_cdr. */ | |
9228 XSETCDR (tree, XCDR (elt)); | |
9229 tree = Qnil; | |
9230 break; | |
9231 } | |
9232 } | |
9233 } | |
9234 | |
9235 if (!NILP (tree)) | |
9236 { | |
9237 tree = XCDR (tree); | |
9238 } | |
9239 | |
9240 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH) | |
9241 { | |
9242 if (count & 1) | |
9243 { | |
9244 tortoise = XCDR (tortoise); | |
9245 } | |
9246 | |
9247 if (EQ (tortoise, tree)) | |
9248 { | |
9249 signal_circular_list_error (tree); | |
9250 } | |
9251 } | |
9252 } | |
9253 | |
9254 RETURN_UNGCPRO (tree_saved); | |
9255 } | |
9256 | |
9257 DEFUN ("nsublis", Fnsublis, 2, MANY, 0, /* | |
9258 Perform substitutions indicated by ALIST in TREE (destructively). | |
9259 Any matching element of TREE is changed via a call to `setcar'. | |
9260 | |
9261 See `member*' for the meaning of :test, :test-not and :key. | |
9262 | |
9263 arguments: (ALIST TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9264 */ | |
9265 (int nargs, Lisp_Object *args)) | |
9266 { | |
9267 Lisp_Object alist = args[0], tree = args[1], tailed = Qnil, keyed = Qnil; | |
9268 Boolint test_not_unboundp = 1; | |
9269 check_test_func_t check_test = NULL; | |
9270 struct gcpro gcpro1, gcpro2; | |
9271 | |
9272 PARSE_KEYWORDS (Fnsublis, nargs, args, 5, (test, if_, test_not, if_not, key), | |
9273 (key = Qidentity)); | |
9274 | |
9275 if (NILP (key)) | |
9276 { | |
9277 key = Qidentity; | |
9278 } | |
9279 | |
9280 get_check_match_function (&test, test_not, if_, if_not, | |
9281 /* nsublis() is going to apply the key, don't ask | |
9282 for a match function that will do it for | |
9283 us. */ | |
9284 Qidentity, &test_not_unboundp, &check_test); | |
9285 | |
9286 GCPRO2 (tailed, keyed); | |
9287 | |
9288 keyed = KEY (key, tree); | |
9289 | |
9290 { | |
9291 /* nsublis() won't attempt to replace a cons handed to it, do that | |
9292 ourselves. */ | |
9293 EXTERNAL_ALIST_LOOP_5 (elt, elt_car, elt_cdr, alist, tail) | |
9294 { | |
9295 tailed = tail; | |
9296 | |
9297 if (check_test (test, key, elt_car, keyed) == test_not_unboundp) | |
9298 { | |
9299 /* See comment in sublis() on using elt_cdr. */ | |
9300 RETURN_UNGCPRO (XCDR (elt)); | |
9301 } | |
9302 } | |
9303 } | |
9304 | |
9305 UNGCPRO; | |
9306 | |
9307 return nsublis (alist, tree, check_test, test_not_unboundp, test, key, 0); | |
9308 } | |
9309 | |
9310 DEFUN ("subst", Fsubst, 3, MANY, 0, /* | |
9311 Substitute NEW for OLD everywhere in TREE (non-destructively). | |
9312 | |
9313 Return a copy of TREE with all elements `eql' to OLD replaced by NEW. | |
9314 | |
9315 See `member*' for the meaning of :test, :test-not and :key. | |
9316 | |
9317 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9318 */ | |
9319 (int nargs, Lisp_Object *args)) | |
9320 { | |
9321 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]), | |
9322 Qnil); | |
9323 args[1] = alist; | |
9324 result = Fsublis (nargs - 1, args + 1); | |
9325 free_cons (XCAR (alist)); | |
9326 free_cons (alist); | |
9327 | |
9328 return result; | |
9329 } | |
9330 | |
9331 DEFUN ("nsubst", Fnsubst, 3, MANY, 0, /* | |
9332 Substitute NEW for OLD everywhere in TREE (destructively). | |
9333 | |
9334 Any element of TREE which is `eql' to OLD is changed to NEW (via a call to | |
9335 `setcar'). | |
9336 | |
9337 See `member*' for the meaning of the keywords. | |
9338 | |
9339 arguments: (NEW OLD TREE &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9340 */ | |
9341 (int nargs, Lisp_Object *args)) | |
9342 { | |
9343 Lisp_Object result, alist = noseeum_cons (noseeum_cons (args[1], args[0]), | |
9344 Qnil); | |
9345 args[1] = alist; | |
9346 result = Fnsublis (nargs - 1, args + 1); | |
9347 free_cons (XCAR (alist)); | |
9348 free_cons (alist); | |
9349 | |
9350 return result; | |
9351 } | |
9352 | |
9353 static Boolint | |
9354 tree_equal (Lisp_Object tree1, Lisp_Object tree2, | |
9355 check_test_func_t check_test, Boolint test_not_unboundp, | |
9356 Lisp_Object test, Lisp_Object key, int depth) | |
9357 { | |
9358 Lisp_Object tortoise1 = tree1, tortoise2 = tree2; | |
9359 struct gcpro gcpro1, gcpro2; | |
9360 int count = 0; | |
9361 Boolint result; | |
9362 | |
9363 if (depth + lisp_eval_depth > max_lisp_eval_depth) | |
9364 { | |
9365 stack_overflow ("Stack overflow in tree-equal", tree1); | |
9366 } | |
9367 | |
9368 GCPRO2 (tree1, tree2); | |
9369 | |
9370 while (CONSP (tree1) && CONSP (tree2) | |
9371 && tree_equal (XCAR (tree1), XCAR (tree2), check_test, | |
9372 test_not_unboundp, test, key, depth + 1)) | |
9373 { | |
9374 tree1 = XCDR (tree1); | |
9375 tree2 = XCDR (tree2); | |
9376 | |
9377 if (++count > CIRCULAR_LIST_SUSPICION_LENGTH) | |
9378 { | |
9379 if (count & 1) | |
9380 { | |
9381 tortoise1 = XCDR (tortoise1); | |
9382 tortoise2 = XCDR (tortoise2); | |
9383 } | |
9384 | |
9385 if (EQ (tortoise1, tree1)) | |
9386 { | |
9387 signal_circular_list_error (tree1); | |
9388 } | |
9389 | |
9390 if (EQ (tortoise2, tree2)) | |
9391 { | |
9392 signal_circular_list_error (tree2); | |
9393 } | |
9394 } | |
9395 } | |
9396 | |
9397 if (CONSP (tree1) || CONSP (tree2)) | |
9398 { | |
9399 UNGCPRO; | |
9400 return 0; | |
9401 } | |
9402 | |
9403 result = check_test (test, key, tree1, tree2) == test_not_unboundp; | |
9404 UNGCPRO; | |
9405 | |
9406 return result; | |
9407 } | |
9408 | |
9409 DEFUN ("tree-equal", Ftree_equal, 2, MANY, 0, /* | |
9410 Return t if TREE1 and TREE2 have `eql' leaves. | |
9411 | |
9412 Atoms are compared by `eql', unless another test is specified using | |
9413 :test; cons cells are compared recursively. | |
9414 | |
9415 See `union' for the meaning of :test, :test-not and :key. | |
9416 | |
9417 arguments: (TREE1 TREE2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
9418 */ | |
9419 (int nargs, Lisp_Object *args)) | |
9420 { | |
9421 Lisp_Object tree1 = args[0], tree2 = args[1]; | |
9422 Boolint test_not_unboundp = 1; | |
9423 check_test_func_t check_test = NULL; | |
9424 | |
9425 PARSE_KEYWORDS (Ftree_equal, nargs, args, 3, (test, key, test_not), | |
9426 (key = Qidentity)); | |
9427 | |
9428 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
9429 &test_not_unboundp, &check_test); | |
9430 | |
9431 return tree_equal (tree1, tree2, check_test, test_not_unboundp, test, key, | |
9432 0) ? Qt : Qnil; | |
9433 } | |
9434 | |
9435 static Lisp_Object | |
9436 mismatch_from_end (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1, | |
9437 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2, | |
9438 check_test_func_t check_match, Boolint test_not_unboundp, | |
9439 Lisp_Object test, Lisp_Object key, | |
9440 Boolint UNUSED (return_sequence1_index)) | |
9441 { | |
9442 Elemcount sequence1_len = XINT (Flength (sequence1)); | |
9443 Elemcount sequence2_len = XINT (Flength (sequence2)), ii = 0; | |
9444 Elemcount starting1, ending1, starting2, ending2; | |
9445 Lisp_Object *sequence1_storage = NULL, *sequence2_storage = NULL; | |
9446 struct gcpro gcpro1, gcpro2; | |
9447 | |
9448 check_sequence_range (sequence1, start1, end1, make_int (sequence1_len)); | |
9449 starting1 = XINT (start1); | |
9450 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX; | |
9451 ending1 = min (ending1, sequence1_len); | |
9452 | |
9453 check_sequence_range (sequence2, start2, end2, make_int (sequence2_len)); | |
9454 starting2 = XINT (start2); | |
9455 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX; | |
9456 ending2 = min (ending2, sequence2_len); | |
9457 | |
9458 if (LISTP (sequence1)) | |
9459 { | |
9460 Lisp_Object *saving; | |
9461 sequence1_storage = saving | |
9462 = alloca_array (Lisp_Object, ending1 - starting1); | |
9463 | |
9464 { | |
9465 EXTERNAL_LIST_LOOP_2 (elt, sequence1) | |
9466 { | |
9467 if (starting1 <= ii && ii < ending1) | |
9468 { | |
9469 *saving++ = elt; | |
9470 } | |
9471 else if (ii == ending1) | |
9472 { | |
9473 break; | |
9474 } | |
9475 | |
9476 ++ii; | |
9477 } | |
9478 } | |
9479 } | |
9480 else if (STRINGP (sequence1)) | |
9481 { | |
9482 const Ibyte *cursor = string_char_addr (sequence1, starting1); | |
9483 | |
9484 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence1_storage, ii, | |
9485 ending1 - starting1); | |
9486 | |
9487 } | |
9488 else if (BIT_VECTORP (sequence1)) | |
9489 { | |
9490 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence1); | |
9491 sequence1_storage = alloca_array (Lisp_Object, ending1 - starting1); | |
9492 for (ii = starting1; ii < ending1; ++ii) | |
9493 { | |
9494 sequence1_storage[ii - starting1] | |
9495 = make_int (bit_vector_bit (vv, ii)); | |
9496 } | |
9497 } | |
9498 else | |
9499 { | |
9500 sequence1_storage = XVECTOR_DATA (sequence1) + starting1; | |
9501 } | |
9502 | |
9503 ii = 0; | |
9504 | |
9505 if (LISTP (sequence2)) | |
9506 { | |
9507 Lisp_Object *saving; | |
9508 sequence2_storage = saving | |
9509 = alloca_array (Lisp_Object, ending2 - starting2); | |
9510 | |
9511 { | |
9512 EXTERNAL_LIST_LOOP_2 (elt, sequence2) | |
9513 { | |
9514 if (starting2 <= ii && ii < ending2) | |
9515 { | |
9516 *saving++ = elt; | |
9517 } | |
9518 else if (ii == ending2) | |
9519 { | |
9520 break; | |
9521 } | |
9522 | |
9523 ++ii; | |
9524 } | |
9525 } | |
9526 } | |
9527 else if (STRINGP (sequence2)) | |
9528 { | |
9529 const Ibyte *cursor = string_char_addr (sequence2, starting2); | |
9530 | |
9531 STRING_DATA_TO_OBJECT_ARRAY (cursor, sequence2_storage, ii, | |
9532 ending2 - starting2); | |
9533 | |
9534 } | |
9535 else if (BIT_VECTORP (sequence2)) | |
9536 { | |
9537 Lisp_Bit_Vector *vv = XBIT_VECTOR (sequence2); | |
9538 sequence2_storage = alloca_array (Lisp_Object, ending2 - starting2); | |
9539 for (ii = starting2; ii < ending2; ++ii) | |
9540 { | |
9541 sequence2_storage[ii - starting2] | |
9542 = make_int (bit_vector_bit (vv, ii)); | |
9543 } | |
9544 } | |
9545 else | |
9546 { | |
9547 sequence2_storage = XVECTOR_DATA (sequence2) + starting2; | |
9548 } | |
9549 | |
9550 GCPRO2 (sequence1_storage[0], sequence2_storage[0]); | |
9551 gcpro1.nvars = ending1 - starting1; | |
9552 gcpro2.nvars = ending2 - starting2; | |
9553 | |
9554 while (ending1 > starting1 && ending2 > starting2) | |
9555 { | |
9556 --ending1; | |
9557 --ending2; | |
9558 | |
9559 if (check_match (test, key, sequence1_storage[ending1 - starting1], | |
9560 sequence2_storage[ending2 - starting2]) | |
9561 != test_not_unboundp) | |
9562 { | |
9563 UNGCPRO; | |
9564 return make_integer (ending1 + 1); | |
9565 } | |
9566 } | |
9567 | |
9568 UNGCPRO; | |
9569 | |
9570 if (ending1 > starting1 || ending2 > starting2) | |
9571 { | |
9572 return make_integer (ending1); | |
9573 } | |
9574 | |
9575 return Qnil; | |
9576 } | |
9577 | |
9578 static Lisp_Object | |
9579 mismatch_list_list (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1, | |
9580 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2, | |
9581 check_test_func_t check_match, Boolint test_not_unboundp, | |
9582 Lisp_Object test, Lisp_Object key, | |
9583 Boolint UNUSED (return_list_index)) | |
9584 { | |
9585 Lisp_Object sequence1_tortoise = sequence1, sequence2_tortoise = sequence2; | |
9586 Lisp_Object orig_sequence1 = sequence1, orig_sequence2 = sequence2; | |
9587 Elemcount ending1 = EMACS_INT_MAX, ending2 = EMACS_INT_MAX; | |
9588 Elemcount starting1, starting2, counting, startcounting; | |
9589 Elemcount shortest_len = 0; | |
9590 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
9591 | |
9592 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX; | |
9593 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX; | |
9594 | |
9595 if (!NILP (end1)) | |
9596 { | |
9597 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX; | |
9598 } | |
9599 | |
9600 if (!NILP (end2)) | |
9601 { | |
9602 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX; | |
9603 } | |
9604 | |
9605 if (!ZEROP (start1)) | |
9606 { | |
9607 sequence1 = Fnthcdr (start1, sequence1); | |
9608 | |
9609 if (NILP (sequence1)) | |
9610 { | |
9611 check_sequence_range (sequence1_tortoise, start1, end1, | |
9612 Flength (sequence1_tortoise)); | |
9613 /* Give up early here. */ | |
9614 return Qnil; | |
9615 } | |
9616 | |
9617 ending1 -= starting1; | |
9618 starting1 = 0; | |
9619 sequence1_tortoise = sequence1; | |
9620 } | |
9621 | |
9622 if (!ZEROP (start2)) | |
9623 { | |
9624 sequence2 = Fnthcdr (start2, sequence2); | |
9625 | |
9626 if (NILP (sequence2)) | |
9627 { | |
9628 check_sequence_range (sequence2_tortoise, start2, end2, | |
9629 Flength (sequence2_tortoise)); | |
9630 return Qnil; | |
9631 } | |
9632 | |
9633 ending2 -= starting2; | |
9634 starting2 = 0; | |
9635 sequence2_tortoise = sequence2; | |
9636 } | |
9637 | |
9638 GCPRO4 (sequence1, sequence2, sequence1_tortoise, sequence2_tortoise); | |
9639 | |
9640 counting = startcounting = min (ending1, ending2); | |
9641 | |
9642 while (counting-- > 0 && !NILP (sequence1) && !NILP (sequence2)) | |
9643 { | |
9644 if (check_match (test, key, | |
9645 CONSP (sequence1) ? XCAR (sequence1) | |
9646 : Fcar (sequence1), | |
9647 CONSP (sequence2) ? XCAR (sequence2) | |
9648 : Fcar (sequence2) ) != test_not_unboundp) | |
9649 { | |
9650 UNGCPRO; | |
9651 return make_integer (XINT (start1) + shortest_len); | |
9652 } | |
9653 | |
9654 sequence1 = CONSP (sequence1) ? XCDR (sequence1) : Fcdr (sequence1); | |
9655 sequence2 = CONSP (sequence2) ? XCDR (sequence2) : Fcdr (sequence2); | |
9656 | |
9657 shortest_len++; | |
9658 | |
9659 if (startcounting - counting > CIRCULAR_LIST_SUSPICION_LENGTH) | |
9660 { | |
9661 if (counting & 1) | |
9662 { | |
9663 sequence1_tortoise = XCDR (sequence1_tortoise); | |
9664 sequence2_tortoise = XCDR (sequence2_tortoise); | |
9665 } | |
9666 | |
9667 if (EQ (sequence1, sequence1_tortoise)) | |
9668 { | |
9669 signal_circular_list_error (sequence1); | |
9670 } | |
9671 | |
9672 if (EQ (sequence2, sequence2_tortoise)) | |
9673 { | |
9674 signal_circular_list_error (sequence2); | |
9675 } | |
9676 } | |
9677 } | |
9678 | |
9679 UNGCPRO; | |
9680 | |
9681 if (NILP (sequence1)) | |
9682 { | |
9683 Lisp_Object args[] = { start1, make_int (shortest_len) }; | |
9684 check_sequence_range (orig_sequence1, start1, end1, | |
9685 Fplus (countof (args), args)); | |
9686 } | |
9687 | |
9688 if (NILP (sequence2)) | |
9689 { | |
9690 Lisp_Object args[] = { start2, make_int (shortest_len) }; | |
9691 check_sequence_range (orig_sequence2, start2, end2, | |
9692 Fplus (countof (args), args)); | |
9693 } | |
9694 | |
9695 if ((!NILP (end1) && shortest_len != ending1 - starting1) || | |
9696 (!NILP (end2) && shortest_len != ending2 - starting2)) | |
9697 { | |
9698 return make_integer (XINT (start1) + shortest_len); | |
9699 } | |
9700 | |
9701 if ((NILP (end1) && CONSP (sequence1)) || (NILP (end2) && CONSP (sequence2))) | |
9702 { | |
9703 return make_integer (XINT (start1) + shortest_len); | |
9704 } | |
9705 | |
9706 return Qnil; | |
9707 } | |
9708 | |
9709 static Lisp_Object | |
9710 mismatch_list_string (Lisp_Object list, Lisp_Object list_start, | |
9711 Lisp_Object list_end, | |
9712 Lisp_Object string, Lisp_Object string_start, | |
9713 Lisp_Object string_end, | |
9714 check_test_func_t check_match, | |
9715 Boolint test_not_unboundp, | |
9716 Lisp_Object test, Lisp_Object key, | |
9717 Boolint return_list_index) | |
9718 { | |
9719 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data; | |
9720 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string); | |
9721 Elemcount char_count = 0, list_starting, list_ending; | |
9722 Elemcount string_starting, string_ending; | |
9723 Lisp_Object character, orig_list = list; | |
9724 struct gcpro gcpro1; | |
9725 | |
9726 list_ending = INTP (list_end) ? XINT (list_end) : 1 + EMACS_INT_MAX; | |
9727 list_starting = INTP (list_start) ? XINT (list_start) : 1 + EMACS_INT_MAX; | |
9728 | |
9729 string_ending = INTP (string_end) ? XINT (string_end) : 1 + EMACS_INT_MAX; | |
9730 string_starting | |
9731 = INTP (string_start) ? XINT (string_start) : 1 + EMACS_INT_MAX; | |
9732 | |
9733 while (char_count < string_starting && string_offset < string_len) | |
9734 { | |
9735 INC_IBYTEPTR (string_data); | |
9736 string_offset = string_data - startp; | |
9737 char_count++; | |
9738 } | |
9739 | |
9740 if (!ZEROP (list_start)) | |
9741 { | |
9742 list = Fnthcdr (list_start, list); | |
9743 if (NILP (list)) | |
9744 { | |
9745 check_sequence_range (orig_list, list_start, list_end, | |
9746 Flength (orig_list)); | |
9747 return Qnil; | |
9748 } | |
9749 | |
9750 list_ending -= list_starting; | |
9751 list_starting = 0; | |
9752 } | |
9753 | |
9754 GCPRO1 (list); | |
9755 | |
9756 while (list_starting < list_ending && string_starting < string_ending | |
9757 && string_offset < string_len && !NILP (list)) | |
9758 { | |
9759 character = make_char (itext_ichar (string_data)); | |
9760 | |
9761 if (return_list_index) | |
9762 { | |
9763 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list), | |
9764 character) | |
9765 != test_not_unboundp) | |
9766 { | |
9767 UNGCPRO; | |
9768 return make_integer (XINT (list_start) + char_count); | |
9769 } | |
9770 } | |
9771 else | |
9772 { | |
9773 if (check_match (test, key, character, | |
9774 CONSP (list) ? XCAR (list) : Fcar (list)) | |
9775 != test_not_unboundp) | |
9776 { | |
9777 UNGCPRO; | |
9778 return make_integer (char_count); | |
9779 } | |
9780 } | |
9781 | |
9782 list = CONSP (list) ? XCDR (list) : Fcdr (list); | |
9783 | |
9784 startp = XSTRING_DATA (string); | |
9785 string_data = startp + string_offset; | |
9786 if (string_len != XSTRING_LENGTH (string) | |
9787 || !valid_ibyteptr_p (string_data)) | |
9788 { | |
9789 mapping_interaction_error (Qmismatch, string); | |
9790 } | |
9791 | |
9792 list_starting++; | |
9793 string_starting++; | |
9794 char_count++; | |
9795 INC_IBYTEPTR (string_data); | |
9796 string_offset = string_data - startp; | |
9797 } | |
9798 | |
9799 UNGCPRO; | |
9800 | |
9801 if (NILP (list)) | |
9802 { | |
9803 Lisp_Object args[] = { list_start, make_int (char_count) }; | |
9804 check_sequence_range (orig_list, list_start, list_end, | |
9805 Fplus (countof (args), args)); | |
9806 } | |
9807 | |
9808 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string)) | |
9809 { | |
9810 check_sequence_range (string, string_start, string_end, | |
9811 make_int (char_count)); | |
9812 } | |
9813 | |
9814 if ((NILP (string_end) ? | |
9815 string_offset < string_len : string_starting < string_ending) || | |
9816 (NILP (list_end) ? !NILP (list) : list_starting < list_ending)) | |
9817 { | |
9818 return make_integer (return_list_index ? XINT (list_start) + char_count : | |
9819 char_count); | |
9820 } | |
9821 | |
9822 return Qnil; | |
9823 } | |
9824 | |
9825 static Lisp_Object | |
9826 mismatch_list_array (Lisp_Object list, Lisp_Object list_start, | |
9827 Lisp_Object list_end, | |
9828 Lisp_Object array, Lisp_Object array_start, | |
9829 Lisp_Object array_end, | |
9830 check_test_func_t check_match, | |
9831 Boolint test_not_unboundp, | |
9832 Lisp_Object test, Lisp_Object key, | |
9833 Boolint return_list_index) | |
9834 { | |
9835 Elemcount ii = 0, list_starting, list_ending; | |
9836 Elemcount array_starting, array_ending, array_len; | |
9837 Lisp_Object orig_list = list; | |
9838 struct gcpro gcpro1; | |
9839 | |
9840 list_ending = INTP (list_end) ? XINT (list_end) : 1 + EMACS_INT_MAX; | |
9841 list_starting = INTP (list_start) ? XINT (list_start) : 1 + EMACS_INT_MAX; | |
9842 | |
9843 array_ending = INTP (array_end) ? XINT (array_end) : 1 + EMACS_INT_MAX; | |
9844 array_starting = INTP (array_start) ? XINT (array_start) : 1 + EMACS_INT_MAX; | |
9845 array_len = XINT (Flength (array)); | |
9846 | |
9847 array_ending = min (array_ending, array_len); | |
9848 | |
9849 check_sequence_range (array, array_start, array_end, make_int (array_len)); | |
9850 | |
9851 if (!ZEROP (list_start)) | |
9852 { | |
9853 list = Fnthcdr (list_start, list); | |
9854 if (NILP (list)) | |
9855 { | |
9856 check_sequence_range (orig_list, list_start, list_end, | |
9857 Flength (orig_list)); | |
9858 return Qnil; | |
9859 } | |
9860 | |
9861 list_ending -= list_starting; | |
9862 list_starting = 0; | |
9863 } | |
9864 | |
9865 GCPRO1 (list); | |
9866 | |
9867 while (list_starting < list_ending && array_starting < array_ending | |
9868 && !NILP (list)) | |
9869 { | |
9870 if (return_list_index) | |
9871 { | |
9872 if (check_match (test, key, CONSP (list) ? XCAR (list) : Fcar (list), | |
9873 Faref (array, make_int (array_starting))) | |
9874 != test_not_unboundp) | |
9875 { | |
9876 UNGCPRO; | |
9877 return make_integer (XINT (list_start) + ii); | |
9878 } | |
9879 } | |
9880 else | |
9881 { | |
9882 if (check_match (test, key, Faref (array, make_int (array_starting)), | |
9883 CONSP (list) ? XCAR (list) : Fcar (list)) | |
9884 != test_not_unboundp) | |
9885 { | |
9886 UNGCPRO; | |
9887 return make_integer (array_starting); | |
9888 } | |
9889 } | |
9890 | |
9891 list = CONSP (list) ? XCDR (list) : Fcdr (list); | |
9892 list_starting++; | |
9893 array_starting++; | |
9894 ii++; | |
9895 } | |
9896 | |
9897 UNGCPRO; | |
9898 | |
9899 if (NILP (list)) | |
9900 { | |
9901 Lisp_Object args[] = { list_start, make_int (ii) }; | |
9902 check_sequence_range (orig_list, list_start, list_end, | |
9903 Fplus (countof (args), args)); | |
9904 } | |
9905 | |
9906 if (array_starting < array_ending || | |
9907 (NILP (list_end) ? !NILP (list) : list_starting < list_ending)) | |
9908 { | |
9909 return make_integer (return_list_index ? XINT (list_start) + ii : | |
9910 array_starting); | |
9911 } | |
9912 | |
9913 return Qnil; | |
9914 } | |
9915 | |
9916 static Lisp_Object | |
9917 mismatch_string_array (Lisp_Object string, Lisp_Object string_start, | |
9918 Lisp_Object string_end, | |
9919 Lisp_Object array, Lisp_Object array_start, | |
9920 Lisp_Object array_end, | |
9921 check_test_func_t check_match, Boolint test_not_unboundp, | |
9922 Lisp_Object test, Lisp_Object key, | |
9923 Boolint return_string_index) | |
9924 { | |
9925 Ibyte *string_data = XSTRING_DATA (string), *startp = string_data; | |
9926 Bytecount string_offset = 0, string_len = XSTRING_LENGTH (string); | |
9927 Elemcount char_count = 0, array_starting, array_ending, array_length; | |
9928 Elemcount string_starting, string_ending; | |
9929 Lisp_Object character; | |
9930 | |
9931 array_starting = INTP (array_start) ? XINT (array_start) : 1 + EMACS_INT_MAX; | |
9932 array_ending = INTP (array_end) ? XINT (array_end) : 1 + EMACS_INT_MAX; | |
9933 array_length = XINT (Flength (array)); | |
9934 check_sequence_range (array, array_start, array_end, make_int (array_length)); | |
9935 array_ending = min (array_ending, array_length); | |
9936 | |
9937 string_ending = INTP (string_end) ? XINT (string_end) : 1 + EMACS_INT_MAX; | |
9938 string_starting | |
9939 = INTP (string_start) ? XINT (string_start) : 1 + EMACS_INT_MAX; | |
9940 | |
9941 while (char_count < string_starting && string_offset < string_len) | |
9942 { | |
9943 INC_IBYTEPTR (string_data); | |
9944 string_offset = string_data - startp; | |
9945 char_count++; | |
9946 } | |
9947 | |
9948 while (array_starting < array_ending && string_starting < string_ending | |
9949 && string_offset < string_len) | |
9950 { | |
9951 character = make_char (itext_ichar (string_data)); | |
9952 | |
9953 if (return_string_index) | |
9954 { | |
9955 if (check_match (test, key, character, | |
9956 Faref (array, make_int (array_starting))) | |
9957 != test_not_unboundp) | |
9958 { | |
9959 return make_integer (char_count); | |
9960 } | |
9961 } | |
9962 else | |
9963 { | |
9964 if (check_match (test, key, | |
9965 Faref (array, make_int (array_starting)), | |
9966 character) | |
9967 != test_not_unboundp) | |
9968 { | |
9969 return make_integer (XINT (array_start) + char_count); | |
9970 } | |
9971 } | |
9972 | |
9973 startp = XSTRING_DATA (string); | |
9974 string_data = startp + string_offset; | |
9975 if (string_len != XSTRING_LENGTH (string) | |
9976 || !valid_ibyteptr_p (string_data)) | |
9977 { | |
9978 mapping_interaction_error (Qmismatch, string); | |
9979 } | |
9980 | |
9981 array_starting++; | |
9982 string_starting++; | |
9983 char_count++; | |
9984 INC_IBYTEPTR (string_data); | |
9985 string_offset = string_data - startp; | |
9986 } | |
9987 | |
9988 if (string_data == XSTRING_DATA (string) + XSTRING_LENGTH (string)) | |
9989 { | |
9990 check_sequence_range (string, string_start, string_end, | |
9991 make_int (char_count)); | |
9992 } | |
9993 | |
9994 if ((NILP (string_end) ? | |
9995 string_offset < string_len : string_starting < string_ending) || | |
9996 (NILP (array_end) ? !NILP (array) : array_starting < array_ending)) | |
9997 { | |
9998 return make_integer (return_string_index ? char_count : | |
9999 XINT (array_start) + char_count); | |
10000 } | |
10001 | |
10002 return Qnil; | |
10003 } | |
10004 | |
10005 static Lisp_Object | |
10006 mismatch_string_string (Lisp_Object string1, | |
10007 Lisp_Object string1_start, Lisp_Object string1_end, | |
10008 Lisp_Object string2, Lisp_Object string2_start, | |
10009 Lisp_Object string2_end, | |
10010 check_test_func_t check_match, | |
10011 Boolint test_not_unboundp, | |
10012 Lisp_Object test, Lisp_Object key, | |
10013 Boolint UNUSED (return_string1_index)) | |
10014 { | |
10015 Ibyte *string1_data = XSTRING_DATA (string1), *startp1 = string1_data; | |
10016 Bytecount string1_offset = 0, string1_len = XSTRING_LENGTH (string1); | |
10017 Ibyte *string2_data = XSTRING_DATA (string2), *startp2 = string2_data; | |
10018 Bytecount string2_offset = 0, string2_len = XSTRING_LENGTH (string2); | |
10019 Elemcount char_count1 = 0, string1_starting, string1_ending; | |
10020 Elemcount char_count2 = 0, string2_starting, string2_ending; | |
10021 Lisp_Object character1, character2; | |
10022 | |
10023 string1_ending = INTP (string1_end) ? XINT (string1_end) : 1 + EMACS_INT_MAX; | |
10024 string1_starting | |
10025 = INTP (string1_start) ? XINT (string1_start) : 1 + EMACS_INT_MAX; | |
10026 | |
10027 string2_starting | |
10028 = INTP (string2_start) ? XINT (string2_start) : 1 + EMACS_INT_MAX; | |
10029 string2_ending = INTP (string2_end) ? XINT (string2_end) : 1 + EMACS_INT_MAX; | |
10030 | |
10031 while (char_count1 < string1_starting && string1_offset < string1_len) | |
10032 { | |
10033 INC_IBYTEPTR (string1_data); | |
10034 string1_offset = string1_data - startp1; | |
10035 char_count1++; | |
10036 } | |
10037 | |
10038 while (char_count2 < string2_starting && string2_offset < string2_len) | |
10039 { | |
10040 INC_IBYTEPTR (string2_data); | |
10041 string2_offset = string2_data - startp2; | |
10042 char_count2++; | |
10043 } | |
10044 | |
10045 while (string2_starting < string2_ending && string1_starting < string1_ending | |
10046 && string1_offset < string1_len && string2_offset < string2_len) | |
10047 { | |
10048 character1 = make_char (itext_ichar (string1_data)); | |
10049 character2 = make_char (itext_ichar (string2_data)); | |
10050 | |
10051 if (check_match (test, key, character1, character2) | |
10052 != test_not_unboundp) | |
10053 { | |
10054 return make_integer (char_count1); | |
10055 } | |
10056 | |
10057 startp1 = XSTRING_DATA (string1); | |
10058 string1_data = startp1 + string1_offset; | |
10059 if (string1_len != XSTRING_LENGTH (string1) | |
10060 || !valid_ibyteptr_p (string1_data)) | |
10061 { | |
10062 mapping_interaction_error (Qmismatch, string1); | |
10063 } | |
10064 | |
10065 startp2 = XSTRING_DATA (string2); | |
10066 string2_data = startp2 + string2_offset; | |
10067 if (string2_len != XSTRING_LENGTH (string2) | |
10068 || !valid_ibyteptr_p (string2_data)) | |
10069 { | |
10070 mapping_interaction_error (Qmismatch, string2); | |
10071 } | |
10072 | |
10073 string2_starting++; | |
10074 string1_starting++; | |
10075 char_count1++; | |
10076 char_count2++; | |
10077 INC_IBYTEPTR (string1_data); | |
10078 string1_offset = string1_data - startp1; | |
10079 INC_IBYTEPTR (string2_data); | |
10080 string2_offset = string2_data - startp2; | |
10081 } | |
10082 | |
10083 if (string1_data == XSTRING_DATA (string1) + XSTRING_LENGTH (string1)) | |
10084 { | |
10085 check_sequence_range (string1, string1_start, string1_end, | |
10086 make_int (char_count1)); | |
10087 } | |
10088 | |
10089 if (string2_data == XSTRING_DATA (string2) + XSTRING_LENGTH (string2)) | |
10090 { | |
10091 check_sequence_range (string2, string2_start, string2_end, | |
10092 make_int (char_count2)); | |
10093 } | |
10094 | |
10095 if ((!NILP (string1_end) && string1_starting < string1_ending) || | |
10096 (!NILP (string2_end) && string2_starting < string2_ending)) | |
10097 { | |
10098 return make_integer (char_count1); | |
10099 } | |
10100 | |
10101 if ((NILP (string1_end) && string1_data | |
10102 < (XSTRING_DATA (string1) + XSTRING_LENGTH (string1))) || | |
10103 (NILP (string2_end) && string2_data | |
10104 < (XSTRING_DATA (string2) + XSTRING_LENGTH (string2)))) | |
10105 { | |
10106 return make_integer (char_count1); | |
10107 } | |
10108 | |
10109 return Qnil; | |
10110 } | |
10111 | |
10112 static Lisp_Object | |
10113 mismatch_array_array (Lisp_Object array1, Lisp_Object start1, Lisp_Object end1, | |
10114 Lisp_Object array2, Lisp_Object start2, Lisp_Object end2, | |
10115 check_test_func_t check_match, Boolint test_not_unboundp, | |
10116 Lisp_Object test, Lisp_Object key, | |
10117 Boolint UNUSED (return_array1_index)) | |
10118 { | |
10119 Elemcount len1 = XINT (Flength (array1)), len2 = XINT (Flength (array2)); | |
10120 Elemcount ending1 = EMACS_INT_MAX, ending2 = EMACS_INT_MAX; | |
10121 Elemcount starting1, starting2; | |
10122 | |
10123 check_sequence_range (array1, start1, end1, make_int (len1)); | |
10124 check_sequence_range (array2, start2, end2, make_int (len2)); | |
10125 | |
10126 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX; | |
10127 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX; | |
10128 | |
10129 if (!NILP (end1)) | |
10130 { | |
10131 ending1 = INTP (end1) ? XINT (end1) : 1 + EMACS_INT_MAX; | |
10132 } | |
10133 | |
10134 if (!NILP (end2)) | |
10135 { | |
10136 ending2 = INTP (end2) ? XINT (end2) : 1 + EMACS_INT_MAX; | |
10137 } | |
10138 | |
10139 ending1 = min (ending1, len1); | |
10140 ending2 = min (ending2, len2); | |
10141 | |
10142 while (starting1 < ending1 && starting2 < ending2) | |
10143 { | |
10144 if (check_match (test, key, Faref (array1, make_int (starting1)), | |
10145 Faref (array2, make_int (starting2))) | |
10146 != test_not_unboundp) | |
10147 { | |
10148 return make_integer (starting1); | |
10149 } | |
10150 starting1++; | |
10151 starting2++; | |
10152 } | |
10153 | |
10154 if (starting1 < ending1 || starting2 < ending2) | |
10155 { | |
10156 return make_integer (starting1); | |
10157 } | |
10158 | |
10159 return Qnil; | |
10160 } | |
10161 | |
10162 typedef Lisp_Object | |
10163 (*mismatch_func_t) (Lisp_Object sequence1, Lisp_Object start1, Lisp_Object end1, | |
10164 Lisp_Object sequence2, Lisp_Object start2, Lisp_Object end2, | |
10165 check_test_func_t check_match, Boolint test_not_unboundp, | |
10166 Lisp_Object test, Lisp_Object key, | |
10167 Boolint return_list_index); | |
10168 | |
10169 static mismatch_func_t | |
10170 get_mismatch_func (Lisp_Object sequence1, Lisp_Object sequence2, | |
10171 Lisp_Object from_end, Boolint *return_sequence1_index_out) | |
10172 { | |
10173 CHECK_SEQUENCE (sequence1); | |
10174 CHECK_SEQUENCE (sequence2); | |
10175 | |
10176 if (!NILP (from_end)) | |
10177 { | |
10178 *return_sequence1_index_out = 1; | |
10179 return mismatch_from_end; | |
10180 } | |
10181 | |
10182 if (LISTP (sequence1)) | |
10183 { | |
10184 if (LISTP (sequence2)) | |
10185 { | |
10186 *return_sequence1_index_out = 1; | |
10187 return mismatch_list_list; | |
10188 } | |
10189 | |
10190 if (STRINGP (sequence2)) | |
10191 { | |
10192 *return_sequence1_index_out = 1; | |
10193 return mismatch_list_string; | |
10194 } | |
10195 | |
10196 *return_sequence1_index_out = 1; | |
10197 return mismatch_list_array; | |
10198 } | |
10199 | |
10200 if (STRINGP (sequence1)) | |
10201 { | |
10202 if (STRINGP (sequence2)) | |
10203 { | |
10204 *return_sequence1_index_out = 1; | |
10205 return mismatch_string_string; | |
10206 } | |
10207 | |
10208 if (LISTP (sequence2)) | |
10209 { | |
10210 *return_sequence1_index_out = 0; | |
10211 return mismatch_list_string; | |
10212 } | |
10213 | |
10214 *return_sequence1_index_out = 1; | |
10215 return mismatch_string_array; | |
10216 } | |
10217 | |
10218 if (ARRAYP (sequence1)) | |
10219 { | |
10220 if (STRINGP (sequence2)) | |
10221 { | |
10222 *return_sequence1_index_out = 0; | |
10223 return mismatch_string_array; | |
10224 } | |
10225 | |
10226 if (LISTP (sequence2)) | |
10227 { | |
10228 *return_sequence1_index_out = 0; | |
10229 return mismatch_list_array; | |
10230 } | |
10231 | |
10232 *return_sequence1_index_out = 1; | |
10233 return mismatch_array_array; | |
10234 } | |
10235 | |
10236 RETURN_NOT_REACHED (NULL); | |
10237 return NULL; | |
10238 } | |
10239 | |
10240 DEFUN ("mismatch", Fmismatch, 2, MANY, 0, /* | |
10241 Compare SEQUENCE1 with SEQUENCE2, return index of first mismatching element. | |
10242 | |
10243 Return nil if the sequences match. If one sequence is a prefix of the | |
10244 other, the return value indicates the end of the shorter sequence. A | |
10245 non-nil return value always reflects an index into SEQUENCE1. | |
10246 | |
10247 See `search' for the meaning of the keywords." | |
10248 | |
10249 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT) | |
10250 */ | |
10251 (int nargs, Lisp_Object *args)) | |
10252 { | |
10253 Lisp_Object sequence1 = args[0], sequence2 = args[1]; | |
10254 Boolint test_not_unboundp = 1, return_first_index = 0; | |
10255 check_test_func_t check_match = NULL; | |
10256 mismatch_func_t mismatch = NULL; | |
10257 | |
10258 PARSE_KEYWORDS (Fmismatch, nargs, args, 8, | |
10259 (test, key, from_end, start1, end1, start2, end2, test_not), | |
10260 (start1 = start2 = Qzero)); | |
10261 | |
10262 CHECK_SEQUENCE (sequence1); | |
10263 CHECK_SEQUENCE (sequence2); | |
10264 | |
10265 CHECK_NATNUM (start1); | |
10266 CHECK_NATNUM (start2); | |
10267 | |
10268 if (!NILP (end1)) | |
10269 { | |
10270 CHECK_NATNUM (end1); | |
10271 } | |
10272 | |
10273 if (!NILP (end2)) | |
10274 { | |
10275 CHECK_NATNUM (end2); | |
10276 } | |
10277 | |
10278 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10279 &test_not_unboundp, NULL); | |
10280 mismatch = get_mismatch_func (sequence1, sequence2, from_end, | |
10281 &return_first_index); | |
10282 | |
10283 if (return_first_index) | |
10284 { | |
10285 return mismatch (sequence1, start1, end1, sequence2, start2, end2, | |
10286 check_match, test_not_unboundp, test, key, 1); | |
10287 } | |
10288 | |
10289 return mismatch (sequence2, start2, end2, sequence1, start1, end1, | |
10290 check_match, test_not_unboundp, test, key, 0); | |
10291 } | |
10292 | |
10293 DEFUN ("search", Fsearch, 2, MANY, 0, /* | |
10294 Search for SEQUENCE1 as a subsequence of SEQUENCE2. | |
10295 | |
10296 Return the index of the leftmost element of the first match found; return | |
10297 nil if there are no matches. | |
10298 | |
10299 In this function, :start1 and :end1 specify a subsequence of SEQUENCE1, and | |
10300 :start2 and :end2 specify a subsequence of SEQUENCE2. See `remove*' for | |
10301 details of the other keywords. | |
10302 | |
10303 arguments: (SEQUENCE1 SEQUENCE2 &key (TEST #'eql) (KEY #'identity) (START1 0) END1 (START2 0) END2 FROM-END TEST-NOT) | |
10304 */ | |
10305 (int nargs, Lisp_Object *args)) | |
10306 { | |
10307 Lisp_Object sequence1 = args[0], sequence2 = args[1], position0 = Qnil; | |
10308 Boolint test_not_unboundp = 1, return_first = 0; | |
10309 check_test_func_t check_test = NULL, check_match = NULL; | |
10310 mismatch_func_t mismatch = NULL; | |
10311 Elemcount starting1 = 0, ending1 = 1 + EMACS_INT_MAX, starting2 = 0; | |
10312 Elemcount ending2 = 1 + EMACS_INT_MAX, ii = 0; | |
10313 Elemcount length1; | |
10314 Lisp_Object object = Qnil; | |
10315 struct gcpro gcpro1, gcpro2; | |
10316 | |
10317 PARSE_KEYWORDS (Fsearch, nargs, args, 8, | |
10318 (test, key, from_end, start1, end1, start2, end2, test_not), | |
10319 (start1 = start2 = Qzero)); | |
10320 | |
10321 CHECK_SEQUENCE (sequence1); | |
10322 CHECK_SEQUENCE (sequence2); | |
10323 CHECK_KEY_ARGUMENT (key); | |
10324 | |
10325 CHECK_NATNUM (start1); | |
10326 starting1 = INTP (start1) ? XINT (start1) : 1 + EMACS_INT_MAX; | |
10327 CHECK_NATNUM (start2); | |
10328 starting2 = INTP (start2) ? XINT (start2) : 1 + EMACS_INT_MAX; | |
10329 | |
10330 if (!NILP (end1)) | |
10331 { | |
10332 Lisp_Object len1 = Flength (sequence1); | |
10333 | |
10334 CHECK_NATNUM (end1); | |
10335 check_sequence_range (sequence1, start1, end1, len1); | |
10336 ending1 = min (XINT (end1), XINT (len1)); | |
10337 } | |
10338 else | |
10339 { | |
10340 end1 = Flength (sequence1); | |
10341 check_sequence_range (sequence1, start1, end1, end1); | |
10342 ending1 = XINT (end1); | |
10343 } | |
10344 | |
10345 length1 = ending1 - starting1; | |
10346 | |
10347 if (!NILP (end2)) | |
10348 { | |
10349 Lisp_Object len2 = Flength (sequence2); | |
10350 | |
10351 CHECK_NATNUM (end2); | |
10352 check_sequence_range (sequence2, start2, end2, len2); | |
10353 ending2 = min (XINT (end2), XINT (len2)); | |
10354 } | |
10355 else | |
10356 { | |
10357 end2 = Flength (sequence2); | |
10358 check_sequence_range (sequence2, start2, end2, end2); | |
10359 ending2 = XINT (end2); | |
10360 } | |
10361 | |
10362 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10363 &test_not_unboundp, &check_test); | |
10364 mismatch = get_mismatch_func (sequence1, sequence2, from_end, &return_first); | |
10365 | |
10366 if (bytecode_arithcompare (start1, make_integer (ending1)) >= 0) | |
10367 { | |
10368 if (NILP (from_end)) | |
10369 { | |
10370 return start2; | |
10371 } | |
10372 | |
10373 if (NILP (end2)) | |
10374 { | |
10375 return Flength (sequence2); | |
10376 } | |
10377 | |
10378 return end2; | |
10379 } | |
10380 | |
10381 if (NILP (from_end)) | |
10382 { | |
10383 Lisp_Object mismatch_start1 = Fadd1 (start1); | |
10384 Lisp_Object first = KEY (key, Felt (sequence1, start1)); | |
10385 GCPRO2 (first, mismatch_start1); | |
10386 | |
10387 ii = starting2; | |
10388 while (ii < ending2) | |
10389 { | |
10390 position0 = position (&object, first, sequence2, check_test, | |
10391 test_not_unboundp, test, key, make_int (ii), | |
10392 end2, Qnil, Qnil, Qsearch); | |
10393 if (NILP (position0)) | |
10394 { | |
10395 UNGCPRO; | |
10396 return Qnil; | |
10397 } | |
10398 | |
10399 if (length1 + XINT (position0) <= ending2 && | |
10400 (return_first ? | |
10401 NILP (mismatch (sequence1, mismatch_start1, end1, | |
10402 sequence2, | |
10403 make_int (1 + XINT (position0)), | |
10404 make_int (length1 + XINT (position0)), | |
10405 check_match, test_not_unboundp, test, key, 1)) : | |
10406 NILP (mismatch (sequence2, | |
10407 make_int (1 + XINT (position0)), | |
10408 make_int (length1 + XINT (position0)), | |
10409 sequence1, mismatch_start1, end1, | |
10410 check_match, test_not_unboundp, test, key, 0)))) | |
10411 | |
10412 | |
10413 { | |
10414 UNGCPRO; | |
10415 return position0; | |
10416 } | |
10417 | |
10418 ii = XINT (position0) + 1; | |
10419 } | |
10420 | |
10421 UNGCPRO; | |
10422 } | |
10423 else | |
10424 { | |
10425 Lisp_Object mismatch_end1 = make_integer (ending1 - 1); | |
10426 Lisp_Object last = KEY (key, Felt (sequence1, mismatch_end1)); | |
10427 GCPRO2 (last, mismatch_end1); | |
10428 | |
10429 ii = ending2; | |
10430 while (ii > starting2) | |
10431 { | |
10432 position0 = position (&object, last, sequence2, check_test, | |
10433 test_not_unboundp, test, key, start2, | |
10434 make_int (ii), Qt, Qnil, Qsearch); | |
10435 | |
10436 if (NILP (position0)) | |
10437 { | |
10438 UNGCPRO; | |
10439 return Qnil; | |
10440 } | |
10441 | |
10442 if (XINT (position0) - length1 + 1 >= starting2 && | |
10443 (return_first ? | |
10444 NILP (mismatch (sequence1, start1, mismatch_end1, | |
10445 sequence2, | |
10446 make_int (XINT (position0) - length1 + 1), | |
10447 make_int (XINT (position0)), | |
10448 check_match, test_not_unboundp, test, key, 1)) : | |
10449 NILP (mismatch (sequence2, | |
10450 make_int (XINT (position0) - length1 + 1), | |
10451 make_int (XINT (position0)), | |
10452 sequence1, start1, mismatch_end1, | |
10453 check_match, test_not_unboundp, test, key, 0)))) | |
10454 { | |
10455 UNGCPRO; | |
10456 return make_int (XINT (position0) - length1 + 1); | |
10457 } | |
10458 | |
10459 ii = XINT (position0); | |
10460 } | |
10461 | |
10462 UNGCPRO; | |
10463 } | |
10464 | |
10465 return Qnil; | |
10466 } | |
10467 | |
10468 /* These two functions do set operations, those that can be visualised with | |
10469 Venn diagrams. */ | |
10470 static Lisp_Object | |
10471 venn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) | |
10472 { | |
10473 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | |
10474 Lisp_Object result = EQ (caller, Qsubsetp) ? Qt : Qnil, result_tail = Qnil; | |
10475 Lisp_Object keyed = Qnil, ignore = Qnil; | |
10476 Elemcount len; | |
10477 Boolint test_not_unboundp = 1; | |
10478 check_test_func_t check_test = NULL; | |
10479 struct gcpro gcpro1, gcpro2, gcpro3; | |
10480 | |
10481 PARSE_KEYWORDS_8 (caller, nargs, args, 4, (test, key, test_not, stable), | |
10482 NULL, 2, 0); | |
10483 | |
10484 CHECK_LIST (liszt1); | |
10485 CHECK_LIST (liszt2); | |
10486 | |
10487 CHECK_KEY_ARGUMENT (key); | |
10488 | |
10489 if (NILP (liszt1) && intersectionp) | |
10490 { | |
10491 return Qnil; | |
10492 } | |
10493 | |
10494 if (NILP (liszt2)) | |
10495 { | |
10496 return intersectionp ? Qnil : liszt1; | |
10497 } | |
10498 | |
10499 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10500 &test_not_unboundp, &check_test); | |
10501 | |
10502 GCPRO3 (tail, keyed, result); | |
10503 | |
10504 { | |
10505 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | |
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 (EQ (Qsubsetp, caller)) | |
10514 { | |
10515 result = Qnil; | |
10516 break; | |
10517 } | |
10518 else if (NILP (stable)) | |
10519 { | |
10520 result = Fcons (elt, result); | |
10521 } | |
10522 else if (NILP (result)) | |
10523 { | |
10524 result = result_tail = Fcons (elt, Qnil); | |
10525 } | |
10526 else | |
10527 { | |
10528 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10529 result_tail = XCDR (result_tail); | |
10530 } | |
10531 } | |
10532 } | |
10533 } | |
10534 | |
10535 UNGCPRO; | |
10536 | |
10537 return result; | |
10538 } | |
10539 | |
10540 static Lisp_Object | |
10541 nvenn (Lisp_Object caller, int nargs, Lisp_Object *args, Boolint intersectionp) | |
10542 { | |
10543 Lisp_Object liszt1 = args[0], liszt2 = args[1], tortoise_elt, ignore = Qnil; | |
10544 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, prev_tail = Qnil; | |
10545 Elemcount count; | |
10546 Boolint test_not_unboundp = 1; | |
10547 check_test_func_t check_test = NULL; | |
10548 struct gcpro gcpro1, gcpro2, gcpro3; | |
10549 | |
10550 PARSE_KEYWORDS_8 (caller, nargs, args, 3, (test, key, test_not), | |
10551 NULL, 2, 0); | |
10552 | |
10553 CHECK_LIST (liszt1); | |
10554 CHECK_LIST (liszt2); | |
10555 | |
10556 CHECK_KEY_ARGUMENT (key); | |
10557 | |
10558 if (NILP (liszt1) && intersectionp) | |
10559 { | |
10560 return Qnil; | |
10561 } | |
10562 | |
10563 if (NILP (liszt2)) | |
10564 { | |
10565 return intersectionp ? Qnil : liszt1; | |
10566 } | |
10567 | |
10568 get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10569 &test_not_unboundp, &check_test); | |
10570 | |
10571 GCPRO3 (tail, keyed, liszt1); | |
10572 | |
10573 tortoise_elt = tail = liszt1, count = 0; | |
10574 | |
10575 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | |
10576 (signal_malformed_list_error (liszt1), 0)) | |
10577 { | |
10578 keyed = KEY (key, elt); | |
10579 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10580 check_test, test_not_unboundp, | |
10581 test, key, 0, Qzero, Qnil)) | |
10582 == intersectionp) | |
10583 { | |
10584 if (NILP (prev_tail)) | |
10585 { | |
10586 liszt1 = XCDR (tail); | |
10587 } | |
10588 else | |
10589 { | |
10590 XSETCDR (prev_tail, XCDR (tail)); | |
10591 } | |
10592 | |
10593 tail = XCDR (tail); | |
10594 /* List is definitely not circular now! */ | |
10595 count = 0; | |
10596 } | |
10597 else | |
10598 { | |
10599 prev_tail = tail; | |
10600 tail = XCDR (tail); | |
10601 } | |
10602 | |
10603 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
10604 | |
10605 if (count & 1) | |
10606 { | |
10607 tortoise_elt = XCDR (tortoise_elt); | |
10608 } | |
10609 | |
10610 if (EQ (elt, tortoise_elt)) | |
10611 { | |
10612 signal_circular_list_error (liszt1); | |
10613 } | |
10614 } | |
10615 | |
10616 UNGCPRO; | |
10617 | |
10618 return liszt1; | |
10619 } | |
10620 | |
10621 DEFUN ("intersection", Fintersection, 2, MANY, 0, /* | |
10622 Combine LIST1 and LIST2 using a set-intersection operation. | |
10623 | |
10624 The result list contains all items that appear in both LIST1 and LIST2. | |
10625 This is a non-destructive function; it makes a copy of the data if necessary | |
10626 to avoid corrupting the original LIST1 and LIST2. | |
10627 | |
10628 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10629 return the items in the order they appear in LIST1. | |
10630 | |
10631 See `union' for the meaning of :test, :test-not and :key." | |
10632 | |
10633 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | |
10634 */ | |
10635 (int nargs, Lisp_Object *args)) | |
10636 { | |
10637 return venn (Qintersection, nargs, args, 1); | |
10638 } | |
10639 | |
10640 DEFUN ("nintersection", Fnintersection, 2, MANY, 0, /* | |
10641 Combine LIST1 and LIST2 using a set-intersection operation. | |
10642 | |
10643 The result list contains all items that appear in both LIST1 and LIST2. | |
10644 This is a destructive function; it reuses the storage of LIST1 whenever | |
10645 possible. | |
10646 | |
10647 See `union' for the meaning of :test, :test-not and :key." | |
10648 | |
10649 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10650 */ | |
10651 (int nargs, Lisp_Object *args)) | |
10652 { | |
10653 return nvenn (Qnintersection, nargs, args, 1); | |
10654 } | |
10655 | |
10656 DEFUN ("subsetp", Fsubsetp, 2, MANY, 0, /* | |
10657 Return non-nil if every element of LIST1 also appears in LIST2. | |
10658 | |
10659 See `union' for the meaning of the keyword arguments. | |
10660 | |
10661 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10662 */ | |
10663 (int nargs, Lisp_Object *args)) | |
10664 { | |
10665 return venn (Qsubsetp, nargs, args, 0); | |
10666 } | |
10667 | |
10668 DEFUN ("set-difference", Fset_difference, 2, MANY, 0, /* | |
10669 Combine LIST1 and LIST2 using a set-difference operation. | |
10670 | |
10671 The result list contains all items that appear in LIST1 but not LIST2. This | |
10672 is a non-destructive function; it makes a copy of the data if necessary to | |
10673 avoid corrupting the original LIST1 and LIST2. | |
10674 | |
10675 See `union' for the meaning of :test, :test-not and :key. | |
10676 | |
10677 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10678 return the items in the order they appear in LIST1. | |
10679 | |
10680 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | |
10681 */ | |
10682 (int nargs, Lisp_Object *args)) | |
10683 { | |
10684 return venn (Qset_difference, nargs, args, 0); | |
10685 } | |
10686 | |
10687 DEFUN ("nset-difference", Fnset_difference, 2, MANY, 0, /* | |
10688 Combine LIST1 and LIST2 using a set-difference operation. | |
10689 | |
10690 The result list contains all items that appear in LIST1 but not LIST2. This | |
10691 is a destructive function; it reuses the storage of LIST1 whenever possible. | |
10692 | |
10693 See `union' for the meaning of :test, :test-not and :key." | |
10694 | |
10695 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10696 */ | |
10697 (int nargs, Lisp_Object *args)) | |
10698 { | |
10699 return nvenn (Qnset_difference, nargs, args, 0); | |
10700 } | |
10701 | |
10702 DEFUN ("nunion", Fnunion, 2, MANY, 0, /* | |
10703 Combine LIST1 and LIST2 using a set-union operation. | |
10704 The result list contains all items that appear in either LIST1 or LIST2. | |
10705 | |
10706 This is a destructive function, it reuses the storage of LIST1 whenever | |
10707 possible. | |
10708 | |
10709 See `union' for the meaning of :test, :test-not and :key. | |
10710 | |
10711 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10712 */ | |
10713 (int nargs, Lisp_Object *args)) | |
10714 { | |
10715 args[0] = nvenn (Qnunion, nargs, args, 0); | |
10716 return bytecode_nconc2 (args); | |
10717 } | |
10718 | |
10719 DEFUN ("union", Funion, 2, MANY, 0, /* | |
10720 Combine LIST1 and LIST2 using a set-union operation. | |
10721 The result list contains all items that appear in either LIST1 or LIST2. | |
10722 This is a non-destructive function; it makes a copy of the data if necessary | |
10723 to avoid corrupting the original LIST1 and LIST2. | |
10724 | |
10725 The keywords :test and :test-not specify two-argument test and negated-test | |
10726 predicates, respectively; :test defaults to `eql'. See `member*' for more | |
10727 information. | |
10728 | |
10729 :key specifies a one-argument function that transforms elements of LIST1 | |
10730 and LIST2 into \"comparison keys\" before the test predicate is applied. | |
10731 For example, if :key is #'car, then the car of elements from LIST1 is | |
10732 compared with the car of elements from LIST2. The :key function, however, | |
10733 does not affect the elements in the returned list, which are taken directly | |
10734 from the elements in LIST1 and LIST2. | |
10735 | |
10736 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10737 return the items of LIST1 in order, followed by the remaining items of LIST2 | |
10738 in the order they occur in LIST2. | |
10739 | |
10740 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT STABLE) | |
10741 */ | |
10742 (int nargs, Lisp_Object *args)) | |
10743 { | |
10744 Lisp_Object liszt1 = args[0], liszt2 = args[1], ignore = Qnil; | |
10745 Lisp_Object elt = Qnil, tail = Qnil, keyed = Qnil, result, result_tail; | |
10746 Elemcount len; | |
10747 Boolint test_not_unboundp = 1; | |
10748 check_test_func_t check_test = NULL, check_match = NULL; | |
10749 struct gcpro gcpro1, gcpro2, gcpro3; | |
10750 | |
10751 PARSE_KEYWORDS (Funion, nargs, args, 4, (test, key, test_not, stable), NULL); | |
10752 | |
10753 CHECK_LIST (liszt1); | |
10754 CHECK_LIST (liszt2); | |
10755 | |
10756 CHECK_KEY_ARGUMENT (key); | |
10757 | |
10758 if (NILP (liszt1)) | |
10759 { | |
10760 return liszt2; | |
10761 } | |
10762 | |
10763 if (NILP (liszt2)) | |
10764 { | |
10765 return liszt1; | |
10766 } | |
10767 | |
10768 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10769 &test_not_unboundp, &check_test); | |
10770 | |
10771 GCPRO3 (tail, keyed, result); | |
10772 | |
10773 if (NILP (stable)) | |
10774 { | |
10775 result = liszt2; | |
10776 { | |
10777 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | |
10778 { | |
10779 keyed = KEY (key, elt); | |
10780 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10781 check_test, test_not_unboundp, | |
10782 test, key, 0, Qzero, Qnil))) | |
10783 { | |
10784 /* The Lisp version of #'union used to check which list was | |
10785 longer, and use that as the tail of the constructed | |
10786 list. That fails when the order of arguments to TEST is | |
10787 specified, as is the case for these functions. We could | |
10788 pass the reverse_check argument to | |
10789 list_position_cons_before, but that means any key argument | |
10790 is called an awful lot more, so it's a space win but not | |
10791 a time win. */ | |
10792 result = Fcons (elt, result); | |
10793 } | |
10794 } | |
10795 } | |
10796 } | |
10797 else | |
10798 { | |
10799 result = result_tail = Qnil; | |
10800 | |
10801 /* The standard `union' doesn't produce a "stable" union -- it | |
10802 iterates over the second list instead of the first one, and returns | |
10803 the values in backwards order. According to the CLTL2 | |
10804 documentation, `union' is not required to preserve the ordering of | |
10805 elements in any fashion; providing the functionality for a stable | |
10806 union is an XEmacs extension. */ | |
10807 { | |
10808 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) | |
10809 { | |
10810 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | |
10811 check_match, test_not_unboundp, | |
10812 test, key, 1, Qzero, Qnil))) | |
10813 { | |
10814 if (NILP (result)) | |
10815 { | |
10816 result = result_tail = Fcons (elt, Qnil); | |
10817 } | |
10818 else | |
10819 { | |
10820 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10821 result_tail = XCDR (result_tail); | |
10822 } | |
10823 } | |
10824 } | |
10825 } | |
10826 | |
10827 result = NILP (result) ? liszt1 : nconc2 (Fcopy_list (liszt1), result); | |
10828 } | |
10829 | |
10830 UNGCPRO; | |
10831 | |
10832 return result; | |
10833 } | |
10834 | |
10835 DEFUN ("set-exclusive-or", Fset_exclusive_or, 2, MANY, 0, /* | |
10836 Combine LIST1 and LIST2 using a set-exclusive-or operation. | |
10837 | |
10838 The result list contains all items that appear in exactly one of LIST1, LIST2. | |
10839 This is a non-destructive function; it makes a copy of the data if necessary | |
10840 to avoid corrupting the original LIST1 and LIST2. | |
10841 | |
10842 See `union' for the meaning of :test, :test-not and :key. | |
10843 | |
10844 A non-nil value for the :stable keyword, not specified by Common Lisp, means | |
10845 return the items in the order they appear in LIST1, followed by the | |
10846 remaining items in the order they appear in LIST2. | |
10847 | |
10848 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10849 */ | |
10850 (int nargs, Lisp_Object *args)) | |
10851 { | |
10852 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | |
10853 Lisp_Object result = Qnil, result_tail = Qnil, keyed = Qnil, ignore = Qnil; | |
10854 Elemcount len; | |
10855 Boolint test_not_unboundp = 1; | |
10856 check_test_func_t check_match = NULL, check_test = NULL; | |
10857 struct gcpro gcpro1, gcpro2, gcpro3; | |
10858 | |
10859 PARSE_KEYWORDS (Fset_exclusive_or, nargs, args, 4, | |
10860 (test, key, test_not, stable), NULL); | |
10861 | |
10862 CHECK_LIST (liszt1); | |
10863 CHECK_LIST (liszt2); | |
10864 | |
10865 CHECK_KEY_ARGUMENT (key); | |
10866 | |
10867 if (NILP (liszt2)) | |
10868 { | |
10869 return liszt1; | |
10870 } | |
10871 | |
10872 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10873 &test_not_unboundp, &check_test); | |
10874 | |
10875 GCPRO3 (tail, keyed, result); | |
10876 { | |
10877 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt1, tail, len) | |
10878 { | |
10879 keyed = KEY (key, elt); | |
10880 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10881 check_test, test_not_unboundp, | |
10882 test, key, 0, Qzero, Qnil))) | |
10883 { | |
10884 if (NILP (stable)) | |
10885 { | |
10886 result = Fcons (elt, result); | |
10887 } | |
10888 else if (NILP (result)) | |
10889 { | |
10890 result = result_tail = Fcons (elt, Qnil); | |
10891 } | |
10892 else | |
10893 { | |
10894 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10895 result_tail = XCDR (result_tail); | |
10896 } | |
10897 } | |
10898 } | |
10899 } | |
10900 | |
10901 { | |
10902 EXTERNAL_LIST_LOOP_4_NO_DECLARE (elt, liszt2, tail, len) | |
10903 { | |
10904 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | |
10905 check_match, test_not_unboundp, | |
10906 test, key, 1, Qzero, Qnil))) | |
10907 { | |
10908 if (NILP (stable)) | |
10909 { | |
10910 result = Fcons (elt, result); | |
10911 } | |
10912 else if (NILP (result)) | |
10913 { | |
10914 result = result_tail = Fcons (elt, Qnil); | |
10915 } | |
10916 else | |
10917 { | |
10918 XSETCDR (result_tail, Fcons (elt, Qnil)); | |
10919 result_tail = XCDR (result_tail); | |
10920 } | |
10921 } | |
10922 } | |
10923 } | |
10924 UNGCPRO; | |
10925 | |
10926 return result; | |
10927 } | |
10928 | |
10929 DEFUN ("nset-exclusive-or", Fnset_exclusive_or, 2, MANY, 0, /* | |
10930 Combine LIST1 and LIST2 using a set-exclusive-or operation. | |
10931 | |
10932 The result list contains all items that appear in exactly one of LIST1 and | |
10933 LIST2. This is a destructive function; it reuses the storage of LIST1 and | |
10934 LIST2 whenever possible. | |
10935 | |
10936 See `union' for the meaning of :test, :test-not and :key. | |
10937 | |
10938 arguments: (LIST1 LIST2 &key (TEST #'eql) (KEY #'identity) TEST-NOT) | |
10939 */ | |
10940 (int nargs, Lisp_Object *args)) | |
10941 { | |
10942 Lisp_Object liszt1 = args[0], liszt2 = args[1], elt = Qnil, tail = Qnil; | |
10943 Lisp_Object result = Qnil, tortoise_elt = Qnil, keyed = Qnil, swap; | |
10944 Lisp_Object prev_tail = Qnil, ignore = Qnil; | |
10945 Elemcount count; | |
10946 Boolint test_not_unboundp = 1; | |
10947 check_test_func_t check_match = NULL, check_test = NULL; | |
10948 struct gcpro gcpro1, gcpro2, gcpro3; | |
10949 | |
10950 PARSE_KEYWORDS (Fnset_exclusive_or, nargs, args, 4, | |
10951 (test, key, test_not, stable), NULL); | |
10952 | |
10953 CHECK_LIST (liszt1); | |
10954 CHECK_LIST (liszt2); | |
10955 | |
10956 CHECK_KEY_ARGUMENT (key); | |
10957 | |
10958 if (NILP (liszt2)) | |
10959 { | |
10960 return liszt1; | |
10961 } | |
10962 | |
10963 check_match = get_check_match_function (&test, test_not, Qnil, Qnil, key, | |
10964 &test_not_unboundp, &check_test); | |
10965 | |
10966 GCPRO3 (tail, keyed, result); | |
10967 | |
10968 tortoise_elt = tail = liszt1, count = 0; | |
10969 | |
10970 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | |
10971 (signal_malformed_list_error (liszt1), 0)) | |
10972 { | |
10973 keyed = KEY (key, elt); | |
10974 if (NILP (list_position_cons_before (&ignore, keyed, liszt2, | |
10975 check_test, test_not_unboundp, | |
10976 test, key, 0, Qzero, Qnil))) | |
10977 { | |
10978 swap = XCDR (tail); | |
10979 | |
10980 if (NILP (prev_tail)) | |
10981 { | |
10982 liszt1 = XCDR (tail); | |
10983 } | |
10984 else | |
10985 { | |
10986 XSETCDR (prev_tail, swap); | |
10987 } | |
10988 | |
10989 XSETCDR (tail, result); | |
10990 result = tail; | |
10991 tail = swap; | |
10992 | |
10993 /* List is definitely not circular now! */ | |
10994 count = 0; | |
10995 } | |
10996 else | |
10997 { | |
10998 prev_tail = tail; | |
10999 tail = XCDR (tail); | |
11000 } | |
11001 | |
11002 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
11003 | |
11004 if (count & 1) | |
11005 { | |
11006 tortoise_elt = XCDR (tortoise_elt); | |
11007 } | |
11008 | |
11009 if (EQ (elt, tortoise_elt)) | |
11010 { | |
11011 signal_circular_list_error (liszt1); | |
11012 } | |
11013 } | |
11014 | |
11015 tortoise_elt = tail = liszt2, count = 0; | |
11016 | |
11017 while (CONSP (tail) ? (elt = XCAR (tail), 1) : NILP (tail) ? 0 : | |
11018 (signal_malformed_list_error (liszt2), 0)) | |
11019 { | |
11020 /* Need to leave the key calculation to list_position_cons_before(). */ | |
11021 if (NILP (list_position_cons_before (&ignore, elt, liszt1, | |
11022 check_match, test_not_unboundp, | |
11023 test, key, 1, Qzero, Qnil))) | |
11024 { | |
11025 swap = XCDR (tail); | |
11026 XSETCDR (tail, result); | |
11027 result = tail; | |
11028 tail = swap; | |
11029 count = 0; | |
11030 } | |
11031 else | |
11032 { | |
11033 tail = XCDR (tail); | |
11034 } | |
11035 | |
11036 if (count++ < CIRCULAR_LIST_SUSPICION_LENGTH) continue; | |
11037 | |
11038 if (count & 1) | |
11039 { | |
11040 tortoise_elt = XCDR (tortoise_elt); | |
11041 } | |
11042 | |
11043 if (EQ (elt, tortoise_elt)) | |
11044 { | |
11045 signal_circular_list_error (liszt1); | |
11046 } | |
11047 } | |
11048 | |
11049 UNGCPRO; | |
11050 | |
11051 return result; | |
11052 } | |
11053 | |
11054 | |
6191 Lisp_Object | 11055 Lisp_Object |
6192 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) | 11056 add_suffix_to_symbol (Lisp_Object symbol, const Ascbyte *ascii_string) |
6193 { | 11057 { |
6194 return Fintern (concat2 (Fsymbol_name (symbol), | 11058 return Fintern (concat2 (Fsymbol_name (symbol), |
6195 build_ascstring (ascii_string)), | 11059 build_ascstring (ascii_string)), |
6201 { | 11065 { |
6202 return Fintern (concat2 (build_ascstring (ascii_string), | 11066 return Fintern (concat2 (build_ascstring (ascii_string), |
6203 Fsymbol_name (symbol)), | 11067 Fsymbol_name (symbol)), |
6204 Qnil); | 11068 Qnil); |
6205 } | 11069 } |
6206 | |
6207 | 11070 |
6208 /* #### this function doesn't belong in this file! */ | 11071 /* #### this function doesn't belong in this file! */ |
6209 | 11072 |
6210 #ifdef HAVE_GETLOADAVG | 11073 #ifdef HAVE_GETLOADAVG |
6211 #ifdef HAVE_SYS_LOADAVG_H | 11074 #ifdef HAVE_SYS_LOADAVG_H |
6819 syms_of_fns (void) | 11682 syms_of_fns (void) |
6820 { | 11683 { |
6821 INIT_LISP_OBJECT (bit_vector); | 11684 INIT_LISP_OBJECT (bit_vector); |
6822 | 11685 |
6823 DEFSYMBOL (Qstring_lessp); | 11686 DEFSYMBOL (Qstring_lessp); |
6824 DEFSYMBOL (Qsort); | |
6825 DEFSYMBOL (Qmerge); | 11687 DEFSYMBOL (Qmerge); |
6826 DEFSYMBOL (Qfill); | 11688 DEFSYMBOL (Qfill); |
6827 DEFSYMBOL (Qidentity); | 11689 DEFSYMBOL (Qidentity); |
6828 DEFSYMBOL (Qvector); | 11690 DEFSYMBOL (Qvector); |
6829 DEFSYMBOL (Qarray); | 11691 DEFSYMBOL (Qarray); |
6831 DEFSYMBOL (Qlist); | 11693 DEFSYMBOL (Qlist); |
6832 DEFSYMBOL (Qbit_vector); | 11694 DEFSYMBOL (Qbit_vector); |
6833 defsymbol (&QsortX, "sort*"); | 11695 defsymbol (&QsortX, "sort*"); |
6834 DEFSYMBOL (Qreduce); | 11696 DEFSYMBOL (Qreduce); |
6835 DEFSYMBOL (Qreplace); | 11697 DEFSYMBOL (Qreplace); |
11698 DEFSYMBOL (Qposition); | |
11699 DEFSYMBOL (Qfind); | |
11700 defsymbol (&QdeleteX, "delete*"); | |
11701 defsymbol (&QremoveX, "remove*"); | |
6836 | 11702 |
6837 DEFSYMBOL (Qmapconcat); | 11703 DEFSYMBOL (Qmapconcat); |
6838 defsymbol (&QmapcarX, "mapcar*"); | 11704 defsymbol (&QmapcarX, "mapcar*"); |
6839 DEFSYMBOL (Qmapvector); | 11705 DEFSYMBOL (Qmapvector); |
6840 DEFSYMBOL (Qmapcan); | 11706 DEFSYMBOL (Qmapcan); |
6844 DEFSYMBOL (Qsome); | 11710 DEFSYMBOL (Qsome); |
6845 DEFSYMBOL (Qevery); | 11711 DEFSYMBOL (Qevery); |
6846 DEFSYMBOL (Qmaplist); | 11712 DEFSYMBOL (Qmaplist); |
6847 DEFSYMBOL (Qmapl); | 11713 DEFSYMBOL (Qmapl); |
6848 DEFSYMBOL (Qmapcon); | 11714 DEFSYMBOL (Qmapcon); |
11715 DEFSYMBOL (Qnsubstitute); | |
11716 DEFSYMBOL (Qdelete_duplicates); | |
11717 DEFSYMBOL (Qsubstitute); | |
11718 DEFSYMBOL (Qmismatch); | |
11719 DEFSYMBOL (Qintersection); | |
11720 DEFSYMBOL (Qnintersection); | |
11721 DEFSYMBOL (Qsubsetp); | |
11722 DEFSYMBOL (Qset_difference); | |
11723 DEFSYMBOL (Qnset_difference); | |
11724 DEFSYMBOL (Qnunion); | |
11725 DEFSYMBOL (Qnintersection); | |
11726 DEFSYMBOL (Qset_difference); | |
11727 DEFSYMBOL (Qnset_difference); | |
6849 | 11728 |
6850 DEFKEYWORD (Q_from_end); | 11729 DEFKEYWORD (Q_from_end); |
6851 DEFKEYWORD (Q_initial_value); | 11730 DEFKEYWORD (Q_initial_value); |
6852 DEFKEYWORD (Q_start1); | 11731 DEFKEYWORD (Q_start1); |
6853 DEFKEYWORD (Q_start2); | 11732 DEFKEYWORD (Q_start2); |
6854 DEFKEYWORD (Q_end1); | 11733 DEFKEYWORD (Q_end1); |
6855 DEFKEYWORD (Q_end2); | 11734 DEFKEYWORD (Q_end2); |
11735 defkeyword (&Q_if_, ":if"); | |
11736 DEFKEYWORD (Q_if_not); | |
11737 DEFKEYWORD (Q_test_not); | |
11738 DEFKEYWORD (Q_count); | |
11739 DEFKEYWORD (Q_stable); | |
6856 | 11740 |
6857 DEFSYMBOL (Qyes_or_no_p); | 11741 DEFSYMBOL (Qyes_or_no_p); |
6858 | 11742 |
6859 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); | 11743 DEFERROR_STANDARD (Qbase64_conversion_error, Qconversion_error); |
6860 | 11744 |
6861 DEFSUBR (Fidentity); | 11745 DEFSUBR (Fidentity); |
6862 DEFSUBR (Frandom); | 11746 DEFSUBR (Frandom); |
6863 DEFSUBR (Flength); | 11747 DEFSUBR (Flength); |
6864 DEFSUBR (Fsafe_length); | 11748 DEFSUBR (Fsafe_length); |
6865 DEFSUBR (Flist_length); | 11749 DEFSUBR (Flist_length); |
11750 DEFSUBR (Fcount); | |
6866 DEFSUBR (Fstring_equal); | 11751 DEFSUBR (Fstring_equal); |
6867 DEFSUBR (Fcompare_strings); | 11752 DEFSUBR (Fcompare_strings); |
6868 DEFSUBR (Fstring_lessp); | 11753 DEFSUBR (Fstring_lessp); |
6869 DEFSUBR (Fstring_modified_tick); | 11754 DEFSUBR (Fstring_modified_tick); |
6870 DEFSUBR (Fappend); | 11755 DEFSUBR (Fappend); |
6884 DEFSUBR (Fnbutlast); | 11769 DEFSUBR (Fnbutlast); |
6885 DEFSUBR (Fmember); | 11770 DEFSUBR (Fmember); |
6886 DEFSUBR (Fold_member); | 11771 DEFSUBR (Fold_member); |
6887 DEFSUBR (Fmemq); | 11772 DEFSUBR (Fmemq); |
6888 DEFSUBR (Fold_memq); | 11773 DEFSUBR (Fold_memq); |
11774 DEFSUBR (FmemberX); | |
11775 DEFSUBR (Fadjoin); | |
6889 DEFSUBR (Fassoc); | 11776 DEFSUBR (Fassoc); |
6890 DEFSUBR (Fold_assoc); | 11777 DEFSUBR (Fold_assoc); |
6891 DEFSUBR (Fassq); | 11778 DEFSUBR (Fassq); |
6892 DEFSUBR (Fold_assq); | 11779 DEFSUBR (Fold_assq); |
6893 DEFSUBR (Frassoc); | 11780 DEFSUBR (Frassoc); |
6894 DEFSUBR (Fold_rassoc); | 11781 DEFSUBR (Fold_rassoc); |
6895 DEFSUBR (Frassq); | 11782 DEFSUBR (Frassq); |
6896 DEFSUBR (Fold_rassq); | 11783 DEFSUBR (Fold_rassq); |
11784 | |
11785 DEFSUBR (Fposition); | |
11786 DEFSUBR (Ffind); | |
11787 | |
6897 DEFSUBR (Fdelete); | 11788 DEFSUBR (Fdelete); |
6898 DEFSUBR (Fold_delete); | 11789 DEFSUBR (Fold_delete); |
6899 DEFSUBR (Fdelq); | 11790 DEFSUBR (Fdelq); |
6900 DEFSUBR (Fold_delq); | 11791 DEFSUBR (Fold_delq); |
11792 DEFSUBR (FdeleteX); | |
11793 DEFSUBR (FremoveX); | |
6901 DEFSUBR (Fremassoc); | 11794 DEFSUBR (Fremassoc); |
6902 DEFSUBR (Fremassq); | 11795 DEFSUBR (Fremassq); |
6903 DEFSUBR (Fremrassoc); | 11796 DEFSUBR (Fremrassoc); |
6904 DEFSUBR (Fremrassq); | 11797 DEFSUBR (Fremrassq); |
11798 DEFSUBR (Fdelete_duplicates); | |
11799 DEFSUBR (Fremove_duplicates); | |
6905 DEFSUBR (Fnreverse); | 11800 DEFSUBR (Fnreverse); |
6906 DEFSUBR (Freverse); | 11801 DEFSUBR (Freverse); |
6907 DEFSUBR (FsortX); | 11802 DEFSUBR (FsortX); |
6908 Ffset (intern ("sort"), QsortX); | |
6909 DEFSUBR (Fmerge); | 11803 DEFSUBR (Fmerge); |
6910 DEFSUBR (Fplists_eq); | 11804 DEFSUBR (Fplists_eq); |
6911 DEFSUBR (Fplists_equal); | 11805 DEFSUBR (Fplists_equal); |
6912 DEFSUBR (Flax_plists_eq); | 11806 DEFSUBR (Flax_plists_eq); |
6913 DEFSUBR (Flax_plists_equal); | 11807 DEFSUBR (Flax_plists_equal); |
6931 DEFSUBR (Fobject_setplist); | 11825 DEFSUBR (Fobject_setplist); |
6932 DEFSUBR (Fequal); | 11826 DEFSUBR (Fequal); |
6933 DEFSUBR (Fequalp); | 11827 DEFSUBR (Fequalp); |
6934 DEFSUBR (Fold_equal); | 11828 DEFSUBR (Fold_equal); |
6935 DEFSUBR (Ffill); | 11829 DEFSUBR (Ffill); |
6936 Ffset (intern ("fillarray"), Qfill); | 11830 |
11831 DEFSUBR (FassocX); | |
11832 DEFSUBR (FrassocX); | |
6937 | 11833 |
6938 DEFSUBR (Fnconc); | 11834 DEFSUBR (Fnconc); |
6939 DEFSUBR (FmapcarX); | 11835 DEFSUBR (FmapcarX); |
6940 DEFSUBR (Fmapvector); | 11836 DEFSUBR (Fmapvector); |
6941 DEFSUBR (Fmapcan); | 11837 DEFSUBR (Fmapcan); |
6943 DEFSUBR (Fmapconcat); | 11839 DEFSUBR (Fmapconcat); |
6944 DEFSUBR (Fmap); | 11840 DEFSUBR (Fmap); |
6945 DEFSUBR (Fmap_into); | 11841 DEFSUBR (Fmap_into); |
6946 DEFSUBR (Fsome); | 11842 DEFSUBR (Fsome); |
6947 DEFSUBR (Fevery); | 11843 DEFSUBR (Fevery); |
6948 Ffset (intern ("mapc-internal"), Fsymbol_function (intern ("mapc"))); | 11844 Ffset (intern ("mapc-internal"), Qmapc); |
6949 Ffset (intern ("mapcar"), Fsymbol_function (intern ("mapcar*"))); | 11845 Ffset (intern ("mapcar"), QmapcarX); |
6950 DEFSUBR (Fmaplist); | 11846 DEFSUBR (Fmaplist); |
6951 DEFSUBR (Fmapl); | 11847 DEFSUBR (Fmapl); |
6952 DEFSUBR (Fmapcon); | 11848 DEFSUBR (Fmapcon); |
6953 | 11849 |
6954 DEFSUBR (Freduce); | 11850 DEFSUBR (Freduce); |
6955 DEFSUBR (Freplace_list); | 11851 DEFSUBR (Freplace_list); |
6956 DEFSUBR (Freplace); | 11852 DEFSUBR (Freplace); |
11853 DEFSUBR (Fsubsetp); | |
11854 DEFSUBR (Fnsubstitute); | |
11855 DEFSUBR (Fsubstitute); | |
11856 DEFSUBR (Fsublis); | |
11857 DEFSUBR (Fnsublis); | |
11858 DEFSUBR (Fsubst); | |
11859 DEFSUBR (Fnsubst); | |
11860 DEFSUBR (Ftree_equal); | |
11861 DEFSUBR (Fmismatch); | |
11862 DEFSUBR (Fsearch); | |
11863 DEFSUBR (Funion); | |
11864 DEFSUBR (Fnunion); | |
11865 DEFSUBR (Fintersection); | |
11866 DEFSUBR (Fnintersection); | |
11867 DEFSUBR (Fset_difference); | |
11868 DEFSUBR (Fnset_difference); | |
11869 DEFSUBR (Fset_exclusive_or); | |
11870 DEFSUBR (Fnset_exclusive_or); | |
11871 | |
6957 DEFSUBR (Fload_average); | 11872 DEFSUBR (Fload_average); |
6958 DEFSUBR (Ffeaturep); | 11873 DEFSUBR (Ffeaturep); |
6959 DEFSUBR (Frequire); | 11874 DEFSUBR (Frequire); |
6960 DEFSUBR (Fprovide); | 11875 DEFSUBR (Fprovide); |
6961 DEFSUBR (Fbase64_encode_region); | 11876 DEFSUBR (Fbase64_encode_region); |