1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 1986, 1987, 1993, 1994 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"
35 extern Lisp_Object
Flookup_key ();
37 Lisp_Object Qstring_lessp
, Qprovide
, Qrequire
;
38 Lisp_Object Qyes_or_no_p_history
;
40 static int internal_equal ();
42 DEFUN ("identity", Fidentity
, Sidentity
, 1, 1, 0,
43 "Return the argument unchanged.")
50 extern long get_random ();
51 extern void seed_random ();
54 DEFUN ("random", Frandom
, Srandom
, 0, 1, 0,
55 "Return a pseudo-random number.\n\
56 All integers representable in Lisp are equally likely.\n\
57 On most systems, this is 28 bits' worth.\n\
58 With positive integer argument N, return random number in interval [0,N).\n\
59 With argument t, set the random number seed from the current time and pid.")
64 unsigned long denominator
;
67 seed_random (getpid () + time (0));
68 if (NATNUMP (limit
) && XFASTINT (limit
) != 0)
70 /* Try to take our random number from the higher bits of VAL,
71 not the lower, since (says Gentzel) the low bits of `random'
72 are less random than the higher ones. We do this by using the
73 quotient rather than the remainder. At the high end of the RNG
74 it's possible to get a quotient larger than limit; discarding
75 these values eliminates the bias that would otherwise appear
76 when using a large limit. */
77 denominator
= ((unsigned long)1 << VALBITS
) / XFASTINT (limit
);
79 val
= get_random () / denominator
;
80 while (val
>= XFASTINT (limit
));
84 return make_number (val
);
87 /* Random data-structure functions */
89 DEFUN ("length", Flength
, Slength
, 1, 1, 0,
90 "Return the length of vector, list or string SEQUENCE.\n\
91 A byte-code function object is also allowed.")
93 register Lisp_Object obj
;
95 register Lisp_Object tail
, val
;
100 XSETFASTINT (val
, XSTRING (obj
)->size
);
101 else if (VECTORP (obj
))
102 XSETFASTINT (val
, XVECTOR (obj
)->size
);
103 else if (COMPILEDP (obj
))
104 XSETFASTINT (val
, XVECTOR (obj
)->size
& PSEUDOVECTOR_SIZE_MASK
);
105 else if (CONSP (obj
))
107 for (i
= 0, tail
= obj
; !NILP (tail
); i
++)
113 XSETFASTINT (val
, i
);
116 XSETFASTINT (val
, 0);
119 obj
= wrong_type_argument (Qsequencep
, obj
);
125 DEFUN ("string-equal", Fstring_equal
, Sstring_equal
, 2, 2, 0,
126 "T if two strings have identical contents.\n\
127 Case is significant, but text properties are ignored.\n\
128 Symbols are also allowed; their print names are used instead.")
130 register Lisp_Object s1
, s2
;
133 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
135 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
136 CHECK_STRING (s1
, 0);
137 CHECK_STRING (s2
, 1);
139 if (XSTRING (s1
)->size
!= XSTRING (s2
)->size
||
140 bcmp (XSTRING (s1
)->data
, XSTRING (s2
)->data
, XSTRING (s1
)->size
))
145 DEFUN ("string-lessp", Fstring_lessp
, Sstring_lessp
, 2, 2, 0,
146 "T if first arg string is less than second in lexicographic order.\n\
147 Case is significant.\n\
148 Symbols are also allowed; their print names are used instead.")
150 register Lisp_Object s1
, s2
;
153 register unsigned char *p1
, *p2
;
157 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
159 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
160 CHECK_STRING (s1
, 0);
161 CHECK_STRING (s2
, 1);
163 p1
= XSTRING (s1
)->data
;
164 p2
= XSTRING (s2
)->data
;
165 end
= XSTRING (s1
)->size
;
166 if (end
> XSTRING (s2
)->size
)
167 end
= XSTRING (s2
)->size
;
169 for (i
= 0; i
< end
; i
++)
172 return p1
[i
] < p2
[i
] ? Qt
: Qnil
;
174 return i
< XSTRING (s2
)->size
? Qt
: Qnil
;
177 static Lisp_Object
concat ();
188 return concat (2, args
, Lisp_String
, 0);
190 return concat (2, &s1
, Lisp_String
, 0);
191 #endif /* NO_ARG_ARRAY */
197 Lisp_Object s1
, s2
, s3
;
204 return concat (3, args
, Lisp_String
, 0);
206 return concat (3, &s1
, Lisp_String
, 0);
207 #endif /* NO_ARG_ARRAY */
210 DEFUN ("append", Fappend
, Sappend
, 0, MANY
, 0,
211 "Concatenate all the arguments and make the result a list.\n\
212 The result is a list whose elements are the elements of all the arguments.\n\
213 Each argument may be a list, vector or string.\n\
214 The last argument is not copied, just used as the tail of the new list.")
219 return concat (nargs
, args
, Lisp_Cons
, 1);
222 DEFUN ("concat", Fconcat
, Sconcat
, 0, MANY
, 0,
223 "Concatenate all the arguments and make the result a string.\n\
224 The result is a string whose elements are the elements of all the arguments.\n\
225 Each argument may be a string, a list of characters (integers),\n\
226 or a vector of characters (integers).")
231 return concat (nargs
, args
, Lisp_String
, 0);
234 DEFUN ("vconcat", Fvconcat
, Svconcat
, 0, MANY
, 0,
235 "Concatenate all the arguments and make the result a vector.\n\
236 The result is a vector whose elements are the elements of all the arguments.\n\
237 Each argument may be a list, vector or string.")
242 return concat (nargs
, args
, Lisp_Vectorlike
, 0);
245 DEFUN ("copy-sequence", Fcopy_sequence
, Scopy_sequence
, 1, 1, 0,
246 "Return a copy of a list, vector or string.\n\
247 The elements of a list or vector are not copied; they are shared\n\
252 if (NILP (arg
)) return arg
;
253 if (!CONSP (arg
) && !VECTORP (arg
) && !STRINGP (arg
))
254 arg
= wrong_type_argument (Qsequencep
, arg
);
255 return concat (1, &arg
, CONSP (arg
) ? Lisp_Cons
: XTYPE (arg
), 0);
259 concat (nargs
, args
, target_type
, last_special
)
262 enum Lisp_Type target_type
;
267 register Lisp_Object tail
;
268 register Lisp_Object
this;
272 Lisp_Object last_tail
;
275 /* In append, the last arg isn't treated like the others */
276 if (last_special
&& nargs
> 0)
279 last_tail
= args
[nargs
];
284 for (argnum
= 0; argnum
< nargs
; argnum
++)
287 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
288 || COMPILEDP (this)))
291 args
[argnum
] = Fnumber_to_string (this);
293 args
[argnum
] = wrong_type_argument (Qsequencep
, this);
297 for (argnum
= 0, leni
= 0; argnum
< nargs
; argnum
++)
300 len
= Flength (this);
301 leni
+= XFASTINT (len
);
304 XSETFASTINT (len
, leni
);
306 if (target_type
== Lisp_Cons
)
307 val
= Fmake_list (len
, Qnil
);
308 else if (target_type
== Lisp_Vectorlike
)
309 val
= Fmake_vector (len
, Qnil
);
311 val
= Fmake_string (len
, len
);
313 /* In append, if all but last arg are nil, return last arg */
314 if (target_type
== Lisp_Cons
&& EQ (val
, Qnil
))
318 tail
= val
, toindex
= -1; /* -1 in toindex is flag we are making a list */
324 for (argnum
= 0; argnum
< nargs
; argnum
++)
328 register int thisindex
= 0;
332 thislen
= Flength (this), thisleni
= XINT (thislen
);
334 if (STRINGP (this) && STRINGP (val
)
335 && ! NULL_INTERVAL_P (XSTRING (this)->intervals
))
337 copy_text_properties (make_number (0), thislen
, this,
338 make_number (toindex
), val
, Qnil
);
343 register Lisp_Object elt
;
345 /* Fetch next element of `this' arg into `elt', or break if
346 `this' is exhausted. */
347 if (NILP (this)) break;
349 elt
= Fcar (this), this = Fcdr (this);
352 if (thisindex
>= thisleni
) break;
354 XSETFASTINT (elt
, XSTRING (this)->data
[thisindex
++]);
356 elt
= XVECTOR (this)->contents
[thisindex
++];
359 /* Store into result */
362 XCONS (tail
)->car
= elt
;
364 tail
= XCONS (tail
)->cdr
;
366 else if (VECTORP (val
))
367 XVECTOR (val
)->contents
[toindex
++] = elt
;
370 while (!INTEGERP (elt
))
371 elt
= wrong_type_argument (Qintegerp
, elt
);
373 #ifdef MASSC_REGISTER_BUG
374 /* Even removing all "register"s doesn't disable this bug!
375 Nothing simpler than this seems to work. */
376 unsigned char *p
= & XSTRING (val
)->data
[toindex
++];
379 XSTRING (val
)->data
[toindex
++] = XINT (elt
);
386 XCONS (prev
)->cdr
= last_tail
;
391 DEFUN ("copy-alist", Fcopy_alist
, Scopy_alist
, 1, 1, 0,
392 "Return a copy of ALIST.\n\
393 This is an alist which represents the same mapping from objects to objects,\n\
394 but does not share the alist structure with ALIST.\n\
395 The objects mapped (cars and cdrs of elements of the alist)\n\
396 are shared, however.\n\
397 Elements of ALIST that are not conses are also shared.")
401 register Lisp_Object tem
;
403 CHECK_LIST (alist
, 0);
406 alist
= concat (1, &alist
, Lisp_Cons
, 0);
407 for (tem
= alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
409 register Lisp_Object car
;
410 car
= XCONS (tem
)->car
;
413 XCONS (tem
)->car
= Fcons (XCONS (car
)->car
, XCONS (car
)->cdr
);
418 DEFUN ("substring", Fsubstring
, Ssubstring
, 2, 3, 0,
419 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
420 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
421 If FROM or TO is negative, it counts from the end.")
424 register Lisp_Object from
, to
;
428 CHECK_STRING (string
, 0);
429 CHECK_NUMBER (from
, 1);
431 to
= Flength (string
);
433 CHECK_NUMBER (to
, 2);
436 XSETINT (from
, XINT (from
) + XSTRING (string
)->size
);
438 XSETINT (to
, XINT (to
) + XSTRING (string
)->size
);
439 if (!(0 <= XINT (from
) && XINT (from
) <= XINT (to
)
440 && XINT (to
) <= XSTRING (string
)->size
))
441 args_out_of_range_3 (string
, from
, to
);
443 res
= make_string (XSTRING (string
)->data
+ XINT (from
),
444 XINT (to
) - XINT (from
));
445 copy_text_properties (from
, to
, string
, make_number (0), res
, Qnil
);
449 DEFUN ("nthcdr", Fnthcdr
, Snthcdr
, 2, 2, 0,
450 "Take cdr N times on LIST, returns the result.")
453 register Lisp_Object list
;
458 for (i
= 0; i
< num
&& !NILP (list
); i
++)
466 DEFUN ("nth", Fnth
, Snth
, 2, 2, 0,
467 "Return the Nth element of LIST.\n\
468 N counts from zero. If LIST is not that long, nil is returned.")
472 return Fcar (Fnthcdr (n
, list
));
475 DEFUN ("elt", Felt
, Selt
, 2, 2, 0,
476 "Return element of SEQUENCE at index N.")
478 register Lisp_Object seq
, n
;
483 if (CONSP (seq
) || NILP (seq
))
484 return Fcar (Fnthcdr (n
, seq
));
485 else if (STRINGP (seq
) || VECTORP (seq
))
486 return Faref (seq
, n
);
488 seq
= wrong_type_argument (Qsequencep
, seq
);
492 DEFUN ("member", Fmember
, Smember
, 2, 2, 0,
493 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
494 The value is actually the tail of LIST whose car is ELT.")
496 register Lisp_Object elt
;
499 register Lisp_Object tail
;
500 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
502 register Lisp_Object tem
;
504 if (! NILP (Fequal (elt
, tem
)))
511 DEFUN ("memq", Fmemq
, Smemq
, 2, 2, 0,
512 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
513 The value is actually the tail of LIST whose car is ELT.")
515 register Lisp_Object elt
;
518 register Lisp_Object tail
;
519 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
521 register Lisp_Object tem
;
523 if (EQ (elt
, tem
)) return tail
;
529 DEFUN ("assq", Fassq
, Sassq
, 2, 2, 0,
530 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
531 The value is actually the element of LIST whose car is KEY.\n\
532 Elements of LIST that are not conses are ignored.")
534 register Lisp_Object key
;
537 register Lisp_Object tail
;
538 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
540 register Lisp_Object elt
, tem
;
542 if (!CONSP (elt
)) continue;
544 if (EQ (key
, tem
)) return elt
;
550 /* Like Fassq but never report an error and do not allow quits.
551 Use only on lists known never to be circular. */
554 assq_no_quit (key
, list
)
555 register Lisp_Object key
;
558 register Lisp_Object tail
;
559 for (tail
= list
; CONSP (tail
); tail
= Fcdr (tail
))
561 register Lisp_Object elt
, tem
;
563 if (!CONSP (elt
)) continue;
565 if (EQ (key
, tem
)) return elt
;
570 DEFUN ("assoc", Fassoc
, Sassoc
, 2, 2, 0,
571 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
572 The value is actually the element of LIST whose car equals KEY.")
574 register Lisp_Object key
;
577 register Lisp_Object tail
;
578 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
580 register Lisp_Object elt
, tem
;
582 if (!CONSP (elt
)) continue;
583 tem
= Fequal (Fcar (elt
), key
);
584 if (!NILP (tem
)) return elt
;
590 DEFUN ("rassq", Frassq
, Srassq
, 2, 2, 0,
591 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
592 The value is actually the element of LIST whose cdr is ELT.")
594 register Lisp_Object key
;
597 register Lisp_Object tail
;
598 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
600 register Lisp_Object elt
, tem
;
602 if (!CONSP (elt
)) continue;
604 if (EQ (key
, tem
)) return elt
;
610 DEFUN ("rassoc", Frassoc
, Srassoc
, 2, 2, 0,
611 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
612 The value is actually the element of LIST whose cdr equals KEY.")
614 register Lisp_Object key
;
617 register Lisp_Object tail
;
618 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
620 register Lisp_Object elt
, tem
;
622 if (!CONSP (elt
)) continue;
623 tem
= Fequal (Fcdr (elt
), key
);
624 if (!NILP (tem
)) return elt
;
630 DEFUN ("delq", Fdelq
, Sdelq
, 2, 2, 0,
631 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
632 The modified LIST is returned. Comparison is done with `eq'.\n\
633 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
634 therefore, write `(setq foo (delq element foo))'\n\
635 to be sure of changing the value of `foo'.")
637 register Lisp_Object elt
;
640 register Lisp_Object tail
, prev
;
641 register Lisp_Object tem
;
653 Fsetcdr (prev
, Fcdr (tail
));
663 DEFUN ("delete", Fdelete
, Sdelete
, 2, 2, 0,
664 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
665 The modified LIST is returned. Comparison is done with `equal'.\n\
666 If the first member of LIST is ELT, deleting it is not a side effect;\n\
667 it is simply using a different list.\n\
668 Therefore, write `(setq foo (delete element foo))'\n\
669 to be sure of changing the value of `foo'.")
671 register Lisp_Object elt
;
674 register Lisp_Object tail
, prev
;
675 register Lisp_Object tem
;
682 if (! NILP (Fequal (elt
, tem
)))
687 Fsetcdr (prev
, Fcdr (tail
));
697 DEFUN ("nreverse", Fnreverse
, Snreverse
, 1, 1, 0,
698 "Reverse LIST by modifying cdr pointers.\n\
699 Returns the beginning of the reversed list.")
703 register Lisp_Object prev
, tail
, next
;
705 if (NILP (list
)) return list
;
712 Fsetcdr (tail
, prev
);
719 DEFUN ("reverse", Freverse
, Sreverse
, 1, 1, 0,
720 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
721 See also the function `nreverse', which is used more often.")
726 register Lisp_Object
*vec
;
727 register Lisp_Object tail
;
730 length
= Flength (list
);
731 vec
= (Lisp_Object
*) alloca (XINT (length
) * sizeof (Lisp_Object
));
732 for (i
= XINT (length
) - 1, tail
= list
; i
>= 0; i
--, tail
= Fcdr (tail
))
733 vec
[i
] = Fcar (tail
);
735 return Flist (XINT (length
), vec
);
738 Lisp_Object
merge ();
740 DEFUN ("sort", Fsort
, Ssort
, 2, 2, 0,
741 "Sort LIST, stably, comparing elements using PREDICATE.\n\
742 Returns the sorted list. LIST is modified by side effects.\n\
743 PREDICATE is called with two elements of LIST, and should return T\n\
744 if the first element is \"less\" than the second.")
746 Lisp_Object list
, pred
;
748 Lisp_Object front
, back
;
749 register Lisp_Object len
, tem
;
750 struct gcpro gcpro1
, gcpro2
;
754 len
= Flength (list
);
759 XSETINT (len
, (length
/ 2) - 1);
760 tem
= Fnthcdr (len
, list
);
764 GCPRO2 (front
, back
);
765 front
= Fsort (front
, pred
);
766 back
= Fsort (back
, pred
);
768 return merge (front
, back
, pred
);
772 merge (org_l1
, org_l2
, pred
)
773 Lisp_Object org_l1
, org_l2
;
777 register Lisp_Object tail
;
779 register Lisp_Object l1
, l2
;
780 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
787 /* It is sufficient to protect org_l1 and org_l2.
788 When l1 and l2 are updated, we copy the new values
789 back into the org_ vars. */
790 GCPRO4 (org_l1
, org_l2
, pred
, value
);
810 tem
= call2 (pred
, Fcar (l2
), Fcar (l1
));
831 DEFUN ("get", Fget
, Sget
, 2, 2, 0,
832 "Return the value of SYMBOL's PROPNAME property.\n\
833 This is the last VALUE stored with `(put SYMBOL PROPNAME VALUE)'.")
836 register Lisp_Object prop
;
838 register Lisp_Object tail
;
839 for (tail
= Fsymbol_plist (sym
); !NILP (tail
); tail
= Fcdr (Fcdr (tail
)))
841 register Lisp_Object tem
;
844 return Fcar (Fcdr (tail
));
849 DEFUN ("put", Fput
, Sput
, 3, 3, 0,
850 "Store SYMBOL's PROPNAME property with value VALUE.\n\
851 It can be retrieved with `(get SYMBOL PROPNAME)'.")
854 register Lisp_Object prop
;
857 register Lisp_Object tail
, prev
;
860 for (tail
= Fsymbol_plist (sym
); !NILP (tail
); tail
= Fcdr (Fcdr (tail
)))
862 register Lisp_Object tem
;
865 return Fsetcar (Fcdr (tail
), val
);
868 newcell
= Fcons (prop
, Fcons (val
, Qnil
));
870 Fsetplist (sym
, newcell
);
872 Fsetcdr (Fcdr (prev
), newcell
);
876 DEFUN ("equal", Fequal
, Sequal
, 2, 2, 0,
877 "T if two Lisp objects have similar structure and contents.\n\
878 They must have the same data type.\n\
879 Conses are compared by comparing the cars and the cdrs.\n\
880 Vectors and strings are compared element by element.\n\
881 Numbers are compared by value, but integers cannot equal floats.\n\
882 (Use `=' if you want integers and floats to be able to be equal.)\n\
883 Symbols must match exactly.")
885 register Lisp_Object o1
, o2
;
887 return internal_equal (o1
, o2
, 0) ? Qt
: Qnil
;
891 internal_equal (o1
, o2
, depth
)
892 register Lisp_Object o1
, o2
;
896 error ("Stack overflow in equal");
902 if (XTYPE (o1
) != XTYPE (o2
))
907 #ifdef LISP_FLOAT_TYPE
909 return (extract_float (o1
) == extract_float (o2
));
913 if (!internal_equal (XCONS (o1
)->car
, XCONS (o2
)->car
, depth
+ 1))
915 o1
= XCONS (o1
)->cdr
;
916 o2
= XCONS (o2
)->cdr
;
920 if (XMISC (o1
)->type
!= XMISC (o2
)->type
)
924 if (!internal_equal (OVERLAY_START (o1
), OVERLAY_START (o1
),
926 || !internal_equal (OVERLAY_END (o1
), OVERLAY_END (o1
),
929 o1
= XOVERLAY (o1
)->plist
;
930 o2
= XOVERLAY (o2
)->plist
;
935 return (XMARKER (o1
)->buffer
== XMARKER (o2
)->buffer
936 && (XMARKER (o1
)->buffer
== 0
937 || XMARKER (o1
)->bufpos
== XMARKER (o2
)->bufpos
));
941 case Lisp_Vectorlike
:
943 register int i
, size
;
944 size
= XVECTOR (o1
)->size
;
945 /* Pseudovectors have the type encoded in the size field, so this test
946 actually checks that the objects have the same type as well as the
948 if (XVECTOR (o2
)->size
!= size
)
950 /* But only true vectors and compiled functions are actually sensible
951 to compare, so eliminate the others now. */
952 if (size
& PSEUDOVECTOR_FLAG
)
954 if (!(size
& PVEC_COMPILED
))
956 size
&= PSEUDOVECTOR_SIZE_MASK
;
958 for (i
= 0; i
< size
; i
++)
961 v1
= XVECTOR (o1
)->contents
[i
];
962 v2
= XVECTOR (o2
)->contents
[i
];
963 if (!internal_equal (v1
, v2
, depth
+ 1))
971 if (XSTRING (o1
)->size
!= XSTRING (o2
)->size
)
973 if (bcmp (XSTRING (o1
)->data
, XSTRING (o2
)->data
,
976 #ifdef USE_TEXT_PROPERTIES
977 /* If the strings have intervals, verify they match;
978 if not, they are unequal. */
979 if ((XSTRING (o1
)->intervals
!= 0 || XSTRING (o2
)->intervals
!= 0)
980 && ! compare_string_intervals (o1
, o2
))
988 DEFUN ("fillarray", Ffillarray
, Sfillarray
, 2, 2, 0,
989 "Store each element of ARRAY with ITEM. ARRAY is a vector or string.")
991 Lisp_Object array
, item
;
993 register int size
, index
, charval
;
997 register Lisp_Object
*p
= XVECTOR (array
)->contents
;
998 size
= XVECTOR (array
)->size
;
999 for (index
= 0; index
< size
; index
++)
1002 else if (STRINGP (array
))
1004 register unsigned char *p
= XSTRING (array
)->data
;
1005 CHECK_NUMBER (item
, 1);
1006 charval
= XINT (item
);
1007 size
= XSTRING (array
)->size
;
1008 for (index
= 0; index
< size
; index
++)
1013 array
= wrong_type_argument (Qarrayp
, array
);
1025 Lisp_Object args
[2];
1028 return Fnconc (2, args
);
1030 return Fnconc (2, &s1
);
1031 #endif /* NO_ARG_ARRAY */
1034 DEFUN ("nconc", Fnconc
, Snconc
, 0, MANY
, 0,
1035 "Concatenate any number of lists by altering them.\n\
1036 Only the last argument is not altered, and need not be a list.")
1041 register int argnum
;
1042 register Lisp_Object tail
, tem
, val
;
1046 for (argnum
= 0; argnum
< nargs
; argnum
++)
1049 if (NILP (tem
)) continue;
1054 if (argnum
+ 1 == nargs
) break;
1057 tem
= wrong_type_argument (Qlistp
, tem
);
1066 tem
= args
[argnum
+ 1];
1067 Fsetcdr (tail
, tem
);
1069 args
[argnum
+ 1] = tail
;
1075 /* This is the guts of all mapping functions.
1076 Apply fn to each element of seq, one by one,
1077 storing the results into elements of vals, a C vector of Lisp_Objects.
1078 leni is the length of vals, which should also be the length of seq. */
1081 mapcar1 (leni
, vals
, fn
, seq
)
1084 Lisp_Object fn
, seq
;
1086 register Lisp_Object tail
;
1089 struct gcpro gcpro1
, gcpro2
, gcpro3
;
1091 /* Don't let vals contain any garbage when GC happens. */
1092 for (i
= 0; i
< leni
; i
++)
1095 GCPRO3 (dummy
, fn
, seq
);
1097 gcpro1
.nvars
= leni
;
1098 /* We need not explicitly protect `tail' because it is used only on lists, and
1099 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1103 for (i
= 0; i
< leni
; i
++)
1105 dummy
= XVECTOR (seq
)->contents
[i
];
1106 vals
[i
] = call1 (fn
, dummy
);
1109 else if (STRINGP (seq
))
1111 for (i
= 0; i
< leni
; i
++)
1113 XSETFASTINT (dummy
, XSTRING (seq
)->data
[i
]);
1114 vals
[i
] = call1 (fn
, dummy
);
1117 else /* Must be a list, since Flength did not get an error */
1120 for (i
= 0; i
< leni
; i
++)
1122 vals
[i
] = call1 (fn
, Fcar (tail
));
1130 DEFUN ("mapconcat", Fmapconcat
, Smapconcat
, 3, 3, 0,
1131 "Apply FN to each element of SEQ, and concat the results as strings.\n\
1132 In between each pair of results, stick in SEP.\n\
1133 Thus, \" \" as SEP results in spaces between the values returned by FN.")
1135 Lisp_Object fn
, seq
, sep
;
1140 register Lisp_Object
*args
;
1142 struct gcpro gcpro1
;
1144 len
= Flength (seq
);
1146 nargs
= leni
+ leni
- 1;
1147 if (nargs
< 0) return build_string ("");
1149 args
= (Lisp_Object
*) alloca (nargs
* sizeof (Lisp_Object
));
1152 mapcar1 (leni
, args
, fn
, seq
);
1155 for (i
= leni
- 1; i
>= 0; i
--)
1156 args
[i
+ i
] = args
[i
];
1158 for (i
= 1; i
< nargs
; i
+= 2)
1161 return Fconcat (nargs
, args
);
1164 DEFUN ("mapcar", Fmapcar
, Smapcar
, 2, 2, 0,
1165 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
1166 The result is a list just as long as SEQUENCE.\n\
1167 SEQUENCE may be a list, a vector or a string.")
1169 Lisp_Object fn
, seq
;
1171 register Lisp_Object len
;
1173 register Lisp_Object
*args
;
1175 len
= Flength (seq
);
1176 leni
= XFASTINT (len
);
1177 args
= (Lisp_Object
*) alloca (leni
* sizeof (Lisp_Object
));
1179 mapcar1 (leni
, args
, fn
, seq
);
1181 return Flist (leni
, args
);
1184 /* Anything that calls this function must protect from GC! */
1186 DEFUN ("y-or-n-p", Fy_or_n_p
, Sy_or_n_p
, 1, 1, 0,
1187 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
1188 Takes one argument, which is the string to display to ask the question.\n\
1189 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
1190 No confirmation of the answer is requested; a single character is enough.\n\
1191 Also accepts Space to mean yes, or Delete to mean no.")
1195 register Lisp_Object obj
, key
, def
, answer_string
, map
;
1196 register int answer
;
1197 Lisp_Object xprompt
;
1198 Lisp_Object args
[2];
1199 int ocech
= cursor_in_echo_area
;
1200 struct gcpro gcpro1
, gcpro2
;
1202 map
= Fsymbol_value (intern ("query-replace-map"));
1204 CHECK_STRING (prompt
, 0);
1206 GCPRO2 (prompt
, xprompt
);
1211 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1214 Lisp_Object pane
, menu
;
1215 redisplay_preserve_echo_area ();
1216 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1217 Fcons (Fcons (build_string ("No"), Qnil
),
1219 menu
= Fcons (prompt
, pane
);
1220 obj
= Fx_popup_dialog (Qt
, menu
);
1221 answer
= !NILP (obj
);
1225 cursor_in_echo_area
= 1;
1226 message ("%s(y or n) ", XSTRING (xprompt
)->data
);
1228 obj
= read_filtered_event (1, 0, 0);
1229 cursor_in_echo_area
= 0;
1230 /* If we need to quit, quit with cursor_in_echo_area = 0. */
1233 key
= Fmake_vector (make_number (1), obj
);
1234 def
= Flookup_key (map
, key
);
1235 answer_string
= Fsingle_key_description (obj
);
1237 if (EQ (def
, intern ("skip")))
1242 else if (EQ (def
, intern ("act")))
1247 else if (EQ (def
, intern ("recenter")))
1253 else if (EQ (def
, intern ("quit")))
1255 /* We want to exit this command for exit-prefix,
1256 and this is the only way to do it. */
1257 else if (EQ (def
, intern ("exit-prefix")))
1262 /* If we don't clear this, then the next call to read_char will
1263 return quit_char again, and we'll enter an infinite loop. */
1268 if (EQ (xprompt
, prompt
))
1270 args
[0] = build_string ("Please answer y or n. ");
1272 xprompt
= Fconcat (2, args
);
1277 if (! noninteractive
)
1279 cursor_in_echo_area
= -1;
1280 message ("%s(y or n) %c", XSTRING (xprompt
)->data
, answer
? 'y' : 'n');
1281 cursor_in_echo_area
= ocech
;
1284 return answer
? Qt
: Qnil
;
1287 /* This is how C code calls `yes-or-no-p' and allows the user
1290 Anything that calls this function must protect from GC! */
1293 do_yes_or_no_p (prompt
)
1296 return call1 (intern ("yes-or-no-p"), prompt
);
1299 /* Anything that calls this function must protect from GC! */
1301 DEFUN ("yes-or-no-p", Fyes_or_no_p
, Syes_or_no_p
, 1, 1, 0,
1302 "Ask user a yes-or-no question. Return t if answer is yes.\n\
1303 Takes one argument, which is the string to display to ask the question.\n\
1304 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
1305 The user must confirm the answer with RET,\n\
1306 and can edit it until it as been confirmed.")
1310 register Lisp_Object ans
;
1311 Lisp_Object args
[2];
1312 struct gcpro gcpro1
;
1315 CHECK_STRING (prompt
, 0);
1318 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1321 Lisp_Object pane
, menu
, obj
;
1322 redisplay_preserve_echo_area ();
1323 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1324 Fcons (Fcons (build_string ("No"), Qnil
),
1327 menu
= Fcons (prompt
, pane
);
1328 obj
= Fx_popup_dialog (Qt
, menu
);
1335 args
[1] = build_string ("(yes or no) ");
1336 prompt
= Fconcat (2, args
);
1342 ans
= Fdowncase (Fread_from_minibuffer (prompt
, Qnil
, Qnil
, Qnil
,
1343 Qyes_or_no_p_history
));
1344 if (XSTRING (ans
)->size
== 3 && !strcmp (XSTRING (ans
)->data
, "yes"))
1349 if (XSTRING (ans
)->size
== 2 && !strcmp (XSTRING (ans
)->data
, "no"))
1357 message ("Please answer yes or no.");
1358 Fsleep_for (make_number (2), Qnil
);
1362 DEFUN ("load-average", Fload_average
, Sload_average
, 0, 0, 0,
1363 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
1364 Each of the three load averages is multiplied by 100,\n\
1365 then converted to integer.\n\
1366 If the 5-minute or 15-minute load averages are not available, return a\n\
1367 shortened list, containing only those averages which are available.")
1371 int loads
= getloadavg (load_ave
, 3);
1375 error ("load-average not implemented for this operating system");
1379 ret
= Fcons (make_number ((int) (load_ave
[--loads
] * 100.0)), ret
);
1384 Lisp_Object Vfeatures
;
1386 DEFUN ("featurep", Ffeaturep
, Sfeaturep
, 1, 1, 0,
1387 "Returns t if FEATURE is present in this Emacs.\n\
1388 Use this to conditionalize execution of lisp code based on the presence or\n\
1389 absence of emacs or environment extensions.\n\
1390 Use `provide' to declare that a feature is available.\n\
1391 This function looks at the value of the variable `features'.")
1393 Lisp_Object feature
;
1395 register Lisp_Object tem
;
1396 CHECK_SYMBOL (feature
, 0);
1397 tem
= Fmemq (feature
, Vfeatures
);
1398 return (NILP (tem
)) ? Qnil
: Qt
;
1401 DEFUN ("provide", Fprovide
, Sprovide
, 1, 1, 0,
1402 "Announce that FEATURE is a feature of the current Emacs.")
1404 Lisp_Object feature
;
1406 register Lisp_Object tem
;
1407 CHECK_SYMBOL (feature
, 0);
1408 if (!NILP (Vautoload_queue
))
1409 Vautoload_queue
= Fcons (Fcons (Vfeatures
, Qnil
), Vautoload_queue
);
1410 tem
= Fmemq (feature
, Vfeatures
);
1412 Vfeatures
= Fcons (feature
, Vfeatures
);
1413 LOADHIST_ATTACH (Fcons (Qprovide
, feature
));
1417 DEFUN ("require", Frequire
, Srequire
, 1, 2, 0,
1418 "If feature FEATURE is not loaded, load it from FILENAME.\n\
1419 If FEATURE is not a member of the list `features', then the feature\n\
1420 is not loaded; so load the file FILENAME.\n\
1421 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
1422 (feature
, file_name
)
1423 Lisp_Object feature
, file_name
;
1425 register Lisp_Object tem
;
1426 CHECK_SYMBOL (feature
, 0);
1427 tem
= Fmemq (feature
, Vfeatures
);
1428 LOADHIST_ATTACH (Fcons (Qrequire
, feature
));
1431 int count
= specpdl_ptr
- specpdl
;
1433 /* Value saved here is to be restored into Vautoload_queue */
1434 record_unwind_protect (un_autoload
, Vautoload_queue
);
1435 Vautoload_queue
= Qt
;
1437 Fload (NILP (file_name
) ? Fsymbol_name (feature
) : file_name
,
1440 tem
= Fmemq (feature
, Vfeatures
);
1442 error ("Required feature %s was not provided",
1443 XSYMBOL (feature
)->name
->data
);
1445 /* Once loading finishes, don't undo it. */
1446 Vautoload_queue
= Qt
;
1447 feature
= unbind_to (count
, feature
);
1454 Qstring_lessp
= intern ("string-lessp");
1455 staticpro (&Qstring_lessp
);
1456 Qprovide
= intern ("provide");
1457 staticpro (&Qprovide
);
1458 Qrequire
= intern ("require");
1459 staticpro (&Qrequire
);
1460 Qyes_or_no_p_history
= intern ("yes-or-no-p-history");
1461 staticpro (&Qyes_or_no_p_history
);
1463 DEFVAR_LISP ("features", &Vfeatures
,
1464 "A list of symbols which are the features of the executing emacs.\n\
1465 Used by `featurep' and `require', and altered by `provide'.");
1468 defsubr (&Sidentity
);
1471 defsubr (&Sstring_equal
);
1472 defsubr (&Sstring_lessp
);
1475 defsubr (&Svconcat
);
1476 defsubr (&Scopy_sequence
);
1477 defsubr (&Scopy_alist
);
1478 defsubr (&Ssubstring
);
1490 defsubr (&Snreverse
);
1491 defsubr (&Sreverse
);
1496 defsubr (&Sfillarray
);
1499 defsubr (&Smapconcat
);
1500 defsubr (&Sy_or_n_p
);
1501 defsubr (&Syes_or_no_p
);
1502 defsubr (&Sload_average
);
1503 defsubr (&Sfeaturep
);
1504 defsubr (&Srequire
);
1505 defsubr (&Sprovide
);