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