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