Update FSF's address in the preamble.
[bpt/emacs.git] / src / fns.c
1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
23
24 /* Note on some machines this defines `vector' as a typedef,
25 so make sure we don't use that name in this file. */
26 #undef vector
27 #define vector *****
28
29 #include "lisp.h"
30 #include "commands.h"
31
32 #include "buffer.h"
33 #include "keyboard.h"
34 #include "intervals.h"
35
36 #ifndef NULL
37 #define NULL (void *)0
38 #endif
39
40 extern Lisp_Object Flookup_key ();
41
42 Lisp_Object Qstring_lessp, Qprovide, Qrequire;
43 Lisp_Object Qyes_or_no_p_history;
44
45 static int internal_equal ();
46 \f
47 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
48 "Return the argument unchanged.")
49 (arg)
50 Lisp_Object arg;
51 {
52 return arg;
53 }
54
55 extern long get_random ();
56 extern void seed_random ();
57 extern long time ();
58
59 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
60 "Return a pseudo-random number.\n\
61 All integers representable in Lisp are equally likely.\n\
62 On most systems, this is 28 bits' worth.\n\
63 With positive integer argument N, return random number in interval [0,N).\n\
64 With argument t, set the random number seed from the current time and pid.")
65 (n)
66 Lisp_Object n;
67 {
68 EMACS_INT val;
69 Lisp_Object lispy_val;
70 unsigned long denominator;
71
72 if (EQ (n, Qt))
73 seed_random (getpid () + time (NULL));
74 if (NATNUMP (n) && XFASTINT (n) != 0)
75 {
76 /* Try to take our random number from the higher bits of VAL,
77 not the lower, since (says Gentzel) the low bits of `random'
78 are less random than the higher ones. We do this by using the
79 quotient rather than the remainder. At the high end of the RNG
80 it's possible to get a quotient larger than n; discarding
81 these values eliminates the bias that would otherwise appear
82 when using a large n. */
83 denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
84 do
85 val = get_random () / denominator;
86 while (val >= XFASTINT (n));
87 }
88 else
89 val = get_random ();
90 XSETINT (lispy_val, val);
91 return lispy_val;
92 }
93 \f
94 /* Random data-structure functions */
95
96 DEFUN ("length", Flength, Slength, 1, 1, 0,
97 "Return the length of vector, list or string SEQUENCE.\n\
98 A byte-code function object is also allowed.")
99 (sequence)
100 register Lisp_Object sequence;
101 {
102 register Lisp_Object tail, val;
103 register int i;
104
105 retry:
106 if (STRINGP (sequence))
107 XSETFASTINT (val, XSTRING (sequence)->size);
108 else if (VECTORP (sequence))
109 XSETFASTINT (val, XVECTOR (sequence)->size);
110 else if (CHAR_TABLE_P (sequence))
111 XSETFASTINT (val, CHAR_TABLE_ORDINARY_SLOTS);
112 else if (BOOL_VECTOR_P (sequence))
113 XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
114 else if (COMPILEDP (sequence))
115 XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
116 else if (CONSP (sequence))
117 {
118 for (i = 0, tail = sequence; !NILP (tail); i++)
119 {
120 QUIT;
121 tail = Fcdr (tail);
122 }
123
124 XSETFASTINT (val, i);
125 }
126 else if (NILP (sequence))
127 XSETFASTINT (val, 0);
128 else
129 {
130 sequence = wrong_type_argument (Qsequencep, sequence);
131 goto retry;
132 }
133 return val;
134 }
135
136 /* This does not check for quits. That is safe
137 since it must terminate. */
138
139 DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
140 "Return the length of a list, but avoid error or infinite loop.\n\
141 This function never gets an error. If LIST is not really a list,\n\
142 it returns 0. If LIST is circular, it returns a finite value\n\
143 which is at least the number of distinct elements.")
144 (list)
145 Lisp_Object list;
146 {
147 Lisp_Object tail, halftail, length;
148 int len = 0;
149
150 /* halftail is used to detect circular lists. */
151 halftail = list;
152 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
153 {
154 if (EQ (tail, halftail) && len != 0)
155 break;
156 len++;
157 if ((len & 1) == 0)
158 halftail = XCONS (halftail)->cdr;
159 }
160
161 XSETINT (length, len);
162 return length;
163 }
164
165 DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
166 "T if two strings have identical contents.\n\
167 Case is significant, but text properties are ignored.\n\
168 Symbols are also allowed; their print names are used instead.")
169 (s1, s2)
170 register Lisp_Object s1, s2;
171 {
172 if (SYMBOLP (s1))
173 XSETSTRING (s1, XSYMBOL (s1)->name);
174 if (SYMBOLP (s2))
175 XSETSTRING (s2, XSYMBOL (s2)->name);
176 CHECK_STRING (s1, 0);
177 CHECK_STRING (s2, 1);
178
179 if (XSTRING (s1)->size != XSTRING (s2)->size ||
180 bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size))
181 return Qnil;
182 return Qt;
183 }
184
185 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
186 "T if first arg string is less than second in lexicographic order.\n\
187 Case is significant.\n\
188 Symbols are also allowed; their print names are used instead.")
189 (s1, s2)
190 register Lisp_Object s1, s2;
191 {
192 register int i;
193 register unsigned char *p1, *p2;
194 register int end;
195
196 if (SYMBOLP (s1))
197 XSETSTRING (s1, XSYMBOL (s1)->name);
198 if (SYMBOLP (s2))
199 XSETSTRING (s2, XSYMBOL (s2)->name);
200 CHECK_STRING (s1, 0);
201 CHECK_STRING (s2, 1);
202
203 p1 = XSTRING (s1)->data;
204 p2 = XSTRING (s2)->data;
205 end = XSTRING (s1)->size;
206 if (end > XSTRING (s2)->size)
207 end = XSTRING (s2)->size;
208
209 for (i = 0; i < end; i++)
210 {
211 if (p1[i] != p2[i])
212 return p1[i] < p2[i] ? Qt : Qnil;
213 }
214 return i < XSTRING (s2)->size ? Qt : Qnil;
215 }
216 \f
217 static Lisp_Object concat ();
218
219 /* ARGSUSED */
220 Lisp_Object
221 concat2 (s1, s2)
222 Lisp_Object s1, s2;
223 {
224 #ifdef NO_ARG_ARRAY
225 Lisp_Object args[2];
226 args[0] = s1;
227 args[1] = s2;
228 return concat (2, args, Lisp_String, 0);
229 #else
230 return concat (2, &s1, Lisp_String, 0);
231 #endif /* NO_ARG_ARRAY */
232 }
233
234 /* ARGSUSED */
235 Lisp_Object
236 concat3 (s1, s2, s3)
237 Lisp_Object s1, s2, s3;
238 {
239 #ifdef NO_ARG_ARRAY
240 Lisp_Object args[3];
241 args[0] = s1;
242 args[1] = s2;
243 args[2] = s3;
244 return concat (3, args, Lisp_String, 0);
245 #else
246 return concat (3, &s1, Lisp_String, 0);
247 #endif /* NO_ARG_ARRAY */
248 }
249
250 DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
251 "Concatenate all the arguments and make the result a list.\n\
252 The result is a list whose elements are the elements of all the arguments.\n\
253 Each argument may be a list, vector or string.\n\
254 The last argument is not copied, just used as the tail of the new list.")
255 (nargs, args)
256 int nargs;
257 Lisp_Object *args;
258 {
259 return concat (nargs, args, Lisp_Cons, 1);
260 }
261
262 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
263 "Concatenate all the arguments and make the result a string.\n\
264 The result is a string whose elements are the elements of all the arguments.\n\
265 Each argument may be a string or a list or vector of characters (integers).\n\
266 \n\
267 Do not use individual integers as arguments!\n\
268 The behavior of `concat' in that case will be changed later!\n\
269 If your program passes an integer as an argument to `concat',\n\
270 you should change it right away not to do so.")
271 (nargs, args)
272 int nargs;
273 Lisp_Object *args;
274 {
275 return concat (nargs, args, Lisp_String, 0);
276 }
277
278 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
279 "Concatenate all the arguments and make the result a vector.\n\
280 The result is a vector whose elements are the elements of all the arguments.\n\
281 Each argument may be a list, vector or string.")
282 (nargs, args)
283 int nargs;
284 Lisp_Object *args;
285 {
286 return concat (nargs, args, Lisp_Vectorlike, 0);
287 }
288
289 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
290 "Return a copy of a list, vector or string.\n\
291 The elements of a list or vector are not copied; they are shared\n\
292 with the original.")
293 (arg)
294 Lisp_Object arg;
295 {
296 if (NILP (arg)) return arg;
297
298 if (CHAR_TABLE_P (arg))
299 {
300 int i, size;
301 Lisp_Object copy;
302
303 /* Calculate the number of extra slots. */
304 size = CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (arg));
305 copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
306 /* Copy all the slots, including the extra ones. */
307 bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
308 (XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK) * sizeof (Lisp_Object));
309
310 /* Recursively copy any char-tables in the ordinary slots. */
311 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
312 if (CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
313 XCHAR_TABLE (copy)->contents[i]
314 = Fcopy_sequence (XCHAR_TABLE (copy)->contents[i]);
315
316 return copy;
317 }
318
319 if (BOOL_VECTOR_P (arg))
320 {
321 Lisp_Object val;
322 int size_in_chars
323 = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
324
325 val = Fmake_bool_vector (Flength (arg), Qnil);
326 bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
327 size_in_chars);
328 return val;
329 }
330
331 if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
332 arg = wrong_type_argument (Qsequencep, arg);
333 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
334 }
335
336 static Lisp_Object
337 concat (nargs, args, target_type, last_special)
338 int nargs;
339 Lisp_Object *args;
340 enum Lisp_Type target_type;
341 int last_special;
342 {
343 Lisp_Object val;
344 Lisp_Object len;
345 register Lisp_Object tail;
346 register Lisp_Object this;
347 int toindex;
348 register int leni;
349 register int argnum;
350 Lisp_Object last_tail;
351 Lisp_Object prev;
352
353 /* In append, the last arg isn't treated like the others */
354 if (last_special && nargs > 0)
355 {
356 nargs--;
357 last_tail = args[nargs];
358 }
359 else
360 last_tail = Qnil;
361
362 for (argnum = 0; argnum < nargs; argnum++)
363 {
364 this = args[argnum];
365 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
366 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
367 {
368 if (INTEGERP (this))
369 args[argnum] = Fnumber_to_string (this);
370 else
371 args[argnum] = wrong_type_argument (Qsequencep, this);
372 }
373 }
374
375 for (argnum = 0, leni = 0; argnum < nargs; argnum++)
376 {
377 this = args[argnum];
378 len = Flength (this);
379 leni += XFASTINT (len);
380 }
381
382 XSETFASTINT (len, leni);
383
384 if (target_type == Lisp_Cons)
385 val = Fmake_list (len, Qnil);
386 else if (target_type == Lisp_Vectorlike)
387 val = Fmake_vector (len, Qnil);
388 else
389 val = Fmake_string (len, len);
390
391 /* In append, if all but last arg are nil, return last arg */
392 if (target_type == Lisp_Cons && EQ (val, Qnil))
393 return last_tail;
394
395 if (CONSP (val))
396 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
397 else
398 toindex = 0;
399
400 prev = Qnil;
401
402 for (argnum = 0; argnum < nargs; argnum++)
403 {
404 Lisp_Object thislen;
405 int thisleni;
406 register int thisindex = 0;
407
408 this = args[argnum];
409 if (!CONSP (this))
410 thislen = Flength (this), thisleni = XINT (thislen);
411
412 if (STRINGP (this) && STRINGP (val)
413 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
414 {
415 copy_text_properties (make_number (0), thislen, this,
416 make_number (toindex), val, Qnil);
417 }
418
419 while (1)
420 {
421 register Lisp_Object elt;
422
423 /* Fetch next element of `this' arg into `elt', or break if
424 `this' is exhausted. */
425 if (NILP (this)) break;
426 if (CONSP (this))
427 elt = Fcar (this), this = Fcdr (this);
428 else
429 {
430 if (thisindex >= thisleni) break;
431 if (STRINGP (this))
432 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
433 else if (BOOL_VECTOR_P (this))
434 {
435 int size_in_chars
436 = ((XBOOL_VECTOR (this)->size + BITS_PER_CHAR)
437 / BITS_PER_CHAR);
438 int byte;
439 byte = XBOOL_VECTOR (val)->data[thisindex / BITS_PER_CHAR];
440 if (byte & (1 << thisindex))
441 elt = Qt;
442 else
443 elt = Qnil;
444 }
445 else
446 elt = XVECTOR (this)->contents[thisindex++];
447 }
448
449 /* Store into result */
450 if (toindex < 0)
451 {
452 XCONS (tail)->car = elt;
453 prev = tail;
454 tail = XCONS (tail)->cdr;
455 }
456 else if (VECTORP (val))
457 XVECTOR (val)->contents[toindex++] = elt;
458 else
459 {
460 while (!INTEGERP (elt))
461 elt = wrong_type_argument (Qintegerp, elt);
462 {
463 #ifdef MASSC_REGISTER_BUG
464 /* Even removing all "register"s doesn't disable this bug!
465 Nothing simpler than this seems to work. */
466 unsigned char *p = & XSTRING (val)->data[toindex++];
467 *p = XINT (elt);
468 #else
469 XSTRING (val)->data[toindex++] = XINT (elt);
470 #endif
471 }
472 }
473 }
474 }
475 if (!NILP (prev))
476 XCONS (prev)->cdr = last_tail;
477
478 return val;
479 }
480 \f
481 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
482 "Return a copy of ALIST.\n\
483 This is an alist which represents the same mapping from objects to objects,\n\
484 but does not share the alist structure with ALIST.\n\
485 The objects mapped (cars and cdrs of elements of the alist)\n\
486 are shared, however.\n\
487 Elements of ALIST that are not conses are also shared.")
488 (alist)
489 Lisp_Object alist;
490 {
491 register Lisp_Object tem;
492
493 CHECK_LIST (alist, 0);
494 if (NILP (alist))
495 return alist;
496 alist = concat (1, &alist, Lisp_Cons, 0);
497 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
498 {
499 register Lisp_Object car;
500 car = XCONS (tem)->car;
501
502 if (CONSP (car))
503 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
504 }
505 return alist;
506 }
507
508 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
509 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
510 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
511 If FROM or TO is negative, it counts from the end.")
512 (string, from, to)
513 Lisp_Object string;
514 register Lisp_Object from, to;
515 {
516 Lisp_Object res;
517
518 CHECK_STRING (string, 0);
519 CHECK_NUMBER (from, 1);
520 if (NILP (to))
521 to = Flength (string);
522 else
523 CHECK_NUMBER (to, 2);
524
525 if (XINT (from) < 0)
526 XSETINT (from, XINT (from) + XSTRING (string)->size);
527 if (XINT (to) < 0)
528 XSETINT (to, XINT (to) + XSTRING (string)->size);
529 if (!(0 <= XINT (from) && XINT (from) <= XINT (to)
530 && XINT (to) <= XSTRING (string)->size))
531 args_out_of_range_3 (string, from, to);
532
533 res = make_string (XSTRING (string)->data + XINT (from),
534 XINT (to) - XINT (from));
535 copy_text_properties (from, to, string, make_number (0), res, Qnil);
536 return res;
537 }
538 \f
539 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
540 "Take cdr N times on LIST, returns the result.")
541 (n, list)
542 Lisp_Object n;
543 register Lisp_Object list;
544 {
545 register int i, num;
546 CHECK_NUMBER (n, 0);
547 num = XINT (n);
548 for (i = 0; i < num && !NILP (list); i++)
549 {
550 QUIT;
551 list = Fcdr (list);
552 }
553 return list;
554 }
555
556 DEFUN ("nth", Fnth, Snth, 2, 2, 0,
557 "Return the Nth element of LIST.\n\
558 N counts from zero. If LIST is not that long, nil is returned.")
559 (n, list)
560 Lisp_Object n, list;
561 {
562 return Fcar (Fnthcdr (n, list));
563 }
564
565 DEFUN ("elt", Felt, Selt, 2, 2, 0,
566 "Return element of SEQUENCE at index N.")
567 (sequence, n)
568 register Lisp_Object sequence, n;
569 {
570 CHECK_NUMBER (n, 0);
571 while (1)
572 {
573 if (CONSP (sequence) || NILP (sequence))
574 return Fcar (Fnthcdr (n, sequence));
575 else if (STRINGP (sequence) || VECTORP (sequence)
576 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
577 return Faref (sequence, n);
578 else
579 sequence = wrong_type_argument (Qsequencep, sequence);
580 }
581 }
582
583 DEFUN ("member", Fmember, Smember, 2, 2, 0,
584 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
585 The value is actually the tail of LIST whose car is ELT.")
586 (elt, list)
587 register Lisp_Object elt;
588 Lisp_Object list;
589 {
590 register Lisp_Object tail;
591 for (tail = list; !NILP (tail); tail = Fcdr (tail))
592 {
593 register Lisp_Object tem;
594 tem = Fcar (tail);
595 if (! NILP (Fequal (elt, tem)))
596 return tail;
597 QUIT;
598 }
599 return Qnil;
600 }
601
602 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
603 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
604 The value is actually the tail of LIST whose car is ELT.")
605 (elt, list)
606 register Lisp_Object elt;
607 Lisp_Object list;
608 {
609 register Lisp_Object tail;
610 for (tail = list; !NILP (tail); tail = Fcdr (tail))
611 {
612 register Lisp_Object tem;
613 tem = Fcar (tail);
614 if (EQ (elt, tem)) return tail;
615 QUIT;
616 }
617 return Qnil;
618 }
619
620 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
621 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
622 The value is actually the element of LIST whose car is KEY.\n\
623 Elements of LIST that are not conses are ignored.")
624 (key, list)
625 register Lisp_Object key;
626 Lisp_Object list;
627 {
628 register Lisp_Object tail;
629 for (tail = list; !NILP (tail); tail = Fcdr (tail))
630 {
631 register Lisp_Object elt, tem;
632 elt = Fcar (tail);
633 if (!CONSP (elt)) continue;
634 tem = Fcar (elt);
635 if (EQ (key, tem)) return elt;
636 QUIT;
637 }
638 return Qnil;
639 }
640
641 /* Like Fassq but never report an error and do not allow quits.
642 Use only on lists known never to be circular. */
643
644 Lisp_Object
645 assq_no_quit (key, list)
646 register Lisp_Object key;
647 Lisp_Object list;
648 {
649 register Lisp_Object tail;
650 for (tail = list; CONSP (tail); tail = Fcdr (tail))
651 {
652 register Lisp_Object elt, tem;
653 elt = Fcar (tail);
654 if (!CONSP (elt)) continue;
655 tem = Fcar (elt);
656 if (EQ (key, tem)) return elt;
657 }
658 return Qnil;
659 }
660
661 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
662 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
663 The value is actually the element of LIST whose car equals KEY.")
664 (key, list)
665 register Lisp_Object key;
666 Lisp_Object list;
667 {
668 register Lisp_Object tail;
669 for (tail = list; !NILP (tail); tail = Fcdr (tail))
670 {
671 register Lisp_Object elt, tem;
672 elt = Fcar (tail);
673 if (!CONSP (elt)) continue;
674 tem = Fequal (Fcar (elt), key);
675 if (!NILP (tem)) return elt;
676 QUIT;
677 }
678 return Qnil;
679 }
680
681 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
682 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
683 The value is actually the element of LIST whose cdr is ELT.")
684 (key, list)
685 register Lisp_Object key;
686 Lisp_Object list;
687 {
688 register Lisp_Object tail;
689 for (tail = list; !NILP (tail); tail = Fcdr (tail))
690 {
691 register Lisp_Object elt, tem;
692 elt = Fcar (tail);
693 if (!CONSP (elt)) continue;
694 tem = Fcdr (elt);
695 if (EQ (key, tem)) return elt;
696 QUIT;
697 }
698 return Qnil;
699 }
700
701 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
702 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
703 The value is actually the element of LIST whose cdr equals KEY.")
704 (key, list)
705 register Lisp_Object key;
706 Lisp_Object list;
707 {
708 register Lisp_Object tail;
709 for (tail = list; !NILP (tail); tail = Fcdr (tail))
710 {
711 register Lisp_Object elt, tem;
712 elt = Fcar (tail);
713 if (!CONSP (elt)) continue;
714 tem = Fequal (Fcdr (elt), key);
715 if (!NILP (tem)) return elt;
716 QUIT;
717 }
718 return Qnil;
719 }
720 \f
721 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
722 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
723 The modified LIST is returned. Comparison is done with `eq'.\n\
724 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
725 therefore, write `(setq foo (delq element foo))'\n\
726 to be sure of changing the value of `foo'.")
727 (elt, list)
728 register Lisp_Object elt;
729 Lisp_Object list;
730 {
731 register Lisp_Object tail, prev;
732 register Lisp_Object tem;
733
734 tail = list;
735 prev = Qnil;
736 while (!NILP (tail))
737 {
738 tem = Fcar (tail);
739 if (EQ (elt, tem))
740 {
741 if (NILP (prev))
742 list = Fcdr (tail);
743 else
744 Fsetcdr (prev, Fcdr (tail));
745 }
746 else
747 prev = tail;
748 tail = Fcdr (tail);
749 QUIT;
750 }
751 return list;
752 }
753
754 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
755 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
756 The modified LIST is returned. Comparison is done with `equal'.\n\
757 If the first member of LIST is ELT, deleting it is not a side effect;\n\
758 it is simply using a different list.\n\
759 Therefore, write `(setq foo (delete element foo))'\n\
760 to be sure of changing the value of `foo'.")
761 (elt, list)
762 register Lisp_Object elt;
763 Lisp_Object list;
764 {
765 register Lisp_Object tail, prev;
766 register Lisp_Object tem;
767
768 tail = list;
769 prev = Qnil;
770 while (!NILP (tail))
771 {
772 tem = Fcar (tail);
773 if (! NILP (Fequal (elt, tem)))
774 {
775 if (NILP (prev))
776 list = Fcdr (tail);
777 else
778 Fsetcdr (prev, Fcdr (tail));
779 }
780 else
781 prev = tail;
782 tail = Fcdr (tail);
783 QUIT;
784 }
785 return list;
786 }
787
788 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
789 "Reverse LIST by modifying cdr pointers.\n\
790 Returns the beginning of the reversed list.")
791 (list)
792 Lisp_Object list;
793 {
794 register Lisp_Object prev, tail, next;
795
796 if (NILP (list)) return list;
797 prev = Qnil;
798 tail = list;
799 while (!NILP (tail))
800 {
801 QUIT;
802 next = Fcdr (tail);
803 Fsetcdr (tail, prev);
804 prev = tail;
805 tail = next;
806 }
807 return prev;
808 }
809
810 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
811 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
812 See also the function `nreverse', which is used more often.")
813 (list)
814 Lisp_Object list;
815 {
816 Lisp_Object length;
817 register Lisp_Object *vec;
818 register Lisp_Object tail;
819 register int i;
820
821 length = Flength (list);
822 vec = (Lisp_Object *) alloca (XINT (length) * sizeof (Lisp_Object));
823 for (i = XINT (length) - 1, tail = list; i >= 0; i--, tail = Fcdr (tail))
824 vec[i] = Fcar (tail);
825
826 return Flist (XINT (length), vec);
827 }
828 \f
829 Lisp_Object merge ();
830
831 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
832 "Sort LIST, stably, comparing elements using PREDICATE.\n\
833 Returns the sorted list. LIST is modified by side effects.\n\
834 PREDICATE is called with two elements of LIST, and should return T\n\
835 if the first element is \"less\" than the second.")
836 (list, predicate)
837 Lisp_Object list, predicate;
838 {
839 Lisp_Object front, back;
840 register Lisp_Object len, tem;
841 struct gcpro gcpro1, gcpro2;
842 register int length;
843
844 front = list;
845 len = Flength (list);
846 length = XINT (len);
847 if (length < 2)
848 return list;
849
850 XSETINT (len, (length / 2) - 1);
851 tem = Fnthcdr (len, list);
852 back = Fcdr (tem);
853 Fsetcdr (tem, Qnil);
854
855 GCPRO2 (front, back);
856 front = Fsort (front, predicate);
857 back = Fsort (back, predicate);
858 UNGCPRO;
859 return merge (front, back, predicate);
860 }
861
862 Lisp_Object
863 merge (org_l1, org_l2, pred)
864 Lisp_Object org_l1, org_l2;
865 Lisp_Object pred;
866 {
867 Lisp_Object value;
868 register Lisp_Object tail;
869 Lisp_Object tem;
870 register Lisp_Object l1, l2;
871 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
872
873 l1 = org_l1;
874 l2 = org_l2;
875 tail = Qnil;
876 value = Qnil;
877
878 /* It is sufficient to protect org_l1 and org_l2.
879 When l1 and l2 are updated, we copy the new values
880 back into the org_ vars. */
881 GCPRO4 (org_l1, org_l2, pred, value);
882
883 while (1)
884 {
885 if (NILP (l1))
886 {
887 UNGCPRO;
888 if (NILP (tail))
889 return l2;
890 Fsetcdr (tail, l2);
891 return value;
892 }
893 if (NILP (l2))
894 {
895 UNGCPRO;
896 if (NILP (tail))
897 return l1;
898 Fsetcdr (tail, l1);
899 return value;
900 }
901 tem = call2 (pred, Fcar (l2), Fcar (l1));
902 if (NILP (tem))
903 {
904 tem = l1;
905 l1 = Fcdr (l1);
906 org_l1 = l1;
907 }
908 else
909 {
910 tem = l2;
911 l2 = Fcdr (l2);
912 org_l2 = l2;
913 }
914 if (NILP (tail))
915 value = tem;
916 else
917 Fsetcdr (tail, tem);
918 tail = tem;
919 }
920 }
921 \f
922
923 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
924 "Extract a value from a property list.\n\
925 PLIST is a property list, which is a list of the form\n\
926 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
927 corresponding to the given PROP, or nil if PROP is not\n\
928 one of the properties on the list.")
929 (plist, prop)
930 Lisp_Object plist;
931 register Lisp_Object prop;
932 {
933 register Lisp_Object tail;
934 for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
935 {
936 register Lisp_Object tem;
937 tem = Fcar (tail);
938 if (EQ (prop, tem))
939 return Fcar (Fcdr (tail));
940 }
941 return Qnil;
942 }
943
944 DEFUN ("get", Fget, Sget, 2, 2, 0,
945 "Return the value of SYMBOL's PROPNAME property.\n\
946 This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
947 (symbol, propname)
948 Lisp_Object symbol, propname;
949 {
950 CHECK_SYMBOL (symbol, 0);
951 return Fplist_get (XSYMBOL (symbol)->plist, propname);
952 }
953
954 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
955 "Change value in PLIST of PROP to VAL.\n\
956 PLIST is a property list, which is a list of the form\n\
957 \(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
958 If PROP is already a property on the list, its value is set to VAL,\n\
959 otherwise the new PROP VAL pair is added. The new plist is returned;\n\
960 use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
961 The PLIST is modified by side effects.")
962 (plist, prop, val)
963 Lisp_Object plist;
964 register Lisp_Object prop;
965 Lisp_Object val;
966 {
967 register Lisp_Object tail, prev;
968 Lisp_Object newcell;
969 prev = Qnil;
970 for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
971 tail = XCONS (XCONS (tail)->cdr)->cdr)
972 {
973 if (EQ (prop, XCONS (tail)->car))
974 {
975 Fsetcar (XCONS (tail)->cdr, val);
976 return plist;
977 }
978 prev = tail;
979 }
980 newcell = Fcons (prop, Fcons (val, Qnil));
981 if (NILP (prev))
982 return newcell;
983 else
984 Fsetcdr (XCONS (prev)->cdr, newcell);
985 return plist;
986 }
987
988 DEFUN ("put", Fput, Sput, 3, 3, 0,
989 "Store SYMBOL's PROPNAME property with value VALUE.\n\
990 It can be retrieved with `(get SYMBOL PROPNAME)'.")
991 (symbol, propname, value)
992 Lisp_Object symbol, propname, value;
993 {
994 CHECK_SYMBOL (symbol, 0);
995 XSYMBOL (symbol)->plist
996 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
997 return value;
998 }
999
1000 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
1001 "T if two Lisp objects have similar structure and contents.\n\
1002 They must have the same data type.\n\
1003 Conses are compared by comparing the cars and the cdrs.\n\
1004 Vectors and strings are compared element by element.\n\
1005 Numbers are compared by value, but integers cannot equal floats.\n\
1006 (Use `=' if you want integers and floats to be able to be equal.)\n\
1007 Symbols must match exactly.")
1008 (o1, o2)
1009 register Lisp_Object o1, o2;
1010 {
1011 return internal_equal (o1, o2, 0) ? Qt : Qnil;
1012 }
1013
1014 static int
1015 internal_equal (o1, o2, depth)
1016 register Lisp_Object o1, o2;
1017 int depth;
1018 {
1019 if (depth > 200)
1020 error ("Stack overflow in equal");
1021
1022 tail_recurse:
1023 QUIT;
1024 if (EQ (o1, o2))
1025 return 1;
1026 if (XTYPE (o1) != XTYPE (o2))
1027 return 0;
1028
1029 switch (XTYPE (o1))
1030 {
1031 #ifdef LISP_FLOAT_TYPE
1032 case Lisp_Float:
1033 return (extract_float (o1) == extract_float (o2));
1034 #endif
1035
1036 case Lisp_Cons:
1037 if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
1038 return 0;
1039 o1 = XCONS (o1)->cdr;
1040 o2 = XCONS (o2)->cdr;
1041 goto tail_recurse;
1042
1043 case Lisp_Misc:
1044 if (XMISCTYPE (o1) != XMISCTYPE (o2))
1045 return 0;
1046 if (OVERLAYP (o1))
1047 {
1048 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
1049 depth + 1)
1050 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
1051 depth + 1))
1052 return 0;
1053 o1 = XOVERLAY (o1)->plist;
1054 o2 = XOVERLAY (o2)->plist;
1055 goto tail_recurse;
1056 }
1057 if (MARKERP (o1))
1058 {
1059 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1060 && (XMARKER (o1)->buffer == 0
1061 || XMARKER (o1)->bufpos == XMARKER (o2)->bufpos));
1062 }
1063 break;
1064
1065 case Lisp_Vectorlike:
1066 {
1067 register int i, size;
1068 size = XVECTOR (o1)->size;
1069 /* Pseudovectors have the type encoded in the size field, so this test
1070 actually checks that the objects have the same type as well as the
1071 same size. */
1072 if (XVECTOR (o2)->size != size)
1073 return 0;
1074 /* Boolvectors are compared much like strings. */
1075 if (BOOL_VECTOR_P (o1))
1076 {
1077 int size_in_chars
1078 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
1079
1080 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1081 return 0;
1082 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1083 size_in_chars))
1084 return 0;
1085 return 1;
1086 }
1087
1088 /* Aside from them, only true vectors, char-tables, and compiled
1089 functions are sensible to compare, so eliminate the others now. */
1090 if (size & PSEUDOVECTOR_FLAG)
1091 {
1092 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
1093 return 0;
1094 size &= PSEUDOVECTOR_SIZE_MASK;
1095 }
1096 for (i = 0; i < size; i++)
1097 {
1098 Lisp_Object v1, v2;
1099 v1 = XVECTOR (o1)->contents [i];
1100 v2 = XVECTOR (o2)->contents [i];
1101 if (!internal_equal (v1, v2, depth + 1))
1102 return 0;
1103 }
1104 return 1;
1105 }
1106 break;
1107
1108 case Lisp_String:
1109 if (XSTRING (o1)->size != XSTRING (o2)->size)
1110 return 0;
1111 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
1112 XSTRING (o1)->size))
1113 return 0;
1114 #ifdef USE_TEXT_PROPERTIES
1115 /* If the strings have intervals, verify they match;
1116 if not, they are unequal. */
1117 if ((XSTRING (o1)->intervals != 0 || XSTRING (o2)->intervals != 0)
1118 && ! compare_string_intervals (o1, o2))
1119 return 0;
1120 #endif
1121 return 1;
1122 }
1123 return 0;
1124 }
1125 \f
1126 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
1127 "Store each element of ARRAY with ITEM.\n\
1128 ARRAY is a vector, string, char-table, or bool-vector.")
1129 (array, item)
1130 Lisp_Object array, item;
1131 {
1132 register int size, index, charval;
1133 retry:
1134 if (VECTORP (array))
1135 {
1136 register Lisp_Object *p = XVECTOR (array)->contents;
1137 size = XVECTOR (array)->size;
1138 for (index = 0; index < size; index++)
1139 p[index] = item;
1140 }
1141 else if (CHAR_TABLE_P (array))
1142 {
1143 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1144 size = CHAR_TABLE_ORDINARY_SLOTS;
1145 for (index = 0; index < size; index++)
1146 p[index] = item;
1147 XCHAR_TABLE (array)->defalt = Qnil;
1148 }
1149 else if (STRINGP (array))
1150 {
1151 register unsigned char *p = XSTRING (array)->data;
1152 CHECK_NUMBER (item, 1);
1153 charval = XINT (item);
1154 size = XSTRING (array)->size;
1155 for (index = 0; index < size; index++)
1156 p[index] = charval;
1157 }
1158 else if (BOOL_VECTOR_P (array))
1159 {
1160 register unsigned char *p = XBOOL_VECTOR (array)->data;
1161 int size_in_chars
1162 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR) / BITS_PER_CHAR;
1163
1164 charval = (! NILP (item) ? -1 : 0);
1165 for (index = 0; index < size_in_chars; index++)
1166 p[index] = charval;
1167 }
1168 else
1169 {
1170 array = wrong_type_argument (Qarrayp, array);
1171 goto retry;
1172 }
1173 return array;
1174 }
1175
1176 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1177 1, 1, 0,
1178 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
1179 (char_table)
1180 Lisp_Object char_table;
1181 {
1182 CHECK_CHAR_TABLE (char_table, 0);
1183
1184 return XCHAR_TABLE (char_table)->purpose;
1185 }
1186
1187 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
1188 1, 1, 0,
1189 "Return the parent char-table of CHAR-TABLE.\n\
1190 The value is either nil or another char-table.\n\
1191 If CHAR-TABLE holds nil for a given character,\n\
1192 then the actual applicable value is inherited from the parent char-table\n\
1193 \(or from its parents, if necessary).")
1194 (char_table)
1195 Lisp_Object char_table;
1196 {
1197 CHECK_CHAR_TABLE (char_table, 0);
1198
1199 return XCHAR_TABLE (char_table)->parent;
1200 }
1201
1202 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
1203 2, 2, 0,
1204 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1205 PARENT must be either nil or another char-table.")
1206 (char_table, parent)
1207 Lisp_Object char_table, parent;
1208 {
1209 Lisp_Object temp;
1210
1211 CHECK_CHAR_TABLE (char_table, 0);
1212
1213 if (!NILP (parent))
1214 {
1215 CHECK_CHAR_TABLE (parent, 0);
1216
1217 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
1218 if (EQ (temp, char_table))
1219 error ("Attempt to make a chartable be its own parent");
1220 }
1221
1222 XCHAR_TABLE (char_table)->parent = parent;
1223
1224 return parent;
1225 }
1226
1227 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
1228 2, 2, 0,
1229 "Return the value in extra-slot number N of char-table CHAR-TABLE.")
1230 (char_table, n)
1231 Lisp_Object char_table, n;
1232 {
1233 CHECK_CHAR_TABLE (char_table, 1);
1234 CHECK_NUMBER (n, 2);
1235 if (XINT (n) < 0
1236 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1237 args_out_of_range (char_table, n);
1238
1239 return XCHAR_TABLE (char_table)->extras[XINT (n)];
1240 }
1241
1242 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1243 Sset_char_table_extra_slot,
1244 3, 3, 0,
1245 "Set extra-slot number N of CHAR-TABLE to VALUE.")
1246 (char_table, n, value)
1247 Lisp_Object char_table, n, value;
1248 {
1249 CHECK_CHAR_TABLE (char_table, 1);
1250 CHECK_NUMBER (n, 2);
1251 if (XINT (n) < 0
1252 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1253 args_out_of_range (char_table, n);
1254
1255 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
1256 }
1257
1258 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1259 2, 2, 0,
1260 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
1261 RANGE should be t (for all characters), nil (for the default value)\n\
1262 a vector which identifies a character set or a row of a character set,\n\
1263 or a character code.")
1264 (char_table, range)
1265 Lisp_Object char_table, range;
1266 {
1267 int i;
1268
1269 CHECK_CHAR_TABLE (char_table, 0);
1270
1271 if (EQ (range, Qnil))
1272 return XCHAR_TABLE (char_table)->defalt;
1273 else if (INTEGERP (range))
1274 return Faref (char_table, range);
1275 else if (VECTORP (range))
1276 {
1277 for (i = 0; i < XVECTOR (range)->size - 1; i++)
1278 char_table = Faref (char_table, XVECTOR (range)->contents[i]);
1279
1280 if (EQ (XVECTOR (range)->contents[i], Qnil))
1281 return XCHAR_TABLE (char_table)->defalt;
1282 else
1283 return Faref (char_table, XVECTOR (range)->contents[i]);
1284 }
1285 else
1286 error ("Invalid RANGE argument to `char-table-range'");
1287 }
1288
1289 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
1290 3, 3, 0,
1291 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
1292 RANGE should be t (for all characters), nil (for the default value)\n\
1293 a vector which identifies a character set or a row of a character set,\n\
1294 or a character code.")
1295 (char_table, range, value)
1296 Lisp_Object char_table, range, value;
1297 {
1298 int i;
1299
1300 CHECK_CHAR_TABLE (char_table, 0);
1301
1302 if (EQ (range, Qt))
1303 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
1304 XCHAR_TABLE (char_table)->contents[i] = value;
1305 else if (EQ (range, Qnil))
1306 XCHAR_TABLE (char_table)->defalt = value;
1307 else if (INTEGERP (range))
1308 Faset (char_table, range, value);
1309 else if (VECTORP (range))
1310 {
1311 for (i = 0; i < XVECTOR (range)->size - 1; i++)
1312 char_table = Faref (char_table, XVECTOR (range)->contents[i]);
1313
1314 if (EQ (XVECTOR (range)->contents[i], Qnil))
1315 XCHAR_TABLE (char_table)->defalt = value;
1316 else
1317 Faset (char_table, XVECTOR (range)->contents[i], value);
1318 }
1319 else
1320 error ("Invalid RANGE argument to `set-char-table-range'");
1321
1322 return value;
1323 }
1324 \f
1325 /* Map C_FUNCTION or FUNCTION over CHARTABLE, calling it for each
1326 character or group of characters that share a value.
1327 DEPTH is the current depth in the originally specified
1328 chartable, and INDICES contains the vector indices
1329 for the levels our callers have descended. */
1330
1331 void
1332 map_char_table (c_function, function, chartable, depth, indices)
1333 Lisp_Object (*c_function) (), function, chartable, depth, *indices;
1334 {
1335 int i;
1336 int size = CHAR_TABLE_ORDINARY_SLOTS;
1337
1338 /* Make INDICES longer if we are about to fill it up. */
1339 if ((depth % 10) == 9)
1340 {
1341 Lisp_Object *new_indices
1342 = (Lisp_Object *) alloca ((depth += 10) * sizeof (Lisp_Object));
1343 bcopy (indices, new_indices, depth * sizeof (Lisp_Object));
1344 indices = new_indices;
1345 }
1346
1347 for (i = 0; i < size; i++)
1348 {
1349 Lisp_Object elt;
1350 indices[depth] = i;
1351 elt = XCHAR_TABLE (chartable)->contents[i];
1352 if (CHAR_TABLE_P (elt))
1353 map_char_table (chartable, c_function, function, depth + 1, indices);
1354 else if (c_function)
1355 (*c_function) (depth + 1, indices, elt);
1356 /* Here we should handle all cases where the range is a single character
1357 by passing that character as a number. Currently, that is
1358 all the time, but with the MULE code this will have to be changed. */
1359 else if (depth == 0)
1360 call2 (function, make_number (i), elt);
1361 else
1362 call2 (function, Fvector (depth + 1, indices), elt);
1363 }
1364 }
1365
1366 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
1367 2, 2, 0,
1368 "Call FUNCTION for each range of like characters in CHAR-TABLE.\n\
1369 FUNCTION is called with two arguments--a key and a value.\n\
1370 The key is always a possible RANGE argument to `set-char-table-range'.")
1371 (function, char_table)
1372 Lisp_Object function, char_table;
1373 {
1374 Lisp_Object keyvec;
1375 Lisp_Object *indices = (Lisp_Object *) alloca (10 * sizeof (Lisp_Object));
1376
1377 map_char_table (NULL, function, char_table, 0, indices);
1378 return Qnil;
1379 }
1380 \f
1381 /* ARGSUSED */
1382 Lisp_Object
1383 nconc2 (s1, s2)
1384 Lisp_Object s1, s2;
1385 {
1386 #ifdef NO_ARG_ARRAY
1387 Lisp_Object args[2];
1388 args[0] = s1;
1389 args[1] = s2;
1390 return Fnconc (2, args);
1391 #else
1392 return Fnconc (2, &s1);
1393 #endif /* NO_ARG_ARRAY */
1394 }
1395
1396 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
1397 "Concatenate any number of lists by altering them.\n\
1398 Only the last argument is not altered, and need not be a list.")
1399 (nargs, args)
1400 int nargs;
1401 Lisp_Object *args;
1402 {
1403 register int argnum;
1404 register Lisp_Object tail, tem, val;
1405
1406 val = Qnil;
1407
1408 for (argnum = 0; argnum < nargs; argnum++)
1409 {
1410 tem = args[argnum];
1411 if (NILP (tem)) continue;
1412
1413 if (NILP (val))
1414 val = tem;
1415
1416 if (argnum + 1 == nargs) break;
1417
1418 if (!CONSP (tem))
1419 tem = wrong_type_argument (Qlistp, tem);
1420
1421 while (CONSP (tem))
1422 {
1423 tail = tem;
1424 tem = Fcdr (tail);
1425 QUIT;
1426 }
1427
1428 tem = args[argnum + 1];
1429 Fsetcdr (tail, tem);
1430 if (NILP (tem))
1431 args[argnum + 1] = tail;
1432 }
1433
1434 return val;
1435 }
1436 \f
1437 /* This is the guts of all mapping functions.
1438 Apply fn to each element of seq, one by one,
1439 storing the results into elements of vals, a C vector of Lisp_Objects.
1440 leni is the length of vals, which should also be the length of seq. */
1441
1442 static void
1443 mapcar1 (leni, vals, fn, seq)
1444 int leni;
1445 Lisp_Object *vals;
1446 Lisp_Object fn, seq;
1447 {
1448 register Lisp_Object tail;
1449 Lisp_Object dummy;
1450 register int i;
1451 struct gcpro gcpro1, gcpro2, gcpro3;
1452
1453 /* Don't let vals contain any garbage when GC happens. */
1454 for (i = 0; i < leni; i++)
1455 vals[i] = Qnil;
1456
1457 GCPRO3 (dummy, fn, seq);
1458 gcpro1.var = vals;
1459 gcpro1.nvars = leni;
1460 /* We need not explicitly protect `tail' because it is used only on lists, and
1461 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1462
1463 if (VECTORP (seq))
1464 {
1465 for (i = 0; i < leni; i++)
1466 {
1467 dummy = XVECTOR (seq)->contents[i];
1468 vals[i] = call1 (fn, dummy);
1469 }
1470 }
1471 else if (STRINGP (seq))
1472 {
1473 for (i = 0; i < leni; i++)
1474 {
1475 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
1476 vals[i] = call1 (fn, dummy);
1477 }
1478 }
1479 else /* Must be a list, since Flength did not get an error */
1480 {
1481 tail = seq;
1482 for (i = 0; i < leni; i++)
1483 {
1484 vals[i] = call1 (fn, Fcar (tail));
1485 tail = Fcdr (tail);
1486 }
1487 }
1488
1489 UNGCPRO;
1490 }
1491
1492 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
1493 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
1494 In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
1495 SEPARATOR results in spaces between the values returned by FUNCTION.")
1496 (function, sequence, separator)
1497 Lisp_Object function, sequence, separator;
1498 {
1499 Lisp_Object len;
1500 register int leni;
1501 int nargs;
1502 register Lisp_Object *args;
1503 register int i;
1504 struct gcpro gcpro1;
1505
1506 len = Flength (sequence);
1507 leni = XINT (len);
1508 nargs = leni + leni - 1;
1509 if (nargs < 0) return build_string ("");
1510
1511 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
1512
1513 GCPRO1 (separator);
1514 mapcar1 (leni, args, function, sequence);
1515 UNGCPRO;
1516
1517 for (i = leni - 1; i >= 0; i--)
1518 args[i + i] = args[i];
1519
1520 for (i = 1; i < nargs; i += 2)
1521 args[i] = separator;
1522
1523 return Fconcat (nargs, args);
1524 }
1525
1526 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
1527 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
1528 The result is a list just as long as SEQUENCE.\n\
1529 SEQUENCE may be a list, a vector or a string.")
1530 (function, sequence)
1531 Lisp_Object function, sequence;
1532 {
1533 register Lisp_Object len;
1534 register int leni;
1535 register Lisp_Object *args;
1536
1537 len = Flength (sequence);
1538 leni = XFASTINT (len);
1539 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
1540
1541 mapcar1 (leni, args, function, sequence);
1542
1543 return Flist (leni, args);
1544 }
1545 \f
1546 /* Anything that calls this function must protect from GC! */
1547
1548 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
1549 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
1550 Takes one argument, which is the string to display to ask the question.\n\
1551 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
1552 No confirmation of the answer is requested; a single character is enough.\n\
1553 Also accepts Space to mean yes, or Delete to mean no.")
1554 (prompt)
1555 Lisp_Object prompt;
1556 {
1557 register Lisp_Object obj, key, def, answer_string, map;
1558 register int answer;
1559 Lisp_Object xprompt;
1560 Lisp_Object args[2];
1561 int ocech = cursor_in_echo_area;
1562 struct gcpro gcpro1, gcpro2;
1563
1564 map = Fsymbol_value (intern ("query-replace-map"));
1565
1566 CHECK_STRING (prompt, 0);
1567 xprompt = prompt;
1568 GCPRO2 (prompt, xprompt);
1569
1570 while (1)
1571 {
1572 #ifdef HAVE_MENUS
1573 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
1574 && have_menus_p ())
1575 {
1576 Lisp_Object pane, menu;
1577 redisplay_preserve_echo_area ();
1578 pane = Fcons (Fcons (build_string ("Yes"), Qt),
1579 Fcons (Fcons (build_string ("No"), Qnil),
1580 Qnil));
1581 menu = Fcons (prompt, pane);
1582 obj = Fx_popup_dialog (Qt, menu);
1583 answer = !NILP (obj);
1584 break;
1585 }
1586 #endif /* HAVE_MENUS */
1587 cursor_in_echo_area = 1;
1588 message_nolog ("%s(y or n) ", XSTRING (xprompt)->data);
1589
1590 obj = read_filtered_event (1, 0, 0);
1591 cursor_in_echo_area = 0;
1592 /* If we need to quit, quit with cursor_in_echo_area = 0. */
1593 QUIT;
1594
1595 key = Fmake_vector (make_number (1), obj);
1596 def = Flookup_key (map, key);
1597 answer_string = Fsingle_key_description (obj);
1598
1599 if (EQ (def, intern ("skip")))
1600 {
1601 answer = 0;
1602 break;
1603 }
1604 else if (EQ (def, intern ("act")))
1605 {
1606 answer = 1;
1607 break;
1608 }
1609 else if (EQ (def, intern ("recenter")))
1610 {
1611 Frecenter (Qnil);
1612 xprompt = prompt;
1613 continue;
1614 }
1615 else if (EQ (def, intern ("quit")))
1616 Vquit_flag = Qt;
1617 /* We want to exit this command for exit-prefix,
1618 and this is the only way to do it. */
1619 else if (EQ (def, intern ("exit-prefix")))
1620 Vquit_flag = Qt;
1621
1622 QUIT;
1623
1624 /* If we don't clear this, then the next call to read_char will
1625 return quit_char again, and we'll enter an infinite loop. */
1626 Vquit_flag = Qnil;
1627
1628 Fding (Qnil);
1629 Fdiscard_input ();
1630 if (EQ (xprompt, prompt))
1631 {
1632 args[0] = build_string ("Please answer y or n. ");
1633 args[1] = prompt;
1634 xprompt = Fconcat (2, args);
1635 }
1636 }
1637 UNGCPRO;
1638
1639 if (! noninteractive)
1640 {
1641 cursor_in_echo_area = -1;
1642 message_nolog ("%s(y or n) %c",
1643 XSTRING (xprompt)->data, answer ? 'y' : 'n');
1644 cursor_in_echo_area = ocech;
1645 }
1646
1647 return answer ? Qt : Qnil;
1648 }
1649 \f
1650 /* This is how C code calls `yes-or-no-p' and allows the user
1651 to redefined it.
1652
1653 Anything that calls this function must protect from GC! */
1654
1655 Lisp_Object
1656 do_yes_or_no_p (prompt)
1657 Lisp_Object prompt;
1658 {
1659 return call1 (intern ("yes-or-no-p"), prompt);
1660 }
1661
1662 /* Anything that calls this function must protect from GC! */
1663
1664 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
1665 "Ask user a yes-or-no question. Return t if answer is yes.\n\
1666 Takes one argument, which is the string to display to ask the question.\n\
1667 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
1668 The user must confirm the answer with RET,\n\
1669 and can edit it until it has been confirmed.")
1670 (prompt)
1671 Lisp_Object prompt;
1672 {
1673 register Lisp_Object ans;
1674 Lisp_Object args[2];
1675 struct gcpro gcpro1;
1676 Lisp_Object menu;
1677
1678 CHECK_STRING (prompt, 0);
1679
1680 #ifdef HAVE_MENUS
1681 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
1682 && have_menus_p ())
1683 {
1684 Lisp_Object pane, menu, obj;
1685 redisplay_preserve_echo_area ();
1686 pane = Fcons (Fcons (build_string ("Yes"), Qt),
1687 Fcons (Fcons (build_string ("No"), Qnil),
1688 Qnil));
1689 GCPRO1 (pane);
1690 menu = Fcons (prompt, pane);
1691 obj = Fx_popup_dialog (Qt, menu);
1692 UNGCPRO;
1693 return obj;
1694 }
1695 #endif /* HAVE_MENUS */
1696
1697 args[0] = prompt;
1698 args[1] = build_string ("(yes or no) ");
1699 prompt = Fconcat (2, args);
1700
1701 GCPRO1 (prompt);
1702
1703 while (1)
1704 {
1705 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
1706 Qyes_or_no_p_history));
1707 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
1708 {
1709 UNGCPRO;
1710 return Qt;
1711 }
1712 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
1713 {
1714 UNGCPRO;
1715 return Qnil;
1716 }
1717
1718 Fding (Qnil);
1719 Fdiscard_input ();
1720 message ("Please answer yes or no.");
1721 Fsleep_for (make_number (2), Qnil);
1722 }
1723 }
1724 \f
1725 DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0,
1726 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
1727 Each of the three load averages is multiplied by 100,\n\
1728 then converted to integer.\n\
1729 If the 5-minute or 15-minute load averages are not available, return a\n\
1730 shortened list, containing only those averages which are available.")
1731 ()
1732 {
1733 double load_ave[3];
1734 int loads = getloadavg (load_ave, 3);
1735 Lisp_Object ret;
1736
1737 if (loads < 0)
1738 error ("load-average not implemented for this operating system");
1739
1740 ret = Qnil;
1741 while (loads > 0)
1742 ret = Fcons (make_number ((int) (load_ave[--loads] * 100.0)), ret);
1743
1744 return ret;
1745 }
1746 \f
1747 Lisp_Object Vfeatures;
1748
1749 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
1750 "Returns t if FEATURE is present in this Emacs.\n\
1751 Use this to conditionalize execution of lisp code based on the presence or\n\
1752 absence of emacs or environment extensions.\n\
1753 Use `provide' to declare that a feature is available.\n\
1754 This function looks at the value of the variable `features'.")
1755 (feature)
1756 Lisp_Object feature;
1757 {
1758 register Lisp_Object tem;
1759 CHECK_SYMBOL (feature, 0);
1760 tem = Fmemq (feature, Vfeatures);
1761 return (NILP (tem)) ? Qnil : Qt;
1762 }
1763
1764 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
1765 "Announce that FEATURE is a feature of the current Emacs.")
1766 (feature)
1767 Lisp_Object feature;
1768 {
1769 register Lisp_Object tem;
1770 CHECK_SYMBOL (feature, 0);
1771 if (!NILP (Vautoload_queue))
1772 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
1773 tem = Fmemq (feature, Vfeatures);
1774 if (NILP (tem))
1775 Vfeatures = Fcons (feature, Vfeatures);
1776 LOADHIST_ATTACH (Fcons (Qprovide, feature));
1777 return feature;
1778 }
1779
1780 DEFUN ("require", Frequire, Srequire, 1, 2, 0,
1781 "If feature FEATURE is not loaded, load it from FILENAME.\n\
1782 If FEATURE is not a member of the list `features', then the feature\n\
1783 is not loaded; so load the file FILENAME.\n\
1784 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
1785 (feature, file_name)
1786 Lisp_Object feature, file_name;
1787 {
1788 register Lisp_Object tem;
1789 CHECK_SYMBOL (feature, 0);
1790 tem = Fmemq (feature, Vfeatures);
1791 LOADHIST_ATTACH (Fcons (Qrequire, feature));
1792 if (NILP (tem))
1793 {
1794 int count = specpdl_ptr - specpdl;
1795
1796 /* Value saved here is to be restored into Vautoload_queue */
1797 record_unwind_protect (un_autoload, Vautoload_queue);
1798 Vautoload_queue = Qt;
1799
1800 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
1801 Qnil, Qt, Qnil);
1802
1803 tem = Fmemq (feature, Vfeatures);
1804 if (NILP (tem))
1805 error ("Required feature %s was not provided",
1806 XSYMBOL (feature)->name->data );
1807
1808 /* Once loading finishes, don't undo it. */
1809 Vautoload_queue = Qt;
1810 feature = unbind_to (count, feature);
1811 }
1812 return feature;
1813 }
1814 \f
1815 syms_of_fns ()
1816 {
1817 Qstring_lessp = intern ("string-lessp");
1818 staticpro (&Qstring_lessp);
1819 Qprovide = intern ("provide");
1820 staticpro (&Qprovide);
1821 Qrequire = intern ("require");
1822 staticpro (&Qrequire);
1823 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
1824 staticpro (&Qyes_or_no_p_history);
1825
1826 DEFVAR_LISP ("features", &Vfeatures,
1827 "A list of symbols which are the features of the executing emacs.\n\
1828 Used by `featurep' and `require', and altered by `provide'.");
1829 Vfeatures = Qnil;
1830
1831 defsubr (&Sidentity);
1832 defsubr (&Srandom);
1833 defsubr (&Slength);
1834 defsubr (&Ssafe_length);
1835 defsubr (&Sstring_equal);
1836 defsubr (&Sstring_lessp);
1837 defsubr (&Sappend);
1838 defsubr (&Sconcat);
1839 defsubr (&Svconcat);
1840 defsubr (&Scopy_sequence);
1841 defsubr (&Scopy_alist);
1842 defsubr (&Ssubstring);
1843 defsubr (&Snthcdr);
1844 defsubr (&Snth);
1845 defsubr (&Selt);
1846 defsubr (&Smember);
1847 defsubr (&Smemq);
1848 defsubr (&Sassq);
1849 defsubr (&Sassoc);
1850 defsubr (&Srassq);
1851 defsubr (&Srassoc);
1852 defsubr (&Sdelq);
1853 defsubr (&Sdelete);
1854 defsubr (&Snreverse);
1855 defsubr (&Sreverse);
1856 defsubr (&Ssort);
1857 defsubr (&Splist_get);
1858 defsubr (&Sget);
1859 defsubr (&Splist_put);
1860 defsubr (&Sput);
1861 defsubr (&Sequal);
1862 defsubr (&Sfillarray);
1863 defsubr (&Schar_table_subtype);
1864 defsubr (&Schar_table_parent);
1865 defsubr (&Sset_char_table_parent);
1866 defsubr (&Schar_table_extra_slot);
1867 defsubr (&Sset_char_table_extra_slot);
1868 defsubr (&Schar_table_range);
1869 defsubr (&Sset_char_table_range);
1870 defsubr (&Smap_char_table);
1871 defsubr (&Snconc);
1872 defsubr (&Smapcar);
1873 defsubr (&Smapconcat);
1874 defsubr (&Sy_or_n_p);
1875 defsubr (&Syes_or_no_p);
1876 defsubr (&Sload_average);
1877 defsubr (&Sfeaturep);
1878 defsubr (&Srequire);
1879 defsubr (&Sprovide);
1880 }