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