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