]> code.delx.au - gnu-emacs/blob - src/fns.c
(Fconcat): Doc fix.
[gnu-emacs] / src / fns.c
1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 1986, 1987, 1993 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 1, 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 Lisp_Object Qstring_lessp, Qprovide, Qrequire;
36 Lisp_Object Qyes_or_no_p_history;
37
38 static Lisp_Object internal_equal ();
39 \f
40 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
41 "Return the argument unchanged.")
42 (arg)
43 Lisp_Object arg;
44 {
45 return arg;
46 }
47
48 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
49 "Return a pseudo-random number.\n\
50 On most systems all integers representable in Lisp are equally likely.\n\
51 This is 24 bits' worth.\n\
52 With argument N, return random number in interval [0,N).\n\
53 With argument t, set the random number seed from the current time and pid.")
54 (limit)
55 Lisp_Object limit;
56 {
57 int val;
58 extern long random ();
59 extern srandom ();
60 extern long time ();
61
62 if (EQ (limit, Qt))
63 srandom (getpid () + time (0));
64 val = random ();
65 if (XTYPE (limit) == Lisp_Int && XINT (limit) != 0)
66 {
67 /* Try to take our random number from the higher bits of VAL,
68 not the lower, since (says Gentzel) the low bits of `random'
69 are less random than the higher ones. */
70 val &= 0xfffffff; /* Ensure positive. */
71 val >>= 5;
72 if (XINT (limit) < 10000)
73 val >>= 6;
74 val %= XINT (limit);
75 }
76 return make_number (val);
77 }
78 \f
79 /* Random data-structure functions */
80
81 DEFUN ("length", Flength, Slength, 1, 1, 0,
82 "Return the length of vector, list or string SEQUENCE.\n\
83 A byte-code function object is also allowed.")
84 (obj)
85 register Lisp_Object obj;
86 {
87 register Lisp_Object tail, val;
88 register int i;
89
90 retry:
91 if (XTYPE (obj) == Lisp_Vector || XTYPE (obj) == Lisp_String
92 || XTYPE (obj) == Lisp_Compiled)
93 return Farray_length (obj);
94 else if (CONSP (obj))
95 {
96 for (i = 0, tail = obj; !NILP(tail); i++)
97 {
98 QUIT;
99 tail = Fcdr (tail);
100 }
101
102 XFASTINT (val) = i;
103 return val;
104 }
105 else if (NILP(obj))
106 {
107 XFASTINT (val) = 0;
108 return val;
109 }
110 else
111 {
112 obj = wrong_type_argument (Qsequencep, obj);
113 goto retry;
114 }
115 }
116
117 DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
118 "T if two strings have identical contents.\n\
119 Case is significant.\n\
120 Symbols are also allowed; their print names are used instead.")
121 (s1, s2)
122 register Lisp_Object s1, s2;
123 {
124 if (XTYPE (s1) == Lisp_Symbol)
125 XSETSTRING (s1, XSYMBOL (s1)->name), XSETTYPE (s1, Lisp_String);
126 if (XTYPE (s2) == Lisp_Symbol)
127 XSETSTRING (s2, XSYMBOL (s2)->name), XSETTYPE (s2, Lisp_String);
128 CHECK_STRING (s1, 0);
129 CHECK_STRING (s2, 1);
130
131 if (XSTRING (s1)->size != XSTRING (s2)->size ||
132 bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size))
133 return Qnil;
134 return Qt;
135 }
136
137 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
138 "T if first arg string is less than second in lexicographic order.\n\
139 Case is significant.\n\
140 Symbols are also allowed; their print names are used instead.")
141 (s1, s2)
142 register Lisp_Object s1, s2;
143 {
144 register int i;
145 register unsigned char *p1, *p2;
146 register int end;
147
148 if (XTYPE (s1) == Lisp_Symbol)
149 XSETSTRING (s1, XSYMBOL (s1)->name), XSETTYPE (s1, Lisp_String);
150 if (XTYPE (s2) == Lisp_Symbol)
151 XSETSTRING (s2, XSYMBOL (s2)->name), XSETTYPE (s2, Lisp_String);
152 CHECK_STRING (s1, 0);
153 CHECK_STRING (s2, 1);
154
155 p1 = XSTRING (s1)->data;
156 p2 = XSTRING (s2)->data;
157 end = XSTRING (s1)->size;
158 if (end > XSTRING (s2)->size)
159 end = XSTRING (s2)->size;
160
161 for (i = 0; i < end; i++)
162 {
163 if (p1[i] != p2[i])
164 return p1[i] < p2[i] ? Qt : Qnil;
165 }
166 return i < XSTRING (s2)->size ? Qt : Qnil;
167 }
168 \f
169 static Lisp_Object concat ();
170
171 /* ARGSUSED */
172 Lisp_Object
173 concat2 (s1, s2)
174 Lisp_Object s1, s2;
175 {
176 #ifdef NO_ARG_ARRAY
177 Lisp_Object args[2];
178 args[0] = s1;
179 args[1] = s2;
180 return concat (2, args, Lisp_String, 0);
181 #else
182 return concat (2, &s1, Lisp_String, 0);
183 #endif /* NO_ARG_ARRAY */
184 }
185
186 DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
187 "Concatenate all the arguments and make the result a list.\n\
188 The result is a list whose elements are the elements of all the arguments.\n\
189 Each argument may be a list, vector or string.\n\
190 The last argument is not copied, just used as the tail of the new list.")
191 (nargs, args)
192 int nargs;
193 Lisp_Object *args;
194 {
195 return concat (nargs, args, Lisp_Cons, 1);
196 }
197
198 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
199 "Concatenate all the arguments and make the result a string.\n\
200 The result is a string whose elements are the elements of all the arguments.\n\
201 Each argument may be a string, a list of characters (integers),\n\
202 or a vector of characters (integers).")
203 (nargs, args)
204 int nargs;
205 Lisp_Object *args;
206 {
207 return concat (nargs, args, Lisp_String, 0);
208 }
209
210 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
211 "Concatenate all the arguments and make the result a vector.\n\
212 The result is a vector whose elements are the elements of all the arguments.\n\
213 Each argument may be a list, vector or string.")
214 (nargs, args)
215 int nargs;
216 Lisp_Object *args;
217 {
218 return concat (nargs, args, Lisp_Vector, 0);
219 }
220
221 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
222 "Return a copy of a list, vector or string.\n\
223 The elements of a list or vector are not copied; they are shared\n\
224 with the original.")
225 (arg)
226 Lisp_Object arg;
227 {
228 if (NILP (arg)) return arg;
229 if (!CONSP (arg) && XTYPE (arg) != Lisp_Vector && XTYPE (arg) != Lisp_String)
230 arg = wrong_type_argument (Qsequencep, arg);
231 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
232 }
233
234 static Lisp_Object
235 concat (nargs, args, target_type, last_special)
236 int nargs;
237 Lisp_Object *args;
238 enum Lisp_Type target_type;
239 int last_special;
240 {
241 Lisp_Object val;
242 Lisp_Object len;
243 register Lisp_Object tail;
244 register Lisp_Object this;
245 int toindex;
246 register int leni;
247 register int argnum;
248 Lisp_Object last_tail;
249 Lisp_Object prev;
250
251 /* In append, the last arg isn't treated like the others */
252 if (last_special && nargs > 0)
253 {
254 nargs--;
255 last_tail = args[nargs];
256 }
257 else
258 last_tail = Qnil;
259
260 for (argnum = 0; argnum < nargs; argnum++)
261 {
262 this = args[argnum];
263 if (!(CONSP (this) || NILP (this)
264 || XTYPE (this) == Lisp_Vector || XTYPE (this) == Lisp_String
265 || XTYPE (this) == Lisp_Compiled))
266 {
267 if (XTYPE (this) == Lisp_Int)
268 args[argnum] = Fnumber_to_string (this);
269 else
270 args[argnum] = wrong_type_argument (Qsequencep, this);
271 }
272 }
273
274 for (argnum = 0, leni = 0; argnum < nargs; argnum++)
275 {
276 this = args[argnum];
277 len = Flength (this);
278 leni += XFASTINT (len);
279 }
280
281 XFASTINT (len) = leni;
282
283 if (target_type == Lisp_Cons)
284 val = Fmake_list (len, Qnil);
285 else if (target_type == Lisp_Vector)
286 val = Fmake_vector (len, Qnil);
287 else
288 val = Fmake_string (len, len);
289
290 /* In append, if all but last arg are nil, return last arg */
291 if (target_type == Lisp_Cons && EQ (val, Qnil))
292 return last_tail;
293
294 if (CONSP (val))
295 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
296 else
297 toindex = 0;
298
299 prev = Qnil;
300
301 for (argnum = 0; argnum < nargs; argnum++)
302 {
303 Lisp_Object thislen;
304 int thisleni;
305 register int thisindex = 0;
306
307 this = args[argnum];
308 if (!CONSP (this))
309 thislen = Flength (this), thisleni = XINT (thislen);
310
311 if (XTYPE (this) == Lisp_String && XTYPE (val) == Lisp_String
312 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
313 {
314 copy_text_properties (make_number (0), thislen, this,
315 make_number (toindex), val, Qnil);
316 }
317
318 while (1)
319 {
320 register Lisp_Object elt;
321
322 /* Fetch next element of `this' arg into `elt', or break if
323 `this' is exhausted. */
324 if (NILP (this)) break;
325 if (CONSP (this))
326 elt = Fcar (this), this = Fcdr (this);
327 else
328 {
329 if (thisindex >= thisleni) break;
330 if (XTYPE (this) == Lisp_String)
331 XFASTINT (elt) = XSTRING (this)->data[thisindex++];
332 else
333 elt = XVECTOR (this)->contents[thisindex++];
334 }
335
336 /* Store into result */
337 if (toindex < 0)
338 {
339 XCONS (tail)->car = elt;
340 prev = tail;
341 tail = XCONS (tail)->cdr;
342 }
343 else if (XTYPE (val) == Lisp_Vector)
344 XVECTOR (val)->contents[toindex++] = elt;
345 else
346 {
347 while (XTYPE (elt) != Lisp_Int)
348 elt = wrong_type_argument (Qintegerp, elt);
349 {
350 #ifdef MASSC_REGISTER_BUG
351 /* Even removing all "register"s doesn't disable this bug!
352 Nothing simpler than this seems to work. */
353 unsigned char *p = & XSTRING (val)->data[toindex++];
354 *p = XINT (elt);
355 #else
356 XSTRING (val)->data[toindex++] = XINT (elt);
357 #endif
358 }
359 }
360 }
361 }
362 if (!NILP (prev))
363 XCONS (prev)->cdr = last_tail;
364
365 return val;
366 }
367 \f
368 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
369 "Return a copy of ALIST.\n\
370 This is an alist which represents the same mapping from objects to objects,\n\
371 but does not share the alist structure with ALIST.\n\
372 The objects mapped (cars and cdrs of elements of the alist)\n\
373 are shared, however.\n\
374 Elements of ALIST that are not conses are also shared.")
375 (alist)
376 Lisp_Object alist;
377 {
378 register Lisp_Object tem;
379
380 CHECK_LIST (alist, 0);
381 if (NILP (alist))
382 return alist;
383 alist = concat (1, &alist, Lisp_Cons, 0);
384 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
385 {
386 register Lisp_Object car;
387 car = XCONS (tem)->car;
388
389 if (CONSP (car))
390 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
391 }
392 return alist;
393 }
394
395 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
396 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
397 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
398 If FROM or TO is negative, it counts from the end.")
399 (string, from, to)
400 Lisp_Object string;
401 register Lisp_Object from, to;
402 {
403 Lisp_Object res;
404
405 CHECK_STRING (string, 0);
406 CHECK_NUMBER (from, 1);
407 if (NILP (to))
408 to = Flength (string);
409 else
410 CHECK_NUMBER (to, 2);
411
412 if (XINT (from) < 0)
413 XSETINT (from, XINT (from) + XSTRING (string)->size);
414 if (XINT (to) < 0)
415 XSETINT (to, XINT (to) + XSTRING (string)->size);
416 if (!(0 <= XINT (from) && XINT (from) <= XINT (to)
417 && XINT (to) <= XSTRING (string)->size))
418 args_out_of_range_3 (string, from, to);
419
420 res = make_string (XSTRING (string)->data + XINT (from),
421 XINT (to) - XINT (from));
422 copy_text_properties (from, to, string, make_number (0), res, Qnil);
423 return res;
424 }
425 \f
426 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
427 "Take cdr N times on LIST, returns the result.")
428 (n, list)
429 Lisp_Object n;
430 register Lisp_Object list;
431 {
432 register int i, num;
433 CHECK_NUMBER (n, 0);
434 num = XINT (n);
435 for (i = 0; i < num && !NILP (list); i++)
436 {
437 QUIT;
438 list = Fcdr (list);
439 }
440 return list;
441 }
442
443 DEFUN ("nth", Fnth, Snth, 2, 2, 0,
444 "Return the Nth element of LIST.\n\
445 N counts from zero. If LIST is not that long, nil is returned.")
446 (n, list)
447 Lisp_Object n, list;
448 {
449 return Fcar (Fnthcdr (n, list));
450 }
451
452 DEFUN ("elt", Felt, Selt, 2, 2, 0,
453 "Return element of SEQUENCE at index N.")
454 (seq, n)
455 register Lisp_Object seq, n;
456 {
457 CHECK_NUMBER (n, 0);
458 while (1)
459 {
460 if (XTYPE (seq) == Lisp_Cons || NILP (seq))
461 return Fcar (Fnthcdr (n, seq));
462 else if (XTYPE (seq) == Lisp_String
463 || XTYPE (seq) == Lisp_Vector)
464 return Faref (seq, n);
465 else
466 seq = wrong_type_argument (Qsequencep, seq);
467 }
468 }
469
470 DEFUN ("member", Fmember, Smember, 2, 2, 0,
471 "Return non-nil if ELT is an element of LIST. Comparison done with EQUAL.\n\
472 The value is actually the tail of LIST whose car is ELT.")
473 (elt, list)
474 register Lisp_Object elt;
475 Lisp_Object list;
476 {
477 register Lisp_Object tail;
478 for (tail = list; !NILP (tail); tail = Fcdr (tail))
479 {
480 register Lisp_Object tem;
481 tem = Fcar (tail);
482 if (! NILP (Fequal (elt, tem)))
483 return tail;
484 QUIT;
485 }
486 return Qnil;
487 }
488
489 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
490 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
491 The value is actually the tail of LIST whose car is ELT.")
492 (elt, list)
493 register Lisp_Object elt;
494 Lisp_Object list;
495 {
496 register Lisp_Object tail;
497 for (tail = list; !NILP (tail); tail = Fcdr (tail))
498 {
499 register Lisp_Object tem;
500 tem = Fcar (tail);
501 if (EQ (elt, tem)) return tail;
502 QUIT;
503 }
504 return Qnil;
505 }
506
507 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
508 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
509 The value is actually the element of LIST whose car is KEY.\n\
510 Elements of LIST that are not conses are ignored.")
511 (key, list)
512 register Lisp_Object key;
513 Lisp_Object list;
514 {
515 register Lisp_Object tail;
516 for (tail = list; !NILP (tail); tail = Fcdr (tail))
517 {
518 register Lisp_Object elt, tem;
519 elt = Fcar (tail);
520 if (!CONSP (elt)) continue;
521 tem = Fcar (elt);
522 if (EQ (key, tem)) return elt;
523 QUIT;
524 }
525 return Qnil;
526 }
527
528 /* Like Fassq but never report an error and do not allow quits.
529 Use only on lists known never to be circular. */
530
531 Lisp_Object
532 assq_no_quit (key, list)
533 register Lisp_Object key;
534 Lisp_Object list;
535 {
536 register Lisp_Object tail;
537 for (tail = list; CONSP (tail); tail = Fcdr (tail))
538 {
539 register Lisp_Object elt, tem;
540 elt = Fcar (tail);
541 if (!CONSP (elt)) continue;
542 tem = Fcar (elt);
543 if (EQ (key, tem)) return elt;
544 }
545 return Qnil;
546 }
547
548 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
549 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
550 The value is actually the element of LIST whose car is KEY.")
551 (key, list)
552 register Lisp_Object key;
553 Lisp_Object list;
554 {
555 register Lisp_Object tail;
556 for (tail = list; !NILP (tail); tail = Fcdr (tail))
557 {
558 register Lisp_Object elt, tem;
559 elt = Fcar (tail);
560 if (!CONSP (elt)) continue;
561 tem = Fequal (Fcar (elt), key);
562 if (!NILP (tem)) return elt;
563 QUIT;
564 }
565 return Qnil;
566 }
567
568 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
569 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
570 The value is actually the element of LIST whose cdr is ELT.")
571 (key, list)
572 register Lisp_Object key;
573 Lisp_Object list;
574 {
575 register Lisp_Object tail;
576 for (tail = list; !NILP (tail); tail = Fcdr (tail))
577 {
578 register Lisp_Object elt, tem;
579 elt = Fcar (tail);
580 if (!CONSP (elt)) continue;
581 tem = Fcdr (elt);
582 if (EQ (key, tem)) return elt;
583 QUIT;
584 }
585 return Qnil;
586 }
587 \f
588 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
589 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
590 The modified LIST is returned. Comparison is done with `eq'.\n\
591 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
592 therefore, write `(setq foo (delq element foo))'\n\
593 to be sure of changing the value of `foo'.")
594 (elt, list)
595 register Lisp_Object elt;
596 Lisp_Object list;
597 {
598 register Lisp_Object tail, prev;
599 register Lisp_Object tem;
600
601 tail = list;
602 prev = Qnil;
603 while (!NILP (tail))
604 {
605 tem = Fcar (tail);
606 if (EQ (elt, tem))
607 {
608 if (NILP (prev))
609 list = Fcdr (tail);
610 else
611 Fsetcdr (prev, Fcdr (tail));
612 }
613 else
614 prev = tail;
615 tail = Fcdr (tail);
616 QUIT;
617 }
618 return list;
619 }
620
621 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
622 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
623 The modified LIST is returned. Comparison is done with `equal'.\n\
624 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
625 therefore, write `(setq foo (delete element foo))'\n\
626 to be sure of changing the value of `foo'.")
627 (elt, list)
628 register Lisp_Object elt;
629 Lisp_Object list;
630 {
631 register Lisp_Object tail, prev;
632 register Lisp_Object tem;
633
634 tail = list;
635 prev = Qnil;
636 while (!NILP (tail))
637 {
638 tem = Fcar (tail);
639 if (! NILP (Fequal (elt, tem)))
640 {
641 if (NILP (prev))
642 list = Fcdr (tail);
643 else
644 Fsetcdr (prev, Fcdr (tail));
645 }
646 else
647 prev = tail;
648 tail = Fcdr (tail);
649 QUIT;
650 }
651 return list;
652 }
653
654 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
655 "Reverse LIST by modifying cdr pointers.\n\
656 Returns the beginning of the reversed list.")
657 (list)
658 Lisp_Object list;
659 {
660 register Lisp_Object prev, tail, next;
661
662 if (NILP (list)) return list;
663 prev = Qnil;
664 tail = list;
665 while (!NILP (tail))
666 {
667 QUIT;
668 next = Fcdr (tail);
669 Fsetcdr (tail, prev);
670 prev = tail;
671 tail = next;
672 }
673 return prev;
674 }
675
676 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
677 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
678 See also the function `nreverse', which is used more often.")
679 (list)
680 Lisp_Object list;
681 {
682 Lisp_Object length;
683 register Lisp_Object *vec;
684 register Lisp_Object tail;
685 register int i;
686
687 length = Flength (list);
688 vec = (Lisp_Object *) alloca (XINT (length) * sizeof (Lisp_Object));
689 for (i = XINT (length) - 1, tail = list; i >= 0; i--, tail = Fcdr (tail))
690 vec[i] = Fcar (tail);
691
692 return Flist (XINT (length), vec);
693 }
694 \f
695 Lisp_Object merge ();
696
697 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
698 "Sort LIST, stably, comparing elements using PREDICATE.\n\
699 Returns the sorted list. LIST is modified by side effects.\n\
700 PREDICATE is called with two elements of LIST, and should return T\n\
701 if the first element is \"less\" than the second.")
702 (list, pred)
703 Lisp_Object list, pred;
704 {
705 Lisp_Object front, back;
706 register Lisp_Object len, tem;
707 struct gcpro gcpro1, gcpro2;
708 register int length;
709
710 front = list;
711 len = Flength (list);
712 length = XINT (len);
713 if (length < 2)
714 return list;
715
716 XSETINT (len, (length / 2) - 1);
717 tem = Fnthcdr (len, list);
718 back = Fcdr (tem);
719 Fsetcdr (tem, Qnil);
720
721 GCPRO2 (front, back);
722 front = Fsort (front, pred);
723 back = Fsort (back, pred);
724 UNGCPRO;
725 return merge (front, back, pred);
726 }
727
728 Lisp_Object
729 merge (org_l1, org_l2, pred)
730 Lisp_Object org_l1, org_l2;
731 Lisp_Object pred;
732 {
733 Lisp_Object value;
734 register Lisp_Object tail;
735 Lisp_Object tem;
736 register Lisp_Object l1, l2;
737 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
738
739 l1 = org_l1;
740 l2 = org_l2;
741 tail = Qnil;
742 value = Qnil;
743
744 /* It is sufficient to protect org_l1 and org_l2.
745 When l1 and l2 are updated, we copy the new values
746 back into the org_ vars. */
747 GCPRO4 (org_l1, org_l2, pred, value);
748
749 while (1)
750 {
751 if (NILP (l1))
752 {
753 UNGCPRO;
754 if (NILP (tail))
755 return l2;
756 Fsetcdr (tail, l2);
757 return value;
758 }
759 if (NILP (l2))
760 {
761 UNGCPRO;
762 if (NILP (tail))
763 return l1;
764 Fsetcdr (tail, l1);
765 return value;
766 }
767 tem = call2 (pred, Fcar (l2), Fcar (l1));
768 if (NILP (tem))
769 {
770 tem = l1;
771 l1 = Fcdr (l1);
772 org_l1 = l1;
773 }
774 else
775 {
776 tem = l2;
777 l2 = Fcdr (l2);
778 org_l2 = l2;
779 }
780 if (NILP (tail))
781 value = tem;
782 else
783 Fsetcdr (tail, tem);
784 tail = tem;
785 }
786 }
787 \f
788 DEFUN ("get", Fget, Sget, 2, 2, 0,
789 "Return the value of SYMBOL's PROPNAME property.\n\
790 This is the last VALUE stored with `(put SYMBOL PROPNAME VALUE)'.")
791 (sym, prop)
792 Lisp_Object sym;
793 register Lisp_Object prop;
794 {
795 register Lisp_Object tail;
796 for (tail = Fsymbol_plist (sym); !NILP (tail); tail = Fcdr (Fcdr (tail)))
797 {
798 register Lisp_Object tem;
799 tem = Fcar (tail);
800 if (EQ (prop, tem))
801 return Fcar (Fcdr (tail));
802 }
803 return Qnil;
804 }
805
806 DEFUN ("put", Fput, Sput, 3, 3, 0,
807 "Store SYMBOL's PROPNAME property with value VALUE.\n\
808 It can be retrieved with `(get SYMBOL PROPNAME)'.")
809 (sym, prop, val)
810 Lisp_Object sym;
811 register Lisp_Object prop;
812 Lisp_Object val;
813 {
814 register Lisp_Object tail, prev;
815 Lisp_Object newcell;
816 prev = Qnil;
817 for (tail = Fsymbol_plist (sym); !NILP (tail); tail = Fcdr (Fcdr (tail)))
818 {
819 register Lisp_Object tem;
820 tem = Fcar (tail);
821 if (EQ (prop, tem))
822 return Fsetcar (Fcdr (tail), val);
823 prev = tail;
824 }
825 newcell = Fcons (prop, Fcons (val, Qnil));
826 if (NILP (prev))
827 Fsetplist (sym, newcell);
828 else
829 Fsetcdr (Fcdr (prev), newcell);
830 return val;
831 }
832
833 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
834 "T if two Lisp objects have similar structure and contents.\n\
835 They must have the same data type.\n\
836 Conses are compared by comparing the cars and the cdrs.\n\
837 Vectors and strings are compared element by element.\n\
838 Numbers are compared by value, but integers cannot equal floats.\n\
839 (Use `=' if you want integers and floats to be able to be equal.)\n\
840 Symbols must match exactly.")
841 (o1, o2)
842 register Lisp_Object o1, o2;
843 {
844 return internal_equal (o1, o2, 0);
845 }
846
847 static Lisp_Object
848 internal_equal (o1, o2, depth)
849 register Lisp_Object o1, o2;
850 int depth;
851 {
852 if (depth > 200)
853 error ("Stack overflow in equal");
854 do_cdr:
855 QUIT;
856 if (EQ (o1, o2)) return Qt;
857 #ifdef LISP_FLOAT_TYPE
858 if (FLOATP (o1) && FLOATP (o2))
859 return (extract_float (o1) == extract_float (o2)) ? Qt : Qnil;
860 #endif
861 if (XTYPE (o1) != XTYPE (o2)) return Qnil;
862 if (XTYPE (o1) == Lisp_Cons
863 || XTYPE (o1) == Lisp_Overlay)
864 {
865 Lisp_Object v1;
866 v1 = internal_equal (Fcar (o1), Fcar (o2), depth + 1);
867 if (NILP (v1))
868 return v1;
869 o1 = Fcdr (o1), o2 = Fcdr (o2);
870 goto do_cdr;
871 }
872 if (XTYPE (o1) == Lisp_Marker)
873 {
874 return ((XMARKER (o1)->buffer == XMARKER (o2)->buffer
875 && (XMARKER (o1)->buffer == 0
876 || XMARKER (o1)->bufpos == XMARKER (o2)->bufpos))
877 ? Qt : Qnil);
878 }
879 if (XTYPE (o1) == Lisp_Vector
880 || XTYPE (o1) == Lisp_Compiled)
881 {
882 register int index;
883 if (XVECTOR (o1)->size != XVECTOR (o2)->size)
884 return Qnil;
885 for (index = 0; index < XVECTOR (o1)->size; index++)
886 {
887 Lisp_Object v, v1, v2;
888 v1 = XVECTOR (o1)->contents [index];
889 v2 = XVECTOR (o2)->contents [index];
890 v = internal_equal (v1, v2, depth + 1);
891 if (NILP (v)) return v;
892 }
893 return Qt;
894 }
895 if (XTYPE (o1) == Lisp_String)
896 {
897 if (XSTRING (o1)->size != XSTRING (o2)->size)
898 return Qnil;
899 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data, XSTRING (o1)->size))
900 return Qnil;
901 return Qt;
902 }
903 return Qnil;
904 }
905 \f
906 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
907 "Store each element of ARRAY with ITEM. ARRAY is a vector or string.")
908 (array, item)
909 Lisp_Object array, item;
910 {
911 register int size, index, charval;
912 retry:
913 if (XTYPE (array) == Lisp_Vector)
914 {
915 register Lisp_Object *p = XVECTOR (array)->contents;
916 size = XVECTOR (array)->size;
917 for (index = 0; index < size; index++)
918 p[index] = item;
919 }
920 else if (XTYPE (array) == Lisp_String)
921 {
922 register unsigned char *p = XSTRING (array)->data;
923 CHECK_NUMBER (item, 1);
924 charval = XINT (item);
925 size = XSTRING (array)->size;
926 for (index = 0; index < size; index++)
927 p[index] = charval;
928 }
929 else
930 {
931 array = wrong_type_argument (Qarrayp, array);
932 goto retry;
933 }
934 return array;
935 }
936
937 /* ARGSUSED */
938 Lisp_Object
939 nconc2 (s1, s2)
940 Lisp_Object s1, s2;
941 {
942 #ifdef NO_ARG_ARRAY
943 Lisp_Object args[2];
944 args[0] = s1;
945 args[1] = s2;
946 return Fnconc (2, args);
947 #else
948 return Fnconc (2, &s1);
949 #endif /* NO_ARG_ARRAY */
950 }
951
952 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
953 "Concatenate any number of lists by altering them.\n\
954 Only the last argument is not altered, and need not be a list.")
955 (nargs, args)
956 int nargs;
957 Lisp_Object *args;
958 {
959 register int argnum;
960 register Lisp_Object tail, tem, val;
961
962 val = Qnil;
963
964 for (argnum = 0; argnum < nargs; argnum++)
965 {
966 tem = args[argnum];
967 if (NILP (tem)) continue;
968
969 if (NILP (val))
970 val = tem;
971
972 if (argnum + 1 == nargs) break;
973
974 if (!CONSP (tem))
975 tem = wrong_type_argument (Qlistp, tem);
976
977 while (CONSP (tem))
978 {
979 tail = tem;
980 tem = Fcdr (tail);
981 QUIT;
982 }
983
984 tem = args[argnum + 1];
985 Fsetcdr (tail, tem);
986 if (NILP (tem))
987 args[argnum + 1] = tail;
988 }
989
990 return val;
991 }
992 \f
993 /* This is the guts of all mapping functions.
994 Apply fn to each element of seq, one by one,
995 storing the results into elements of vals, a C vector of Lisp_Objects.
996 leni is the length of vals, which should also be the length of seq. */
997
998 static void
999 mapcar1 (leni, vals, fn, seq)
1000 int leni;
1001 Lisp_Object *vals;
1002 Lisp_Object fn, seq;
1003 {
1004 register Lisp_Object tail;
1005 Lisp_Object dummy;
1006 register int i;
1007 struct gcpro gcpro1, gcpro2, gcpro3;
1008
1009 /* Don't let vals contain any garbage when GC happens. */
1010 for (i = 0; i < leni; i++)
1011 vals[i] = Qnil;
1012
1013 GCPRO3 (dummy, fn, seq);
1014 gcpro1.var = vals;
1015 gcpro1.nvars = leni;
1016 /* We need not explicitly protect `tail' because it is used only on lists, and
1017 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1018
1019 if (XTYPE (seq) == Lisp_Vector)
1020 {
1021 for (i = 0; i < leni; i++)
1022 {
1023 dummy = XVECTOR (seq)->contents[i];
1024 vals[i] = call1 (fn, dummy);
1025 }
1026 }
1027 else if (XTYPE (seq) == Lisp_String)
1028 {
1029 for (i = 0; i < leni; i++)
1030 {
1031 XFASTINT (dummy) = XSTRING (seq)->data[i];
1032 vals[i] = call1 (fn, dummy);
1033 }
1034 }
1035 else /* Must be a list, since Flength did not get an error */
1036 {
1037 tail = seq;
1038 for (i = 0; i < leni; i++)
1039 {
1040 vals[i] = call1 (fn, Fcar (tail));
1041 tail = Fcdr (tail);
1042 }
1043 }
1044
1045 UNGCPRO;
1046 }
1047
1048 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
1049 "Apply FN to each element of SEQ, and concat the results as strings.\n\
1050 In between each pair of results, stick in SEP.\n\
1051 Thus, \" \" as SEP results in spaces between the values returned by FN.")
1052 (fn, seq, sep)
1053 Lisp_Object fn, seq, sep;
1054 {
1055 Lisp_Object len;
1056 register int leni;
1057 int nargs;
1058 register Lisp_Object *args;
1059 register int i;
1060 struct gcpro gcpro1;
1061
1062 len = Flength (seq);
1063 leni = XINT (len);
1064 nargs = leni + leni - 1;
1065 if (nargs < 0) return build_string ("");
1066
1067 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
1068
1069 GCPRO1 (sep);
1070 mapcar1 (leni, args, fn, seq);
1071 UNGCPRO;
1072
1073 for (i = leni - 1; i >= 0; i--)
1074 args[i + i] = args[i];
1075
1076 for (i = 1; i < nargs; i += 2)
1077 args[i] = sep;
1078
1079 return Fconcat (nargs, args);
1080 }
1081
1082 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
1083 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
1084 The result is a list just as long as SEQUENCE.\n\
1085 SEQUENCE may be a list, a vector or a string.")
1086 (fn, seq)
1087 Lisp_Object fn, seq;
1088 {
1089 register Lisp_Object len;
1090 register int leni;
1091 register Lisp_Object *args;
1092
1093 len = Flength (seq);
1094 leni = XFASTINT (len);
1095 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
1096
1097 mapcar1 (leni, args, fn, seq);
1098
1099 return Flist (leni, args);
1100 }
1101 \f
1102 /* Anything that calls this function must protect from GC! */
1103
1104 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
1105 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
1106 Takes one argument, which is the string to display to ask the question.\n\
1107 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
1108 No confirmation of the answer is requested; a single character is enough.\n\
1109 Also accepts Space to mean yes, or Delete to mean no.")
1110 (prompt)
1111 Lisp_Object prompt;
1112 {
1113 register Lisp_Object obj, key, def, answer_string, map;
1114 register int answer;
1115 Lisp_Object xprompt;
1116 Lisp_Object args[2];
1117 int ocech = cursor_in_echo_area;
1118 struct gcpro gcpro1, gcpro2;
1119
1120 map = Fsymbol_value (intern ("query-replace-map"));
1121
1122 CHECK_STRING (prompt, 0);
1123 xprompt = prompt;
1124 GCPRO2 (prompt, xprompt);
1125
1126 while (1)
1127 {
1128 cursor_in_echo_area = 1;
1129 message ("%s(y or n) ", XSTRING (xprompt)->data);
1130
1131 obj = read_filtered_event (1, 0, 0);
1132 cursor_in_echo_area = 0;
1133 /* If we need to quit, quit with cursor_in_echo_area = 0. */
1134 QUIT;
1135
1136 key = Fmake_vector (make_number (1), obj);
1137 def = Flookup_key (map, key);
1138 answer_string = Fsingle_key_description (obj);
1139
1140 if (EQ (def, intern ("skip")))
1141 {
1142 answer = 0;
1143 break;
1144 }
1145 else if (EQ (def, intern ("act")))
1146 {
1147 answer = 1;
1148 break;
1149 }
1150 else if (EQ (def, intern ("recenter")))
1151 {
1152 Frecenter (Qnil);
1153 xprompt = prompt;
1154 continue;
1155 }
1156 else if (EQ (def, intern ("quit")))
1157 Vquit_flag = Qt;
1158
1159 QUIT;
1160
1161 /* If we don't clear this, then the next call to read_char will
1162 return quit_char again, and we'll enter an infinite loop. */
1163 Vquit_flag = Qnil;
1164
1165 Fding (Qnil);
1166 Fdiscard_input ();
1167 if (EQ (xprompt, prompt))
1168 {
1169 args[0] = build_string ("Please answer y or n. ");
1170 args[1] = prompt;
1171 xprompt = Fconcat (2, args);
1172 }
1173 }
1174 UNGCPRO;
1175
1176 if (! noninteractive)
1177 {
1178 cursor_in_echo_area = -1;
1179 message ("%s(y or n) %c", XSTRING (xprompt)->data, answer ? 'y' : 'n');
1180 cursor_in_echo_area = ocech;
1181 }
1182
1183 return answer ? Qt : Qnil;
1184 }
1185 \f
1186 /* This is how C code calls `yes-or-no-p' and allows the user
1187 to redefined it.
1188
1189 Anything that calls this function must protect from GC! */
1190
1191 Lisp_Object
1192 do_yes_or_no_p (prompt)
1193 Lisp_Object prompt;
1194 {
1195 return call1 (intern ("yes-or-no-p"), prompt);
1196 }
1197
1198 /* Anything that calls this function must protect from GC! */
1199
1200 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
1201 "Ask user a yes-or-no question. Return t if answer is yes.\n\
1202 Takes one argument, which is the string to display to ask the question.\n\
1203 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
1204 The user must confirm the answer with RET,\n\
1205 and can edit it until it as been confirmed.")
1206 (prompt)
1207 Lisp_Object prompt;
1208 {
1209 register Lisp_Object ans;
1210 Lisp_Object args[2];
1211 struct gcpro gcpro1;
1212
1213 CHECK_STRING (prompt, 0);
1214
1215 args[0] = prompt;
1216 args[1] = build_string ("(yes or no) ");
1217 prompt = Fconcat (2, args);
1218
1219 GCPRO1 (prompt);
1220 while (1)
1221 {
1222 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
1223 Qyes_or_no_p_history));
1224 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
1225 {
1226 UNGCPRO;
1227 return Qt;
1228 }
1229 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
1230 {
1231 UNGCPRO;
1232 return Qnil;
1233 }
1234
1235 Fding (Qnil);
1236 Fdiscard_input ();
1237 message ("Please answer yes or no.");
1238 Fsleep_for (make_number (2), Qnil);
1239 }
1240 }
1241 \f
1242 DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0,
1243 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
1244 Each of the three load averages is multiplied by 100,\n\
1245 then converted to integer.\n\
1246 If the 5-minute or 15-minute load averages are not available, return a\n\
1247 shortened list, containing only those averages which are available.")
1248 ()
1249 {
1250 double load_ave[3];
1251 int loads = getloadavg (load_ave, 3);
1252 Lisp_Object ret;
1253
1254 if (loads < 0)
1255 error ("load-average not implemented for this operating system");
1256
1257 ret = Qnil;
1258 while (loads > 0)
1259 ret = Fcons (make_number ((int) (load_ave[--loads] * 100.0)), ret);
1260
1261 return ret;
1262 }
1263 \f
1264 Lisp_Object Vfeatures;
1265
1266 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
1267 "Returns t if FEATURE is present in this Emacs.\n\
1268 Use this to conditionalize execution of lisp code based on the presence or\n\
1269 absence of emacs or environment extensions.\n\
1270 Use `provide' to declare that a feature is available.\n\
1271 This function looks at the value of the variable `features'.")
1272 (feature)
1273 Lisp_Object feature;
1274 {
1275 register Lisp_Object tem;
1276 CHECK_SYMBOL (feature, 0);
1277 tem = Fmemq (feature, Vfeatures);
1278 return (NILP (tem)) ? Qnil : Qt;
1279 }
1280
1281 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
1282 "Announce that FEATURE is a feature of the current Emacs.")
1283 (feature)
1284 Lisp_Object feature;
1285 {
1286 register Lisp_Object tem;
1287 CHECK_SYMBOL (feature, 0);
1288 if (!NILP (Vautoload_queue))
1289 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
1290 tem = Fmemq (feature, Vfeatures);
1291 if (NILP (tem))
1292 Vfeatures = Fcons (feature, Vfeatures);
1293 LOADHIST_ATTACH (Fcons (Qprovide, feature));
1294 return feature;
1295 }
1296
1297 DEFUN ("require", Frequire, Srequire, 1, 2, 0,
1298 "If feature FEATURE is not loaded, load it from FILENAME.\n\
1299 If FEATURE is not a member of the list `features', then the feature\n\
1300 is not loaded; so load the file FILENAME.\n\
1301 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
1302 (feature, file_name)
1303 Lisp_Object feature, file_name;
1304 {
1305 register Lisp_Object tem;
1306 CHECK_SYMBOL (feature, 0);
1307 tem = Fmemq (feature, Vfeatures);
1308 LOADHIST_ATTACH (Fcons (Qrequire, feature));
1309 if (NILP (tem))
1310 {
1311 int count = specpdl_ptr - specpdl;
1312
1313 /* Value saved here is to be restored into Vautoload_queue */
1314 record_unwind_protect (un_autoload, Vautoload_queue);
1315 Vautoload_queue = Qt;
1316
1317 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
1318 Qnil, Qt, Qnil);
1319
1320 tem = Fmemq (feature, Vfeatures);
1321 if (NILP (tem))
1322 error ("Required feature %s was not provided",
1323 XSYMBOL (feature)->name->data );
1324
1325 /* Once loading finishes, don't undo it. */
1326 Vautoload_queue = Qt;
1327 feature = unbind_to (count, feature);
1328 }
1329 return feature;
1330 }
1331 \f
1332 syms_of_fns ()
1333 {
1334 Qstring_lessp = intern ("string-lessp");
1335 staticpro (&Qstring_lessp);
1336 Qprovide = intern ("provide");
1337 staticpro (&Qprovide);
1338 Qrequire = intern ("require");
1339 staticpro (&Qrequire);
1340 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
1341 staticpro (&Qyes_or_no_p_history);
1342
1343 DEFVAR_LISP ("features", &Vfeatures,
1344 "A list of symbols which are the features of the executing emacs.\n\
1345 Used by `featurep' and `require', and altered by `provide'.");
1346 Vfeatures = Qnil;
1347
1348 defsubr (&Sidentity);
1349 defsubr (&Srandom);
1350 defsubr (&Slength);
1351 defsubr (&Sstring_equal);
1352 defsubr (&Sstring_lessp);
1353 defsubr (&Sappend);
1354 defsubr (&Sconcat);
1355 defsubr (&Svconcat);
1356 defsubr (&Scopy_sequence);
1357 defsubr (&Scopy_alist);
1358 defsubr (&Ssubstring);
1359 defsubr (&Snthcdr);
1360 defsubr (&Snth);
1361 defsubr (&Selt);
1362 defsubr (&Smember);
1363 defsubr (&Smemq);
1364 defsubr (&Sassq);
1365 defsubr (&Sassoc);
1366 defsubr (&Srassq);
1367 defsubr (&Sdelq);
1368 defsubr (&Sdelete);
1369 defsubr (&Snreverse);
1370 defsubr (&Sreverse);
1371 defsubr (&Ssort);
1372 defsubr (&Sget);
1373 defsubr (&Sput);
1374 defsubr (&Sequal);
1375 defsubr (&Sfillarray);
1376 defsubr (&Snconc);
1377 defsubr (&Smapcar);
1378 defsubr (&Smapconcat);
1379 defsubr (&Sy_or_n_p);
1380 defsubr (&Syes_or_no_p);
1381 defsubr (&Sload_average);
1382 defsubr (&Sfeaturep);
1383 defsubr (&Srequire);
1384 defsubr (&Sprovide);
1385 }