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