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