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