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