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