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