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