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