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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
24 /* Note on some machines this defines `vector' as a typedef,
25 so make sure we don't use that name in this file. */
34 #include "intervals.h"
37 #define NULL (void *)0
40 extern Lisp_Object
Flookup_key ();
42 Lisp_Object Qstring_lessp
, Qprovide
, Qrequire
;
43 Lisp_Object Qyes_or_no_p_history
;
44 Lisp_Object Qcursor_in_echo_area
;
46 static int internal_equal ();
48 DEFUN ("identity", Fidentity
, Sidentity
, 1, 1, 0,
49 "Return the argument unchanged.")
56 extern long get_random ();
57 extern void seed_random ();
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.")
70 Lisp_Object lispy_val
;
71 unsigned long denominator
;
74 seed_random (getpid () + time (NULL
));
75 if (NATNUMP (n
) && XFASTINT (n
) != 0)
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
);
86 val
= get_random () / denominator
;
87 while (val
>= XFASTINT (n
));
91 XSETINT (lispy_val
, val
);
95 /* Random data-structure functions */
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.")
101 register Lisp_Object sequence
;
103 register Lisp_Object tail
, val
;
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
))
119 for (i
= 0, tail
= sequence
; !NILP (tail
); i
++)
125 XSETFASTINT (val
, i
);
127 else if (NILP (sequence
))
128 XSETFASTINT (val
, 0);
131 sequence
= wrong_type_argument (Qsequencep
, sequence
);
137 /* This does not check for quits. That is safe
138 since it must terminate. */
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.")
148 Lisp_Object tail
, halftail
, length
;
151 /* halftail is used to detect circular lists. */
153 for (tail
= list
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
155 if (EQ (tail
, halftail
) && len
!= 0)
159 halftail
= XCONS (halftail
)->cdr
;
162 XSETINT (length
, len
);
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.")
171 register Lisp_Object s1
, s2
;
174 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
176 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
177 CHECK_STRING (s1
, 0);
178 CHECK_STRING (s2
, 1);
180 if (XSTRING (s1
)->size
!= XSTRING (s2
)->size
||
181 bcmp (XSTRING (s1
)->data
, XSTRING (s2
)->data
, XSTRING (s1
)->size
))
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.")
191 register Lisp_Object s1
, s2
;
194 register unsigned char *p1
, *p2
;
198 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
200 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
201 CHECK_STRING (s1
, 0);
202 CHECK_STRING (s2
, 1);
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
;
210 for (i
= 0; i
< end
; i
++)
213 return p1
[i
] < p2
[i
] ? Qt
: Qnil
;
215 return i
< XSTRING (s2
)->size
? Qt
: Qnil
;
218 static Lisp_Object
concat ();
229 return concat (2, args
, Lisp_String
, 0);
231 return concat (2, &s1
, Lisp_String
, 0);
232 #endif /* NO_ARG_ARRAY */
238 Lisp_Object s1
, s2
, s3
;
245 return concat (3, args
, Lisp_String
, 0);
247 return concat (3, &s1
, Lisp_String
, 0);
248 #endif /* NO_ARG_ARRAY */
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.")
260 return concat (nargs
, args
, Lisp_Cons
, 1);
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\
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.")
276 return concat (nargs
, args
, Lisp_String
, 0);
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.")
287 return concat (nargs
, args
, Lisp_Vectorlike
, 0);
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\
297 if (NILP (arg
)) return arg
;
299 if (CHAR_TABLE_P (arg
))
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
));
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
]);
320 if (BOOL_VECTOR_P (arg
))
324 = (XBOOL_VECTOR (arg
)->size
+ BITS_PER_CHAR
) / BITS_PER_CHAR
;
326 val
= Fmake_bool_vector (Flength (arg
), Qnil
);
327 bcopy (XBOOL_VECTOR (arg
)->data
, XBOOL_VECTOR (val
)->data
,
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);
338 concat (nargs
, args
, target_type
, last_special
)
341 enum Lisp_Type target_type
;
346 register Lisp_Object tail
;
347 register Lisp_Object
this;
351 Lisp_Object last_tail
;
354 /* In append, the last arg isn't treated like the others */
355 if (last_special
&& nargs
> 0)
358 last_tail
= args
[nargs
];
363 for (argnum
= 0; argnum
< nargs
; argnum
++)
366 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
367 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
370 args
[argnum
] = Fnumber_to_string (this);
372 args
[argnum
] = wrong_type_argument (Qsequencep
, this);
376 for (argnum
= 0, leni
= 0; argnum
< nargs
; argnum
++)
379 len
= Flength (this);
380 leni
+= XFASTINT (len
);
383 XSETFASTINT (len
, leni
);
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
);
390 val
= Fmake_string (len
, len
);
392 /* In append, if all but last arg are nil, return last arg */
393 if (target_type
== Lisp_Cons
&& EQ (val
, Qnil
))
397 tail
= val
, toindex
= -1; /* -1 in toindex is flag we are making a list */
403 for (argnum
= 0; argnum
< nargs
; argnum
++)
407 register int thisindex
= 0;
411 thislen
= Flength (this), thisleni
= XINT (thislen
);
413 if (STRINGP (this) && STRINGP (val
)
414 && ! NULL_INTERVAL_P (XSTRING (this)->intervals
))
416 copy_text_properties (make_number (0), thislen
, this,
417 make_number (toindex
), val
, Qnil
);
422 register Lisp_Object elt
;
424 /* Fetch next element of `this' arg into `elt', or break if
425 `this' is exhausted. */
426 if (NILP (this)) break;
428 elt
= Fcar (this), this = Fcdr (this);
431 if (thisindex
>= thisleni
) break;
433 XSETFASTINT (elt
, XSTRING (this)->data
[thisindex
++]);
434 else if (BOOL_VECTOR_P (this))
437 = ((XBOOL_VECTOR (this)->size
+ BITS_PER_CHAR
)
440 byte
= XBOOL_VECTOR (val
)->data
[thisindex
/ BITS_PER_CHAR
];
441 if (byte
& (1 << thisindex
))
447 elt
= XVECTOR (this)->contents
[thisindex
++];
450 /* Store into result */
453 XCONS (tail
)->car
= elt
;
455 tail
= XCONS (tail
)->cdr
;
457 else if (VECTORP (val
))
458 XVECTOR (val
)->contents
[toindex
++] = elt
;
461 while (!INTEGERP (elt
))
462 elt
= wrong_type_argument (Qintegerp
, elt
);
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
++];
470 XSTRING (val
)->data
[toindex
++] = XINT (elt
);
477 XCONS (prev
)->cdr
= last_tail
;
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.")
492 register Lisp_Object tem
;
494 CHECK_LIST (alist
, 0);
497 alist
= concat (1, &alist
, Lisp_Cons
, 0);
498 for (tem
= alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
500 register Lisp_Object car
;
501 car
= XCONS (tem
)->car
;
504 XCONS (tem
)->car
= Fcons (XCONS (car
)->car
, XCONS (car
)->cdr
);
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.")
515 register Lisp_Object from
, to
;
519 CHECK_STRING (string
, 0);
520 CHECK_NUMBER (from
, 1);
522 to
= Flength (string
);
524 CHECK_NUMBER (to
, 2);
527 XSETINT (from
, XINT (from
) + XSTRING (string
)->size
);
529 XSETINT (to
, XINT (to
) + XSTRING (string
)->size
);
530 if (!(0 <= XINT (from
) && XINT (from
) <= XINT (to
)
531 && XINT (to
) <= XSTRING (string
)->size
))
532 args_out_of_range_3 (string
, from
, to
);
534 res
= make_string (XSTRING (string
)->data
+ XINT (from
),
535 XINT (to
) - XINT (from
));
536 copy_text_properties (from
, to
, string
, make_number (0), res
, Qnil
);
540 DEFUN ("nthcdr", Fnthcdr
, Snthcdr
, 2, 2, 0,
541 "Take cdr N times on LIST, returns the result.")
544 register Lisp_Object list
;
549 for (i
= 0; i
< num
&& !NILP (list
); i
++)
557 DEFUN ("nth", Fnth
, Snth
, 2, 2, 0,
558 "Return the Nth element of LIST.\n\
559 N counts from zero. If LIST is not that long, nil is returned.")
563 return Fcar (Fnthcdr (n
, list
));
566 DEFUN ("elt", Felt
, Selt
, 2, 2, 0,
567 "Return element of SEQUENCE at index N.")
569 register Lisp_Object sequence
, n
;
574 if (CONSP (sequence
) || NILP (sequence
))
575 return Fcar (Fnthcdr (n
, sequence
));
576 else if (STRINGP (sequence
) || VECTORP (sequence
)
577 || BOOL_VECTOR_P (sequence
) || CHAR_TABLE_P (sequence
))
578 return Faref (sequence
, n
);
580 sequence
= wrong_type_argument (Qsequencep
, sequence
);
584 DEFUN ("member", Fmember
, Smember
, 2, 2, 0,
585 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
586 The value is actually the tail of LIST whose car is ELT.")
588 register Lisp_Object elt
;
591 register Lisp_Object tail
;
592 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
594 register Lisp_Object tem
;
596 if (! NILP (Fequal (elt
, tem
)))
603 DEFUN ("memq", Fmemq
, Smemq
, 2, 2, 0,
604 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
605 The value is actually the tail of LIST whose car is ELT.")
607 register Lisp_Object elt
;
610 register Lisp_Object tail
;
611 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
613 register Lisp_Object tem
;
615 if (EQ (elt
, tem
)) return tail
;
621 DEFUN ("assq", Fassq
, Sassq
, 2, 2, 0,
622 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
623 The value is actually the element of LIST whose car is KEY.\n\
624 Elements of LIST that are not conses are ignored.")
626 register Lisp_Object key
;
629 register Lisp_Object tail
;
630 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
632 register Lisp_Object elt
, tem
;
634 if (!CONSP (elt
)) continue;
636 if (EQ (key
, tem
)) return elt
;
642 /* Like Fassq but never report an error and do not allow quits.
643 Use only on lists known never to be circular. */
646 assq_no_quit (key
, list
)
647 register Lisp_Object key
;
650 register Lisp_Object tail
;
651 for (tail
= list
; CONSP (tail
); tail
= Fcdr (tail
))
653 register Lisp_Object elt
, tem
;
655 if (!CONSP (elt
)) continue;
657 if (EQ (key
, tem
)) return elt
;
662 DEFUN ("assoc", Fassoc
, Sassoc
, 2, 2, 0,
663 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
664 The value is actually the element of LIST whose car equals KEY.")
666 register Lisp_Object key
;
669 register Lisp_Object tail
;
670 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
672 register Lisp_Object elt
, tem
;
674 if (!CONSP (elt
)) continue;
675 tem
= Fequal (Fcar (elt
), key
);
676 if (!NILP (tem
)) return elt
;
682 DEFUN ("rassq", Frassq
, Srassq
, 2, 2, 0,
683 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
684 The value is actually the element of LIST whose cdr is ELT.")
686 register Lisp_Object key
;
689 register Lisp_Object tail
;
690 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
692 register Lisp_Object elt
, tem
;
694 if (!CONSP (elt
)) continue;
696 if (EQ (key
, tem
)) return elt
;
702 DEFUN ("rassoc", Frassoc
, Srassoc
, 2, 2, 0,
703 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
704 The value is actually the element of LIST whose cdr equals KEY.")
706 register Lisp_Object key
;
709 register Lisp_Object tail
;
710 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
712 register Lisp_Object elt
, tem
;
714 if (!CONSP (elt
)) continue;
715 tem
= Fequal (Fcdr (elt
), key
);
716 if (!NILP (tem
)) return elt
;
722 DEFUN ("delq", Fdelq
, Sdelq
, 2, 2, 0,
723 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
724 The modified LIST is returned. Comparison is done with `eq'.\n\
725 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
726 therefore, write `(setq foo (delq element foo))'\n\
727 to be sure of changing the value of `foo'.")
729 register Lisp_Object elt
;
732 register Lisp_Object tail
, prev
;
733 register Lisp_Object tem
;
745 Fsetcdr (prev
, Fcdr (tail
));
755 DEFUN ("delete", Fdelete
, Sdelete
, 2, 2, 0,
756 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
757 The modified LIST is returned. Comparison is done with `equal'.\n\
758 If the first member of LIST is ELT, deleting it is not a side effect;\n\
759 it is simply using a different list.\n\
760 Therefore, write `(setq foo (delete element foo))'\n\
761 to be sure of changing the value of `foo'.")
763 register Lisp_Object elt
;
766 register Lisp_Object tail
, prev
;
767 register Lisp_Object tem
;
774 if (! NILP (Fequal (elt
, tem
)))
779 Fsetcdr (prev
, Fcdr (tail
));
789 DEFUN ("nreverse", Fnreverse
, Snreverse
, 1, 1, 0,
790 "Reverse LIST by modifying cdr pointers.\n\
791 Returns the beginning of the reversed list.")
795 register Lisp_Object prev
, tail
, next
;
797 if (NILP (list
)) return list
;
804 Fsetcdr (tail
, prev
);
811 DEFUN ("reverse", Freverse
, Sreverse
, 1, 1, 0,
812 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
813 See also the function `nreverse', which is used more often.")
818 register Lisp_Object
*vec
;
819 register Lisp_Object tail
;
822 length
= Flength (list
);
823 vec
= (Lisp_Object
*) alloca (XINT (length
) * sizeof (Lisp_Object
));
824 for (i
= XINT (length
) - 1, tail
= list
; i
>= 0; i
--, tail
= Fcdr (tail
))
825 vec
[i
] = Fcar (tail
);
827 return Flist (XINT (length
), vec
);
830 Lisp_Object
merge ();
832 DEFUN ("sort", Fsort
, Ssort
, 2, 2, 0,
833 "Sort LIST, stably, comparing elements using PREDICATE.\n\
834 Returns the sorted list. LIST is modified by side effects.\n\
835 PREDICATE is called with two elements of LIST, and should return T\n\
836 if the first element is \"less\" than the second.")
838 Lisp_Object list
, predicate
;
840 Lisp_Object front
, back
;
841 register Lisp_Object len
, tem
;
842 struct gcpro gcpro1
, gcpro2
;
846 len
= Flength (list
);
851 XSETINT (len
, (length
/ 2) - 1);
852 tem
= Fnthcdr (len
, list
);
856 GCPRO2 (front
, back
);
857 front
= Fsort (front
, predicate
);
858 back
= Fsort (back
, predicate
);
860 return merge (front
, back
, predicate
);
864 merge (org_l1
, org_l2
, pred
)
865 Lisp_Object org_l1
, org_l2
;
869 register Lisp_Object tail
;
871 register Lisp_Object l1
, l2
;
872 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
879 /* It is sufficient to protect org_l1 and org_l2.
880 When l1 and l2 are updated, we copy the new values
881 back into the org_ vars. */
882 GCPRO4 (org_l1
, org_l2
, pred
, value
);
902 tem
= call2 (pred
, Fcar (l2
), Fcar (l1
));
924 DEFUN ("plist-get", Fplist_get
, Splist_get
, 2, 2, 0,
925 "Extract a value from a property list.\n\
926 PLIST is a property list, which is a list of the form\n\
927 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
928 corresponding to the given PROP, or nil if PROP is not\n\
929 one of the properties on the list.")
932 register Lisp_Object prop
;
934 register Lisp_Object tail
;
935 for (tail
= plist
; !NILP (tail
); tail
= Fcdr (Fcdr (tail
)))
937 register Lisp_Object tem
;
940 return Fcar (Fcdr (tail
));
945 DEFUN ("get", Fget
, Sget
, 2, 2, 0,
946 "Return the value of SYMBOL's PROPNAME property.\n\
947 This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
949 Lisp_Object symbol
, propname
;
951 CHECK_SYMBOL (symbol
, 0);
952 return Fplist_get (XSYMBOL (symbol
)->plist
, propname
);
955 DEFUN ("plist-put", Fplist_put
, Splist_put
, 3, 3, 0,
956 "Change value in PLIST of PROP to VAL.\n\
957 PLIST is a property list, which is a list of the form\n\
958 \(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
959 If PROP is already a property on the list, its value is set to VAL,\n\
960 otherwise the new PROP VAL pair is added. The new plist is returned;\n\
961 use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
962 The PLIST is modified by side effects.")
965 register Lisp_Object prop
;
968 register Lisp_Object tail
, prev
;
971 for (tail
= plist
; CONSP (tail
) && CONSP (XCONS (tail
)->cdr
);
972 tail
= XCONS (XCONS (tail
)->cdr
)->cdr
)
974 if (EQ (prop
, XCONS (tail
)->car
))
976 Fsetcar (XCONS (tail
)->cdr
, val
);
981 newcell
= Fcons (prop
, Fcons (val
, Qnil
));
985 Fsetcdr (XCONS (prev
)->cdr
, newcell
);
989 DEFUN ("put", Fput
, Sput
, 3, 3, 0,
990 "Store SYMBOL's PROPNAME property with value VALUE.\n\
991 It can be retrieved with `(get SYMBOL PROPNAME)'.")
992 (symbol
, propname
, value
)
993 Lisp_Object symbol
, propname
, value
;
995 CHECK_SYMBOL (symbol
, 0);
996 XSYMBOL (symbol
)->plist
997 = Fplist_put (XSYMBOL (symbol
)->plist
, propname
, value
);
1001 DEFUN ("equal", Fequal
, Sequal
, 2, 2, 0,
1002 "T if two Lisp objects have similar structure and contents.\n\
1003 They must have the same data type.\n\
1004 Conses are compared by comparing the cars and the cdrs.\n\
1005 Vectors and strings are compared element by element.\n\
1006 Numbers are compared by value, but integers cannot equal floats.\n\
1007 (Use `=' if you want integers and floats to be able to be equal.)\n\
1008 Symbols must match exactly.")
1010 register Lisp_Object o1
, o2
;
1012 return internal_equal (o1
, o2
, 0) ? Qt
: Qnil
;
1016 internal_equal (o1
, o2
, depth
)
1017 register Lisp_Object o1
, o2
;
1021 error ("Stack overflow in equal");
1027 if (XTYPE (o1
) != XTYPE (o2
))
1032 #ifdef LISP_FLOAT_TYPE
1034 return (extract_float (o1
) == extract_float (o2
));
1038 if (!internal_equal (XCONS (o1
)->car
, XCONS (o2
)->car
, depth
+ 1))
1040 o1
= XCONS (o1
)->cdr
;
1041 o2
= XCONS (o2
)->cdr
;
1045 if (XMISCTYPE (o1
) != XMISCTYPE (o2
))
1049 if (!internal_equal (OVERLAY_START (o1
), OVERLAY_START (o1
),
1051 || !internal_equal (OVERLAY_END (o1
), OVERLAY_END (o1
),
1054 o1
= XOVERLAY (o1
)->plist
;
1055 o2
= XOVERLAY (o2
)->plist
;
1060 return (XMARKER (o1
)->buffer
== XMARKER (o2
)->buffer
1061 && (XMARKER (o1
)->buffer
== 0
1062 || XMARKER (o1
)->bufpos
== XMARKER (o2
)->bufpos
));
1066 case Lisp_Vectorlike
:
1068 register int i
, size
;
1069 size
= XVECTOR (o1
)->size
;
1070 /* Pseudovectors have the type encoded in the size field, so this test
1071 actually checks that the objects have the same type as well as the
1073 if (XVECTOR (o2
)->size
!= size
)
1075 /* Boolvectors are compared much like strings. */
1076 if (BOOL_VECTOR_P (o1
))
1079 = (XBOOL_VECTOR (o1
)->size
+ BITS_PER_CHAR
) / BITS_PER_CHAR
;
1081 if (XBOOL_VECTOR (o1
)->size
!= XBOOL_VECTOR (o2
)->size
)
1083 if (bcmp (XBOOL_VECTOR (o1
)->data
, XBOOL_VECTOR (o2
)->data
,
1089 /* Aside from them, only true vectors, char-tables, and compiled
1090 functions are sensible to compare, so eliminate the others now. */
1091 if (size
& PSEUDOVECTOR_FLAG
)
1093 if (!(size
& (PVEC_COMPILED
| PVEC_CHAR_TABLE
)))
1095 size
&= PSEUDOVECTOR_SIZE_MASK
;
1097 for (i
= 0; i
< size
; i
++)
1100 v1
= XVECTOR (o1
)->contents
[i
];
1101 v2
= XVECTOR (o2
)->contents
[i
];
1102 if (!internal_equal (v1
, v2
, depth
+ 1))
1110 if (XSTRING (o1
)->size
!= XSTRING (o2
)->size
)
1112 if (bcmp (XSTRING (o1
)->data
, XSTRING (o2
)->data
,
1113 XSTRING (o1
)->size
))
1115 #ifdef USE_TEXT_PROPERTIES
1116 /* If the strings have intervals, verify they match;
1117 if not, they are unequal. */
1118 if ((XSTRING (o1
)->intervals
!= 0 || XSTRING (o2
)->intervals
!= 0)
1119 && ! compare_string_intervals (o1
, o2
))
1127 DEFUN ("fillarray", Ffillarray
, Sfillarray
, 2, 2, 0,
1128 "Store each element of ARRAY with ITEM.\n\
1129 ARRAY is a vector, string, char-table, or bool-vector.")
1131 Lisp_Object array
, item
;
1133 register int size
, index
, charval
;
1135 if (VECTORP (array
))
1137 register Lisp_Object
*p
= XVECTOR (array
)->contents
;
1138 size
= XVECTOR (array
)->size
;
1139 for (index
= 0; index
< size
; index
++)
1142 else if (CHAR_TABLE_P (array
))
1144 register Lisp_Object
*p
= XCHAR_TABLE (array
)->contents
;
1145 size
= CHAR_TABLE_ORDINARY_SLOTS
;
1146 for (index
= 0; index
< size
; index
++)
1148 XCHAR_TABLE (array
)->defalt
= Qnil
;
1150 else if (STRINGP (array
))
1152 register unsigned char *p
= XSTRING (array
)->data
;
1153 CHECK_NUMBER (item
, 1);
1154 charval
= XINT (item
);
1155 size
= XSTRING (array
)->size
;
1156 for (index
= 0; index
< size
; index
++)
1159 else if (BOOL_VECTOR_P (array
))
1161 register unsigned char *p
= XBOOL_VECTOR (array
)->data
;
1163 = (XBOOL_VECTOR (array
)->size
+ BITS_PER_CHAR
) / BITS_PER_CHAR
;
1165 charval
= (! NILP (item
) ? -1 : 0);
1166 for (index
= 0; index
< size_in_chars
; index
++)
1171 array
= wrong_type_argument (Qarrayp
, array
);
1177 DEFUN ("char-table-subtype", Fchar_table_subtype
, Schar_table_subtype
,
1179 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
1181 Lisp_Object char_table
;
1183 CHECK_CHAR_TABLE (char_table
, 0);
1185 return XCHAR_TABLE (char_table
)->purpose
;
1188 DEFUN ("char-table-parent", Fchar_table_parent
, Schar_table_parent
,
1190 "Return the parent char-table of CHAR-TABLE.\n\
1191 The value is either nil or another char-table.\n\
1192 If CHAR-TABLE holds nil for a given character,\n\
1193 then the actual applicable value is inherited from the parent char-table\n\
1194 \(or from its parents, if necessary).")
1196 Lisp_Object char_table
;
1198 CHECK_CHAR_TABLE (char_table
, 0);
1200 return XCHAR_TABLE (char_table
)->parent
;
1203 DEFUN ("set-char-table-parent", Fset_char_table_parent
, Sset_char_table_parent
,
1205 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1206 PARENT must be either nil or another char-table.")
1207 (char_table
, parent
)
1208 Lisp_Object char_table
, parent
;
1212 CHECK_CHAR_TABLE (char_table
, 0);
1216 CHECK_CHAR_TABLE (parent
, 0);
1218 for (temp
= parent
; !NILP (temp
); temp
= XCHAR_TABLE (temp
)->parent
)
1219 if (EQ (temp
, char_table
))
1220 error ("Attempt to make a chartable be its own parent");
1223 XCHAR_TABLE (char_table
)->parent
= parent
;
1228 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot
, Schar_table_extra_slot
,
1230 "Return the value in extra-slot number N of char-table CHAR-TABLE.")
1232 Lisp_Object char_table
, n
;
1234 CHECK_CHAR_TABLE (char_table
, 1);
1235 CHECK_NUMBER (n
, 2);
1237 || XINT (n
) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table
)))
1238 args_out_of_range (char_table
, n
);
1240 return XCHAR_TABLE (char_table
)->extras
[XINT (n
)];
1243 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot
,
1244 Sset_char_table_extra_slot
,
1246 "Set extra-slot number N of CHAR-TABLE to VALUE.")
1247 (char_table
, n
, value
)
1248 Lisp_Object char_table
, n
, value
;
1250 CHECK_CHAR_TABLE (char_table
, 1);
1251 CHECK_NUMBER (n
, 2);
1253 || XINT (n
) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table
)))
1254 args_out_of_range (char_table
, n
);
1256 return XCHAR_TABLE (char_table
)->extras
[XINT (n
)] = value
;
1259 DEFUN ("char-table-range", Fchar_table_range
, Schar_table_range
,
1261 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
1262 RANGE should be t (for all characters), nil (for the default value)\n\
1263 a vector which identifies a character set or a row of a character set,\n\
1264 or a character code.")
1266 Lisp_Object char_table
, range
;
1270 CHECK_CHAR_TABLE (char_table
, 0);
1272 if (EQ (range
, Qnil
))
1273 return XCHAR_TABLE (char_table
)->defalt
;
1274 else if (INTEGERP (range
))
1275 return Faref (char_table
, range
);
1276 else if (VECTORP (range
))
1278 for (i
= 0; i
< XVECTOR (range
)->size
- 1; i
++)
1279 char_table
= Faref (char_table
, XVECTOR (range
)->contents
[i
]);
1281 if (EQ (XVECTOR (range
)->contents
[i
], Qnil
))
1282 return XCHAR_TABLE (char_table
)->defalt
;
1284 return Faref (char_table
, XVECTOR (range
)->contents
[i
]);
1287 error ("Invalid RANGE argument to `char-table-range'");
1290 DEFUN ("set-char-table-range", Fset_char_table_range
, Sset_char_table_range
,
1292 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
1293 RANGE should be t (for all characters), nil (for the default value)\n\
1294 a vector which identifies a character set or a row of a character set,\n\
1295 or a character code.")
1296 (char_table
, range
, value
)
1297 Lisp_Object char_table
, range
, value
;
1301 CHECK_CHAR_TABLE (char_table
, 0);
1304 for (i
= 0; i
< CHAR_TABLE_ORDINARY_SLOTS
; i
++)
1305 XCHAR_TABLE (char_table
)->contents
[i
] = value
;
1306 else if (EQ (range
, Qnil
))
1307 XCHAR_TABLE (char_table
)->defalt
= value
;
1308 else if (INTEGERP (range
))
1309 Faset (char_table
, range
, value
);
1310 else if (VECTORP (range
))
1312 for (i
= 0; i
< XVECTOR (range
)->size
- 1; i
++)
1313 char_table
= Faref (char_table
, XVECTOR (range
)->contents
[i
]);
1315 if (EQ (XVECTOR (range
)->contents
[i
], Qnil
))
1316 XCHAR_TABLE (char_table
)->defalt
= value
;
1318 Faset (char_table
, XVECTOR (range
)->contents
[i
], value
);
1321 error ("Invalid RANGE argument to `set-char-table-range'");
1326 /* Map C_FUNCTION or FUNCTION over CHARTABLE, calling it for each
1327 character or group of characters that share a value.
1328 DEPTH is the current depth in the originally specified
1329 chartable, and INDICES contains the vector indices
1330 for the levels our callers have descended. */
1333 map_char_table (c_function
, function
, chartable
, depth
, indices
)
1334 Lisp_Object (*c_function
) (), function
, chartable
, depth
, *indices
;
1337 int size
= CHAR_TABLE_ORDINARY_SLOTS
;
1339 /* Make INDICES longer if we are about to fill it up. */
1340 if ((depth
% 10) == 9)
1342 Lisp_Object
*new_indices
1343 = (Lisp_Object
*) alloca ((depth
+= 10) * sizeof (Lisp_Object
));
1344 bcopy (indices
, new_indices
, depth
* sizeof (Lisp_Object
));
1345 indices
= new_indices
;
1348 for (i
= 0; i
< size
; i
++)
1352 elt
= XCHAR_TABLE (chartable
)->contents
[i
];
1353 if (CHAR_TABLE_P (elt
))
1354 map_char_table (c_function
, function
, chartable
, depth
+ 1, indices
);
1355 else if (c_function
)
1356 (*c_function
) (depth
+ 1, indices
, elt
);
1357 /* Here we should handle all cases where the range is a single character
1358 by passing that character as a number. Currently, that is
1359 all the time, but with the MULE code this will have to be changed. */
1360 else if (depth
== 0)
1361 call2 (function
, make_number (i
), elt
);
1363 call2 (function
, Fvector (depth
+ 1, indices
), elt
);
1367 DEFUN ("map-char-table", Fmap_char_table
, Smap_char_table
,
1369 "Call FUNCTION for each range of like characters in CHAR-TABLE.\n\
1370 FUNCTION is called with two arguments--a key and a value.\n\
1371 The key is always a possible RANGE argument to `set-char-table-range'.")
1372 (function
, char_table
)
1373 Lisp_Object function
, char_table
;
1376 Lisp_Object
*indices
= (Lisp_Object
*) alloca (10 * sizeof (Lisp_Object
));
1378 map_char_table (NULL
, function
, char_table
, 0, indices
);
1388 Lisp_Object args
[2];
1391 return Fnconc (2, args
);
1393 return Fnconc (2, &s1
);
1394 #endif /* NO_ARG_ARRAY */
1397 DEFUN ("nconc", Fnconc
, Snconc
, 0, MANY
, 0,
1398 "Concatenate any number of lists by altering them.\n\
1399 Only the last argument is not altered, and need not be a list.")
1404 register int argnum
;
1405 register Lisp_Object tail
, tem
, val
;
1409 for (argnum
= 0; argnum
< nargs
; argnum
++)
1412 if (NILP (tem
)) continue;
1417 if (argnum
+ 1 == nargs
) break;
1420 tem
= wrong_type_argument (Qlistp
, tem
);
1429 tem
= args
[argnum
+ 1];
1430 Fsetcdr (tail
, tem
);
1432 args
[argnum
+ 1] = tail
;
1438 /* This is the guts of all mapping functions.
1439 Apply fn to each element of seq, one by one,
1440 storing the results into elements of vals, a C vector of Lisp_Objects.
1441 leni is the length of vals, which should also be the length of seq. */
1444 mapcar1 (leni
, vals
, fn
, seq
)
1447 Lisp_Object fn
, seq
;
1449 register Lisp_Object tail
;
1452 struct gcpro gcpro1
, gcpro2
, gcpro3
;
1454 /* Don't let vals contain any garbage when GC happens. */
1455 for (i
= 0; i
< leni
; i
++)
1458 GCPRO3 (dummy
, fn
, seq
);
1460 gcpro1
.nvars
= leni
;
1461 /* We need not explicitly protect `tail' because it is used only on lists, and
1462 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1466 for (i
= 0; i
< leni
; i
++)
1468 dummy
= XVECTOR (seq
)->contents
[i
];
1469 vals
[i
] = call1 (fn
, dummy
);
1472 else if (STRINGP (seq
))
1474 for (i
= 0; i
< leni
; i
++)
1476 XSETFASTINT (dummy
, XSTRING (seq
)->data
[i
]);
1477 vals
[i
] = call1 (fn
, dummy
);
1480 else /* Must be a list, since Flength did not get an error */
1483 for (i
= 0; i
< leni
; i
++)
1485 vals
[i
] = call1 (fn
, Fcar (tail
));
1493 DEFUN ("mapconcat", Fmapconcat
, Smapconcat
, 3, 3, 0,
1494 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
1495 In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
1496 SEPARATOR results in spaces between the values returned by FUNCTION.")
1497 (function
, sequence
, separator
)
1498 Lisp_Object function
, sequence
, separator
;
1503 register Lisp_Object
*args
;
1505 struct gcpro gcpro1
;
1507 len
= Flength (sequence
);
1509 nargs
= leni
+ leni
- 1;
1510 if (nargs
< 0) return build_string ("");
1512 args
= (Lisp_Object
*) alloca (nargs
* sizeof (Lisp_Object
));
1515 mapcar1 (leni
, args
, function
, sequence
);
1518 for (i
= leni
- 1; i
>= 0; i
--)
1519 args
[i
+ i
] = args
[i
];
1521 for (i
= 1; i
< nargs
; i
+= 2)
1522 args
[i
] = separator
;
1524 return Fconcat (nargs
, args
);
1527 DEFUN ("mapcar", Fmapcar
, Smapcar
, 2, 2, 0,
1528 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
1529 The result is a list just as long as SEQUENCE.\n\
1530 SEQUENCE may be a list, a vector or a string.")
1531 (function
, sequence
)
1532 Lisp_Object function
, sequence
;
1534 register Lisp_Object len
;
1536 register Lisp_Object
*args
;
1538 len
= Flength (sequence
);
1539 leni
= XFASTINT (len
);
1540 args
= (Lisp_Object
*) alloca (leni
* sizeof (Lisp_Object
));
1542 mapcar1 (leni
, args
, function
, sequence
);
1544 return Flist (leni
, args
);
1547 /* Anything that calls this function must protect from GC! */
1549 DEFUN ("y-or-n-p", Fy_or_n_p
, Sy_or_n_p
, 1, 1, 0,
1550 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
1551 Takes one argument, which is the string to display to ask the question.\n\
1552 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
1553 No confirmation of the answer is requested; a single character is enough.\n\
1554 Also accepts Space to mean yes, or Delete to mean no.")
1558 register Lisp_Object obj
, key
, def
, answer_string
, map
;
1559 register int answer
;
1560 Lisp_Object xprompt
;
1561 Lisp_Object args
[2];
1562 struct gcpro gcpro1
, gcpro2
;
1563 int count
= specpdl_ptr
- specpdl
;
1565 specbind (Qcursor_in_echo_area
, Qt
);
1567 map
= Fsymbol_value (intern ("query-replace-map"));
1569 CHECK_STRING (prompt
, 0);
1571 GCPRO2 (prompt
, xprompt
);
1578 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1581 Lisp_Object pane
, menu
;
1582 redisplay_preserve_echo_area ();
1583 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1584 Fcons (Fcons (build_string ("No"), Qnil
),
1586 menu
= Fcons (prompt
, pane
);
1587 obj
= Fx_popup_dialog (Qt
, menu
);
1588 answer
= !NILP (obj
);
1591 #endif /* HAVE_MENUS */
1592 cursor_in_echo_area
= 1;
1593 choose_minibuf_frame ();
1594 message_nolog ("%s(y or n) ", XSTRING (xprompt
)->data
);
1596 obj
= read_filtered_event (1, 0, 0);
1597 cursor_in_echo_area
= 0;
1598 /* If we need to quit, quit with cursor_in_echo_area = 0. */
1601 key
= Fmake_vector (make_number (1), obj
);
1602 def
= Flookup_key (map
, key
);
1603 answer_string
= Fsingle_key_description (obj
);
1605 if (EQ (def
, intern ("skip")))
1610 else if (EQ (def
, intern ("act")))
1615 else if (EQ (def
, intern ("recenter")))
1621 else if (EQ (def
, intern ("quit")))
1623 /* We want to exit this command for exit-prefix,
1624 and this is the only way to do it. */
1625 else if (EQ (def
, intern ("exit-prefix")))
1630 /* If we don't clear this, then the next call to read_char will
1631 return quit_char again, and we'll enter an infinite loop. */
1636 if (EQ (xprompt
, prompt
))
1638 args
[0] = build_string ("Please answer y or n. ");
1640 xprompt
= Fconcat (2, args
);
1645 if (! noninteractive
)
1647 cursor_in_echo_area
= -1;
1648 message_nolog ("%s(y or n) %c",
1649 XSTRING (xprompt
)->data
, answer
? 'y' : 'n');
1652 unbind_to (count
, Qnil
);
1653 return answer
? Qt
: Qnil
;
1656 /* This is how C code calls `yes-or-no-p' and allows the user
1659 Anything that calls this function must protect from GC! */
1662 do_yes_or_no_p (prompt
)
1665 return call1 (intern ("yes-or-no-p"), prompt
);
1668 /* Anything that calls this function must protect from GC! */
1670 DEFUN ("yes-or-no-p", Fyes_or_no_p
, Syes_or_no_p
, 1, 1, 0,
1671 "Ask user a yes-or-no question. Return t if answer is yes.\n\
1672 Takes one argument, which is the string to display to ask the question.\n\
1673 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
1674 The user must confirm the answer with RET,\n\
1675 and can edit it until it has been confirmed.")
1679 register Lisp_Object ans
;
1680 Lisp_Object args
[2];
1681 struct gcpro gcpro1
;
1684 CHECK_STRING (prompt
, 0);
1687 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1690 Lisp_Object pane
, menu
, obj
;
1691 redisplay_preserve_echo_area ();
1692 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1693 Fcons (Fcons (build_string ("No"), Qnil
),
1696 menu
= Fcons (prompt
, pane
);
1697 obj
= Fx_popup_dialog (Qt
, menu
);
1701 #endif /* HAVE_MENUS */
1704 args
[1] = build_string ("(yes or no) ");
1705 prompt
= Fconcat (2, args
);
1711 ans
= Fdowncase (Fread_from_minibuffer (prompt
, Qnil
, Qnil
, Qnil
,
1712 Qyes_or_no_p_history
));
1713 if (XSTRING (ans
)->size
== 3 && !strcmp (XSTRING (ans
)->data
, "yes"))
1718 if (XSTRING (ans
)->size
== 2 && !strcmp (XSTRING (ans
)->data
, "no"))
1726 message ("Please answer yes or no.");
1727 Fsleep_for (make_number (2), Qnil
);
1731 DEFUN ("load-average", Fload_average
, Sload_average
, 0, 0, 0,
1732 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
1733 Each of the three load averages is multiplied by 100,\n\
1734 then converted to integer.\n\
1735 If the 5-minute or 15-minute load averages are not available, return a\n\
1736 shortened list, containing only those averages which are available.")
1740 int loads
= getloadavg (load_ave
, 3);
1744 error ("load-average not implemented for this operating system");
1748 ret
= Fcons (make_number ((int) (load_ave
[--loads
] * 100.0)), ret
);
1753 Lisp_Object Vfeatures
;
1755 DEFUN ("featurep", Ffeaturep
, Sfeaturep
, 1, 1, 0,
1756 "Returns t if FEATURE is present in this Emacs.\n\
1757 Use this to conditionalize execution of lisp code based on the presence or\n\
1758 absence of emacs or environment extensions.\n\
1759 Use `provide' to declare that a feature is available.\n\
1760 This function looks at the value of the variable `features'.")
1762 Lisp_Object feature
;
1764 register Lisp_Object tem
;
1765 CHECK_SYMBOL (feature
, 0);
1766 tem
= Fmemq (feature
, Vfeatures
);
1767 return (NILP (tem
)) ? Qnil
: Qt
;
1770 DEFUN ("provide", Fprovide
, Sprovide
, 1, 1, 0,
1771 "Announce that FEATURE is a feature of the current Emacs.")
1773 Lisp_Object feature
;
1775 register Lisp_Object tem
;
1776 CHECK_SYMBOL (feature
, 0);
1777 if (!NILP (Vautoload_queue
))
1778 Vautoload_queue
= Fcons (Fcons (Vfeatures
, Qnil
), Vautoload_queue
);
1779 tem
= Fmemq (feature
, Vfeatures
);
1781 Vfeatures
= Fcons (feature
, Vfeatures
);
1782 LOADHIST_ATTACH (Fcons (Qprovide
, feature
));
1786 DEFUN ("require", Frequire
, Srequire
, 1, 2, 0,
1787 "If feature FEATURE is not loaded, load it from FILENAME.\n\
1788 If FEATURE is not a member of the list `features', then the feature\n\
1789 is not loaded; so load the file FILENAME.\n\
1790 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
1791 (feature
, file_name
)
1792 Lisp_Object feature
, file_name
;
1794 register Lisp_Object tem
;
1795 CHECK_SYMBOL (feature
, 0);
1796 tem
= Fmemq (feature
, Vfeatures
);
1797 LOADHIST_ATTACH (Fcons (Qrequire
, feature
));
1800 int count
= specpdl_ptr
- specpdl
;
1802 /* Value saved here is to be restored into Vautoload_queue */
1803 record_unwind_protect (un_autoload
, Vautoload_queue
);
1804 Vautoload_queue
= Qt
;
1806 Fload (NILP (file_name
) ? Fsymbol_name (feature
) : file_name
,
1809 tem
= Fmemq (feature
, Vfeatures
);
1811 error ("Required feature %s was not provided",
1812 XSYMBOL (feature
)->name
->data
);
1814 /* Once loading finishes, don't undo it. */
1815 Vautoload_queue
= Qt
;
1816 feature
= unbind_to (count
, feature
);
1823 Qstring_lessp
= intern ("string-lessp");
1824 staticpro (&Qstring_lessp
);
1825 Qprovide
= intern ("provide");
1826 staticpro (&Qprovide
);
1827 Qrequire
= intern ("require");
1828 staticpro (&Qrequire
);
1829 Qyes_or_no_p_history
= intern ("yes-or-no-p-history");
1830 staticpro (&Qyes_or_no_p_history
);
1831 Qcursor_in_echo_area
= intern ("cursor-in-echo-area");
1832 staticpro (&Qcursor_in_echo_area
);
1834 Fset (Qyes_or_no_p_history
, Qnil
);
1836 DEFVAR_LISP ("features", &Vfeatures
,
1837 "A list of symbols which are the features of the executing emacs.\n\
1838 Used by `featurep' and `require', and altered by `provide'.");
1841 defsubr (&Sidentity
);
1844 defsubr (&Ssafe_length
);
1845 defsubr (&Sstring_equal
);
1846 defsubr (&Sstring_lessp
);
1849 defsubr (&Svconcat
);
1850 defsubr (&Scopy_sequence
);
1851 defsubr (&Scopy_alist
);
1852 defsubr (&Ssubstring
);
1864 defsubr (&Snreverse
);
1865 defsubr (&Sreverse
);
1867 defsubr (&Splist_get
);
1869 defsubr (&Splist_put
);
1872 defsubr (&Sfillarray
);
1873 defsubr (&Schar_table_subtype
);
1874 defsubr (&Schar_table_parent
);
1875 defsubr (&Sset_char_table_parent
);
1876 defsubr (&Schar_table_extra_slot
);
1877 defsubr (&Sset_char_table_extra_slot
);
1878 defsubr (&Schar_table_range
);
1879 defsubr (&Sset_char_table_range
);
1880 defsubr (&Smap_char_table
);
1883 defsubr (&Smapconcat
);
1884 defsubr (&Sy_or_n_p
);
1885 defsubr (&Syes_or_no_p
);
1886 defsubr (&Sload_average
);
1887 defsubr (&Sfeaturep
);
1888 defsubr (&Srequire
);
1889 defsubr (&Sprovide
);