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