1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 86, 87, 93, 94, 95 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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)
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.
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. */
23 /* Note on some machines this defines `vector' as a typedef,
24 so make sure we don't use that name in this file. */
33 #include "intervals.h"
36 #define NULL (void *)0
39 extern Lisp_Object
Flookup_key ();
41 Lisp_Object Qstring_lessp
, Qprovide
, Qrequire
;
42 Lisp_Object Qyes_or_no_p_history
;
44 static int internal_equal ();
46 DEFUN ("identity", Fidentity
, Sidentity
, 1, 1, 0,
47 "Return the argument unchanged.")
54 extern long get_random ();
55 extern void seed_random ();
58 DEFUN ("random", Frandom
, Srandom
, 0, 1, 0,
59 "Return a pseudo-random number.\n\
60 All integers representable in Lisp are equally likely.\n\
61 On most systems, this is 28 bits' worth.\n\
62 With positive integer argument N, return random number in interval [0,N).\n\
63 With argument t, set the random number seed from the current time and pid.")
68 Lisp_Object lispy_val
;
69 unsigned long denominator
;
72 seed_random (getpid () + time (NULL
));
73 if (NATNUMP (limit
) && XFASTINT (limit
) != 0)
75 /* Try to take our random number from the higher bits of VAL,
76 not the lower, since (says Gentzel) the low bits of `random'
77 are less random than the higher ones. We do this by using the
78 quotient rather than the remainder. At the high end of the RNG
79 it's possible to get a quotient larger than limit; discarding
80 these values eliminates the bias that would otherwise appear
81 when using a large limit. */
82 denominator
= ((unsigned long)1 << VALBITS
) / XFASTINT (limit
);
84 val
= get_random () / denominator
;
85 while (val
>= XFASTINT (limit
));
89 XSETINT (lispy_val
, val
);
93 /* Random data-structure functions */
95 DEFUN ("length", Flength
, Slength
, 1, 1, 0,
96 "Return the length of vector, list or string SEQUENCE.\n\
97 A byte-code function object is also allowed.")
99 register Lisp_Object obj
;
101 register Lisp_Object tail
, val
;
106 XSETFASTINT (val
, XSTRING (obj
)->size
);
107 else if (VECTORP (obj
))
108 XSETFASTINT (val
, XVECTOR (obj
)->size
);
109 else if (COMPILEDP (obj
))
110 XSETFASTINT (val
, XVECTOR (obj
)->size
& PSEUDOVECTOR_SIZE_MASK
);
111 else if (CONSP (obj
))
113 for (i
= 0, tail
= obj
; !NILP (tail
); i
++)
119 XSETFASTINT (val
, i
);
122 XSETFASTINT (val
, 0);
125 obj
= wrong_type_argument (Qsequencep
, obj
);
131 /* This does not check for quits. That is safe
132 since it must terminate. */
134 DEFUN ("safe-length", Fsafe_length
, Ssafe_length
, 1, 1, 0,
135 "Return the length of a list, but avoid error or infinite loop.\n\
136 This function never gets an error. If LIST is not really a list,\n\
137 it returns 0. If LIST is circular, it returns a finite value\n\
138 which is at least the number of distinct elements.")
142 Lisp_Object tail
, halftail
, length
;
145 /* halftail is used to detect circular lists. */
147 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
149 if (EQ (tail
, halftail
) && len
!= 0)
156 halftail
= XCONS (halftail
)->cdr
;
159 XSETINT (length
, len
);
163 DEFUN ("string-equal", Fstring_equal
, Sstring_equal
, 2, 2, 0,
164 "T if two strings have identical contents.\n\
165 Case is significant, but text properties are ignored.\n\
166 Symbols are also allowed; their print names are used instead.")
168 register Lisp_Object s1
, s2
;
171 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
173 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
174 CHECK_STRING (s1
, 0);
175 CHECK_STRING (s2
, 1);
177 if (XSTRING (s1
)->size
!= XSTRING (s2
)->size
||
178 bcmp (XSTRING (s1
)->data
, XSTRING (s2
)->data
, XSTRING (s1
)->size
))
183 DEFUN ("string-lessp", Fstring_lessp
, Sstring_lessp
, 2, 2, 0,
184 "T if first arg string is less than second in lexicographic order.\n\
185 Case is significant.\n\
186 Symbols are also allowed; their print names are used instead.")
188 register Lisp_Object s1
, s2
;
191 register unsigned char *p1
, *p2
;
195 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
197 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
198 CHECK_STRING (s1
, 0);
199 CHECK_STRING (s2
, 1);
201 p1
= XSTRING (s1
)->data
;
202 p2
= XSTRING (s2
)->data
;
203 end
= XSTRING (s1
)->size
;
204 if (end
> XSTRING (s2
)->size
)
205 end
= XSTRING (s2
)->size
;
207 for (i
= 0; i
< end
; i
++)
210 return p1
[i
] < p2
[i
] ? Qt
: Qnil
;
212 return i
< XSTRING (s2
)->size
? Qt
: Qnil
;
215 static Lisp_Object
concat ();
226 return concat (2, args
, Lisp_String
, 0);
228 return concat (2, &s1
, Lisp_String
, 0);
229 #endif /* NO_ARG_ARRAY */
235 Lisp_Object s1
, s2
, s3
;
242 return concat (3, args
, Lisp_String
, 0);
244 return concat (3, &s1
, Lisp_String
, 0);
245 #endif /* NO_ARG_ARRAY */
248 DEFUN ("append", Fappend
, Sappend
, 0, MANY
, 0,
249 "Concatenate all the arguments and make the result a list.\n\
250 The result is a list whose elements are the elements of all the arguments.\n\
251 Each argument may be a list, vector or string.\n\
252 The last argument is not copied, just used as the tail of the new list.")
257 return concat (nargs
, args
, Lisp_Cons
, 1);
260 DEFUN ("concat", Fconcat
, Sconcat
, 0, MANY
, 0,
261 "Concatenate all the arguments and make the result a string.\n\
262 The result is a string whose elements are the elements of all the arguments.\n\
263 Each argument may be a string or a list or vector of characters (integers).\n\
265 Do not use individual integers as arguments!\n\
266 The behavior of `concat' in that case will be changed later!\n\
267 If your program passes an integer as an argument to `concat',\n\
268 you should change it right away not to do so.")
273 return concat (nargs
, args
, Lisp_String
, 0);
276 DEFUN ("vconcat", Fvconcat
, Svconcat
, 0, MANY
, 0,
277 "Concatenate all the arguments and make the result a vector.\n\
278 The result is a vector whose elements are the elements of all the arguments.\n\
279 Each argument may be a list, vector or string.")
284 return concat (nargs
, args
, Lisp_Vectorlike
, 0);
287 DEFUN ("copy-sequence", Fcopy_sequence
, Scopy_sequence
, 1, 1, 0,
288 "Return a copy of a list, vector or string.\n\
289 The elements of a list or vector are not copied; they are shared\n\
294 if (NILP (arg
)) return arg
;
295 if (!CONSP (arg
) && !VECTORP (arg
) && !STRINGP (arg
))
296 arg
= wrong_type_argument (Qsequencep
, arg
);
297 return concat (1, &arg
, CONSP (arg
) ? Lisp_Cons
: XTYPE (arg
), 0);
301 concat (nargs
, args
, target_type
, last_special
)
304 enum Lisp_Type target_type
;
309 register Lisp_Object tail
;
310 register Lisp_Object
this;
314 Lisp_Object last_tail
;
317 /* In append, the last arg isn't treated like the others */
318 if (last_special
&& nargs
> 0)
321 last_tail
= args
[nargs
];
326 for (argnum
= 0; argnum
< nargs
; argnum
++)
329 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
330 || COMPILEDP (this)))
333 args
[argnum
] = Fnumber_to_string (this);
335 args
[argnum
] = wrong_type_argument (Qsequencep
, this);
339 for (argnum
= 0, leni
= 0; argnum
< nargs
; argnum
++)
342 len
= Flength (this);
343 leni
+= XFASTINT (len
);
346 XSETFASTINT (len
, leni
);
348 if (target_type
== Lisp_Cons
)
349 val
= Fmake_list (len
, Qnil
);
350 else if (target_type
== Lisp_Vectorlike
)
351 val
= Fmake_vector (len
, Qnil
);
353 val
= Fmake_string (len
, len
);
355 /* In append, if all but last arg are nil, return last arg */
356 if (target_type
== Lisp_Cons
&& EQ (val
, Qnil
))
360 tail
= val
, toindex
= -1; /* -1 in toindex is flag we are making a list */
366 for (argnum
= 0; argnum
< nargs
; argnum
++)
370 register int thisindex
= 0;
374 thislen
= Flength (this), thisleni
= XINT (thislen
);
376 if (STRINGP (this) && STRINGP (val
)
377 && ! NULL_INTERVAL_P (XSTRING (this)->intervals
))
379 copy_text_properties (make_number (0), thislen
, this,
380 make_number (toindex
), val
, Qnil
);
385 register Lisp_Object elt
;
387 /* Fetch next element of `this' arg into `elt', or break if
388 `this' is exhausted. */
389 if (NILP (this)) break;
391 elt
= Fcar (this), this = Fcdr (this);
394 if (thisindex
>= thisleni
) break;
396 XSETFASTINT (elt
, XSTRING (this)->data
[thisindex
++]);
398 elt
= XVECTOR (this)->contents
[thisindex
++];
401 /* Store into result */
404 XCONS (tail
)->car
= elt
;
406 tail
= XCONS (tail
)->cdr
;
408 else if (VECTORP (val
))
409 XVECTOR (val
)->contents
[toindex
++] = elt
;
412 while (!INTEGERP (elt
))
413 elt
= wrong_type_argument (Qintegerp
, elt
);
415 #ifdef MASSC_REGISTER_BUG
416 /* Even removing all "register"s doesn't disable this bug!
417 Nothing simpler than this seems to work. */
418 unsigned char *p
= & XSTRING (val
)->data
[toindex
++];
421 XSTRING (val
)->data
[toindex
++] = XINT (elt
);
428 XCONS (prev
)->cdr
= last_tail
;
433 DEFUN ("copy-alist", Fcopy_alist
, Scopy_alist
, 1, 1, 0,
434 "Return a copy of ALIST.\n\
435 This is an alist which represents the same mapping from objects to objects,\n\
436 but does not share the alist structure with ALIST.\n\
437 The objects mapped (cars and cdrs of elements of the alist)\n\
438 are shared, however.\n\
439 Elements of ALIST that are not conses are also shared.")
443 register Lisp_Object tem
;
445 CHECK_LIST (alist
, 0);
448 alist
= concat (1, &alist
, Lisp_Cons
, 0);
449 for (tem
= alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
451 register Lisp_Object car
;
452 car
= XCONS (tem
)->car
;
455 XCONS (tem
)->car
= Fcons (XCONS (car
)->car
, XCONS (car
)->cdr
);
460 DEFUN ("substring", Fsubstring
, Ssubstring
, 2, 3, 0,
461 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
462 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
463 If FROM or TO is negative, it counts from the end.")
466 register Lisp_Object from
, to
;
470 CHECK_STRING (string
, 0);
471 CHECK_NUMBER (from
, 1);
473 to
= Flength (string
);
475 CHECK_NUMBER (to
, 2);
478 XSETINT (from
, XINT (from
) + XSTRING (string
)->size
);
480 XSETINT (to
, XINT (to
) + XSTRING (string
)->size
);
481 if (!(0 <= XINT (from
) && XINT (from
) <= XINT (to
)
482 && XINT (to
) <= XSTRING (string
)->size
))
483 args_out_of_range_3 (string
, from
, to
);
485 res
= make_string (XSTRING (string
)->data
+ XINT (from
),
486 XINT (to
) - XINT (from
));
487 copy_text_properties (from
, to
, string
, make_number (0), res
, Qnil
);
491 DEFUN ("nthcdr", Fnthcdr
, Snthcdr
, 2, 2, 0,
492 "Take cdr N times on LIST, returns the result.")
495 register Lisp_Object list
;
500 for (i
= 0; i
< num
&& !NILP (list
); i
++)
508 DEFUN ("nth", Fnth
, Snth
, 2, 2, 0,
509 "Return the Nth element of LIST.\n\
510 N counts from zero. If LIST is not that long, nil is returned.")
514 return Fcar (Fnthcdr (n
, list
));
517 DEFUN ("elt", Felt
, Selt
, 2, 2, 0,
518 "Return element of SEQUENCE at index N.")
520 register Lisp_Object seq
, n
;
525 if (CONSP (seq
) || NILP (seq
))
526 return Fcar (Fnthcdr (n
, seq
));
527 else if (STRINGP (seq
) || VECTORP (seq
))
528 return Faref (seq
, n
);
530 seq
= wrong_type_argument (Qsequencep
, seq
);
534 DEFUN ("member", Fmember
, Smember
, 2, 2, 0,
535 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
536 The value is actually the tail of LIST whose car is ELT.")
538 register Lisp_Object elt
;
541 register Lisp_Object tail
;
542 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
544 register Lisp_Object tem
;
546 if (! NILP (Fequal (elt
, tem
)))
553 DEFUN ("memq", Fmemq
, Smemq
, 2, 2, 0,
554 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
555 The value is actually the tail of LIST whose car is ELT.")
557 register Lisp_Object elt
;
560 register Lisp_Object tail
;
561 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
563 register Lisp_Object tem
;
565 if (EQ (elt
, tem
)) return tail
;
571 DEFUN ("assq", Fassq
, Sassq
, 2, 2, 0,
572 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
573 The value is actually the element of LIST whose car is KEY.\n\
574 Elements of LIST that are not conses are ignored.")
576 register Lisp_Object key
;
579 register Lisp_Object tail
;
580 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
582 register Lisp_Object elt
, tem
;
584 if (!CONSP (elt
)) continue;
586 if (EQ (key
, tem
)) return elt
;
592 /* Like Fassq but never report an error and do not allow quits.
593 Use only on lists known never to be circular. */
596 assq_no_quit (key
, list
)
597 register Lisp_Object key
;
600 register Lisp_Object tail
;
601 for (tail
= list
; CONSP (tail
); tail
= Fcdr (tail
))
603 register Lisp_Object elt
, tem
;
605 if (!CONSP (elt
)) continue;
607 if (EQ (key
, tem
)) return elt
;
612 DEFUN ("assoc", Fassoc
, Sassoc
, 2, 2, 0,
613 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
614 The value is actually the element of LIST whose car equals KEY.")
616 register Lisp_Object key
;
619 register Lisp_Object tail
;
620 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
622 register Lisp_Object elt
, tem
;
624 if (!CONSP (elt
)) continue;
625 tem
= Fequal (Fcar (elt
), key
);
626 if (!NILP (tem
)) return elt
;
632 DEFUN ("rassq", Frassq
, Srassq
, 2, 2, 0,
633 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
634 The value is actually the element of LIST whose cdr is ELT.")
636 register Lisp_Object key
;
639 register Lisp_Object tail
;
640 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
642 register Lisp_Object elt
, tem
;
644 if (!CONSP (elt
)) continue;
646 if (EQ (key
, tem
)) return elt
;
652 DEFUN ("rassoc", Frassoc
, Srassoc
, 2, 2, 0,
653 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
654 The value is actually the element of LIST whose cdr equals KEY.")
656 register Lisp_Object key
;
659 register Lisp_Object tail
;
660 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
662 register Lisp_Object elt
, tem
;
664 if (!CONSP (elt
)) continue;
665 tem
= Fequal (Fcdr (elt
), key
);
666 if (!NILP (tem
)) return elt
;
672 DEFUN ("delq", Fdelq
, Sdelq
, 2, 2, 0,
673 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
674 The modified LIST is returned. Comparison is done with `eq'.\n\
675 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
676 therefore, write `(setq foo (delq element foo))'\n\
677 to be sure of changing the value of `foo'.")
679 register Lisp_Object elt
;
682 register Lisp_Object tail
, prev
;
683 register Lisp_Object tem
;
695 Fsetcdr (prev
, Fcdr (tail
));
705 DEFUN ("delete", Fdelete
, Sdelete
, 2, 2, 0,
706 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
707 The modified LIST is returned. Comparison is done with `equal'.\n\
708 If the first member of LIST is ELT, deleting it is not a side effect;\n\
709 it is simply using a different list.\n\
710 Therefore, write `(setq foo (delete element foo))'\n\
711 to be sure of changing the value of `foo'.")
713 register Lisp_Object elt
;
716 register Lisp_Object tail
, prev
;
717 register Lisp_Object tem
;
724 if (! NILP (Fequal (elt
, tem
)))
729 Fsetcdr (prev
, Fcdr (tail
));
739 DEFUN ("nreverse", Fnreverse
, Snreverse
, 1, 1, 0,
740 "Reverse LIST by modifying cdr pointers.\n\
741 Returns the beginning of the reversed list.")
745 register Lisp_Object prev
, tail
, next
;
747 if (NILP (list
)) return list
;
754 Fsetcdr (tail
, prev
);
761 DEFUN ("reverse", Freverse
, Sreverse
, 1, 1, 0,
762 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
763 See also the function `nreverse', which is used more often.")
768 register Lisp_Object
*vec
;
769 register Lisp_Object tail
;
772 length
= Flength (list
);
773 vec
= (Lisp_Object
*) alloca (XINT (length
) * sizeof (Lisp_Object
));
774 for (i
= XINT (length
) - 1, tail
= list
; i
>= 0; i
--, tail
= Fcdr (tail
))
775 vec
[i
] = Fcar (tail
);
777 return Flist (XINT (length
), vec
);
780 Lisp_Object
merge ();
782 DEFUN ("sort", Fsort
, Ssort
, 2, 2, 0,
783 "Sort LIST, stably, comparing elements using PREDICATE.\n\
784 Returns the sorted list. LIST is modified by side effects.\n\
785 PREDICATE is called with two elements of LIST, and should return T\n\
786 if the first element is \"less\" than the second.")
788 Lisp_Object list
, pred
;
790 Lisp_Object front
, back
;
791 register Lisp_Object len
, tem
;
792 struct gcpro gcpro1
, gcpro2
;
796 len
= Flength (list
);
801 XSETINT (len
, (length
/ 2) - 1);
802 tem
= Fnthcdr (len
, list
);
806 GCPRO2 (front
, back
);
807 front
= Fsort (front
, pred
);
808 back
= Fsort (back
, pred
);
810 return merge (front
, back
, pred
);
814 merge (org_l1
, org_l2
, pred
)
815 Lisp_Object org_l1
, org_l2
;
819 register Lisp_Object tail
;
821 register Lisp_Object l1
, l2
;
822 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
829 /* It is sufficient to protect org_l1 and org_l2.
830 When l1 and l2 are updated, we copy the new values
831 back into the org_ vars. */
832 GCPRO4 (org_l1
, org_l2
, pred
, value
);
852 tem
= call2 (pred
, Fcar (l2
), Fcar (l1
));
874 DEFUN ("plist-get", Fplist_get
, Splist_get
, 2, 2, 0,
875 "Extract a value from a property list.\n\
876 PLIST is a property list, which is a list of the form\n\
877 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
878 corresponding to the given PROP, or nil if PROP is not\n\
879 one of the properties on the list.")
882 register Lisp_Object prop
;
884 register Lisp_Object tail
;
885 for (tail
= val
; !NILP (tail
); tail
= Fcdr (Fcdr (tail
)))
887 register Lisp_Object tem
;
890 return Fcar (Fcdr (tail
));
895 DEFUN ("get", Fget
, Sget
, 2, 2, 0,
896 "Return the value of SYMBOL's PROPNAME property.\n\
897 This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
899 Lisp_Object symbol
, propname
;
901 CHECK_SYMBOL (symbol
, 0);
902 return Fplist_get (XSYMBOL (symbol
)->plist
, propname
);
905 DEFUN ("plist-put", Fplist_put
, Splist_put
, 3, 3, 0,
906 "Change value in PLIST of PROP to VAL.\n\
907 PLIST is a property list, which is a list of the form\n\
908 \(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
909 If PROP is already a property on the list, its value is set to VAL,\n\
910 otherwise the new PROP VAL pair is added. The new plist is returned;\n\
911 use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
912 The PLIST is modified by side effects.")
915 register Lisp_Object prop
;
918 register Lisp_Object tail
, prev
;
921 for (tail
= plist
; CONSP (tail
) && CONSP (XCONS (tail
)->cdr
);
922 tail
= XCONS (XCONS (tail
)->cdr
)->cdr
)
924 if (EQ (prop
, XCONS (tail
)->car
))
926 Fsetcar (XCONS (tail
)->cdr
, val
);
931 newcell
= Fcons (prop
, Fcons (val
, Qnil
));
935 Fsetcdr (XCONS (prev
)->cdr
, newcell
);
939 DEFUN ("put", Fput
, Sput
, 3, 3, 0,
940 "Store SYMBOL's PROPNAME property with value VALUE.\n\
941 It can be retrieved with `(get SYMBOL PROPNAME)'.")
942 (symbol
, propname
, value
)
943 Lisp_Object symbol
, propname
, value
;
945 CHECK_SYMBOL (symbol
, 0);
946 XSYMBOL (symbol
)->plist
947 = Fplist_put (XSYMBOL (symbol
)->plist
, propname
, value
);
951 DEFUN ("equal", Fequal
, Sequal
, 2, 2, 0,
952 "T if two Lisp objects have similar structure and contents.\n\
953 They must have the same data type.\n\
954 Conses are compared by comparing the cars and the cdrs.\n\
955 Vectors and strings are compared element by element.\n\
956 Numbers are compared by value, but integers cannot equal floats.\n\
957 (Use `=' if you want integers and floats to be able to be equal.)\n\
958 Symbols must match exactly.")
960 register Lisp_Object o1
, o2
;
962 return internal_equal (o1
, o2
, 0) ? Qt
: Qnil
;
966 internal_equal (o1
, o2
, depth
)
967 register Lisp_Object o1
, o2
;
971 error ("Stack overflow in equal");
977 if (XTYPE (o1
) != XTYPE (o2
))
982 #ifdef LISP_FLOAT_TYPE
984 return (extract_float (o1
) == extract_float (o2
));
988 if (!internal_equal (XCONS (o1
)->car
, XCONS (o2
)->car
, depth
+ 1))
990 o1
= XCONS (o1
)->cdr
;
991 o2
= XCONS (o2
)->cdr
;
995 if (XMISCTYPE (o1
) != XMISCTYPE (o2
))
999 if (!internal_equal (OVERLAY_START (o1
), OVERLAY_START (o1
),
1001 || !internal_equal (OVERLAY_END (o1
), OVERLAY_END (o1
),
1004 o1
= XOVERLAY (o1
)->plist
;
1005 o2
= XOVERLAY (o2
)->plist
;
1010 return (XMARKER (o1
)->buffer
== XMARKER (o2
)->buffer
1011 && (XMARKER (o1
)->buffer
== 0
1012 || XMARKER (o1
)->bufpos
== XMARKER (o2
)->bufpos
));
1016 case Lisp_Vectorlike
:
1018 register int i
, size
;
1019 size
= XVECTOR (o1
)->size
;
1020 /* Pseudovectors have the type encoded in the size field, so this test
1021 actually checks that the objects have the same type as well as the
1023 if (XVECTOR (o2
)->size
!= size
)
1025 /* But only true vectors and compiled functions are actually sensible
1026 to compare, so eliminate the others now. */
1027 if (size
& PSEUDOVECTOR_FLAG
)
1029 if (!(size
& PVEC_COMPILED
))
1031 size
&= PSEUDOVECTOR_SIZE_MASK
;
1033 for (i
= 0; i
< size
; i
++)
1036 v1
= XVECTOR (o1
)->contents
[i
];
1037 v2
= XVECTOR (o2
)->contents
[i
];
1038 if (!internal_equal (v1
, v2
, depth
+ 1))
1046 if (XSTRING (o1
)->size
!= XSTRING (o2
)->size
)
1048 if (bcmp (XSTRING (o1
)->data
, XSTRING (o2
)->data
,
1049 XSTRING (o1
)->size
))
1051 #ifdef USE_TEXT_PROPERTIES
1052 /* If the strings have intervals, verify they match;
1053 if not, they are unequal. */
1054 if ((XSTRING (o1
)->intervals
!= 0 || XSTRING (o2
)->intervals
!= 0)
1055 && ! compare_string_intervals (o1
, o2
))
1063 DEFUN ("fillarray", Ffillarray
, Sfillarray
, 2, 2, 0,
1064 "Store each element of ARRAY with ITEM. ARRAY is a vector or string.")
1066 Lisp_Object array
, item
;
1068 register int size
, index
, charval
;
1070 if (VECTORP (array
))
1072 register Lisp_Object
*p
= XVECTOR (array
)->contents
;
1073 size
= XVECTOR (array
)->size
;
1074 for (index
= 0; index
< size
; index
++)
1077 else if (STRINGP (array
))
1079 register unsigned char *p
= XSTRING (array
)->data
;
1080 CHECK_NUMBER (item
, 1);
1081 charval
= XINT (item
);
1082 size
= XSTRING (array
)->size
;
1083 for (index
= 0; index
< size
; index
++)
1088 array
= wrong_type_argument (Qarrayp
, array
);
1100 Lisp_Object args
[2];
1103 return Fnconc (2, args
);
1105 return Fnconc (2, &s1
);
1106 #endif /* NO_ARG_ARRAY */
1109 DEFUN ("nconc", Fnconc
, Snconc
, 0, MANY
, 0,
1110 "Concatenate any number of lists by altering them.\n\
1111 Only the last argument is not altered, and need not be a list.")
1116 register int argnum
;
1117 register Lisp_Object tail
, tem
, val
;
1121 for (argnum
= 0; argnum
< nargs
; argnum
++)
1124 if (NILP (tem
)) continue;
1129 if (argnum
+ 1 == nargs
) break;
1132 tem
= wrong_type_argument (Qlistp
, tem
);
1141 tem
= args
[argnum
+ 1];
1142 Fsetcdr (tail
, tem
);
1144 args
[argnum
+ 1] = tail
;
1150 /* This is the guts of all mapping functions.
1151 Apply fn to each element of seq, one by one,
1152 storing the results into elements of vals, a C vector of Lisp_Objects.
1153 leni is the length of vals, which should also be the length of seq. */
1156 mapcar1 (leni
, vals
, fn
, seq
)
1159 Lisp_Object fn
, seq
;
1161 register Lisp_Object tail
;
1164 struct gcpro gcpro1
, gcpro2
, gcpro3
;
1166 /* Don't let vals contain any garbage when GC happens. */
1167 for (i
= 0; i
< leni
; i
++)
1170 GCPRO3 (dummy
, fn
, seq
);
1172 gcpro1
.nvars
= leni
;
1173 /* We need not explicitly protect `tail' because it is used only on lists, and
1174 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1178 for (i
= 0; i
< leni
; i
++)
1180 dummy
= XVECTOR (seq
)->contents
[i
];
1181 vals
[i
] = call1 (fn
, dummy
);
1184 else if (STRINGP (seq
))
1186 for (i
= 0; i
< leni
; i
++)
1188 XSETFASTINT (dummy
, XSTRING (seq
)->data
[i
]);
1189 vals
[i
] = call1 (fn
, dummy
);
1192 else /* Must be a list, since Flength did not get an error */
1195 for (i
= 0; i
< leni
; i
++)
1197 vals
[i
] = call1 (fn
, Fcar (tail
));
1205 DEFUN ("mapconcat", Fmapconcat
, Smapconcat
, 3, 3, 0,
1206 "Apply FN to each element of SEQ, and concat the results as strings.\n\
1207 In between each pair of results, stick in SEP.\n\
1208 Thus, \" \" as SEP results in spaces between the values returned by FN.")
1210 Lisp_Object fn
, seq
, sep
;
1215 register Lisp_Object
*args
;
1217 struct gcpro gcpro1
;
1219 len
= Flength (seq
);
1221 nargs
= leni
+ leni
- 1;
1222 if (nargs
< 0) return build_string ("");
1224 args
= (Lisp_Object
*) alloca (nargs
* sizeof (Lisp_Object
));
1227 mapcar1 (leni
, args
, fn
, seq
);
1230 for (i
= leni
- 1; i
>= 0; i
--)
1231 args
[i
+ i
] = args
[i
];
1233 for (i
= 1; i
< nargs
; i
+= 2)
1236 return Fconcat (nargs
, args
);
1239 DEFUN ("mapcar", Fmapcar
, Smapcar
, 2, 2, 0,
1240 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
1241 The result is a list just as long as SEQUENCE.\n\
1242 SEQUENCE may be a list, a vector or a string.")
1244 Lisp_Object fn
, seq
;
1246 register Lisp_Object len
;
1248 register Lisp_Object
*args
;
1250 len
= Flength (seq
);
1251 leni
= XFASTINT (len
);
1252 args
= (Lisp_Object
*) alloca (leni
* sizeof (Lisp_Object
));
1254 mapcar1 (leni
, args
, fn
, seq
);
1256 return Flist (leni
, args
);
1259 /* Anything that calls this function must protect from GC! */
1261 DEFUN ("y-or-n-p", Fy_or_n_p
, Sy_or_n_p
, 1, 1, 0,
1262 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
1263 Takes one argument, which is the string to display to ask the question.\n\
1264 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
1265 No confirmation of the answer is requested; a single character is enough.\n\
1266 Also accepts Space to mean yes, or Delete to mean no.")
1270 register Lisp_Object obj
, key
, def
, answer_string
, map
;
1271 register int answer
;
1272 Lisp_Object xprompt
;
1273 Lisp_Object args
[2];
1274 int ocech
= cursor_in_echo_area
;
1275 struct gcpro gcpro1
, gcpro2
;
1277 map
= Fsymbol_value (intern ("query-replace-map"));
1279 CHECK_STRING (prompt
, 0);
1281 GCPRO2 (prompt
, xprompt
);
1286 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1289 Lisp_Object pane
, menu
;
1290 redisplay_preserve_echo_area ();
1291 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1292 Fcons (Fcons (build_string ("No"), Qnil
),
1294 menu
= Fcons (prompt
, pane
);
1295 obj
= Fx_popup_dialog (Qt
, menu
);
1296 answer
= !NILP (obj
);
1300 cursor_in_echo_area
= 1;
1301 message_nolog ("%s(y or n) ", XSTRING (xprompt
)->data
);
1303 obj
= read_filtered_event (1, 0, 0);
1304 cursor_in_echo_area
= 0;
1305 /* If we need to quit, quit with cursor_in_echo_area = 0. */
1308 key
= Fmake_vector (make_number (1), obj
);
1309 def
= Flookup_key (map
, key
);
1310 answer_string
= Fsingle_key_description (obj
);
1312 if (EQ (def
, intern ("skip")))
1317 else if (EQ (def
, intern ("act")))
1322 else if (EQ (def
, intern ("recenter")))
1328 else if (EQ (def
, intern ("quit")))
1330 /* We want to exit this command for exit-prefix,
1331 and this is the only way to do it. */
1332 else if (EQ (def
, intern ("exit-prefix")))
1337 /* If we don't clear this, then the next call to read_char will
1338 return quit_char again, and we'll enter an infinite loop. */
1343 if (EQ (xprompt
, prompt
))
1345 args
[0] = build_string ("Please answer y or n. ");
1347 xprompt
= Fconcat (2, args
);
1352 if (! noninteractive
)
1354 cursor_in_echo_area
= -1;
1355 message_nolog ("%s(y or n) %c",
1356 XSTRING (xprompt
)->data
, answer
? 'y' : 'n');
1357 cursor_in_echo_area
= ocech
;
1360 return answer
? Qt
: Qnil
;
1363 /* This is how C code calls `yes-or-no-p' and allows the user
1366 Anything that calls this function must protect from GC! */
1369 do_yes_or_no_p (prompt
)
1372 return call1 (intern ("yes-or-no-p"), prompt
);
1375 /* Anything that calls this function must protect from GC! */
1377 DEFUN ("yes-or-no-p", Fyes_or_no_p
, Syes_or_no_p
, 1, 1, 0,
1378 "Ask user a yes-or-no question. Return t if answer is yes.\n\
1379 Takes one argument, which is the string to display to ask the question.\n\
1380 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
1381 The user must confirm the answer with RET,\n\
1382 and can edit it until it has been confirmed.")
1386 register Lisp_Object ans
;
1387 Lisp_Object args
[2];
1388 struct gcpro gcpro1
;
1391 CHECK_STRING (prompt
, 0);
1394 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1397 Lisp_Object pane
, menu
, obj
;
1398 redisplay_preserve_echo_area ();
1399 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1400 Fcons (Fcons (build_string ("No"), Qnil
),
1403 menu
= Fcons (prompt
, pane
);
1404 obj
= Fx_popup_dialog (Qt
, menu
);
1411 args
[1] = build_string ("(yes or no) ");
1412 prompt
= Fconcat (2, args
);
1418 ans
= Fdowncase (Fread_from_minibuffer (prompt
, Qnil
, Qnil
, Qnil
,
1419 Qyes_or_no_p_history
));
1420 if (XSTRING (ans
)->size
== 3 && !strcmp (XSTRING (ans
)->data
, "yes"))
1425 if (XSTRING (ans
)->size
== 2 && !strcmp (XSTRING (ans
)->data
, "no"))
1433 message ("Please answer yes or no.");
1434 Fsleep_for (make_number (2), Qnil
);
1438 DEFUN ("load-average", Fload_average
, Sload_average
, 0, 0, 0,
1439 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
1440 Each of the three load averages is multiplied by 100,\n\
1441 then converted to integer.\n\
1442 If the 5-minute or 15-minute load averages are not available, return a\n\
1443 shortened list, containing only those averages which are available.")
1447 int loads
= getloadavg (load_ave
, 3);
1451 error ("load-average not implemented for this operating system");
1455 ret
= Fcons (make_number ((int) (load_ave
[--loads
] * 100.0)), ret
);
1460 Lisp_Object Vfeatures
;
1462 DEFUN ("featurep", Ffeaturep
, Sfeaturep
, 1, 1, 0,
1463 "Returns t if FEATURE is present in this Emacs.\n\
1464 Use this to conditionalize execution of lisp code based on the presence or\n\
1465 absence of emacs or environment extensions.\n\
1466 Use `provide' to declare that a feature is available.\n\
1467 This function looks at the value of the variable `features'.")
1469 Lisp_Object feature
;
1471 register Lisp_Object tem
;
1472 CHECK_SYMBOL (feature
, 0);
1473 tem
= Fmemq (feature
, Vfeatures
);
1474 return (NILP (tem
)) ? Qnil
: Qt
;
1477 DEFUN ("provide", Fprovide
, Sprovide
, 1, 1, 0,
1478 "Announce that FEATURE is a feature of the current Emacs.")
1480 Lisp_Object feature
;
1482 register Lisp_Object tem
;
1483 CHECK_SYMBOL (feature
, 0);
1484 if (!NILP (Vautoload_queue
))
1485 Vautoload_queue
= Fcons (Fcons (Vfeatures
, Qnil
), Vautoload_queue
);
1486 tem
= Fmemq (feature
, Vfeatures
);
1488 Vfeatures
= Fcons (feature
, Vfeatures
);
1489 LOADHIST_ATTACH (Fcons (Qprovide
, feature
));
1493 DEFUN ("require", Frequire
, Srequire
, 1, 2, 0,
1494 "If feature FEATURE is not loaded, load it from FILENAME.\n\
1495 If FEATURE is not a member of the list `features', then the feature\n\
1496 is not loaded; so load the file FILENAME.\n\
1497 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
1498 (feature
, file_name
)
1499 Lisp_Object feature
, file_name
;
1501 register Lisp_Object tem
;
1502 CHECK_SYMBOL (feature
, 0);
1503 tem
= Fmemq (feature
, Vfeatures
);
1504 LOADHIST_ATTACH (Fcons (Qrequire
, feature
));
1507 int count
= specpdl_ptr
- specpdl
;
1509 /* Value saved here is to be restored into Vautoload_queue */
1510 record_unwind_protect (un_autoload
, Vautoload_queue
);
1511 Vautoload_queue
= Qt
;
1513 Fload (NILP (file_name
) ? Fsymbol_name (feature
) : file_name
,
1516 tem
= Fmemq (feature
, Vfeatures
);
1518 error ("Required feature %s was not provided",
1519 XSYMBOL (feature
)->name
->data
);
1521 /* Once loading finishes, don't undo it. */
1522 Vautoload_queue
= Qt
;
1523 feature
= unbind_to (count
, feature
);
1530 Qstring_lessp
= intern ("string-lessp");
1531 staticpro (&Qstring_lessp
);
1532 Qprovide
= intern ("provide");
1533 staticpro (&Qprovide
);
1534 Qrequire
= intern ("require");
1535 staticpro (&Qrequire
);
1536 Qyes_or_no_p_history
= intern ("yes-or-no-p-history");
1537 staticpro (&Qyes_or_no_p_history
);
1539 DEFVAR_LISP ("features", &Vfeatures
,
1540 "A list of symbols which are the features of the executing emacs.\n\
1541 Used by `featurep' and `require', and altered by `provide'.");
1544 defsubr (&Sidentity
);
1547 defsubr (&Ssafe_length
);
1548 defsubr (&Sstring_equal
);
1549 defsubr (&Sstring_lessp
);
1552 defsubr (&Svconcat
);
1553 defsubr (&Scopy_sequence
);
1554 defsubr (&Scopy_alist
);
1555 defsubr (&Ssubstring
);
1567 defsubr (&Snreverse
);
1568 defsubr (&Sreverse
);
1570 defsubr (&Splist_get
);
1572 defsubr (&Splist_put
);
1575 defsubr (&Sfillarray
);
1578 defsubr (&Smapconcat
);
1579 defsubr (&Sy_or_n_p
);
1580 defsubr (&Syes_or_no_p
);
1581 defsubr (&Sload_average
);
1582 defsubr (&Sfeaturep
);
1583 defsubr (&Srequire
);
1584 defsubr (&Sprovide
);