Mercurial > hg > xemacs-beta
comparison src/fns.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Random utility Lisp functions. | |
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc. | |
3 Copyright (C) 1995, 1996 Ben Wing. | |
4 | |
5 This file is part of XEmacs. | |
6 | |
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 | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
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 | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
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 | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Mule 2.0, FSF 19.30. */ | |
23 | |
24 /* This file has been Mule-ized. */ | |
25 | |
26 /* Note: FSF 19.30 has bool vectors. We have bit vectors. */ | |
27 | |
28 /* Hacked on for Mule by Ben Wing, December 1994, January 1995. */ | |
29 | |
30 #include <config.h> | |
31 | |
32 /* Note on some machines this defines `vector' as a typedef, | |
33 so make sure we don't use that name in this file. */ | |
34 #undef vector | |
35 #define vector ***** | |
36 | |
37 #include "lisp.h" | |
38 | |
39 #include "buffer.h" | |
40 #include "bytecode.h" | |
41 #include "commands.h" | |
42 #include "device.h" | |
43 #include "events.h" | |
44 #include "extents.h" | |
45 #include "frame.h" | |
46 #include "systime.h" | |
47 | |
48 Lisp_Object Qstring_lessp; | |
49 Lisp_Object Qidentity; | |
50 | |
51 static Lisp_Object mark_bit_vector (Lisp_Object, void (*) (Lisp_Object)); | |
52 static void print_bit_vector (Lisp_Object, Lisp_Object, int); | |
53 static int bit_vector_equal (Lisp_Object o1, Lisp_Object o2, int depth); | |
54 static unsigned long bit_vector_hash (Lisp_Object obj, int depth); | |
55 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bit-vector", bit_vector, | |
56 mark_bit_vector, print_bit_vector, 0, | |
57 bit_vector_equal, bit_vector_hash, | |
58 struct Lisp_Bit_Vector); | |
59 | |
60 static Lisp_Object | |
61 mark_bit_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) | |
62 { | |
63 return (Qnil); | |
64 } | |
65 | |
66 static void | |
67 print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | |
68 { | |
69 int i; | |
70 struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); | |
71 int len = bit_vector_length (v); | |
72 int last = len; | |
73 | |
74 if (INTP (Vprint_length)) | |
75 last = min (len, XINT (Vprint_length)); | |
76 write_c_string ("#*", printcharfun); | |
77 for (i = 0; i < last; i++) | |
78 { | |
79 if (bit_vector_bit (v, i)) | |
80 write_c_string ("1", printcharfun); | |
81 else | |
82 write_c_string ("0", printcharfun); | |
83 } | |
84 | |
85 if (last != len) | |
86 write_c_string ("...", printcharfun); | |
87 } | |
88 | |
89 static int | |
90 bit_vector_equal (Lisp_Object o1, Lisp_Object o2, int depth) | |
91 { | |
92 struct Lisp_Bit_Vector *v1 = XBIT_VECTOR (o1); | |
93 struct Lisp_Bit_Vector *v2 = XBIT_VECTOR (o2); | |
94 | |
95 if (bit_vector_length (v1) != bit_vector_length (v2)) | |
96 return 0; | |
97 | |
98 return !memcmp (v1->bits, v2->bits, | |
99 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v1)) * | |
100 sizeof (long)); | |
101 } | |
102 | |
103 static unsigned long | |
104 bit_vector_hash (Lisp_Object obj, int depth) | |
105 { | |
106 struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); | |
107 return HASH2 (bit_vector_length (v), | |
108 memory_hash (v->bits, | |
109 BIT_VECTOR_LONG_STORAGE (bit_vector_length (v)) * | |
110 sizeof (long))); | |
111 } | |
112 | |
113 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0 /* | |
114 Return the argument unchanged. | |
115 */ ) | |
116 (arg) | |
117 Lisp_Object arg; | |
118 { | |
119 return arg; | |
120 } | |
121 | |
122 extern long get_random (void); | |
123 extern void seed_random (long arg); | |
124 | |
125 DEFUN ("random", Frandom, Srandom, 0, 1, 0 /* | |
126 Return a pseudo-random number. | |
127 All integers representable in Lisp are equally likely.\n\ | |
128 On most systems, this is 28 bits' worth.\n\ | |
129 With positive integer argument N, return random number in interval [0,N).\n\ | |
130 With argument t, set the random number seed from the current time and pid. | |
131 */ ) | |
132 (limit) | |
133 Lisp_Object limit; | |
134 { | |
135 EMACS_INT val; | |
136 Lisp_Object lispy_val; | |
137 unsigned long denominator; | |
138 | |
139 if (EQ (limit, Qt)) | |
140 seed_random (getpid () + time (NULL)); | |
141 if (NATNUMP (limit) && !ZEROP (limit)) | |
142 { | |
143 /* Try to take our random number from the higher bits of VAL, | |
144 not the lower, since (says Gentzel) the low bits of `random' | |
145 are less random than the higher ones. We do this by using the | |
146 quotient rather than the remainder. At the high end of the RNG | |
147 it's possible to get a quotient larger than limit; discarding | |
148 these values eliminates the bias that would otherwise appear | |
149 when using a large limit. */ | |
150 denominator = ((unsigned long)1 << VALBITS) / XINT (limit); | |
151 do | |
152 val = get_random () / denominator; | |
153 while (val >= XINT (limit)); | |
154 } | |
155 else | |
156 val = get_random (); | |
157 XSETINT (lispy_val, val); | |
158 return lispy_val; | |
159 } | |
160 | |
161 /* Random data-structure functions */ | |
162 | |
163 #ifdef LOSING_BYTECODE | |
164 | |
165 /* #### Delete this shit */ | |
166 | |
167 /* Charcount is a misnomer here as we might be dealing with the | |
168 length of a vector or list, but emphasizes that we're not dealing | |
169 with Bytecounts in strings */ | |
170 static Charcount | |
171 length_with_bytecode_hack (Lisp_Object seq) | |
172 { | |
173 if (!COMPILED_FUNCTIONP (seq)) | |
174 return (XINT (Flength (seq))); | |
175 else | |
176 { | |
177 struct Lisp_Compiled_Function *b = XCOMPILED_FUNCTION (seq); | |
178 int intp = b->flags.interactivep; | |
179 int domainp = b->flags.domainp; | |
180 | |
181 if (intp) | |
182 return (COMPILED_INTERACTIVE + 1); | |
183 else if (domainp) | |
184 return (COMPILED_DOMAIN + 1); | |
185 else | |
186 return (COMPILED_DOC_STRING + 1); | |
187 } | |
188 } | |
189 | |
190 #endif /* LOSING_BYTECODE */ | |
191 | |
192 void | |
193 check_losing_bytecode (CONST char *function, Lisp_Object seq) | |
194 { | |
195 if (COMPILED_FUNCTIONP (seq)) | |
196 error_with_frob | |
197 (seq, | |
198 "As of 19.14, `%s' no longer works with compiled-function objects", | |
199 function); | |
200 } | |
201 | |
202 DEFUN ("length", Flength, Slength, 1, 1, 0 /* | |
203 Return the length of vector, bit vector, list or string SEQUENCE. | |
204 */ ) | |
205 (obj) | |
206 Lisp_Object obj; | |
207 { | |
208 Lisp_Object tail; | |
209 int i; | |
210 | |
211 retry: | |
212 if (STRINGP (obj)) | |
213 return (make_int (string_char_length (XSTRING (obj)))); | |
214 else if (VECTORP (obj)) | |
215 return (make_int (vector_length (XVECTOR (obj)))); | |
216 else if (BIT_VECTORP (obj)) | |
217 return (make_int (bit_vector_length (XBIT_VECTOR (obj)))); | |
218 else if (CONSP (obj)) | |
219 { | |
220 for (i = 0, tail = obj; !NILP (tail); i++) | |
221 { | |
222 QUIT; | |
223 tail = Fcdr (tail); | |
224 } | |
225 | |
226 return (make_int (i)); | |
227 } | |
228 else if (NILP (obj)) | |
229 { | |
230 return (Qzero); | |
231 } | |
232 else | |
233 { | |
234 check_losing_bytecode ("length", obj); | |
235 obj = wrong_type_argument (Qsequencep, obj); | |
236 goto retry; | |
237 } | |
238 } | |
239 | |
240 /* This does not check for quits. That is safe | |
241 since it must terminate. */ | |
242 | |
243 DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0 /* | |
244 Return the length of a list, but avoid error or infinite loop. | |
245 This function never gets an error. If LIST is not really a list, | |
246 it returns 0. If LIST is circular, it returns a finite value | |
247 which is at least the number of distinct elements. | |
248 */ ) | |
249 (list) | |
250 Lisp_Object list; | |
251 { | |
252 Lisp_Object tail, halftail, length; | |
253 int len = 0; | |
254 | |
255 /* halftail is used to detect circular lists. */ | |
256 halftail = list; | |
257 for (tail = list; CONSP (tail); tail = XCDR (tail)) | |
258 { | |
259 if (EQ (tail, halftail) && len != 0) | |
260 break; | |
261 len++; | |
262 if ((len & 1) == 0) | |
263 halftail = XCDR (halftail); | |
264 } | |
265 | |
266 XSETINT (length, len); | |
267 return length; | |
268 } | |
269 | |
270 /*** string functions. ***/ | |
271 | |
272 DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0 /* | |
273 T if two strings have identical contents. | |
274 Case is significant. Text properties are ignored. | |
275 (Under XEmacs, `equal' also ignores text properties and extents in | |
276 strings, but this is not the case under FSF Emacs.) | |
277 Symbols are also allowed; their print names are used instead. | |
278 */ ) | |
279 (s1, s2) | |
280 Lisp_Object s1, s2; | |
281 { | |
282 int len; | |
283 | |
284 if (SYMBOLP (s1)) | |
285 XSETSTRING (s1, XSYMBOL (s1)->name); | |
286 if (SYMBOLP (s2)) | |
287 XSETSTRING (s2, XSYMBOL (s2)->name); | |
288 CHECK_STRING (s1); | |
289 CHECK_STRING (s2); | |
290 | |
291 len = string_length (XSTRING (s1)); | |
292 if (len != string_length (XSTRING (s2)) || | |
293 memcmp (string_data (XSTRING (s1)), string_data (XSTRING (s2)), len)) | |
294 return Qnil; | |
295 return Qt; | |
296 } | |
297 | |
298 | |
299 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0 /* | |
300 T if first arg string is less than second in lexicographic order. | |
301 If I18N2 support was compiled in, ordering is determined by the locale. | |
302 Case is significant for the default C locale. | |
303 Symbols are also allowed; their print names are used instead. | |
304 */ ) | |
305 (s1, s2) | |
306 Lisp_Object s1, s2; | |
307 { | |
308 struct Lisp_String *p1, *p2; | |
309 Charcount end, len2; | |
310 | |
311 if (SYMBOLP (s1)) | |
312 XSETSTRING (s1, XSYMBOL (s1)->name); | |
313 if (SYMBOLP (s2)) | |
314 XSETSTRING (s2, XSYMBOL (s2)->name); | |
315 CHECK_STRING (s1); | |
316 CHECK_STRING (s2); | |
317 | |
318 p1 = XSTRING (s1); | |
319 p2 = XSTRING (s2); | |
320 end = string_char_length (XSTRING (s1)); | |
321 len2 = string_char_length (XSTRING (s2)); | |
322 if (end > len2) | |
323 end = len2; | |
324 | |
325 { | |
326 int i; | |
327 | |
328 #ifdef I18N2 | |
329 Bytecount bcend = charcount_to_bytecount (string_data (p1), end); | |
330 /* Compare strings using collation order of locale. */ | |
331 /* Need to be tricky to handle embedded nulls. */ | |
332 | |
333 for (i = 0; i < bcend; i += strlen((char *) string_data (p1) + i) + 1) | |
334 { | |
335 int val = strcoll ((char *) string_data (p1) + i, | |
336 (char *) string_data (p2) + i); | |
337 if (val < 0) | |
338 return Qt; | |
339 if (val > 0) | |
340 return Qnil; | |
341 } | |
342 #else /* not I18N2 */ | |
343 for (i = 0; i < end; i++) | |
344 { | |
345 if (string_char (p1, i) != string_char (p2, i)) | |
346 return string_char (p1, i) < string_char (p2, i) ? Qt : Qnil; | |
347 } | |
348 #endif /* not I18N2 */ | |
349 /* Can't do i < len2 because then comparison between "foo" and "foo^@" | |
350 won't work right in I18N2 case */ | |
351 return ((end < len2) ? Qt : Qnil); | |
352 } | |
353 } | |
354 | |
355 DEFUN ("string-modified-tick", Fstring_modified_tick, Sstring_modified_tick, | |
356 1, 1, 0 /* | |
357 Return STRING's tick counter, incremented for each change to the string. | |
358 Each string has a tick counter which is incremented each time the contents | |
359 of the string are changed (e.g. with `aset'). It wraps around occasionally. | |
360 */ ) | |
361 (string) | |
362 Lisp_Object string; | |
363 { | |
364 struct Lisp_String *s; | |
365 | |
366 CHECK_STRING (string); | |
367 s = XSTRING (string); | |
368 if (CONSP (s->plist) && INTP (XCAR (s->plist))) | |
369 return XCAR (s->plist); | |
370 else | |
371 return Qzero; | |
372 } | |
373 | |
374 void | |
375 bump_string_modiff (Lisp_Object str) | |
376 { | |
377 struct Lisp_String *s = XSTRING (str); | |
378 Lisp_Object *ptr = &s->plist; | |
379 | |
380 #ifdef I18N3 | |
381 /* #### remove the `string-translatable' property from the string, | |
382 if there is one. */ | |
383 #endif | |
384 /* skip over extent info if it's there */ | |
385 if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr))) | |
386 ptr = &XCDR (*ptr); | |
387 if (CONSP (*ptr) && INTP (XCAR (*ptr))) | |
388 XSETINT (XCAR (*ptr), 1+XINT (XCAR (*ptr))); | |
389 else | |
390 *ptr = Fcons (make_int (1), *ptr); | |
391 } | |
392 | |
393 | |
394 enum concat_target_type { c_cons, c_string, c_vector, c_bit_vector }; | |
395 static Lisp_Object concat (int nargs, Lisp_Object *args, | |
396 enum concat_target_type target_type, | |
397 int last_special); | |
398 | |
399 Lisp_Object | |
400 concat2 (Lisp_Object s1, Lisp_Object s2) | |
401 { | |
402 Lisp_Object args[2]; | |
403 args[0] = s1; | |
404 args[1] = s2; | |
405 return concat (2, args, c_string, 0); | |
406 } | |
407 | |
408 Lisp_Object | |
409 concat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3) | |
410 { | |
411 Lisp_Object args[3]; | |
412 args[0] = s1; | |
413 args[1] = s2; | |
414 args[2] = s3; | |
415 return concat (3, args, c_string, 0); | |
416 } | |
417 | |
418 Lisp_Object | |
419 vconcat2 (Lisp_Object s1, Lisp_Object s2) | |
420 { | |
421 Lisp_Object args[2]; | |
422 args[0] = s1; | |
423 args[1] = s2; | |
424 return concat (2, args, c_vector, 0); | |
425 } | |
426 | |
427 Lisp_Object | |
428 vconcat3 (Lisp_Object s1, Lisp_Object s2, Lisp_Object s3) | |
429 { | |
430 Lisp_Object args[3]; | |
431 args[0] = s1; | |
432 args[1] = s2; | |
433 args[2] = s3; | |
434 return concat (3, args, c_vector, 0); | |
435 } | |
436 | |
437 DEFUN ("append", Fappend, Sappend, 0, MANY, 0 /* | |
438 Concatenate all the arguments and make the result a list. | |
439 The result is a list whose elements are the elements of all the arguments. | |
440 Each argument may be a list, vector, bit vector, or string. | |
441 The last argument is not copied, just used as the tail of the new list. | |
442 */ ) | |
443 (nargs, args) | |
444 int nargs; | |
445 Lisp_Object *args; | |
446 { | |
447 return concat (nargs, args, c_cons, 1); | |
448 } | |
449 | |
450 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0 /* | |
451 Concatenate all the arguments and make the result a string. | |
452 The result is a string whose elements are the elements of all the arguments. | |
453 Each argument may be a string or a list or vector of characters (integers). | |
454 | |
455 Do not use individual integers as arguments! | |
456 The behavior of `concat' in that case will be changed later! | |
457 If your program passes an integer as an argument to `concat', | |
458 you should change it right away not to do so. | |
459 */ ) | |
460 (nargs, args) | |
461 int nargs; | |
462 Lisp_Object *args; | |
463 { | |
464 return concat (nargs, args, c_string, 0); | |
465 } | |
466 | |
467 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0 /* | |
468 Concatenate all the arguments and make the result a vector. | |
469 The result is a vector whose elements are the elements of all the arguments. | |
470 Each argument may be a list, vector, bit vector, or string. | |
471 */ ) | |
472 (nargs, args) | |
473 int nargs; | |
474 Lisp_Object *args; | |
475 { | |
476 return concat (nargs, args, c_vector, 0); | |
477 } | |
478 | |
479 DEFUN ("bvconcat", Fbvconcat, Sbvconcat, 0, MANY, 0 /* | |
480 Concatenate all the arguments and make the result a bit vector. | |
481 The result is a bit vector whose elements are the elements of all the | |
482 arguments. Each argument may be a list, vector, bit vector, or string. | |
483 */ ) | |
484 (nargs, args) | |
485 int nargs; | |
486 Lisp_Object *args; | |
487 { | |
488 return concat (nargs, args, c_bit_vector, 0); | |
489 } | |
490 | |
491 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0 /* | |
492 Return a copy of a list, vector, bit vector or string. | |
493 The elements of a list or vector are not copied; they are shared | |
494 with the original. | |
495 */ ) | |
496 (arg) | |
497 Lisp_Object arg; | |
498 { | |
499 again: | |
500 if (NILP (arg)) return arg; | |
501 /* We handle conses separately because concat() is big and hairy and | |
502 doesn't handle (copy-sequence '(a b . c)) and it's easier to redo this | |
503 than to fix concat() without worrying about breaking other things. | |
504 */ | |
505 if (CONSP (arg)) | |
506 { | |
507 Lisp_Object rest = arg; | |
508 Lisp_Object head, tail; | |
509 tail = Qnil; | |
510 while (CONSP (rest)) | |
511 { | |
512 Lisp_Object new = Fcons (XCAR (rest), XCDR (rest)); | |
513 if (NILP (tail)) | |
514 head = tail = new; | |
515 else | |
516 XCDR (tail) = new, tail = new; | |
517 rest = XCDR (rest); | |
518 QUIT; | |
519 } | |
520 if (!NILP (tail)) | |
521 XCDR (tail) = rest; | |
522 return head; | |
523 } | |
524 else if (STRINGP (arg)) | |
525 return concat (1, &arg, c_string, 0); | |
526 else if (VECTORP (arg)) | |
527 return concat (1, &arg, c_vector, 0); | |
528 else if (BIT_VECTORP (arg)) | |
529 return concat (1, &arg, c_bit_vector, 0); | |
530 else | |
531 { | |
532 check_losing_bytecode ("copy-sequence", arg); | |
533 arg = wrong_type_argument (Qsequencep, arg); | |
534 goto again; | |
535 } | |
536 } | |
537 | |
538 struct merge_string_extents_struct | |
539 { | |
540 Lisp_Object string; | |
541 Bytecount entry_offset; | |
542 Bytecount entry_length; | |
543 }; | |
544 | |
545 static Lisp_Object | |
546 concat (int nargs, Lisp_Object *args, | |
547 enum concat_target_type target_type, | |
548 int last_special) | |
549 { | |
550 Lisp_Object val; | |
551 Lisp_Object tail = Qnil; | |
552 int toindex; | |
553 int argnum; | |
554 Lisp_Object last_tail; | |
555 Lisp_Object prev; | |
556 struct merge_string_extents_struct *args_mse = 0; | |
557 Bufbyte *string_result = 0; | |
558 Bufbyte *string_result_ptr = 0; | |
559 struct gcpro gcpro1; | |
560 | |
561 /* The modus operandi in Emacs is "caller gc-protects args". | |
562 However, concat is called many times in Emacs on freshly | |
563 created stuff. So we help those callers out by protecting | |
564 the args ourselves to save them a lot of temporary-variable | |
565 grief. */ | |
566 | |
567 GCPRO1 (args[0]); | |
568 gcpro1.nvars = nargs; | |
569 | |
570 #ifdef I18N3 | |
571 /* #### if the result is a string and any of the strings have a string | |
572 for the `string-translatable' property, then concat should also | |
573 concat the args but use the `string-translatable' strings, and store | |
574 the result in the returned string's `string-translatable' property. */ | |
575 #endif | |
576 if (target_type == c_string) | |
577 { | |
578 args_mse = ((struct merge_string_extents_struct *) | |
579 alloca (nargs * | |
580 sizeof (struct merge_string_extents_struct))); | |
581 } | |
582 | |
583 /* In append, the last arg isn't treated like the others */ | |
584 if (last_special && nargs > 0) | |
585 { | |
586 nargs--; | |
587 last_tail = args[nargs]; | |
588 } | |
589 else | |
590 last_tail = Qnil; | |
591 | |
592 /* Check and coerce the arguments. */ | |
593 for (argnum = 0; argnum < nargs; argnum++) | |
594 { | |
595 Lisp_Object seq = args[argnum]; | |
596 if (CONSP (seq) || NILP (seq)) | |
597 ; | |
598 else if (VECTORP (seq) || STRINGP (seq) || BIT_VECTORP (seq)) | |
599 ; | |
600 #ifdef LOSING_BYTECODE | |
601 else if (COMPILED_FUNCTIONP (seq)) | |
602 /* Urk! We allow this, for "compatibility"... */ | |
603 ; | |
604 #endif | |
605 else if (INTP (seq)) | |
606 /* This is too revolting to think about but maintains | |
607 compatibility with FSF (and lots and lots of old code). */ | |
608 args[argnum] = Fnumber_to_string (seq); | |
609 else | |
610 { | |
611 check_losing_bytecode ("concat", seq); | |
612 args[argnum] = wrong_type_argument (Qsequencep, seq); | |
613 } | |
614 | |
615 if (args_mse) | |
616 { | |
617 if (STRINGP (seq)) | |
618 args_mse[argnum].string = seq; | |
619 else | |
620 args_mse[argnum].string = Qnil; | |
621 } | |
622 } | |
623 | |
624 { | |
625 /* Charcount is a misnomer here as we might be dealing with the | |
626 length of a vector or list, but emphasizes that we're not dealing | |
627 with Bytecounts in strings */ | |
628 Charcount total_length; | |
629 | |
630 for (argnum = 0, total_length = 0; argnum < nargs; argnum++) | |
631 { | |
632 #ifdef LOSING_BYTECODE | |
633 Charcount thislen = length_with_bytecode_hack (args[argnum]); | |
634 #else | |
635 Charcount thislen = XINT (Flength (args[argnum])); | |
636 #endif | |
637 total_length += thislen; | |
638 } | |
639 | |
640 switch (target_type) | |
641 { | |
642 case c_cons: | |
643 if (total_length == 0) | |
644 /* In append, if all but last arg are nil, return last arg */ | |
645 RETURN_UNGCPRO (last_tail); | |
646 val = Fmake_list (make_int (total_length), Qnil); | |
647 break; | |
648 case c_vector: | |
649 val = make_vector (total_length, Qnil); | |
650 break; | |
651 case c_bit_vector: | |
652 val = make_bit_vector (total_length, Qzero); | |
653 break; | |
654 case c_string: | |
655 /* We don't make the string yet because we don't know the | |
656 actual number of bytes. This loop was formerly written | |
657 to call Fmake_string() here and then call set_string_char() | |
658 for each char. This seems logical enough but is waaaaaaaay | |
659 slow -- set_string_char() has to scan the whole string up | |
660 to the place where the substitution is called for in order | |
661 to find the place to change, and may have to do some | |
662 realloc()ing in order to make the char fit properly. | |
663 O(N^2) yuckage. */ | |
664 val = Qnil; | |
665 string_result = (Bufbyte *) alloca (total_length * MAX_EMCHAR_LEN); | |
666 string_result_ptr = string_result; | |
667 break; | |
668 default: | |
669 abort (); | |
670 } | |
671 } | |
672 | |
673 | |
674 if (CONSP (val)) | |
675 tail = val, toindex = -1; /* -1 in toindex is flag we are | |
676 making a list */ | |
677 else | |
678 toindex = 0; | |
679 | |
680 prev = Qnil; | |
681 | |
682 for (argnum = 0; argnum < nargs; argnum++) | |
683 { | |
684 Charcount thisleni = 0; | |
685 Charcount thisindex = 0; | |
686 Lisp_Object seq = args[argnum]; | |
687 Bufbyte *string_source_ptr = 0; | |
688 Bufbyte *string_prev_result_ptr = string_result_ptr; | |
689 | |
690 if (!CONSP (seq)) | |
691 { | |
692 #ifdef LOSING_BYTECODE | |
693 thisleni = length_with_bytecode_hack (seq); | |
694 #else | |
695 thisleni = XINT (Flength (seq)); | |
696 #endif | |
697 } | |
698 if (STRINGP (seq)) | |
699 string_source_ptr = string_data (XSTRING (seq)); | |
700 | |
701 while (1) | |
702 { | |
703 Lisp_Object elt; | |
704 | |
705 /* We've come to the end of this arg, so exit. */ | |
706 if (NILP (seq)) | |
707 break; | |
708 | |
709 /* Fetch next element of `seq' arg into `elt' */ | |
710 if (CONSP (seq)) | |
711 { | |
712 elt = Fcar (seq); | |
713 seq = Fcdr (seq); | |
714 } | |
715 else | |
716 { | |
717 if (thisindex >= thisleni) | |
718 break; | |
719 | |
720 if (STRINGP (seq)) | |
721 { | |
722 elt = make_char (charptr_emchar (string_source_ptr)); | |
723 INC_CHARPTR (string_source_ptr); | |
724 } | |
725 else if (VECTORP (seq)) | |
726 elt = vector_data (XVECTOR (seq))[thisindex]; | |
727 else if (BIT_VECTORP (seq)) | |
728 elt = make_int (bit_vector_bit (XBIT_VECTOR (seq), | |
729 thisindex)); | |
730 else | |
731 elt = Felt (seq, make_int (thisindex)); | |
732 thisindex++; | |
733 } | |
734 | |
735 /* Store into result */ | |
736 if (toindex < 0) | |
737 { | |
738 /* toindex negative means we are making a list */ | |
739 XCAR (tail) = elt; | |
740 prev = tail; | |
741 tail = XCDR (tail); | |
742 } | |
743 else if (VECTORP (val)) | |
744 vector_data (XVECTOR (val))[toindex++] = elt; | |
745 else if (BIT_VECTORP (val)) | |
746 { | |
747 CHECK_BIT (elt); | |
748 set_bit_vector_bit (XBIT_VECTOR (val), toindex++, XINT (elt)); | |
749 } | |
750 else | |
751 { | |
752 CHECK_CHAR_COERCE_INT (elt); | |
753 string_result_ptr += set_charptr_emchar (string_result_ptr, | |
754 XCHAR (elt)); | |
755 } | |
756 } | |
757 if (args_mse) | |
758 { | |
759 args_mse[argnum].entry_offset = | |
760 string_prev_result_ptr - string_result; | |
761 args_mse[argnum].entry_length = | |
762 string_result_ptr - string_prev_result_ptr; | |
763 } | |
764 } | |
765 | |
766 /* Now we finally make the string. */ | |
767 if (target_type == c_string) | |
768 { | |
769 val = make_string (string_result, string_result_ptr - string_result); | |
770 for (argnum = 0; argnum < nargs; argnum++) | |
771 { | |
772 if (STRINGP (args_mse[argnum].string)) | |
773 copy_string_extents (val, args_mse[argnum].string, | |
774 args_mse[argnum].entry_offset, 0, | |
775 args_mse[argnum].entry_length); | |
776 } | |
777 } | |
778 | |
779 if (!NILP (prev)) | |
780 XCDR (prev) = last_tail; | |
781 | |
782 RETURN_UNGCPRO (val); | |
783 } | |
784 | |
785 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0 /* | |
786 Return a copy of ALIST. | |
787 This is an alist which represents the same mapping from objects to objects, | |
788 but does not share the alist structure with ALIST. | |
789 The objects mapped (cars and cdrs of elements of the alist) | |
790 are shared, however. | |
791 Elements of ALIST that are not conses are also shared. | |
792 */ ) | |
793 (alist) | |
794 Lisp_Object alist; | |
795 { | |
796 Lisp_Object tem; | |
797 | |
798 CHECK_LIST (alist); | |
799 if (NILP (alist)) | |
800 return alist; | |
801 alist = concat (1, &alist, c_cons, 0); | |
802 for (tem = alist; CONSP (tem); tem = XCDR (tem)) | |
803 { | |
804 Lisp_Object car; | |
805 car = XCAR (tem); | |
806 | |
807 if (CONSP (car)) | |
808 XCAR (tem) = Fcons (XCAR (car), XCDR (car)); | |
809 } | |
810 return alist; | |
811 } | |
812 | |
813 DEFUN ("copy-tree", Fcopy_tree, Scopy_tree, 1, 2, 0 /* | |
814 Return a copy of a list and substructures. | |
815 The argument is copied, and any lists contained within it are copied | |
816 recursively. Circularities and shared substructures are not preserved. | |
817 Second arg VECP causes vectors to be copied, too. Strings and bit vectors | |
818 are not copied. | |
819 */ ) | |
820 (arg, vecp) | |
821 Lisp_Object arg, vecp; | |
822 { | |
823 if (CONSP (arg)) | |
824 { | |
825 Lisp_Object rest; | |
826 rest = arg = Fcopy_sequence (arg); | |
827 while (CONSP (rest)) | |
828 { | |
829 Lisp_Object elt = XCAR (rest); | |
830 QUIT; | |
831 if (CONSP (elt) || VECTORP (elt)) | |
832 XCAR (rest) = Fcopy_tree (elt, vecp); | |
833 if (VECTORP (XCDR (rest))) /* hack for (a b . [c d]) */ | |
834 XCDR (rest) = Fcopy_tree (XCDR (rest), vecp); | |
835 rest = XCDR (rest); | |
836 } | |
837 } | |
838 else if (VECTORP (arg) && ! NILP (vecp)) | |
839 { | |
840 int i = vector_length (XVECTOR (arg)); | |
841 int j; | |
842 arg = Fcopy_sequence (arg); | |
843 for (j = 0; j < i; j++) | |
844 { | |
845 Lisp_Object elt = vector_data (XVECTOR (arg)) [j]; | |
846 QUIT; | |
847 if (CONSP (elt) || VECTORP (elt)) | |
848 vector_data (XVECTOR (arg)) [j] = Fcopy_tree (elt, vecp); | |
849 } | |
850 } | |
851 return arg; | |
852 } | |
853 | |
854 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0 /* | |
855 Return a substring of STRING, starting at index FROM and ending before TO. | |
856 TO may be nil or omitted; then the substring runs to the end of STRING. | |
857 If FROM or TO is negative, it counts from the end. | |
858 Relevant parts of the string-extent-data are copied in the new string. | |
859 */ ) | |
860 (string, from, to) | |
861 Lisp_Object string; | |
862 Lisp_Object from, to; | |
863 { | |
864 Charcount ccfr, ccto; | |
865 Bytecount bfr, bto; | |
866 Lisp_Object val; | |
867 | |
868 CHECK_STRING (string); | |
869 /* Historically, FROM could not be omitted. Whatever ... */ | |
870 CHECK_INT (from); | |
871 get_string_range_char (string, from, to, &ccfr, &ccto, | |
872 GB_HISTORICAL_STRING_BEHAVIOR); | |
873 bfr = charcount_to_bytecount (string_data (XSTRING (string)), ccfr); | |
874 bto = charcount_to_bytecount (string_data (XSTRING (string)), ccto); | |
875 val = make_string (string_data (XSTRING (string)) + bfr, bto - bfr); | |
876 /* Copy any applicable extent information into the new string: */ | |
877 copy_string_extents (val, string, 0, bfr, bto - bfr); | |
878 return (val); | |
879 } | |
880 | |
881 DEFUN ("subseq", Fsubseq, Ssubseq, 2, 3, 0 /* | |
882 Return a subsequence of SEQ, starting at index FROM and ending before TO. | |
883 TO may be nil or omitted; then the subsequence runs to the end of SEQ. | |
884 If FROM or TO is negative, it counts from the end. | |
885 The resulting subsequence is always the same type as the original | |
886 sequence. | |
887 If SEQ is a string, relevant parts of the string-extent-data are copied | |
888 in the new string. | |
889 */ ) | |
890 (seq, from, to) | |
891 Lisp_Object seq; | |
892 Lisp_Object from, to; | |
893 { | |
894 int len, f, t; | |
895 | |
896 if (STRINGP (seq)) | |
897 return Fsubstring (seq, from, to); | |
898 | |
899 if (CONSP (seq) || NILP (seq)) | |
900 ; | |
901 else if (VECTORP (seq) || BIT_VECTORP (seq)) | |
902 ; | |
903 else | |
904 { | |
905 check_losing_bytecode ("subseq", seq); | |
906 seq = wrong_type_argument (Qsequencep, seq); | |
907 } | |
908 | |
909 len = XINT (Flength (seq)); | |
910 CHECK_INT (from); | |
911 f = XINT (from); | |
912 if (f < 0) | |
913 f = len + f; | |
914 if (NILP (to)) | |
915 t = len; | |
916 else | |
917 { | |
918 CHECK_INT (to); | |
919 t = XINT (to); | |
920 if (t < 0) | |
921 t = len + t; | |
922 } | |
923 | |
924 if (!(0 <= f && f <= t && t <= len)) | |
925 args_out_of_range_3 (seq, make_int (f), make_int (t)); | |
926 | |
927 if (VECTORP (seq)) | |
928 { | |
929 Lisp_Object result = make_vector (t - f, Qnil); | |
930 int i; | |
931 Lisp_Object *in_elts = vector_data (XVECTOR (seq)); | |
932 Lisp_Object *out_elts = vector_data (XVECTOR (result)); | |
933 | |
934 for (i = f; i < t; i++) | |
935 out_elts[i - f] = in_elts[i]; | |
936 return result; | |
937 } | |
938 | |
939 if (CONSP (seq)) | |
940 { | |
941 Lisp_Object result = Qnil; | |
942 int i; | |
943 | |
944 seq = Fnthcdr (make_int (f), seq); | |
945 | |
946 for (i = f; i < t; i++) | |
947 { | |
948 result = Fcons (Fcar (seq), result); | |
949 seq = Fcdr (seq); | |
950 } | |
951 | |
952 return Fnreverse (result); | |
953 } | |
954 | |
955 /* bit vector */ | |
956 { | |
957 Lisp_Object result = make_bit_vector (t - f, Qzero); | |
958 int i; | |
959 | |
960 for (i = f; i < t; i++) | |
961 set_bit_vector_bit (XBIT_VECTOR (result), i - f, | |
962 bit_vector_bit (XBIT_VECTOR (seq), i)); | |
963 return result; | |
964 } | |
965 } | |
966 | |
967 | |
968 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0 /* | |
969 Take cdr N times on LIST, returns the result. | |
970 */ ) | |
971 (n, list) | |
972 Lisp_Object n; | |
973 Lisp_Object list; | |
974 { | |
975 REGISTER int i, num; | |
976 CHECK_INT (n); | |
977 num = XINT (n); | |
978 for (i = 0; i < num && !NILP (list); i++) | |
979 { | |
980 QUIT; | |
981 list = Fcdr (list); | |
982 } | |
983 return list; | |
984 } | |
985 | |
986 DEFUN ("nth", Fnth, Snth, 2, 2, 0 /* | |
987 Return the Nth element of LIST. | |
988 N counts from zero. If LIST is not that long, nil is returned. | |
989 */ ) | |
990 (n, list) | |
991 Lisp_Object n, list; | |
992 { | |
993 return Fcar (Fnthcdr (n, list)); | |
994 } | |
995 | |
996 DEFUN ("elt", Felt, Selt, 2, 2, 0 /* | |
997 Return element of SEQUENCE at index N. | |
998 */ ) | |
999 (seq, n) | |
1000 Lisp_Object seq, n; | |
1001 { | |
1002 retry: | |
1003 CHECK_INT_COERCE_CHAR (n); /* yuck! */ | |
1004 if (CONSP (seq) || NILP (seq)) | |
1005 { | |
1006 Lisp_Object tem = Fnthcdr (n, seq); | |
1007 /* #### Utterly, completely, fucking disgusting. | |
1008 * #### The whole point of "elt" is that it operates on | |
1009 * #### sequences, and does error- (bounds-) checking. | |
1010 */ | |
1011 if (CONSP (tem)) | |
1012 return (XCAR (tem)); | |
1013 else | |
1014 #if 1 | |
1015 /* This is The Way It Has Always Been. */ | |
1016 return Qnil; | |
1017 #else | |
1018 /* This is The Way Mly Says It Should Be. */ | |
1019 args_out_of_range (seq, n); | |
1020 #endif | |
1021 } | |
1022 else if (STRINGP (seq) | |
1023 || VECTORP (seq) | |
1024 || BIT_VECTORP (seq)) | |
1025 return (Faref (seq, n)); | |
1026 #ifdef LOSING_BYTECODE | |
1027 else if (COMPILED_FUNCTIONP (seq)) | |
1028 { | |
1029 int idx = XINT (n); | |
1030 if (idx < 0) | |
1031 { | |
1032 lose: | |
1033 args_out_of_range (seq, n); | |
1034 } | |
1035 /* Utter perversity */ | |
1036 { | |
1037 struct Lisp_Compiled_Function *b = XCOMPILED_FUNCTION (seq); | |
1038 switch (idx) | |
1039 { | |
1040 case COMPILED_ARGLIST: | |
1041 return (b->arglist); | |
1042 case COMPILED_BYTECODE: | |
1043 return (b->bytecodes); | |
1044 case COMPILED_CONSTANTS: | |
1045 return (b->constants); | |
1046 case COMPILED_STACK_DEPTH: | |
1047 return (make_int (b->maxdepth)); | |
1048 case COMPILED_DOC_STRING: | |
1049 return (compiled_function_documentation (b)); | |
1050 case COMPILED_DOMAIN: | |
1051 return (compiled_function_domain (b)); | |
1052 case COMPILED_INTERACTIVE: | |
1053 if (b->flags.interactivep) | |
1054 return (compiled_function_interactive (b)); | |
1055 /* if we return nil, can't tell interactive with no args | |
1056 from noninteractive. */ | |
1057 goto lose; | |
1058 default: | |
1059 goto lose; | |
1060 } | |
1061 } | |
1062 } | |
1063 #endif /* LOSING_BYTECODE */ | |
1064 else | |
1065 { | |
1066 check_losing_bytecode ("elt", seq); | |
1067 seq = wrong_type_argument (Qsequencep, seq); | |
1068 goto retry; | |
1069 } | |
1070 } | |
1071 | |
1072 DEFUN ("member", Fmember, Smember, 2, 2, 0 /* | |
1073 Return non-nil if ELT is an element of LIST. Comparison done with `equal'. | |
1074 The value is actually the tail of LIST whose car is ELT. | |
1075 */ ) | |
1076 (elt, list) | |
1077 Lisp_Object elt; | |
1078 Lisp_Object list; | |
1079 { | |
1080 REGISTER Lisp_Object tail, tem; | |
1081 for (tail = list; !NILP (tail); tail = Fcdr (tail)) | |
1082 { | |
1083 tem = Fcar (tail); | |
1084 if (! NILP (Fequal (elt, tem))) | |
1085 return tail; | |
1086 QUIT; | |
1087 } | |
1088 return Qnil; | |
1089 } | |
1090 | |
1091 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0 /* | |
1092 Return non-nil if ELT is an element of LIST. Comparison done with `eq'. | |
1093 The value is actually the tail of LIST whose car is ELT. | |
1094 */ ) | |
1095 (elt, list) | |
1096 Lisp_Object elt; | |
1097 Lisp_Object list; | |
1098 { | |
1099 REGISTER Lisp_Object tail, tem; | |
1100 for (tail = list; !NILP (tail); tail = Fcdr (tail)) | |
1101 { | |
1102 tem = Fcar (tail); | |
1103 if (HACKEQ_UNSAFE (elt, tem)) return tail; | |
1104 QUIT; | |
1105 } | |
1106 return Qnil; | |
1107 } | |
1108 | |
1109 Lisp_Object | |
1110 memq_no_quit (Lisp_Object elt, Lisp_Object list) | |
1111 { | |
1112 REGISTER Lisp_Object tail, tem; | |
1113 for (tail = list; CONSP (tail); tail = XCDR (tail)) | |
1114 { | |
1115 tem = XCAR (tail); | |
1116 if (HACKEQ_UNSAFE (elt, tem)) return tail; | |
1117 } | |
1118 return Qnil; | |
1119 } | |
1120 | |
1121 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0 /* | |
1122 Return non-nil if KEY is `equal' to the car of an element of LIST. | |
1123 The value is actually the element of LIST whose car equals KEY. | |
1124 */ ) | |
1125 (key, list) | |
1126 Lisp_Object key; | |
1127 Lisp_Object list; | |
1128 { | |
1129 /* This function can GC. */ | |
1130 REGISTER Lisp_Object tail, elt, tem; | |
1131 for (tail = list; !NILP (tail); tail = Fcdr (tail)) | |
1132 { | |
1133 elt = Fcar (tail); | |
1134 if (!CONSP (elt)) continue; | |
1135 tem = Fequal (Fcar (elt), key); | |
1136 if (!NILP (tem)) return elt; | |
1137 QUIT; | |
1138 } | |
1139 return Qnil; | |
1140 } | |
1141 | |
1142 Lisp_Object | |
1143 assoc_no_quit (Lisp_Object key, Lisp_Object list) | |
1144 { | |
1145 int speccount = specpdl_depth (); | |
1146 specbind (Qinhibit_quit, Qt); | |
1147 return (unbind_to (speccount, Fassoc (key, list))); | |
1148 } | |
1149 | |
1150 DEFUN ("assq", Fassq, Sassq, 2, 2, 0 /* | |
1151 Return non-nil if KEY is `eq' to the car of an element of LIST. | |
1152 The value is actually the element of LIST whose car is KEY. | |
1153 Elements of LIST that are not conses are ignored. | |
1154 */ ) | |
1155 (key, list) | |
1156 Lisp_Object key; | |
1157 Lisp_Object list; | |
1158 { | |
1159 REGISTER Lisp_Object tail, elt, tem; | |
1160 for (tail = list; !NILP (tail); tail = Fcdr (tail)) | |
1161 { | |
1162 elt = Fcar (tail); | |
1163 if (!CONSP (elt)) continue; | |
1164 tem = Fcar (elt); | |
1165 if (HACKEQ_UNSAFE (key, tem)) return elt; | |
1166 QUIT; | |
1167 } | |
1168 return Qnil; | |
1169 } | |
1170 | |
1171 /* Like Fassq but never report an error and do not allow quits. | |
1172 Use only on lists known never to be circular. */ | |
1173 | |
1174 Lisp_Object | |
1175 assq_no_quit (Lisp_Object key, Lisp_Object list) | |
1176 { | |
1177 /* This cannot GC. */ | |
1178 REGISTER Lisp_Object tail, elt, tem; | |
1179 for (tail = list; CONSP (tail); tail = XCDR (tail)) | |
1180 { | |
1181 elt = XCAR (tail); | |
1182 if (!CONSP (elt)) continue; | |
1183 tem = XCAR (elt); | |
1184 if (HACKEQ_UNSAFE (key, tem)) return elt; | |
1185 } | |
1186 return Qnil; | |
1187 } | |
1188 | |
1189 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0 /* | |
1190 Return non-nil if KEY is `equal' to the cdr of an element of LIST. | |
1191 The value is actually the element of LIST whose cdr equals KEY. | |
1192 */ ) | |
1193 (key, list) | |
1194 Lisp_Object key; | |
1195 Lisp_Object list; | |
1196 { | |
1197 REGISTER Lisp_Object tail; | |
1198 for (tail = list; !NILP (tail); tail = Fcdr (tail)) | |
1199 { | |
1200 REGISTER Lisp_Object elt, tem; | |
1201 elt = Fcar (tail); | |
1202 if (!CONSP (elt)) continue; | |
1203 tem = Fequal (Fcdr (elt), key); | |
1204 if (!NILP (tem)) return elt; | |
1205 QUIT; | |
1206 } | |
1207 return Qnil; | |
1208 } | |
1209 | |
1210 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0 /* | |
1211 Return non-nil if KEY is `eq' to the cdr of an element of LIST. | |
1212 The value is actually the element of LIST whose cdr is KEY. | |
1213 */ ) | |
1214 (key, list) | |
1215 Lisp_Object key; | |
1216 Lisp_Object list; | |
1217 { | |
1218 REGISTER Lisp_Object tail, elt, tem; | |
1219 for (tail = list; !NILP (tail); tail = Fcdr (tail)) | |
1220 { | |
1221 elt = Fcar (tail); | |
1222 if (!CONSP (elt)) continue; | |
1223 tem = Fcdr (elt); | |
1224 if (HACKEQ_UNSAFE (key, tem)) return elt; | |
1225 QUIT; | |
1226 } | |
1227 return Qnil; | |
1228 } | |
1229 | |
1230 Lisp_Object | |
1231 rassq_no_quit (Lisp_Object key, Lisp_Object list) | |
1232 { | |
1233 REGISTER Lisp_Object tail, elt, tem; | |
1234 for (tail = list; CONSP (tail); tail = XCDR (tail)) | |
1235 { | |
1236 elt = XCAR (tail); | |
1237 if (!CONSP (elt)) continue; | |
1238 tem = XCDR (elt); | |
1239 if (HACKEQ_UNSAFE (key, tem)) return elt; | |
1240 } | |
1241 return Qnil; | |
1242 } | |
1243 | |
1244 | |
1245 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0 /* | |
1246 Delete by side effect any occurrences of ELT as a member of LIST. | |
1247 The modified LIST is returned. Comparison is done with `equal'. | |
1248 If the first member of LIST is ELT, there is no way to remove it by side | |
1249 effect; therefore, write `(setq foo (delete element foo))' to be sure | |
1250 of changing the value of `foo'. | |
1251 */ ) | |
1252 (elt, list) | |
1253 Lisp_Object elt; | |
1254 Lisp_Object list; | |
1255 { | |
1256 REGISTER Lisp_Object tail, prev; | |
1257 | |
1258 tail = list; | |
1259 prev = Qnil; | |
1260 while (!NILP (tail)) | |
1261 { | |
1262 if (!NILP (Fequal (elt, Fcar (tail)))) | |
1263 { | |
1264 if (NILP (prev)) | |
1265 list = Fcdr (tail); | |
1266 else | |
1267 Fsetcdr (prev, Fcdr (tail)); | |
1268 } | |
1269 else | |
1270 prev = tail; | |
1271 tail = Fcdr (tail); | |
1272 QUIT; | |
1273 } | |
1274 return list; | |
1275 } | |
1276 | |
1277 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0 /* | |
1278 Delete by side effect any occurrences of ELT as a member of LIST. | |
1279 The modified LIST is returned. Comparison is done with `eq'. | |
1280 If the first member of LIST is ELT, there is no way to remove it by side | |
1281 effect; therefore, write `(setq foo (delq element foo))' to be sure of | |
1282 changing the value of `foo'. | |
1283 */ ) | |
1284 (elt, list) | |
1285 Lisp_Object elt; | |
1286 Lisp_Object list; | |
1287 { | |
1288 REGISTER Lisp_Object tail, prev; | |
1289 REGISTER Lisp_Object tem; | |
1290 | |
1291 tail = list; | |
1292 prev = Qnil; | |
1293 while (!NILP (tail)) | |
1294 { | |
1295 tem = Fcar (tail); | |
1296 if (HACKEQ_UNSAFE (elt, tem)) | |
1297 { | |
1298 if (NILP (prev)) | |
1299 list = Fcdr (tail); | |
1300 else | |
1301 Fsetcdr (prev, Fcdr (tail)); | |
1302 } | |
1303 else | |
1304 prev = tail; | |
1305 tail = Fcdr (tail); | |
1306 QUIT; | |
1307 } | |
1308 return list; | |
1309 } | |
1310 | |
1311 /* no quit, no errors; be careful */ | |
1312 | |
1313 Lisp_Object | |
1314 delq_no_quit (Lisp_Object elt, Lisp_Object list) | |
1315 { | |
1316 REGISTER Lisp_Object tail, prev; | |
1317 REGISTER Lisp_Object tem; | |
1318 | |
1319 tail = list; | |
1320 prev = Qnil; | |
1321 while (CONSP (tail)) | |
1322 { | |
1323 tem = XCAR (tail); | |
1324 if (HACKEQ_UNSAFE (elt, tem)) | |
1325 { | |
1326 if (NILP (prev)) | |
1327 list = XCDR (tail); | |
1328 else | |
1329 XCDR (prev) = XCDR (tail); | |
1330 } | |
1331 else | |
1332 prev = tail; | |
1333 tail = XCDR (tail); | |
1334 } | |
1335 return list; | |
1336 } | |
1337 | |
1338 /* Be VERY careful with this. This is like delq_no_quit() but | |
1339 also calls free_cons() on the removed conses. You must be SURE | |
1340 that no pointers to the freed conses remain around (e.g. | |
1341 someone else is pointing to part of the list). This function | |
1342 is useful on internal lists that are used frequently and where | |
1343 the actual list doesn't escape beyond known code bounds. */ | |
1344 | |
1345 Lisp_Object | |
1346 delq_no_quit_and_free_cons (Lisp_Object elt, Lisp_Object list) | |
1347 { | |
1348 REGISTER Lisp_Object tail, prev; | |
1349 REGISTER Lisp_Object tem; | |
1350 | |
1351 tail = list; | |
1352 prev = Qnil; | |
1353 while (CONSP (tail)) | |
1354 { | |
1355 Lisp_Object cons_to_free = Qnil; | |
1356 tem = XCAR (tail); | |
1357 if (HACKEQ_UNSAFE (elt, tem)) | |
1358 { | |
1359 if (NILP (prev)) | |
1360 list = XCDR (tail); | |
1361 else | |
1362 XCDR (prev) = XCDR (tail); | |
1363 cons_to_free = tail; | |
1364 } | |
1365 else | |
1366 prev = tail; | |
1367 tail = XCDR (tail); | |
1368 if (!NILP (cons_to_free)) | |
1369 free_cons (XCONS (cons_to_free)); | |
1370 } | |
1371 return list; | |
1372 } | |
1373 | |
1374 DEFUN ("remassoc", Fremassoc, Sremassoc, 2, 2, 0 /* | |
1375 Delete by side effect any elements of LIST whose car is `equal' to KEY. | |
1376 The modified LIST is returned. If the first member of LIST has a car | |
1377 that is `equal' to KEY, there is no way to remove it by side effect; | |
1378 therefore, write `(setq foo (remassoc key foo))' to be sure of changing | |
1379 the value of `foo'. | |
1380 */ ) | |
1381 (key, list) | |
1382 Lisp_Object key; | |
1383 Lisp_Object list; | |
1384 { | |
1385 REGISTER Lisp_Object tail, prev; | |
1386 | |
1387 tail = list; | |
1388 prev = Qnil; | |
1389 while (!NILP (tail)) | |
1390 { | |
1391 Lisp_Object elt = Fcar (tail); | |
1392 if (CONSP (elt) && ! NILP (Fequal (key, Fcar (elt)))) | |
1393 { | |
1394 if (NILP (prev)) | |
1395 list = Fcdr (tail); | |
1396 else | |
1397 Fsetcdr (prev, Fcdr (tail)); | |
1398 } | |
1399 else | |
1400 prev = tail; | |
1401 tail = Fcdr (tail); | |
1402 QUIT; | |
1403 } | |
1404 return list; | |
1405 } | |
1406 | |
1407 Lisp_Object | |
1408 remassoc_no_quit (Lisp_Object key, Lisp_Object list) | |
1409 { | |
1410 int speccount = specpdl_depth (); | |
1411 specbind (Qinhibit_quit, Qt); | |
1412 return (unbind_to (speccount, Fremassoc (key, list))); | |
1413 } | |
1414 | |
1415 DEFUN ("remassq", Fremassq, Sremassq, 2, 2, 0 /* | |
1416 Delete by side effect any elements of LIST whose car is `eq' to KEY. | |
1417 The modified LIST is returned. If the first member of LIST has a car | |
1418 that is `eq' to KEY, there is no way to remove it by side effect; | |
1419 therefore, write `(setq foo (remassq key foo))' to be sure of changing | |
1420 the value of `foo'. | |
1421 */ ) | |
1422 (key, list) | |
1423 Lisp_Object key; | |
1424 Lisp_Object list; | |
1425 { | |
1426 REGISTER Lisp_Object tail, prev; | |
1427 | |
1428 tail = list; | |
1429 prev = Qnil; | |
1430 while (!NILP (tail)) | |
1431 { | |
1432 Lisp_Object elt = Fcar (tail); | |
1433 if (CONSP (elt) && HACKEQ_UNSAFE (key, Fcar (elt))) | |
1434 { | |
1435 if (NILP (prev)) | |
1436 list = Fcdr (tail); | |
1437 else | |
1438 Fsetcdr (prev, Fcdr (tail)); | |
1439 } | |
1440 else | |
1441 prev = tail; | |
1442 tail = Fcdr (tail); | |
1443 QUIT; | |
1444 } | |
1445 return list; | |
1446 } | |
1447 | |
1448 /* no quit, no errors; be careful */ | |
1449 | |
1450 Lisp_Object | |
1451 remassq_no_quit (Lisp_Object key, Lisp_Object list) | |
1452 { | |
1453 REGISTER Lisp_Object tail, prev; | |
1454 REGISTER Lisp_Object tem; | |
1455 | |
1456 tail = list; | |
1457 prev = Qnil; | |
1458 while (CONSP (tail)) | |
1459 { | |
1460 tem = XCAR (tail); | |
1461 if (CONSP (tem) && HACKEQ_UNSAFE (key, XCAR (tem))) | |
1462 { | |
1463 if (NILP (prev)) | |
1464 list = XCDR (tail); | |
1465 else | |
1466 XCDR (prev) = XCDR (tail); | |
1467 } | |
1468 else | |
1469 prev = tail; | |
1470 tail = XCDR (tail); | |
1471 } | |
1472 return list; | |
1473 } | |
1474 | |
1475 DEFUN ("remrassoc", Fremrassoc, Sremrassoc, 2, 2, 0 /* | |
1476 Delete by side effect any elements of LIST whose cdr is `equal' to VALUE. | |
1477 The modified LIST is returned. If the first member of LIST has a car | |
1478 that is `equal' to VALUE, there is no way to remove it by side effect; | |
1479 therefore, write `(setq foo (remrassoc value foo))' to be sure of changing | |
1480 the value of `foo'. | |
1481 */ ) | |
1482 (value, list) | |
1483 Lisp_Object value; | |
1484 Lisp_Object list; | |
1485 { | |
1486 REGISTER Lisp_Object tail, prev; | |
1487 | |
1488 tail = list; | |
1489 prev = Qnil; | |
1490 while (!NILP (tail)) | |
1491 { | |
1492 Lisp_Object elt = Fcar (tail); | |
1493 if (CONSP (elt) && ! NILP (Fequal (value, Fcdr (elt)))) | |
1494 { | |
1495 if (NILP (prev)) | |
1496 list = Fcdr (tail); | |
1497 else | |
1498 Fsetcdr (prev, Fcdr (tail)); | |
1499 } | |
1500 else | |
1501 prev = tail; | |
1502 tail = Fcdr (tail); | |
1503 QUIT; | |
1504 } | |
1505 return list; | |
1506 } | |
1507 | |
1508 DEFUN ("remrassq", Fremrassq, Sremrassq, 2, 2, 0 /* | |
1509 Delete by side effect any elements of LIST whose cdr is `eq' to VALUE. | |
1510 The modified LIST is returned. If the first member of LIST has a car | |
1511 that is `eq' to VALUE, there is no way to remove it by side effect; | |
1512 therefore, write `(setq foo (remrassq value foo))' to be sure of changing | |
1513 the value of `foo'. | |
1514 */ ) | |
1515 (value, list) | |
1516 Lisp_Object value; | |
1517 Lisp_Object list; | |
1518 { | |
1519 REGISTER Lisp_Object tail, prev; | |
1520 | |
1521 tail = list; | |
1522 prev = Qnil; | |
1523 while (!NILP (tail)) | |
1524 { | |
1525 Lisp_Object elt = Fcar (tail); | |
1526 if (CONSP (elt) && HACKEQ_UNSAFE (value, Fcdr (elt))) | |
1527 { | |
1528 if (NILP (prev)) | |
1529 list = Fcdr (tail); | |
1530 else | |
1531 Fsetcdr (prev, Fcdr (tail)); | |
1532 } | |
1533 else | |
1534 prev = tail; | |
1535 tail = Fcdr (tail); | |
1536 QUIT; | |
1537 } | |
1538 return list; | |
1539 } | |
1540 | |
1541 /* no quit, no errors; be careful */ | |
1542 | |
1543 Lisp_Object | |
1544 remrassq_no_quit (Lisp_Object value, Lisp_Object list) | |
1545 { | |
1546 REGISTER Lisp_Object tail, prev; | |
1547 REGISTER Lisp_Object tem; | |
1548 | |
1549 tail = list; | |
1550 prev = Qnil; | |
1551 while (CONSP (tail)) | |
1552 { | |
1553 tem = XCAR (tail); | |
1554 if (CONSP (tem) && HACKEQ_UNSAFE (value, XCDR (tem))) | |
1555 { | |
1556 if (NILP (prev)) | |
1557 list = XCDR (tail); | |
1558 else | |
1559 XCDR (prev) = XCDR (tail); | |
1560 } | |
1561 else | |
1562 prev = tail; | |
1563 tail = XCDR (tail); | |
1564 } | |
1565 return list; | |
1566 } | |
1567 | |
1568 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0 /* | |
1569 Reverse LIST by modifying cdr pointers. | |
1570 Returns the beginning of the reversed list. | |
1571 */ ) | |
1572 (list) | |
1573 Lisp_Object list; | |
1574 { | |
1575 Lisp_Object prev, tail, next; | |
1576 struct gcpro gcpro1, gcpro2; | |
1577 | |
1578 /* We gcpro our args; see `nconc' */ | |
1579 prev = Qnil; | |
1580 tail = list; | |
1581 GCPRO2 (prev, tail); | |
1582 while (!NILP (tail)) | |
1583 { | |
1584 QUIT; | |
1585 next = Fcdr (tail); | |
1586 Fsetcdr (tail, prev); | |
1587 prev = tail; | |
1588 tail = next; | |
1589 } | |
1590 UNGCPRO; | |
1591 return prev; | |
1592 } | |
1593 | |
1594 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0 /* | |
1595 Reverse LIST, copying. Returns the beginning of the reversed list. | |
1596 See also the function `nreverse', which is used more often. | |
1597 */ ) | |
1598 (list) | |
1599 Lisp_Object list; | |
1600 { | |
1601 Lisp_Object length; | |
1602 Lisp_Object *vec; | |
1603 Lisp_Object tail; | |
1604 REGISTER int i; | |
1605 | |
1606 length = Flength (list); | |
1607 vec = (Lisp_Object *) alloca (XINT (length) * sizeof (Lisp_Object)); | |
1608 for (i = XINT (length) - 1, tail = list; i >= 0; i--, tail = Fcdr (tail)) | |
1609 vec[i] = Fcar (tail); | |
1610 | |
1611 return Flist (XINT (length), vec); | |
1612 } | |
1613 | |
1614 static Lisp_Object list_merge (Lisp_Object org_l1, Lisp_Object org_l2, | |
1615 Lisp_Object lisp_arg, | |
1616 int (*pred_fn) (Lisp_Object, Lisp_Object, | |
1617 Lisp_Object lisp_arg)); | |
1618 | |
1619 Lisp_Object | |
1620 list_sort (Lisp_Object list, | |
1621 Lisp_Object lisp_arg, | |
1622 int (*pred_fn) (Lisp_Object, Lisp_Object, | |
1623 Lisp_Object lisp_arg)) | |
1624 { | |
1625 Lisp_Object front, back; | |
1626 Lisp_Object len, tem; | |
1627 struct gcpro gcpro1, gcpro2, gcpro3; | |
1628 int length; | |
1629 | |
1630 front = list; | |
1631 len = Flength (list); | |
1632 length = XINT (len); | |
1633 if (length < 2) | |
1634 return list; | |
1635 | |
1636 XSETINT (len, (length / 2) - 1); | |
1637 tem = Fnthcdr (len, list); | |
1638 back = Fcdr (tem); | |
1639 Fsetcdr (tem, Qnil); | |
1640 | |
1641 GCPRO3 (front, back, lisp_arg); | |
1642 front = list_sort (front, lisp_arg, pred_fn); | |
1643 back = list_sort (back, lisp_arg, pred_fn); | |
1644 UNGCPRO; | |
1645 return list_merge (front, back, lisp_arg, pred_fn); | |
1646 } | |
1647 | |
1648 | |
1649 static int | |
1650 merge_pred_function (Lisp_Object obj1, Lisp_Object obj2, | |
1651 Lisp_Object pred) | |
1652 { | |
1653 Lisp_Object tmp; | |
1654 | |
1655 /* prevents the GC from happening in call2 */ | |
1656 int speccount = specpdl_depth (); | |
1657 /* Emacs' GC doesn't actually relocate pointers, so this probably | |
1658 isn't strictly necessary */ | |
1659 record_unwind_protect (restore_gc_inhibit, | |
1660 make_int (gc_currently_forbidden)); | |
1661 gc_currently_forbidden = 1; | |
1662 tmp = call2 (pred, obj1, obj2); | |
1663 unbind_to (speccount, Qnil); | |
1664 | |
1665 if (NILP (tmp)) | |
1666 return -1; | |
1667 else | |
1668 return 1; | |
1669 } | |
1670 | |
1671 DEFUN ("sort", Fsort, Ssort, 2, 2, 0 /* | |
1672 Sort LIST, stably, comparing elements using PREDICATE. | |
1673 Returns the sorted list. LIST is modified by side effects. | |
1674 PREDICATE is called with two elements of LIST, and should return T | |
1675 if the first element is \"less\" than the second. | |
1676 */ ) | |
1677 (list, pred) | |
1678 Lisp_Object list, pred; | |
1679 { | |
1680 return list_sort (list, pred, merge_pred_function); | |
1681 } | |
1682 | |
1683 Lisp_Object | |
1684 merge (Lisp_Object org_l1, Lisp_Object org_l2, | |
1685 Lisp_Object pred) | |
1686 { | |
1687 return list_merge (org_l1, org_l2, pred, merge_pred_function); | |
1688 } | |
1689 | |
1690 | |
1691 static Lisp_Object | |
1692 list_merge (Lisp_Object org_l1, Lisp_Object org_l2, | |
1693 Lisp_Object lisp_arg, | |
1694 int (*pred_fn) (Lisp_Object, Lisp_Object, Lisp_Object lisp_arg)) | |
1695 { | |
1696 Lisp_Object value; | |
1697 Lisp_Object tail; | |
1698 Lisp_Object tem; | |
1699 Lisp_Object l1, l2; | |
1700 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; | |
1701 | |
1702 l1 = org_l1; | |
1703 l2 = org_l2; | |
1704 tail = Qnil; | |
1705 value = Qnil; | |
1706 | |
1707 /* It is sufficient to protect org_l1 and org_l2. | |
1708 When l1 and l2 are updated, we copy the new values | |
1709 back into the org_ vars. */ | |
1710 | |
1711 GCPRO4 (org_l1, org_l2, lisp_arg, value); | |
1712 | |
1713 while (1) | |
1714 { | |
1715 if (NILP (l1)) | |
1716 { | |
1717 UNGCPRO; | |
1718 if (NILP (tail)) | |
1719 return l2; | |
1720 Fsetcdr (tail, l2); | |
1721 return value; | |
1722 } | |
1723 if (NILP (l2)) | |
1724 { | |
1725 UNGCPRO; | |
1726 if (NILP (tail)) | |
1727 return l1; | |
1728 Fsetcdr (tail, l1); | |
1729 return value; | |
1730 } | |
1731 | |
1732 if (((*pred_fn) (Fcar (l2), Fcar (l1), lisp_arg)) < 0) | |
1733 { | |
1734 tem = l1; | |
1735 l1 = Fcdr (l1); | |
1736 org_l1 = l1; | |
1737 } | |
1738 else | |
1739 { | |
1740 tem = l2; | |
1741 l2 = Fcdr (l2); | |
1742 org_l2 = l2; | |
1743 } | |
1744 if (NILP (tail)) | |
1745 value = tem; | |
1746 else | |
1747 Fsetcdr (tail, tem); | |
1748 tail = tem; | |
1749 } | |
1750 } | |
1751 | |
1752 | |
1753 /************************************************************************/ | |
1754 /* property-list functions */ | |
1755 /************************************************************************/ | |
1756 | |
1757 /* For properties of text, we need to do order-insensitive comparison of | |
1758 plists. That is, we need to compare two plists such that they are the | |
1759 same if they have the same set of keys, and equivalent values. | |
1760 So (a 1 b 2) would be equal to (b 2 a 1). | |
1761 | |
1762 NIL_MEANS_NOT_PRESENT is as in `plists-eq' etc. | |
1763 LAXP means use `equal' for comparisons. | |
1764 */ | |
1765 int | |
1766 plists_differ (Lisp_Object a, Lisp_Object b, int nil_means_not_present, | |
1767 int laxp, int depth) | |
1768 { | |
1769 int eqp = (depth == -1); /* -1 as depth means us eq, not equal. */ | |
1770 int la, lb, m, i, fill; | |
1771 Lisp_Object *keys, *vals; | |
1772 char *flags; | |
1773 Lisp_Object rest; | |
1774 | |
1775 if (NILP (a) && NILP (b)) | |
1776 return 0; | |
1777 | |
1778 Fcheck_valid_plist (a); | |
1779 Fcheck_valid_plist (b); | |
1780 | |
1781 la = XINT (Flength (a)); | |
1782 lb = XINT (Flength (b)); | |
1783 m = (la > lb ? la : lb); | |
1784 fill = 0; | |
1785 keys = (Lisp_Object *) alloca (m * sizeof (Lisp_Object)); | |
1786 vals = (Lisp_Object *) alloca (m * sizeof (Lisp_Object)); | |
1787 flags = (char *) alloca (m * sizeof (char)); | |
1788 | |
1789 /* First extract the pairs from A. */ | |
1790 for (rest = a; !NILP (rest); rest = XCDR (XCDR (rest))) | |
1791 { | |
1792 Lisp_Object k = XCAR (rest); | |
1793 Lisp_Object v = XCAR (XCDR (rest)); | |
1794 /* Maybe be Ebolified. */ | |
1795 if (nil_means_not_present && NILP (v)) continue; | |
1796 keys [fill] = k; | |
1797 vals [fill] = v; | |
1798 flags[fill] = 0; | |
1799 fill++; | |
1800 } | |
1801 /* Now iterate over B, and stop if we find something that's not in A, | |
1802 or that doesn't match. As we match, mark them. */ | |
1803 for (rest = b; !NILP (rest); rest = XCDR (XCDR (rest))) | |
1804 { | |
1805 Lisp_Object k = XCAR (rest); | |
1806 Lisp_Object v = XCAR (XCDR (rest)); | |
1807 /* Maybe be Ebolified. */ | |
1808 if (nil_means_not_present && NILP (v)) continue; | |
1809 for (i = 0; i < fill; i++) | |
1810 { | |
1811 if (!laxp ? EQ (k, keys [i]) : internal_equal (k, keys [i], depth)) | |
1812 { | |
1813 if ((eqp | |
1814 /* Ebolified here too, sigh ... */ | |
1815 ? !HACKEQ_UNSAFE (v, vals [i]) | |
1816 : !internal_equal (v, vals [i], depth))) | |
1817 /* a property in B has a different value than in A */ | |
1818 goto MISMATCH; | |
1819 flags [i] = 1; | |
1820 break; | |
1821 } | |
1822 } | |
1823 if (i == fill) | |
1824 /* there are some properties in B that are not in A */ | |
1825 goto MISMATCH; | |
1826 } | |
1827 /* Now check to see that all the properties in A were also in B */ | |
1828 for (i = 0; i < fill; i++) | |
1829 if (flags [i] == 0) | |
1830 goto MISMATCH; | |
1831 | |
1832 /* Ok. */ | |
1833 return 0; | |
1834 | |
1835 MISMATCH: | |
1836 return 1; | |
1837 } | |
1838 | |
1839 DEFUN ("plists-eq", Fplists_eq, Splists_eq, 2, 3, 0 /* | |
1840 Return non-nil if property lists A and B are `eq'. | |
1841 A property list is an alternating list of keywords and values. | |
1842 This function does order-insensitive comparisons of the property lists: | |
1843 For example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal. | |
1844 Comparison between values is done using `eq'. See also `plists-equal'. | |
1845 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with | |
1846 a nil value is ignored. This feature is a virus that has infected | |
1847 old Lisp implementations (and thus E-Lisp, due to RMS's enamorment with | |
1848 old Lisps), but should not be used except for backward compatibility. | |
1849 */ ) | |
1850 (a, b, nil_means_not_present) | |
1851 Lisp_Object a, b, nil_means_not_present; | |
1852 { | |
1853 return (plists_differ (a, b, !NILP (nil_means_not_present), 0, -1) | |
1854 ? Qnil : Qt); | |
1855 } | |
1856 | |
1857 DEFUN ("plists-equal", Fplists_equal, Splists_equal, 2, 3, 0 /* | |
1858 Return non-nil if property lists A and B are `equal'. | |
1859 A property list is an alternating list of keywords and values. This | |
1860 function does order-insensitive comparisons of the property lists: For | |
1861 example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal. | |
1862 Comparison between values is done using `equal'. See also `plists-eq'. | |
1863 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with | |
1864 a nil value is ignored. This feature is a virus that has infected | |
1865 old Lisp implementations (and thus E-Lisp, due to RMS's enamorment with | |
1866 old Lisps), but should not be used except for backward compatibility. | |
1867 */ ) | |
1868 (a, b, nil_means_not_present) | |
1869 Lisp_Object a, b, nil_means_not_present; | |
1870 { | |
1871 return (plists_differ (a, b, !NILP (nil_means_not_present), 0, 1) | |
1872 ? Qnil : Qt); | |
1873 } | |
1874 | |
1875 | |
1876 DEFUN ("lax-plists-eq", Flax_plists_eq, Slax_plists_eq, 2, 3, 0 /* | |
1877 Return non-nil if lax property lists A and B are `eq'. | |
1878 A property list is an alternating list of keywords and values. | |
1879 This function does order-insensitive comparisons of the property lists: | |
1880 For example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal. | |
1881 Comparison between values is done using `eq'. See also `plists-equal'. | |
1882 A lax property list is like a regular one except that comparisons between | |
1883 keywords is done using `equal' instead of `eq'. | |
1884 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with | |
1885 a nil value is ignored. This feature is a virus that has infected | |
1886 old Lisp implementations (and thus E-Lisp, due to RMS's enamorment with | |
1887 old Lisps), but should not be used except for backward compatibility. | |
1888 */ ) | |
1889 (a, b, nil_means_not_present) | |
1890 Lisp_Object a, b, nil_means_not_present; | |
1891 { | |
1892 return (plists_differ (a, b, !NILP (nil_means_not_present), 1, -1) | |
1893 ? Qnil : Qt); | |
1894 } | |
1895 | |
1896 DEFUN ("lax-plists-equal", Flax_plists_equal, Slax_plists_equal, 2, 3, 0 /* | |
1897 Return non-nil if lax property lists A and B are `equal'. | |
1898 A property list is an alternating list of keywords and values. This | |
1899 function does order-insensitive comparisons of the property lists: For | |
1900 example, the property lists '(a 1 b 2) and '(b 2 a 1) are equal. | |
1901 Comparison between values is done using `equal'. See also `plists-eq'. | |
1902 A lax property list is like a regular one except that comparisons between | |
1903 keywords is done using `equal' instead of `eq'. | |
1904 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with | |
1905 a nil value is ignored. This feature is a virus that has infected | |
1906 old Lisp implementations (and thus E-Lisp, due to RMS's enamorment with | |
1907 old Lisps), but should not be used except for backward compatibility. | |
1908 */ ) | |
1909 (a, b, nil_means_not_present) | |
1910 Lisp_Object a, b, nil_means_not_present; | |
1911 { | |
1912 return (plists_differ (a, b, !NILP (nil_means_not_present), 1, 1) | |
1913 ? Qnil : Qt); | |
1914 } | |
1915 | |
1916 /* Return the value associated with key PROPERTY in property list PLIST. | |
1917 Return nil if key not found. This function is used for internal | |
1918 property lists that cannot be directly manipulated by the user. | |
1919 */ | |
1920 | |
1921 Lisp_Object | |
1922 internal_plist_get (Lisp_Object plist, Lisp_Object property) | |
1923 { | |
1924 Lisp_Object tail = plist; | |
1925 | |
1926 for (; !NILP (tail); tail = XCDR (XCDR (tail))) | |
1927 { | |
1928 struct Lisp_Cons *c = XCONS (tail); | |
1929 if (EQ (c->car, property)) | |
1930 return XCAR (c->cdr); | |
1931 } | |
1932 | |
1933 return Qunbound; | |
1934 } | |
1935 | |
1936 /* Set PLIST's value for PROPERTY to VALUE. Analogous to | |
1937 internal_plist_get(). */ | |
1938 | |
1939 void | |
1940 internal_plist_put (Lisp_Object *plist, Lisp_Object property, | |
1941 Lisp_Object value) | |
1942 { | |
1943 Lisp_Object tail = *plist; | |
1944 | |
1945 for (; !NILP (tail); tail = XCDR (XCDR (tail))) | |
1946 { | |
1947 struct Lisp_Cons *c = XCONS (tail); | |
1948 if (EQ (c->car, property)) | |
1949 { | |
1950 XCAR (c->cdr) = value; | |
1951 return; | |
1952 } | |
1953 } | |
1954 | |
1955 *plist = Fcons (property, Fcons (value, *plist)); | |
1956 } | |
1957 | |
1958 int | |
1959 internal_remprop (Lisp_Object *plist, Lisp_Object property) | |
1960 { | |
1961 Lisp_Object tail = *plist; | |
1962 | |
1963 if (NILP (tail)) | |
1964 return 0; | |
1965 | |
1966 if (EQ (XCAR (tail), property)) | |
1967 { | |
1968 *plist = XCDR (XCDR (tail)); | |
1969 return 1; | |
1970 } | |
1971 | |
1972 for (tail = XCDR (tail); !NILP (XCDR (tail)); | |
1973 tail = XCDR (XCDR (tail))) | |
1974 { | |
1975 struct Lisp_Cons *c = XCONS (tail); | |
1976 if (EQ (XCAR (c->cdr), property)) | |
1977 { | |
1978 c->cdr = XCDR (XCDR (c->cdr)); | |
1979 return 1; | |
1980 } | |
1981 } | |
1982 | |
1983 return 0; | |
1984 } | |
1985 | |
1986 /* Called on a malformed property list. BADPLACE should be some | |
1987 place where truncating will form a good list -- i.e. we shouldn't | |
1988 result in a list with an odd length. */ | |
1989 | |
1990 static Lisp_Object | |
1991 bad_bad_bunny (Lisp_Object *plist, Lisp_Object *badplace, Error_behavior errb) | |
1992 { | |
1993 if (ERRB_EQ (errb, ERROR_ME)) | |
1994 return Fsignal (Qmalformed_property_list, list2 (*plist, *badplace)); | |
1995 else | |
1996 { | |
1997 if (ERRB_EQ (errb, ERROR_ME_WARN)) | |
1998 { | |
1999 warn_when_safe_lispobj | |
2000 (Qlist, Qwarning, | |
2001 list2 (build_string | |
2002 ("Malformed property list -- list has been truncated"), | |
2003 *plist)); | |
2004 *badplace = Qnil; | |
2005 } | |
2006 return Qunbound; | |
2007 } | |
2008 } | |
2009 | |
2010 /* Called on a circular property list. BADPLACE should be some place | |
2011 where truncating will result in an even-length list, as above. | |
2012 If doesn't particularly matter where we truncate -- anywhere we | |
2013 truncate along the entire list will break the circularity, because | |
2014 it will create a terminus and the list currently doesn't have one. | |
2015 */ | |
2016 | |
2017 static Lisp_Object | |
2018 bad_bad_turtle (Lisp_Object *plist, Lisp_Object *badplace, Error_behavior errb) | |
2019 { | |
2020 if (ERRB_EQ (errb, ERROR_ME)) | |
2021 /* #### Eek, this will probably result in another error | |
2022 when PLIST is printed out */ | |
2023 return Fsignal (Qcircular_property_list, list1 (*plist)); | |
2024 else | |
2025 { | |
2026 if (ERRB_EQ (errb, ERROR_ME_WARN)) | |
2027 { | |
2028 warn_when_safe_lispobj | |
2029 (Qlist, Qwarning, | |
2030 list2 (build_string | |
2031 ("Circular property list -- list has been truncated"), | |
2032 *plist)); | |
2033 *badplace = Qnil; | |
2034 } | |
2035 return Qunbound; | |
2036 } | |
2037 } | |
2038 | |
2039 /* Advance the tortoise pointer by two (one iteration of a property-list | |
2040 loop) and the hare pointer by four and verify that no malformations | |
2041 or circularities exist. If so, return zero and store a value into | |
2042 RETVAL that should be returned by the calling function. Otherwise, | |
2043 return 1. See external_plist_get(). | |
2044 */ | |
2045 | |
2046 static int | |
2047 advance_plist_pointers (Lisp_Object *plist, | |
2048 Lisp_Object **tortoise, Lisp_Object **hare, | |
2049 Error_behavior errb, Lisp_Object *retval) | |
2050 { | |
2051 int i; | |
2052 Lisp_Object *tortsave = *tortoise; | |
2053 | |
2054 /* Note that our "fixing" may be more brutal than necessary, | |
2055 but it's the user's own problem, not ours. if they went in and | |
2056 manually fucked up a plist. */ | |
2057 | |
2058 for (i = 0; i < 2; i++) | |
2059 { | |
2060 /* This is a standard iteration of a defensive-loop-checking | |
2061 loop. We just do it twice because we want to advance past | |
2062 both the property and its value. | |
2063 | |
2064 If the pointer indirection is confusing you, remember that | |
2065 one level of indirection on the hare and tortoise pointers | |
2066 is only due to pass-by-reference for this function. The other | |
2067 level is so that the plist can be fixed in place. */ | |
2068 | |
2069 /* When we reach the end of a well-formed plist, **HARE is | |
2070 nil. In that case, we don't do anything at all except | |
2071 advance TORTOISE by one. Otherwise, we advance HARE | |
2072 by two (making sure it's OK to do so), then advance | |
2073 TORTOISE by one (it will always be OK to do so because | |
2074 the HARE is always ahead of the TORTOISE and will have | |
2075 already verified the path), then make sure TORTOISE and | |
2076 HARE don't contain the same non-nil object -- if the | |
2077 TORTOISE and the HARE ever meet, then obviously we're | |
2078 in a circularity, and if we're in a circularity, then | |
2079 the TORTOISE and the HARE can't cross paths without | |
2080 meeting, since the HARE only gains one step over the | |
2081 TORTOISE per iteration. */ | |
2082 | |
2083 if (!NILP (**hare)) | |
2084 { | |
2085 Lisp_Object *haresave = *hare; | |
2086 if (!CONSP (**hare)) | |
2087 { | |
2088 *retval = bad_bad_bunny (plist, haresave, errb); | |
2089 return 0; | |
2090 } | |
2091 *hare = &XCDR (**hare); | |
2092 /* In a non-plist, we'd check here for a nil value for | |
2093 **HARE, which is OK (it just means the list has an | |
2094 odd number of elements). In a plist, it's not OK | |
2095 for the list to have an odd number of elements. */ | |
2096 if (!CONSP (**hare)) | |
2097 { | |
2098 *retval = bad_bad_bunny (plist, haresave, errb); | |
2099 return 0; | |
2100 } | |
2101 *hare = &XCDR (**hare); | |
2102 } | |
2103 | |
2104 *tortoise = &XCDR (**tortoise); | |
2105 if (!NILP (**hare) && EQ (**tortoise, **hare)) | |
2106 { | |
2107 *retval = bad_bad_turtle (plist, tortsave, errb); | |
2108 return 0; | |
2109 } | |
2110 } | |
2111 | |
2112 return 1; | |
2113 } | |
2114 | |
2115 /* Return the value of PROPERTY from PLIST, or Qunbound if | |
2116 property is not on the list. | |
2117 | |
2118 PLIST is a Lisp-accessible property list, meaning that it | |
2119 has to be checked for malformations and circularities. | |
2120 | |
2121 If ERRB is ERROR_ME, an error will be signalled. Otherwise, the | |
2122 function will never signal an error; and if ERRB is ERROR_ME_WARN, | |
2123 on finding a malformation or a circularity, it issues a warning and | |
2124 attempts to silently fix the problem. | |
2125 | |
2126 A pointer to PLIST is passed in so that PLIST can be successfully | |
2127 "fixed" even if the error is at the beginning of the plist. */ | |
2128 | |
2129 Lisp_Object | |
2130 external_plist_get (Lisp_Object *plist, Lisp_Object property, | |
2131 int laxp, Error_behavior errb) | |
2132 { | |
2133 Lisp_Object *tortoise = plist; | |
2134 Lisp_Object *hare = plist; | |
2135 | |
2136 while (!NILP (*tortoise)) | |
2137 { | |
2138 Lisp_Object *tortsave = tortoise; | |
2139 Lisp_Object retval; | |
2140 | |
2141 /* We do the standard tortoise/hare march. We isolate the | |
2142 grungy stuff to do this in advance_plist_pointers(), though. | |
2143 To us, all this function does is advance the tortoise | |
2144 pointer by two and the hare pointer by four and make sure | |
2145 everything's OK. We first advance the pointers and then | |
2146 check if a property matched; this ensures that our | |
2147 check for a matching property is safe. */ | |
2148 | |
2149 if (!advance_plist_pointers (plist, &tortoise, &hare, errb, &retval)) | |
2150 return retval; | |
2151 | |
2152 if (!laxp ? EQ (XCAR (*tortsave), property) | |
2153 : internal_equal (XCAR (*tortsave), property, 0)) | |
2154 return XCAR (XCDR (*tortsave)); | |
2155 } | |
2156 | |
2157 return Qunbound; | |
2158 } | |
2159 | |
2160 /* Set PLIST's value for PROPERTY to VALUE, given a possibly | |
2161 malformed or circular plist. Analogous to external_plist_get(). */ | |
2162 | |
2163 void | |
2164 external_plist_put (Lisp_Object *plist, Lisp_Object property, | |
2165 Lisp_Object value, int laxp, Error_behavior errb) | |
2166 { | |
2167 Lisp_Object *tortoise = plist; | |
2168 Lisp_Object *hare = plist; | |
2169 | |
2170 while (!NILP (*tortoise)) | |
2171 { | |
2172 Lisp_Object *tortsave = tortoise; | |
2173 Lisp_Object retval; | |
2174 | |
2175 /* See above */ | |
2176 if (!advance_plist_pointers (plist, &tortoise, &hare, errb, &retval)) | |
2177 return; | |
2178 | |
2179 if (!laxp ? EQ (XCAR (*tortsave), property) | |
2180 : internal_equal (XCAR (*tortsave), property, 0)) | |
2181 { | |
2182 XCAR (XCDR (*tortsave)) = value; | |
2183 return; | |
2184 } | |
2185 } | |
2186 | |
2187 *plist = Fcons (property, Fcons (value, *plist)); | |
2188 } | |
2189 | |
2190 int | |
2191 external_remprop (Lisp_Object *plist, Lisp_Object property, | |
2192 int laxp, Error_behavior errb) | |
2193 { | |
2194 Lisp_Object *tortoise = plist; | |
2195 Lisp_Object *hare = plist; | |
2196 | |
2197 while (!NILP (*tortoise)) | |
2198 { | |
2199 Lisp_Object *tortsave = tortoise; | |
2200 Lisp_Object retval; | |
2201 | |
2202 /* See above */ | |
2203 if (!advance_plist_pointers (plist, &tortoise, &hare, errb, &retval)) | |
2204 return 0; | |
2205 | |
2206 if (!laxp ? EQ (XCAR (*tortsave), property) | |
2207 : internal_equal (XCAR (*tortsave), property, 0)) | |
2208 { | |
2209 /* Now you see why it's so convenient to have that level | |
2210 of indirection. */ | |
2211 *tortsave = XCDR (XCDR (*tortsave)); | |
2212 return 1; | |
2213 } | |
2214 } | |
2215 | |
2216 return 0; | |
2217 } | |
2218 | |
2219 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 3, 0 /* | |
2220 Extract a value from a property list. | |
2221 PLIST is a property list, which is a list of the form | |
2222 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value | |
2223 corresponding to the given PROP, or DEFAULT if PROP is not | |
2224 one of the properties on the list. | |
2225 */ ) | |
2226 (plist, prop, defalt) /* Cant spel in C */ | |
2227 Lisp_Object plist, prop, defalt; | |
2228 { | |
2229 Lisp_Object val = external_plist_get (&plist, prop, 0, ERROR_ME); | |
2230 if (UNBOUNDP (val)) | |
2231 return defalt; | |
2232 return val; | |
2233 } | |
2234 | |
2235 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0 /* | |
2236 Change value in PLIST of PROP to VAL. | |
2237 PLIST is a property list, which is a list of the form \(PROP1 VALUE1 | |
2238 PROP2 VALUE2 ...). PROP is usually a symbol and VAL is any object. | |
2239 If PROP is already a property on the list, its value is set to VAL, | |
2240 otherwise the new PROP VAL pair is added. The new plist is returned; | |
2241 use `(setq x (plist-put x prop val))' to be sure to use the new value. | |
2242 The PLIST is modified by side effects. | |
2243 */ ) | |
2244 (plist, prop, val) | |
2245 Lisp_Object plist, prop, val; | |
2246 { | |
2247 external_plist_put (&plist, prop, val, 0, ERROR_ME); | |
2248 return plist; | |
2249 } | |
2250 | |
2251 DEFUN ("plist-remprop", Fplist_remprop, Splist_remprop, 2, 2, 0 /* | |
2252 Remove from PLIST the property PROP and its value. | |
2253 PLIST is a property list, which is a list of the form \(PROP1 VALUE1 | |
2254 PROP2 VALUE2 ...). PROP is usually a symbol. The new plist is | |
2255 returned; use `(setq x (plist-remprop x prop val))' to be sure to use | |
2256 the new value. The PLIST is modified by side effects. | |
2257 */ ) | |
2258 (plist, prop) | |
2259 Lisp_Object plist, prop; | |
2260 { | |
2261 external_remprop (&plist, prop, 0, ERROR_ME); | |
2262 return plist; | |
2263 } | |
2264 | |
2265 DEFUN ("plist-member", Fplist_member, Splist_member, 2, 2, 0 /* | |
2266 Return t if PROP has a value specified in PLIST. | |
2267 */ ) | |
2268 (plist, prop) | |
2269 Lisp_Object plist, prop; | |
2270 { | |
2271 return UNBOUNDP (Fplist_get (plist, prop, Qunbound)) ? Qnil : Qt; | |
2272 } | |
2273 | |
2274 DEFUN ("check-valid-plist", Fcheck_valid_plist, Scheck_valid_plist, | |
2275 1, 1, 0 /* | |
2276 Given a plist, signal an error if there is anything wrong with it. | |
2277 This means that it's a malformed or circular plist. | |
2278 */ ) | |
2279 (plist) | |
2280 Lisp_Object plist; | |
2281 { | |
2282 Lisp_Object *tortoise; | |
2283 Lisp_Object *hare; | |
2284 | |
2285 start_over: | |
2286 tortoise = &plist; | |
2287 hare = &plist; | |
2288 while (!NILP (*tortoise)) | |
2289 { | |
2290 Lisp_Object retval; | |
2291 | |
2292 /* See above */ | |
2293 if (!advance_plist_pointers (&plist, &tortoise, &hare, ERROR_ME, | |
2294 &retval)) | |
2295 goto start_over; | |
2296 } | |
2297 | |
2298 return Qnil; | |
2299 } | |
2300 | |
2301 DEFUN ("valid-plist-p", Fvalid_plist_p, Svalid_plist_p, | |
2302 1, 1, 0 /* | |
2303 Given a plist, return non-nil if its format is correct. | |
2304 If it returns nil, `check-valid-plist' will signal an error when given | |
2305 the plist; that means it's a malformed or circular plist or has non-symbols | |
2306 as keywords. | |
2307 */ ) | |
2308 (plist) | |
2309 Lisp_Object plist; | |
2310 { | |
2311 Lisp_Object *tortoise; | |
2312 Lisp_Object *hare; | |
2313 | |
2314 tortoise = &plist; | |
2315 hare = &plist; | |
2316 while (!NILP (*tortoise)) | |
2317 { | |
2318 Lisp_Object retval; | |
2319 | |
2320 /* See above */ | |
2321 if (!advance_plist_pointers (&plist, &tortoise, &hare, ERROR_ME_NOT, | |
2322 &retval)) | |
2323 return Qnil; | |
2324 } | |
2325 | |
2326 return Qt; | |
2327 } | |
2328 | |
2329 DEFUN ("canonicalize-plist", Fcanonicalize_plist, Scanonicalize_plist, | |
2330 1, 2, 0 /* | |
2331 Destructively remove any duplicate entries from a plist. | |
2332 In such cases, the first entry applies. | |
2333 | |
2334 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with | |
2335 a nil value is removed. This feature is a virus that has infected | |
2336 old Lisp implementations (and thus E-Lisp, due to RMS's enamorment with | |
2337 old Lisps), but should not be used except for backward compatibility. | |
2338 | |
2339 The new plist is returned. If NIL-MEANS-NOT-PRESENT is given, the | |
2340 return value may not be EQ to the passed-in value, so make sure to | |
2341 `setq' the value back into where it came from. | |
2342 */ ) | |
2343 (plist, nil_means_not_present) | |
2344 Lisp_Object plist, nil_means_not_present; | |
2345 { | |
2346 Lisp_Object head = plist; | |
2347 | |
2348 Fcheck_valid_plist (plist); | |
2349 | |
2350 while (!NILP (plist)) | |
2351 { | |
2352 Lisp_Object prop = Fcar (plist); | |
2353 Lisp_Object next = Fcdr (plist); | |
2354 | |
2355 CHECK_CONS (next); /* just make doubly sure we catch any errors */ | |
2356 if (!NILP (nil_means_not_present) && NILP (Fcar (next))) | |
2357 { | |
2358 if (EQ (head, plist)) | |
2359 head = Fcdr (next); | |
2360 plist = Fcdr (next); | |
2361 continue; | |
2362 } | |
2363 /* external_remprop returns 1 if it removed any property. | |
2364 We have to loop till it didn't remove anything, in case | |
2365 the property occurs many times. */ | |
2366 while (external_remprop (&XCDR (next), prop, 0, ERROR_ME)); | |
2367 plist = Fcdr (next); | |
2368 } | |
2369 | |
2370 return head; | |
2371 } | |
2372 | |
2373 DEFUN ("lax-plist-get", Flax_plist_get, Slax_plist_get, 2, 3, 0 /* | |
2374 Extract a value from a lax property list. | |
2375 | |
2376 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 | |
2377 VALUE1 PROP2 VALUE2...), where comparions between properties is done | |
2378 using `equal' instead of `eq'. This function returns the value | |
2379 corresponding to the given PROP, or DEFAULT if PROP is not one of the | |
2380 properties on the list. | |
2381 */ ) | |
2382 (lax_plist, prop, defalt) /* Cant spel in C */ | |
2383 Lisp_Object lax_plist, prop, defalt; | |
2384 { | |
2385 Lisp_Object val = external_plist_get (&lax_plist, prop, 1, ERROR_ME); | |
2386 if (UNBOUNDP (val)) | |
2387 return defalt; | |
2388 return val; | |
2389 } | |
2390 | |
2391 DEFUN ("lax-plist-put", Flax_plist_put, Slax_plist_put, 3, 3, 0 /* | |
2392 Change value in LAX-PLIST of PROP to VAL. | |
2393 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 | |
2394 VALUE1 PROP2 VALUE2...), where comparions between properties is done | |
2395 using `equal' instead of `eq'. PROP is usually a symbol and VAL is | |
2396 any object. If PROP is already a property on the list, its value is | |
2397 set to VAL, otherwise the new PROP VAL pair is added. The new plist | |
2398 is returned; use `(setq x (lax-plist-put x prop val))' to be sure to | |
2399 use the new value. The LAX-PLIST is modified by side effects. | |
2400 */ ) | |
2401 (lax_plist, prop, val) | |
2402 Lisp_Object lax_plist, prop, val; | |
2403 { | |
2404 external_plist_put (&lax_plist, prop, val, 1, ERROR_ME); | |
2405 return lax_plist; | |
2406 } | |
2407 | |
2408 DEFUN ("lax-plist-remprop", Flax_plist_remprop, Slax_plist_remprop, 2, 2, 0 /* | |
2409 Remove from LAX-PLIST the property PROP and its value. | |
2410 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 | |
2411 VALUE1 PROP2 VALUE2...), where comparions between properties is done | |
2412 using `equal' instead of `eq'. PROP is usually a symbol. The new | |
2413 plist is returned; use `(setq x (lax-plist-remprop x prop val))' to be | |
2414 sure to use the new value. The LAX-PLIST is modified by side effects. | |
2415 */ ) | |
2416 (lax_plist, prop) | |
2417 Lisp_Object lax_plist, prop; | |
2418 { | |
2419 external_remprop (&lax_plist, prop, 1, ERROR_ME); | |
2420 return lax_plist; | |
2421 } | |
2422 | |
2423 DEFUN ("lax-plist-member", Flax_plist_member, Slax_plist_member, 2, 2, 0 /* | |
2424 Return t if PROP has a value specified in LAX-PLIST. | |
2425 LAX-PLIST is a lax property list, which is a list of the form \(PROP1 | |
2426 VALUE1 PROP2 VALUE2...), where comparions between properties is done | |
2427 using `equal' instead of `eq'. | |
2428 */ ) | |
2429 (lax_plist, prop) | |
2430 Lisp_Object lax_plist, prop; | |
2431 { | |
2432 return UNBOUNDP (Flax_plist_get (lax_plist, prop, Qunbound)) ? Qnil : Qt; | |
2433 } | |
2434 | |
2435 DEFUN ("canonicalize-lax-plist", Fcanonicalize_lax_plist, | |
2436 Scanonicalize_lax_plist, 1, 2, 0 /* | |
2437 Destructively remove any duplicate entries from a lax plist. | |
2438 In such cases, the first entry applies. | |
2439 | |
2440 If optional arg NIL-MEANS-NOT-PRESENT is non-nil, then a property with | |
2441 a nil value is removed. This feature is a virus that has infected | |
2442 old Lisp implementations (and thus E-Lisp, due to RMS's enamorment with | |
2443 old Lisps), but should not be used except for backward compatibility. | |
2444 | |
2445 The new plist is returned. If NIL-MEANS-NOT-PRESENT is given, the | |
2446 return value may not be EQ to the passed-in value, so make sure to | |
2447 `setq' the value back into where it came from. | |
2448 */ ) | |
2449 (lax_plist, nil_means_not_present) | |
2450 Lisp_Object lax_plist, nil_means_not_present; | |
2451 { | |
2452 Lisp_Object head = lax_plist; | |
2453 | |
2454 Fcheck_valid_plist (lax_plist); | |
2455 | |
2456 while (!NILP (lax_plist)) | |
2457 { | |
2458 Lisp_Object prop = Fcar (lax_plist); | |
2459 Lisp_Object next = Fcdr (lax_plist); | |
2460 | |
2461 CHECK_CONS (next); /* just make doubly sure we catch any errors */ | |
2462 if (!NILP (nil_means_not_present) && NILP (Fcar (next))) | |
2463 { | |
2464 if (EQ (head, lax_plist)) | |
2465 head = Fcdr (next); | |
2466 lax_plist = Fcdr (next); | |
2467 continue; | |
2468 } | |
2469 /* external_remprop returns 1 if it removed any property. | |
2470 We have to loop till it didn't remove anything, in case | |
2471 the property occurs many times. */ | |
2472 while (external_remprop (&XCDR (next), prop, 1, ERROR_ME)); | |
2473 lax_plist = Fcdr (next); | |
2474 } | |
2475 | |
2476 return head; | |
2477 } | |
2478 | |
2479 /* In C because the frame props stuff uses it */ | |
2480 | |
2481 DEFUN ("destructive-alist-to-plist", Fdestructive_alist_to_plist, | |
2482 Sdestructive_alist_to_plist, 1, 1, 0 /* | |
2483 Convert association list ALIST into the equivalent property-list form. | |
2484 The plist is returned. This converts from | |
2485 | |
2486 \((a . 1) (b . 2) (c . 3)) | |
2487 | |
2488 into | |
2489 | |
2490 \(a 1 b 2 c 3) | |
2491 | |
2492 The original alist is destroyed in the process of constructing the plist. | |
2493 See also `alist-to-plist'. | |
2494 */ ) | |
2495 (alist) | |
2496 Lisp_Object alist; | |
2497 { | |
2498 Lisp_Object head = alist; | |
2499 while (!NILP (alist)) | |
2500 { | |
2501 /* remember the alist element. */ | |
2502 Lisp_Object el = Fcar (alist); | |
2503 | |
2504 Fsetcar (alist, Fcar (el)); | |
2505 Fsetcar (el, Fcdr (el)); | |
2506 Fsetcdr (el, Fcdr (alist)); | |
2507 Fsetcdr (alist, el); | |
2508 alist = Fcdr (Fcdr (alist)); | |
2509 } | |
2510 | |
2511 return head; | |
2512 } | |
2513 | |
2514 /* Symbol plists are directly accessible, so we need to protect against | |
2515 invalid property list structure */ | |
2516 | |
2517 static Lisp_Object | |
2518 symbol_getprop (Lisp_Object sym, Lisp_Object propname, Lisp_Object defalt) | |
2519 { | |
2520 Lisp_Object val = external_plist_get (&XSYMBOL (sym)->plist, propname, | |
2521 0, ERROR_ME); | |
2522 if (UNBOUNDP (val)) | |
2523 return defalt; | |
2524 return val; | |
2525 } | |
2526 | |
2527 static void | |
2528 symbol_putprop (Lisp_Object sym, Lisp_Object propname, Lisp_Object value) | |
2529 { | |
2530 external_plist_put (&XSYMBOL (sym)->plist, propname, value, 0, ERROR_ME); | |
2531 } | |
2532 | |
2533 static int | |
2534 symbol_remprop (Lisp_Object symbol, Lisp_Object propname) | |
2535 { | |
2536 return external_remprop (&XSYMBOL (symbol)->plist, propname, 0, ERROR_ME); | |
2537 } | |
2538 | |
2539 /* We store the string's extent info as the first element of the string's | |
2540 property list; and the string's MODIFF as the first or second element | |
2541 of the string's property list (depending on whether the extent info | |
2542 is present), but only if the string has been modified. This is ugly | |
2543 but it reduces the memory allocated for the string in the vast | |
2544 majority of cases, where the string is never modified and has no | |
2545 extent info. */ | |
2546 | |
2547 | |
2548 static Lisp_Object * | |
2549 string_plist_ptr (struct Lisp_String *s) | |
2550 { | |
2551 Lisp_Object *ptr = &s->plist; | |
2552 | |
2553 if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr))) | |
2554 ptr = &XCDR (*ptr); | |
2555 if (CONSP (*ptr) && INTP (XCAR (*ptr))) | |
2556 ptr = &XCDR (*ptr); | |
2557 return ptr; | |
2558 } | |
2559 | |
2560 Lisp_Object | |
2561 string_getprop (struct Lisp_String *s, Lisp_Object property, | |
2562 Lisp_Object defalt) | |
2563 { | |
2564 Lisp_Object val = external_plist_get (string_plist_ptr (s), property, 0, | |
2565 ERROR_ME); | |
2566 if (UNBOUNDP (val)) | |
2567 return defalt; | |
2568 return val; | |
2569 } | |
2570 | |
2571 void | |
2572 string_putprop (struct Lisp_String *s, Lisp_Object property, | |
2573 Lisp_Object value) | |
2574 { | |
2575 external_plist_put (string_plist_ptr (s), property, value, 0, ERROR_ME); | |
2576 } | |
2577 | |
2578 static int | |
2579 string_remprop (struct Lisp_String *s, Lisp_Object property) | |
2580 { | |
2581 return external_remprop (string_plist_ptr (s), property, 0, ERROR_ME); | |
2582 } | |
2583 | |
2584 static Lisp_Object | |
2585 string_plist (struct Lisp_String *s) | |
2586 { | |
2587 return *string_plist_ptr (s); | |
2588 } | |
2589 | |
2590 DEFUN ("get", Fget, Sget, 2, 3, 0 /* | |
2591 Return the value of OBJECT's PROPNAME property. | |
2592 This is the last VALUE stored with `(put OBJECT PROPNAME VALUE)'. | |
2593 If there is no such property, return optional third arg DEFAULT | |
2594 (which defaults to `nil'). OBJECT can be a symbol, face, extent, | |
2595 or string. See also `put', `remprop', and `object-plist'. | |
2596 */ ) | |
2597 (object, propname, defalt) /* Cant spel in C */ | |
2598 Lisp_Object object, propname, defalt; | |
2599 { | |
2600 Lisp_Object val; | |
2601 | |
2602 /* Various places in emacs call Fget() and expect it not to quit, | |
2603 so don't quit. */ | |
2604 | |
2605 /* It's easiest to treat symbols specially because they may not | |
2606 be an lrecord */ | |
2607 if (SYMBOLP (object)) | |
2608 val = symbol_getprop (object, propname, defalt); | |
2609 else if (STRINGP (object)) | |
2610 val = string_getprop (XSTRING (object), propname, defalt); | |
2611 else if (LRECORDP (object)) | |
2612 { | |
2613 CONST struct lrecord_implementation | |
2614 *imp = XRECORD_LHEADER (object)->implementation; | |
2615 if (imp->getprop) | |
2616 { | |
2617 val = (imp->getprop) (object, propname); | |
2618 if (UNBOUNDP (val)) | |
2619 val = defalt; | |
2620 } | |
2621 else | |
2622 goto noprops; | |
2623 } | |
2624 else | |
2625 { | |
2626 noprops: | |
2627 signal_simple_error ("Object type has no properties", object); | |
2628 } | |
2629 | |
2630 return val; | |
2631 } | |
2632 | |
2633 DEFUN ("put", Fput, Sput, 3, 3, 0 /* | |
2634 Store OBJECT's PROPNAME property with value VALUE. | |
2635 It can be retrieved with `(get OBJECT PROPNAME)'. OBJECT can be a | |
2636 symbol, face, extent, or string. | |
2637 | |
2638 For a string, no properties currently have predefined meanings. | |
2639 For the predefined properties for extents, see `set-extent-property'. | |
2640 For the predefined properties for faces, see `set-face-property'. | |
2641 | |
2642 See also `get', `remprop', and `object-plist'. | |
2643 */ ) | |
2644 (object, propname, value) | |
2645 Lisp_Object object; | |
2646 Lisp_Object propname; | |
2647 Lisp_Object value; | |
2648 { | |
2649 CHECK_SYMBOL (propname); | |
2650 CHECK_IMPURE (object); | |
2651 | |
2652 if (SYMBOLP (object)) | |
2653 symbol_putprop (object, propname, value); | |
2654 else if (STRINGP (object)) | |
2655 string_putprop (XSTRING (object), propname, value); | |
2656 else if (LRECORDP (object)) | |
2657 { | |
2658 CONST struct lrecord_implementation | |
2659 *imp = XRECORD_LHEADER (object)->implementation; | |
2660 if (imp->putprop) | |
2661 { | |
2662 if (! (imp->putprop) (object, propname, value)) | |
2663 signal_simple_error ("Can't set property on object", propname); | |
2664 } | |
2665 else | |
2666 goto noprops; | |
2667 } | |
2668 else | |
2669 { | |
2670 noprops: | |
2671 signal_simple_error ("Object type has no settable properties", object); | |
2672 } | |
2673 | |
2674 return value; | |
2675 } | |
2676 | |
2677 void | |
2678 pure_put (Lisp_Object sym, Lisp_Object prop, Lisp_Object val) | |
2679 { | |
2680 Fput (sym, prop, Fpurecopy (val)); | |
2681 } | |
2682 | |
2683 DEFUN ("remprop", Fremprop, Sremprop, 2, 2, 0 /* | |
2684 Remove from OBJECT's property list the property PROPNAME and its | |
2685 value. OBJECT can be a symbol, face, extent, or string. Returns | |
2686 non-nil if the property list was actually changed (i.e. if PROPNAME | |
2687 was present in the property list). See also `get', `put', and | |
2688 `object-plist'. | |
2689 */ ) | |
2690 (object, propname) | |
2691 Lisp_Object object, propname; | |
2692 { | |
2693 int retval = 0; | |
2694 | |
2695 CHECK_SYMBOL (propname); | |
2696 CHECK_IMPURE (object); | |
2697 | |
2698 if (SYMBOLP (object)) | |
2699 retval = symbol_remprop (object, propname); | |
2700 else if (STRINGP (object)) | |
2701 retval = string_remprop (XSTRING (object), propname); | |
2702 else if (LRECORDP (object)) | |
2703 { | |
2704 CONST struct lrecord_implementation | |
2705 *imp = XRECORD_LHEADER (object)->implementation; | |
2706 if (imp->remprop) | |
2707 { | |
2708 retval = (imp->remprop) (object, propname); | |
2709 if (retval == -1) | |
2710 signal_simple_error ("Can't remove property from object", | |
2711 propname); | |
2712 } | |
2713 else | |
2714 goto noprops; | |
2715 } | |
2716 else | |
2717 { | |
2718 noprops: | |
2719 signal_simple_error ("Object type has no removable properties", object); | |
2720 } | |
2721 | |
2722 return retval ? Qt : Qnil; | |
2723 } | |
2724 | |
2725 DEFUN ("object-plist", Fobject_plist, Sobject_plist, 1, 1, 0 /* | |
2726 Return a property list of OBJECT's props. | |
2727 For a symbol this is equivalent to `symbol-plist'. | |
2728 Do not modify the property list directly; this may or may not have | |
2729 the desired effects. (In particular, for a property with a special | |
2730 interpretation, this will probably have no effect at all.) | |
2731 */ ) | |
2732 (object) | |
2733 Lisp_Object object; | |
2734 { | |
2735 if (SYMBOLP (object)) | |
2736 return Fsymbol_plist (object); | |
2737 else if (STRINGP (object)) | |
2738 return string_plist (XSTRING (object)); | |
2739 else if (LRECORDP (object)) | |
2740 { | |
2741 CONST struct lrecord_implementation | |
2742 *imp = XRECORD_LHEADER (object)->implementation; | |
2743 if (imp->plist) | |
2744 return (imp->plist) (object); | |
2745 else | |
2746 signal_simple_error ("Object type has no properties", object); | |
2747 } | |
2748 else | |
2749 signal_simple_error ("Object type has no properties", object); | |
2750 | |
2751 return Qnil; | |
2752 } | |
2753 | |
2754 | |
2755 int | |
2756 internal_equal (Lisp_Object o1, Lisp_Object o2, int depth) | |
2757 { | |
2758 if (depth > 200) | |
2759 error ("Stack overflow in equal"); | |
2760 do_cdr: | |
2761 QUIT; | |
2762 if (HACKEQ_UNSAFE (o1, o2)) | |
2763 return (1); | |
2764 /* Note that (equal 20 20.0) should be nil */ | |
2765 else if (XTYPE (o1) != XTYPE (o2)) | |
2766 return (0); | |
2767 else if (CONSP (o1)) | |
2768 { | |
2769 if (!internal_equal (Fcar (o1), Fcar (o2), depth + 1)) | |
2770 return (0); | |
2771 o1 = Fcdr (o1); | |
2772 o2 = Fcdr (o2); | |
2773 goto do_cdr; | |
2774 } | |
2775 | |
2776 #ifndef LRECORD_VECTOR | |
2777 else if (VECTORP (o1)) | |
2778 { | |
2779 int indecks; | |
2780 int len = vector_length (XVECTOR (o1)); | |
2781 if (len != vector_length (XVECTOR (o2))) | |
2782 return (0); | |
2783 for (indecks = 0; indecks < len; indecks++) | |
2784 { | |
2785 Lisp_Object v1, v2; | |
2786 v1 = vector_data (XVECTOR (o1)) [indecks]; | |
2787 v2 = vector_data (XVECTOR (o2)) [indecks]; | |
2788 if (!internal_equal (v1, v2, depth + 1)) | |
2789 return (0); | |
2790 } | |
2791 return (1); | |
2792 } | |
2793 #endif /* !LRECORD_VECTOR */ | |
2794 else if (STRINGP (o1)) | |
2795 { | |
2796 Bytecount len = string_length (XSTRING (o1)); | |
2797 if (len != string_length (XSTRING (o2))) | |
2798 return (0); | |
2799 if (memcmp (string_data (XSTRING (o1)), string_data (XSTRING (o2)), len)) | |
2800 return (0); | |
2801 return (1); | |
2802 } | |
2803 else if (LRECORDP (o1)) | |
2804 { | |
2805 CONST struct lrecord_implementation | |
2806 *imp1 = XRECORD_LHEADER (o1)->implementation, | |
2807 *imp2 = XRECORD_LHEADER (o2)->implementation; | |
2808 if (imp1 != imp2) | |
2809 return (0); | |
2810 else if (imp1->equal == 0) | |
2811 /* EQ-ness of the objects was noticed above */ | |
2812 return (0); | |
2813 else | |
2814 return ((imp1->equal) (o1, o2, depth)); | |
2815 } | |
2816 | |
2817 return (0); | |
2818 } | |
2819 | |
2820 DEFUN ("equal", Fequal, Sequal, 2, 2, 0 /* | |
2821 T if two Lisp objects have similar structure and contents. | |
2822 They must have the same data type. | |
2823 Conses are compared by comparing the cars and the cdrs. | |
2824 Vectors and strings are compared element by element. | |
2825 Numbers are compared by value. Symbols must match exactly. | |
2826 */ ) | |
2827 (o1, o2) | |
2828 Lisp_Object o1, o2; | |
2829 { | |
2830 return ((internal_equal (o1, o2, 0)) ? Qt : Qnil); | |
2831 } | |
2832 | |
2833 | |
2834 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0 /* | |
2835 Store each element of ARRAY with ITEM. | |
2836 ARRAY is a vector, bit vector, or string. | |
2837 */ ) | |
2838 (array, item) | |
2839 Lisp_Object array, item; | |
2840 { | |
2841 retry: | |
2842 if (VECTORP (array)) | |
2843 { | |
2844 Lisp_Object *p; | |
2845 int size; | |
2846 int indecks; | |
2847 CHECK_IMPURE (array); | |
2848 size = vector_length (XVECTOR (array)); | |
2849 p = vector_data (XVECTOR (array)); | |
2850 for (indecks = 0; indecks < size; indecks++) | |
2851 p[indecks] = item; | |
2852 } | |
2853 else if (VECTORP (array)) | |
2854 { | |
2855 struct Lisp_Bit_Vector *v; | |
2856 int size; | |
2857 int indecks; | |
2858 | |
2859 CHECK_BIT (item); | |
2860 CHECK_IMPURE (array); | |
2861 v = XBIT_VECTOR (array); | |
2862 size = bit_vector_length (v); | |
2863 for (indecks = 0; indecks < size; indecks++) | |
2864 set_bit_vector_bit (v, indecks, XINT (item)); | |
2865 } | |
2866 else if (STRINGP (array)) | |
2867 { | |
2868 Charcount size; | |
2869 Charcount indecks; | |
2870 Emchar charval; | |
2871 CHECK_CHAR_COERCE_INT (item); | |
2872 CHECK_IMPURE (array); | |
2873 charval = XCHAR (item); | |
2874 size = string_char_length (XSTRING (array)); | |
2875 for (indecks = 0; indecks < size; indecks++) | |
2876 set_string_char (XSTRING (array), indecks, charval); | |
2877 bump_string_modiff (array); | |
2878 } | |
2879 else | |
2880 { | |
2881 array = wrong_type_argument (Qarrayp, array); | |
2882 goto retry; | |
2883 } | |
2884 return array; | |
2885 } | |
2886 | |
2887 Lisp_Object | |
2888 nconc2 (Lisp_Object s1, Lisp_Object s2) | |
2889 { | |
2890 Lisp_Object args[2]; | |
2891 args[0] = s1; | |
2892 args[1] = s2; | |
2893 return Fnconc (2, args); | |
2894 } | |
2895 | |
2896 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0 /* | |
2897 Concatenate any number of lists by altering them. | |
2898 Only the last argument is not altered, and need not be a list. | |
2899 */ ) | |
2900 (nargs, args) | |
2901 int nargs; | |
2902 Lisp_Object *args; | |
2903 { | |
2904 int argnum; | |
2905 Lisp_Object tail, tem, val; | |
2906 struct gcpro gcpro1; | |
2907 | |
2908 /* The modus operandi in Emacs is "caller gc-protects args". | |
2909 However, nconc (particularly nconc2 ()) is called many times | |
2910 in Emacs on freshly created stuff (e.g. you see the idiom | |
2911 nconc2 (Fcopy_sequence (foo), bar) a lot). So we help those | |
2912 callers out by protecting the args ourselves to save them | |
2913 a lot of temporary-variable grief. */ | |
2914 | |
2915 GCPRO1 (args[0]); | |
2916 gcpro1.nvars = nargs; | |
2917 | |
2918 val = Qnil; | |
2919 | |
2920 for (argnum = 0; argnum < nargs; argnum++) | |
2921 { | |
2922 tem = args[argnum]; | |
2923 if (NILP (tem)) continue; | |
2924 | |
2925 if (NILP (val)) | |
2926 val = tem; | |
2927 | |
2928 if (argnum + 1 == nargs) break; | |
2929 | |
2930 if (!CONSP (tem)) | |
2931 tem = wrong_type_argument (Qlistp, tem); | |
2932 | |
2933 while (CONSP (tem)) | |
2934 { | |
2935 tail = tem; | |
2936 tem = Fcdr (tail); | |
2937 QUIT; | |
2938 } | |
2939 | |
2940 tem = args[argnum + 1]; | |
2941 Fsetcdr (tail, tem); | |
2942 if (NILP (tem)) | |
2943 args[argnum + 1] = tail; | |
2944 } | |
2945 | |
2946 RETURN_UNGCPRO (val); | |
2947 } | |
2948 | |
2949 | |
2950 /* This is the guts of all mapping functions. | |
2951 Apply fn to each element of seq, one by one, | |
2952 storing the results into elements of vals, a C vector of Lisp_Objects. | |
2953 leni is the length of vals, which should also be the length of seq. | |
2954 | |
2955 If VALS is a null pointer, do not accumulate the results. */ | |
2956 | |
2957 static void | |
2958 mapcar1 (int leni, Lisp_Object *vals, Lisp_Object fn, Lisp_Object seq) | |
2959 { | |
2960 Lisp_Object tail; | |
2961 Lisp_Object dummy = Qnil; | |
2962 int i; | |
2963 struct gcpro gcpro1, gcpro2, gcpro3; | |
2964 Lisp_Object result; | |
2965 | |
2966 GCPRO3 (dummy, fn, seq); | |
2967 | |
2968 if (vals) | |
2969 { | |
2970 /* Don't let vals contain any garbage when GC happens. */ | |
2971 for (i = 0; i < leni; i++) | |
2972 vals[i] = Qnil; | |
2973 gcpro1.var = vals; | |
2974 gcpro1.nvars = leni; | |
2975 } | |
2976 | |
2977 /* We need not explicitly protect `tail' because it is used only on | |
2978 lists, and 1) lists are not relocated and 2) the list is marked | |
2979 via `seq' so will not be freed */ | |
2980 | |
2981 if (VECTORP (seq)) | |
2982 { | |
2983 for (i = 0; i < leni; i++) | |
2984 { | |
2985 dummy = vector_data (XVECTOR (seq))[i]; | |
2986 result = call1 (fn, dummy); | |
2987 if (vals) | |
2988 vals[i] = result; | |
2989 } | |
2990 } | |
2991 else if (BIT_VECTORP (seq)) | |
2992 { | |
2993 struct Lisp_Bit_Vector *v = XBIT_VECTOR (seq); | |
2994 for (i = 0; i < leni; i++) | |
2995 { | |
2996 XSETINT (dummy, bit_vector_bit (v, i)); | |
2997 result = call1 (fn, dummy); | |
2998 if (vals) | |
2999 vals[i] = result; | |
3000 } | |
3001 } | |
3002 else if (STRINGP (seq)) | |
3003 { | |
3004 for (i = 0; i < leni; i++) | |
3005 { | |
3006 result = call1 (fn, make_char (string_char (XSTRING (seq), i))); | |
3007 if (vals) | |
3008 vals[i] = result; | |
3009 } | |
3010 } | |
3011 else /* Must be a list, since Flength did not get an error */ | |
3012 { | |
3013 tail = seq; | |
3014 for (i = 0; i < leni; i++) | |
3015 { | |
3016 result = call1 (fn, Fcar (tail)); | |
3017 if (vals) | |
3018 vals[i] = result; | |
3019 tail = Fcdr (tail); | |
3020 } | |
3021 } | |
3022 | |
3023 UNGCPRO; | |
3024 } | |
3025 | |
3026 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0 /* | |
3027 Apply FN to each element of SEQ, and concat the results as strings. | |
3028 In between each pair of results, stick in SEP. | |
3029 Thus, \" \" as SEP results in spaces between the values returned by FN. | |
3030 */ ) | |
3031 (fn, seq, sep) | |
3032 Lisp_Object fn, seq, sep; | |
3033 { | |
3034 Lisp_Object len; | |
3035 int leni; | |
3036 int nargs; | |
3037 Lisp_Object *args; | |
3038 int i; | |
3039 struct gcpro gcpro1; | |
3040 | |
3041 len = Flength (seq); | |
3042 leni = XINT (len); | |
3043 nargs = leni + leni - 1; | |
3044 if (nargs < 0) return build_string (""); | |
3045 | |
3046 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object)); | |
3047 | |
3048 GCPRO1 (sep); | |
3049 mapcar1 (leni, args, fn, seq); | |
3050 UNGCPRO; | |
3051 | |
3052 for (i = leni - 1; i >= 0; i--) | |
3053 args[i + i] = args[i]; | |
3054 | |
3055 for (i = 1; i < nargs; i += 2) | |
3056 args[i] = sep; | |
3057 | |
3058 return Fconcat (nargs, args); | |
3059 } | |
3060 | |
3061 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0 /* | |
3062 Apply FUNCTION to each element of SEQUENCE, and make a list of the results. | |
3063 The result is a list just as long as SEQUENCE. | |
3064 SEQUENCE may be a list, a vector, a bit vector, or a string. | |
3065 */ ) | |
3066 (fn, seq) | |
3067 Lisp_Object fn, seq; | |
3068 { | |
3069 Lisp_Object len; | |
3070 int leni; | |
3071 Lisp_Object *args; | |
3072 | |
3073 len = Flength (seq); | |
3074 leni = XINT (len); | |
3075 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object)); | |
3076 | |
3077 mapcar1 (leni, args, fn, seq); | |
3078 | |
3079 return Flist (leni, args); | |
3080 } | |
3081 | |
3082 DEFUN ("mapc-internal", Fmapc_internal, Smapc_internal, 2, 2, 0 /* | |
3083 Apply FUNCTION to each element of SEQUENCE. | |
3084 SEQUENCE may be a list, a vector, a bit vector, or a string. | |
3085 This function is like `mapcar' but does not accumulate the results, | |
3086 which is more efficient if you do not use the results. | |
3087 */ ) | |
3088 (fn, seq) | |
3089 Lisp_Object fn, seq; | |
3090 { | |
3091 Lisp_Object len; | |
3092 int leni; | |
3093 | |
3094 len = Flength (seq); | |
3095 leni = XINT (len); | |
3096 | |
3097 mapcar1 (leni, 0, fn, seq); | |
3098 | |
3099 return Qnil; | |
3100 } | |
3101 | |
3102 | |
3103 /* #### this function doesn't belong in this file! */ | |
3104 | |
3105 DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0 /* | |
3106 Return list of 1 minute, 5 minute and 15 minute load averages. | |
3107 Each of the three load averages is multiplied by 100, | |
3108 then converted to integer. | |
3109 | |
3110 If the 5-minute or 15-minute load averages are not available, return a | |
3111 shortened list, containing only those averages which are available. | |
3112 | |
3113 On most systems, this won't work unless the emacs executable is installed | |
3114 as setgid kmem (assuming that /dev/kmem is in the group kmem). | |
3115 */ ) | |
3116 () | |
3117 { | |
3118 double load_ave[10]; /* hey, just in case */ | |
3119 int loads = getloadavg (load_ave, 3); | |
3120 Lisp_Object ret; | |
3121 | |
3122 if (loads == -2) | |
3123 error ("load-average not implemented for this operating system."); | |
3124 else if (loads < 0) | |
3125 error ("could not get load-average; check permissions."); | |
3126 | |
3127 ret = Qnil; | |
3128 while (loads > 0) | |
3129 ret = Fcons (make_int ((int) (load_ave[--loads] * 100.0)), ret); | |
3130 | |
3131 return ret; | |
3132 } | |
3133 | |
3134 | |
3135 Lisp_Object Vfeatures; | |
3136 | |
3137 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0 /* | |
3138 Return t if FEATURE is present in this Emacs. | |
3139 Use this to conditionalize execution of lisp code based on the presence or | |
3140 absence of emacs or environment extensions. | |
3141 Use `provide' to declare that a feature is available. | |
3142 This function looks at the value of the variable `features'. | |
3143 */ ) | |
3144 (feature) | |
3145 Lisp_Object feature; | |
3146 { | |
3147 Lisp_Object tem; | |
3148 CHECK_SYMBOL (feature); | |
3149 tem = Fmemq (feature, Vfeatures); | |
3150 return (NILP (tem)) ? Qnil : Qt; | |
3151 } | |
3152 | |
3153 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0 /* | |
3154 Announce that FEATURE is a feature of the current Emacs. | |
3155 */ ) | |
3156 (feature) | |
3157 Lisp_Object feature; | |
3158 { | |
3159 Lisp_Object tem; | |
3160 CHECK_SYMBOL (feature); | |
3161 if (!NILP (Vautoload_queue)) | |
3162 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue); | |
3163 tem = Fmemq (feature, Vfeatures); | |
3164 if (NILP (tem)) | |
3165 Vfeatures = Fcons (feature, Vfeatures); | |
3166 LOADHIST_ATTACH (Fcons (Qprovide, feature)); | |
3167 return feature; | |
3168 } | |
3169 | |
3170 DEFUN ("require", Frequire, Srequire, 1, 2, 0 /* | |
3171 If feature FEATURE is not loaded, load it from FILENAME. | |
3172 If FEATURE is not a member of the list `features', then the feature | |
3173 is not loaded; so load the file FILENAME. | |
3174 If FILENAME is omitted, the printname of FEATURE is used as the file name. | |
3175 */ ) | |
3176 (feature, file_name) | |
3177 Lisp_Object feature, file_name; | |
3178 { | |
3179 Lisp_Object tem; | |
3180 CHECK_SYMBOL (feature); | |
3181 tem = Fmemq (feature, Vfeatures); | |
3182 LOADHIST_ATTACH (Fcons (Qrequire, feature)); | |
3183 if (!NILP (tem)) | |
3184 return (feature); | |
3185 else | |
3186 { | |
3187 int speccount = specpdl_depth (); | |
3188 | |
3189 /* Value saved here is to be restored into Vautoload_queue */ | |
3190 record_unwind_protect (un_autoload, Vautoload_queue); | |
3191 Vautoload_queue = Qt; | |
3192 | |
3193 call4 (Qload, NILP (file_name) ? Fsymbol_name (feature) : file_name, | |
3194 Qnil, Qt, Qnil); | |
3195 | |
3196 tem = Fmemq (feature, Vfeatures); | |
3197 if (NILP (tem)) | |
3198 error ("Required feature %s was not provided", | |
3199 string_data (XSYMBOL (feature)->name)); | |
3200 | |
3201 /* Once loading finishes, don't undo it. */ | |
3202 Vautoload_queue = Qt; | |
3203 return (unbind_to (speccount, feature)); | |
3204 } | |
3205 } | |
3206 | |
3207 | |
3208 Lisp_Object Qyes_or_no_p; | |
3209 | |
3210 void | |
3211 syms_of_fns (void) | |
3212 { | |
3213 defsymbol (&Qstring_lessp, "string-lessp"); | |
3214 defsymbol (&Qidentity, "identity"); | |
3215 defsymbol (&Qyes_or_no_p, "yes-or-no-p"); | |
3216 | |
3217 defsubr (&Sidentity); | |
3218 defsubr (&Srandom); | |
3219 defsubr (&Slength); | |
3220 defsubr (&Ssafe_length); | |
3221 defsubr (&Sstring_equal); | |
3222 defsubr (&Sstring_lessp); | |
3223 defsubr (&Sstring_modified_tick); | |
3224 defsubr (&Sappend); | |
3225 defsubr (&Sconcat); | |
3226 defsubr (&Svconcat); | |
3227 defsubr (&Sbvconcat); | |
3228 defsubr (&Scopy_sequence); | |
3229 defsubr (&Scopy_alist); | |
3230 defsubr (&Scopy_tree); | |
3231 defsubr (&Ssubstring); | |
3232 defsubr (&Ssubseq); | |
3233 defsubr (&Snthcdr); | |
3234 defsubr (&Snth); | |
3235 defsubr (&Selt); | |
3236 defsubr (&Smember); | |
3237 defsubr (&Smemq); | |
3238 defsubr (&Sassoc); | |
3239 defsubr (&Sassq); | |
3240 defsubr (&Srassoc); | |
3241 defsubr (&Srassq); | |
3242 defsubr (&Sdelete); | |
3243 defsubr (&Sdelq); | |
3244 defsubr (&Sremassoc); | |
3245 defsubr (&Sremassq); | |
3246 defsubr (&Sremrassoc); | |
3247 defsubr (&Sremrassq); | |
3248 defsubr (&Snreverse); | |
3249 defsubr (&Sreverse); | |
3250 defsubr (&Ssort); | |
3251 defsubr (&Splists_eq); | |
3252 defsubr (&Splists_equal); | |
3253 defsubr (&Slax_plists_eq); | |
3254 defsubr (&Slax_plists_equal); | |
3255 defsubr (&Splist_get); | |
3256 defsubr (&Splist_put); | |
3257 defsubr (&Splist_remprop); | |
3258 defsubr (&Splist_member); | |
3259 defsubr (&Scheck_valid_plist); | |
3260 defsubr (&Svalid_plist_p); | |
3261 defsubr (&Scanonicalize_plist); | |
3262 defsubr (&Slax_plist_get); | |
3263 defsubr (&Slax_plist_put); | |
3264 defsubr (&Slax_plist_remprop); | |
3265 defsubr (&Slax_plist_member); | |
3266 defsubr (&Scanonicalize_lax_plist); | |
3267 defsubr (&Sdestructive_alist_to_plist); | |
3268 defsubr (&Sget); | |
3269 defsubr (&Sput); | |
3270 defsubr (&Sremprop); | |
3271 defsubr (&Sobject_plist); | |
3272 defsubr (&Sequal); | |
3273 defsubr (&Sfillarray); | |
3274 defsubr (&Snconc); | |
3275 defsubr (&Smapcar); | |
3276 defsubr (&Smapc_internal); | |
3277 defsubr (&Smapconcat); | |
3278 defsubr (&Sload_average); | |
3279 defsubr (&Sfeaturep); | |
3280 defsubr (&Srequire); | |
3281 defsubr (&Sprovide); | |
3282 } | |
3283 | |
3284 void | |
3285 init_provide_once (void) | |
3286 { | |
3287 DEFVAR_LISP ("features", &Vfeatures /* | |
3288 A list of symbols which are the features of the executing emacs. | |
3289 Used by `featurep' and `require', and altered by `provide'. | |
3290 */ ); | |
3291 Vfeatures = Qnil; | |
3292 } |