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